---
title: 推理计算、候选与验证
url: https://doc.liz6.com/ai/01-model-foundations/04-reasoning-and-verification
locale: zh
area: ai
tags:
- 大模型与 Agent
- 模型基础
date: 2026-06-30
modified: 2026-09-10
description: 增加推理投入可能产生更多候选，也可能只重复同一种错误。本文先区分训练、单次生成和应用验证，再推导“候选中有正确答案”与“最终选中正确答案”的差别，最后讨论计算预算怎样用任务结果来衡量。
---

# 推理计算、候选与验证

增加推理投入可能产生更多候选，也可能只重复同一种错误。本文先区分训练、单次生成和应用验证，再推导“候选中有正确答案”与“最终选中正确答案”的差别，最后讨论计算预算怎样用任务结果来衡量。

## 训练与推理阶段的计算

训练调整模型参数；推理在给定参数和输入下产生输出。增加推理计算可以表现为生成中间步骤、尝试多个候选、调用工具获取新信息，或根据反馈修订。它不会自动更新模型权重，也不会凭空补出本来没有的外部事实。

Chain-of-Thought prompting 的经典做法是在提示中给出包含中间步骤的示范，让模型按类似形式解决新问题。原始论文在特定模型和算术、常识、符号任务中观察到提升；它不是“只要说逐步思考就适用于任何任务”的定律。[Chain-of-Thought Prompting](https://arxiv.org/abs/2201.11903)

推理模型通常还通过专门训练提高利用推理阶段计算的能力。API 中的 thinking 则是产品提供的推理控制与返回结构，两者不是同一个层次：提示可以要求输出解题过程，但不能由此推断模型内部采用了什么训练方法、花了多少隐藏计算，或者执行了真正的外部检查。

| 层次 | 改变的对象 | 例子 |
|---|---|---|
| 训练 | 参数和行为倾向 | 学习分解、修订、使用反馈 |
| 单次生成 | 本轮计算过程与输出 | 在回答前处理更多中间步骤 |
| 应用编排 | 多次生成及工具调用的组织 | 生成补丁、运行测试、按失败修正 |
| 展示 | 用户看到的内容 | 简短结论、解题说明、进度摘要 |

## 把额外计算用在候选与验证上

### 分解让中间结果可以检查

计算 27×453，可以拆成 20×453=9060 与 7×453=3171，再相加得到 12231。换一种分解是 453×(30−3)=13590−1359=12231。两种计算能互相核对，但如果都由同一个系统错误地执行，仍可能共同出错。需要更强的计算保证时，可使用确定性的算术工具。

这个例子只是人可检查的解题说明，不是对某个模型内部过程的记录。它显示了分解的作用：每一步都有输入、操作和可核验的输出；相比“我认真检查过”，这些中间产物更容易发现错误。

### 多个候选只有在选择有效时才有价值

self-consistency 通过采样多条解题路径，再聚合最终答案；其研究在若干推理基准上观察到增益。[Self-Consistency](https://arxiv.org/abs/2203.11171) 如果多个候选都依赖同一条错误事实，投票却可能更自信地选错。

即使**假设**每次尝试独立、成功概率都是 0.6，三次中至少一次成功的概率是 1−0.4³=0.936，也不能把最终成功率直接写成 93.6%。这个数字只表示候选中存在正确答案的概率，应用还需要识别它；而真实模型重复生成通常不满足独立错误假设。

### 外部反馈把搜索变成可验证的改进

<svg viewBox="0 0 760 361.6076965332031" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="额外计算的价值：提出候选之后获得可检查的反馈" style="max-width:100%;height:auto" font-family="Source Han Sans CN,Microsoft YaHei,sans-serif">
<defs><marker id="reasoning-verification-arrow" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto"><path d="M0,0 L8,4 L0,8 Z" fill="#64748b"></path></marker></defs>
<rect width="760" height="361.6076965332031" rx="12" fill="#f8fafc"></rect>


<g transform="translate(0 0)"><rect x="30" y="90" width="200" height="82" rx="8" fill="#e0e7ff" stroke="#c7d2fe"></rect><text x="130.0" y="128.0" font-size="15" fill="#1e293b" text-anchor="middle" font-weight="600">提出候选方案</text><text x="130.0" y="150.0" font-size="12" fill="#475569" text-anchor="middle" font-weight="400">模型生成或多次采样</text><line x1="230" y1="131" x2="275" y2="131" stroke="#64748b" stroke-width="1.8" marker-end="url(#reasoning-verification-arrow)"></line><rect x="280" y="90" width="200" height="82" rx="8" fill="#e0e7ff" stroke="#c7d2fe"></rect><text x="380.0" y="128.0" font-size="15" fill="#1e293b" text-anchor="middle" font-weight="600">执行验证</text><text x="380.0" y="150.0" font-size="12" fill="#475569" text-anchor="middle" font-weight="400">计算、测试、检索证据</text><line x1="480" y1="131" x2="525" y2="131" stroke="#64748b" stroke-width="1.8" marker-end="url(#reasoning-verification-arrow)"></line><rect x="530" y="90" width="200" height="82" rx="8" fill="#e0e7ff" stroke="#c7d2fe"></rect><text x="630.0" y="128.0" font-size="15" fill="#1e293b" text-anchor="middle" font-weight="600">判断任务结果</text><text x="630.0" y="150.0" font-size="12" fill="#475569" text-anchor="middle" font-weight="400">依据反馈接受或修订</text><line x1="630" y1="177" x2="630" y2="255" stroke="#64748b" stroke-width="1.8" marker-end="url(#reasoning-verification-arrow)"></line><line x1="630" y1="255" x2="130" y2="255" stroke="#64748b" stroke-width="1.8" marker-end="url(#reasoning-verification-arrow)"></line><line x1="130" y1="255" x2="130" y2="177" stroke="#64748b" stroke-width="1.8" marker-end="url(#reasoning-verification-arrow)"></line><text x="380" y="241" font-size="14" fill="#334155" text-anchor="middle" font-weight="400">失败时带具体反例回到方案阶段；受任务预算约束</text><text x="28" y="336" font-size="13" fill="#475569" text-anchor="start" font-weight="400">图示是应用可以实现的验证循环，不是对模型内部思维链的观察记录。</text></g><text x="24" y="29" font-size="19" fill="#0f172a" text-anchor="start" font-weight="700"><tspan x="24" dy="0">额外计算的价值：提出候选之后获得可检查的反馈</tspan></text>
</svg>

以修复排序函数为例，候选 A 通过普通正数样例，却在含重复元素时破坏稳定顺序。把这个失败输入和预期结果提供给模型，比只要求“再仔细检查”提供了更明确的修订信号。候选 B 通过该例后，还要在其他未用于修订的用例上检查，避免只针对反例打补丁。

验证器本身也有边界：单元测试只覆盖测试条件；另一个模型打分也会有偏差；多数票需要可比较的答案格式。推理计算如何分配，取决于任务难度、候选质量和验证器能力，不能只按输出 token 数线性放大收益。[Scaling LLM Test-Time Compute Optimally](https://arxiv.org/abs/2408.03314)

### 有正确候选，为什么仍选错？

把 93.6% 看成正确候选可用性的上限，再乘上明确条件下的识别率 q。q 并非通用的裁判准确率；它只定义在候选集合确实含正确解的情况。切换共同错误的极端对照，观察独立假设对结论的影响。

$$
P(\text{final correct})=\bigl[1-(1-p)^n\bigr]q
$$

**有正确候选，为什么仍选错？**

至少一个正确候选的概率是 1−(1−p)ⁿ；只有选择器能找出它，才成为最终成功。


## 可见解释、内部计算与执行证据

| 看到的内容 | 可以说明什么 | 不能据此确认什么 |
|---|---|---|
| 一段解题说明 | 模型给出的论证与假设 | 它忠实记录了全部内部过程 |
| thinking 摘要 | 服务允许展示的过程概述 | 摘要长度等于实际推理开销 |
| “已经运行测试”文字 | 模型声称做过该操作 | 工具实际执行并成功 |
| 关联到此次运行的测试产物 | 对应版本、命令和结果 | 未覆盖情形也一定正确 |

对 Claude，当前 thinking 文档说明可见 thinking 文本是摘要，省略展示时仍可能存在需要续传的结构化块。服务中的内部推理计费也不能通过数可见摘要字数还原；这些是该接口的语义，不应推广为所有开放模型都不返回过程文本。[Claude Thinking](https://platform.claude.com/docs/en/build-with-claude/thinking)

应用应分别保存用于协议续话的原始响应结构、可展示文本，以及实际工具执行记录。不要从摘要重新构造签名或其他不透明字段；工具循环中的回传要求、历史块保留策略应遵守当前模型文档。一次响应可能包含 thinking、文本和工具调用，不能只取第一段文字就宣布整轮任务完成。

前端若需要展示进度，可以显示真实的请求状态和已经发生的工具事件；thinking 摘要可作为辅助，但不应把“计划运行测试”展示成“测试通过”。没有文字流出也不单独证明卡死，需要结合请求状态、超时和连接事件判断。

## 三类预算控制

### effort 是行为倾向，不是硬计数器

以 Claude 的 `output_config.effort` 为例，它调整响应时的计算与 token 使用倾向，可能影响 thinking、工具调用和解释。支持的档位以及各档位的效果依模型而异；不能把 high 解释成固定生成多少 token，也不能假定降低 effort 一定缩短可见答案。[Claude Effort](https://platform.claude.com/docs/en/build-with-claude/effort)

temperature 改变候选概率分布，effort 改变推理投入，用户要求的篇幅则约束最终展示目标。需要“两句话回答”时应直接表达篇幅要求；需要严谨证明时应提供命题、条件与验证标准，而不是用温度替代。采样机制见 [Token 与采样](/ai/01-model-foundations/01-tokens-and-sampling.md)。

### 单次输出限制与跨请求预算

| 控制 | 作用范围 | 达到边界时怎么处理 |
|---|---|---|
| effort 或推理档位 | 本轮行为倾向 | 仍需统计实际消耗 |
| `max_tokens` 等输出上限 | 单次响应，计数按接口定义 | 检查截断与停止原因 |
| task budget 等模型可见预算 | 让模型经营一段任务 | 不把自我节制当强制终止保证 |
| 应用执行上限 | 整个任务的请求、工具与资源 | 调度器停止新动作并保存状态 |

Claude task budget 是给模型的任务级预算信号，计数与客户端重复发送历史、账单 usage 并不完全相同；它不能直接替代财务账或应用硬限制。[Task budgets](https://platform.claude.com/docs/en/build-with-claude/task-budgets)

例如，应用只允许本任务进行 12 次工具调用，并有 120 秒总时限。这个规则要由执行器检查，不能只写进 prompt 后假设一定遵守。每次准备执行工具时，核验剩余调用次数和截止时间；预算耗尽后保留结果、未完成项与恢复位置。取消请求也不意味着已经发出的外部操作自动回滚，必须按工具自身语义确认结果。

### API 配置要区分模型代际

Claude 的手动 `budget_tokens` 与 adaptive thinking 有各自支持范围；当前文档将手动模式列为旧模式，并提供迁移说明。不要把“某代模型拒绝手动配置”推广成所有模型的通则，也不要为了统一配置而给每个端点发送它不支持的字段。[Extended thinking](https://platform.claude.com/docs/en/build-with-claude/extended-thinking)

配置适配层应明确目标模型、支持模式和输出限制，再构造请求；将不支持参数导致的 400 与模型任务失败分开统计。理论文章保留控制含义，接入代码的字段、默认值和兼容表以目标模型的当前文档为准。

## 用任务成功率计算收益

### 同一组任务，比较完整运行

固定任务集、输入材料、工具权限、验证规则与超时，然后只改变推理档位或候选策略。分类和抽取需要看标签正确率与格式；代码任务需要看真实测试；长 Agent 任务则要看最终目标是否完成，不能只看每一轮文字是否像在推进。

下面是假设的 100 道任务结果。每次运行消耗已经包含本次策略中的失败尝试和验证；为便于演算，将全部成本统一成虚构的成本单位。

| 配置 | 总成功数 | 总成本 | 每次成功分摊成本 |
|---|---:|---:|---:|
| A：较少计算 | 70 | 100 | 100/70≈1.43 |
| B：更多计算 | 80 | 200 | 200/80=2.50 |

B 的成功率提高 10 个百分点，但每次成功分摊成本也提高了。额外 100 成本换来 10 个额外成功，边际成本为 10。是否值得取决于任务价值、质量门槛和延迟约束；不能只凭“多成功了”或“多花 token 了”作结论。

```python
from fractions import Fraction

runs = {"A": (70, 100), "B": (80, 200)}
for name, (successes, cost) in runs.items():
    print(name, "每次成功分摊成本", round(float(Fraction(cost, successes)), 2))
assert Fraction(200 - 100, 80 - 70) == 10
# A 每次成功分摊成本 1.43
# B 每次成功分摊成本 2.5
```

真实比较还应记录 p50/p95 延迟、超时率、重试和工具费用。若新策略用了不同输入或不同模型，不能把变化全部归因于 effort。样本少时保留逐题配对结果，并重复测量有随机性的任务，避免用一次运行的小波动定档。

### 根据失败原因调整计算，而非一律拉满

| 失败原因 | 先处理什么 | 增加推理投入是否直接有效 |
|---|---|---|
| 缺少必要事实 | 检索或读取可信材料 | 无法凭空补证据 |
| 理解了条件但多步处理出错 | 分解、反例、验证反馈 | 可能有效，需评估 |
| 工具参数格式无效 | schema、模板与解析器 | 不一定 |
| 循环重复已失败的动作 | 保存状态、去重、终止条件 | 可能反而延长循环 |
| 答案正确但返回很慢 | 减少无收益探索，比较较低档位 | 观察正确率是否保持 |

完整观测应连接请求、工具、产物和任务级结果，详见 [评估与可观测](/ai/04-evaluation-and-production/01-evaluation-and-observability.md)。推理预算是这个循环中的一个控制点；能否把模型建议变成受控行动，继续看 [Agent 循环与工具使用](/ai/03-agent-systems/01-agent-loop.md)。

继续阅读：[提示与输出契约](/ai/02-context-and-interfaces/01-prompt-and-output-contracts)。
