如何用LangChain构建一个Zero-shot ReAct Agent?

来源:JS脚本作者:香港程序员头衔:程序员
导读:本期聚焦于香港程序员创作的《如何用LangChain构建一个Zero-shot ReAct Agent?》,敬请观看详情。当语言模型需要查询实时数据或调用本地函数时,仅靠文本生成无法完成实际动作,必须通过代理框架把推理与执行连接起来。LangChain提供的Zero-shot ReAct Agent正是这一思路的轻量实现,它不依赖大量任务示例,而是依靠模型自身的指令跟随能力,在Thought、Action、Observation三个环节中循环推进。模型先输出思考内容,再给出要调用的工具和参数,代理执行后把结果重新注入上下文,直到生成最终回答。这种模式大幅降低了接入成本,适合快速验证工具调用、信息检索和自动化任务。本文从零开始构建一个可运行的Zero-shot ReAct Agent,解析提示词结构、输出解析器和执行循环,并对比Few-shot模式,说明在什么场景下优先选择Zero-shot。读完可以理解Agent的底层流程,也能避开工具描述、参数校验和死循环等高频问题。

大语言模型擅长生成文本,却无法自己查询天气、执行SQL或发送HTTP请求。要让模型具备行动能力,需要在推理和工具之间建立一个受控的循环,LangChain的Agent模块正是为此设计。其中Zero-shot ReAct Agent不要求为每个工具准备演示示例,适合大多数初步接入场景。下面会从工作机制开始,再到代码实现、运行流程和选型注意,完整走一遍。

如何用LangChain构建一个Zero-shot ReAct Agent?

一、Zero-shot ReAct Agent 的核心机制

ReAct的全称是Reasoning + Acting,也就是推理与行动交替进行。模型不会一次性给出最终答案,而是按照固定的循环步骤推进。每一步模型都要输出一个Thought,说明它当前在思考什么;接着输出一个Action,指定要调用哪个工具;然后系统执行该工具并把返回结果作为Observation重新喂给模型。这个循环会持续到模型认为信息足够,输出Final Answer为止。

Zero-shot的含义是不为每个工具单独编写Few-shot示例。在Few-shot模式中,提示词会包含若干条完整的输入输出范本,帮助模型理解工具用法。而Zero-shot模式只提供工具名称、参数说明和格式约束,完全依赖模型自身的语义理解能力。这意味着提示词更短、维护成本更低,但对模型的基础能力要求更高。好在当前主流模型对常见的ReAct格式已经非常熟悉,Zero-shot模式在多数简单场景下表现稳定。

可以将这个循环拆成下表所示的几个环节:

步骤模型输出代理动作
思考Thought: 需要先获取单词长度等待模型继续输出
行动Action: get_word_length根据工具名匹配函数
参数Action Input: {"word": "strawberry"}解析参数并执行工具
观察Observation: 10把结果追加到上下文
结束Final Answer: strawberry有10个字母返回给用户

理解了机制之后,下一步就可以直接写代码来验证。一个典型的工具定义如下:

from langchain.agents import tool

@tool
def get_word_length(word: str) -> int:
    """返回一个英文单词的字母数量。"""
    return len(word)

这里使用@tool装饰器把普通函数包装成LangChain可以识别的工具。函数的文档字符串至关重要,因为它会作为工具描述传给模型,模型根据这段描述决定何时调用该工具。描述写得越清楚,模型越不容易出错。

二、用LangChain快速搭建一个可运行示例

要创建一个Agent,需要准备四样东西:一个语言模型、一个工具列表、一个提示词模板和一个执行器。语言模型负责推理和决策,工具列表提供可执行的能力,提示词模板约束输出格式,执行器则把整个循环串起来。

先安装必要的依赖:

pip install langchain langchain-openai

接着初始化模型和工具。下面这段代码会从LangChain Hub拉取官方提供的ReAct提示词,然后创建Agent和AgentExecutor:

from langchain_openai import ChatOpenAI
from langchain.agents import create_react_agent, AgentExecutor
from langchain import hub

llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
tools = [get_word_length]
prompt = hub.pull("hwchase17/react")
agent = create_react_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

