规划、推理与反思

目录

有了可用的记忆与证据,Agent 仍需要决定下一步:继续查询、调整计划,还是交付已有结论。规划、推理与反思分别关注行动安排、判断依据和结果检查,它们共同服务于任务完成。

不能从 next-token prediction 推导出“模型不会前瞻、不能规划、无法修正”。模型可以生成计划并在后续输出中修改它;工程要解决的是如何表达依赖、执行计划、验证结果,以及在失败后可靠地改变后续动作。

延续订单异常调查场景,本篇比较几种组织方式,并说明搜索、投票和反思怎样获得真实收益。

1. 先分清职责,再决定是否拆开调用

职责 问什么 订单调查中的例子
规划 为完成目标,需要哪些步骤与依赖? 先获取支付请求 ID,再查询支付方状态
推理 现有事实支持什么判断? 订单未确认且支付查询超时,只能说明结果未知
反思 实际结果是否符合预期,下一步怎样调整? 原查询没有返回最终状态,需要换证据来源

三者可以在同一轮决策中完成,也可以拆成独立阶段。分开有利于评估与复用,却会增加调用、信息传递和状态管理。是否拆分应由任务需要决定,而不是要求每一步都调用 Planner、Executor 和 Reflector。

真正需要独立保证的是执行边界:计划由谁提出,不改变授权与业务规则;反思是否单独调用模型,不改变结果需要核验的要求。

2. 四种组织方式可以组合

方式 核心机制 适用信号 需要承担的成本
ReAct 随观察结果提出下一步动作 环境变化多,事先难以确定完整路径 多轮调用与上下文管理
Plan-and-Execute 显式计划与依赖,再调度执行 步骤依赖、进度追踪和交付要求较明确 计划验证、更新与恢复
Tree of Thoughts 展开候选思路,评估后保留分支 存在多种候选,且有可用的评价信号 搜索、评分与候选状态管理
Hierarchical 将目标分解为不同粒度的子任务 单一任务范围过大,子任务边界明确 层间契约、协调与整体预算

这些不是从低级到高级的必经路线。一个显式计划中的调查步骤可以使用 ReAct,一个单 Agent 也可以并行调用独立工具,不必为了并行而拆成多个 Agent。

ReAct:行动产生下一轮所需的证据

ReAct把推理与行动交替组织。查询发现新信息后,模型可以改变下一步;它并不要求模型永远只看局部,也不排斥保留整体目标和计划。

沿用运行时篇的控制循环,关键是记录模型调用与工具结果、检查权限和预算,并区分回答与完成。这里不再复制一份省略校验的循环。

长任务的成本取决于消息策略、结果大小和调用次数,不能用“超过 7 步就不适用”划线。先看主要开销来自反复推理、冗余工具调用,还是重复传递不相关历史,再决定是否改成显式计划。

Plan-and-Execute:把依赖变成可检查的数据

对于订单调查,一个初始计划可以是:

{
  "plan_version": 1,
  "steps": [
    {
      "id": "order",
      "tool": "query_order",
      "depends_on": [],
      "expected_output": "订单当前状态及支付请求标识"
    },
    {
      "id": "events",
      "tool": "query_order_events",
      "depends_on": [],
      "expected_output": "订单状态变更记录"
    },
    {
      "id": "payment",
      "tool": "query_payment_status",
      "depends_on": ["order"],
      "expected_output": "已有支付请求的处理状态"
    }
  ]
}

这是计划实例,省略了工具参数的绑定细节;并不是可直接提交给某个 SDK 的定义。订单查询与事件查询可以独立执行,支付查询依赖订单结果。是否增加最终综合步骤,由输出目标决定,不必规定所有计划最后都调用模型。

Schema 能检查字段类型,却不能独立保证步骤 ID 唯一、依赖存在、没有环或工具参数能从前置输出中得到。下面的 Python 函数可运行,用于验证有限 DAG 的依赖并给出一个合法顺序:

def topological_order(steps):
    by_id = {}
    for step in steps:
        sid = step["id"]
        if sid in by_id:
            raise ValueError("duplicate step id")
        by_id[sid] = step

    remaining = {}
    for sid, step in by_id.items():
        dependencies = set(step["depends_on"])
        if sid in dependencies or not dependencies <= by_id.keys():
            raise ValueError("invalid dependency")
        remaining[sid] = dependencies

    ordered = []
    while remaining:
        ready = [sid for sid, deps in remaining.items() if not deps]
        if not ready:
            raise ValueError("cyclic dependency")
        ordered.extend(ready)
        for sid in ready:
            del remaining[sid]
        for deps in remaining.values():
            deps.difference_update(ready)
    return ordered

