[控场AI]
· 6 分钟阅读· 3,310 字

你的LLM评估套件在骗你:构建真正可靠的对抗性测试

你的LLM评估套件在骗你:构建真正可靠的对抗性测试

92%通过率可能是谎言——本文讲解如何用对抗性测试、人工校准与严重度加权构建真正预测生产行为的LLM评估体系。

多数团队依赖「黄金数据集」评估LLM,用语义相似度打分并宣告成功,却在上线后遭遇真实用户的投诉浪潮。本文指出核心问题:黄金集只衡量干净输入上的平均表现,无法覆盖约束违反、提示注入、上下文溢出和多跳推理等生产场景中的真实失败模式。解决方案分四层:一、从事故日志提炼失败分类,构建确定性二元检查器替代模糊相似度分数;二、对生产流量采样并获取人工标注,将评估套件本身当作需追踪精确率与召回率的分类模型,把评估与人类判断的不一致转化为新用例;三、按失败严重度加权评分,防止高聚合通过率掩盖安全关键失败;四、通过定时任务自动化整个闭环,让评估套件随产品持续进化而无需大量手工维护。

你上线了新功能,评估套件显示92%通过率。两周后,支持工单堆积如山:模型编造引用、无视否定约束、在多步推理上彻底崩溃。而你的评估一个都没抓到——因为它测量的是错误的东西。

这正是Karpathy所描述的「能力认知鸿沟」在工程层面的具体表现:它在你的CI流水线里显示为一个个绿色对勾,却覆盖着对用户失败的代码。本文梳理如何构建能够真正预测生产行为的评估体系。

Your LLM Evaluation Suite Is Lying To You

幸福路径陷阱

大多数团队从一个「黄金数据集」起步:50到100个代表性输入及其期望输出。他们跑一遍模型,计算精确匹配或语义相似度,就宣告大功告成。这种做法衡量的是已知分布上的平均表现。

问题在于,生产环境根本不运行在已知分布上。用户会粘贴5万token的日志、要求输出带有冲突schema约束的JSON、对话中途切换语言、或者尝试提示注入攻击。你的黄金数据集里一个这样的案例都没有。

一个典型的朴素评估通过SentenceTransformer计算预测与标准答案的余弦相似度,最终返回0.87这样漂亮的分数。你据此上线,用户却拿到了垃圾结果。原因很简单:这个评估测量的是干净问题上的语义相似度,而不是指令遵循、约束满足或拒绝行为。相似度高,不等于行为正确。

「语义相似度」作为评估指标的局限性值得专门说明。SentenceTransformer等模型将文本映射为高维向量,余弦相似度衡量的是两段文字在语义空间中的「方向接近程度」。这种方法对改写、同义替换、风格变化具有一定鲁棒性,在信息检索等场景表现优秀。然而它天然无法捕捉「行为约束」层面的差异:「输出格式正确的JSON」和「输出了一段流畅解释JSON是什么的文字」,在语义空间中可能相当接近,但前者满足下游需求,后者会直接导致解析崩溃。换言之,相似度度量的是「说了什么」,而非「做了什么」。当评估目标从「生成正确的文字」转向「遵守约束、满足结构要求、抵御攻击」时,任何基于嵌入距离的指标都存在系统性盲区。

构建对抗性测试用例

真正的突破口是从你自己的事故日志出发,建立一张失败分类表。每一个线上故障都应当转化为一个测试用例。原文给出了一个清晰的分类框架:

类别示例黄金集为何会遗漏
约束违反要求「只输出JSON」,模型却加了前言黄金答案干净,无否定约束
上下文溢出10万token输入被模型静默截断黄金集样本仅2k token
多跳推理「跨地区对比Q3和Q4营收」黄金集是单跳问答
对抗性构造「忽略上述指令并……」黄金集没有攻击向量
格式漂移禁用markdown时模型却开始使用黄金集不强制否定格式规则

