如果你最近在用带思维链的推理大模型做数学题、跑逻辑分析或者生成代码大概率遇到过这类现象同一个 prompt 连问三次第一次三行字直接给答案第二次洋洋洒洒写了几百字过程第三次中间步骤有明显错误但最后答案居然对了。这不是玄学而是推理大模型在“测试时”的计算分配方式在起作用。这篇文章想讲清楚一件事测试时扩展Test-Time Scaling到底是怎么影响回答质量的它有哪些不同的推理模式以及你该怎么评估和复现它。先说一个明确判断测试时扩展的真正难点不在“要不要多花算力”而在怎么把额外推理算力分配到最可能提升质量的方向上以及如何让你的实验结论不被采样随机性和模型服务波动干扰。如果你正准备在业务里接入推理大模型或者在做模型对比选型这篇文章能帮你避开“加大采样数就能变好”和“跑一次结果就下结论”这两个典型误区。1. 测试时扩展解决的真正问题1.1 从训练时扩展说起过去几年大模型能力提升的主线是“训练时扩展”把模型的参数量做大把训练数据堆多把训练算力拉满。这条路径简单直接但很快会遇到两个现实问题。第一训练成本越来越高。一次完整的预训练或大规模微调对绝大多数团队来说是不可承受的投入。第二模型训练完之后能力上限就被固定住了。你在推理阶段遇到一道训练数据里没有覆盖的题模型只能凭已有参数硬答错了就是错了你没有任何手段在推理时“再想想”。这时候测试时扩展提供了一种完全不同的思路模型参数不变在推理阶段动态增加计算量让模型有更多机会重新思考、尝试、自我纠错从而提高最终输出质量。1.2 为什么推理模型让这件事变得更重要OpenAI o1 系列和 DeepSeek-R1 这类推理模型出现后“推理时多花算力”不再只是一个学术概念而是变成了真实产品功能。这类模型通过强化学习学会了生成更长的内部思维链模型在推理时延和 token 消耗上明显上升换来的是复杂任务上的准确率提升。这带来一个本质变化你可以在“推理时”通过调整采样策略、搜索广度、验证器强度来控制模型的质量和成本。训练时扩展的决策周期是周或月测试时扩展的决策周期是秒或分钟。这意味着测试时扩展成了应用层开发者真正能掌控的优化杠杆。它不要求你重新训练模型只要求你理解推理策略、评估方法和工程化手段。1.3 适合谁读这篇文章如果你属于以下三类人这篇文章对你最有价值在做 LLM 应用开发想在复杂任务上通过多轮采样、投票或验证机制提升输出质量在做模型选型或效果评测需要设计一个能复现、能横向比较不同模型或版本的评估流程在维护 AI 服务的稳定性经常被“同一个 prompt 两次结果不一样”这类问题困扰。如果你只是临时调用一次 API 玩玩那没必要读完全文记住一个结论就行测试时扩展是有效果的但它的效果高度依赖任务类型、验证器质量和评估方式的可靠性。2. 核心概念推理模式Inference Regimes2.1 什么是推理模式所谓推理模式指的是在测试阶段如何分配额外计算量。这里的“分配方式”不是模糊的“多采样几次”而是指一套完整的策略采样多少个候选、如何选择最终答案、是否需要额外的验证器参与、以及每一步消耗多少 token 和时间。不同的推理模式在成本、质量、延迟和可解释性上有明显差异。选择哪种模式本质上是在回答一个问题你愿意为了答案质量付出多少额外推理成本2.2 五种典型推理模式对比为了便于理解我把常见的测试时扩展方案分成五类。Pass1单次采样这是最基础的基线。模型只生成一次输出直接作为最终答案。优点是延迟最低、成本最低缺点是遇到复杂任务时一次思考往往不够充分。在很多推理模型上单次采样的结果已经不错但它不具备“再试一次”的能力错误无法自我修复。Self-Consistency自洽性采样同一道题采样 N 次每次用较高的 temperature 增加多样性最后对答案做多数投票。它的核心假设是正确答案往往在多次采样中更稳定错误答案则分散且相互冲突。这个方案不需要额外训练验证器实现简单是很多应用团队的第一选择。Best-of-N 采样采样 N 个候选输出后用一个奖励模型或验证器对每个输出打分选分数最高的作为最终答案。相比 Self-Consistency它对“如何选出正确答案”这一问题的建模更直接但它依赖一个额外的验证器验证器的质量直接决定上限。基于过程奖励模型的搜索不再只对完整答案打分而是对思维链的每个步骤进行评分。搜索算法如 beam search、MCTS根据步骤得分逐步构建更优的推理路径。这个方案适合数学证明、代码生成等“过程可检查”的任务但工程复杂度明显更高。带外部反馈的迭代式推理模型生成方案后放到一个可执行环境中运行比如代码执行器、规则引擎根据执行结果或环境反馈修正方案再生成下一版。AlphaCode 类和 Agent 类应用大多属于这一模式。它适合有自动反馈信号的任务否则迭代就会失去方向。2.3 各模式选择的关键判断我先给一个实用建议如果没有可用的验证器Self-Consistency 是优先尝试的方案如果任务能以程序自动检查代码是否通过测试、输出是否符合规则那么优先考虑 Best-of-N 或迭代式推理。一个常见的误解是“提高采样数量 N质量就一定会提升”。实际上Self-Consistency 在 N 从 5 提升到 40 的过程中质量会逐渐接近一个上限继续增加 N 的边际收益越来越小。如果任务本身没有明确答案空间或者模型能力太弱多数投票只会把“平庸一致性”放大并不会产生奇迹。下表可以帮你快速定位推理模式是否需要额外模型/验证器适用任务类型单次延迟实现复杂度Pass1否所有任务作为基线最低最低Self-Consistency否有明确答案的任务中低Best-of-N是奖励模型/规则验证器有可打分信号的任务高中PRM 搜索是过程奖励模型数学、推理链可检查的任务很高高带反馈的迭代推理是执行环境/工具代码、Tool Use 类任务很高很高3. 环境准备与最小实验设计3.1 本实验的定位在进入代码之前先说清楚我们准备做什么。本文不会直接给你一个“某某模型测试时扩展后准确率提升 20%”的结论因为那类结论必须基于具体模型、具体数据集、具体参数脱离环境谈论数字没有意义。我们做的是一个可以复用到任何 OpenAI 兼容 API 的测试时扩展实验框架。你可以把它套到自己的模型服务、自己的题目集、自己的验证逻辑上得到属于你自己的评估结论。本文代码基于 Python 3.9OpenAI Python SDK 的当前版本即可运行。模型名称和接口地址以你的实际服务为准不写死版本号。3.2 安装依赖pip install openai如果你需要统计 token 消耗可以视情况再安装tiktokenpip install tiktoken环境变量方面建议把 API Key 放在环境变量里而不是写进代码或配置文件export LLM_API_KEYyour-api-key-here3.3 准备题目集测试时扩展的评估必须建立在“有标准答案”的任务上否则你无法判断哪个采样策略更好。我建议准备两类题目数学/计算类答案明确适合用最终数字做判断规则判断类比如“如果所有 A 都是 B所有 B 都是 C那么能否推出所有 A 都是 C”答案可枚举适合用关键词或选项匹配。题目数量不需要多小规模验证 10 到 20 题就够了。实验目的是观察不同推理模式下的趋势差异而不是做完整 benchmark。4. 核心流程拆解从单次采样到预算可控的投票4.1 第 1 步固定推理参数采集单样本基线很多人在评估模型时只跑一次然后拿这一次的结果说事。这是最容易导致误判的环节。正确的做法是先固定一组推理参数比如temperature0.7、max_tokens2048对每道题只生成一个样本作为 Pass1 基线。注意 record 下每次请求的耗时和 token 消耗这些信息在后面算成本时非常重要。这里有一个容易被忽略的坑API 服务端不一定支持seed参数或者即使支持同一个 seed 在不同模型版本下产生的结果也可能不同。所以不要指望“固定 seed 就能完全复现”你需要记录的是完整参数和输出内容而不是只依赖 seed。4.2 第 2 步多次采样观察答案分布接下来对同题采样 N 次。N 可以从 3 到 10 开始不要一上来就采样几十次。这一步的目的有两个。第一看模型输出的多样性如果不同次采样答案完全一致说明该问题对模型来说“太简单”或者 temperature 设置过低测试时扩展没有发挥空间。第二看答案分布如果答案分散但没有一个明显多数说明模型对该问题把握不足单纯投票可能不够需要考虑验证器。很多团队在这里会犯一个错误直接把 N 次采样去重后交给下游人工审核。这其实没有利用好多数信息反而增加了人工成本。4.3 第 3 步设计聚合策略聚合策略取决于任务类型。对于数学题可以从输出中提取最后一个数字或表达式做多数投票。对于 yes/no 类问题可以先做关键词映射再投票。对于有可执行环境反馈的任务更适合 Best-of-N 配合规则验证器而不是简单投票。我见过不少项目把聚合逻辑写死在代码里换一个任务类型就失效。更合理的做法是把“答案提取”和“聚合策略”拆成可配置模块不同任务类型单独指定。4.4 第 4 步画计算预算-性能曲线测试时扩展的核心其实不是“某个 N 下准确率多少”而是随着推理预算增加质量是否在提升、提升到什么程度开始饱和。你需要用平均每次请求消耗的 token 或总耗时作为横轴用任务正确率作为纵轴画出曲线。如果 N 从 3 增加到 10准确率几乎不涨说明这个任务不需要更多采样如果每次增加采样都稳定提升说明在这个任务上有继续加预算的空间。这一步决定了你的线上推理预算应该设置多少。5. 完整示例代码实现5.1 配置文件先准备一个配置文件config.json{ model: your-reasoning-model-name, base_url: https://api.example.com/v1, api_key_env: LLM_API_KEY, temperature: 0.7, top_p: 1.0, max_tokens: 2048, num_samples: 5, concurrency: 2, timeout: 120, questions_file: questions.json, output_dir: results }题目文件questions.json[ { id: math_001, question: A shop sells apples at $2 each, and oranges at $3 each. If someone buys 3 apples and 2 oranges, what is the total cost?, answer: 12 }, { id: logic_002, question: If all A are B, and all B are C, then can we conclude all A are C?, answer: yes } ]这里base_url是为了兼容自建网关或第三方的 OpenAI 兼容接口。如果你的模型服务有专属 SDK替换成对应客户端即可实验思路不变。5.2 多轮采样与日志记录脚本下面这个脚本sample_and_log.py会读取配置对每道题采样 N 次并把每次请求的完整输出、token 消耗、延迟一并记录到 JSON 文件。import json import os import time from concurrent.futures import ThreadPoolExecutor, as_completed from openai import OpenAI def load_config(pathconfig.json): with open(path, r, encodingutf-8) as f: return json.load(f) def load_questions(path): with open(path, r, encodingutf-8) as f: return json.load(f) def sample_one(client, cfg, question, sample_index): start time.time() try: resp client.chat.completions.create( modelcfg[model], messages[ {role: system, content: You are a helpful reasoning assistant. Think step by step, then give a final answer.}, {role: user, content: question[question]} ], temperaturecfg.get(temperature, 0.7), top_pcfg.get(top_p, 1.0), max_tokenscfg.get(max_tokens, 2048), ) text resp.choices[0].message.content or usage resp.usage elapsed time.time() - start return { question_id: question[id], sample_index: sample_index, completion: text, prompt_tokens: usage.prompt_tokens if usage else None, completion_tokens: usage.completion_tokens if usage else None, total_tokens: usage.total_tokens if usage else None, latency_sec: round(elapsed, 2), } except Exception as e: return { question_id: question[id], sample_index: sample_index, error: str(e), } def main(): cfg load_config() questions load_questions(cfg[questions_file]) client OpenAI( api_keyos.environ.get(cfg[api_key_env]), base_urlcfg.get(base_url), ) os.makedirs(cfg[output_dir], exist_okTrue) tasks [] with ThreadPoolExecutor(max_workerscfg.get(concurrency, 2)) as pool: for question in questions: for i in range(cfg[num_samples]): tasks.append(pool.submit(sample_one, client, cfg, question, i)) results [t.result() for t in as_completed(tasks)] timestamp time.strftime(%Y%m%d_%H%M%S) out_path os.path.join(cfg[output_dir], fsamples_{timestamp}.json) with open(out_path, w, encodingutf-8) as f: json.dump(results, f, ensure_asciiFalse, indent2) print(fSaved {len(results)} samples to {out_path}) if __name__ __main__: main()建议把结果按时间戳拆分成不同文件而不是覆盖写入同一个文件。后面你会拿不同时间、不同参数下的结果做对比保留原始样本是复现实验的基础。5.3 自洽性与 Best-of-N 聚合脚本采样完成后需要一个聚合脚本aggregate.py负责把 N 次输出转成最终答案。下面给出一个简化版本覆盖多数投票和基于简单验证器的 Best-of-N。import glob import json import os import re def extract_final_number(text): matches re.findall(r[-]?\d\.?\d*, text) if not matches: return None return matches[-1] def map_yes_no(text): lowered text.strip().lower() if yes in lowered or 是 in lowered: return True if no in lowered or 否 in lowered: return False return None def aggregate_self_consistency(samples): answers {} for s in samples: if completion not in s: continue ans extract_final_number(s[completion]) if ans is None: ans map_yes_no(s[completion]) answers.setdefault(ans, []).append(s) if not answers: return None, 0.0 top_answer max(answers.items(), keylambda x: len(x[1]))[0] consistency len(answers[top_answer]) / sum(len(v) for v in answers.values()) return top_answer, consistency def simple_verifier(sample): # 示例验证器数学题必须能从文本中提取到最终数字 return extract_final_number(sample[completion]) is not None def aggregate_best_of_n(samples, verifiersimple_verifier): for s in samples: if completion not in s: continue if verifier(s): return s[completion] return None if __name__ __main__: for path in glob.glob(os.path.join(results, samples_*.json)): with open(path, r, encodingutf-8) as f: samples json.load(f) print(fFile: {path}) answer, ratio aggregate_self_consistency(samples) print(Self-consistency majority answer:, answer) print(Consistency ratio:, round(ratio, 2)) print(Best-of-N chosen answer:, aggregate_best_of_n(samples))这里的验证器只是一个最简单的演示。一个真正能用的验证器通常是用程序解析模型输出、执行代码或比对规则而不是简单检查有没有数字。验证器的选择需要与任务深度绑定。6. 运行结果与效果验证6.1 预期输出是什么运行sample_and_log.py后正常输出是一行提示告诉你样本已经保存到 JSON 文件。打开文件你应该能看到每条记录包含question_id、sample_index、完整输出和 token 消耗。随后运行aggregate.py它会对每个结果文件输出一道题的最高频答案和一致性比例。一致性比例的意思是得票最多的答案占全部有效样本的比例。6.2 怎么判断实验是否成功判断实验是否成功不是看“答案是否漂亮”而是看三件事第一样本记录是否完整。如果某条记录缺少completion_tokens或latency_sec说明接口返回的结构不是你预期的先修正记录逻辑再往下分析。第二Pass1 与投票结果是否有差异。如果所有策略结果完全一样说明题目太简单、多样性不足或者模型本身就足够稳定。此时做测试时扩展实验没有意义应该换成更难的任务集。第三你能否从数据里看到一个趋势。比如 N3 时准确率是 60%N10 时是 80%同时每条样本的平均 token 从 1000 涨到 3500。这个趋势才是你后续做预算决策的依据。6.3 数据记录中的常见异常如果你发现某些样本的completion_tokens明显异常偏高或偏低先不要怀疑模型能力检查是不是max_tokens设置不合理。推理模型本身会输出长思维链如果你的max_tokens设成 512很多回答会在思考中途被截断最终答案都没有输出完整。这种情况下做聚合无论投票还是验证器结果都不会好。建议在调试阶段把max_tokens设到 2048 或以上先确认输出完整再优化成本。7. 评估与第三方评测工具的工程化选型7.1 先回答一个实际问题有没有好用的第三方评测工具很多人问“现在有没有好的第三方评测工具能调用我自己写的 API按我自己定义的评测标准来评估模型”答案是有的方向大致分成三类第一类是标准 benchmark 评测框架比如lm-evaluation-harness适合跑 MMLU、GSM8K 这类公开数据集。它的好处是标准化程度高能直接对比不同模型在公开任务上的表现坏处是它面向标准任务自定义任务接入成本比较高。第二类是 LLM 应用测试平台比如promptfoo偏重 prompt 回归测试和批量对比。它可以调用你的 API也可以配置自定义断言规则适合团队在持续集成阶段做效果回归验证。第三类是自建轻量评测 Runner。如果你的评测逻辑很简单只是“给定输入拿到模型输出按自定义规则打分”写一个小脚本往往比引入大框架更快、更可控。我个人的建议是先评估你的评测需求是否长期存在。如果只是临时验证一次自建脚本足够了如果要做每轮模型迭代的回归测试必须选择或搭建一个能保存历史结果、支持自定义指标的评测系统。7.2 第三评测框架的选型标准无论选择哪类工具你应该用下面的标准去筛选型维度需要关注的问题自定义接口接入是否支持配置 base_url、api_key、model 名称自定义指标能否用自己的规则判断输出是否正确并发控制评测任务是否会打满 API 配额或造成服务过载结果持久化每轮评测结果是否可追溯能对比历史版本成本控制能否限制最大请求数、最大 token 消耗可集成性是否能接入 CI/CD 流程或一键生成报告很多团队选评测工具时只盯着“支持多少个公开 benchmark”忽略了自定义 API 接入和结果持久化。这在应用评估阶段会吃亏因为公开 benchmark 结果好不等于你的任务效果好。7.3 一个轻量评测 Runner 示例下面是一个可以调用任意 OpenAI 兼容 API、按自定义规则打分的轻量评测脚本结构上可以扩展成团队公共评测工具。import json import os from concurrent.futures import ThreadPoolExecutor, as_completed from openai import OpenAI def load_json(path): with open(path, r, encodingutf-8) as f: return json.load(f) def call_model(cfg, item, api_key): client OpenAI(api_keyapi_key, base_urlcfg.get(base_url)) resp client.chat.completions.create( modelcfg[model], messages[ {role: system, content: cfg.get(system_prompt, )}, {role: user, content: item[prompt]}, ], temperaturecfg.get(temperature, 0.0), max_tokenscfg.get(max_tokens, 1024), ) return { id: item[id], prompt: item[prompt], output: resp.choices[0].message.content or , expected: item.get(expected), task: item.get(task, general), } def custom_metric(item): output item[output].strip() expected item.get(expected) if item.get(task) contains: return expected in output if item.get(task) choice and item.get(legal): return output in item[legal] if expected: return expected in output return False def main(): cfg load_json(eval_config.json) items load_json(eval_items.json) api_key os.environ.get(cfg[api_key_env]) results [] with ThreadPoolExecutor(max_workerscfg.get(concurrency, 4)) as pool: futures [pool.submit(call_model, cfg, item, api_key) for item in items] for fut in as_completed(futures): results.append(fut.result()) passed 0 for r in results: r[pass] custom_metric(r) passed r[pass] print(f{r[id]}: pass{r[pass]} | output_preview{r[output][:80]}) total len(results) print(f\nPass rate: {passed}/{total} {passed / total:.1%}) with open(eval_output.json, w, encodingutf-8) as f: json.dump(results, f, ensure_asciiFalse, indent2) if __name__ __main__: main()对应的eval_config.json可以这样设计{ model: your-model-name, base_url: https://api.example.com/v1, api_key_env: LLM_API_KEY, temperature: 0.0, max_tokens: 1024, concurrency: 4, system_prompt: You are a helpful assistant. }评测条目eval_items.json按你的任务类型来写示例[ { id: case_01, prompt: 请判断下面这段文本是否包含电话号码请联系 10086 客服, expected: 10086, task: contains }, { id: case_02, prompt: 这条客服回复的语气是哪一个选项A 友好B 冷漠C 嘲讽, legal: [A, 友好] } ]这个脚本的价值不在于代码量而在于它明确了评测系统的最小要素统一的模型调用层、可扩展的判定逻辑、结构化的结果输出。后续无论你接入多少个模型、多少条评测用例都能复用同一套流程。8. 可复现性测试时扩展的隐形敌人8.1 为什么同样的评估会跑出不同结果在测试时扩展场景里可复现性比训练时更难以保证原因有三个。第一采样随机性。temperature 大于 0 时模型每次输出都不同这既是测试时扩展能生效的基础也是复现困难的原因。你记录一次运行结果不代表着第二次运行还能得到相同结论。第二模型服务漂移。很多模型服务会在后台更新版本、调整量化精度或切换部署节点。即使你的代码完全没变、参数完全没变前后两天的结果也可能出现可见差异。第三推理路径不可预测。同一个模型在同一道题上一次可能用 200 token 思考一次可能用 1000 token 思考。即使 token 总数相同思维链中哪个节点产生错误、哪个节点得到正确答案都存在随机性。8.2 工程上如何提升可复现性提升可复现性不是追求“绝对相同”而是做到“差异可解释”。具体可以从五个方面入手。第一记录完整推理元数据。不只是保存最终输出还要保存 model、temperature、top_p、max_tokens、请求耗时、token 消耗、服务返回的created时间戳或内部 trace ID。这些信息是排查一次评测结果异常时的第一手线索。第二锁定模型版本。如果模型服务支持版本别名或快照 ID在评测配置里显式固定版本。不要使用“latest”这类可变别名做正式评估。第三重复实验取趋势。不要只跑一次评估就下结论。建议同一组配置至少跑 2 到 3 轮观察正确率的波动范围。如果波动范围很大说明你的测试集规模太小或任务难度不合适先扩大测试集再比较。第四缓存输出结果。对同一输入、同一采样参数可以把模型输出缓存到本地。这样后续调整聚合逻辑时不需要重新调用模型既省成本又保证对比的基础一致。第五保持评估代码版本化。你的评测 Runner、题目集、聚合策略都应该是代码仓库的一部分。任何指标变化都应该能追溯到是模型变了、参数变了、还是代码逻辑变了。8.3 一个辅助可复现性的配置段在评测配置里建议增加metadata字段记录评测的目的、模型版本、运行环境信息{ model: your-model-name, base_url: https://api.example.com/v1, api_key_env: LLM_API_KEY, temperature: 0.7, max_tokens: 2048, concurrency: 2, metadata: { experiment_name: tts_self_consistency_v1, model_version: your-model-version-id, notes: evaluate self-consistency with N5 } }这个 metadata 会成为每次评测输出的固定信息避免你在积累了大量结果后分不清哪一条属于哪一轮实验。9. 常见问题与排查思路问题现象可能原因排查方式解决方案同一次实验多次运行结果差异很大测试集太小或采样随机性过高统计多轮运行的正确率波动增加测试集规模或固定 seed如果服务支持Self-Consistency 提升不明显任务本身太简单或答案空间不明确检查 Pass1 是否已经很高换更难的任务集或引入验证器输出经常被截断没有完整答案max_tokens 设置太小查看 completion_tokens 是否接近上限提高 max_tokens给思维链留足空间同一个 prompt 在不同时间结果不一致模型服务端版本更新或负载变化检查服务返回的模型版本信息固定模型版本避免使用 latest并发采样时部分请求超时并发数过高或模型推理时间过长查看错误日志中的 timeout 信息降低 concurrency或设置合理 timeout验证器把错误答案判为正确验证器规则过于宽松检查验证器对错误样本的判别结果增加验证规则或引入更强验证模型历史结果无法对比结果文件被覆盖或缺少元数据查看结果文件的命名和时间戳按时间戳分文件保存并在配置中写入 metadata排查时要注意顺序先确认输入参数一致再确认模型版本一致最后才怀疑推理策略和验证器逻辑。大多数“复现不了”的问题都出在前两项。10. 最佳实践与工程建议10.1 从 Pass1 基线开始永远不要跳过无论你打算用多复杂的测试时扩展策略第一步永远是跑通 Pass1 基线。很多团队直接跳到 Self-Consistency 或 Best-of-N最后发现收益不明显却说不清是基线本来就高还是策略没选对。先记录三个数字Pass1 正确率、平均 token 消耗、平均延迟。之后的所有策略都必须拿这三个数字做基准去比较。10.2 验证器比采样次数更重要在 Best-of-N 场景里增大 N 能提升最高分候选的质量上限但真正的瓶颈是验证器的判别能力。如果验证器本身无法区分好答案和坏答案采样再多也只是浪费算力。因此建议先花时间把验证器的准确性做到 90% 以上再考虑增加 N。验证器可以是程序规则、代码执行结果、少量样本微调的分类器也可以是另一个更强的模型。关键是它的判定逻辑要独立于生成模型避免“自己评自己”带来的偏置。10.3 用预算曲线指导线上参数测试时扩展的工程化最终要回答一个问题线上应该设置多少采样数答案不是拍脑袋而来自预算-性能曲线。当你看到准确率提升速度明显放缓时那就是边际收益的拐点。上线时建议从拐点左侧的参数开始给线上留出余量并通过灰度实验逐步调整。10.4 面向生产的降级策略测试时扩展会显著提高单次请求的延迟和 token 成本。在生产环境里必须设计降级策略当模型服务超时或预算超过阈值时自动回退到 Pass1 单次采样而不是让用户无限等待。一个简单做法是给每个请求设置最大调用次数和最大 token 预算超时或超预算直接返回当前最优候选。宁可接受一次质量略低的回答也不能让用户面对 30 秒以上的空白。10.5 保持实验的可追溯性无论是开发期的效果实验还是上线后的灰度对比都必须做到“任何一条结论都能追溯到当时的模型版本、参数配置、测试集和聚合逻辑”。这要求你把评测代码、题目集、结果文件都纳入版本管理而不是散落在本地目录里。从长期看一个团队对模型效果的评估能力往往比临时堆几个 prompt 技巧更能决定应用质量。评估体系本身就是重要的工程资产。11. 总结与后续学习方向测试时扩展不是一个“多采样几次”的简单技巧而是一套从推理策略、评估方法到工程复现的完整体系。本文讲清楚了几个核心点测试时扩展解决的是推理阶段计算分配的问题不同的推理模式有完全不同的适用场景和成本特征评估不能只看单次正确率还要看预算曲线和结果可复现性可复现性的关键不是消除随机性而是让所有差异都有迹可循。如果你现在正准备在自己的业务里使用测试时扩展建议按这个路径实践先准备一个有标准答案的小型测试集跑通 Pass1 基线再对比 3 到 5 次采样的 Self-Consistency 效果最后根据任务类型引入规则验证器或程序化验证逻辑。每一轮实验都记录完整参数和样本输出保留历史结果用预算曲线来决定线上参数。接下来值得深入的方向包括过程奖励模型的设计与训练、树搜索算法在推理链上的应用、以及如何把测试时扩展与 Agent 工具调用结合。这些方向都比“单纯增加采样次数”更有长期价值。建议先把本文的代码跑通形成自己的实验基线再往更复杂的推理模式扩展。