第六章 让Agent学会规划,不是让它自由发挥

112 阅读13分钟

上一章我们聊了记忆系统——Agent怎么"记住"事。但记住只是基础,记住之后怎么做,才是Agent能不能干活的关键。

很多Agent演示看起来很酷:给它一个任务,它自己拆步骤、自己调工具、自己修正错误。但真到生产环境,"自由发挥"变成了"自由翻车"——死循环、偏题、忘了目标。

问题出在哪?没有规划,推理就是闭眼猜。

01 规划和推理,不是一回事

先说一个最常见的混淆:很多人把"规划"和"推理"当成同一件事。它们不是。

❌ 推理 Reasoning✅ 规划 Planning
"这一步该做什么?""整体该怎么完成?"
局部的、即时的全局的、前瞻的
基于当前上下文做判断基于最终目标做分解
类似:走一步看一步类似:看地图再出发

没有规划的推理,就是"应激反应"——每一步看起来都合理,但整体方向可能是错的。就像GPS只给你下一步转弯指令,但不告诉你全程路线,你走两步就迷路。

核心区别

推理回答"现在做什么",规划回答"怎么做到"。前者是执行层,后者是策略层。Agent需要两层都有,但规划的优先级更高——方向错了,推理越强跑得越偏。

02 为什么LLM天然不擅长规划

LLM是自回归模型——它只能从左到右生成token。这意味着它本质上是一个"单步预测器",不是一个"全局优化器"。

让它规划一个5步任务时,它是在生成第1步的时候,用对第2-5步的"猜测"来保证一致性。这个猜测经常不准,尤其是:

  1. 步骤间有依赖:第3步需要第1步的结果,但生成第1步时还没执行

  2. 目标约束复杂:要同时满足A、B、C三个条件,LLM容易顾此失彼

  3. 步骤多:超过5步的规划,LLM的准确率急剧下降

fig0-planning-vs-reasoning.png 这就是为什么"让LLM自由发挥"的Agent,在简单任务上表现还行,复杂任务就开始飘。

03 规划的4种主流方法

业界不是没意识到这个问题。以下是4种主流的规划方法,各有适用场景:

方法1:单次规划(Plan-then-Execute)

最朴素的方法:先让LLM生成完整计划,再逐步执行。

plan = llm.generate_plan(task="帮我调研竞品并写报告")
for step in plan:
    result = execute(step)
    # 问题:如果第2步发现数据不够,计划怎么办?

优点:简单、可控、容易调试

缺点:不适应变化。执行中发现计划有问题,要么硬着头皮走,要么全盘重来

方法2:ReAct(推理+行动交替)

最流行的Agent范式:思考和行动交替进行。

while not done:
    thought = llm.think(observation)    # "我需要先查竞品列表"
    action = llm.act(thought)            # 调用search_competitors
    observation = execute(action)         # 得到结果

优点:灵活、能根据中间结果调整

缺点:没有全局约束,容易"跑偏"——搜索着搜索着开始研究无关话题

方法3:规划-执行-重规划(Plan-Execute-Replan)

结合前两者的优点:有全局计划,但允许中途调整。

plan = llm.generate_plan(task)

while not done:
    step = plan.pop(0)
    result = execute(step)
    
    if need_replan(result):
        # 根据新信息重新规划剩余步骤
        remaining_plan = llm.replan(
            original_goal=task,
            completed=done_steps,
            new_info=result
        )
        plan = remaining_plan

优点:兼顾全局和局部,是工程实践中最实用的方法

缺点:replan的触发条件需要仔细设计,过于频繁replan等于没有计划

⚠️ ⚠️ replan频率是个关键参数:太低→计划过时,太高→和没有计划一样。经验值:每3-5步replan一次,或在工具返回异常时触发。

方法4:树搜索(Tree of Thought / MCTS)

最"学术"的方法:把规划当成搜索问题,探索多条路径,选最优解。

fig1-four-planning-methods.png 优点:理论上最优,能处理多约束问题

缺点:token消耗巨大,延迟高,实践中很少用——除非你的任务真的值这个成本

方法选择指南

