当前位置: 首页 > news >正文

第24课:LangChain|内置Agent使用【ReAct、OpenAI Function Calling实战】

文章目录

    • 课程导读 & 学习目标
    • 前置知识与环境准备
      • 1.1 环境沿用
      • 1.2 依赖包安装
      • 1.3 模型选择
      • 1.4 上节课回顾与本课定位
    • 核心概念深度拆解
      • 2.1 ReAct Agent:提示词驱动的通用模式
      • 2.2 OpenAI Function Calling:原生结构化调用
      • 2.3 两种模式的对比总结
      • 2.4 LangGraph中的create_react_agent函数
    • 底层运行原理剖析
      • 3.1 ReAct Agent的内部实现
      • 3.2 Function Calling Agent的内部实现
      • 3.3 思维链(Chain-of-Thought)与ReAct的关系
    • 核心API/组件源码解读
      • 4.1 create_react_agent 快速上手
      • 4.2 自定义系统提示词(state_modifier)
      • 4.3 手动实现ReAct Agent(不借助create_react_agent)
    • 手把手项目实战教学
      • 实战一:使用create_react_agent构建本地ReAct Agent(Ollama)
      • 实战二:Function Calling Agent(智谱GLM-4)
      • 实战三:对比ReAct和Function Calling的输出差异
    • 完整可运行Python代码
    • 环境依赖安装命令
    • 常见报错坑点与避坑方案
      • 坑1:`create_react_agent` 报错 `Model does not support bind_tools`
      • 坑2:ReAct Agent 无法正确解析 Action
      • 坑3:Function Calling Agent 调用工具时参数类型错误
      • 坑4:本地Ollama模型无响应或超时
    • 本节核心知识点总结
    • 课后练习题
      • 选择题
      • 简答题
      • 实践题
    • 🔗《30节课 LangChain 从入门到精通》系列课程导航

课程导读 & 学习目标

在上一节课中,我们深入剖析了Agent的核心原理,并使用LangGraph从零构建了一个支持工具调用的ReAct Agent。你理解了“LLM + 工具 + 循环”的工作机制。但是,在实际开发中,我们往往不需要从头编写所有节点和边——LangChain和LangGraph提供了更高级的抽象和预置模式,可以大幅简化Agent的开发工作。

本节课将聚焦于两种最主流的Agent模式:ReActOpenAI Function Calling。ReAct(Reasoning + Acting)是一种基于提示词模板的通用模式,通过引导LLM输出“Thought/Action/Action Input/Observation”结构来实现工具调用,兼容任何支持文本生成的LLM。OpenAI Function Calling则是OpenAI、智谱GLM-4等模型原生支持的结构化工具调用方式,模型直接返回JSON格式的工具参数,更加可靠和高效。

需要注意的是,LangChain旧版中的initialize_agentAgentExecutor等API已被标记为废弃。现代开发中,我们推荐使用LangGraph的统一框架来实现这两种模式。本节课将教你如何在LangGraph中优雅地实现ReAct Agent和Function Calling Agent,并对比它们的适用场景。

学完本节课,你将达到以下目标:

  1. 深刻理解ReAct Agent的工作机制:掌握如何通过提示词模板引导模型输出结构化的“思考-行动-观察”序列。
  2. 掌握OpenAI Function Calling Agent的实现:学会使用llm.bind_tools()构建原生工具调用的Agent,体验更可靠的工具使用。
  3. 对比两种模式的优缺点:了解何时选择ReAct(兼容任何模型),何时选择Function Calling(模型原生支持,精度更高)。
  4. 能够快速构建具备多工具调用能力的Agent:通过LangGraph预置组件简化代码。
  5. 完成两个完整的实战项目:基于本地Ollama模型的ReAct Agent(无需function calling支持)和基于智谱GLM-4的Function Calling Agent。

前置知识与环境准备

1.1 环境沿用

继续使用前几课的langchain_course虚拟环境,Python 3.10+。

# 激活虚拟环境sourcevenv/bin/activate# Mac/Linux# venv\Scripts\activate # Windows# 升级pippipinstall--upgradepip

1.2 依赖包安装

