多模型兜底前,先测错误是否相关
文章指出,不同供应商的模型可能在相同输入上同时出错,换模型重试并不必然提升答案可靠性。作者提出测量模型错误相关性,并将冗余失效检查纳入测试,但摘录未展示具体实现。
AI 深度解读
给 AI 应用接上第二家 LLM 服务商,不等于给错误答案买了保险。作者提醒:不同模型可能在同一批输入上拒答、编造引用,或误读表格。主模型答错,备用模型再答一次,结果可能只是多花一份钱。
这篇文章值得读的地方,是把「多模型应该更可靠」变成了一个可以验证的问题:失败集合重叠多少,模型更新后覆盖是否缩水,以及哪些检查应该交给确定性的程序。它提供了做法,但没有给出跨模型实测数据,结论需要带着这个前提看。
换了服务商,为什么还会一起答错
备用模型能补救主模型,前提是它能处理主模型失败的输入。不同公司的名字,只能证明供应商不同,证明不了错误互补。
作者列出了四股推动模型趋同的力量:
- 训练数据来自大量重叠的公开网页,模型掌握的事实和偏见可能相近。
- 人类反馈强化学习(RLHF)等后训练方法,会奖励相似的礼貌、谨慎、乐于助人的回答方式。
- 模型蒸馏会利用其他模型的输出训练,直接传递部分行为。
- 团队围绕相同的公开评测优化,容易形成相似的答题偏好。
这些解释有合理性,但原文没有展示各家的数据重叠比例、蒸馏关系或具体实验。把不同模型描述成相近先验上的两次微调,是作者的概括,不能当成已验证的模型谱系。
这里也要分清故障类型。原文针对的是内容错误:同样的幻觉、拒答和理解偏差。第二家服务商能否缓解接口不可用、限流等问题,是另一项需要单独验证的能力。
服务商不同,不能直接推导出内容错误彼此独立。
别先数模型,先算失败集合重叠多少
作者建议,把同一套评测题分别交给两个模型,记录每题是否通过,再计算失败集合的 Jaccard 相似度。
下面的函数解决的是:两个模型失败过的所有题目里,有多少题是双方一起失败的。
def failure_overlap(results_a, results_b):
"""results: {prompt_id: passed_bool} from your eval harness"""
failed_a = {k for k, v in results_a.items() if not v}
failed_b = {k for k, v in results_b.items() if not v}
shared = failed_a & failed_b
union = failed_a | failed_b
jaccard = len(shared) / len(union) if union else 0.0
return {
"failed_a": len(failed_a),
"failed_b": len(failed_b),
"shared": len(shared),
"jaccard": round(jaccard, 3),
}
重点看 len(shared) / len(union):分子是共同失败数,分母是至少有一个模型失败的题目数。结果接近 0,说明失败输入较少重叠;接近 1,说明两个模型经常在相同位置栽跟头。双方全部通过时,代码返回 0.0,不能把它解释成已经证明了错误互补。
评测之前,还必须保证两份结果覆盖相同的 prompt_id,并采用一致的通过标准。否则,集合差异可能只是漏跑题目。
比数字更有用的是打开 shared 对应的输入。作者认为,模糊指令、边界格式,以及安全回答与任务要求冲突的情况,往往集中在这里。这是经验判断,原文没有列出失败样本。
对主备链路,我还会补看一个方向性指标:主模型失败的题目中,备用模型救回了多少。Jaccard 描述双方的重叠程度,却不能单独回答「这个备用模型对当前主模型有多大帮助」。
CI 可以盯住变化,但别把不同当成正确
模型服务可能在同一个 API 端点后更新,之前测出的互补性会过期。作者因此建议,把多样性检查放进持续集成(CI)。
这段测试检查一批原本回答不同的边界题,是否开始出现过高的一致率。
EDGE_CASES = [
# prompts both providers currently handle differently
]
def test_providers_stay_diverse(run, judge, threshold=0.9):
a = run(model="primary", prompts=EDGE_CASES)
b = run(model="secondary", prompts=EDGE_CASES)
agree = sum(1 for x, y in zip(a, b) if judge(x, y) == "same")
rate = agree / len(EDGE_CASES)
assert rate < threshold, (
f"providers agree on {rate:.0%} of edge cases; "
"fallback no longer provides independent coverage"
)
要看清 threshold=0.9 和严格小于的断言:一致率达到 90% 就会失败。这个阈值只是示例,原文没有说明它经过校准。EDGE_CASES 也必须先填入实际题目,空列表会导致除零;run 和 judge 则需要接入自己的评测系统。
作者给出的判断方式包括精确匹配、schema 比较,以及第三个模型评判,并倾向把精确匹配作为默认选项。但精确匹配对措辞和格式敏感,模型判官又可能误判语义是否相同,需要按任务选择。
更关键的是,一致率并不等于准确率。两个模型可能一起答对,也可能一起答错;回答不同,也可能只是 JSON 字段顺序变了。因此,这个测试适合发出调查信号,不能仅凭失败就宣布备用模型失效。它必须和正确性评测放在一起看。
我的判断
我认可作者把注意力从供应商数量拉回失败样本,也认可把正则、JSON Schema 和数据库查询放进模型链路。这些检查不依赖模型的训练过程,能提供不同来源的约束。
但它们覆盖什么,就只能保证什么。JSON Schema 可以检查字段和类型,检查不了字段里的事实是否正确;数据库查询也取决于数据本身是否可靠。原文称能明确命名的失败类型通常占多数,却没有提供数据,这一点只能当成经验之谈。
作者对错误独立性的表述也偏强。备用模型发挥作用,并不要求错误完全独立,只要它能补上一部分主模型的失败,就可能有价值。是否划算,还要结合新增延迟、调用成本和成功补救数量判断。
该追求的是能验证的互补覆盖,而不是为了不同而不同。
相比再接一家模型,确定性校验更适合处理格式、字段约束和已有数据核对;对于开放式内容的事实与推理错误,文章没有给出足够证据,证明哪种模型组合更有效。
能拿来做什么
- 给现有 AI 功能整理一套带通过标准的评测题,纳入真实失败输入,让主模型和备用模型跑同一批题,再计算 Jaccard 和备用模型的补救比例。
- 如果 Node 服务需要模型返回结构化数据,就先用 JSON Schema 检查必填字段、类型和枚举;涉及已有业务记录时,再核对数据库中的值。
- 把已知存在差异的边界题加入 CI,并同时保留正确性检查;出现告警后,先区分格式变化、能力改善和共同失败增加。
- 为主备调用明确切换条件。超时、校验失败和内容错误需要分别处理;如果无法识别主模型已经答错,备用模型即使能答对,也可能根本不会被调用。