简单线性任务 → 单次规划 需要灵活应变 → ReAct 生产环境首选 → Plan-Execute-Replan 高价值复杂决策 → 树搜索(慎重)

04 规划最大的坑:目标漂移

目标漂移(Goal Drift)是Agent规划的头号杀手。表现:Agent开始执行任务A,中间发现有趣的B,转而去做B,最后忘了A。

听起来像个笑话?但在ReAct模式下,这是常态。原因:

  1. LLM的注意力被新信息吸引:搜索结果里的"有趣"内容比原始目标更抓眼球

  2. 没有目标校验机制:每一步推理都是独立的,没有人问"这和原始目标还有关系吗?"

  3. 上下文稀释:随着对话变长,原始目标在上下文中的权重越来越低 gr

fig2-goal-drift.png

怎么对抗目标漂移?3个实战技巧:

技巧1:目标注入(Goal Injection)

不是在开头说一次目标就够了——每一步都提醒LLM原始目标是什么:

system = f"""
你的原始任务是:{original_goal}
当前进度:{completed_steps}/{total_steps}
请在思考时确认:我这一步是否服务于原始目标?
"""

技巧2:相关性检查(Relevance Check)

在执行任何工具调用之前,加一步轻量级检查:

def should_execute(action, original_goal):
    check = llm.judge(
        f"执行'{action}'是否有助于完成'{original_goal}'?只回答是或否"
    )
    return check == "是"

代价:每次判断多消耗几十个token。收益:避免浪费成百上千个token在无关操作上。

技巧3:步骤预算(Step Budget)

给Agent设定步骤上限。不是技术限制,是经济限制——超过N步还没完成,就停下来汇报当前进度,让人类决定是否继续。

MAX_STEPS = 10 # 根据任务复杂度设定
if step_count > MAX_STEPS:
    return "已达到步骤上限,当前进度:..."

05 多步推理的幻觉问题

LLM做规划时有个很隐蔽的坑:它会"假装"推理

让它规划一个5步任务,它可能写出看起来逻辑自洽的5步计划。但仔细检查会发现:第3步的输入需要第2步的输出,但第2步的输出根本不可能提供第3步需要的格式。

这不是"幻觉"(hallucination),更像是"推理幻觉"——推理过程看起来合理,但基于错误的因果假设

❌ 错误示例✅ 正确做法
步骤2: "调用API获取用户列表"步骤2: "调用API获取用户列表"
→ 返回: [{name: "张三"}, ...]步骤2.5: "根据用户ID查询订单"
步骤3: "从返回的订单数据中提取金额"→ 用步骤2的结果作为步骤2.5的输入
→ ❌ 步骤2没有返回订单数据!→ 确保每步的输入输出对齐

**怎么解决?**在规划阶段就做"输入输出对齐检查":

def validate_plan(plan):
    for i in range(1, len(plan)):
        # 检查步骤i的输入是否可以被步骤i-1的输出满足
        input_ok = llm.judge(
            f"步骤'{plan[i]}'的输入,能否由步骤'{plan[i-1]}'的输出提供?"
        )
        if not input_ok:
            # 自动插入中间步骤或修改计划
            plan = llm.fix_plan(plan, broken_step=i)
    return plan

06 实战:一个可靠的Agent规划层设计

把上面的原则整合起来,一个生产可用的规划层应该长这样:

class AgentPlanner:
    def __init__(self, task, max_steps=10, replan_interval=3):
        self.task = task
        self.max_steps = max_steps
        self.replan_interval = replan_interval
        self.completed = []
        self.plan = self._initial_plan()
    
    def _initial_plan(self):
        # 1. 生成初始计划
        plan = llm.generate_plan(self.task)
        # 2. 输入输出对齐检查
        plan = self._validate_io_alignment(plan)
        # 3. 步骤预算校验
assert len(plan) <= self.max_steps
        return plan
    
    def next_step(self, observation):
        # 目标注入:每步都带原始目标
        context = {
            "goal": self.task,
            "completed": self.completed,
            "observation": observation
        }
        
        # 相关性检查
if not self._check_relevance(observation):
            return "检测结果偏离目标,正在重新对齐..."
