规划、推理与反思

LLM 的训练目标是 next-token prediction,这种机制天然缺两种能力——前瞻(生成第一步时不会考虑第五步的后果)和回溯(一旦写下就不能回头修正)。给 LLM 补上这两个缺口的工程手段有三种:规划补前瞻、推理补深度、反思补回溯。三者不是"加上模型就有",是用 Prompt、Schema、终止条件和评估反馈搭出来的外部脚手架。下面展开四种规划范式的伪代码骨架、反思机制的 schema 与终止条件,以及在 o1/o3 这类推理模型出现后,"什么时候该升级到哪一档"的判断信号怎么变。


1. 为什么 LLM 缺这三种能力

LLM 的训练目标是 next-token prediction——给定前文预测下一个 token。这种机制天然缺两种能力:

缺失能力 表现
前瞻(Lookahead) 生成第一步时不会考虑"这个决定在第五步会导致什么后果"——每步选局部最优,但局部最优叠加不等于全局最优
回溯(Backtrack) 一旦生成就不回头修正。中间出错,后续 token 也基于错误前提继续生成

三种能力分别补这两个缺:

能力 补什么 在什么阶段
规划 前瞻 执行前——把大目标拆成子目标,考虑步骤间依赖
推理 思考深度 每步决策前——通过结构化思维链提升单步质量
反思 回溯 执行后——检查结果、分析错误、决定重试或调整

三者结合,Agent 才能从"工具调用器"变成"问题解决者"。规划解决"做什么",推理解决"想清楚",反思解决"对不对"。

这三种能力的边界其实容易混淆。规划和推理都在 LLM 调用内部完成,但规划关心的是"目标到步骤"的分解,推理关心的是"前提到结论"的演绎。反思则发生在执行之后,关心"实际结果是否符合预期"。一个常见的设计错误是把三者混在一个 prompt 里——让 LLM 同时规划、推理、反思——结果三个能力都做得不好。结构化的做法是把三者拆成不同的调用阶段,让每次调用只承担一个职责。


2. 规划范式的四种主流形态

范式演进

范式 思想 解决什么 引入什么问题
ReAct 每步交替 Thought 和 Action,下一步基于上一步 Observation 多步推理 + 行动 Greedy,缺全局视野
Plan-and-Execute 先规划完整计划,再逐步执行 全局视野、可追踪、可并行 计划可能过时,修正成本高
Tree-of-Thought 同时考虑多条推理路径,评估后选最优深入 探索多种可能性 成本 8-10 倍于 ReAct
Hierarchical 递归分解——高层拆子目标,低层拆具体动作 处理跨粒度的真正复杂任务 架构复杂,调试困难

2.1 ReAct:贪心但实用

ReAct 的设计哲学是"边走边看":每一步基于当前观察决定下一个动作,不预先规划全部步骤。优势是应变能力强——如果第 2 步发现新信息推翻了第 1 步的假设,ReAct 在第 3 步就能调整方向;劣势是没有全局视图——可能在某条死胡同里走很远才意识到该回头。

最小骨架就是一个 while 循环:

def react_loop(goal: str, tools: list[Tool], max_steps: int = 10) -> str:
    """ReAct:Thought → Action → Observation 反复直到 final answer"""
    messages = [system_msg(REACT_PROMPT), user_msg(goal)]

    for step in range(max_steps):
        # 一步 Think + Plan:LLM 输出 thought 和可选的 tool_call
        response = llm.complete(messages, tools=tools)

        # 如果没有 tool_call,说明 LLM 认为已能给出最终答案
        if not response.tool_calls:
            return response.text

        # 否则执行工具,结果作为下一轮的 observation
        for tc in response.tool_calls:
            observation = invoke(tc)
            messages.append(tool_msg(tc.id, observation))

    return safe_terminate("max_steps reached")

工程上 ReAct 几乎是默认选择,因为它的实现成本极低——一个 while 循环加 Thought-Action-Observation 三段式 prompt 就够了。绝大多数生产 Agent(Cursor、Claude Code、客服 Agent)的核心循环都是 ReAct 的变种。

ReAct 的成本陷阱:每步 LLM 调用,上下文每步累积,token 消耗 O(N²)。5 步约 15K-25K tokens,10 步可能 50K+。这意味着 ReAct 不适合超过 7-8 步的长任务——再长就要考虑 Plan-and-Execute 或 Hierarchical。

