OpenRouter 指南:用置信度阈值实现模型分级升级路由
Confidence Thresholds for Model Escalation Routing
OpenRouter 发布教程,讲解如何让廉价模型通过结构化输出返回 0 到 1 的置信度字段,低置信度的请求再升级到更强模型。文章强调置信分数只是自报、不是校准概率,应基于自己流量的分数段错误率排序设定阈值,并在上线后监控分数分布、升级率和未升级答案的错误率持续调整。
原文给出按置信度分数分级路由的完整做法,读者可以照着在自己流量上校准阈值并权衡准确率、成本和延迟。
把每个请求都发给最强的模型能以最高价格获得好答案,因为你会为那些更便宜的模型本可正确回答的请求支付前沿模型的价格。固定路由规则,例如按关键词或任务类型选择模型,成本更低,但需要随着流量变化而重写。
基于置信度的升级介于两者之间。你让模型给自己的答案打分,然后根据该分数进行路由。高分答案留在便宜的模型上。低分答案则交给更强的模型。本指南分五步搭建这一机制。
简而言之
- 基于置信度的升级根据模型为其自身答案报告的分数来路由每个请求,因此便宜的模型处理它有把握的请求,而更强的模型只会看到它没把握的那些。
- 用结构化输出强制生成分数。一个要求数值型置信度字段的 JSON schema 能让每个模型给出相同的信号,而不是从自由文本中的模糊措辞去猜测。
- 使用排名,而非绝对数值。0.85 并不等于经过校准的 85% 正确概率。在你自己的流量上验证,低分答案确实比高分答案更常出错,然后依据这一排序进行路由。
- 根据你自己的数据设定阈值。让有代表性的流量通过便宜的模型,查看每个分数区间的错误率,把分界点设在错误率攀升之处。
- 把阈值当作一个需要反复调整的设置。记录分数分布、升级率,以及未升级答案的错误率,并在你的模型或流量变化时重新调优。

