AI AI树洞

Chapter 04

第四章 智能体经典范式构建

前三章建立了 Agent 和 LLM 的基础,本章进入构建方法。我们会先准备离线 LLM 客户端和工具系统,再实现 ReAct、Plan-and-Solve、Reflection 三种经典范式。

本章学习目标

概念目标 理解推理-行动循环、先规划后执行、反思改进三种范式的适用边界。
工程目标 能根据任务选择 Agent 范式,并说明每种范式的调试重点和成本。

4.1 环境准备与基础工具定义

4.1.1 安装依赖库

教学代码全部使用 Python 标准库,不依赖真实模型 API。这样你可以先理解范式结构,再把离线客户端替换成真实 LLM SDK。

python3 public/course/code/chapter4/react_agent.py
python3 public/course/code/chapter4/plan_and_solve.py
python3 public/course/code/chapter4/reflection_agent.py

4.1.2 配置 API 密钥

真实项目通常会通过环境变量配置模型供应商、API Key、模型名和超时时间。本章为了可复现,使用 OfflineLLMClient 模拟模型输出。

from dataclasses import dataclass


@dataclass
class LLMMessage:
    role: str
    content: str


class OfflineLLMClient:
    def complete(self, messages: list[LLMMessage]) -> str:
        prompt = "\n".join(message.content for message in messages)
        if "Plan-and-Solve" in prompt:
            return "1. 收集事实\n2. 计算关键数值\n3. 汇总答案"
        return "Thought: 需要先计算。\nAction: calculator\nAction Input: 18 * 7 + 6"

4.1.3 封装基础 LLM 调用函数与工具

工具系统负责把可执行能力暴露给 Agent。工具必须有名称、说明、参数输入和返回值;高风险工具还需要权限和人工确认。

from dataclasses import dataclass
from typing import Callable


@dataclass
class Tool:
    name: str
    description: str
    run: Callable[[str], str]


class ToolRegistry:
    def register(self, tool: Tool) -> None:
        ...

    def get(self, name: str) -> Tool:
        ...

    def describe(self) -> str:
        ...

完整代码见 llm_client.pytools.py

4.2 ReAct

4.2.1 ReAct 的工作流程

ReAct 的核心是把 Reasoning 和 Acting 交替组织起来。模型先输出 Thought,说明为什么要做某一步;再输出 Action 和 Action Input,调用工具;工具结果作为 Observation 回到上下文,进入下一轮。

Thought判断下一步需要什么信息。
Action选择一个已注册工具。
Input生成工具参数。
Observation读取工具返回结果。
Answer达到目标后给出最终答案。

4.2.2 工具的定义与实现

ReAct 强依赖工具说明。工具描述太少,模型不知道何时调用;描述太松,模型会生成危险参数。入门阶段建议只暴露只读工具和计算工具。

4.2.3 ReAct 智能体的编码实现

class ReActAgent:
    def __init__(self, llm, tools, max_steps: int = 4) -> None:
        self.llm = llm
        self.tools = tools
        self.max_steps = max_steps
        self.trace: list[str] = []

    def run(self, question: str) -> str:
        for _ in range(self.max_steps):
            response = self.llm.complete(...)
            if "Final Answer:" in response:
                return response.split("Final Answer:", 1)[1].strip()
            tool_name, tool_input = self.parse_action(response)
            observation = self.tools.get(tool_name).run(tool_input)
            self.trace.append(f"Observation: {observation}")

完整代码见 react_agent.py

4.2.4 ReAct 的特点、局限性与调试技巧

优点局限调试重点
流程直观,便于观察每轮工具调用。 长任务会堆积上下文,错误会在循环中放大。 检查 Action 格式、工具返回、最大步数和停止条件。

4.3 Plan-and-Solve

4.3.1 Plan-and-Solve 的工作原理

Plan-and-Solve 先把问题拆成计划,再逐步执行。它适合结构较清楚但步骤较多的任务,例如资料整理、报告写作、数学解题和多阶段分析。

4.3.2 规划阶段

规划阶段不急着调用工具,而是生成步骤清单。好的计划要具体、可执行、可验证,避免“分析问题”“给出答案”这类空泛步骤。

4.3.3 执行器与状态管理

class PlanAndSolveAgent:
    def plan(self, question: str) -> list[str]:
        raw = self.llm.complete(...)
        return [line.split(".", 1)[1].strip() for line in raw.splitlines()]

    def execute_step(self, step: str) -> str:
        if "计算" in step:
            return self.tools.get("calculator").run("18 * 7 + 6")
        return "根据已有结果组织最终回答"

完整代码见 plan_and_solve.py

4.3.4 运行实例与分析

如果 ReAct 像边走边问路,Plan-and-Solve 更像先画路线图再出发。它降低了盲目工具调用的概率,但计划一旦错误,也可能把后续步骤带偏。

4.4 Reflection

4.4.1 Reflection 机制的核心思想

Reflection 让 Agent 在生成答案后进行审查,找到缺陷,再修订下一版。它常用于代码生成、长文写作、复杂推理和需要质量把关的任务。

4.4.2 案例设定与记忆模块设计

Reflection 通常需要记录每一轮草稿、反馈和修订结果。这样下一轮才能避免重复犯错,也方便人工审查。

4.4.3 Reflection 智能体的编码实现

class ReflectionAgent:
    def run(self, task: str) -> str:
        answer = self.draft(task)
        for _ in range(self.max_rounds):
            critique = self.critique(task, answer)
            answer = self.revise(answer, critique)
        return answer

完整代码见 reflection_agent.py

4.4.4 运行实例与分析

运行示例会输出初稿、审查意见和修订稿。你需要重点观察两件事:反馈是否指出了可执行问题,修订稿是否真正响应了反馈。如果反馈只说“需要更好”,Reflection 就会变成重复调用;如果反馈包含证据、边界和改进目标,修订质量才会稳定提升。

4.4.5 Reflection 机制的成本收益分析

Reflection 会增加调用次数和延迟,不适合所有任务。它更适合高价值输出,而不是简单问答。生产中可以只对低置信度、高风险或高价值任务触发反思。

4.5 本章小结

本章实现了三种经典范式:ReAct 适合边观察边行动,Plan-and-Solve 适合先拆解再执行,Reflection 适合先生成再审查。后续学习框架时,你会看到这些范式被封装成节点、角色、图和工具系统。

习题

  1. 练习 4.1:扩展工具。ToolRegistry 增加 word_count 工具,并让 ReActAgent 调用它。
  2. 练习 4.2:改进解析。 当模型输出缺少 Action Input 时,让 ReActAgent 安全停止并返回错误原因。
  3. 练习 4.3:计划校验。 给 Plan-and-Solve 增加计划审查函数,过滤空泛步骤。
  4. 练习 4.4:反思触发条件。 只在答案长度少于 50 字时触发 Reflection。

参考文献

  • ReAct:推理与行动结合的经典范式。
  • Reflexion:通过语言反馈改进 Agent 行为。