news 2026/10/16 3:05:15

LangChain Agent 入门:ReAct 循环到底在跑什么

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LangChain Agent 入门:ReAct 循环到底在跑什么
个人主页: > for_ever_love__ <(欢迎各位大佬莅临😊)
其他栏目: > 大模型开发从0到1 <
其他栏目: > iOS项目总结大全 <
其他栏目: > 我想学python了 <
其他栏目: > iOS UI <

文章目录

  • LangChain Agent 入门:ReAct 循环到底在跑什么
    • 一、ReAct 是什么
    • 二、一个最小可运行的 Agent
    • 三、图结构:其实只有两个节点
    • 四、为什么官方推荐 LangGraph 而不是 AgentExecutor
    • 五、给 Agent 加"人设"
    • 六、三个必须处理的工程问题
      • 6.1 死循环:限制步数
      • 6.2 工具报错:让它自己重试
      • 6.3 流式输出:让用户看到过程
    • 七、Agent vs 普通链:什么时候该用
    • 八、小结

LangChain Agent 入门:ReAct 循环到底在跑什么

工具调用是一问一答:你问,模型说"我想调 X",你调完告诉它,它回答。
Agent 则是把这个循环自动化,让模型自己决定"还要不要再调一次、调什么",
直到它认为可以回答为止。

这篇讲 ReAct 的原理、用 LangGraph 建一个能跑的 Agent,
以及为什么现在官方推荐 LangGraph 而不是旧的 AgentExecutor。

一、ReAct 是什么

ReAct =Reasoning +Acting,翻译过来就是"边想边做"。

它让模型在每一步都显式输出两类内容:

Thought(思考): 我需要先查一下订单状态,才能回答物流问题 Action(行动): search_order(order_id="SO20240115") Observation(观察): 订单已发货,物流单号 SF123456 Thought: 现在我知道订单已发货,还需要查物流详情 Action: query_logistics(tracking_no="SF123456") Observation: 包裹已到达北京市朝阳区,预计明天送达 Thought: 信息够了,可以回答了 Action: 回答用户

关键在 Thought 这一步。模型不是盲目调工具,
而是先说清楚"我现在缺什么、所以我要调什么"。
这个"自言自语"显著提升了多步推理的正确率,
也让整个过程的可解释性大幅提升——你能看到它为什么这么干。

二、一个最小可运行的 Agent

pipinstalllanggraph langchain-openai
fromlangchain_core.toolsimporttoolfromlangchain_openaiimportChatOpenAIfromlanggraph.prebuiltimportcreate_react_agent@tooldefsearch_order(order_id:str)->str:"""根据订单号查询订单状态。订单号格式如 SO20240115。"""returnf"订单{order_id}:已发货,物流单号 SF123456"@tooldefquery_logistics(tracking_no:str)->str:"""根据物流单号查询配送进度。"""returnf"快递{tracking_no}:已到达北京市朝阳区,预计明天送达"llm=ChatOpenAI(model="gpt-4o-mini",temperature=0)tools=[search_order,query_logistics]agent=create_react_agent(llm,tools)result=agent.invoke({"messages":[("user","我的订单 SO20240115 到哪了?")]})forminresult["messages"]:print(f"[{m.type}]{m.contentorm.tool_calls}")

输出大致是:

[human] 我的订单 SO20240115 到哪了? [ai] tool_calls=[{'name': 'search_order', 'args': {'order_id': 'SO20240115'}}] [tool] 订单 SO20240115:已发货,物流单号 SF123456 [ai] tool_calls=[{'name': 'query_logistics', 'args': {'tracking_no': 'SF123456'}}] [tool] 快递 SF123456:已到达北京市朝阳区,预计明天送达 [ai] 您的订单已发货,目前已到达北京市朝阳区,预计明天送达。

模型自己串起了两步调用:
先用订单号查到物流单号,再用物流单号查进度。
这就是 Agent 和单次工具调用的本质区别。

三、图结构:其实只有两个节点

create_react_agent生成的图非常简单:

┌─────────┐ │ START │ └────┬────┘ ▼ ┌─────────┐ │ agent │ ← 模型:决定调工具还是回答 └────┬────┘ 条件边 │ ┌───────┴───────┐ ▼ ▼ ┌───────┐ ┌────────┐ │ tools │ │ END │ (没有 tool_calls → 结束) └───┬───┘ └────────┘ │ └──→ 回到 agent
  • agent 节点:调用模型。如果返回的tool_calls非空 → 去 tools;
    为空 → 结束;
  • tools 节点:执行工具,把结果包装成ToolMessage追加到消息列表;
  • 循环回到 agent,模型看到新结果再决定下一步。

用代码表达就是:

fromlanggraph.graphimportStateGraph,MessagesState,END,STARTfromlanggraph.prebuiltimportToolNode,tools_conditiondefcall_model(state:MessagesState):response=llm_with_tools.invoke(state["messages"])return{"messages":[response]}graph=StateGraph(MessagesState)graph.add_node("agent",call_model)graph.add_node("tools",ToolNode(tools))graph.add_edge(START,"agent")graph.add_conditional_edges("agent",tools_condition)# 有 tool_calls → tools,否则 ENDgraph.add_edge("tools","agent")agent=graph.compile()

这就是create_react_agent的全部实现。
理解了这个骨架,后面加记忆、加人工审核、加分支都只是在这张图上改。

四、为什么官方推荐 LangGraph 而不是 AgentExecutor

旧的AgentExecutor(langchain.agents)是个黑盒类:

# 旧写法,已不推荐fromlangchain.agentsimportAgentExecutor,create_tool_calling_agent agent=AgentExecutor(agent=...,tools=tools,verbose=True)

它被取代的原因:

维度AgentExecutorLangGraph
控制流固定的黑盒循环显式图,可任意改边
加一步人工审核很难加一个节点,改一条边
中间状态藏在内部state 完全可见可改
断点/回溯不支持有 checkpointer,可暂停恢复
多 Agent不支持原生支持

一句话:AgentExecutor 是"配置一个循环",LangGraph 是"画一张图"。
当你的需求只是简单循环时两者差不多;
一旦要加分支、加审核、加记忆、加多 Agent,前者的黑盒就变成枷锁了。

新项目直接用create_react_agent(它底层就是 LangGraph)。

五、给 Agent 加"人设"

agent=create_react_agent(llm,tools,prompt="""你是一个电商客服助手。 规则: 1. 只回答和订单、物流、售后相关的问题,其他问题礼貌拒绝; 2. 查不到信息时明确说"没查到",不要编造物流信息; 3. 涉及退款、投诉等敏感操作,先说明需要转人工,不要自行处理; 4. 回答简洁,不超过 3 句话。 """,)

prompt参数接受字符串或SystemMessage。
这个 system prompt 很重要——它决定了 Agent 的行为边界。
工具是"能力",prompt 是"规矩",两者都要有。

六、三个必须处理的工程问题

6.1 死循环:限制步数

模型可能陷入"调工具→结果不满意→再调→还是不满意"的死循环。
必须设上限:

fromlanggraph.errorsimportGraphRecursionError agent=create_react_agent(llm,tools)try:result=agent.invoke({"messages":[("user",question)]},config={"recursion_limit":10},# 最多 10 步)exceptGraphRecursionError:print("步数超限,已中断")

生产环境一定要设recursion_limit,
否则一次异常输入可能烧掉你几百次工具调用。

6.2 工具报错:让它自己重试

@tooldefquery_logistics(tracking_no:str)->str:"""根据物流单号查询配送进度。"""try:returnapi.query(tracking_no)exceptTimeoutError:# 返回可读错误,模型可能会重试或换策略return"查询超时,请稍后重试。如果多次失败,请告知用户联系人工客服。"exceptNotFound:returnf"未找到单号{tracking_no}的物流信息,可能是单号有误。"

不要让异常冒泡中断整个图。把错误转成有指导性的文本,
模型能读得懂,往往会自己修正参数重试一次。

6.3 流式输出:让用户看到过程

Agent 跑几步要十几秒,黑屏等待体验很差。
用stream_mode="values"逐步输出:

forchunkinagent.stream({"messages":[("user","订单 SO20240115 到哪了?")]},stream_mode="values",):last=chunk["messages"][-1]iflast.type=="ai"andlast.tool_calls:forcinlast.tool_calls:print(f" 调用工具:{c['name']}{c['args']}")eliflast.type=="tool":print(f" 工具返回:{last.content[:80]}")eliflast.type=="ai":print(f" 回答:{last.content}")

这样用户能看到"正在查订单 → 正在查物流 → 得出答案",
感知等待时间大幅缩短。

七、Agent vs 普通链:什么时候该用

场景用什么
流程固定:检索 → 拼 prompt → 生成普通 LCEL 链
需要根据结果动态决定下一步Agent
需要调用外部系统(查库、发请求)Agent
延迟要求严格(< 2 秒)普通链(Agent 至少 2 次模型调用)
成本敏感普通链
输入不可预测、步骤数不定Agent

不要为了用 Agent 而用 Agent。
大多数"问答"类需求用固定链就够了,且更快更省更可控。
Agent 的价值在于处理不可预测的多步任务。

八、小结

  • ReAct =Thought → Action → Observation循环,
    核心是"先说清楚为什么,再动手";
  • create_react_agent生成的图只有agent / tools 两个节点,
    靠tools_condition判断"有 tool_calls 就继续,没有就结束";
  • 新项目用 LangGraph,旧的AgentExecutor是黑盒,加分支/审核/记忆都很痛苦;
  • 三个必做工程项:recursion_limit防死循环、工具错误转文本让它自愈、流式输出改善体验;
  • prompt参数是 Agent 的"规矩",和工具(能力)同等重要;
  • 流程固定就别用 Agent,普通链更快更省。

下一篇讲 Agent 进阶:多工具协作、错误处理与人工介入。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/16 3:04:46

品牌名称语义挖掘的Prompt工程:四维拆解、四类资产与排他性双重检验

一、问题定义 LLM为白酒品类生成slogan时&#xff0c;默认检索的是品类功能词表——水源、窖龄、工艺、大师。这套词表已经被数十万个白酒SKU穷尽&#xff0c;输出必然同质化。 名称语义是差异化剩余区&#xff1a;名字里的字义、词源、谐音、典故&#xff0c;天然私有&#xf…

作者头像 李华
网站建设 2026/10/16 3:04:32

动漫推荐系统毕设实战:Hadoop+Spark+Kafka与知识图谱全链路解析

1. 为什么我推荐用这套技术栈来做动漫推荐系统先说结论&#xff1a;如果你的毕业设计既要体现大数据全链路处理能力&#xff0c;又希望推荐算法不是"调个包交差"&#xff0c;还要有让答辩老师眼前一亮的可视化与知识图谱模块&#xff0c;那HadoopSparkKafkaHive这套组…

作者头像 李华
网站建设 2026/10/16 3:04:20

不用专业仪器,怎么通过手感和外观快速判断纸箱的大致承重能力?

不用专业仪器&#xff0c;怎么通过手感和外观快速判断纸箱的大致承重能力&#xff1f;一、快速判断的适用场景在没有专业压力试验机的仓储收货、现场选型场景中&#xff0c;通过手感与外观可快速估算纸箱的大致承重范围。该方法虽不能替代实验室检测&#xff0c;但可满足初步选…

作者头像 李华
网站建设 2026/10/16 3:01:40

华为公司职位分析:云服务伙伴支持专员

本文完全依据华为官方云服务伙伴支持专员岗位职责、岗位要求撰写&#xff0c;聚焦华为云伙伴生态运营、营销活动操盘、产品专项运营、伙伴赋能管理、数据与KPI经营、合规内控核心工作&#xff0c;系统拆解岗位定位、必备专业知识、软硬核心技能、简历优化策略、高频面试真题及标…

作者头像 李华