置信度分数是什么,不是什么
该分数是一种自我报告。模型生成它的方式与生成答案其余部分的方式相同,因此它带有同样的不确定性。两个相同的分数并不保证相同的正确几率。一个提示词上的 0.85 与另一个提示词上或来自另一个模型的 0.85 不可互换,而且这个数字不是经过校准的概率。
你能用的是排名,前提是你已经验证过它。让你自己的一批请求通过便宜的模型,给答案评分,并按分数分组。如果较低分数区间的答案比较高分区间更常出错,那么这种排序就可用于路由,尽管绝对数值不可用。你要找的不是等于 90% 正确的那个分数。你要找的是排名中那个把可以交付的答案与需要二次调用的答案分开的点。第 2 步就是这项测量。
第 1 步:用结构化输出获得数值型置信度字段
不要从自由文本中解读不确定性。当模型不确定时,没有任何东西要求它在行文中含糊其辞,也没有固定的模糊措辞词汇表可供解析。
相反,使用 结构化输出,让模型在经 schema 验证的响应中返回一个置信度字段。你传入一个类型为 json_schema 的 response_format,并要求同时给出一个答案和一个介于 0 与 1 之间的数值型置信度:
{
"model": "openai/gpt-5.6-luna",
"messages": [
{
"role": "user",
"content": "..."
}
],
"provider": {
"require_parameters": true
},
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "answer_with_confidence",
"strict": true,
"schema": {
"type": "object",
"properties": {
"answer": {
"type": "string"
},
"confidence": {
"type": "number",
"description": "How likely the answer is correct, from 0 (a guess) to 1 (certain)."
}
},
"required": ["answer", "confidence"],
"additionalProperties": false
}
}
}
}现在每个响应都带有一个数值型置信度,无论哪个模型作答,你的路由代码都能直接读取。决定升级什么就变成了数字的比较,而不是解析语言。
schema 在字段的 description 中声明了 0 到 1 的范围,而不是用 minimum 和 maximum 关键字。Anthropic 的 structured outputs 文档 将 minimum 和 maximum 等数值约束列为不支持,因此描述形式才是跨提供商通用的做法。strict: true 要求具有原生严格模式的提供商精确执行 schema。执行情况因提供商而异,有些提供商将 schema 视为强提示而非保证,因此在依据解析后的 JSON 进行路由之前,请先对其进行验证。
在依赖此功能之前,请先做两项检查。第一,结构化输出支持是按提供商端点设置的,而不是按模型设置的,同一个模型可能由支持和不支持该功能的提供商提供服务。将 models 页面 筛选为至少有一个支持端点的模型,并检查模型页面 Providers 部分中的 structured_outputs 参数。第二,在你的 provider preferences 中设置 require_parameters: true,这样我们只会将请求路由到支持其中每个参数的端点。如果没有该标志,response_format 只是一个软偏好。当模型有部分端点支持时,我们会路由到支持的端点,但如果模型的所有端点都不支持,我们仍会发送请求,而该参数会被忽略。
第 2 步:根据你自己的错误率设定起始阈值
阈值来自对你自身流量的测量,而不是从指南中照搬一个数字。用上述 schema 将一批具有代表性的请求样本跑过你的廉价模型,记录置信度分数以及每个答案是否正确,并在错误率开始攀升的位置设定截止值。高于该线的请求由廉价模型解决。低于该线的请求则升级到更强的模型。
一开始要偏保守。起初过度升级、之后再放宽阈值,代价是花钱。升级不足则会交付自信的错误答案。
下面是一个示例。假设你将 200 个具有代表性的请求跑过廉价模型,并按分数区间对结果进行分组。该表仅作说明,其算术内部一致,并非目标值。你自己的分布会有所不同。
| 分数区间 | 请求占比 | 观察到的错误率 |
|---|---|---|
| 0.95 至 1.00 | 41% | 1% |
| 0.85 至 0.94 | 27% | 4% |
| 0.70 至 0.84 | 18% | 11% |
| 0.50 至 0.69 | 9% | 34% |
| 低于 0.50 | 5% | 61% |
错误率在 0.70 以下急剧攀升,因此 0.7 是候选截止值。阈值 0.7 会将其下方的两个区间(占请求的 14%)升级,并让其余 86% 由廉价模型解决。
在此样本中,廉价模型的总体错误率略低于 10%。将底部 14% 升级后,你保留的答案的错误率降至约 4%,代价是大约每七个请求中就有一次需要第二次调用。在你自己的流量上运行此过程的意义在于找到你自己的截止值,而不是采用 0.7。
第 3 步:根据准确率、成本和延迟调整阈值
阈值是在升级量与错误率之间做权衡。提高阈值会让更多请求获得第二次调用,这能捕获更多错误,但成本更高、运行更慢。降低阈值会让更多请求留在廉价模型上,这更快、更便宜,但会让更多错误答案通过。将其设在哪里取决于错误答案对你的产品意味着什么。有三件事会影响这一选择。
准确率。阈值越高,就会有更多临界答案被送去进行第二次调用,因此最终输出的错误更少。在示例中,将阈值从 0.7 提高到 0.85 也会把 0.70 到 0.84 这一区间纳入升级范围,而该区间的错误率为 11%。升级请求占比从 14% 上升到 32%,而保留答案的错误率从约 4% 下降到约 2%。
成本。每次升级都是一次额外的模型调用,是在你已经付费的廉价调用之上叠加的。成本取决于廉价模型与升级目标之间的价格差,以及你升级的频率。在确定目标升级率之前,请查看当前的各模型定价。随着新模型发布,层级之间的差距和价格本身都会变化。
延迟。被升级的请求会多一次往返,因此更慢。如果大量流量被升级,这条慢路径可能会逼近延迟预算。当你的产品有硬性响应时间上限时,这个上限可能会在成本或准确率之前,先限制你能升级多少。