if len(self.completed) % self.replan_interval == 0:
            self.plan = self._replan(observation)
        
        return self.plan.pop(0)
    
    def _replan(self, new_info):
        # 基于已完成步骤和新信息重新规划
        remaining = llm.replan(
            goal=self.task,
            done=self.completed,
            new_observation=new_info,
            steps_left=self.max_steps - len(self.completed)
        )
        return self._validate_io_alignment(remaining)

07 规划层的成本账

规划不是免费的。每多一层规划,就多消耗token、增加延迟。算笔账:

无规划(纯ReAct): 每步1次LLM调用 × N步 = N次调用 总token ≈ N × 500(平均每步)

Plan-Execute-Replan: 初始规划1次 + 每步1次 + 每3步replan 1次 总token ≈ 1×1500 + N×500 + (N/3)×1000 ≈ N×833 + 1500

带相关性检查: 在Plan-Execute-Replan基础上,每步多1次轻量判断(≈100 token) 总token ≈ N×933 + 1500

看起来多了不少?但比起目标漂移导致的无效执行(可能浪费10+步),规划层的开销是值得的。

成本取舍原则

规划层的成本,取决于任务失败的成本。如果一步错就浪费大量token(如调用了付费API、修改了数据),规划层越重越好。如果每步成本很低(只是搜索),轻量规划就够。

08 推理模型:从"不擅长规划"到"规划即推理"

上面整篇文章建立在一个前提上:LLM天然不擅长规划。

这个前提正在动摇。

什么是推理模型

推理模型(reasoning model)——OpenAI的o4/GPT-5.5 Thinking、DeepSeek的R3、Qwen的QwQ-32B——的共同特征:在给出最终回答前,先做一段隐式的思维链(Chain-of-Thought)推理

传统模型(GPT-5.1、Claude Sonnet)是"脱口而出"——收到问题,直接生成答案。

推理模型是"先想再说"——收到问题,先在内部推理几百到几千个token,然后给出答案。这段内部推理对用户不可见(OpenAI称之为"reasoning tokens"),但模型在推理过程中可以自我纠错、回溯、验证。

这和Agent规划有什么关系?关系大了。

推理模型天然更擅长规划

回到02节讲的"LLM不擅长规划的3个原因":

  1. 步骤间有依赖 → 推理模型在内部推理时可以模拟执行结果,提前发现依赖问题
  2. 目标约束复杂 → 推理模型的内部CoT可以逐一检查约束,减少遗漏
  3. 步骤多时准确率下降 → 推理模型的thinking token可以"延展"推理深度,虽然仍然有上限,但比直接生成强得多

实际数据:在SWE-bench(软件工程任务)上,o4的通过率是传统模型的2-3倍。这本质上是因为软件工程任务需要"先理解代码结构→制定修改计划→分步执行→验证结果",这正是规划能力的体现。

推理模型+Agent的3种融合模式

模式1:推理模型作为规划器

# 用推理模型做规划,普通模型做执行
planner = ReasoningModel("o4")  # 擅长全局规划
executor = ChatModel("gpt-5.1")  # 擅长快速执行

plan = planner.generate_plan(task)  # o4的内部CoT会做深度规划
for step in plan:
    result = executor.execute(step)  # GPT-5.1快速执行单步
    if need_replan:
        plan = planner.replan(task, done, result)

优点:规划质量高,执行成本低。o4的reasoning token虽然贵(约$15/M input),但规划调用次数少(1-3次),执行用便宜的GPT-5.1。

缺点:规划和执行脱节——推理模型生成的计划可能假设了不存在的工具能力。

模式2:推理模型全链路

# 整个Agent循环用推理模型
while not done:
    thought = GPT-5.5 Thinking.think(observation)   # 内部自动做深度推理
    action = GPT-5.5 Thinking.act(thought)
    observation = execute(action)

优点:最简单,每一步推理模型都会自己"想清楚"再行动。

缺点太贵了。o4每次调用的reasoning token可能消耗5K-50K tokens。一个10步的Agent任务,光reasoning就50K-500K tokens,成本0.750.75-7.5。加上output token,单任务成本轻松超过$10。

模式3:推理模型按需激活(推荐)