# 核心依赖pipinstalllangchain==0.3.7 langchain-core==0.3.21 langchain-community==0.3.7 langchain-openai==0.2.8 python-dotenv==1.0.1# LangGraph 基础pipinstalllanggraph# 本地模型支持(ReAct Agent演示用)pipinstalllangchain-ollama# 验证安装python-c"from langgraph.prebuilt import create_react_agent; print('✓ LangGraph预置ReAct Agent可用')"python-c"from langchain_core.messages import HumanMessage; from langchain_openai import ChatOpenAI; llm=ChatOpenAI(model='gpt-3.5-turbo'); llm.bind_tools([]); print('✓ Function calling支持')"

1.3 模型选择

本节课将演示两种Agent:

  • ReAct Agent:使用Ollama本地模型(如qwen2.5:7b),不需要function calling能力,通用性最强。
  • OpenAI Function Calling Agent:使用智谱GLM-4(兼容OpenAI接口)或真正的OpenAI GPT-4。

确保你的.env文件中配置了对应的API密钥(如果是智谱或OpenAI)。Ollama用户请确保已下载模型并启动服务。

1.4 上节课回顾与本课定位

第23课我们手写了LangGraph Agent的所有组件(agent_node、tools_node、条件边)。本节课我们将使用LangGraph提供的create_react_agent预置函数快速构建ReAct Agent,并演示如何利用bind_tools实现更简洁的Function Calling Agent。两者的核心思想相同,但实现方式和适用场景不同。学完本课,你将对Agent的工程实践有更全面的掌握。

核心概念深度拆解

2.1 ReAct Agent:提示词驱动的通用模式

ReAct(Reasoning and Acting)是2022年由Google Research提出的Agent范式。它通过提示词引导LLM输出一个特定的格式,包含:

  • Thought:模型的推理过程。
  • Action:要调用的工具名称。
  • Action Input:传递给工具的参数。
  • Observation:工具返回的结果(由系统填充,不是模型生成)。

LangGraph的create_react_agent函数封装了这一模式。你只需要提供工具列表和LLM,它会自动构建状态图、解析器、工具执行器等。核心逻辑是:将工具的描述和调用规范注入到系统提示词中,然后解析模型输出中的ActionAction Input

这种模式的优势是兼容任何文本生成模型,包括不支持原生function calling的开源模型(如Llama 2、Qwen 1.5等)。缺点是依赖模型严格遵循输出格式,对提示词工程要求较高,且解析可能失败。

2.2 OpenAI Function Calling:原生结构化调用

OpenAI、智谱GLM-4、DeepSeek-V4等模型在API层面支持functionstools参数。通过bind_tools将工具schema传给模型后,模型直接返回一个结构化的tool_calls字段,包含工具名称和参数JSON。这种方式无需手动解析文本,极其可靠。

在LangGraph中,我们可以使用ToolExecutor和自定义节点来处理tool_calls,或者在create_react_agent中也支持传入state_modifier来指定使用function calling。

优势:高可靠性、支持复杂参数类型、并行工具调用。劣势:要求模型API支持function calling,不适用于普通本地模型(除非通过Ollama的兼容模式,但部分模型仍不支持)。

2.3 两种模式的对比总结

特性ReAct AgentFunction Calling Agent
实现原理提示词模板 + 文本解析原生API结构化调用
模型要求任何文本生成模型模型需支持function calling
可靠性中等(依赖格式遵循)高(机器可读JSON)
参数复杂度仅支持简单字符串参数支持嵌套对象、数组、枚举等
并行调用通常单步单工具原生支持并行多个工具
调试难度较难(需检查模型输出文本)简单(直接查看tool_calls)
适用场景本地模型、旧模型、教学演示生产环境、API模型

2.4 LangGraph中的create_react_agent函数

create_react_agent是LangGraph提供的预置Agent构建器。其签名如下:

fromlanggraph.prebuiltimportcreate_react_agent agent=create_react_agent(model:BaseChatModel,tools:List[BaseTool],state_modifier:Optional[str]=None,messages_modifier:Optional[Callable]=None,checkpointer:Optional[BaseCheckpointSaver]=None,interrupt_before:Optional[List[str]]=None,interrupt_after:Optional[List[str]]=None,)
  • model:支持bind_tools的聊天模型(如果模型不支持,可以传一个自定义的model,内部会使用ReAct提示词)。
  • tools:工具列表。
  • state_modifier:系统提示词,用来指导Agent行为。
  • checkpointer:可选的状态持久化。