这个函数不执行任务,也不验证业务权限。DAG 是这里选择的计划表示;包含循环和等待的任务可以使用状态机,不能把所有工作流都称为 DAG。

重规划要改变真正的调度对象

常见错误是遍历旧计划的拓扑排序时,只给 plan 变量赋一个新值。循环仍会继续执行旧列表,新计划实际上没有生效。

正确方向是保存带版本的计划和步骤状态,调度器每次从当前版本选择就绪步骤。发生重规划时,要明确哪些已完成结果可以复用、哪些未开始步骤作废、哪些进行中的任务需要等待或取消。

以下为教学伪代码:

while scheduler.can_continue(task):
    plan, states = scheduler.load_current(task)
    step = scheduler.next_ready(plan, states)
    if step is None:
        return scheduler.resolve_no_ready_step(task, plan, states)

    result = runtime.execute_checked(step, states)
    scheduler.record_result(task, plan.version, step.id, result)

    if needs_replanning(result, plan):
        proposal = planner.revise(plan, states, result)
        validate_plan(proposal)
        scheduler.replace_pending_plan(
            task, expected_version=plan.version, proposal=proposal
        )

版本检查防止旧调度者覆盖新计划。重规划不能抹掉已经发生的支付、退款等副作用;继续执行、取消或补偿都要遵循实际业务操作状态。

3. 搜索候选,不等于并行试做真实业务

Tree of Thoughts研究把中间思路作为搜索节点,结合候选生成、评价和搜索策略处理任务。它适合在可评价空间中探索;评价偏差也可能让搜索更快地淘汰正确答案。

计算成本应按搜索策略统计。分支数 3、深度 4 的完整树有 81 个叶子,根之外共有 3+9+27+81=120 个节点。81 不是固定的模型调用次数:候选可以批量生成,评分也可以批量处理,剪枝还会改变访问节点数。

如果每层只保留两个节点继续展开,初始一层生成 3 个候选,后面三层各最多生成 6 个,共最多 21 个候选;这仍未包含评分、提前终止等细节。不能直接写成“成本必然是 ReAct 的十倍”。

订单调查可以比较几种证据获取方案,但不能为了选出最优分支,实际尝试多次扣款或退款。候选搜索应作用于计划、草稿、沙箱测试或可回滚模拟;真实动作仍由授权运行时按单一业务操作执行。

分层规划也有同样边界。子任务应带目标、输入、可用工具、预算和验收条件,不能只传一句描述就默认继承所有权限。父任务还需要控制总调用量与深度,避免每个子任务都使用完整预算导致整体失控。

4. 多次采样能改善答案,也会重复同一类错误

Self-Consistency通过采样多条推理路径并聚合答案,在论文研究的推理基准上获得了改善。这支持把多样化采样作为实验方法,不能直接推出它适合替代权限检查。

多数投票有几个前提:答案可以规范化比较,候选具有足够差异,评价目标一致。不同采样仍来自共享模型与上下文,错误可能高度相关;“独立采样”不等于“错误相互独立”。

下面是严格多数聚合的可运行示例,输入是已规范化的离散答案:

from collections import Counter

def strict_majority(answers):
    if not answers:
        return {"status": "insufficient", "answer": None}
    counts = Counter(answers)
    winner, votes = counts.most_common(1)[0]
    if votes * 2 <= len(answers):
        return {"status": "inconclusive", "answer": None}
    return {"status": "majority", "answer": winner}

四个候选中两个相同,只是半数,不能当作严格多数;没有多数时也不应让列表顺序决定胜者。即使得到多数,状态仍是“多数意见”,不是“已验证正确”。

SQL 是否越权、用户是否授权删除、退款金额是否可用,都应由相应的权限与业务机制判断。让模型投票五次不会产生执行授权。

评估采样是否划算,需要估计错误率减少量 × 错误损失,再与新增计算、延迟和维护成本比较。只把单次错误损失除以模型费用,会遗漏“增加采样究竟减少多少错误”这个关键因素。