2.2 Plan-and-Execute:先想后做

Plan-and-Execute 把规划和执行解耦——先用一次 LLM 调用产出完整计划(步骤列表 + 依赖关系),然后逐步执行:

def plan_and_execute(goal: str, tools: list[Tool]) -> str:
    # 阶段 1:一次 LLM 调用产出完整 Plan(强 schema 约束)
    plan: Plan = llm.complete(
        prompt=PLANNER_PROMPT.format(goal=goal, tools=tools),
        schema=PLAN_SCHEMA,
    )

    # 阶段 2:按依赖关系执行 Plan
    results = {}
    for step in topological_sort(plan.steps):
        # 注入前置步骤的结果作为本步的上下文
        ctx = {dep_id: results[dep_id] for dep_id in step.depends_on}
        results[step.id] = execute_step(step, ctx, tools)

        # 关键:每步执行后判断 Plan 是否仍然有效
        if replan_signal(results[step.id], plan):
            plan = llm.complete(
                prompt=REPLAN_PROMPT.format(plan=plan, executed=results),
                schema=PLAN_SCHEMA,
            )

    # 阶段 3:最终综合
    return llm.complete(SYNTHESIS_PROMPT.format(plan=plan, results=results))

Plan 本身需要严格 schema,否则下游执行器没法消费:

{
  "name": "task_plan",
  "parameters": {
    "type": "object",
    "properties": {
      "analysis": {
        "type": "string",
        "description": "简短分析任务复杂度与拆分思路(≤ 100 字)"
      },
      "steps": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "id": {"type": "integer"},
            "description": {"type": "string"},
            "tool": {"type": "string", "enum": ["search", "calc", "summarize", null]},
            "args": {"type": "object"},
            "depends_on": {"type": "array", "items": {"type": "integer"}},
            "expected_output": {"type": "string"},
            "fallback_action": {"type": "string"}
          },
          "required": ["id", "description", "depends_on"]
        },
        "minItems": 3,
        "maxItems": 7
      },
      "synthesis_step_id": {"type": "integer"}
    },
    "required": ["analysis", "steps", "synthesis_step_id"]
  }
}

minItems: 3, maxItems: 7 是工程上很有效的约束——少于 3 步通常是"该用 ReAct 不该用 Plan-Exec",多于 7 步通常是"过度拆分"。Plan-and-Execute 的隐藏价值:当任务超过 6-7 步时,通常比 ReAct 省钱。原因是 ReAct 每步都要重新把所有历史塞进 prompt,而 Plan-and-Execute 的执行步只需要塞当前步骤的局部上下文。

Replan 机制是这个范式的关键设计点。常见做法是:执行每步后让 LLM 判断"当前计划是否仍然有效"——如果有效则继续,无效则触发 Replan。Replan 的代价不便宜(要重新做一次完整规划),所以触发频率要控制——不能每步都 Replan,但也不能完全不 Replan。

2.3 Tree-of-Thought:探索多条路径

ToT 的思想来自经典搜索算法——把推理建模成树搜索,每个节点是一个中间状态,分支是可能的下一步。LLM 同时生成多个候选下一步、对每个候选评分、选评分最高的展开:

def tot_search(
    task: str,
    branching_factor: int = 3,
    max_depth: int = 4,
    beam_width: int = 2,
) -> str:
    """Tree-of-Thought:beam search 风格的多路径推理"""
    beam = [Node(state=task, score=0.0, parent=None)]

    for depth in range(max_depth):
        candidates = []
        for node in beam:
            # 每个节点生成 N 个候选下一步
            children = llm.complete(
                EXPAND_PROMPT.format(state=node.state),
                n=branching_factor,
            )
            # 对每个候选独立打分(用同一个或不同的 LLM)
            scored = [
                Node(state=c, score=llm_judge(c, task), parent=node)
                for c in children
            ]
            candidates.extend(scored)

        # 剪枝:只保留 top beam_width 个继续展开
        beam = sorted(candidates, key=lambda n: -n.score)[:beam_width]

        if any(n.is_terminal for n in beam):
            return best(beam).reconstruct_path()

    return best(beam).reconstruct_path()

