
前几天我在调试一个基于 7B 模型的辅助问答服务时遇到一件让我印象很深的事。用户连续追问了三次“你确定吗”模型每一次都给出新的解释而第四次问“那到底哪一次是对的”它居然回答“我之前说的都是猜测现在这句话也不确定。”这个场景恰好踩中了一个非常重要但经常被低估的研究方向Verbalized Uncertainty也就是语言模型用自然语言表达自己的不确定性。小模型在缺乏足够容量和知识时这种“口头上的不确定”往往并不可靠。最近看到一个论文标题“Provable Limits and Certified Deferral for Verbalized Uncertainty in Small Language Models”几乎把这个问题说透了小模型在表达不确定性上存在可证明的边界而更务实的做法不是让它承认不知道而是引入认证延迟让系统在模型不可信时主动转交。这篇文章不打算逐字复述论文而是从一个工程实践者的角度聊聊这个方向到底解决了什么以及我们能不能在小模型项目里真正用起来。1. 先理解“言语化不确定性”为什么被寄予厚望1.1 从概率置信度到自然语言模型怎么把“不知道”说出来传统 NLP 系统里置信度是一个数字来自 softmax 概率或 logit。分类器输出 0.87就是 87% 置信度。但在大语言模型时代用户看到的是自然语言模型可以通过生成“我没有足够信息”“这一点我不太确定”“我建议谨慎对待”这类句子来表达不确定。这种表达方式最大的好处是人可以直接理解不需要额外解读概率图或校准曲线。对小模型来说这个能力显得更有吸引力。很多端侧或内部工具跑不动大模型也做不了复杂的 ensemble 采样用户更不可能去阅读 token 的概率直方图。如果模型能直接说“我不确定”产品上会显得更智能、更安全。这也是为什么“言语化不确定性”最近被频繁讨论。它本质上是把置信度从数值空间迁移到了语义空间让人和模型之间多了一个可对话的接口。1.2 小模型为什么更需要这种能力小模型参数量少、知识覆盖有限出错概率天然高于大模型。在客服预筛、内容分类、知识库问答这些场景如果模型能主动说“我不确定”产品会比现在可靠很多。过去系统通常靠阈值过滤低分答案比如生成 token 的平均概率低于 0.4 就拒答。但问题在于小模型的生成概率校准本来就差一个模型可能对错误答案给出很高的概率对正确答案反而犹豫。于是研究者开始把目光投向文本层面的“自述不确定性”希望模型自己能够根据内部状态说出“我不知道”。这个思路有道理既然模型学会了语言为什么不利用语言来告诉我们它有多不确定1.3 但真正的问题是它可以说话不代表它说得准这里必须清醒一下。模型说“我不确定”不代表它真的不确定。语言模型的训练目标是下一词预测不是自我认知校准。它会模仿训练数据里的表达方式如果语料中大量存在“我不确定”这类措辞它也会在面对困难问题时自然使用。反过来它也可能因为流畅性压力在完全不确定时选择一种更果断的表达。更麻烦的是小模型的表征能力有限很难在深层把自己内部状态和表层语言对齐。从工程角度看这就是一个“弱信号”。可以把模型自述的不确定性当作参考但绝对不能把它当作安全机制。否则你会遇到大量 false negative模型明明已经很慌了但为了保持对话连贯硬着头皮说“我认为答案是正确的”。这也是为什么单靠提示词让模型“不确定时就说不确定”解决不了根本问题。提示词能约束格式无法提升模型对自身不确定性的感知能力。2. 可证明限制不是“感觉上不准”而是“理论上就有边界”2.1 “可证明限制”通常会证明什么只看标题里的 Provable Limits就能判断这不是一篇“我们实验发现小模型容易过度自信”的文章而是在给出更严格的理论结论。从这类研究习惯看“可证明限制”通常意味着在某一组假设下小模型的言语化不确定性不可能同时满足几个理想性质。比如你希望它校准它说出“70% 确定”的时候真实准确率真的接近 70%你又希望它能覆盖足够的输入不要遇到稍微复杂的问题就拒答你还希望它生成的回答内容流畅、有信息量。这三个目标放在一起可能就不存在完美解。换句话说这不是通过调参就能绕过的问题而是模型容量、训练目标和生成机制共同作用下的硬边界。理解这一点很重要因为它决定了后续技术路线的选择。我们不能指望一个 7B 模型通过更好的提示词就变成不确定性表达专家。真正能做的是接受这个边界然后在系统层面补上机制。2.2 为什么小模型尤其难小模型在“言语化不确定性”上的困难可以从三个角度解释。第一是容量限制。模型需要学习“知识边界”和“问题难度”之间的关系这本身是一个很复杂的函数。参数量越少拟合这个边界的难度越大。第二是监督信号稀疏。训练语料里模型“知道什么”和“不知道什么”没有标准答案很少会有大量样本专门告诉模型这个问题超出你的能力范围你应该拒绝回答。第三是生成式目标带来的偏差。语言模型更倾向于流利、连贯地继续文本而不是停下来承认自己能力不足。小模型还要面对一个更隐蔽的问题它的隐层表征可能不足以区分“这个问题我很熟悉”和“这个问题我没见过”。因为模型的知识覆盖有限很多没见过的问题在表征空间里可能和见过的问题非常接近于是它自信地生成一个看似合理的答案。这就是为什么“可证明限制”在小模型上体现得比大模型更明显。2.3 对工程师意味着什么我见过太多项目踩坑在小模型的 system prompt 里写“如果你不确定请回答不确定”然后拿模型输出的“我不确定”作为过滤标签。结果往往是误杀率很高一些能答对的问题模型也会谦虚地说“我不确定”一些明显在胡编的问题模型却斩钉截铁。问题在于提示词只约束输出格式不能提升内部不确定性感知。如果一个题型在训练集中很少见模型根本意识不到自己没见过它只会自信地生成。所以当你在小模型上看到“我确定”或“我不确定”时不要把它当作模型内部置信度的透明窗口。它更像是一句经过语言模型润色后的“态度表达”而不是经过校准的置信度测量。理解了这一点就会明白为什么第二个关键词是 Certified Deferral。既然模型嘴里的话不可靠那就不能依赖它自己来决定要不要拒绝回答。我们需要在模型外部增加一个判断机制让系统来决定这次回答是否可以被信任或者是否需要转交给其他模块。3. 认证延迟把不确定性变成系统行为而不是一句道歉3.1 什么是延迟什么是“认证”Deferral 的直接含义是延迟、转交。在语言模型场景里它指模型不直接给出最终答案而是选择把问题交给更可靠的后续系统比如大型模型、检索模块或人工审核。Certified 则强调这种转交行为带有形式化保障。经典的选择性预测就是这样模型不仅要输出答案还要输出一个“我是否应该回答”的决策。如果能把这个决策做得足够好整体系统的可靠性就能上一个大台阶。对小模型来说认证延迟尤其合适。小模型可以继续回答简单问题一旦碰到它不熟悉、或者外部打分器认为风险较高的输入系统就自动转交。这个过程中模型自己说没说过“我不确定”反而不重要。重要的是一套独立于生成文本的评估机制能够在模型犯错前捕捉到风险信号。3.2 延迟机制怎么设计设计一个可靠的延迟策略不能只依赖模型生成的“我不确定”。通常需要一个独立打分器它用来评估“这次回答是否可信”。打分器可以有多种来源基于模型隐藏层特征训练一个小分类器判断这一次生成是否处于模型擅长的分布内。基于多次采样的语义一致性。同一个问题让模型生成多次如果结果互相矛盾说明不确定性高。基于逻辑规则或外部知识库。如果回答内容与知识库冲突也可以在打分阶段提前拦截。分数越高代表模型这次回答越可信。当分数低于阈值时触发延迟。要实现“认证”性质一般需要在验证集上对阈值进行校准使得某个错误率指标可以被控制在设定范围内。注意这里的保证通常只在验证集所代表的分布内成立。如果你的线上输入分布和开发集差异很大所谓的“认证”就会失效。3.3 关键参数与流程核心参数包括延迟阈值、覆盖率、风险容忍度和转交成本。下面这个表可以帮助你理解它们的关系参数高阈值低阈值模型直接回答比例低高回答部分的准确率高低延迟到大模型/人工的比例高低系统总成本高低典型适用场景医疗、金融等错误代价高低成本内容生成、推荐在实际项目里你还需要定义一个代价函数。比如每次模型直接回答正确可以节省一次转交成本但回答错误可能带来更严重的业务损失。代价函数决定了最优阈值的位置。更稳妥的做法是先画一条覆盖率-准确率曲线然后根据业务风险选择阈值。3.4 一个最小工作流示例下面用伪代码展示一个最简单的认证延迟流程。这里刻意不依赖某个库因为不同项目的模型部署方式差别很大。def answer_with_deferral(query, model, scorer, threshold0.6): response model.generate(query) # 注意score 应该来自独立打分器而不是模型自述文本 score scorer.score(query, response) if score threshold: return defer_to_expert(query, response) return response这个流程虽然简单但它有一个非常重要的变化不确定性不再依赖模型自己说“我不知道”而是由外部打分器在你设定的阈值下做决策。模型可以继续它的流畅表达但系统最终是否放行由另一套机制决定。这是从“让模型自我反省”到“让系统强制兜底”的关键转变。4. 在新手项目里落地先跑通再优化最后工程化4.1 环境准备与最小样例如果你打算在自己的项目里试这个思路我建议先从最小可用流程开始不要一上来就追求完美的打分器。先加载一个小模型能让它生成回答即可。常见做法是使用 Hugging Face Transformers比如from transformers import pipeline model_id your-small-model # 根据实际环境选择可用的模型 pipe pipeline(text-generation, modelmodel_id) query 请解释一下什么是量子纠缠 response pipe(query, max_new_tokens128)[0][generated_text] print(response)这只是为了确认环境通。真正要做的延迟策略是在这个基础上增加一个打分器。初期可以用最笨的办法让模型对同一个问题生成三次回答然后计算两两之间的语义相似度。如果三次结果都不一致就转交。这个方案不需要训练额外模型已经能带来一定改善。4.2 如何评估延迟策略的好坏不要只看整体准确率要同时看覆盖率、回答部分的准确率、误拒率和系统总成本。建议你准备一个小规模带标注的验证集比如 1000 条问题。每一条都要有标准答案和正确性标注。然后计算在不同阈值下模型实际回答了多少比例、这些回答里正确率是多少、延迟过去的问题里原本可以答对的占比是多少。画一条覆盖率-准确率曲线会非常直观横轴是覆盖率纵轴是回答部分的准确率。曲线越靠近右上角说明这个打分器越好。如果曲线和随机打分差不了太多那就说明你的打分器并没有捕捉到模型的不确定性需要换一种信号。4.3 常见排查链路落地过程中会遇到一些典型问题我建议按下面的顺序排查。现象模型明明不确定但仍然回答。 先检查打分器是否真正接入到了上线流程里而不是只在前端展示。很多初版工程会把打分器放在日志层线上请求其实没经过它。 再检查打分器是不是用了模型自述文本。如果你把模型生成的“我确定”当作高分信号那就等于绕了一大圈回到原点。 最后检查阈值是不是设得太低导致低分样本也被放行。现象延迟率过高大量本来能答对的问题被转交。 先检查验证集分布和线上分布是否一致。如果验证集里全是难题模型直接回答的准确率自然很低阈值会被压得特别紧。 再检查打分器是否对简单问题也存在低分倾向。 最后可以适当降低阈值或者引入多条评分规则不要只依赖单一信号。现象延迟后系统成本剧增。 可以把延迟策略做成多级低风险问题先转给规则或检索模块只有高风险问题才转给大模型或人工。不要让所有低分问题都进同一个高成本通道。4.4 适用边界认证延迟不是万能的。它适合错误代价较高的场景比如医疗建议、法律咨询、金融分析辅助。也适合那种你有一个更可靠但更昂贵资源的场景比如大模型或人工专家。如果你的系统里没有一个“更可靠的后续系统”那延迟策略就只是把问题从左手换到右手没有实际意义。它不适合高吞吐、低延迟、几乎零成本要求的场景。额外打分器和延迟转交会带来延迟和成本如果你只是在做大规模内容标签模型说错一两个也没关系那就不需要这套机制。更重要的是如果小模型本身能力太差在大多数问题上的答案都是错的那任何打分器都无法挽救。延迟策略解决的是“能力足够但不稳定”的问题而不是“能力完全不够”的问题。5. 回到最初那个问题该不该相信小模型说“我不知道”5.1 三个经验判断我可以给出三条比较直接的经验判断。第一小模型的自述不确定性是一个弱信号。它可以作为产品体验的一部分但不要作为安全机制的核心依据。第二认证延迟的可靠性来自外部打分器和校准过程而不是模型嘴里的话。模型的言语化不确定性能不能信最终要靠数据和指标来判断。第三落地时要遵循先测量、再调参、最后工程化的顺序。没有提前测量就没有办法确认你的延迟策略到底提升了什么。5.2 可复用的三步框架如果你现在就要把这套思路用起来可以从下面三步开始。第一步先测量。准备 200 条真实输入让模型回答同时让它用一句话说明自己的信心。人工标注正确性然后计算当模型说“我很确定”时准确率到底是多少。结果可能让你意外。第二步再接入打分器。选一个独立信号可以是多次采样的语义一致性也可以是用隐藏层特征训练的小分类器。在验证集上画出覆盖率-准确率曲线找到你愿意接受的阈值。第三步最后工程化。把延迟转交动作接到外部服务记录日志监控覆盖率、转交率、准确率。每隔一段时间拿新样本重新校准因为输入分布会变阈值也会过时。回到开头那个场景。那个小模型最后还是回答了“我现在不确定”但我已经不会再拿这句话当作安全信号。真正让系统可靠起来的是我在它后面加了一个“不确定就转交”的关卡。模型的言语化不确定性不该被寄予太高期望它真正有价值的位置是作为整个兜底系统里的一个输入信号而不是最终答案。这大概就是这个研究方向给普通工程师最大的启示。