
我最早注意到这个问题是在一次药企RAG项目的验收评审会上。同事端着那份基于真实语料整理的多选题评测报告走进会议室宽松评分95分现场气氛一度相当轻松。但业务负责人追问了一句“你们这个评分标准能不能接受某个选项漏选但其他选项全对”会议室安静了两秒。我把评分口径从“宽松匹配”切到“全对才算对”之后同一个测试集的分数直接掉到85分。这10分的落差不是模型在测试时碰巧状态不好而是我们对“到底什么叫答对了”这件事的定义有分歧。这种分歧在药企场景里非常要命。药企语料不像通用领域的百科问答它的答案往往是一组离散选项比如“下列哪些情况禁止使用本品”“以下哪些属于不良反应”这些题目天然适合用多选题来评测。但如果验收RAG系统时只盯着一个宽松口径的准确率很多踩线的错误会被掩盖掉而上线之后面对真实患者的提问时一个漏选就可能变成安全事故。这篇文章就是把这次实测的完整过程、两套评分标准的设计逻辑、以及我后来整理的验收方案展开讲清楚给正在做RAG知识库落地、尤其是医疗医药领域的朋友一个可以直接参考的评测框架。1. 为什么要在药企真实语料上做这场评测1.1 药企语料和通用知识库的区别在哪里药企场景的RAG知识库语料来源通常是说明书、注册文件、质量标准、临床研究总结、文献摘要、内部培训材料和检查记录。这些文档有几个非常鲜明的特点。第一术语密度极高一个实体往往对应多个写法。比如“对乙酰氨基酚”在说明书里可能写作“扑热息痛”在文献摘要里又变成“APAP”在大模型内部向量化的时候这些写法是否能被正确召回本身就是一个隐藏的坑。第二答案粒度细到离谱。说明书里“禁忌”和“注意事项”是两节但在文本上经常只差一句话不良反应的发生率可能写作“常见≥1/100至1/10”而不是“5%”这就给生成模型留下了很大的解释空间。如果评测时不给模型一套严格约束的评分口径模型很容易产出一个“看起来对但经不起推敲”的答案。第三容错率极低。通用场景答错一个知识点用户顶多觉得体验差一点药企场景里患者可能会照着答案做决策。所以评测标准必须能区分“答得还行”和“答得完全正确”这就直接指向了评分口径的设计问题。1.2 这场实测的起点一张高分开出的“上线通行证”项目进入验收阶段时负责评测的同事先做了一版测试集题目全部来自真实的电话咨询记录和线上问答渠道类型覆盖说明书查询、适应证确认、用法用量核对、不良反应报告等。其中多选题占比大约三成这是药企客服问题的典型结构——用户问“我吃这个药的时候能不能同时吃感冒药”翻译成结构化知识就是“该药品与哪些药物存在相互作用”的多选判断。第一轮评测跑下来宽松评分95分。这是一个让人很兴奋的数字但在场的医学顾问翻了几条模型输出之后皱着眉头说了一句话“这几题的答案虽然都带上了正确选项但漏了一个更关键的选项如果患者只看到这些会出事。”于是我们把评分逻辑改成严格模式同一份测试集、同一个模型、同样的检索管线分数变成了85分。这个问题的价值不在于“95还是85”而在于它暴露了一个事实评测口径不一致时同一个RAG系统会给人完全不同的可靠性印象。1.3 评测集和语料的构成说明为了让结论更有参考价值我把评测集的构成说明一下。测试集一共300道题其中多选题120道单选题180道。多选题按临床场景进一步切分禁忌证判断、相互作用查询、不良反应筛选、用法用量核对、储存条件和有效期判断。金标准答案由两位在职医学顾问独立标注遇到不一致的选项组经讨论后统一口径。语料侧知识库包含了最新版说明书、公开的临床指导原则、公司内部产品培训材料、经过脱敏处理的文献摘要总计约2.3GB文本。向量检索采用混合检索方式关键词检索和语义向量检索并行重排后再送给大模型生成。这些都是RAG知识库的常规配置不算特殊。特殊的是评测方式——我坚持用两套评分规则跑了一遍而不是只看一个分数。2. 两套评分标准的设计多选题不是“答对多少”的问题2.1 宽松评分规则95分是怎么来的先说明宽松评分规则的细节因为很多人理解的“宽松”和实际上的“宽松”并不一样。在我们的定义里宽松评分遵循三个原则模型输出的选项集合与金标准完全一致得满分。金标准有多个正确选项模型输出包含其中一部分但未全选按“命中正确选项数 / 金标准正确选项数”给比例分。模型输出了金标准之外的干扰项额外扣分但扣分后不出现负分。举一个具体例子。金标准答案是A、B、C三个选项模型输出是A、B。宽松评分下命中2/3得0.67分。如果模型输出了A、B、D其中D是干扰项先按命中2/3折算0.67再扣除干扰项D的权重。最终得多少取决于扣分系数怎么设我们当时设的是每多选一个错误选项扣0.2分所以这道题的得分是0.47分。这种评分方式在通用RAG评测里非常普遍它本质上认可“部分正确”的价值。95分就是在这样的规则下跑出来的模型大部分时候都能命中至少一半的正确选项丢分主要来自漏选和少量多选。2.2 严格评分规则把“选对但没选全”当成错误严格评分规则只有一条模型输出的选项集合必须与金标准完全一致多选、少选、错选任何一项整题记为0分。同样是金标准A、B、C输出A、B得0分输出A、B、D得0分输出A、C得0分只有输出A、B、C才算1分。这个规则看起来很粗暴但它在药企场景里有明确的业务依据。想象一个患者问“服用本品期间需要慎用的药物有哪些”模型答出了其中两种漏掉了禁忌等级更高的第三种患者可能因此发生药物相互作用风险。这个时候“部分正确”在业务上等于“不正确的完整答案”。我在设计严格评分规则的时候还顺手加了一个中间档——也就是“不允许错选和多选但允许少选”。也就是说输出A、B可以给0.5分但输出A、B、D直接0分。这个档位更贴近临床应用多选的危害大于漏选因为多选意味着模型主动给出了错误信息漏选至少没有主动产生错误。这份评测里中间档跑出来的分数是89分介于95和85之间三个分数放在一起能更清楚地看出系统真实的可靠性边界。2.3 评分规则转换后分数的落差到底意味着什么两套评分规则的差异和题目分布直接挂钩。可以做一个粗略的量化分析120道多选题宽松和严格之间的分差是10分换算成题目数量大约有12道题处于“部分命中的可给分区间”。也就是说约10%的多选题存在候选选项召回不全的问题——模型能定位到正确答案所在的段落也能解析出部分正确选项但没有拿到全部。这里有个关键结论**宽松评分把这个10%的问题定义成“部分正确”严格评分则把它定义成“错误”。**从模型能力角度看系统其实没有变化变的是业务方对可靠性的容忍度。做RAG验收时最怕的不是分数低而是不清楚这个分数是用什么口径算出来的。我们需要用两套口径同时呈现让决策层自己判断哪些错误可以容忍哪些不能。为了让实现更清晰我顺手写了严格评分和中间档的判定逻辑Python伪代码供参考def score_multiple_choice(gold: set, pred: set, mode: str) - float: if gold pred: return 1.0 if mode strict: return 0.0 if mode lenient_partial: # 不允许错选但允许漏选 if pred - gold: # 存在金标准之外的选项 return 0.0 return len(pred gold) / len(gold) if mode lenient_full: # 错选扣分漏选给比例分 if pred - gold: penalty 0.2 * len(pred - gold) else: penalty 0.0 acc len(pred gold) / len(gold) return max(0.0, acc - penalty) raise ValueError(funknown mode: {mode})3. 85分背后的失败模式拆解误差到底藏在哪一层3.1 多选题漏选检索召回不足还是模型决策保守严格评分掉分的那12道题我全部拉出来做了错误归类。归类结果很有意思漏选占了大头。漏选的直接原因一般是两种。第一种是检索层的问题向量检索返回的片段里缺少某个正确选项对应的知识块。比如有一道题问“哪些患者禁用本品”金标准包括“有严重肝功能不全者”“对本品任一成分过敏者”“正在使用单胺氧化酶抑制剂者”三组。检索返回的结果覆盖了前两组知识块但“单胺氧化酶抑制剂”这个信息只出现在某个文档的脚注里向量召回时相似度排序排在top8之外重排也没把它捞回来。模型在生成时根本“看不见”这个选项自然不可能输出它。第二种是生成层的保守策略。有些题目检索片段确实包含了全部正确选项但模型最后还是只输出了其中一部分。我观察到的规律是当检索片段中出现相互矛盾或条件语句很复杂的文本时模型倾向于只输出它“最有把握”的选项把“可能对但不确定”的选项丢掉。这在对话体验层面不一定坏但在多选题评测里就是实打实的漏选错误。要定位到底是哪一层出错最直接的办法是看检索结果的top_k命中情况先检查金标准每个正确选项对应的文本块是否出现在检索返回结果中如果出现了问题大概率在生成层如果没出现问题就在检索层。3.2 完全选错知识定位偏差的典型案例完全选错的题数量不多但每道都值得单独复盘。我挑一个最有代表性的例子。有一道题问“下列哪些属于该药品的不良反应”金标准答案是“恶心、头晕、皮疹”其中“头晕”在说明书里的表述是“偶见头晕发生率0.1%-1%”。模型输出的是“恶心、皮疹、眩晕”。问题就出在“头晕”和“眩晕”的表述差异上。金标准标注者依据说明书原文用了“头晕”这个词模型从检索到的另一个来源的文献摘要里看到了“眩晕”这个表述并且认为二者在医学上是同一语义于是替换了选项。但评测规则是字面选项比对“眩晕”不等于“头晕”严格评分直接判错。这个案例暴露的不是简单的“选项字面不一致”问题而是知识库内多来源文档术语归一化不够。如果知识库做过分词标准化或者检索时配置了同义词扩展这道题大概率能答对。但药企知识库往往由多类来源拼合而成每个来源有自己的术语习惯RAG测评需要把这部分错误单独列出来不要和模型能力混为一谈。3.3 医生视角和算法视角的差异同样的答案不同的判断第三类情况最微妙——医生评估时觉得答案没问题但严格评分判错。举个例子。金标准里有一个选项是“半衰期约3.5-4.5小时”模型输出的是“半衰期约4小时”。从临床角度讲4小时落在3.5到4.5的区间内医生会认为答案准确。但严格评分只做集合比对两个表达不一致分数就是0。这种错误在宽松评分里会折算部分分数但在严格评分里一刀切。我后来和医学顾问讨论这类案例时达成了一个共识**严格评分的目的是筛选“能在系统层面稳定复现准确答案”的能力而不是判断“某个答案是否具备医学合理性”。**这两者的边界必须分清楚否则评测结果会变成医生和算法的相互不理解。正因为有这类“语义等价但字面不同”的案例存在我建议药企评测组在严格评分之外再单独维护一个“医学等价答案池”把已知的等价表述收录进去。评测时先做字面匹配匹配不上再去池子里查等价表述命中也算正确。这相当于给评测系统加了业务知识层能减少一部分“看起来不合理”的误杀。4. 只盯一个分数的陷阱RAG验收的常见坑4.1 单一指标的“虚高”幻觉是怎么产生的95分单独看很优秀但它掩盖了三类问题一是10%的多选题存在部分命中二是评测集本身的题目分布偏向说明书原文查询对推理类问题覆盖不足三是宽松评分默认“部分正确”有价值但药企业务不一定认这个价值。我在不同项目上反复验证过当评测集数量少于100题时宽松评分的波动范围可以接近10个百分点。因为题目总量少一道多选题的判分差异就会显著拉高或拉低整体分数。如果验收时只看一个总分很容易被这个随机波动误导。正确做法是看分数的话要看三组数宽松分、严格分、中间档分。三个数字之间的差值本身就是重要的诊断信息。宽松和严格的差值很大说明系统存在大量“部分正确但不完全正确”的输出中间档和严格分差值大说明错误大多来自多选或错选安全风险更高。4.2 评测集偏移分数不反映真实场景还有一种常见误判叫“评测集偏移”。很多人做RAG评测时题目的编写依托的是知识库已有文档比如从说明书里摘抄原句改写成问题那么在检索环节原文召回的概率天然偏高因为问题文本和答案文本在向量空间里高度相似。这种题目测的是模型“能不能记住原文”而不是“能不能回答用户真实会问的问题”。药企真实用户的提问方式和员工整理测试题的提问方式很不一样。真实提问往往是口语化的“我吃了这个药有点恶心正常吗还能不能继续吃”“青霉素过敏能吃这个头孢吗”而测试题往往是“本品常见不良反应包括以下哪些选项”“头孢菌素类药物的禁忌证包括”这两种问法在检索阶段的表现差异很大。为了对抗评测集偏移我们把大约30%的测试题设计成了“问句重写”模式先由标注人员用口语重写说明书里的事实型问题再由医学顾问确认改写后的题目是否语义等价。这样至少可以让评测集里有一定比例的真实问法分布。4.3 除准确率外这类指标更应该在验收里固定下来我在药企RAG验收中除了准确率之外一定会固定记录三类指标。第一类是答案层面的忠实度也就是模型输出是否严格基于检索片段有没有输出知识库里不存在的细节。这个指标用来对抗幻觉。在多选题场景里忠实度可以进一步细化为“错误选项是否来自检索片段之外”如果模型输出了一个知识库里根本没有的选项说明生成过程跑偏了。第二类是证据覆盖率即正确答案对应的关键信息是否出现在检索返回结果里。前面提到的漏选案例本质上就是证据覆盖率不够。这个指标算起来很简单金标准的每个正确选项对应原文位置能否在检索返回的top_k片段里找到。如果正确答案靠前但final准确率不高问题在生成层如果正确答案根本不在检索结果里打断一下是在检索层就有缺失。第三类是低置信度拒绝率。这个指标统计的是模型遇到不确定问题时主动说“据现有资料无法确认”的次数。药企场景里一个诚实的“我不知道”远比一个自信的错误答案有价值。如果严格评分85分的同时低置信度拒绝率不到2%我会认为系统的风险反而更高因为它经常在不该给答案的时候强行输出。5. 一套更适合药企场景的验收方案5.1 按业务风险分层设定验收门槛经过了这次实测我把药企RAG验收的思路调整成了“按风险分层”。不同的问题类型对应的容错空间完全不同不能用一个统一分数线来卡。风险等级问题类型示例验收门槛额外约束A类高危禁忌证、药物相互作用、过敏警告、剂量调整严格评分≥90且禁忌相关零漏报每个答案必须引用说明书原文块B类中危适应证、不良反应、用法用量核对严格评分≥85中间档≥90证据覆盖率≥95%C类低危科普解释、文献综述、药品储存宽松评分≥85即可忠实度≥90%A类设定“零漏报”不是因为模型能保证零漏报而是因为漏报的代价实在是业务无法承担的。实际操作中我们会单独从测试集里抽出50道禁忌证多选题人工逐条判断是否有漏选这个检查不经过自动评分脚本。B类是绝大多数日常咨询的类型用严格评分做基准线85分是可以接受的下限。如果低于85分说明系统在“给出完整且准确选项集合”这项核心能力上还有明显缺口建议先优化知识库再谈上线。C类问题即使答得不完整用户也不会因此面临安全风险所以宽松评分85分就够了。把C类评测放到宽松口径下主要目的是确认模型的表达流畅度和基础知识掌握度。5.2 更新线上反馈闭环不是评测完就结束评测不是上线前的验收动作上线之后也需要持续跑。我建议药企RAG项目专门维护一套“回归测试集”它由三部分组成原始人工标注题占50%线上真实问题脱敏后转化的题目占30%定期从知识库新版本中抽取的高频新问题占20%。每次模型更新、知识库更新、检索参数调整都先跑一遍回归测试集对比宽松分、严格分、中间档分的变化。理想状况是三个分数同步上涨或持平如果一个分数上涨但另一个分数下跌说明这次改动改变了系统的“答题风格”需要回退或补充调优。另外线上日志的间接信号比任何离线评测都更早反映问题。比如模型输出被用户复制后去搜索引擎查证的次数增加说明模型给出的答案不够权威用户不放心又比如同一个问题在短时间内反复咨询说明上一次回答没有解决用户需求。这些信号不直接等于评测分数但和真正的业务反馈强相关建议纳入产品周报。5.3 评测集设计要覆盖哪些内容一份可直接落地的检查清单药企RAG评测集设计我总结了一份自用的检查清单按检查项逐条打分可以避免评测集偏移和覆盖不足。第一题目来源占比要合理。真实咨询记录转化来的题目不低于40%专家手工编写的业务场景题不超过30%知识库原文改写题不超过30%。第二每张测试卷必须包含特定题型比例。多选题占比建议在30%-40%之间因为这类题目最能反映系统的可靠边界。全是单选题的评测集会把明显的漏选问题隐藏掉。第三必须包含否定问句和条件限制句。比如“以下哪些情况不推荐使用”“高血压患者使用本品时需要注意什么”这类题目。否定问句是RAG系统最常见的失误场景如果评测集里没有这类问题准确率会显得虚高。第四必须设置干扰候选。多选题里除了正确答案还要放一些与原文字面接近但语义错误的候选选项。这样能测出模型是否真正理解知识语义而不是机械匹配字面重合度。第五知识库更新版本之后评测题不能一成不变。新说明书删除了旧条款、新增了黑框警告对应题目的金标准答案也要同步修订。这个维护工作必须排进项目常规流程不然评测集本身会过期。5.4 人工复核的权重不应该被自动化完全替代大模型评估和自动评分脚本能大幅提高评测效率但在药企场景我坚持保留人工复核环节尤其是A类和B类题目。做法很简单每次评测从测试集中抽出15%的题目由医学顾问按“业务可接受”口径去复核。业务可接受的意思是不要求模型输出与金标准完全一致而是判断模型输出是否会导致医生或患者做出错误的安全性决策。这个判断维度是自动评分脚本很难覆盖的。我在这次实测中也做了人工复核对比。按宽松评分95、严格评分85但医学顾问给出的“业务可接受率”是92%。也就是说有一部分严格评分判错的答案医生看了之后认为不会造成实质危害反过来也有一部分答案虽然自动评分判对了医生认为表述方式容易造成误导。所以严格评分是底线标尺人工复核是纠偏机制两者不是替代关系是互补关系。6. 从这次实测中沉淀下来的验收原则做完这次评测总结的时候我一直在想一个问题验收RAG系统到底在验收什么是验收一个分数还是验收一套对失败模式的理解我现在更倾向后者。**评分口径的差异本质是失败容忍度的差异。**宽松评分把漏选当作部分正确严格评分把漏选当作错误中间档把多选当作错误而允许漏选。企业想清楚自己能容忍哪类失败再选对应的评分口径这个优先级比“分数高低”重要得多。药企场景里我倾向以严格评分为基线中间档作为参考宽松分只是上限展示。另外一个比较深的体会是**多选题出分容易、出解释难。**扣了分之后一定要往回追归类是检索层还是生成层是术语归一化问题评测集本身的问题还是模型策略保守的问题。不做归类的评测得到的就是一个单纯让人高兴或让人难过的数字对系统改进几乎没有帮助。现在再有人来问我RAG知识库评测怎么做我会先反问一个问题你的题目里有多少多选题如果占比不超过三成先把题目结构补齐再谈指标。多选题的漏选是RAG系统最典型、最隐蔽、也最能影响业务安全感的失败模式它不会体现在单选题为主的评测报告里但在真实使用场景中无处不在。把多选题放到评测中心并同时用宽松、严格、中间档三种口径跑分数你才能真正知道你的知识库在哪个粒度上是可靠的。