ToT 适合结果可评估的任务——数学题(答案可验证)、代码生成(能跑测试)、创意写作(可由人或另一个 LLM 评分)。不适合结果难评估的任务,因为 ToT 的核心是评分驱动剪枝,评分不准就退化成"昂贵的随机搜索"。

成本是 ToT 的硬伤。一个分支宽度 3、深度 4 的搜索树,理论上要做 3⁴=81 次 LLM 调用。即使做剪枝,5-10 倍的成本相比 ReAct 也是常态。

什么时候 ToT 的 5-10 倍成本值得花?三个判据,全部满足才上:

判据 阈值 不满足时退回
错误的代价 ≥ 单次正确执行成本的 10 倍 关键决策(金融决策、医疗诊断、不可逆操作) ReAct + 反思兜底
评分信号清晰可验证 有外部验证器(编译/运行/单元测试/正则) LLM-judge + Self-Consistency
解空间宽广(多条合理路径) 数学题/代码/设计/创意 单路径推理就够

生产上 ToT 通常不用作整个 Agent 的主循环,而是用在关键节点上——核心决策处展开搜索,其他地方还是 ReAct。一个常见的混合模式是"ReAct 主循环 + 关键步内嵌 ToT"——日常 90% 走 ReAct,遇到"这一步做错很贵"的节点切到 ToT 搜索 + 评估,再回到 ReAct 继续。

2.4 Hierarchical:递归分解

Hierarchical 处理的是"跨粒度复杂度"——任务大到单个 LLM 调用根本理解不了的时候。"实现一个完整的电商系统"这种任务,没法直接 ReAct(步骤可能上千)、也没法 Plan-and-Execute(一个计划塞不下)。解法是递归:

def hierarchical_solve(goal: str, depth: int = 0, max_depth: int = 3) -> Result:
    """递归分解:顶层拆子目标,每个子目标交给下层 Agent"""
    if depth >= max_depth or is_atomic(goal):
        # 触底——用 ReAct 直接解决最细粒度任务
        return react_loop(goal, tools=available_tools())

    # 顶层只做分解,不做执行
    sub_goals = llm.complete(
        DECOMPOSE_PROMPT.format(goal=goal, depth=depth),
        schema=DECOMPOSITION_SCHEMA,
    )

    # 递归解决每个子目标
    sub_results = []
    for sub in sub_goals:
        sub_result = hierarchical_solve(sub.description, depth + 1, max_depth)
        sub_results.append((sub, sub_result))

        # 子目标失败要决定是否回到上层重规划
        if sub_result.failed and sub.is_critical:
            return Result.failed(reason=f"critical sub-goal failed at depth {depth+1}")

    # 上层 Agent 汇总下层结果
    return llm.complete(
        AGGREGATE_PROMPT.format(goal=goal, sub_results=sub_results),
    )

Hierarchical 的工程难点是层间通信:上层 Agent 要把任务"传"给下层,下层 Agent 要把结果"返回"给上层。如果传递的信息过多,上层 Agent 上下文会爆炸;过少则下层 Agent 缺失关键约束。这是为什么 Hierarchical 和多 Agent 协作里的 Supervisor-Worker 模式高度同构——本质上是同一个问题。

2.5 怎么选

场景
1-3 步的简单工具调用 ReAct(规划是过度设计)
5+ 步的多步任务,路径可预测 Plan-and-Execute
创意 / 数学 / 代码——需要探索多解 Tree-of-Thought
跨多个粒度的复杂项目(系统设计) Hierarchical
不确定 从 ReAct 开始,遇到瓶颈再升级

混合形态在生产中很常见——比如 Plan-and-Execute 的某个执行步内嵌一个小型 ReAct 循环("这一步本身需要工具调用"),或者 Hierarchical 的每个 Worker 内部用 Plan-Exec。范式不是互斥的,是可组合的。


3. 如何让 LLM 真的会规划

ReAct/Plan-and-Execute 都依赖一个前提:LLM 能生成合理的计划。但 LLM 不是天生会规划的——训练目标是预测下一个 token,不是"生成最优任务分解"。规划能力需要 prompt 引导。

一个合格的规划 Prompt 的骨架:

你是任务规划者,把一个高层目标拆解为可执行的步骤列表。

