首页 游戏 软件 资讯 排行榜 专题
首页
AI教程
LangChain从入门到精通:工具与函数调用详解

LangChain从入门到精通:工具与函数调用详解

热心网友
61
转载
2026-05-28

大模型的能力边界:时效性挑战与解决方案

先看一段代码,猜猜大模型会输出什么?

# 通义千问大模型model = get_lc_model_client()output_parser = JsonOutputParser()resp = model.invoke("今天是几月几号?")print(resp)

结果令人意外——AI竟然不知道今天是几月几号。再换一个模型(DeepSeek)试试:

model = get_ali_model_client()

没错,它确实给了一个日期,但那并不是真实的今天。之前讨论“为什么需要RAG”时,我们提到过大模型的时效性局限:训练成本极高,模型不可能实时更新。因此,那些最新的事件、最新的知识,大模型很可能一无所知。

这就是大模型的一个能力边界。要突破这一限制,除了RAG技术,还有另一个关键手段——Tool(工具调用)。

Tool:大模型的能力延伸

Tool(工具)是LangChain中的一个核心概念。它封装了一个具体功能(比如一个Python函数),包含名称、描述和参数模式(Schema)。开发者通过@tool装饰器或继承BaseTool来创建工具,本质上是在告诉模型:“我这里有这些能力可以调用。” 整个工作流程如下:

  • 定义工具:开发者将函数(例如get_date())及其描述、参数格式提前告知LLM。
  • 模型规划:用户提问后,LLM并不直接给出答案,而是分析用户意图,选择合适的工具,并严格按照格式生成一个结构化的调用请求。
  • 外部执行:程序解析这个请求,安全地在本地或远端执行真实的函数,获取结果。
  • 整合回复:将执行结果返回给LLM,由它组织成自然语言回复用户。

简单来说,LLM扮演“大脑”(负责理解和规划),外部函数扮演“手脚”(负责执行和获取信息),两者通过结构化的“神经接口”(Function Calling规范)协同工作。

bind_tools():动态绑定工具

bind_tools()的作用是把一个或多个工具(函数)转换成大模型能理解和遵循的“调用规范”(通常是JSON Schema格式),然后“绑定”到某个特定的对话模型实例上。绑定之后,这个模型在思考时,就具备了调用这些工具的能力。

  • 动态性与组合性bind_tools()的最大优势在于动态性。你可以在运行时根据不同的场景,为同一个模型绑定不同的工具集,实现高度灵活。
  • 底层协议屏蔽:它抽象了不同模型提供商(OpenAI、Anthropic、DeepSeek)在工具调用上的细节差异,提供统一接口。在OpenAI的上下文中,它本质上是在准备tools参数。

# 大模型客户端绑定工具tool_llm = model.bind_tools([get_date, open_browser])resp = tool_llm.invoke("今天是几月几号?")

Agent:工具调用的智能控制器

工具的选择和调用执行,最终是由Agent来完成的。

# 创建Agentagent = create_agent(model=llm,# 聊天模型tools=tools, # 工具列表system_prompt=system_prompt,checkpointer=memory# 传入记忆组件)

在大模型使用工具时,你可以用bind_tools进行工具绑定,但在工程实践中,推荐优先使用带tools参数的Agent,因为它提供了更完善的工具管理和执行流程。

方式一:@tool装饰器

代码示例

获取今天具体日期的自定义工具:

# 注意:函数的描述必须写在函数体中的第一行@tooldef get_date():# 文本描述相当于工具说明说,大模型正是依靠这段说明来选择对应工具""" 获取今天的具体日期 """# """ 获取今天的北京的天气 """return datetime.date.today().strftime("%Y-%m-%d")

获取浏览器并打开指定网站的工具:

mport webbrowser@tooldef open_browser(url, browser_name=None):# """ 获取浏览器,打开网站 """""" 获取浏览器,打开网站可以做很多事情,包括查询天气,汽车限号等 """if browser_name:# 获取特定浏览器的控制器browser = webbrowser.get(browser_name)else:# 使用默认浏览器browser = webbrowser# 打开浏览器并导航到指定的URLbrowser.open(url)