该图表将每个候选阈值应用到示例表格中。提高阈值会降低你保留答案的错误率,同时提高需要为第二次调用付费的流量占比。这三个因素并非独立变化。为提高准确率而提高阈值,总会给被升级的那部分流量增加成本和延迟,因此正确的阈值是你的错误容忍度、预算和响应时间限制三者交汇之处。
第 4 步:在代码中路由低置信度请求
阈值设定后,由你的代码做出升级决策。它读取置信度字段,当分数低于阈值时,将请求发送给更强的模型。我们不会替你做出这个决定。我们的模型回退会在模型返回错误时触发,而不是在模型返回有效答案但置信度分数较低时触发。有两种方式可以组织这个决策。
在同一函数中重试。将调用包装在一个函数中。把请求发送给廉价模型,读取置信度,如果低于阈值,就将相同的消息发送给更强的模型并返回该答案。升级策略集中在一处,因此当你更改阈值或升级目标时,只需改一次,不会有调用点继续沿用旧决策。
运行单独的第一遍。将廉价模型调用视为第一遍。记录其答案和分数,然后仅当分数低于阈值时才调用更强的模型。这需要更多代码,但它会记录廉价模型升级的频率,以及其分数是否仍与真实错误相符,而这些正是你在第 5 步中重新调优所依据的数据。
模型 ID 是字符串,因此你可以通过配置而非代码来更改任一层级。在选择廉价模型和强模型时,请浏览我们的模型目录,因为每个层级的正确选择会随着新模型的发布而变化。
你可以在任一模式下叠加错误故障转移。传入一个 models 数组后,当列表中的第一个模型返回错误时,调用可以故障转移到下一个模型。默认情况下,任何错误都可以触发回退,包括提供商宕机、速率限制、被过滤模型上的审核标记,以及上下文长度验证错误。我们按最终回答的模型来计费,并在响应的 model 字段中返回该模型。这与你的置信度升级是相互独立的机制。它由错误触发,而不是由有效的低置信度回答触发,因此两者可以组合使用。故障转移让每次调用保持存活,而你的阈值决定一个存活的回答何时需要更强的模型。
第 5 步:在生产环境中监控并重新调优
在发布时合适的阈值可能会变得不再合适。从第一天起就记录三件事。
- 分数分布,这样当模型或流量变化时,你可以重新运行第 2 步的校准。
- 随时间变化的升级率。
- 未升级回答的错误率,这个数字能告诉你阈值是否仍在发挥作用。
当情况发生变化时重新调优。将廉价模型或升级目标换成新版本会改变分数分布。流量向更难或更简单的请求偏移会移动你的错误区间。成本压力可能促使你为了更低的升级率而接受更高的错误率。阈值是一个需要随着这些变化不断调整的设置。
常见错误
将自报分数当作经过校准的概率。该方法基于排序,而非字面意义上的可能性。按分数对一批回答排序,错误回答会聚集在低端,但 0.9 并不意味着该回答有 90% 的概率是正确的。请根据第 2 步中按区间统计错误率的练习来设定阈值,而不是根据原始数字。
对所有任务类型使用同一个阈值。一个回答“你们的退款政策是什么”的支持机器人和一个回答“如果我今天取消会被收费吗”的机器人,错误回答的代价并不相同。单一的全局阈值会对简单情况过度升级,或对高风险情况升级不足。在你了解任务类型的地方,为每种类型设置各自的阈值。
发布后不关注升级率。适合你校准批次的阈值可能会随着流量偏移或你底层的模型变化而变得不再合适,而且不会有任何错误提示你。
结论
基于置信度的升级让请求在廉价模型报告高置信度时留在廉价模型上,只在置信度不高时才为更强的模型付费,无需关键词或任务类型规则。这个循环很小。用结构化输出强制生成一个数值置信度字段。根据你自己的按分数区间统计的错误率来找到阈值,而不是随便选一个数字。选择适合你想要跟踪方式的路由模式,用一个函数实现策略,或为第一遍使用单独的日志。然后在发布后关注未升级回答的错误率,并随着模型和流量的变化进行调整。
常见问题
什么是置信度阈值?
置信度阈值是一个分数,低于该分数时,你将请求发送给更强的模型,而不是接受廉价模型的回答。高于该线,回答按原样发出。低于该线,请求升级。你根据自己错误率数据来设定这条线,而不是使用默认数字。
什么是 AI 中的置信度分数?
置信度分数是模型在给出答案的同时报告的一个数字,通常在 0 到 1 之间,用来表示它有多确定。这是一种自我报告,而不是经过校准的概率,所以 0.9 并不意味着有 90% 的概率是正确的。你能测量并依赖的是排序。在你自己的请求批次上,在根据分数进行路由之前,先确认得分较低的答案比得分较高的答案出错更频繁。
设置置信度阈值最可靠的方法是什么,以便让轻量级模型处理大多数请求,只在置信度低时才交给高级模型?
用你自己的流量来测量。让一批有代表性的请求通过轻量级模型,记录每个置信度分数以及答案是否正确,并按分数区间对结果进行分组。把阈值设在错误率急剧上升的位置。这样轻量级模型处理该线以上的所有请求,只有线以下低置信度的请求才会交给高级模型。先保守设置,然后在观察你保留的答案的错误率时进行调整。
如何自动从小模型升级到前沿模型?
让小模型通过结构化输出返回一个数值型置信度字段,然后让你的代码据此进行路由。当分数低于你的阈值时,将同一请求发送给前沿模型,可以在同一函数内联进行,也可以作为一次显式的第二次调用。OpenRouter 的模型回退是一个单独的功能。它们会在提供商宕机或速率限制等错误时将调用回退到另一个模型,而不是因为置信度分数低,所以要把这两种机制区分开。
参考资料
- 结构化输出,用于
response_format配合type: json_schema、各端点支持情况以及strict模式。 - 提供商路由,用于
require_parameters以及response_format的默认参数偏好。 - 模型回退,用于
models数组以及触发它的错误。 - Anthropic 结构化输出,用于了解 Anthropic 严格模式不支持的 JSON Schema 关键字。
- 支持结构化输出的模型以及模型目录,用于获取当前模型 slug。
- 定价,用于了解当前各模型费率。
来源:OpenRouter:Announcements(RSS) · openrouter.ai