## 可用工具
{tools_list}                       # 明确列出,LLM 不可发明新工具

## 输入
目标:{goal}
约束:{constraints}                # 时间预算、成本预算、安全要求

## 规划要求
1. 先输出 analysis 字段判断任务是否需要规划
   - 简单到 1-2 步能做完的,标 needs_planning=false,直接返回 1 步计划
2. 步骤数控制在 3-7 步之间,超出意味着过度拆分
3. 每步必须能用列表中的工具完成;如果工具不够,明确说"need_tool: X"
4. 标注 depends_on——只允许引用更小 id 的步骤(避免循环依赖)
5. 标注 expected_output 强迫思考步骤间数据流
6. 最后一步必须是 synthesis(tool=null),不能以工具调用结尾
7. 每步标注 fallback_action:失败时的兜底动作

输出严格遵循 JSON Schema:{plan_schema_json}
要素 缺失后果
角色定义("你是任务规划者") LLM 直接尝试回答问题,跳过规划
可用资源(工具列表) 生成不可执行的步骤(引用不存在的工具)
输出格式约束(JSON Schema) 生成自由文本"计划",下游无法解析
规划质量约束(步骤数、依赖标注) 过度拆分或步骤间逻辑断裂

三个反复有效的技巧:

  • 强制 analysis 字段:让 LLM 先回答"这任务是否需要多步规划",避免给简单问题写 10 步计划
  • 强制 expected_output:每步预估输出,迫使 LLM 思考步骤间数据流动,减少"步骤 3 依赖步骤 2 的结果,但步骤 2 根本不产生这个结果"
  • 限制步骤数为 3-7 步:没有上限时 LLM 倾向于过度拆分,每步做的事微不足道,反而增加失败概率

规划的常见失败模式

失败 修复
过度拆分(10+ 步) 加步骤数上限
幻觉工具(引用不存在的工具) 明确列出可用工具 + "ONLY use tools from the list above"
循环依赖(step 3 依赖 step 5,step 5 依赖 step 3) 约束 "depends_on must only reference smaller ids"
跳过综合(所有步骤都是工具调用,没有最终综合) 约束 "final step must be a synthesis step with tool: null"
过度乐观(步骤之间假设上一步必然成功) 在 prompt 里要求标注"失败情况下的兜底动作"
没估算成本(每步都用最强模型) 在规划阶段就标注"这一步可用更便宜的模型"

一个常被忽视的工程技巧:规划 prompt 里加入"假设你只有 5 步可用,你会做哪 5 步"这种限制。LLM 在被迫做取舍时往往能产出更好的计划——和资源约束在人类工程师身上的作用一样。


4. 推理增强:让 LLM 想得更深

规划解决"做事的方法论",推理增强解决"每步思考的深度"——LLM 在某一步推理本身错了,规划再好也救不了。

4.1 Chain-of-Thought 家族

CoT 的核心思想极简单:让 LLM 在输出最终答案前先输出中间推理步骤。一句 "Let's think step by step" 在数学和逻辑推理任务上能让准确率提升 10-30%。但 CoT 不是免费的——它把 token 消耗增加 2-5 倍,并且延迟相应增加。

方法 核心 开销 适用
Zero-shot CoT 加一句"逐步思考" 通用任务的快速提升
Few-shot CoT 提供带推理过程的示例 领域特定推理
Self-Consistency 同一问题推理 N 次(temperature > 0),投票取多数 高(N 倍成本) 需要高准确率的关键决策
Chain-of-Verification 推理后自我验证每步 中高 事实性要求高的任务

4.2 Self-Consistency 的伪代码

def self_consistency(
    question: str,
    n_samples: int = 5,
    temperature: float = 0.7,
) -> str:
    """同一问题独立推理 N 次,投票取多数答案"""
    answers = []
    for _ in range(n_samples):
        # 高温度让 LLM 走不同的推理路径
        cot = llm.complete(COT_PROMPT.format(q=question), temperature=temperature)
        # 从 CoT 末尾提取最终答案(按 schema 强制结构)
        final = extract_final_answer(cot)
        answers.append(final)

    # 取出现频率最高的答案
    counts = Counter(answers)
    winner, freq = counts.most_common(1)[0]

    # 一致性低(freq < n/2)意味着 LLM 自己也没把握
    if freq < n_samples / 2:
        return escalate("low_self_consistency", candidates=counts)

    return winner