5. 增加推理算力应服从任务评估

推理时计算扩展研究讨论了如何分配额外推理计算,以及收益与问题难度、方法选择之间的关系。更多计算可能改善结果,但不是每个任务都持续获益,也不能保证稳定的提升幅度。

可比较的方案包括单次标准调用、更高推理预算、多次候选采样、外部验证与局部搜索。比较时保持任务集和成功标准一致,记录成功率、延迟分位数与每个成功任务的成本。

模型分工也需要实测:更强模型规划、较轻模型执行或评价,可以节省成本,但评价“是否正确”并不必然比生成更简单。输出只有一个通过标签,不代表判断过程容易。

内部推理能力增强,可能减少应用层展开候选的必要性;显式计划仍可用于进度展示、审批、依赖调度和恢复。内部推理不能替代这些持久执行契约。

6. 反思需要证据,不要求编造根因

反思可以来自规则、测试、工具结果、人工反馈或模型评价。它的价值是发现具体差距并指导下一步,而不是每次都生成一段“我反思了”。

Chain-of-Verification研究了生成与验证步骤的组织方式。工程中无论采用哪种方法,都要先明确验证的信号能证明什么。

信号 可以证明什么 不能直接证明什么
编译通过 代码满足本次编译检查 业务行为正确
测试通过 覆盖用例的断言成立 未覆盖场景全部正确
HTTP 200 收到该接口的成功状态响应 请求的全部业务目标已完成
SQL 返回记录 查询获得了数据 条件、权限和业务结论都正确
模型评价通过 评价器按输入给出通过判断 没有偏差、幻觉或遗漏

强制要求模型填写“根因”,反而可能诱导它在证据不足时编造解释。可以用这样的反思记录:

{
  "decision": "gather_evidence",
  "observed_issue": "支付状态查询超时",
  "confirmed_cause": null,
  "hypotheses": [
    "查询服务暂时不可用",
    "网络链路超时"
  ],
  "evidence_refs": ["tool-result-002"],
  "next_action": "查询已有支付请求状态,暂不重新提交支付"
}

这里保留了症状、假设与未知项。后续恢复成功,也不能倒推出先前的超时一定由某个具体原因造成。

模型自报置信度和预计改善值可以记录,但没有校准时,不应以“0.75 就接受”或“预计改善低于 0.1 就停止”作为通用阈值。

7. 执行前检查与执行后核验不能颠倒

不可逆操作必须在执行前检查授权、金额、对象、状态及必要审批。执行后的反思用于核对结果和处理异常,不能补回已经错过的执行许可。

候选动作先经过授权与业务检查,执行后核验结果并决定完成、调整或暂停

反思循环应由几类可解释条件约束:

条件 对应结果
明确验收条件满足 标记完成,保存证据
缺少必要信息或授权 等待输入或审批
可恢复错误且还有预算 有限重试或调整方案
多次无进展,或评价信号不足 暂停、升级或交付未完成说明
用户取消、时限或预算耗尽 停止新动作,记录已有操作状态
结果未知且可能已有副作用 查询和核对原操作,不盲目重做

重试次数与改善阈值应按任务配置。安全与授权检查不能为了节省成本而随机抽样;可以抽样的是额外质量分析或离线评估,且要与必需检查明确区分。

8. 用失败样本决定架构调整

如果 Agent 总在同一项查询上打转,先检查工具结果和任务状态,不要马上增加另一个评估 Agent。如果计划经常失效,先看环境信息是否不足、步骤粒度是否合适,再考虑局部重规划或分层。

几种有区分度的验证包括:

  • 让计划包含重复 ID、缺失依赖和环,确认执行前拒绝
  • 在中途替换计划,确认旧的待执行步骤确实不再被调度
  • 提供四个候选答案的 2:2 平票,确认不被当作多数通过
  • 让接口返回受理成功但业务仍处理中,确认不会标记完成
  • 让新方案修改退款金额,确认原审批和幂等参数不会被直接复用
  • 让反思无法确定根因,确认系统保留未知并继续收集允许的证据

规划、推理和反思的收益,最终体现为更少无效动作、更准确的判断与更可靠的结果。需要何种组织形式,应由这些证据决定。下一篇把依赖和调度进一步展开为显式工作流中的串联、路由与并行。

评论