# 默认用普通模型,遇到复杂决策时切换到推理模型
class HybridAgent:
    def __init__(self):
        self.fast_model = ChatModel("gpt-5.1")      # 日常执行
        self.thinking_model = ReasoningModel("o4-mini")  # 复杂决策
    
    def plan_step(self, context):
        complexity = self._assess_complexity(context)
        
        if complexity == "simple":
            return self.fast_model.think(context)
        elif complexity == "moderate":
            return self.thinking_model.think(context)
        else:  # complex
            return self.thinking_model.deep_think(context)  # 更多reasoning budget
    
    def _assess_complexity(self, context):
        """评估当前决策的复杂度"""
        # 简单:单步可完成,工具调用明确
        # 中等:需要2-3步推理,有约束条件
        # 复杂:多约束、多依赖、需要回溯
        ...

优点:成本可控。90%的步骤用便宜模型,只在关键决策点用推理模型。

缺点:复杂度评估本身可能不准——你怎么知道当前步骤是"简单"还是"复杂"?

实践建议:用一个简单的启发式——凡是需要replan的步骤,都用推理模型。正常执行用普通模型。这天然实现了"普通模型执行 + 推理模型兜底"。

DeepSeek R3:推理模型的性价比标杆

DeepSeek R3的特殊之处在于:它的推理能力接近o4,但成本只有o4的1/20

  • DeepSeek R3 API定价:约0.55/Minputtokensvso40.55/M input tokens(vs o4的15/M)
  • 在数学推理、代码生成等任务上,DeepSeek R3接近o4的80-90%水平
  • 开源,可以本地部署(671B参数,需要多卡,但DeepSeek R3-Distill版本可以单卡跑)

对Agent规划的影响:DeepSeek R3让推理模型不再是"高端玩家专属"。以前只有高价值任务才用得起o4做规划,现在中等价值任务也可以用DeepSeek R3做推理了。

但DeepSeek R3有个坑:它的reasoning token虽然是隐式的,但API仍然计费。而且DeepSeek R3的reasoning过程有时会"跑偏"——在CoT中开始讨论无关话题,浪费大量reasoning token。需要设置max_tokens限制来控制。

推理模型的"规划陷阱"

推理模型更强了,但不是万能的。实战中有3个陷阱:

陷阱1:过度推理

推理模型倾向于"想太多"——一个3步就能搞定的任务,o4可能在内部CoT中推理了20步。这不是质量问题,是成本问题。一个简单的查询任务,用o4比用GPT-5.1贵10倍,但结果可能只好了5%。

解法:根据任务类型选择模型,不要无脑用推理模型。简单查询→GPT-5.1,复杂推理→o4/o4-mini。

陷阱2:推理与工具的断裂

推理模型在内部CoT中做了一个完美的计划,但到了实际调用工具时,可能发现:

  • 工具的参数格式和推理模型假设的不一样
  • 工具的返回结果和推理模型预期的不一样
  • 推理模型"以为"某个工具存在,但实际没有

解法:推理模型的plan必须经过"工具可用性校验"——在执行前,检查计划中涉及的每个工具是否存在、参数是否匹配。

陷阱3:推理延迟

推理模型的thinking时间可能是普通模型的5-10倍。o4处理一个复杂问题可能需要30-60秒的思考时间。在Agent交互场景中,用户等待1分钟是很差的体验。

解法:推理模型适合后台任务和批量处理,不适合实时交互。面向用户的Agent,用推理模型做规划、普通模型做交互。

更新后的规划方法选择指南

任务类型推理模型方案普通模型方案原因
简单线性任务单次规划单次规划 + 普通模型不需要推理模型
灵活应变任务ReActReAct + 推理模型按需激活关键决策用推理模型
生产环境Plan-Execute-ReplanPlan-Execute-Replan + 混合模型规划用推理模型,执行用普通模型
高价值复杂决策树搜索推理模型全链路 或 树搜索+推理模型推理模型的CoT部分替代了树搜索

一句话总结:推理模型没有消除规划问题,但把"LLM不擅长规划"的天花板抬高了。以前需要复杂的规划框架来弥补LLM的不足,现在推理模型可以承担更多规划职责,框架可以更轻。但目标漂移、多步幻觉等老问题仍然需要工程手段兜底。