Self-Consistency 的工程价值:在 GSM8K 数学基准上把 CoT 准确率从 58% 提升到 75%(Wang et al., 2022, arXiv:2203.11171)。Agent 场景里几个真实用法:

用法 场景 收益判据
关键操作确认 "是否执行删除"、"是否走退款"——Agent 推理 5 次取多数 错误代价 ≥ 5 倍 LLM 调用成本
SQL 安全判断 "这条 SQL 是不是只读、是不是越权" 进生产前的硬门槛检查
评估器去偏 LLM-as-Judge 5 次取多数,降低单次评分的随机性 Quality Gate 决策
路由决策的一致性 多 Agent 系统 Router 选哪个 worker——同一问题 5 次结果是否稳定 路由分歧本身就是"应该问澄清"的信号

判断要不要上 Self-Consistency 的最简公式:单次错误代价 ÷ N 倍 LLM 调用成本 > 1,就划算。多次独立推理不容易都犯同一个错——这是 Self-Consistency 的统计基础。

CoT 的失效场景:当任务本身是"模式识别"而非"逻辑推演"时,CoT 不仅不增益,还可能损害准确率——LLM 被迫"编造"推理过程,反而引入错误。情感分析、分类、命名实体识别这类任务通常不需要 CoT。

4.3 推理时扩展(Test-time Compute Scaling)

2024-2025 推理领域最重要的发现:推理阶段投入更多算力可以持续提升质量,且幅度可预测。OpenAI 的 o1/o3 和 Anthropic 的 Extended Thinking 都是这个思路的产品化。这种"推理算力"既包括模型内部的隐式思考(reasoning tokens),也包括 Self-Consistency、ToT 这类显式多路径推理。

对 Agent 工程师,核心问题是:什么时候值得让模型多想一会儿

场景 错误代价 推理边际收益 策略
简单查询(查天气) 直接输出,不需要深度推理
常规工具调用 标准 CoT 足够
复杂数据分析 Extended Thinking / o3
关键决策 很高 Self-Consistency + 人工确认

判断标准是单次错误的代价多花的推理算力代价的比较。简单查询错了影响小,深度推理不划算;关键决策错了代价高(金钱损失、合规风险、用户信任流失),多花 10 倍推理算力也值。

4.4 Reasoning Model 对架构的影响

o1/o3 这类推理模型改变了几个 Agent 架构假设:

假设 之前 现在
LLM 是"快思考" 单次调用亚秒级 单次推理可能 10-60s
工具超时设置 网络/API 慢的兜底 必须区分"LLM 思考时间"和"工具执行时间"
成本模型 按 token 计 推理模型 token 消耗可能是标准模型的 5-20 倍
规划与执行的分工 框架做规划,模型做执行 模型自己规划(内部 CoT),框架只做工具调度

有效模式:用推理模型做规划(一次性高质量规划),用标准模型做执行(快速逐步执行)——和分层规划同构。这种"贵模型规划 + 便宜模型执行"的混合架构在生产中越来越常见,原因是规划阶段的质量天花板很高(一个好规划能省下后面所有步骤),而执行阶段的边际收益很低(执行 prompt 通常简单)。

另一个值得注意的变化:推理模型让显式规划的价值下降了。以前 Plan-and-Execute 的核心价值之一是"用一次完整规划替代多次 ReAct",但推理模型内部已经做了类似的隐式规划,所以推理模型 + ReAct 的组合在很多场景下可以达到"普通模型 + Plan-and-Execute"的效果。


5. 反思:自我纠错

Agent 三类典型失败——LLM 输出错误(幻觉、逻辑错)、工具执行失败(超时、参数错)、计划不可行(前提假设不成立)。没有反思,错误无意识地传播——第 2 步的错变成第 3 步的输入,错误累积。

反思的核心问题:用什么评估、什么时候停

5.1 谁来评估:Self-Critique 的局限

让同一个 LLM 评估自己的输出。理论支持是 LLM 在验证上通常比生成更强——就像检查别人的代码比自己写更容易。这个理论部分成立——在某些任务上 LLM 验证准确率确实高于生成准确率,但前提是验证标准清晰且可检查("这段 SQL 是否能跑通")。