该函数返回一个编译后的StateGraph实例,可以像普通LangGraph应用一样调用.invoke.stream

对于不支持function calling的模型,create_react_agent自动降级为ReAct模式,提示词中包含工具描述和输出格式指令。对于支持function calling的模型,它会使用原生工具调用方式。这意味着create_react_agent是一个统一的接口,你无需关心底层实现,它会自动选择最优策略。

底层运行原理剖析

3.1 ReAct Agent的内部实现

create_react_agent检测到模型不支持bind_tools时,它会构建一个ReAct提示词模板。该模板包括:

你是一个非常有用的AI助手,能够使用以下工具来解决问题: {tools} 使用格式如下: Thought: 你当前的想法。 Action: 工具名称,必须是[{tool_names}]之一 Action Input: 工具的输入,应该是JSON字符串。 ……(重复Thought/Action/Action Input/Observation直到获得最终答案) Final Answer: 对用户的最终回复

LLM的输出会被正则表达式或json.loads解析,提取ActionAction Input。然后ToolExecutor执行工具,生成Observation,再将Observation附加到消息历史中,重复循环。

3.2 Function Calling Agent的内部实现

如果模型支持bind_toolscreate_react_agent会:

  1. 调用model.bind_tools(tools)获得一个绑定好工具的模型实例。
  2. 构建一个代理节点,调用该模型,期望模型返回AIMessage对象,其tool_calls属性非空。
  3. 如果tool_calls存在,路由到tools_node执行工具调用,将结果以ToolMessage形式追加。
  4. 如果没有tool_calls,则直接输出content作为最终答案。

这种模式避免了文本解析,直接使用API原生功能。

3.3 思维链(Chain-of-Thought)与ReAct的关系

ReAct是思维链的一种扩展。思维链只关注推理步骤,而ReAct在此基础上增加了“行动”和“观察”,使模型不仅能思考,还能与外部环境交互。

核心API/组件源码解读

4.1 create_react_agent 快速上手

fromlanggraph.prebuiltimportcreate_react_agentfromlangchain_community.toolsimporttoolfromlangchain_openaiimportChatOpenAI@tooldefadd(a:int,b:int)->int:"""两数相加"""returna+b llm=ChatOpenAI(model="gpt-3.5-turbo")agent=create_react_agent(llm,[add])result=agent.invoke({"messages":[("human","3加5等于多少?")]})print(result["messages"][-1].content)

4.2 自定义系统提示词(state_modifier)

agent=create_react_agent(llm,tools,state_modifier="你是一个数学专家。请一步步思考,使用计算器工具辅助计算。")

state_modifier会作为系统消息插入到对话开头,指导Agent的行为风格。

4.3 手动实现ReAct Agent(不借助create_react_agent)

如果需要完全控制提示词格式,可以手动实现ReAct Agent,但通常没有必要。create_react_agent已经足够灵活。

手把手项目实战教学

实战一:使用create_react_agent构建本地ReAct Agent(Ollama)

目标:使用本地Ollama模型(qwen2.5:7b)和create_react_agent构建一个ReAct Agent,配备计算器和时间查询工具。由于qwen2.5:7b支持function calling?需要确认。实际上qwen2.5:7b在Ollama中可能不支持原生function calling,但create_react_agent会自动使用ReAct模式。我们将演示跨平台兼容性。

importdatetimefromlangchain_ollamaimportChatOllamafromlangchain_core.toolsimporttoolfromlanggraph.prebuiltimportcreate_react_agent@tooldefcalculate(expression:str)->str:"""计算数学表达式。例如'2+2'"""try:returnstr(eval(expression))except:return"计算错误"@tooldefget_current_time()->str:"""获取当前时间"""returndatetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")llm=ChatOllama(model="qwen2.5:7b",temperature=0)tools=[calculate,get_current_time]agent=create_react_agent(llm,tools)result=agent.invoke({"messages":[("human","现在几点了?然后计算1234*5678")]})print(result["messages"][-1].content)

注意:第一次运行时,模型可能会尝试输出ActionAction Inputcreate_react_agent会自动解析并调用工具。

