Skip to main content

Q5: 解释 LangChain 中的 ZeroShotAgent 和 ReActAgent 的区别。

这是一个很经典的 LangChain 面试题。很多初学者会混淆这两个概念,因为它们在实现上确实有重叠。

简单直接的结论是:在 LangChain 的早期版本中,ZeroShotAgent 就是 ReActAgent 的一个具体实现。 两者都基于 ReAct(Reasoning + Acting) 框架。如果你面试的是较新版本(LangChain >= 0.1.0),ZeroShotAgent 已被标记为弃用,官方推荐直接使用 ReActAgentcreate_react_agent

不过,既然面试官专门问“区别”,他考察的是你对设计理念提示词模板结构的理解。下面是核心区别:

1. 核心定义:名字背后的含义

  • ReAct Agent:强调推理循环。它强制要求模型在每个步骤中交替输出 Thought(思考)Action(行动)Observation(观察)。这是一个通用的架构模式。
  • ZeroShot Agent:强调零样本能力。意思是,它没有给模型提供当前任务的具体示例(Few-shot Examples)。模型必须仅凭工具的描述文字,就推断出该调用哪个工具。

2. 关键区别:提示词模板(最重要)

这是两者最实质的技术差异。

  • ReActAgent 的提示词:非常简洁,只告诉模型遵循 Thought/Action/Action Input/Observation 的格式,并输出 Final Answer 结束。不包含任何“如何使用工具”的示例。

    // 伪代码
    “你可以使用这些工具:[工具列表]。请严格按照以下格式回复:
    Thought: 思考...
    Action: 要调用的工具名
    Action Input: 工具的输入
    Observation: 工具返回的结果
    ...(重复)...
    Thought: 我知道答案了
    Final Answer: 最终回复”
  • ZeroShotAgent 的提示词:它继承自 ReAct 的单步推理模式,但默认包含了动态生成的工具描述。更重要的是,它允许你通过 agent_kwargs 传入 prefixsuffix 来定制指令。它的核心假设是:“模型只要看懂工具的描述(docstring),就知道怎么用,不需要我给它例子。”

面试话术总结

“在实现上,ZeroShotAgent 使用了标准的 ReAct 格式,但它没有内置的 few-shot 示例。它完全依赖工具自身的描述文本(func.__doc__)来指导模型行为。”

3. 实际使用场景的区别

维度ZeroShotAgent (旧版)ReActAgent (新版)
任务复杂度适合单一、明确的简单任务适合需要多步推理、回溯的复杂任务
工具数量工具较多时(5+),表现可能下降配合 handle_parsing_errors 更鲁棒
是否需要示例不需要(零样本)可以通过 few_shot_examples 手动提供
当前状态Deprecated (弃用)Active (推荐)

4. 一个容易踩坑的“假区别”

很多面试者会回答:“ZeroShotAgent 只能调用一次工具,ReActAgent 可以循环多次调用工具。” 这是错误的。 两者都支持多步循环(比如先搜索,再计算,再搜索)。区别不在于循环次数,而在于是否依赖上下文示例

面试最佳答案(参考话术)

你可以这样组织语言:

“在 LangChain 中,两者的核心区别在于设计定位

  1. ReActAgent 是严格遵循 ReAct 论文思想的通用代理,它强制模型执行 ‘思考-行动-观察’ 的循环,并且支持通过 few_shot_examples 进行上下文学习
  2. ZeroShotAgent 本质上是一个特化的 ReActAgent。‘Zero Shot’ 意味着它在提示词中不包含任何具体的任务示例,完全依靠工具本身的描述(docstring)来让模型推理如何行动。

在实际代码演进中,ZeroShotAgent 已经被标记为弃用,因为 create_react_agent 可以更清晰地实现相同功能。如果面试官追问何时用谁,我会说:新版代码一律使用 ReActAgentcreate_react_agent;只有在阅读老项目代码时,才需要知道 ZeroShotAgent 相当于一个没有提供 examples 参数的 ReActAgent。”