
如果你和我一样经常被大模型“看起来什么都懂一到复杂问题就掉链子”折磨过那这篇文章应该能帮到你。这里说的不是微调也不是换更大参数的模型而是推理时计算inference-time compute——简单讲就是在模型生成答案的时候多花一些算力和时间让它“多想几步”“多验证几遍”。我最早接触这个概念是因为用同一套提示词、同一个模型在数学逻辑题上怎么都提升不了准确率。后来试着把单次回答改成多次采样、拆分步骤、树状搜索效果直接上了一个台阶。从最基础的思维链Chain-of-ThoughtCoT到自洽性采样Self-ConsistencyCoT-SC再到思维树Tree-of-ThoughtsToT这是一条很有意思的技术演进路线也基本覆盖了当前推理时计算的常用手段。这篇文章我会从“为什么推理时计算有用”讲起把CoT、CoT-SC、ToT的原理、提示词样例、搜索策略、实现思路和踩坑经验都整理出来。适合正在做LLM应用开发、评估选型、RAG项目优化的开发者也适合刚接触提示工程但想往深处走的玩家。我会尽量把话说得直白一点把可以复现的操作细节给足。1. 推理时计算模型“想得久”为什么真的有用1.1 什么是推理时计算推理时计算也叫测试时计算test-time compute或解码时扩展inference-time scaling。早期我们对LLM的性能提升默认走“预训练时拼命堆参数和数据”这条路模型训完就固定了上线调用时只做一次前向传播生成一个答案就完事。推理时计算要改变的是这个“一次前向传播”的假设允许模型在推理阶段多次采样、生成多个中间步骤、自评自纠甚至用搜索算法在多个候选推理路径中选最优。换句话说训练时提升模型“底子”推理时提升模型“临场发挥”。一个很贴切的类比是考试。模型本身相当于一个考生预训练和后训练决定了它的知识储备而推理时计算等于要求考生“先把草稿写到草稿纸上再检查几遍甚至列出不同解法对比一下”。这当然会花更长时间但正确率实实在在地提高。1.2 为什么最近才火起来Scaling Law的接力棒你可以把“堆算力提升模型能力”这件事分成三段预训练阶段、后训练阶段RLHF、SFT等、推理阶段。前两段的算力投入已经很大边际收益开始变缓而推理阶段的扩展性才刚刚被人认真挖掘。我个人的观察是真正让“推理时计算”破圈的是带显式思考过程的模型系列出现。这类模型在回答数学、代码、逻辑类问题时会先输出大段内部推理再做总结效果远超直接问答。受此启发开源社区和学术界重新审视了“让模型思考更久”这个朴素思路发现它不仅适用于专门训练过的模型对普通指令模型也有明显收益。对应用开发者来说这其实是低成本提效的思路不需要重新训练模型只需要在调用策略上做文章就能把同一个模型的推理上限再往上顶一截。后面的内容都是围绕“怎么设计这个调用策略”展开的。2. 从CoT到CoT-SC让模型把思维过程“说出来”2.1 CoT的原理与提示词设计思维链Chain-of-Thought最早的核心是让模型在给出最终答案之前先输出中间推理过程。理论上自回归模型本身就是一步步生成token的但它不会默认就把“草稿”铺开。CoT要做的是把推理轨迹显式化让模型沿着“先理解、再分步计算、最后归纳答案”的顺序走完。CoT的实现方式有两种。一种是零样本CoT就是在提示词末尾加一句“请一步步思考最后给出答案”。实测下来零样本CoT在简单问题上有效但遇到多步推理时模型容易编造步骤中间任何一步错最终答案就跟着错。更稳妥的是少样本CoT也就是在提示词里给出1到3个包含完整推理过程的示例。比如问题小明有5个苹果给了小红2个又从水果店买了3个现在有几个 思考过程小明原有5个。给小红2个剩3个。又买3个3加3等于6。所以现在是6个。 最终答案6 问题一个矩形的长是8厘米宽是3厘米面积是多少 思考过程矩形面积等于长乘以宽。8乘以3等于24。所以面积是24平方厘米。 最终答案24这里有个关键点示例的推理过程必须真实、逐步、可验证而不是把答案复述一遍。模型学的是“结构的形态”不是“题目的答案”。我见过不少人在示例里只写“答案是6”那和直接告诉模型“遇到这类题输出6”没有区别泛化能力极差。2.2 解码参数与CoT的配合很多人以为CoT就是提示词的事改一改prompt就行。实际上解码参数不配合CoT的效果会大打折扣。做推理任务时我不会把temperature设得太低。temperature很低比如0.1时模型会走一条最“贪心”的路径思路容易固化temperature到0.7左右模型有更多空间生成不同的推导方式。但要小心太高比如1.2以上会引入大量无关内容。我的常用范围是0.6到0.9。max_tokens也要留意。模型生成完整推理轨迹非常吃长度如果max_tokens设得太小推理写到一半被截断最终答案会缺失。我一般会根据任务复杂度估算简单应用题给512复杂数学或代码题给1024或更多。另外如果你使用的是API建议在请求参数里打开“流式输出”或设置较长的超时时间。CoT路径长非流式接口容易出现等待时间超时重试重试会导致成本翻倍。2.3 CoT-SC多条推理路径投票Single Path CoT的问题在于模型一次只能选择一条推理链。一旦某条链中途有一步错了没有机会修正。Self-Consistency自洽性的思路是同一个问题让模型采样生成多个不同的CoT推理路径每个路径得出一个答案最后对答案做多数投票或按语义相似度聚合。CoT-SC为什么有效它本质上是把“一个考生答一次题”变成“一个考生独立答多次题”再用投票来过滤掉个别错误路径。逻辑上只要正确路径出现的概率高于错误路径多数投票就能放大正确信号。在数学、代码、常识推理任务上这个策略通常比单次CoT提升几个到十几个百分点的准确率。实际落地时我会这样设计CoT-SC流程同一问题构造5到15份请求提示词相同temperature设为0.7左右。每个请求要求模型输出“思考过程 最终答案”并用固定格式包住最终答案比如“最终答案 ”。收集所有最终答案写一个聚合函数。选择题直接按选项投票数字题对比数值开放式题目用嵌入向量算相似度再聚类。聚合这一步很多人会轻视但它直接决定CoT-SC的上限。如果只是简单比对字符串“6.0”和“6”会被当成两个答案投票反而受损。我会先做归一化比如去小数、去单位、统一格式再做计数。看下面这个对比表会更直观方法推理路径数量是否需要搜索典型成本适用场景直接问答1无低简单任务、低延迟场景CoT1无中需要步骤可见的推理任务CoT-SC多次无中高需要稳定准确率的推理任务Tree-of-Thoughts多路径且分层是高多步、有明确状态转移的复杂任务3. Tree-of-Thoughts把单线推理升级成树的搜索空间3.1 ToT的核心思想CoT最大的限制是“线性”不管中间步骤多复杂模型都是一条路走到黑。而人的思考方式其实更像树的搜索——遇到岔路口会分支出几个可能方向先尝试其中一个走不通再回退或者同时保留几个可能性做对比。Tree-of-Thoughts要做的就是把这个“分支 评估 搜索”的结构塞进LLM推理流程里。ToT把整个推理过程拆成多个状态节点。状态不是最终答案而是当前“思考到哪一步”。比如解数学应用题时一个状态可以是“我已经设x为未知数列出等式”写文章时一个状态可以是“我决定从背景切入提出第1个论点”。每个状态下模型生成若干个候选的下一步然后另一个模型或同一个模型评估这些候选筛选出最有希望的方向继续深入。这样一来推理过程从一条线变成了一棵树。树的每个分支都可能通向答案搜索策略决定先走哪条、保留多少条。3.2 状态生成器与评估器的设计模式实现ToT核心模块有三个状态表示、候选生成器、状态评估器。状态表示要尽量轻量化。通常不需要维护完整对话历史而是每轮“压缩”成一句话比如“已完成步骤列出方程当前表达式x37”。这样下一轮模型能直接基于状态继续也不需要把前面所有token都重新读一遍。候选生成器做的事情是给定当前状态让LLM生成k个下一状态候选。提示词大致长这样当前问题... 当前已经完成... 请列出接下来可以采取的3种不同思路用编号分隔要求每种思路都具体、可执行。这里有一个经验如果直接让模型生成“3种思路”模型常常只会做“换个说法复述同一思路”。解决方法是先让模型给出“思路的差异点”再描述具体做法或者用两个步骤第一步头脑风暴第二步压缩成候选。状态评估器是ToT里最影响效果的部分。评估方式有两种LLM打分给每个候选状态打一个分比如0到10分或者分成“可行/不确定/不可行”。优点是灵活缺点是成本高而且LLM打分经常自相矛盾。程序化评估如果任务有明确的验证条件比如数学等式是否成立、代码是否能编译、是否符合字数要求优先用规则判定。规则能判定的部分尽量不要让模型打分。我的一般取舍是能用正则、代码、公式验算的就用程序程序覆盖不到的主观合理性才交给LLM打分。给LLM打分时一次请求里让模型给多个候选状态同时打分能减少一半以上的调用成本。3.3 搜索策略BFS与DFS的取舍有了候选生成器和评估器还需要决定“沿着树怎么走”。ToT论文里默认用两种策略广度优先搜索BFS和深度优先搜索DFS。BFS适合步骤数量已知的任务。比如“3步内算出结果”的游戏题每一层先扩展出若干个候选状态每层保留评分最高的b个节点继续下一层直到达到最大步数再从最后一层里选最佳答案。BFS的优点是探索充分不容易漏掉好分支缺点是内存和调用次数增长很快。DFS更像人的解题习惯从根节点一路往下走走到底发现不对回溯到上一个分叉点再走其它分支。它更适合开放式任务比如“写一段大纲然后扩展成长文”因为你要一边写一边判断是否离题。DFS要特别注意深度限制和回溯条件否则模型会在一条错误分支上生成大量无意义内容。实际做的时候我会把深度、每层保留节点数、最大调用次数都设成可配置参数。同一个任务先跑一遍小规模比如深度3、宽3确认状态表示和评估器没问题再放大搜索规模。一上来就宽深拉满很容易预算爆炸。3.4 一个最小可用的实现思路下面这段是伪代码展示ToT的核心控制流。你可以根据自己用的SDK替换llm调用部分# 伪代码只展示控制流不依赖具体模型 import dataclasses dataclasses.dataclass class State: text: str score: float 0.0 def gen_candidate_states(question, current_state, k): prompt build_candidate_prompt(question, current_state.text, k) outputs llm.chat(prompt, nk, temperature0.7) return [State(texto.strip()) for o in outputs] def evaluate_states(question, states): prompt build_eval_prompt(question, [s.text for s in states]) scores llm.chat(prompt, temperature0.0) # 假设模型返回一行一个分数 for s, val in zip(states, parse_scores(scores)): s.score val return states def tree_search(question, max_depth3, beam_width3, k5): beam [State(text)] for depth in range(max_depth): next_beam [] for state in beam: candidates gen_candidate_states(question, state, k) candidates evaluate_states(question, candidates) next_beam.extend(candidates) # 保留评分最高的 beam_width 个节点 beam sorted(next_beam, keylambda s: -s.score)[:beam_width] if has_final_answer(question, beam): return extract_answer(beam[0].text) return generate_final_answer(question, beam[0].text)这段代码有几个地方需要特别注意has_final_answer要能判断“这个状态是否已经可以得出答案”如果无法自动判断可以交给LLM做一个极短的“是否已解决”分类调用beam_width和max_depth必须限制否则每次循环调用模型的次数是beam_width * k很快就跑满了。4. 从树的思维走出更远的变体GoT、ReAct与验证器4.1 GoT让推理图比树更灵活ToT虽然已经从“线”走到了“树”但树仍然不允许两个子节点合并。比如要综合多个分支的结论或者要先写两个版本再融合树结构就有点力不从心。Graph-of-ThoughtsGoT把推理结构进一步放宽成有向图多个状态节点可以互相引用、合并、聚合。我实际用GoT的场景不多因为大多数情况下ToT的树结构已经足够支撑“分支、评估、回溯”这套动作。但如果你的任务明显需要“多路论证后取交集”比如对比两个方案、合并两份摘要不妨把状态图设计成DAG。实现上需要维护一个节点列表和邻接表比ToT的二叉堆要麻烦一些。在动手之前建议先估算一下这个问题里节点之间真的需要合并吗如果不需要简单用ToT或CoT-SC就够了。4.2 ReAct让推理去调用外部工具进行校验ReAct全称是Reasoning Acting核心思想是让模型在推理过程中调用外部工具搜索、代码解释器、数据库、API并把工具返回的结果纳入下一步推理。它和ToT并不互斥更多是维度上的补充ToT管的是“如何搜索思考路径”ReAct管的是“思考过程中如何获得真实世界反馈”。在RAG场景中ReAct的用法很典型给定问题模型先判断需要查什么调用检索工具查看结果决定是继续检索还是给出答案。一个较好的地方在于工具返回的内容可以用来修正模型脑海中的错误假设——这比纯靠prompt“让模型自己猜正确答案”要可靠得多。如果你要在CoT-SC基础上叠加ReAct建议把工具调用视为一个“可执行的状态”。比如在ToT的候选生成器里增加“调用代码解释器计算这个表达式”这样的动作候选评估这个候选时先执行工具再把执行结果作为直接证据。这样推理路径既是树状的又对外部环境开放。4.3 过程奖励模型与验证器的作用上面说的评估器大多是用LLM自身打分或规则判断。还有一种更专业的方式训练一个过程奖励模型Process Reward ModelPRM专门给推理步骤打分。这和结果奖励模型ORM的区别在于PRM是逐步给分能在搜索过程中更早识别出错误分支不需要等到最终答案生成才知道好坏。如果你的团队已经有不少标注数据可以尝试训一个轻量PRM它会被用来做Beam Search剪枝每一步只保留PRM分数最高的几个节点。就算不训PRM也可以用更粗糙的办法近似让主模型每隔几步给自己的中间结果做一个“自评”在评测里加上“这个步骤是否与问题相关、是否有明显错误”两问。虽然精度不如专门训练的PRM但胜在零成本。5. 实操过程与经验把推理时计算真正落地5.1 模型选择不是所有模型都适合“深度思考”推理时计算不是点石成金。如果你的模型本身指令跟从能力很差生成的中间步骤都是乱写那再多的采样和搜索也只是放大噪声。我的一般原则是优先选指令跟从能力强的模型它们在遵循“先思考后回答”“按格式输出”这类指令上更稳定。如果在预算内优先选本身带推理优化过的模型它们的“thinking”路径质量更高外挂CoT-SC的收益会更明显。小参数模型也能用推理时计算但效果提升的上限低一些。有个参考经验当模型的单次CoT准确率低于30%时搜索和采样很难救回来当单次CoT能做到50%以上CoT-SC和ToT的收益往往很大。在实际选型时不要只看排行榜分数。找几个和你的业务场景高度相似的任务先跑一次“单次CoT”再跑一次“CoT-SC”看准确率提升幅度就能判断这个模型的“可思考性”到底如何。5.2 提示词与采样参数的组合技巧给一个我验证过比较稳的组合模板适用于数学、逻辑、代码解题类任务你是严格的分析师。请按以下要求作答 1. 先逐步列出推理过程每个步骤单独编号。 2. 推理过程中可以使用数学表达式和代码块。 3. 最后必须单独给出最终答案包裹在“最终答案”之后。 4. 如果发现前面的步骤有误请明确说明并重新推导。采样参数上我的默认值如下CoT单次temperature 0.3到0.5max_tokens 512到1024。CoT-SCtemperature 0.7采样次数8到15max_tokens同上。ToT状态生成temperature 0.7候选数k3到5。评分器temperature 0避免评分本身的不确定性。还有一个容易忽略的参数stop。在要求模型输出“最终答案”后可以设置一个停止符比如遇到“下一题”或空行就停止生成省下不少无意义token。5.3 成本控制推理预算、异步策略、缓存推理时计算最大的争议就是“贵”。同样的任务直接问答可能花几百个tokenToT可能要花几千甚至几万token。我的建议是把每次请求的消耗都记录下来做到心里有数。可以这样控制成本用小模型做评估器。候选生成可以用大模型但状态打分可以尝试用更小的模型很多场景下一个小模型足够区分“靠谱/不靠谱”。合并评分调用。不要给每个候选单独发一次评分请求把5到10个候选塞进同一个请求里让模型逐行打分能省一半以上的请求数。做查询缓存。高频问题如果已经跑过一次高质量推理把结果缓存下来。短期看缓存命中率可能不高但长期看能显著减少重复消耗。设置硬性预算。给每次搜索限定“最大调用次数”比如10次和50次。超过就强制输出当前最优结果哪怕它不是完美答案。很多业务场景里“及时止损返回次优解”比“计算到超时报错”要友善得多。5.4 一个通用基线先CoT-SC再按需上ToT很多团队一上来就上ToT结果效果提升有限成本倒是涨了十倍。我推荐一条更稳妥的路径先把业务问题定义清楚设计好评估集至少100条有标准答案或可评分的题目。跑一次单次CoT作为基线记录准确率和平均token数。跑CoT-SC采样5到10次。观察准确率提升幅度和成本增幅。如果CoT-SC准确率已经达到要求就不要上ToT如果还不够且问题本身有清晰的状态转移过程再上ToT。这样做的好处是“循序渐进”。每次只增加一点复杂度就能判断收益来自哪里。如果CoT-SC收益很小大概率是模型底子的问题换模型比换提示策略更有效。6. 常见问题与排查技巧实录6.1 输出循环或陷入局部循环怎么处理症状模型反复生成同一句话或者在某一步骤上反复“重新推导”却没有任何进展。常见诱因是温度过高、提示词里缺少“停止重复”的指令、或者模型本身在小规模搜索下被一个看似合理的错误分支困住。我的排查顺序是先降低temperature到0.5左右再在提示词里加一句“如果发现之前步骤重复请跳到下一步继续不要重复已经完成的计算”如果还不行检查max_tokens是否过短导致模型没有足够空间跳出循环。ToT场景下还要确认候选生成器是否在“原地打转”。可以要求候选生成器输出“与当前状态不同的思路”并在代码里把与父节点文本相似度超过阈值比如0.9的候选直接丢弃。6.2 采样多次但答案几乎一样怎么办按理说temperature在0.7时模型应该有一定多样性但有些任务尤其是答案明确、训练数据充足的问题模型会高度自信无论怎么采样结果都趋同。这时提高temperature效果有限反而容易引入噪声。更有效的思路是改变“采样起点”给不同的采样请求使用不同的few-shot示例或不同的题目表述让模型从不同角度开始思考。还有一个办法是提示词里让模型“先用方法A思考再用方法B验证比较两种结果是否一致”。这样即使模型原生路径趋同也能通过显式要求触发不同思路。CoT-SC采样次数也不用盲目增加当唯一的正确路径占比已经很高时把采样次数从15次加到30次收益几乎可以忽略。6.3 搜索结果越搜越慢怎么控制延迟ToT和CoT-SC天然是高延迟方案。如果你的业务有实时交互要求需要区分“离线高精推理”和“在线快速推理”两个通道。比如用户触发一次复杂操作时可以先返回一个“快速答案”后台再跑深度推理深度推理结果出来后主动推送。代码层面把多路采样请求改为异步并发并行等待所有LLM返回延迟可以从“串行n倍”降到“接近单个请求的延迟”。需要注意的是并发请求要设置速率限制和超时。我在实际操作里通常把并发数控制在10到20超时设为60秒并做好失败重试的退避策略。6.4 效果评估如何判断推理时计算真的带来了增益盲上推理时计算最危险的事情是你花了几倍的成本却没检验过收益。因此评估集和指标设计很重要。我一般会记录三类指标正确率/主指标对比直接问答、CoT、CoT-SC、ToT四档配置在评估集上的准确率。答案多样性计算多次采样结果中“唯一答案数量”。如果多样性很低说明采样策略没有真正探索不同思路。开销平均每题的LLM调用次数、总token数、端到端延迟。当这四档配置的主指标都拉出来之后你可以画一条“成本-准确率”曲线。正常情况下准确率会随成本增加而上升然后趋于平稳。如果曲线已经“平了”继续加搜索深度就是纯烧钱。用表格总结一下常见的坑和解决办法现象常见原因解决建议推理输出重复、循环温度过高、提示词缺乏停止指令降温度、加stop符、候选去重多次采样结果雷同模型过度自信、prompt不够开放变体few-shot、要求多解法对比成本过高且收益下滑搜索深度过大、评估过于频繁设硬性调用次数上限、用小模型打分搜索路径质量差状态表示不清、评估器信号不准压缩状态为关键信息、优先用规则评分延迟不可接受串行调用、推理路径过长异步并发、离线/在线双通道最后再分享一点我个人的体会推理时计算的本质是用更多的计算换更好的判断。它不能代替好的提示词、合适的数据和扎实的评估体系但它是目前“不加参数、不动权重”前提下普通开发者最容易掌控的提效杠杆。我现在的默认工作流是所有推理类任务先跑一次CoT再跑5次CoT-SC用这个组合作为基线只有在基线暴露出“多步复杂度高、步骤间强依赖”的特征时才把ToT搬上来。别急着一步到位把小步快跑的收益吃透你会比盲目堆搜索更接近那个终极秘籍的真相。