模型给出一个答案以后, 在不改参数, 不改提示模板, 不改任何可保留状态的前提下, 还能不能把这一题做得更好? 这是 L0 要回答的问题. 修订, 搜索和验证都在做这件事, 差别在信号从哪来: 模型自己写的反馈, 多次采样的投票, 还是执行结果, 测试和检索到的资料.
1. L0 的边界
1.1. 定义
沿用 1.2 的记号. 当前任务的轨迹记为 , 输出记为 , 可保留状态记为 . 一次 L0 转移写成
第一个条件说输出或产生它的轨迹在实际起作用的语义上变了. 第二个条件说可保留状态没变. 两个条件合起来, 就是「这一题的答案变了, Agent 没变」.
1.2. 任务内的临时状态
这个边界允许任务内存在相当多的临时状态. 自我批评, 多候选搜索, 验证, 甚至很长的工作记忆, 都可以在 L0 内部运行. 综述举的例子是 Focus: 它把一条很长的软件工程轨迹压缩成一个紧凑的知识块, 并删掉更早的交互, 让 Agent 在同一个任务里继续工作. 这样能延长有效的推理长度, 但压缩出来的知识块不跨任务保留, 所以仍然是 L0.
不跨任务保留有两面. 一面是隔离: 一次有害的修改通常随这一题结束而丢弃, 不会污染之后的任务. 另一面是能力上限: 一次正确的修正也不会留下来, 下一道同类题要重新发现一遍.
1.3. 迭代修订: Self-Refine
机制:Self-Refine (Madaan et al., 2023) 用同一个模型 完成三件事: 生成初稿, 给初稿写反馈, 按反馈改写. 三件事各用一个少样本提示: , , . 不需要训练. 初稿由输入 和生成提示拼接后得到 ( 表示拼接):
第 轮的反馈由同一个模型对当前输出 写出:
改写时, 模型拿到的不只是最近一轮的输出和反馈, 而是全部历史:
停止条件 有两种: 到达指定轮数, 或者从反馈里提取一个停止信号, 比如让模型在反馈里给一个分数. 论文实验里最多迭代 4 轮, 返回最终一轮的 . 式 (2) 的提示示例是「输入, 输出, 反馈」三元组, 论文要求示例里的反馈「可执行」和「具体」. 可执行指反馈里包含一个可能改善输出的具体动作; 具体指反馈指出输出中需要改的那一处. 论文里代码优化的例子是: 初稿用循环求 , 反馈指出这是暴力求和, 应该用 , 改写后的代码直接返回 (n*(n+1))//2.
结果:论文在 7 个任务上用 GPT-3.5 (text-davinci-003), ChatGPT (gpt-3.5-turbo) 和 GPT-4 做了对比. 下表摘录 GPT-4 一列 (数字是各任务自己的指标, 偏好类任务是被偏好的比例):
| 任务 | 基线 | + Self-Refine | 指标 |
|---|---|---|---|
| 对话回复 | 25.4 | 74.6 | GPT-4 偏好 |
| 代码可读性 | 27.4 | 56.2 | 命名恰当的变量占比 (GPT-4 判) |
| 约束生成 | 15.0 | 45.0 | 概念覆盖率 |
| 代码优化 | 27.3 | 36.0 | 被优化的程序占比 |
| 数学推理 (GSM8K) | 92.9 | 93.1 | 解题率 |
前四行的增益大, 最终一行几乎没有. GPT-3.5 在数学推理上是 64.1 到 64.1, 完全没变. 论文自己给了数学推理没有增益的原因: 数学里的错误常常只在某一行或某一步运算, 而一条看起来前后一致的推理链会让模型认为「everything looks good」. ChatGPT 在 94% 的样本上给出的反馈就是这句话. 论文附录 H.1 报告, 如果由外部来源告诉模型当前答案错了, 数学推理上的增益会超过 5 个百分点.
这组数字说明了 Self-Refine 起作用的条件. 对话回复, 代码可读性, 约束生成这几类任务, 模型自己就能看出初稿哪里不满足要求: 回复没有接住用户的话, 变量名不清楚, 漏了某个必须出现的概念. 数学推理的错误, 模型自己看不出来. 反馈环节识别不出错误时, 改写环节没有东西可改.
消融: 反馈和轮数:论文做了两组消融. 第一组换掉反馈的质量:
| 任务 | Self-Refine 反馈 | 泛泛的反馈 | 无反馈 |
|---|---|---|---|
| 代码优化 | 27.5 | 26.0 | 24.8 |
| 情感反转 | 43.2 | 31.2 | 0 |
| 缩写生成 | 56.4 | 54.0 | 48.0 |
「泛泛的反馈」指让模型写一句笼统的改进意见. 「无反馈」指模型仍然迭代改写, 但不显式写反馈. 情感反转一栏从 43.2 掉到 0, 说明这个任务里, 模型不先说出「哪里没有反转」, 改写就完全失败. 第二组看轮数. 三个任务上, 各轮的得分 (三个模型平均) 如下:
| 任务 | ||||
|---|---|---|---|---|
| 代码优化 | 22.0 | 27.0 | 27.9 | 28.8 |
| 情感反转 | 33.9 | 34.9 | 36.1 | 36.8 |
| 约束生成 | 29.0 | 40.3 | 46.7 | 49.7 |
代码优化的总增益是 , 其中第一轮贡献 , 占 74%. 后两轮各只加 0.9. 约束生成的增益分布更平: 三轮依次是 11.3, 6.4, 3.0. 多数增益来自前一两轮. 论文还测了较弱的 Vicuna-13B. 它能生成初稿, 但不能稳定地按要求格式写反馈; 即使直接给它人工写好的反馈, 它也常常重复原来的输出, 或者编出一段不相干的对话. Self-Refine 要求模型同时具备三种能力: 生成, 诊断, 按诊断改写. 缺一种, 循环就转不起来.
角色分离?Self-Refine 让同一个模型扮演生成者和批评者. 一种变体是把角色拆开. 综述提到的 Table-Critic 把表格推理的修订拆成判官 (Judge), 批评者 (Critic), 修订者 (Refiner) 三个角色: 判官定位错误, 批评者写批评, 修订者改. 这让修复过程更明确. 但拆角色不改变一件事: 如果三个角色由同一个模型扮演, 用同一套判断标准, 它们的盲区也相同. 判官看不出的错误, 批评者和修订者同样看不出. 综述对这一类方法的结论是, 重复提示和角色分离都不能保证得到独立的诊断.
2. 有外部依据的修复
2.1. 执行, 测试和证明
模型自己写的反馈有盲区. 一个直接的办法是换一个反馈来源: 让程序跑一遍, 让测试判一遍, 让证明助手检查一遍. 这些信号不经过模型的判断, 能暴露模型看不出的错误. 综述列了几类代表系统. SELF-DEBUGGING 根据程序的执行结果修改程序. AlphaCodium 和 Agentless 把反思, 错误定位, 构造测试, 执行和补丁验证组合成一条流水线. Baldur 用证明助手 Isabelle 返回的错误信息修复证明. AgentCoder 把写代码, 设计测试, 执行分给不同的角色.
这些检查比模型自己的批评更有区分力: 一个测试失败了就是失败了, 不受模型「觉得对不对」影响. 它们的局限也很明确. 测试不完整时, 错误的程序可以通过全部测试; 规格写得不完整时, 证明通过也只说明满足了写下来的那部分规格.
2.2. 把成本算进来以后: Olausson 等人的实验
Olausson 等人 (2023) 在 HumanEval 和 APPS 上研究了 Code Llama, GPT-3.5 和 GPT-4 的自我修复 (self-repair): 程序没通过测试, 模型读错误信息, 写一段解释, 再生成修复后的程序. 这篇论文的关键设置是把修复的成本算进去. 自我修复要多调用几次模型. 如果把这些调用换成直接多采样几个程序, 结果可能同样好. 论文的结论是: 按相同的采样预算比较, 自我修复的增益通常不大, 在不同数据子集之间差别很大, 有时完全没有. 论文认为瓶颈在反馈环节: 模型对自己代码的解释质量不够. 为了验证这一点, 他们请 16 名有经验的程序员, 为 GPT-4 写错的 40 个程序各写两份反馈, 再让 GPT-4 按人写的反馈修复:
| 难度 | GPT-4 自己的反馈 | 人写的反馈 |
|---|---|---|
| 入门 | 42.64% | 62.21% |
| Interview 级 | 19.33% | 45.67% |
| 竞赛 | 3.67% | 14.67% |
| 总体 | 33.30% | 52.60% |
总体修复成功率从 33.3% 提到 52.6%, 是原来的 倍. 修复程序的仍然是 GPT-4, 变的只是反馈. 这和 Self-Refine 在数学推理上的结论一致: 诊断环节决定修复的上限.
环境观察和局部证据?不能执行的任务, 可以从环境里拿证据. Inner Monologue 和 DEPS 根据成功信号, 场景描述, 人类反馈和观察到的失败修改计划. Kestrel 和 Reflect-R1 在修改答案之前, 先检索相关的局部视觉或时间证据. 这类证据能暴露模型口头自我批评发现不了的错误. 可靠性仍取决于覆盖范围: 观察只覆盖访问过的状态, 检索只覆盖找到的资料. 一个早期就走错方向的轨迹, 在单条轨迹内往往改不回来. 这时 L0 方法就从修订单个候选, 转向同时保留多个候选.
3. 搜索与验证: 从采样, 树到 CodeT
3.1. Self-Consistency
Self-Consistency (Wang et al., 2022) 替换的是 CoT 提示里的贪心解码. 贪心解码只走一条推理路径. Self-Consistency 从模型里采样 条推理路径 , 每条路径给出一个最终答案 , 再对推理路径做边缘化, 取出现次数最多的答案:
这里 在括号内条件成立时取 1, 否则取 0. 求和统计的是有多少条路径得出答案 . 推理路径本身不参与比较, 只有最终答案参与投票, 这就是「对推理路径边缘化」的意思. 手算一个例子. 一道应用题采样 5 条路径, 最终答案依次是
按答案计数: 18 出现 3 次, 26 出现 1 次, 9 出现 1 次. 输出 . 如果贪心解码恰好走的是第 3 条路径, 输出就是 26. 这个方法依赖一个假设: 一道复杂推理题通常有多种思考方式, 但正确答案只有一个; 错误的推理路径各错各的, 不容易落到同一个错误答案上. 假设成立时, 正确答案会在投票中占多数. 论文在 PaLM-540B 上的结果 (算术推理, 准确率):
| 数据集 | CoT + 贪心 | Self-Consistency | 增益 |
|---|---|---|---|
| GSM8K | 56.5 | 74.4 | +17.9 |
| AQuA | 35.8 | 48.3 | +12.5 |
| SVAMP | 79.0 | 86.6 | +7.6 |
| ASDiv | 74.0 | 81.9 | +7.9 |
增益在基础较弱, 题目多步的数据集上更大. 小模型上增益较小: UL2-20B 在 GSM8K 上只从 4.1 到 7.3. 模型几乎答不对时, 投票里也没有多少正确答案可选.
3.2. Tree of Thoughts
Self-Consistency 采样的是完整路径, 中间步骤不做任何选择. Tree of Thoughts (Yao et al., 2023) 把推理拆成若干个「思维」(thought), 每个思维是一段连贯的文本, 作为解题的一个中间步骤. 推理过程变成在思维构成的树上搜索. 一个 ToT 系统要定四件事: 怎么把问题拆成思维步骤; 在每个节点上怎么生成候选的下一步; 怎么评估一个中间状态; 用什么搜索算法. 评估和生成都由同一个语言模型完成.
论文用 Game of 24 做主实验: 给 4 个数, 用加减乘除和括号, 每个数恰好用一次, 算出 24. 例如输入 4 9 10 13, 一个解是 . 这个任务被拆成 3 步, 每步用两个剩下的数做一次运算. 在每个节点上, 模型提出若干可能的下一步; 然后模型对每个候选状态给出 sure / maybe / impossible 三档评价, 判断从这个状态还能不能凑出 24. 评价的依据可以是几步前瞻, 也可以是「剩下的数太大或太小」这类常识. 每个候选评价采样 3 次. 搜索用广度优先, 每一步保留得分最高的 个状态. 测试集是 4nums.com 按人类解题时间排序后第 901–1000 号, 偏难的 100 题. GPT-4 的结果:
| 方法 | 成功率 |
|---|---|
| 直接输入输出 (IO) | 7.3% |
| CoT | 4.0% |
| CoT + Self-Consistency () | 9.0% |
| IO + 迭代修订 () | 27% |
| ToT, | 45% |
| ToT, | 74% |
| IO, 100 次取最好 | 33% |
| CoT, 100 次取最好 | 49% |
表里最终两行要单独读. 「100 次取最好」是指采样 100 次, 只要有一次对就算对. 这需要事先知道正确答案才能挑出那一次, 论文把它称为 oracle 设置. 即使给了这个条件, CoT 也只有 49%, 低于不知道答案的 ToT () 的 74%. CoT + Self-Consistency 只有 9.0%, 原因在任务结构. Game of 24 的第一步就决定了后面能不能凑出 24, 而 CoT 从左到右生成, 第一步选错了无法回退. 论文的错误分析显示, 约 60% 的 CoT 样本在生成第一步 (例如「4+9」这样的前三个词) 之后就已经不可能凑出 24. 投票只能在完整答案之间选, 多数路径在第一步就走进死路时, 投票也选不出正确答案. ToT 在每一步都评估, 把 impossible 的状态剪掉, 并保留多个 maybe 状态, 解决的正是这个问题.
ToT 的代价是调用次数. 每个节点要生成候选, 每个候选要评价 3 次, 广度 时每一步要处理更多节点. 论文把 ToT 在 到 时每题访问的节点数, 和 IO/CoT「 次取最好」的 放在同一张图里, 把一次采样算作访问一个节点. 在这张图上, CoT 取到 100 次也只有 49%, 低于 的 ToT. 但在比较任何搜索方法时, 都要先对齐调用预算, 这一点在第 5 节还会出现.
搜索的共同局限?综述把 beam search, RAP, Graph of Thoughts, rStar, LATS 也放在这一类. 它们改的是搜索拓扑和提议, 评估的分工. 共同的局限是: 投票和由模型给出的价值评估, 都可能放大候选之间共有的错误. 如果多数候选犯了同一个错, 投票会选中这个错; 如果评估者和生成者有同样的误解, 价值评估会给错误的中间状态打高分. 另一类方法决定把推理算力花在哪里. 快慢推理切换, 按难度分配 TestingTime 算力, CodeMonkeys 和 S* 在不确定的样本上, 或并行的「编辑, 测试」轨迹上分配计算. 这些方法的收益同样有条件: 预测的后果要准, 复用的结构要和任务匹配, 选择器要能认出有价值的候选.
3.3. CodeT 的双重执行一致性
用模型生成很多个程序以后, 要从中选一个. 最自然的办法是跑测试, 但大多数编程题没有现成的测试用例, 人工写测试成本很高. CodeT (Chen et al., 2022) 的做法是让同一个预训练模型既生成程序, 也生成测试用例, 再用执行结果做选择. 这立刻带来一个问题: 测试也是模型写的, 也可能写错. 一个程序没通过某个测试, 可能是程序错了, 也可能是测试错了. CodeT 用「双重执行一致性」(dual execution agreement) 处理这个问题.
候选代码与测试同时生成?把每个生成的程序 在每个生成的测试 上跑一遍. 程序 通过测试 , 就记一对 . 能通过同一组测试的程序被认为功能相同, 即使写法不同. 一个一致集 (consensus set) 由一组功能相同的程序 和它们都能通过的测试 组成. 一致集的得分是
是集合里的程序数, 是集合里的测试数. 得分等于集合里「程序, 测试」对的个数. 算法从得分最高的一致集里取一个程序作为输出. 论文的示例: 题目是「返回一个数的平方」. 一个一致集有程序 和测试 , 得分 ; 另一个一致集只有程序 , 但它通过了 四个测试, 得分 . 输出从第一个集合里取. 这个得分同时用了两种一致性. 大, 说明很多独立采样的程序实现了同一个功能, 这是 Self-Consistency 的思路. 大, 说明这个功能通过了很多测试. 论文附录做了消融: 只用 , 或只用 , 效果都不如两者相乘.
结果与局限?零样本设置下, code-davinci-002 加上 CodeT 的 pass@1:
| 基准 | 基线 | CodeT |
|---|---|---|
| HumanEval | 47.0% | 65.8% |
| MBPP | 58.1% | 67.7% |
| APPS 入门 | 27.2% | 34.6% |
| CodeContests | 0.7% | 2.1% |
CodeT 的测试和程序来自同一个模型. 如果模型对题意有系统性的误解, 它生成的程序和测试会按同一种误解彼此一致, 一致集的得分反而很高. 综述对执行类验证的结论是: 执行给出的行为关系是可检查的, 但受测试覆盖率限制; 当检查过程和候选共享同一个误解时, 一致性检查能排除不一致, 但证明不了正确.
综述同类列出的还有: MBR-EXEC 按采样到的行为给程序分组; LEVER 把执行结果和一个学习得到的验证器结合; RARR 和 Chain-of-Verification 用另外检索或另外问出的事实证据修改答案; CRITIC 把工具交互检查推广到搜索引擎和代码解释器. 没有可执行或有出处的检查时, 一些方法从模型自身的分布构造重建或一致性测试, 例如反向自验证. 它们能拒绝自相矛盾的答案, 但对和模型共享误解的错误无能为力.
4. 自我纠错为什么会让结果变差
Huang 等人的实验设置?Huang 等人 (2023, Google DeepMind) 把自我纠错分成两种条件. 有 oracle 标签时, 用正确答案决定什么时候停止纠错: 当前答案已经对了, 就不再改. 内在自我纠错 (intrinsic self-correction) 时, 不用任何标签, 由模型自己决定保留还是修改之前的答案. 他们选的数据集, 都是之前的工作报告过自我纠错有明显增益的: GSM8K, CommonSenseQA, HotpotQA. 每道题最多纠错两轮. 每一轮先让模型审查自己的答案, 再根据审查结果给出新答案, 所以第 轮结束时一共调用了 次模型.
4.1. 有标签和没有标签
有 oracle 标签时 (准确率, %):
| 模型 | 条件 | GSM8K | CommonSenseQA | HotpotQA |
|---|---|---|---|---|
| GPT-3.5 | 标准提示 | 75.9 | 75.8 | 26.0 |
| GPT-3.5 | 自我纠错 (oracle) | 84.3 | 89.7 | 29.0 |
| GPT-4 | 标准提示 | 95.5 | 82.0 | 49.0 |
| GPT-4 | 自我纠错 (oracle) | 97.5 | 85.5 | 59.0 |
没有标签时:
| 模型 | 条件 | 调用次数 | GSM8K | CommonSenseQA | HotpotQA |
|---|---|---|---|---|---|
| GPT-3.5 | 标准提示 | 1 | 75.9 | 75.8 | 26.0 |
| GPT-3.5 | 纠错第 1 轮 | 3 | 75.1 | 38.1 | 25.0 |
| GPT-3.5 | 纠错第 2 轮 | 5 | 74.7 | 41.8 | 25.0 |
| GPT-4 | 标准提示 | 1 | 95.5 | 82.0 | 49.0 |
| GPT-4 | 纠错第 1 轮 | 3 | 91.5 | 79.5 | 49.0 |
| GPT-4 | 纠错第 2 轮 | 5 | 89.0 | 80.0 | 43.0 |
两张表的模型, 提示, 数据都一样. 有标签时, 标签挡住了一种情况: 模型把原本正确的答案改错. 没有标签时这种情况不受限制, 准确率全部下降. GPT-3.5 在 CommonSenseQA 上从 75.8 掉到 38.1, 掉了一半. 论文还测了 GPT-4-Turbo 和 Llama-2-70b-chat, 并换了三种不同措辞的审查提示, 结论都一样: 没有标签时, 自我纠错一致地降低推理准确率. Llama-2 在 GSM8K 上从 62.0 降到 36.5.
论文分析了 GPT-3.5 在 GSM8K 上两轮纠错后答案的变化: 74.7% 的情况下答案没变; 在答案变了的情况里, 从对改成错的次数多于从错改成对. 论文的解释是, 模型判断不了自己推理的对错. 如果初始提示已经设计合理, 初稿相对于这个提示已经是模型能给出的最好回答; 审查提示相当于再加一段提示, 它没有提供关于题目的新信息, 反而可能把模型推离对原问题的最优回答.
4.2. 公平比较需要固定什么
自我纠错要多调用模型. 和它比较的基线也应该用同样多的调用次数. 论文用这个标准重新测了多智能体辩论 (多个模型副本互相批评对方的答案). 在 GSM8K 上, 用 gpt-3.5-turbo-0301, 3 个智能体:
| 方法 | 响应数 | 准确率 |
|---|---|---|
| 标准提示 | 1 | 76.7 |
| Self-Consistency | 3 | 82.5 |
| 辩论第 1 轮 | 6 | 83.2 |
| Self-Consistency | 6 | 85.3 |
| 辩论第 2 轮 | 9 | 83.0 |
| Self-Consistency | 9 | 88.2 |
响应数相同时, 辩论不如直接多采样再投票. 论文的判断是, 辩论带来的增益来自多次生成之间的一致性选择, 和 Self-Consistency 同源, 不能算作「纠错」.
初始提示也要固定?第三个问题出在提示设计上. Self-Refine 的约束生成任务要求一句话里用上 20–30 个给定概念. 原论文的初始提示没有明确要求用上全部概念, 改进出现在反馈环节: 反馈指出漏了哪些概念, 改写时补上. Huang 等人在初始提示里加了一句「写一段合理的话, 包含上面的全部概念」:
| 条件 | 调用次数 | 概念覆盖率 |
|---|---|---|
| 原论文: 标准提示 | 1 | 44.0 |
| 原论文: 自我纠错 | 7 | 67.0 |
| 改进后的标准提示 | 1 | 81.8 |
| 改进后的标准提示 + 自我纠错 | 7 | 75.1 |
把要求写进初始提示, 一次调用就达到 81.8, 超过原论文自我纠错 7 次调用后的 67.0. 在这个更好的初稿上再做自我纠错, 覆盖率反而降到 75.1.
这些实验怎样改变结论?三组实验对应三个评估错误: 用了推理时拿不到的标签; 没有对齐调用次数; 初始提示没把要求写全. 去掉这三个错误以后, 推理任务上的内在自我纠错没有增益, 还常常有害. 这不等于任务内的推理没用. Self-Consistency 和 ToT 的增益在对齐预算后仍然存在, 执行反馈和人写的反馈也确实提高了修复成功率. 能起作用的方法, 都带进了一份模型自己的判断以外的信息: 多次独立采样之间的一致性, 程序的执行结果, 人的诊断. 综述的说法是, 更多的推理不能代替那些能把「修好了」和「新引入了错误」区分开的证据.
5. 证据来源与 L0 的上限
5.1. 证据从哪来
把前面的方法按「谁提供证据」排成一张表:
| 方法 | 证据来源 | 能看到什么 | 看不到什么 |
|---|---|---|---|
| Self-Refine, 内在自我纠错 | 同一个模型的判断 | 风格, 格式, 明显遗漏 | 模型自己意识不到的错误 |
| 角色分离 (Table-Critic) | 同一模型的不同角色 | 错误位置更明确 | 各角色共有的盲区 |
| Self-Consistency, 辩论 | 多次独立采样的一致性 | 偶然性错误 | 多数路径共有的错误 |
| ToT 的状态评估 | 模型对中间状态的评价 | 明显走不通的分支 | 评价本身的误判 |
| CodeT | 模型写的测试的执行结果 | 程序与测试是否一致 | 程序与测试共有的误解 |
| SELF-DEBUGGING, Baldur | 执行器, 证明助手 | 测试或规格覆盖的行为 | 测试和规格没覆盖的部分 |
| 人写的反馈 | 人的诊断 | 模型看不出的错误 | 取决于人的投入 |
从上往下, 证据越来越独立于产生候选的那个模型. 这张表没有给方法排好坏, 因为证据的可用性取决于任务: 对话回复没有执行器, 数学证明没有现成的人工反馈. 在此基础上, 综述还给出了三条要求. 第一, 覆盖范围要事先声明. 执行只观察到测试过的行为, 检索只观察到找到的资料, 环境反馈只观察到访问过的状态, 固定的 rubric 只观察到写进去的标准. 一个检查对它覆盖之外的属性不提供证据.
第二, 停止规则要和证据源绑在一起. 同一个外部检查被反复调用, 每次失败都触发一次修改, 检查就从「审计」变成了「开发反馈」, 循环会逐渐贴合这个检查本身. 所以每个证据源都要配套停止, 放弃作答, 上交给人和预算对齐的规则. 第三, 比较的对象要选对. 应当比较的是: 同一个任务, 同样的预算, 同样的证据协议下, 被采纳的候选和改动前的候选. 拿到不同数量或不同种类反馈的两个系统之间的比较, 说明不了修订本身的作用. 第 5.2 节的辩论与初始提示对照, 都是这一条的具体例子.
5.2. 候选覆盖、选择准确率与结论边界
覆盖范围和停止规则都合格时, L0 的证据可以支持一个关于「这道题上被选中的输出」的结论. 它不能单独支持「这个 Agent 在之后的独立任务上会做得更好」, 因为按第 1 节的边界, 可保留状态 没有变. 这是 L0 和 L1 的分界. 一个系统如果把 L0 过程中筛选出来的好答案拿去训练模型, 改动就落到了 上, 并且会影响之后的任务. 这时有用的改动和错误都会被带进之后的任务. 2.2 讲的单模型自训练, 就是从这一步开始的: STaR 让模型对训练题生成推理过程, 用标准答案筛掉推错的, 再拿留下的推理过程微调模型. 筛选这一步和本篇的验证是同一个问题, 区别在于筛选结果被写进了参数.
候选覆盖和选择准确率?任务内搜索的端到端成功率可以拆成两部分. 令 表示候选集合中至少有一个正确答案, 表示系统最终选中正确答案, 则
生成器决定覆盖率 , 验证器决定条件选择率 . 最终 pass@1 上升时, 不拆这两项就无法知道增益来自多采样覆盖了正确轨迹, 还是验证器更会识别正确轨迹. oracle 选择器给出覆盖上限: 候选中只要有正确答案就选中. 将实际选择结果与 oracle 比较, 差距就是选择器尚未利用的空间. 若 oracle@k 随 快速上升、实际结果停滞, 继续增加样本只会制造更多选择负担; 应改验证. 若实际结果已经贴近 oracle, 瓶颈在生成分布.
候选之间通常相关. 假设单次正确率为 , 独立采样 次的覆盖率为 ; 语言模型从同一提示采样时会重复相似推理, 实际增长更慢. 提高温度或使用不同角色能增加多样性, 也可能降低单候选质量. 有效策略优化的是质量—多样性乘积, 不单独追求答案数量. 选择器也会随候选数退化. 当错误答案共享流畅叙述或相同最终值, 多数投票会把相关错误放大. 判官面对大量近似候选时, 细微逻辑差异更难识别. 因而应同时画 oracle@k、实际 select@k 与成本曲线, 找到边际收益转负的位置.
Self-Consistency 的主要贡献通常落在覆盖与聚合. 它从同一模型采样多条推理, 按最终答案多数投票. 若正确推理有多种表述、错误答案较分散, 投票有效; 若错误来自共同误解并集中到同一答案, 投票会稳定选择错误. 最终答案一致性无法检查推理过程是否正确. CodeT 增加执行一致性, 把程序与生成测试形成的通过关系用于分组. 它提供了与语言表面不同的证据, 但生成测试仍来自模型, 可能遗漏所有候选共享的漏洞. 双重执行一致性提高选择率, 不会让候选集合中凭空出现正确程序; 生成与选择两项仍需分别报告.
自我反馈的贝叶斯视角?把初稿正确性记作隐变量 , 模型产生反馈 . 有用反馈应改变后验 , 并给出能提高修订成功率的方向. 反馈写得长、列出很多问题, 不代表它含有关于 的信息. 若模型在正确答案上也经常生成批评, 假阳性率 较高, 修订会破坏正确答案. 若模型对错误答案经常说没有问题, 假阴性率高, 修订不启动. 强基座正确率 已经很高时, 即使反馈器表面准确, 假阳性造成的损失也可能超过修复收益.
设错误答案被修对概率为 , 正确答案被改错概率为 , 初稿准确率为 , 一轮后
净收益条件为 . 当 接近 1, 左边可修复样本变少, 右边暴露的正确样本仍多. 这解释了 Huang 等人在强模型上观察到的退化, 也说明停止门控比「多想一轮」更关键. 标准答案门控能将 压低, 因为只有已知错误时才修订. 但它引入了推理时 oracle, 实验问题变成「知道答案错以后能否修复」. 部署时没有 oracle, 需要可获得的外部信号, 如程序执行、约束检查、检索证据或校准过的验证器.
模型置信度可以作为门控, 前提是经过校准. 语言模型口头说「我有 90% 把握」常受措辞和提示影响. 更可靠的做法是在留出集上估计风险—覆盖曲线: 只对低置信样本启动修订, 比较被覆盖部分的修复率与破坏率. 阈值随任务类型变化, 统一阈值可能在数学题有效、开放问答失效. 反馈还要区分诊断与修改建议. 「第三步符号错误」可以定位问题, 「把答案改成 42」直接提供候选. 前者需要修订器具备修复能力, 后者可能只是另一次答案采样. 消融时分别提供错误位置、错误类型和完整建议, 才能知道收益来自验证信息还是额外生成.
6. 搜索系统的验证与停止
6.1. 验证器与停止策略
Tree of Thoughts 把中间思维当作状态, 生成若干后继并用价值函数剪枝. 设真实可达成功概率为 , 评估器给出 . 搜索效果取决于排序误差, 尤其是早期剪枝是否误删通向正确答案的分支. 束宽 增大能降低误删概率, 成本按深度迅速增长. 若每层扩展 个后继, 无剪枝节点数为 ; 束搜索控制为约 , 代价是评估器一次错误可能永久丢掉正确路径. 回溯和保留多样分支能缓解, 需要更多预算.
价值评估与生成器共享模型时, 错误相关. 模型生成一条符合自身偏好的错误思路, 又容易给它高分. 换独立判官可能降低相关性, 但判官若来自相似训练数据仍会共享盲点. 程序执行、状态约束和环境反馈提供异质证据, 能在适用任务上切断共同偏差. 搜索树的「状态」常只是一段自然语言, 不满足真正 Markov 性. 两段看似相同的思路可能隐含不同未写信息, 价值函数难以准确预测后续; 冗长状态又占用上下文并增加噪声. 让状态包含可验证中间量, 如方程、程序变量或环境观察, 能提高评估可辨识性.
树搜索结果超过直接采样时, 还要对齐调用数. 同样总 token 下, 深搜一条路径、广采多条完整答案和自一致性投票各有不同覆盖. 若 Tree of Thoughts 使用更多模型调用和工具反馈, 增益不能全归到树结构. 性能—成本曲线比单个最高分更有信息. 搜索不会自动带来学习. 整棵树在任务结束后丢弃, 仍是 L0 的 TestingTime 计算. 将成功路径蒸馏进参数进入 L1, 将搜索启发写成跨任务技能进入 L2, 修改以后怎样搜索的更新器才触及 L3. 计算深度与演化深度是两条轴.
外部验证器的有效域?程序执行器能确定代码是否运行、输出是否满足测试, 无法判断测试没有表达的需求. 数学符号工具能核对等式, 无法自动确认建模假设. 检索能提供来源, 来源本身可能过时或不适用. 外部验证器强在其有效域内提供与模型不同的证据. 把目标性质写成 , 验证器检查近似性质 . 若 能可靠推出 , 验证器精度高; 若 时容易得到 , 召回高. 单元测试往往精度较高、召回有限: 通过的实现大概率满足已测行为, 正确实现也可能因环境问题失败.
验证器被反复查询后会成为优化目标. 候选可以硬编码测试、删除日志标记、捕获异常或利用计时误差. 隐藏实现只能增加利用难度, 候选若能影响验证器输入通道, 仍可能绕过. 独立采集日志、随机生成测试和限制查询次数能减轻. 验证器组合采用分层逻辑. 语法检查先淘汰无效候选, 单元测试检查局部功能, 属性测试覆盖不变量, 隐藏集测泛化, 人工审查处理规格歧义. 前级便宜高召回, 后级昂贵高精度. 全部压成一个总分会让强项抵消硬失败.
执行反馈还有诊断价值. 只返回通过/失败, 泄漏少但修复效率低; 返回具体堆栈和失败输入, 帮助定位也让候选更容易拟合测试. 开发阶段可以提供详细反馈, 最终审计使用新的隐藏测试与有限反馈, 分开优化与确认角色. 外部验证不意味着绝对正确. 运行环境、数值精度、随机性和依赖版本都会影响结果. 保存环境镜像、重复运行和对照已知实现, 才能区分候选错误与验证基础设施故障. 遇到证据冲突时, 先检查各自有效域与环境.
停止策略决定修订会不会过头?迭代修订需要回答何时停. 固定轮数简单, 却会让已经正确的答案继续暴露在破坏风险下; 依赖模型自评停止, 又把最困难的正确性判断交回同一个模型. 理想停止器比较下一轮的预期收益与成本. 令当前答案正确概率为 , 再修订一轮将错误修对的概率为 , 将正确改错的概率为 , 调用成本为 . 期望净收益近似为
只有 才值得继续. 强模型或后期轮次的 较高, 修复空间缩小, 即使不大也会让净收益转负. 现实系统不知道 , 可以在留出集上按任务类型和反馈信号估计. 程序测试失败时 很低, 继续修复通常合理; 所有测试通过但模型口头犹豫时, 外部证据应压过自评. 对开放任务, 多个低相关验证器一致指出具体错误, 比一句笼统「还可以改进」更适合作为继续条件.
停止规则要与返回规则配套. Self-Refine 常返回最终一轮, 即使中间版本更好也会丢失. 保存每轮候选, 由独立验证器选最佳, 可以避免单调性假设; 选择器若不可靠, 候选变多又增加选择偏差. 另一种策略是只在外部指标明确改善时提交新版本, 否则保留在任答案. 循环检测也很重要. 修订可能在两个答案之间来回切换, 或不断改写措辞而语义不变. 对规范化答案、程序 AST 或执行行为计算相似度, 检测周期与无效变化, 可以提前停止. 这类停止信号不判断答案正确, 只判断继续迭代缺少新信息.
停止本身属于 L0 控制逻辑. 如果系统从多次任务中学到新的停止策略并跨任务保留, 变化落在脚手架 ; 如果它学会修改以后怎样优化停止策略, 才进入改进器 . 单次任务中动态决定轮数不会自动提升演化层级.
验证器要同时校准分数和排序?验证器有两个用途: 判断单个候选是否可信, 以及在多个候选间排序. 校准关注分数语义, 排序关注相对次序. 一个判官可能把所有概率报得过高, 排序仍然好; 也可能总体准确率高, 在顶部候选间无法区分. 候选选择最关心 top-k 区域. 自然样本上的 AUC 很高, 不代表从一百个高分候选中选冠军可靠. 搜索会把候选集中到判官决策边界与漏洞区域, 应在经过优化的候选分布上测 precision@k、pairwise accuracy 和 regret.
选择 regret 定义为 oracle 最佳真实效用与被选候选真实效用之差:
它同时反映判官是否把关键排序弄错和错误代价有多大. 两个判官 pairwise accuracy 相同, 一个只错在近似等价候选, 另一个把最好选成最差, regret 完全不同. 校准允许风险控制. 在留出集上估计「判官分数至少 」的真实错误率, 选择满足目标风险的阈值. 候选分布随模型、提示和搜索方法变化后, 旧校准可能失效, 需要重测. 判官被搜索器反复利用时, 高分区的实际错误率往往上升. 评判解释可以辅助诊断, 不能当作正确性的独立证据. 模型能为错误分数生成连贯理由, 理由与分数来自同一内部状态. 将理由转成可执行检查、引用定位或明确反例, 再由外部工具验证, 才增加新信息.
参考文献
- Kaiqi Wang, Wenjin Hou, Yuchen Yan 等 (2026). Diving into Reliable Self-Evolving Agents: A Survey. §3 Output-Level Self-Evolution, 式 (6), 表 3.
- Aman Madaan, Niket Tandon, Prakhar Gupta 等 (2023). Self-Refine: Iterative Refinement with Self-Feedback. NeurIPS 2023. 式 (1)–(4), 表 1, 表 2, 图 4, 附录 H.
- Jie Huang, Xinyun Chen, Swaroop Mishra 等 (2023). Large Language Models Cannot Self-Correct Reasoning Yet. ICLR 2024. 表 2–8, 图 1.
- Theo X. Olausson, Jeevana Priya Inala, Chenglong Wang, Jianfeng Gao, Armando Solar-Lezama (2023). Is Self-Repair a Silver Bullet for Code Generation?. ICLR 2024. 表 1.
- Xuezhi Wang, Jason Wei, Dale Schuurmans 等 (2022). Self-Consistency Improves Chain of Thought Reasoning in Language Models. ICLR 2023. 表 2.
- Shunyu Yao, Dian Yu, Jeffrey Zhao 等 (2023). Tree of Thoughts: Deliberate Problem Solving with Large Language Models. NeurIPS 2023. §4.1, 表 2.
- Bei Chen, Fengji Zhang, Anh Nguyen 等 (2022). CodeT: Code Generation with Generated Tests. ICLR 2023. §2, 附录 I.
上一篇: 1.1.3 · 证据, 接受与控制
下一篇: 2.1.2 · L1: 单模型自训练