实战二:Function Calling Agent(智谱GLM-4)

目标:使用智谱GLM-4(支持OpenAI function calling)构建一个更为可靠的Agent。

importosfromdotenvimportload_dotenvfromlangchain_openaiimportChatOpenAIfromlangchain_core.toolsimporttoolfromlanggraph.prebuiltimportcreate_react_agent load_dotenv()@tooldefcalculate(expression:str)->str:"""计算数学表达式"""returnstr(eval(expression))llm=ChatOpenAI(model="glm-4",openai_api_key=os.getenv("ZHIPU_API_KEY"),openai_api_base=os.getenv("BASE_URL"),temperature=0)agent=create_react_agent(llm,[calculate])result=agent.invoke({"messages":[("human","计算(2+3)*4的结果")]})print(result["messages"][-1].content)

由于glm-4支持function calling,create_react_agent会自动切换到原生模式,无需手动解析文本。

实战三:对比ReAct和Function Calling的输出差异

通过流式输出查看内部步骤:

# ReAct模式(使用Ollama)forstepinagent.stream({"messages":[("human","2的10次方")]}):print(step)

你会看到agent节点输出包含thoughtaction字段的文本,而在Function Calling模式下,你会看到tool_calls字段。

完整可运行Python代码

整合上述实战,形成完整的演示脚本。

#!/usr/bin/env python# -*- coding: utf-8 -*-""" LangChain 第24课:内置Agent实战 演示两种模式: 1. 基于Ollama的ReAct Agent(通用) 2. 基于智谱GLM-4的Function Calling Agent """importdatetimeimportosfromdotenvimportload_dotenvfromlangchain_core.toolsimporttoolfromlanggraph.prebuiltimportcreate_react_agentfromlangchain_ollamaimportChatOllamafromlangchain_openaiimportChatOpenAI load_dotenv()# ========== 定义公共工具 ==========@tooldefcalculate(expression:str)->str:"""计算数学表达式的值。输入应为字符串格式,如 '2+2' 或 'sqrt(16)'。"""try:# 注意:生产环境请用安全计算库,这里仅演示returnstr(eval(expression))exceptExceptionase:returnf"计算错误:{e}"@tooldefget_current_time()->str:"""获取当前日期和时间"""returndatetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")defrun_react_agent():"""使用本地Ollama模型 + ReAct模式(自动降级)"""print("\n=== ReAct Agent (Ollama) ===")llm=ChatOllama(model="qwen2.5:7b",temperature=0)agent=create_react_agent(llm,[calculate,get_current_time])query="现在几点了?然后帮我计算 1234 * 5678 的结果。"print(f"用户:{query}")result=agent.invoke({"messages":[("human",query)]})final=result["messages"][-1].contentprint(f"Agent:{final}")defrun_function_calling_agent():"""使用智谱GLM-4 + Function Calling原生模式"""print("\n=== Function Calling Agent (智谱GLM-4) ===")llm=ChatOpenAI(model="glm-4",openai_api_key=os.getenv("ZHIPU_API_KEY"),openai_api_base=os.getenv("BASE_URL"),temperature=0)agent=create_react_agent(llm,[calculate])query="计算 (2+3)*4 的结果"print(f"用户:{query}")result=agent.invoke({"messages":[("human",query)]})final=result["messages"][-1].contentprint(f"Agent:{final}")if__name__=="__main__":run_react_agent()run_function_calling_agent()

环境依赖安装命令

# 激活虚拟环境sourcevenv/bin/activate# venv\Scripts\activate# 安装核心依赖pipinstalllangchain==0.3.7 langchain-core==0.3.21 langchain-community==0.3.7 langchain-openai==0.2.8 python-dotenv==1.0.1 langgraph langchain-ollama# 拉取本地模型(如未下载)ollama pull qwen2.5:7b# 验证安装python-c"from langgraph.prebuilt import create_react_agent; print('✓ create_react_agent可用')"

常见报错坑点与避坑方案

坑1:create_react_agent报错Model does not support bind_tools

原因:你使用的模型(如某些Ollama模型)确实不支持function calling,但create_react_agent仍会以ReAct模式运行,不会报错。如果报错,请升级langchain-corelanggraph到最新版。

解决方案:确保langgraph>=0.1.0。如果模型确实不支持,程序会自动降级,无需干预。