result = executor.invoke({"input": "单词 strawberry 有几个字母?"})
print(result["output"])

创建Agent时使用create_react_agent,它会绑定模型、工具和提示词。AgentExecutor是真正执行循环的组件,它负责调用模型、解析Action、执行工具并更新上下文。verbose=True可以打印完整执行过程,对调试非常有用。

在这个例子中,模型会先输出Thought,然后给出Action和Action Input。AgentExecutor解析出工具名get_word_length和参数{"word": "strawberry"},调用函数得到结果10,再把这个结果作为Observation拼回上下文。模型看到Observation后判断信息已经足够,于是输出Final Answer。整个过程不需要人工干预。

三、运行流程拆解与常见问题

上面的执行过程表面看起来简单,但背后涉及多个组件协同。提示词模板通常包含tools、tool_names和agent_scratchpad三个关键变量,分别对应工具描述列表、工具名列表和历史执行记录。每次循环开始时,执行器会把最新的Observation追加到agent_scratchpad,然后重新渲染提示词并请求模型。

一次典型的执行记录可以简化成下面这段文本:

Thought: 我需要计算 strawberry 的长度
Action: get_word_length
Action Input: {"word": "strawberry"}
Observation: 10
Thought: 我已经得到结果
Final Answer: strawberry 有 10 个字母

模型输出的Action部分会被输出解析器捕获。解析器会按照约定格式提取工具名和参数,如果提取失败,AgentExecutor会抛出解析错误。这是实际开发中最常见的故障之一。解决办法通常是降低temperature、更换更强的模型,或者改写提示词使格式要求更明确。

另一个高频问题是死循环。模型可能在得到Observation后反复调用同一个工具,却始终不输出Final Answer。对此可以在AgentExecutor中设置最大迭代次数和提前停止策略:

executor = AgentExecutor(
    agent=agent,
    tools=tools,
    verbose=True,
    max_iterations=5,
    early_stopping_method="force",
)

当循环次数达到上限时,early_stopping_method="force"会强制返回当前阶段生成的文本,避免任务无限挂起。此外,工具描述不够清晰也可能导致模型在多个工具之间反复横跳。建议每个工具的描述都明确说明适用场景、参数含义和返回值格式。

四、Zero-shot 与 Few-shot 的选择及生产落地

Zero-shot和Few-shot并非绝对优劣,而是适应不同阶段。Zero-shot优势在于提示词短、维护成本低,非常适合工具数量不多、工具语义清晰的场景。一旦工具数量增加到十几个,或者某些工具参数复杂、容易出现歧义,Few-shot示例的价值就会凸显出来。示例可以直观地告诉模型如何处理边界情况,减少解析错误和误调用。

但在生产环境中选择Zero-shot时,需要额外关注几个问题。首先是工具执行超时。如果某个工具需要访问外部API或数据库,长时间无响应会拖垮整个Agent循环。其次是工具权限控制。模型生成的参数可能包含危险操作,例如执行删除或写入命令,必须在工具实现层做白名单校验。最后是日志记录。生产环境建议记录每一轮Thought、Action和Observation,便于复盘模型决策链。

一个更贴近生产的工具示例如下,它在函数内部增加了异常捕获,避免异常直接中断Agent循环:

@tool
def search_database(query: str) -> str:
    """根据 SQL 查询业务数据库,返回 JSON 字符串。"""
    try:
        # 实际项目里替换为连接池查询
        return '{"rows": 3, "status": "ok"}'
    except Exception as e:
        return f"error: {e}"

从整体来看,Zero-shot ReAct Agent是一种低成本、高灵活性的工具调用方案。它把语言模型的推理能力与外部函数连接起来,让模型从只会生成文本进化到可以执行具体动作。虽然生产环境中还面临解析稳定性、超时控制和工具安全等问题,但只要把这些基础环节处理好,Zero-shot ReAct Agent完全可以作为自动化流程的第一版落地架构。后续再根据实际任务复杂度,逐步加入Few-shot示例、更严格的输出解析器或更细粒度的工具权限控制。

LangChain AgentZero-shot ReActReAct框架修改时间:2026-09-23 20:06:12

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0923/61030.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。