使用方式:

agent = create_agent(model=llm,# 聊天模型tools=[get_date, open_browser], # 工具列表system_prompt=system_prompt,checkpointer=memory# 传入记忆组件)# 获取今天的日期result = agent.invoke({"messages":[{"role":"user","content":"今天是几月几号?"}]})

注意事项

  1. 函数的描述必须写在函数体中的第一行,否则AI无法识别。
  2. 函数的描述必须准确,且与函数实际功能保持一致。否则会导致回答混乱。

比如,如果把get_date的描述改为“获取今天的北京的天气”:

@tooldef get_date():""" 获取今天的北京的天气 """return datetime.date.today().strftime("%Y-%m-%d")result = agent.invoke({"messages":[{"role":"user","content":"今天北京的天气怎么样?"}]})

用户问天气,结果却调用了日期函数——这就是描述错误带来的问题。

Log验证

前面我们已经介绍了核心流程,现在结合代码Debug来验证一下。从打印结果可以看到:

  1. 用户提问后,大模型发现自己无法直接回答。
  2. 它尝试寻找合适的工具,找到后触发了tool_callsfinesh_reason=tool_calls
  3. tool_calls信息显示name=get_date
  4. 调用get_date返回ToolMessage(2026-03-12)
  5. AI拿到日期信息后,就能给出正确答案了。

果然,和我们前面讲解的核心流程基本一致。

方式二:Tool()类

除了@tool装饰器,还可以通过Tool()类来显式定义工具。

外部函数定义

# 定义工具函数def get_current_time(input: str = "") -> str:"""获取当前时间"""current_datetime = datetime.now()formatted_time = current_datetime.strftime('%Y-%m-%d %H:%M:%S')result = f"当前时间:{formatted_time}。"print(result)return resultdef recom_drink(input: str = "") -> str:"""推荐附近的饮品店"""result = '''距离您500米内有如下饮料店:n1、蜜雪冰城n2、茶颜悦色n另外距离您200米内有惠民便利店,里面应该有矿泉水或其他饮品'''return resultdef open_calc(input: str = "") -> str:"""打开计算器"""try:subprocess.Popen(['calc.exe'])return "计算器已打开"except Exception as e:return f"打开计算器失败: {str(e)}"def open_browser(url: str) -> str:"""打开浏览器访问指定网址"""try:webbrowser.open(url)return f"已打开浏览器访问 {url}"except Exception as e:return f"打开浏览器失败: {str(e)}"

Tool()定义

  • name:工具名称,可以自定义,但建议与函数名保持一致。
  • func:关联的函数名,务必准确。
  • description:函数的功能描述,作用与@tool中写在函数首行的描述相同,但此处函数首行就不必再写了。

# 创建LangChain工具列表# 方式二,自定义工具tools = [# 通过Tool来描述声明工具 name 工具名称 func 函数体 description 函数的功能描述Tool(name="get_current_time", #可以随意,但是建议跟函数名称一致func=get_current_time,# 函数的功能描述,说明书description="当你想知道现在的时间时非常有用。"),Tool(name="recom_drink",func=recom_drink,description="用户口渴,为其推荐附近的饮品店"),Tool(name="open_calc",func=open_calc,description="打开本地计算机上的计算器。"),Tool(name="open_browser",func=lambda url: open_browser(url),description="打开本地计算机上的网页浏览器,并接受网站的url作为参数。")]

Agent构建

# 这个时候函数工具选择和调用执行,都是通过Agent来完成的# 创建Agentagent = create_agent(model=llm,# 聊天模型tools=tools, # 工具列表system_prompt=system_prompt,checkpointer=memory# 传入记忆组件)

方式三:BaseTool继承

这种方式是将工具函数封装成一个类,必须继承自BaseTool。这样设计的目的是为了给AI工具调用建立一套“强类型、结构化”的输入契约。这绝不仅仅是语法规范,而是构建可靠AI Agent的工程基石。

BaseTool类定义

  • name:工具名称
  • description:工具描述

class DateTool(BaseTool):"""一个获取当前具体日期的简单工具。它是继承BaseTool类的最简示例。"""# 1. 定义工具名称。这将是Agent在思考时提到的名字。name: str = "get_date"# 2. 定义工具描述。清晰准确的描述直接决定了Agent能否在正确场景下想起并使用它。description: str = "当需要知道今天的准确日期(年月日)时,使用此工具。"

args_schema(BaseModel)

args_schema是一个强类型、可自描述的合约规范,专门用于约束和指导大模型如何生成调用该工具的参数。

args_schema告诉LangChain框架:“我这个工具的所有输入参数,其名称、类型、约束和描述,都完整地定义在这个Pydantic BaseModel里。” 这样框架能自动完成以下几件事:

  1. 生成准确的JSON Schema:这是与OpenAI等模型API进行“函数调用”通信的协议基础。
  2. 自动化验证:在工具执行前,框架自动用schema验证模型生成的参数,无效输入会被拦截,避免工具函数崩溃。
  3. 工具发现的元数据:框架可以收集所有工具的schema,自动生成工具目录或用于路由。

# 3. 定义参数模式。即使此工具无需参数,也最好显式定义一个空的Schema,这是良好的实践。args_schema: Type[BaseModel] = DateToolInput

# 使用Pydantic定义输入参数的模型。本例中无需输入,所以模型为空。class DateToolInput(BaseModel):# 这个工具不需要任何输入参数。# 如果未来需要扩展,可以在这里添加字段,例如:# format: str = Field("YYYY-MM-DD", description="日期格式")query: Optional[str] = Field(default=None,description="查询日期的提示词,可为空")

_run方法实现

_run函数是工具“能力”的具体实现,是连接AI决策与现实世界接口的唯一执行终点。我们这里获取日期的真正实现就在这个函数里。

# 4. 实现核心的 _run 方法。这里是所有业务逻辑存放的地方。def _run(self, query: Optional[str] = None) -> str:"""执行工具,返回当前日期字符串。"""# 使用datetime模块获取当前日期,并格式化为易读的字符串。current_date = datetime.date.today().strftime("%Y-%m-%d")return f"今天是:{current_date}"# 5. (可选)实现 _arun 方法以支持异步调用。简单工具可暂不实现。async def _arun(self, query: Optional[str] = None):raise NotImplementedError("此工具暂不支持异步调用。")

调用方式

# 实例化工具date_tool = DateTool()

方式一(invoke)

直接使用date_tool:

# 方式一:invokeresult = date_tool.invoke("今天是几月几号?")result = date_tool.invoke("")print(result) # 输出:今天是:2026-03-13

方式二(run)

同样是直接使用date_tool:

# 方式二:runresult = date_tool.run("今天是几月几号?")result = date_tool.run("")print(result)

方式三(Agent)

# 方式三:Agent# 获取模型model = get_lc_model_client()# 创建工具列表tools = [date_tool]# 使用ReAct提示模板,让Agent具备“思考-行动”的推理能力prompt = "你是人工智能助手。需要帮助用户解决各种问题。"# 大模型客户端绑定工具# 创建Agentagent = create_agent(model=model,# 聊天模型tools=tools, # 工具列表system_prompt=prompt)# 调用示例result = agent.invoke({"messages": [{"role": "user", "content": "今天是几月几号?"}]},)

带参数的demo示例

后续我们会在实战案例中进一步巩固tool的使用,其中会涉及带参数的场景,具体可参见源码 tools-get_weather_demo.py

自定义tool

这是开发者为了满足特定业务需求,通过继承BaseTool基类或使用@tool装饰器,自行创建的工具。它封装了专有的逻辑、数据或第三方服务,像上面举例的get_date/DateToolopen_browserrecom_drink都属于自定义工具。

  • 本质:是你为AI智能体量身定做的“专属装备”,是实现业务差异化和核心价值的关键。
  • 核心能力:连接一切——可以把任何函数、类方法、API、数据库查询、甚至遗留系统接口包装成一个工具。
  • 典型场景:查询内部知识库或CRM系统;调用公司内部的订单或天气API;执行特定的数据分析或业务流程。

预置tool

定义

这是LangChain官方或活跃社区预先封装好、可直接调用的工具集合。它们解决的是AI应用中最常见、最通用的需求,属于“开箱即用”的标准化组件。

  • 本质:经过良好测试、接口标准化的“功能黑盒”。只需关注配置(如API密钥),无需关心内部实现。
  • 典型代表WikipediaQueryRun(查询维基百科)、DuckDuckGoSearchRun(网络搜索)、ArxivQueryRun(学术论文搜索)、PythonREPLTool(安全沙箱中运行Python代码)等。

示例

ArxivQueryRun 为例,展示简单调用方法。

  1. 使用load_tools(["arxiv"])组装Agent:

# 组装Agentagent = create_agent( model=llm, tools=load_tools(["arxiv"]), #添加工具列表,绑定的论文查询的工具 system_prompt=system_prompt, checkpointer=memory# 传入记忆组件)

  1. 调用Agent查询论文:

# 调用Agent查询论文result = agent.invoke({"messages": [{"role": "user", "content": "请查询arxiv论文编号1605.08386的信息"}]},# 配置会话标识,用于区分不同用户config={"configurable": {"thread_id": "user_1"}}# 会话唯一标识,用于区分不同用户)

Function Calling:模型与工具的通信协议

Function Calling(函数调用)是模型在推理过程中生成的一个结构化输出。当模型决定要使用某个工具时,它不会直接执行代码,而是返回一个JSON对象,里面包含要调用的工具名称(name)和具体参数(arguments)。这是模型“思考”的结果。

  • 向模型描述一个工具:必须提供一个符合特定JSON Schema格式的工具描述列表,包括工具名、描述和参数模式。
  • 模型如何回应表示想要调用工具:模型不会在文本中说“请调用XXX工具”,而是在返回的特定结构(如OpenAI的tool_calls数组)中,输出一个标准的JSON对象,包含要调用的工具名和参数。

前面讲到的bind_tools,当调用bind_tools(get_date)时,LangChain会自动将工具定义(args_schemadescription)转换成底层模型(如GPT-4)所要求的Function Calling格式。

简单来说,Function Calling是“通信协议”,而LangChain Tool是“工程实现框架”。Tool是开发者提供的能力定义,Function Calling是模型发出的使用请求。在LangChain中,通过Tool来扩展Agent的能力,而Agent通过Function Calling来实际使用这些能力。

源码

github

来源:https://juejin.cn/post/7616201064984428554
免责声明: 游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

相关攻略

堪比收费字体9种字重无衬线体免费速领
AI资讯
堪比收费字体9种字重无衬线体免费速领

这款硬朗像素风无衬线字体,带你体验未来感设计与9档字重自由 一、全文速览图 二、字体简介 本期免费商用字体:Sinkin Sans,由英国专业字体工作室K-Type出品。这是一款融合了inktrap凹槽工艺的现代无衬线体,兼具优雅气质与实用性能,视觉上现代而不失温度,清晰易读,辨识度极佳。全家族共提

热心网友
05.28
LangChain 网页 RAG 实战 入门到精通 第7篇
AI教程
LangChain 网页 RAG 实战 入门到精通 第7篇

基于Langchain-RAG实现网页摘要检索工具,通过WebBaseLoader加载网页并分割文档,构建向量存储和检索器。采用两种摘要方法:检索链结合文档链生成问答式摘要,或使用内置摘要链直接总结。需注意通过提示词模板显式控制输出语言,避免默认英文输出。

热心网友
05.28
免费可商用高级复古字体 文创包装神器
AI资讯
免费可商用高级复古字体 文创包装神器

Roland是一款免费可商用的复古装饰字体,灵感源自中世纪哥特书写传统,融合历史厚重感与现代视觉张力。提供Regular、Contour、Shadow三种字重,适用于复古海报、文创包装、品牌标识等场景,无需署名,无隐藏条款。

热心网友
05.28
QoderWake写代码实操:数字程序员自主完成代码变更测试全流程
AI资讯
QoderWake写代码实操:数字程序员自主完成代码变更测试全流程

QoderWake作为数字程序员需绑定身份与权限,通过监听仓库事件自动生成代码变更并创建PullRequest,随后在沙箱环境执行单元测试与集成验证,测试失败时输出分层诊断。最终生成交付包,经指定角色审批后方可合并部署,确保全流程可控可追溯。

热心网友
05.28
QoderWake日志调试快速定位脚本执行错误
AI资讯
QoderWake日志调试快速定位脚本执行错误

QoderWake脚本执行错误可通过日志定位。调试核心五步:启用详细日志模式并重定向输出;按时间戳与进程ID筛选关键日志段;检查脚本内嵌变量与路径解析结果;复现失败步骤并注入临时调试语句;验证Python解释器与依赖模块兼容性。

热心网友
05.28

最新APP

宝宝过生日
宝宝过生日
应用辅助 04-07
台球世界
台球世界
体育竞技 04-07
解绳子
解绳子
休闲益智 04-07
骑兵冲突
骑兵冲突
棋牌策略 04-07
三国真龙传
三国真龙传
角色扮演 04-07

热门推荐

Paralives首发销量充足 支撑后续开发无需DLC
游戏攻略
Paralives首发销量充足 支撑后续开发无需DLC

《Paralives》开发商承诺所有后续更新永久免费,拒绝付费DLC模式。15人小团队依靠首发销售额即可支撑多年运营,无需依赖额外内容包维持开发,展现了与《模拟人生》系列不同的差异化竞争思路。

热心网友
05.28
比亚迪宋Ultra DM-i上市12.99万 承诺城市领航安全兜底
业界动态
比亚迪宋Ultra DM-i上市12.99万 承诺城市领航安全兜底

2025年5月28日,比亚迪王朝网全新力作——宋Ultra DM-i正式推向市场,共推出5款配置车型,官方售价区间为12 99万至15 99万元。此次定价策略极具突破性:一款拥有310公里纯电续航能力的中型插电混动SUV,直接下探至13万元级别市场。作为王朝网络的新旗舰,该车明确瞄准高频出行需求场景

热心网友
05.28
折叠屏iPhone Ultra外观已定,第三方保护壳亮相
科技数码
折叠屏iPhone Ultra外观已定,第三方保护壳亮相

先来关注一个有趣的细节:苹果首款折叠屏手机,传闻将于今年秋季正式亮相。产品命名可能为iPhone Ultra,也有媒体称之为iPhone Fold——无论最终叫什么,这都将标志着苹果在折叠形态领域首次“出手”。 近日,配件厂商iFunSmart已率先上架iPhone Ultra的首批保护壳——这绝非

热心网友
05.28
山寨币ETF批量上市后市场表现分析 哪些项目值得关注
web3.0
山寨币ETF批量上市后市场表现分析 哪些项目值得关注

山寨币ETF迎来批量上市潮,首批项目市场表现如何?一文分析 Binance币安 欧易OKX ️ Huobi火币️ 最近,市场出现了一个不容忽视的新动向:XRP、DOGE、LTC、HBAR等现货ETF已经悄然登陆美国市场。与此同时,A VAX、LINK等资产的同类产品也正在审批流程中。进入11月以来,

热心网友
05.28
即使在大幅涨价后 Steam Deck 玩家热情依旧再次售罄
游戏攻略
即使在大幅涨价后 Steam Deck 玩家热情依旧再次售罄

近日,公司对SteamDeck1TBOLED版涨价300美元至949美元,上架短短不到24小时便再度售罄。据外界分析,该公司从中国大量补货并分批投放库存,高溢价未影响众多玩家的抢购热情与速度,其人气极其旺盛无比足以支撑快速清空。

热心网友
05.28