但盲区在于:LLM 的系统性偏见在生成和评估中是一致的——一个倾向于过度自信的模型,评估自己的输出时也倾向于给高分。如果生成阶段 LLM 漏掉了某种边缘情况,评估阶段它大概率也漏掉,因为"想到这个边缘情况"本身是它的盲点。

工程上的对策有几种:

对策 思路 代价
异源评估 Judge 用 Claude,生成用 GPT 多一个 API 依赖
外部信号验证 代码跑测试、SQL 查结果、API 返回 200 实现复杂,但最可靠
多次自评 + 投票 Self-Consistency 思路 成本翻几倍
显式 checklist 列出"评估清单"强制 LLM 逐项检查 prompt 工程负担

最有效的反思是外部信号驱动的——代码能编译运行、SQL 能查到数据、API 返回成功状态码——这些是 LLM 无法"自欺欺人"的硬信号。能用外部信号就别用 LLM Self-Critique。

5.2 反思的结构化输出

为什么反思必须是结构化输出而不是自由文本?三个理由:自由文本的反思下游没法消费——代码不能 if reflection.contains("应该重试"),必须 if reflection.decision == "retry"自由文本会鼓励 LLM 写看起来很有道理的废话,结构化 schema 强迫它在固定字段里给出可被检查的判断;自由文本无法做反思的反思——下一轮想知道上轮反思的根因/置信度/改进幅度,只有字段化才能查询。一句话:反思的输出格式决定了反思机制能不能闭环

Reflect 的 schema 决定了下游能否消费它的判断。一个最小可用的 schema:

{
  "name": "reflection",
  "parameters": {
    "type": "object",
    "properties": {
      "what_went_well": {
        "type": "array",
        "items": {"type": "string"}
      },
      "what_went_wrong": {
        "type": "array",
        "items": {"type": "string"}
      },
      "root_cause": {
        "type": "string",
        "description": "不是症状描述,是根因——'API key 错' 而非 '工具调用失败'"
      },
      "what_to_do_next": {
        "type": "string",
        "description": "具体改进方向,能直接指导下一步动作"
      },
      "decision": {
        "type": "string",
        "enum": ["accept", "retry_same", "retry_with_change", "escalate_to_human", "give_up"]
      },
      "confidence": {"type": "number", "minimum": 0, "maximum": 1},
      "expected_improvement": {
        "type": "number",
        "description": "预计下次重试能改善多少(0-1)。预计 < 0.1 时不该再重试"
      }
    },
    "required": ["root_cause", "decision", "confidence", "expected_improvement"]
  }
}

最关键的字段是 root_cause——它强迫 LLM 不要停留在"输出有点不对"这种症状层面,而要追溯到"为什么会出这个错"。没有 root_cause 字段的反思往往退化成"复述错误",对下一轮决策没有指导价值。

expected_improvement 是改善 improvement_threshold 的关键设计——下面会展开。

5.3 终止条件:四道防线

反思不能无限循环。任何一个条件触发都终止:

反思终止条件

def should_stop_reflecting(history: list[Reflection], state: ReflectState) -> bool:
    """四道防线,任一触发就停"""
    latest = history[-1]

    # 防线 1:质量达标,正常退出
    if latest.confidence >= 0.75 and latest.decision == "accept":
        return True

    # 防线 2:重试次数上限
    if len(history) >= 3:
        return True

    # 防线 3:连续两轮改善幅度太小——反思没有意义了
    if len(history) >= 2:
        if latest.expected_improvement < 0.1:
            return True
        # 实际改善(用外部信号衡量)也很小
        if abs(state.last_score - state.previous_score) < 0.05:
            return True

    # 防线 4:成本兜底
    if state.tokens_used >= state.token_budget:
        return True

    return False
条件 阈值 防什么
confidence ≥ quality_threshold 0.7-0.8 正常退出
attempt ≥ max_retries 3 反复失败
improvement < threshold 连续两轮差距 < 0.1 反思发现问题但提不出改进——再试也没用
total_tokens ≥ cost_budget 一万到几万 token 成本兜底

最容易忽视的是 improvement_threshold——Agent 反复反思但不改进,是反思机制最常见的失败模式。表现形式是 LLM 每次反思都"识别出新问题"但其实是同一个根因的不同表述,重试再多次也解决不了。improvement_threshold 在工程上是说"反思两轮还没明显进步就别再试了,要么人工介入要么换策略"。

