Test-time Compute 中文常译成「推理时计算」或「测试时计算」,也叫 inference-time scaling、推理侧扩展。它是一个统称,指的是在模型回答问题的那一刻多投入算力和时间,用来换更好的结果。
关键在于:这些方法不改动模型参数、也不重新训练。同一个模型,让它多想一会儿、多试几条路、答完自己检查一遍,准确率就会上去。
先用一句话抓住它
Test-time Compute 是在提问的这一刻多花算力换准确率,而不是靠训练更大的模型。
生活里的类比是问小孩一道难题。你说「快点答」,他脱口而出一个数;你说「不急,把过程写出来」,他会打草稿、算完再核一遍,通常就对了。孩子的知识量没变,变的是这次思考投入的时间。
为什么会出现这个词
过去几年提升模型能力的主要办法是把训练规模做大:更多参数、更多数据、更多训练算力。这条路成本高、周期长,而且边际收益在收窄。人们发现另一条路同样有效——训练不动,但在回答时多花算力。
这条路径在推理模型(reasoning model)上被系统化了:模型把「思考 token」和「输出 token」明确分开,并通过强化学习去调节思考的长度和方式。DeepSeek R1 是常被引用的例子,它用最终答案是否正确作为奖励,让推理过程作为一种隐式搜索被训练出来。
需要注意训练和推理这两侧是耦合的:既然推理成本随回答长度增长,那些鼓励模型长思考的训练方法,本质上就把推理时计算写进了模型习惯里。
flowchart TB
Q["问题"] --> Easy{"难不难?"}
Easy -->|简单| Short["短思考<br/>直接作答"]
Easy -->|难| Long["长思考"]
Long --> Multi["采样多条推理路径"]
Multi --> Pick["投票 / 验证器挑选"]
Pick --> Check["自我检查与修正"]
Check --> Ans["答案"]
Short --> Ans它通常包含什么
常见做法可以归成几类。更长的思维链:先生成中间推理步骤,再给最终答案。采样与聚合:对同一个问题生成多条推理路径,再用自洽投票、重排序、验证器打分等方式挑一条,规模上可以从几条到上千条。显式搜索:蒙特卡洛树搜索或树状遍历,配合结果奖励模型或过程奖励模型,支持前瞻和回溯。
迭代改写:自我批评、按上一轮失败信息重试,在推理空间里回退再走。工具使用:调用计算器、定理证明器、代码执行或搜索来核对子问题,把静态推理变成可以外部验证的混合系统。还有一类是隐空间的循环深度:不多产出 token,而是在潜在表示上反复迭代一个循环块,像 RNN 的隐状态那样精炼推理。
和训练时扩展的区别
训练时扩展改变的是模型本身:参数更多、见过的数据更多,能力上限被抬高,成本一次性付在训练阶段。推理时扩展不动模型,成本按每次请求付,可以按问题难度动态分配。
有一个常被引用的等价关系:在推理任务上,一个 7B 模型配合数十倍的推理 token,可以逼近一个 70B 模型直接作答的表现。这带来的部署含义很实际——可以部署更小的推理模型,然后按每个请求的难度分配算力,简单问题走短链、难题走长链,平均成本反而低于永远调用大模型。
但要注意准确率和推理算力大致是对数关系,也就是边际递减:算力翻倍带来的提升会越来越小,所以训练侧和推理侧之间存在一个最优分配点,不是一味加长就好。
和推理模型、上下文窗口的关系
推理模型是把这套机制内化到模型里的产物:它默认会先思考再回答,思考长度由训练时的强化学习调节。你在 API 里看到的「思考预算」「推理力度」这类参数,调的就是这一层。
推理时计算也会挤占上下文窗口:思考 token 同样占额度,长思考会让可用于对话历史和资料的空间变少,这也是为什么上下文压缩和推理模型经常一起被讨论。
容易误解的地方
第一个误解是把「思考更久」当成万能。它对有明确验证信号的任务(数学、代码、逻辑推理)效果最好,因为多试几条路之后能判断哪条对;对开放式写作、主观判断这类没有客观检验标准的任务,多想不一定更好,有时还会绕远。
第二个误解是忽略延迟和成本。这本质上是一次交易:拿速度和费用换质量。值不值取决于任务——用户等着看结果的交互场景和跑在后台的批量任务,愿意付的等待完全不同。
第三个误解是以为思考过程等于真实推理。模型输出的中间步骤是生成出来的文本,不一定忠实反映它内部的计算,把它当解释来看要谨慎。
怎么判断它该不该用
先看任务有没有可验证的对错。有——数学题、代码、结构化抽取、需要多步推导的分析,那么加大推理投入通常直接见效。没有客观标准的任务,先试试更清楚的提示词和更好的上下文,往往比让模型多想更划算。
再看约束。对延迟敏感的场景(对话、补全、实时接口)要谨慎;离线批处理、报告生成、代码修复这类可以慢的场景则很适合。实际做法上,比较稳的是分档:先用普通模式跑,检测到失败或低置信时再升级到长思考重跑一次,而不是所有请求都开满。