ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

大模型置信度审计:50万次API调用揭示“自信”背后的错误率

大模型置信度审计:50万次API调用揭示“自信”背后的错误率 Jev是我们团队折腾了大半年的一款内部AI助手底层接了好几家大模型API用来做客服答疑、代码辅助和内部知识库问答。这个助手最大的特点不是能力多突出而是它特别“自信”——几乎每个回答后面都会附带一个把握评分经常是“95%确定”。上个月我们终于把五十万次真实API调用的评估跑完了汇总数据那一刻整个组都安静了在它最自信的那批回答里依然有接近一成的结果是错的。这篇文章就把整个实验的设计、发现、原理拆解和工程避坑完整写出来给所有正在做LLM应用、正在思考“能不能相信模型置信度”的同学一个参考。1. 项目缘起为什么要审计一个AI助手的“自信”1.1 Jev是什么以及我们最初的设计思路Jev这个名字没有特殊含义纯粹是内部代号。它是一个统一的任务型助手对外提供问答接口对内则把不同的底层模型封装成路由DeepSeek、GLM、Qwen还有GPT系列。选择多模型而不是绑定一家是因为每个模型擅长的领域不一样而且可以互相兜底。产品经理当时提了一个很自然的需求如果Jev对自己的答案很有信心就直接把它返回给用户如果它没把握就转人工处理。于是我们在每个响应后面加了一个confidence字段来源是模型返回的logprobs求和后归一化。这个设计在演示阶段看着很美。用户提一个问题Jev回答完附带一个93%的置信度交互界面显示绿色高亮运营同学看了直点头。但我当时心里就犯嘀咕这个置信度到底可不可信模型的“自信”和答案的“正确”之间有没有强关联没有验证过的置信度本质上就是一个心理安慰。所以我说服团队做了这次大规模评估目标很明确把“自信”和“正确”这两件事放在同一把尺子下量清楚。1.2 预警信号人工抽检发现“高置信度”答案也会翻车在正式跑50万次之前我们先做了一轮3000条的小样本抽检结果已经不太妙。当时我们把Jev置信度大于0.9的回复抽出来让三名标注员判断是否可接受发现有约10%的回答存在明显错误。这些错误包括代码逻辑错误、事实张冠李戴、数学计算过程推导出了不成立的结论。最让人难受的是这些错误答案的语气非常笃定完全看不出“本地模型在这里其实没把握”。我印象最深的一条是它回答一个关于数据库索引的问题置信度0.96条理清晰地分析了B树最后建议加冗余索引完全是错误的方案可能导致线上写放大加剧。要不是人工复核它大概率已经进生产环境了。这个小样本测试让我意识到置信度系统的安全边界可能被我们高估了。但3000条不够支撑一个严格的结论我们需要更大的样本量和更细分维度的数据这正是50万次API调用的由来。1.3 实验目标不只是“准确率”而是校准度准确率是一个整体概念比如“50万次调用整体正确率84%”这个数字对产品决策没有直接帮助。真正有用的是校准度calibration当模型说它有90%把握时它到底有多少概率是对的只有当置信度和正确率基本对齐时我们才敢用置信度作为自动返回或转人工的依据。所以实验目标被拆成了三个问题。第一Jev的置信度分桶之后每一桶的真实正确率是多少第二不同领域代码、数学、事实问答、摘要翻译的置信度可信度是否一致第三模型自报的把握分数比如让它说“我有多确定”和基于logprob计算的置信度哪个更贴近真实正确率这三个问题都需要足够大的样本才能回答。2. 五十万次API调用的实验设计与执行细节2.1 样本量从哪来统计学上的最低要求很多人问我为什么是50万次而不是5万次这里有一个统计上的计算逻辑。如果我们只想知道整体正确率几千条样本就够了。但我们要按置信度分桶、按领域细看每个格子都需要足够样本。用最简单的样本量公式算n Z平方乘以p(1-p)除以E平方。设期望错误率p0.1允许误差E0.0195%置信区间下Z1.96单个格子大约需要3457条样本。这还只是一个置信度分桶。我们计划把置信度分成5个区间覆盖6个领域理论上是30个格子加起来超过10万条有效样本。但真实环境里会有无效调用、超时、报错、重复样本而且我们希望覆盖更多长尾问题所以把总调用量抬高到50万次这样每个关键分桶都能有几千到上万条样本统计置信区间可以压到1%以内。这个量级的实验才有资格讨论“6%和8%的错误率差异是真实的还是噪声”。2.2 测试集构成与标准答案测试集不是随便找一堆问题喂进去就完事。我们用了四个来源生产环境脱敏后的历史用户问题、公开的评测集数学、代码、常识类、内部团队构造的对抗性样本特意设计的多步推理和边界情况、以及知识截止日期之后才发生的新事件类问题。之所以加入最后一类是想看看模型在“数据中根本不存在正确答案”的时候怎么表现。标准答案的标注分两层程序化可验证的代码跑单测、数学用表达式计算器核对以及人工标注的开放性问题。对人工标注的部分我们要求两个人独立标注不一致的地方再让第三人仲裁。这里有个教训如果标准答案本身有噪声后面的评估全白做。我们一开始图省事用另一个大模型给所有问题生成“参考回答”结果发现参考回答自己也错了一批尤其是数学和事实类。后来全部重标多花了两周时间但数据的可信度完全不一样了。50万次调用的质量很大程度取决于那几千条标准答案的质量。2.3 置信度怎么取logprob、自评分与自洽性大模型API返回的置信度信息有三种常见来源。第一种是logprob对数概率OpenAI兼容接口可以通过logprobs参数拿到每个token的概率我们把整段答案的token对数概率相加取平均作为答案的置信度。第二种是让模型自己打分在prompt末尾加一句“请用0到100的整数表示你对以上回答的确定程度”然后解析输出。第三种是自洽性同一问题用较高温度采样多次看看答案是否一致一致率就是置信度。实测下来logprob平均是最稳定的信号和真实正确率的相关性最高。模型自评分明显膨胀它经常给出90以上的分数但对应的实际正确率只相当于logprob置信度70分的档位。自洽性效果也不错但成本高因为要把调用量翻好几倍。所以我们最终的实验主方案是logprob同时对2万条子样本额外做了自洽性对比。结论后续会细说。2.4 调用架构、并发控制与成本估算整个实验跑在内部的一台容器化测试环境里异步客户端统一调度同时向多个模型服务商发起请求。并发控制在10到20之间这个数字不是拍脑袋定的太高会触发限流太低跑完50万次要一个月。实测每个请求平均耗时1.8秒左右20并发下一天大概能跑90万次请求所以整个实验实际上三天就跑完了主要调用。每条请求都要记录模型名称、版本、temperature、max_tokens、prompt指纹、响应全文、logprob序列、token用量、延迟、finish_reason和错误码。成本方面按当前主流API的公开价格估算假设平均每次调用输入300token、输出500token50万次调用约产生1.5亿输入token和2.5亿输出token。如果输入按每百万token一美元、输出按每百万token两美元算总费用在五六百美元左右加上重试、指纹、特殊配置和自洽性采样整轮实验花了一千多美元。这比人工标注50万条数据便宜了两个数量级也是大模型时代能做大规模质量评估的红利。但如果不控制并发和重试策略账单翻三倍也是很容易的事这一块后面专门讲。2.5 数据落库与清洗所有原始请求和响应都落到了PostgreSQL里表结构按一次调用一行设计长字段单独存。50万条数据不算大但带logprob序列之后单行能到几十KB所以用了一台独立磁盘的实例。清洗规则包括删除超时请求、空响应请求、触发内容过滤的请求、finish_reason为length导致的截断响应。最终有效样本大约47.5万条损失率5%左右对于这个量级的实验完全可接受。清洗时还发现了一个有趣的现象有1.8%的请求返回了完全相同的响应但logprob不一致这说明服务端可能发生了动态量化或者模型版本热切换。这类数据我们没有简单丢弃而是单独打了个标记后面分析稳定性时用上了。3. 核心发现自信满满不等于正确率满满3.1 校准曲线期望的正确率与实际的正确率我们把有效样本按logprob置信度分桶统计每个桶的实际正确率画出来一条校准曲线。理想情况下置信度0.9的桶应该有90%的正确率曲线应该贴着对角线走。Jev的实际曲线明显在对角线下方而且越往高置信偏差反而更顽固。置信度区间样本占比实际正确率0.95以上31%88.1%0.90-0.9522%86.9%0.80-0.9025%74.3%0.60-0.8015%55.2%0.60以下7%37.8%可以看出当模型说它有95%以上把握时实际正确率只有88%出头。这已经不是误差级别的差距而是系统性的高估。对产品来说如果以0.9作为自动回答的阈值意味着每一百条自动回复里会有超过十条是错的这个错误率在大多数业务场景下都不可接受。3.2 分领域数据代码和数学是重灾区整体校准曲线掩盖了不同领域的巨大差异。我们把高置信样本logprob大于0.9单独拉出来分领域统计错误率差异非常明显。领域高置信样本占比高置信错误率代码生成36%14.2%数学计算41%11.5%事实问答44%9.8%文本摘要/翻译39%4.1%生活常识35%3.6%代码生成是最危险的有36%的答案模型给出了0.9以上的高置信但其中14.2%是错误的。这个问题在代码场景里尤其隐蔽因为代码只要能编译通过、看起来结构完整非专业用户根本看不出逻辑错误。数学计算次之推理链越长模型越容易在中间某一步犯错但整体输出依然流畅且自信。文本摘要和翻译这类“语言流畅度主导”的任务反而校准得更好因为只要语言通顺内容偏差往往不算致命。3.3 自评分的虚高模型说自己有把握实际打了个七折我们在2万条子样本里让Jev同时输出自评分和logprob对比两者的校准效果。结果很扎心模型自评分的平均值是92.3而同期logprob置信度的平均值是81.5。自评分在90以上的样本实际正确率只有78%而logprob在90以上的样本实际正确率有88%。也就是说如果你在界面上展示模型自己报的把握分数它比真实可靠性乐观了差不多十个百分点。自评分的分布也有问题它大量集中在90到99这个区间很少给出中间值。模型在“完全有把握”和“有点把握”之间的区分度很低这可能是它在训练过程中被要求“尽可能提供帮助”导致的习惯。所以我的建议很直接不要用模型口头说的“我很确定”作为安全判断信号要么用logprob要么用自洽性。3.4 稳定性问题同一问题跑两遍都可能不一样实验过程中我们额外做了稳定性抽样把1000条问题以temperature0的相同参数重复调用三次。理论上temperature0应该是确定性的但实际有三成问题至少出现了一次不同的答案。尤其在不同模型间同一问题高置信区间的答案不一致比例达到12%左右。这说明两个问题一是API服务端存在量化、负载均衡或版本差异不能把“同参重跑”当成绝对可靠二是置信度本身是一个带噪信号单次高置信存在偶然性。这个发现直接影响了一个原本规划的策略通过同参重试来校验答案。如果重试本身就不稳定那么“重试两次答案一致才输出”的方案只能作为辅助不能作为安全兜底。4. 为什么大模型会“自信地犯错”4.1 token概率不等于“对世界的确认”理解这个问题要先回到大模型的基本原理。模型每次只做一件事预测下一个token的概率分布softmax之后取最高概率的那个token输出。所谓置信度本质上是模型内部参数对“哪个token最符合当前上下文”的确定程度。它衡量的是一种语言模式上的流畅性而不是对现实世界事实的确认程度。就像一个人背书背得很熟你问他“这段内容的结论在现实里成立吗”他照样能流利背完甚至越背越有底气但你问他为什么成立他根本不知道。在数学和代码这类规则型任务里模型生成每一步都符合训练数据中的模式所以每一步的token概率都很高整条链的置信度自然被拉高。但它并没有一个“全局校验器”去检查前面的步骤是否引入了错误。这是logprob置信度最根本的局限它反映的是局部平滑程度不是全局正确性。4.2 训练目标决定了模型没有“说不会”的动机传统机器学习分类器训练时会同时优化正确类别的概率也会在训练数据里学习“这个样本不属于任何已知类别”时的低置信输出。但大语言模型训练目标主要是最大化下一个token的预测概率数据集中“不好意思我不知道”这类样本占比极低。RLHF阶段又加入了“帮助性”和“无害性”约束模型学会了倾向于给出答案而不是承认能力边界。这就导致它在面对知识截止日期之后的新事件、或者训练数据里本来就含糊的问题时依然倾向于编造一个看似合理的答案并给出较高的概率分数。这有点像销售话术训练所有话术都围绕“如何把问题接住”而不是“在不确定时主动承认不清楚”。一个被训出嘴皮子很顺的销售你让他回答一个他完全不懂的领域问题他也能给出一套自信的说法但他传达的信息可靠性大概率不高。我们把模型变成“什么都能接住”的对话助手却期望它能像一个谨慎的老专家那样及时说“这个我不确定我需要查一查”本身就是训练目标里缺失的。4.3 多步推理中局部错误会被整体“带偏”还不自知多步推理是自信错误的高发地带。我们拆了一批错误样本发现典型模式是第一步或第二步就发生了偏差但后续所有步骤都自行一致地延续了这个偏差导致最终结论错误。举个例子计算328乘以17时模型第一步把乘数17看成了7后面每一步乘法和加法都计算正确整条推导链非常流畅logprob全程都很高。它没有一个“重新审视原始问题”的机制来发现最开始的关键信息已经被自己悄悄改写了。这种错误在人身上也很常见你抄错了一个数字剩下的解题过程全对最后答案自然不对但你检查的时候可能反复看中间步骤都发现不了问题因为问题出在源头。模型在生成时并没有对“原始条件”和“当前使用条件”做一致性校验。这也是为什么单纯增加模型参数量或训练数据并不能从根本上解决高置信错误问题——它需要的是在推理链路里显式地增加校验机制。4.4 温度、提示词和API波动对置信度的影响置信度对采样参数极其敏感。我们实验里默认temperature0但单独测了一批temperature0.7的调用logprob置信度整体下降且不同模型下降幅度差异很大。有些模型在温度调高后反而出现更复杂的校准曲线低置信区间的正确率偶尔高于高置信区间。这个现象说明任何基于概率分数的置信度评估都必须和采样配置绑定不能只看数值本身。提示词格式也会影响置信度。我们在实验中发现询问模型“你确定吗”之后重答有11%的高置信答案被模型自己修改成另一个答案且修改后的答案正确率并没有显著提升。这说明模型很容易被外部暗示动摇它的“坚持”和“动摇”都不代表真实性。API波动则体现在服务端模型滚动更新同一个prompt在一周前后调用logprob分布可能整体偏移置信度阈值需要随版本重新校准。5. 工程实践如何围绕“不太可信的置信度”搭防护墙5.1 多级阈值设计自动回答、二次校验、转人工既然知道了置信度会虚高就不能用一个简单的阈值一刀切。我们最终采用多级策略根据业务场景容忍度做分流。logprob置信度高于0.97允许直接自动回答但只适用于低风险场景比如闲聊、常见问题答疑。0.9到0.97进入二次校验通道需要换模型复答、检索验证或工具验证验证通过才输出。0.75到0.9默认转人工或者返回给用户时明确提示“以下回答仅供参考建议进一步核实”。低于0.75直接转人工并在工单里附带模型的原始日志方便人工快速定位。这个阈值看起来保守但实测之后我们发现就算把阈值提高到0.97自动回答的错误率仍然在6%左右。如果业务场景不能容忍6%的错误那就必须叠加更重的校验措施而不能只靠调阈值。安全边界是靠多层防护叠出来的不是靠一个置信度数字扛下来的。5.2 二次校验的三板斧换模型、跑测试、查检索针对不同场景我们总结了三类靠谱的校验手段。第一类是换模型交叉回答同一个问题发给另一个厂商的模型让它在不知道原始答案的情况下重新作答然后比对语义一致性。对高置信样本这种方式能把错误率再压掉四分之一。第二类是执行类校验代码类回答生成后立刻扔到沙箱里跑单测数学类回答把最终数值用计算器独立验算这类校验对规则型错误几乎是降维打击。第三类是检索校验事实类问题强制走RAG先生成查询检索内部知识库或联网检索再把检索结果拼进上下文让模型只基于检索内容作答。这三类校验的成本差异很大。换模型交叉回答成本最高基本等于每次调用多花一倍API费用执行类校验成本最低但覆盖面窄检索校验成本中等对事实类问题效果好。建议的做法是按业务优先级组合高风险场景全部校验中风险场景只做执行类低风险场景靠阈值兜底。5.3 多模型分歧检测与自洽性采样多模型分歧检测是比置信度更直观的安全信号。如果一个高置信答案同时被另一个独立模型确认它出错的概率会大幅下降反过来如果两个模型给出互相矛盾的答案即使两边置信度都很高也说明这个问题本身就处在模型的“知识模糊区”必须交由人工或更权威的信息源处理。自洽性采样是便宜版的替代方案同一个模型把temperature调高为0.7采样三次看主流答案占比。我们在子样本上跑下来主流答案占比与正确率的相关性明显高于logprob尤其在高置信区间。但代价是三次采样等于三倍成本不可能全量跑。所以现在产品里大概只有5%的流量会触发自洽性采样用来做长期的置信度校准参考。5.4 是否向用户展示置信度我的选择研究完整个实验后我们的结论是不向用户直接展示具体置信度数值。原因很简单用户看到“置信度95%”会建立不合理的信任预期一旦遇到哪怕5%的错误用户对产品的信任崩塌速度会远高于“不显示置信度”的情况。置信度是一个内部信号用来决定路由策略、触发校验、设置工单优先级而不是拿来炫耀的。但对运营和产品团队我们会保留置信度字段做可视化面板。运营同学看到低置信度内容占比和转人工率能及时给内容库补充语料。如果把置信度直接暴露给用户连这个内部复盘的机会都会失去。5.5 把50万次评估变成常态化回归50万次评估不是一次性活动。模型服务商会更新版本我们的业务问题分布也在变化置信度的校准曲线会漂移。现在我们的CI流程里挂了一个定时任务每周跑一轮包含两万条金标样本的小型回归用固定成本测出本周的置信度-正确率校准曲线。如果某一档置信度区间的错误率比上周明显变高了会触发告警提示团队检查模型版本更新和提示词变化。金标样本库是持续生长的每月把生产环境里被人工纠正过的用户反馈case加进去定期清理过时问题。这个机制比任何一次性评测都更有价值因为它把“模型可靠性”从一次性项目变成了日常监控指标。6. 常见问题与排错实录50万次API调用踩过的坑6.1 API报错速查表大规模调用API和我们平时写几个demo完全不同各种错误码扑面而来。我把这次实验里遇到的高频报错整理成了一个速查表都是实际踩过坑的。报错信息可能原因处理办法429 Too Many Requests并发超过限流阈值指数退避重试控制并发在8到20区间重试三次仍失败就降级到备用模型connection dropped (ECONNRESET)连接池被服务端强制断开增加连接池大小启用keepalive不要无限重试两次失败后强制休息30秒400 maximum context length is 1048576 tokens输入超出模型上下文窗口长文档先切块再做RAG摘要历史消息截断只保留最近的系统指令和关键上下文401 invalid api key密钥无效或过期检查环境变量是否有多余空格确认没有把密钥提交到git轮换密钥后更新配置400 organization has been disabled组织层面被停用检查账户账单和后台状态联系服务商客服permission denied while trying to connect to docker api测试环境无权访问Docker socket将当前用户加入docker组或者使用根目录的socket路径重启会话后生效6.2 成本失控如何避免账单爆炸实验中途发生过一次成本预警某个模型服务商因为配置里没有写max_tokens上限大量请求顶着最大输出跑一天烧掉了预估预算的三倍。从那以后我们立了一条硬规矩所有调用必须显式设置max_tokens可以是合理推算上限但绝不能写-1或无限。另一个办法是给每个账户设置预算告警走到80%就暂停任务人工确认后才能继续。还有一点容易被忽视便宜模型的隐性成本。有些模型单次调用很便宜但错误率高错误答案会转人工人工处理成本远高于API费用。我们后来算总账的方式是总成本等于API调用费加上人工复核成本乘以错误率。按照这个口径最便宜的模型往往是总成本最高的模型。6.3 评估偏差自动评估与人工复核的差距用LLM自动评估大样本结果能省大量人力但自动评估和人工判断之间有系统性差距。我们抽了2000条人工复核发现自动评估对“事实正确但表达别扭”的答案误判率很低但对“虚构了引用来源但整体读起来合理”的答案漏判率明显偏高。如果完全依赖自动评估金标集里会混入一批“看似正确实则错误”的样本后面的模型训练和评估都会被污染。所以现在的流程是自动评估做初筛把最有争议的样本自动评估给出中高分数但模型自评分高、logprob又不够高的捞出来人工复核。抽样比例虽然只有5%到8%但反馈进金标库之后对置信度校准曲线的修正非常明显。6.4 数据安全红线脱敏、权限与合规调外部API之前所有真实用户问题都要经过脱敏处理姓名、手机号、地址、身份证号一类的PII字段用占位符替换。内部知识库的敏感文档不能直接发给外部API即使供应商声称不存储数据这种信任也要有书面协议兜底。实验里我们还专门训练了脱敏检测器在发送前自动扫描请求内容命中规则就直接拦截宁可多拦不错放。权限方面API密钥全部走密钥管理系统运行环境通过secret注入不写进代码仓库也不打进镜像。不同小组成员开独立子账户避免一个人拿到全部密钥。这次的Docker API权限报错其实也是权限管理的一部分环境隔离清晰排查问题会快很多。7. 写在最后我给所有做LLM应用的人几点体会这轮实验跑下来我自己最大的体会是大模型是一个能力很强但嘴上没谱的实习生你可以让它快速处理80%的常规任务但永远不要因为它自信满满就免检。置信度有价值的不是“模型说它有多确定”而是“我们通过大规模实测摸清了这个确定程度的真实水分”然后把它当成工程参数来看待。建议所有正在做LLM应用的团队哪怕预算有限也花一两万次调用跑一轮自己的校准测试。不需要像我这次一样做到50万次但测试集一定要包含代码、数学和事实类问题并且单独统计因为这三个领域的置信度虚高问题最严重。测试完再把logprob、温度、模型版本、prompt指纹这些元数据都保留下来两个多月后回看你会发现自己模型的校准曲线可能已经漂移了不少。最后分享一个小技巧给每次API调用生成一个唯一request_id重试时复用同一个id。这看起来是个小事但在追溯错误答案、比对置信度波动、清洗重复数据时帮了大忙。这次50万次实验能在一周内完成分析很大程度上就是靠这个看似不起眼的字段把数据关系串起来的。
返回列表