5.4 反思的三个陷阱

陷阱 后果 对策
简单任务也反思 浪费 3-4 倍 token 加复杂度判断(长度阈值、关键词),简单任务跳过
反思用大模型 成本翻倍 反思用 GPT-4o-mini 这类小模型
100% 触发反思 平稳期成本不必要 采样反思——30% 的执行触发反思,平稳期降到 10%

反思机制本身要遵守"边际成本=边际收益"的原则。反思加在每一步上既是过度设计也是浪费——大部分步骤本来就是对的,反思只是反复确认。把反思加在关键节点上(产出最终结果之前、不可逆操作之前、长任务的阶段性 milestone)才是高 ROI 的做法。


6. 什么时候该反思、什么时候该跳过

不是所有任务都需要反思。决策按四问筛选:

问题
错误成本高吗? 进下一问 跳过反思(闲聊、简单查询)
错误可自动检测吗? 用外部验证(代码跑测试)——比 LLM Self-Critique 更可靠也更便宜 进下一问
预算够吗? 结构化反思 + 最多 3 轮重试 单轮 Self-Critique 兜底
延迟敏感吗? 是:最多一轮反思 否:完整流程

判断流程的伪代码:

class ReflectMode(Enum):
    SKIP                   = "skip"                  # 不反思,直接返回结果
    EXTERNAL_ONLY          = "external_only"         # 只用外部信号(跑测试/查 API),不用 LLM
    SINGLE_SHOT_CRITIQUE   = "single_shot_critique"  # 一次 LLM 自评,无重试
    ONE_ROUND_LLM_JUDGE    = "one_round_llm_judge"   # 一轮 LLM judge,结构化决策
    FULL_REFLECT_LOOP      = "full_reflect_loop"     # 完整结构化反思 + 多轮重试

def select_reflection_mode(task: TaskSpec, budget: Budget) -> ReflectMode:
    if task.error_cost == "low":
        return ReflectMode.SKIP

    # 外部信号优先——比 LLM Self-Critique 强一个数量级
    if task.has_external_validator:
        return ReflectMode.EXTERNAL_ONLY  # 跑测试、查 API、校验 schema

    if not budget.allows_multi_round_reflection:
        return ReflectMode.SINGLE_SHOT_CRITIQUE

    if task.latency_sensitive:
        return ReflectMode.ONE_ROUND_LLM_JUDGE

    return ReflectMode.FULL_REFLECT_LOOP   # 完整结构化反思 + 多轮

7. 七类任务的范式速查

范式选择矩阵

场景 推荐 原因 切换的触发信号
简单工具调用 ReAct 1-2 步完成,规划过度设计 步数稳定超 7 → Plan-and-Execute
多步研究 / 调研 Plan-and-Execute 需要全局视野和步骤追踪 中途 Replan 频率 > 30% → Hierarchical
创意 / 数学 / 代码 Tree-of-Thought 需探索多条路径 评分信号不可靠 → 回退到 ReAct + 外部验证
复杂项目(系统设计) Hierarchical 粒度跨度大,需递归分解 层间通信成本 > 节点工作量 → 切薄层级
高可靠(金融、法律) Plan-and-Execute + Reflection 全局规划 + 结果验证 Reflection 反复不收敛 → 升级 HITL
实时交互(客服) ReAct 延迟敏感,逐步响应 P95 延迟超 SLA → 加预生成 / 短规划
长时任务(数据管道) Hierarchical + Plan-Exec 可中断、可恢复、可并行 节点失败率 > 5% → 升 Saga 补偿

混合模式在生产中很常见——Hierarchical 的 Worker 内部用 Plan-Exec、Dynamic Routing 的专家内部用 Peer-to-Peer。核心原则:从 ReAct 开始,只在它的局限性确实成为瓶颈时升级

升级触发信号:

触发 升级到
ReAct 步数普遍超过 7 步 Plan-and-Execute
关键决策需要更高准确率 在关键节点引入 Tree-of-Thought 或 Self-Consistency
单个 Agent 上下文不够装下任务知识 Hierarchical
任务有强可验证性(代码、SQL、数学) 加 Reflection + 外部信号