坑2:ReAct Agent 无法正确解析 Action

现象:模型输出不符合预期格式,Agent卡住或循环。

原因:模型能力较弱,不能很好地遵循输出格式指令。

解决方案:尝试更换更强的模型(如qwen2.5:14b、llama3.2);或使用更精确的提示词模板,在state_modifier中明确要求“必须严格按格式输出”。

坑3:Function Calling Agent 调用工具时参数类型错误

现象:模型生成tool_calls但参数是字符串而非数字。

原因:工具函数的参数类型定义不清晰(如使用了int但docstring未说明)。

解决方案:使用Pydantic模型定义参数,并在工具注解中明确类型。@tool会自动从类型注解生成schema。

@tooldefadd(a:int,b:int)->int:"""相加两个整数"""returna+b

坑4:本地Ollama模型无响应或超时

原因:模型加载慢或硬件不足。

解决方案:减少max_tokens,或使用更小的量化模型(如qwen2.5:7b-q4_0)。

本节核心知识点总结

📌两种内置Agent模式

  • ReAct Agent:基于提示词模板,兼容任何模型,通过解析Action/Action Input文本调用工具。
  • Function Calling Agent:利用模型原生的结构化输出,可靠、高效,但要求模型支持function calling。

📌create_react_agent是LangGraph提供的预置Agent构建器,它会根据模型能力自动选择ReAct或Function Calling模式。你只需提供LLM和工具列表,即可快速得到生产级的Agent。

📌核心参数

  • model:聊天模型实例。
  • tools:工具列表。
  • state_modifier:系统提示词,用于指导Agent行为。
  • checkpointer:可选的状态持久化,支持断点续传。

📌适用场景

  • 本地开发、模型受限时使用ReAct模式。
  • 生产环境、API模型推荐使用Function Calling模式。

📌与旧版AgentExecutor的对比:新版LangGraph的create_react_agent功能更强大,支持流式、状态持久化、人机交互,是官方推荐的统一接口。

课后练习题

选择题

1. 使用create_react_agent构建Agent时,如果本地模型不支持function calling,会发生什么?
A. 程序报错退出。
B. 自动降级为ReAct模式,通过文本解析调用工具。
C. 忽略工具列表,直接回答问题。
D. 自动下载支持function calling的模型。

答案及解析:B。create_react_agent会检测模型能力,自动选择合适模式。

2. 以下哪项是ReAct Agent相比Function Calling Agent的劣势?
A. 需要更多token。
B. 解析依赖模型输出格式,可靠性较低。
C. 不支持并行工具调用。
D. 以上都是。

答案及解析:D。ReAct模式通常需要更多token(因为要输出Thought),解析不可靠,且不支持并行调用。

3.state_modifier参数的作用是什么?
A. 修改工具列表。
B. 设置系统提示词,指导Agent行为。
C. 定义模型温度。
D. 开启记忆功能。

答案及解析:B。state_modifier作为系统消息注入,影响Agent的决策风格。

简答题

4. 请简述在LangGraph中,create_react_agent比手工编写Agent节点(如第23课)的优势。

参考答案

  • 代码量少:无需手动定义agent_nodetools_node、条件边,减少样板代码。
  • 自动模式切换:根据模型能力自动选择ReAct或Function Calling,兼容性强。
  • 内置解析器:处理ReAct的文本解析和Function Calling的tool_calls,避免自己写正则。
  • 支持检查点:可选checkpointer参数轻松集成状态持久化。
  • 流式支持:内置.stream方法,方便调试。

5. 解释为什么在生产环境中更推荐使用Function Calling Agent而非ReAct Agent。

参考答案:Function Calling Agent利用模型原生的结构化输出,避免了文本解析的不确定性和格式错误,可靠性大大提升。此外,它还支持复杂参数类型(嵌套对象、数组)和并行多工具调用,而ReAct通常只能处理简单字符串参数且单步单工具。Function Calling Agent的调试也更容易,因为tool_calls字段是机器可读的JSON。

实践题

6. 扩展本课的Function Calling Agent,添加一个“发送邮件”工具(模拟),要求工具的参数为收件人、主题、正文。然后让Agent发送一封测试邮件。

参考答案

