推理模型(Reasoning LLM)是最近两年大模型能力跃升最明显的一条线:它不再拿到问题就吐答案,而是先生成一段思维链(Chain of Thought)反复推演、自我校验,再给结论。支撑这套玩法的核心概念叫 test-time compute——把算力从训练阶段挪一部分到推理阶段花。这篇文章讲三件事:推理模型凭什么更准、它是怎么被训出来的、以及在真实工程里怎么调 reasoning_effort、怎么控成本,代码和参数都可以直接照着用。
推理模型和普通模型差在哪:三代形态对照
很多人以为”让模型一步步想”只是提示词技巧,其实从 CoT 提示到今天的可开关思考模式,工程接口已经变了三代。先把形态分清,后面的调参才不会错位:
| 维度 | 普通对话模型 | 专用推理模型 | 可开关思考模型 |
|---|---|---|---|
| 推理触发方式 | 靠提示词写”请一步步思考” | 默认开启,无法关闭 | 参数开关按需开启 |
| 思考深度控制 | 无 | 基本无 | reasoning_effort 分档控制 |
| 思维链存放位置 | 混在 content 里 | 独立字段 reasoning_content | 独立字段 reasoning_content |
| 简单任务成本 | 低 | 高(想太多) | 可降到普通模型水平 |
| 工程适配难点 | 无 | 延迟不可控 | 多轮拼接与开关策略 |
结论很直接:今天做工程集成,应当默认按”可开关”形态设计代码,即同一套调用链既能开思考也能关思考,而不是为推理模型单独写一条分支。这跟当年 MoE 从论文走向线上的路径很像,可以对照站内这篇MoE 混合专家模型:从原理到工程落地解读。
test-time compute:算力从训练挪到推理
为什么预训练这条路变慢了
经典缩放定律里,模型能力大致由参数量和训练 token 量决定。问题是高质量公开文本正在见底,参数继续堆的边际收益不断走低。于是各家把注意力转向另一条独立的坐标轴:推理时的算力预算。同一个模型,允许它多想 10 倍的 token,在数学、代码、逻辑这类”答案可验证”的任务上准确率能出现台阶式提升——公开的行业统计里,软件工程类基准一年内的解题率从个位数涨到七成以上,靠的主要就是这条路线。
推理算力的三种花法
- 拉长生成长度:模型在给出答案前生成大量中间推理 token,这是最主流也最省事的做法。
- 重复采样 + 投票:同一问题采样 N 条解法,用多数表决或一致性检查挑答案,提升”至少有一条对”的覆盖率。
- 搜索 + 验证:把候选推理路径当搜索树展开,用打分器给中间步骤评分,剪掉错误分支并回溯到最近的可信节点。
三种花法的成本差异巨大:第一种只是多花输出 token,后两种要跑多次前向,延迟和费用可能翻好几倍。所以生产环境里绝大多数团队只用第一种,把后两种留给离线批处理或高价值任务。
模型怎么学会”长思考”:奖励模型与 RLVR
推理能力不是靠喂更多题目喂出来的,而是靠强化学习”练”出来的。关键分歧在于奖励信号的粒度——只看最终答案,还是逐步打分。
| 对比项 | 结果奖励模型 ORM | 过程奖励模型 PRM |
|---|---|---|
| 评分粒度 | 只给最终答案一个分数 | 每一个中间步骤都给分 |
| 信用分配 | 稀疏、延迟,说不清哪步对 | 能精确定位逻辑出错的位置 |
| 典型失效 | 蒙对答案但中间逻辑是错的 | 训练成本高 |
| 标注成本 | 低,只标最终结果 | 极高,要逐步标注 |
| 能否指导搜索 | 基本不能用于剪枝 | 可直接给树搜索做剪枝信号 |
PRM 效果好但标注贵,于是折中方案是用蒙特卡洛式的合成 rollout 把最终结果的信号”摊”到中间步骤上,拿到接近过程级的粒度而不必雇人逐步标注。另一条被验证有效的路线叫 RLVR(可验证奖励强化学习):只在有客观判定器的领域做 RL——数学有答案、代码能跑单测、形式化证明能被检查器验证。奖励可自动生成,训练就能规模化。这也解释了为什么推理模型在数学和代码上进步最猛,而在开放写作上提升有限:没有验证器的地方,就没有可靠奖励。
下面这段是过程校验在推理侧的最小实现思路——把模型的每步推理拿去打分,一旦低于阈值就触发回溯,而不是等整条链跑完才发现错:
from dataclasses import dataclass
from typing import List
@dataclass
class ReasoningStep:
index: int
content: str
score: float # 0.0 ~ 1.0,来自过程打分器
verified: bool = False
# 返回第一个不可信步骤的下标,用于回溯;全部通过则返回 None
def first_bad_step(steps: List[ReasoningStep], threshold: float = 0.85):
for s in steps:
if s.score < threshold:
return s.index
return None
# 用法:拿到中间步骤后先校验,再决定是否重采样该分支
bad = first_bad_step(steps)
if bad is not None:
resample_from(bad) # 只重跑坏掉的那一段,比整条链重来省得多
调用实战:reasoning_content 与 reasoning_effort
接口层面只需记住两点:思维链走独立字段、思考深度靠独立参数。以 OpenAI 兼容格式为例,思维链通过与 content 同级的 reasoning_content 返回:
from openai import OpenAI
client = OpenAI(api_key="sk-xxx", base_url="https://api.deepseek.com")
resp = client.chat.completions.create(
model="deepseek-reasoner", # 专用推理模型
messages=[{"role": "user", "content": "9.11 和 9.8 哪个更大?给出推导。"}],
)
msg = resp.choices[0].message
print("思维链:", msg.reasoning_content) # 模型的内部推演,可选择不展示给用户
print("最终答案:", msg.content)
print("token 用量:", resp.usage) # 推理 token 计入输出计费,务必观测
如果用的是可开关思考的新一代模型,开关和档位是两个独立参数,且开关通常要放在 extra_body 里透传:
resp = client.chat.completions.create(
model="deepseek-v4-pro",
messages=[{"role": "user", "content": "帮我把这段 SQL 改成窗口函数写法并说明取舍"}],
reasoning_effort="high", # 思考深度档位
extra_body={"thinking": {"type": "enabled"}}, # 思考开关:enabled / disabled
)
# 关闭思考:把开关置为 disabled(部分服务商等价于 reasoning_effort="none")
fast = client.chat.completions.create(
model="deepseek-v4-pro",
messages=[{"role": "user", "content": "把这句话翻译成英文"}],
extra_body={"thinking": {"type": "disabled"}},
)
档位怎么选:一张表定档
| 档位 | 适用任务 | 延迟感受 | 成本影响 |
|---|---|---|---|
none / 关闭 | 翻译、摘要、格式转换、意图分类 | 与普通模型一致 | 基线 |
low | 结构化抽取、简单改写、轻量判断 | 略增 | 1~2 倍输出 token |
medium | 多步分析、代码审查、方案对比 | 数秒 | 数倍 |
high / max | 数学证明、复杂排障、架构推演 | 十几秒到数十秒 | 可能十倍以上 |
还有一条容易踩的参数红线:开启思考模式后,temperature、top_p、presence_penalty、frequency_penalty 这类采样参数通常不生效。为兼容旧代码,服务端一般不会报错,只是静默忽略——于是你调了半天温度却发现输出毫无变化,白白浪费时间。想控制风格,就改提示词或换档位,别指望采样参数。
多轮对话与工具调用:最容易翻车的地方
思维链要不要回传给下一轮,是推理模型集成里最反直觉的一条规则,而且两种场景的答案相反:
- 纯对话多轮:上一轮的
reasoning_content不需要拼回上下文,传了也会被忽略。硬拼进去只会白烧输入 token。 - 带工具调用:模型在给最终答案前会边推理边调工具,此时中间的
reasoning_content必须完整回传,否则后续请求会直接返回 400。
# 场景一:纯对话多轮 —— 只回传 content,reasoning_content 可丢
messages.append({"role": "assistant", "content": msg.content})
messages.append({"role": "user", "content": "那第二种方案的风险呢?"})
# 场景二:带 tools 的多轮 —— reasoning_content 必须原样回传
messages.append({
"role": "assistant",
"reasoning_content": msg.reasoning_content, # 缺这行 → HTTP 400
"content": msg.content,
"tool_calls": msg.tool_calls,
})
for call in msg.tool_calls:
result = dispatch(call) # 本地执行工具
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": json.dumps(result, ensure_ascii=False),
})
流式场景要多做一件事:reasoning_content 和 content 会分块交替到达,前端必须按字段名区分”思考中”和”正式回答”两个区域,否则用户会看到思维链和答案糊在一起:
stream = client.chat.completions.create(
model="deepseek-reasoner",
messages=[{"role": "user", "content": "推导一下这段代码的时间复杂度"}],
stream=True,
)
thinking, answer = [], []
for chunk in stream:
delta = chunk.choices[0].delta
if getattr(delta, "reasoning_content", None):
thinking.append(delta.reasoning_content) # 渲染到"思考过程"折叠区
elif delta.content:
answer.append(delta.content) # 渲染到正式回答区
工具调用本身的参数设计与错误处理,可以接着看站内这篇大模型工具调用:Function Calling 实战;如果要把推理模型接进多智能体协作,协议层的选型见MCP 与 A2A:2026 AI Agent 协议选型指南。
成本与延迟:过度思考是最贵的 bug
推理 token 计入输出计费,而输出通常比输入贵。这带来一个反直觉的账:单价一路在跌,但因为每次回答的 token 数暴涨,单次请求的成本反而可能上升。更糟的是,简单问题上开高档思考不只是浪费——过度推演还会把本来对的答案想歪。
学术界正在做的”自适应思考”给了量化参考:2026 年 8 月一篇工作让 1.5B 模型自己在 NoThink / 短思考 / 长思考三档里选,MATH-500 上准确率基本持平(0.782 对 0.796),平均响应长度从 4796 token 降到 2811(约 41%);在更简单的 GSM8K 上 token 降幅达到 76%。也就是说,光把”该不该想”这件事判断对,就能省掉四成以上算力。
工程上不必等模型自适应,用一个轻量分类器做快慢路由就能吃到大部分收益:
FAST_MODEL, SLOW_MODEL = "deepseek-v4-flash", "deepseek-v4-pro"
# 只用关键词+长度做粗筛,成本几乎为零;线上再用小模型做意图分类升级
HARD_HINTS = ("为什么", "证明", "推导", "排查", "架构", "对比取舍", "算法", "复杂度")
def route(question: str):
hard = len(question) > 120 or any(k in question for k in HARD_HINTS)
if hard:
return SLOW_MODEL, "high", {"thinking": {"type": "enabled"}}
return FAST_MODEL, None, {"thinking": {"type": "disabled"}}
def ask(question: str, timeout: int = 90):
model, effort, extra = route(question)
kwargs = {"model": model, "messages": [{"role": "user", "content": question}],
"extra_body": extra, "timeout": timeout}
if effort:
kwargs["reasoning_effort"] = effort
r = client.chat.completions.create(**kwargs)
# 记录用量,按 model+effort 维度做成本看板,才能发现"谁在偷偷烧钱"
log_usage(model, effort, r.usage.completion_tokens)
return r.choices[0].message.content
三条必须写进代码的纪律
- 超时给足:高档思考十几秒起步,客户端默认 30s 超时会大面积失败,建议 90~180s 并配流式给用户反馈。
- 输出上限兜底:设置
max_tokens防止思维链失控刷屏,同时监控被截断比例。 - 结果缓存:高成本问答按”归一化问题 + 模型 + 档位”做键缓存,命中直接返回,这是性价比最高的省钱手段。
什么时候不该用推理模型
推理模型不是普通模型的升级替换品,它换来的准确率是用延迟和费用买的。下面这些场景请直接关思考:意图分类与路由、格式转换与翻译、检索式问答(答案在文档里,不需要推演)、高并发实时接口、以及任何延迟预算低于 2 秒的交互。反过来,数学与逻辑推导、多步排障、代码审查与重构方案、需要权衡多个约束的技术选型,这些才是推理模型真正拉开差距的地方。
还有一个常被忽略的替代方案:先把上下文质量做好,再考虑加思考。很多”模型不够聪明”的问题,根源是检索给错了资料。这种情况下优化召回比开高档思考便宜得多,思路见大模型 RAG 进阶:混合检索与重排序优化实战。若要在本地或端侧跑推理模型,还得额外算量化与显存的账,可参考本地大模型量化部署:GGUF 与 llama.cpp 调优与端侧大模型部署实战:2026 边缘推理落地指南。
落地清单:按这个顺序接推理模型
- 先分任务:把线上请求按”是否需要多步推演”打标,估算真正需要思考的比例,通常远低于直觉。
- 代码按可开关写:思考开关和
reasoning_effort做成配置项,能灰度、能一键回退。 - 拆开渲染:
reasoning_content与content分区展示,思维链默认折叠。 - 补齐多轮规则:纯对话丢弃思维链、带工具调用必须回传,写进单元测试防回归。
- 建成本看板:按模型 + 档位统计输出 token 与 P95 延迟,超阈值告警。
- 做 A/B:同一批真实问题跑关思考 / low / high 三组,比准确率增益与单次成本,用数据定档。
- 选型复盘:闭源与开源推理模型的能力和价格变动很快,定期重评,参考开源大模型格局速览:2026 主流选择与选型。
一句话总结:推理模型的工程价值不在”永远多想”,而在”该想的时候想得深,不该想的时候一秒不想”。把路由、档位、成本看板这三件事做扎实,它就是准确率杠杆;全都默认开高档,它只会是一张不断变厚的账单。