不要因为"看起来更高级"而升级。每个升级都伴随成本翻倍和调试复杂度的跃升。


8. 三种能力如何同时上场

规划、推理、反思单独使用都能提升 Agent 质量,但真正的杠杆在于三者协同

协同模式 描述 适用
规划期推理 规划时让 LLM 用 CoT 仔细思考分解方案 复杂任务,规划质量决定全局质量
执行后反思 每个执行步骤完成后用 Reflection 评估,错则触发局部 Replan 不可逆操作前的兜底
反思驱动重规划 多步反思发现整体计划走偏,触发完整 Replan 长任务的中段调整
推理驱动剪枝 ToT 用 CoT 评估每个分支,剪掉低分支 搜索空间大的任务

一个把三者编织在一起的伪代码——核心是三档模型对应三种用途:贵推理模型管规划质量(一次性投入)、标准模型管执行速度(每步一次)、便宜小模型管反思评判(关键节点偶发)。

def agent_with_three_capabilities(goal: str) -> str:
    plan = llm.complete(PLANNER_PROMPT.format(goal=goal),
                        model="reasoning", schema=PLAN_SCHEMA)   # 贵但只一次

    results = {}
    for step in topological_sort(plan.steps):
        results[step.id] = react_loop(step.description, model="standard")  # 标准模型 ReAct

        if step.is_irreversible:                                  # 关键节点才反思
            reflect = llm.complete(REFLECT_PROMPT.format(step=step, result=results[step.id]),
                                   model="cheap_judge", schema=REFLECTION_SCHEMA)
            if reflect.decision == "retry_with_change": continue
            if reflect.decision == "escalate_to_human": return human_approval(...)
            if reflect.decision == "give_up":           return safe_fail(...)

        if accumulated_drift(results, plan) > REPLAN_THRESHOLD:   # 整体走偏才重规划
            plan = replan(goal, plan, results)
    return synthesize(plan, results)

模型分档的依据:规划阶段的质量天花板高(一个好规划能省下后面所有步骤),所以贵模型一次性投入合算;执行阶段已知步骤要做什么,标准模型够用;反思阶段只是"是否通过 + 决策标签",小模型 + 结构化 schema 即可。三档不区分会让账单贵 5-10 倍。

这种协同的工程意义是:不要把规划、推理、反思看成独立的功能模块,而要看成同一个循环里的不同阶段。一个生产级 Agent 几乎一定会同时用到三者,问题只是用得轻还是用得重。


9. 单 Agent 规划撞墙的四个地方

规划、推理、反思让单 Agent 从"走一步看一步"进化到"先想后做再检查"。但单 Agent 的认知能力终有上限:

  • 上下文窗口限制:任务涉及的知识超出 context window 时,再好的规划也没用
  • 专业性限制:一个 Agent 很难同时擅长编码、写作和数据分析——就像一个人很难同时是程序员、设计师和产品经理
  • 执行效率限制:单 Agent 串行执行,即使计划中的步骤可以并行
  • 决策路径单一:单 Agent 的决策由同一个 LLM 在同一个 prompt 下做出,缺少不同视角的对抗与互补

当这些限制成为瓶颈,需要的不是更好的规划算法,而是多个 Agent 的协作——每个专注擅长领域,由 Orchestrator 协调。


10. 给 LLM 补三种能力的统一逻辑

规划、推理、反思看起来是三件事,本质上是给 LLM 补同一件事——它在 next-token prediction 这个生成机制下做不到的非线性思考。规划补前瞻(任务还没开始就想清楚),推理增强补深度(每一步想得更透),反思补回溯(错了之后能找根因)。三者都不是"换个更大的模型自然就有",是工程上用外部结构搭出来的——CoT 是结构、Plan 是结构、Self-Critique 是结构,让 LLM 在受控的脚手架里产出可消费的中间产物。

工程上最常见的判断错误是把这三件事都当成"上模型就好"。每升级一个模型确实会让基础推理强一些,但规划深度不会自动出现、反思的根因分析也不会自动严谨——这些都是 Prompt 工程 + 输出 Schema + 终止条件 + 评估反馈共同作用的产物。把它们当"功能模块"装上去就够用是浅层理解,把它们看成"循环里的不同阶段"是工程视角。

加载导航中...

评论