frompydanticimportBaseModel,FieldclassEmailInput(BaseModel):to:str=Field(description="收件人邮箱")subject:str=Field(description="邮件主题")body:str=Field(description="邮件正文")@tool(args_schema=EmailInput)defsend_email(to:str,subject:str,body:str)->str:"""发送邮件(模拟)"""print(f"[模拟] 发送邮件给{to}:{subject}-{body[:50]}...")returnf"邮件已发送至{to}"tools.append(send_email)# 然后让Agent执行:请发一封主题为 '测试' 的邮件给 admin@example.com,正文为 'Hello Agent'。

通过这个练习,你将体会到Function Calling对复杂参数类型的天然支持。


🔗《30节课 LangChain 从入门到精通》系列课程导航

去订阅

🌟 感谢您耐心阅读到这里!
💡 如果本文对您有所启发欢迎:
👍 点赞📌 收藏 📤 分享给更多需要的伙伴。
🗣️ 期待在评论区看到您的想法, 共同进步。
🔔 关注我,持续获取更多干货内容~
🤗 我们下篇文章见~

http://www.jsqmd.com/news/865543/

相关文章:

  • 开放式厨房选灶具常见问题解答(2026最新专家版) - 资讯速览
  • 智慧校园平台怎么选?职业院校重点关注这几个核心点
  • 【AI模型落地生死线】:DeepSeek许可证合规检查清单(含12个可执行代码级检测点+自动化脚本)
  • Magpie窗口缩放神器:3分钟掌握Windows 10/11最佳画质提升方案
  • iOS Widget 开发-16:Widget 网络数据加载策略
  • Reqable下载安装全流程攻略(非常详细,2026实测) - sdfsafafa
  • 2026 年 5 月上海包包回收排行榜 TOP6:六家机构实力大比拼,榜首添价收实至名归 - 薛定谔的梨花猫
  • 收的顶海口五店靠谱吗?2026 资质 + 报价 + 服务全测评 - 奢侈品回收测评
  • 终极指南:3分钟在Windows上安装苹果USB驱动和iPhone网络共享
  • 创业公司如何借助Taotoken快速原型验证多个大模型能力
  • 2026年 温州二手方木/温州二手建筑模板/温州二手方木批发,优选温州柳婷木业口碑推荐 - 资讯速览
  • 2026年推荐:衡阳报废车回收/回收报废车/新能源报废车回收,优选衡阳市兄弟报废车回收商家推荐 - 资讯速览
  • 优雅的代码长什么样?一个十年程序员的审美标准——从测试视角的深度解构
  • AI短剧工具好不好怎么判断:看镜头衔接和角色延续
  • HarmonyOS APP<<古今职鉴定>>开源教程第21篇:弹窗与对话框设计
  • taotoken的token消耗明细在控制台中的可视化体验
  • 如何快速掌握GetQzonehistory:QQ空间备份的完整教程
  • HarmonyOS APP<<古今职鉴定>>开源教程第22篇:图片处理与资源管理
  • 2026西宁婚纱摄影推荐TOP5!这几家口碑好到爆! - charlieruizvin
  • 2026年北京被动房全案服务商选型指南|利坚美EPC总承包如何破局权责推诿陷阱 - 企业名录优选推荐
  • 2026全球名义雇主EOR服务商优选,泰国海外人力资源服务商推荐 - 品牌2025
  • 国内核心空港空运报关服务商技术能力实测对比 - 奔跑123
  • 过度设计是程序员的“职业病”,如何克制?
  • 推挽变压器深度解析:隔离电源设计中的选型准则与工程验证
  • 拍了一堆没修图的照片发不出去?这个私有相册让我终于不用再“表演”生活了
  • 从化区做美妆日化老板娘自己管账多年账务很乱换哪家代账公司能规范?|3个风险点+梳理路径全解 - 欢欢在创业
  • 简单比复杂更难:技术人如何修炼“简化”的能力?
  • 【信息科学与工程学】计算机科学与自动化——第十五篇 云计算 第三系列 亿级并发的算法
  • 成都搬家公司哪家靠谱?2026 口碑 TOP5 新鲜出炉 - 资讯速览
  • 长沙学校毕业典礼大型活动拍摄:定格现场温度 留存记忆 - 奔跑123