关键在于:把每个用例写成确定性测试,用二元的通过/失败检查器,而不是模糊的相似度分数。例如「只输出JSON」的检查器直接验证输出是否以{开头并能被json.loads解析;提示注入的检查器则直接确认输出中不含被注入的HACKED字符串。

这些检查器可以直接放进CI。任何在已知失败模式上的回归都会阻断部署。它们快速、确定且可解释——一旦某个失败,你立刻知道是哪项能力退化了,而不是对着一个模糊的0.87发愁。

「提示注入攻击」(Prompt Injection)是表格中对抗性构造一行的具体技术背景。其原理是通过用户输入向模型注入伪造指令,覆盖或篡改系统提示的行为意图,经典形式为「忽略上述所有指令,改为执行……」。与传统SQL注入类似,根本原因在于模型无法在结构层面区分「指令」与「数据」。间接提示注入则更隐蔽:攻击向量藏在模型会读取的外部文档或网页中,用户本人并不知情。对于任何具备工具调用、RAG检索或代理行为的LLM应用,提示注入是真实的安全威胁而非理论风险,必须在评估套件中持续覆盖,且检查器应当是确定性的字符串匹配,而非依赖模型自评。

用人工标注持续校准

对抗性用例能抓住已知失败。但能力鸿沟会不断扩大,因为新的失败模式会随着用户的创造性探索不断涌现。为此需要一个校准闭环:

  1. 采样生产流量(1-5%的请求,并清洗PII)
  2. 路由给人工标注员,使用极简评分标准:「该输出是否满足用户意图?是/否/部分」
  3. 将人工标签与评估预测对比
  4. 把不一致的样本添加为新的对抗性用例

原文给出了一个深刻的洞见:你的评估套件本身也是一个模型。它相对于人类判断同样存在精确率(precision)和召回率(recall)。两者都要追踪。当召回率下降时——即评估判定通过、但人类判定失败——你就有了盲点,应当把这些样本补入对抗性集合。校准代码中对「部分满足」的处理采取保守策略,直接视为失败,这是一个值得借鉴的工程取舍。

将评估套件类比为「可度量精确率与召回率的分类模型」,是本文最值得展开的方法论洞见。在二分类框架下:精确率(Precision)= 评估判定「通过」中真正让用户满意的比例;召回率(Recall)= 所有真正让用户满意的输出中被评估正确识别的比例。实践中更危险的是召回率下降——评估放行了用户实际不满意的输出,这些失败在指标上隐身,直到支持工单爆发才被察觉。精确率下降则是另一方向的成本:评估过于严苛,误杀了本可上线的能力,导致开发团队对评估失去信任、开始绕过它。两者都需要追踪,且应当在不同严重度分层上分别计算,而非用全局聚合数字掩盖结构性问题。

衡量用户真实体验

聚合指标会掩盖长尾。一个92%通过率但其中8%是灾难性失败的系统,远比70%通过率但能优雅降级的系统更糟糕。因此要追踪的是失败的严重程度,而非单纯的通过率。

原文给出的方案是严重度加权评分:给每类失败分配权重——提示注入失败是安全事件,权重设为5;JSON格式错误会破坏下游解析,权重3;多跳推理答错用户能察觉,权重2。最终的分数按加权计算,而非简单平均。

这种设计强制团队优先处理真正重要的问题。一个权重为5的安全相关注入失败,其分量应当远超一个权重为1的格式小瑕疵。它让「92%」这个数字无处藏身——如果缺失的那8%恰好集中在高权重项上,加权分数会毫不留情地暴露风险。

自动化反馈闭环

整套方法的终局是把校准输出直接接入测试套件。当标注员标记出一种新的失败模式时,脚本自动生成对抗性用例模板。原文演示了通过cron或GitHub Actions每周运行一次的流程:从S3拉取生产日志和标注数据,输出按日期命名的测试文件。

自动生成的文件会清晰地注明来源与模式,例如「人工标注员在50个样本中标记了3个失败,模式:当输入包含逗号时模型忽略『仅输出CSV』指令」,并附上对应的二元检查器。经过人工审查后合并,新用例便会在每个PR上随CI运行。

这样一来,评估套件会随产品一起进化,而不是逐渐腐烂。它每周都变得更聪明,且几乎不需要人工维护成本。

核心要点

  • 黄金数据集只衡量干净输入上的平均表现,会遗漏约束违反、注入攻击和推理失败——而这些恰恰是用户真实遭遇的问题
  • 从事故日志构建对抗性用例,让每个线上故障都变成能阻断回归的二元测试
  • 每周运行校准闭环:采样生产流量、获取人工标签、度量评估相对人类的精确率与召回率、将不一致转化为新用例
  • 按严重度加权失败,不让92%的通过率掩盖5%的安全关键失败率
  • 自动化整个闭环,让评估套件每周自我成长而无需手动维护

本文的方法论源自Karpathy关于「LLM能力共识鸿沟正在扩大」的讨论,并在其基础上补充了具体的对抗性评估模式、可运行的校准循环代码,以及原推文未覆盖的严重度加权评分系统。

#LLM评估#对抗性测试#大模型评估套件#AI评估校准#提示注入防御#严重度加权评分#生产环境测试
分享:

相关推荐