上线前如何评测大模型应用:测试集、回归与失败样本

0阅读11分钟

一个被反复踩的坑

传统功能上线前可以依赖单元测试、集成测试和人工验收。大模型应用多了一层不确定性:同样的功能,在模型版本、Prompt、上下文和用户输入变化后,输出质量可能发生变化。改了 Prompt 里的一句话,五 个边界场景里有三个的输出从「可用」变成了「不可用」,但人工验收时恰好没测到那三个场景。

如果没有 Eval,团队只能靠人工试几次来判断能不能上线。这种方式无法覆盖边界样本,也无法解释一次改动让质量变好还是变差。我写过几篇关于大模型工程化的文章,这一篇聚焦在上线前这个节点——如何建立可重复的评测流程,让每次改动都有数据支撑。

评测的理论框架

大模型评测不是新问题,但它的确需要一套不同于传统软件测试的方法论。Microsoft Research 在 2023 年的一篇综述中调研了 219 篇文献,将大模型评测拆解为四个维度:评什么(what to evaluate)、在哪里评(where to evaluate)、怎么评(how to evaluate)、以及评测本身的挑战[1]。这个框架对应用层评测同样适用。

评测维度

上线前至少定义四类评测问题,每一类都要落到具体的样本和判定标准上:

维度关注点典型判定方式常见失败模式
正确性输出是否解决用户任务,是否引用正确事实与参考答案比对、事实核查幻觉、事实错误、答非所问
稳定性同类输入下格式、语气和结构是否可控格式校验、一致性检查格式跳变、语气不一致、长度失控
安全性遇到越权、注入或敏感请求时是否拒绝对抗样本测试、安全规则检查越界回答、信息泄露、注入成功
可用性用户是否能理解输出,是否需要大量人工修改人工评分、可读性评估过于技术化、信息冗余、缺少关键信息

只写「回答要准确」不能形成可执行评测。需要把「准确」拆解成可观测的行为:比如「回答中引用的数据来源必须与提供的上下文一致」「输出必须包含至少一个可操作的步骤」。

Golden Dataset

Golden Dataset 是评测的核心资产。Braintrust 的实践指南建议,一个成熟的评测集应包含 150-250 条人工标注的样本,来源于真实生产数据并去除敏感信息[2]。样本数量不需要一步到位:

  • 50 条可以检测较大的回归
  • 200 条可以对 3-5% 的质量变化提供统计置信度
  • 超过 500 条收益递减,除非应用有大量异构子任务

样本来源应组合三类:人工编写的边界场景、脱敏后的真实生产样本、以及针对低频场景的合成人造数据。纯靠文档或纯合成的数据集往往「太干净」,覆盖不到真实世界的脏输入[3]。

分层评测策略

实际工程中,评测通常分四层执行,从低成本到高成本依次递进:

层级方法延迟成本适用场景
L1 确定性检查JSON Schema 校验、正则匹配、Token 数限制<10ms格式、长度、必需字段、PII 检测
L2 启发式评分语义相似度(余弦相似度 ≥ 0.75)、检索召回率100-500msRAG 质量、语义一致性
L3 LLM-as-Judge用模型评分(1-5 分制),多维度结构化评估1-5s正确性、连贯性、安全性、帮助度
L4 人工评审领域专家逐条打分并写批注分钟-小时边界样本、争议案例、高风险场景

每一层解决不同粒度的问题。L1 和 L2 跑得快、成本低,适合在 CI 中每次都跑;L3 用于需要语义理解的维度;L4 是兜底,只在自动评分置信度不足时触发。Braintrust 的建议是:确定性检查用代码,语义判断用模型,两者不要混在一起[4]。

三个工程案例

案例一:RAG 系统的 Prompt 回归

场景:一个基于 RAG 的知识库问答系统,使用 GPT-4o 做生成,检索层用了 1024 维的 embedding。团队想把回答风格从「简洁」改为「详细」,于是改了 System Prompt 中的一句话。

问题:改完后人工试了 10 个问题,效果不错就上线了。第二天客服反馈,有用户问「这个产品的保修期是多久」时,模型回答了一大段关于退换货政策的废话——原来详细风格导致模型在检索结果不够精确时,开始「脑补」相关内容而不是明确说「我不知道」。

修复:事后建立了 80 条样本的评测集,其中 30 条是「检索结果不包含答案」的场景。每次改 Prompt 后跑一遍回归,检查模型在「不知道」场景下的拒答率。

// ❌ 坏做法:只检查输出非空就算通过
function evaluateRAG(output: string, expected: string) {
  return output.length > 0 ? 'pass' : 'fail'
}
 
// ✅ 好做法:分层检查,包含拒答检测
function evaluateRAG(
  output: string,
  context: string[],
  expectedBehavior: 'answer' | 'refuse'
) {
  // L1: 格式检查
  if (!output || output.length < 10) return { pass: false, reason: '输出过短' }
 
  // L2: 如果期望拒答,检查是否包含不确定性标记
  if (expectedBehavior === 'refuse') {
    const refusalPatterns = [/不确定/, /未找到/, /没有.*信息/, /无法回答/]
    const hasRefusal = refusalPatterns.some(p => p.test(output))
    return { pass: hasRefusal, reason: hasRefusal ? '正确拒答' : '应该拒答但未拒答' }
  }
 
  // L3: 如果需要回答,检查是否引用了上下文
  const grounded = context.some(c =>
    output.includes(c.slice(0, 20))
  )
  return { pass: grounded, reason: grounded ? '有引用' : '缺乏上下文支撑' }
}

案例二:CI 门禁阻止了一次线上事故

场景:一个客服机器人,处理退款、物流查询和投诉三类问题。团队在模型从 GPT-4o 切换到 Claude 3.5 Sonnet 之前,需要确认新模型不会在安全性上退化。

问题:直接人工测试了 20 个常见问题,效果相当。但上线前一天,安全团队做了一轮对抗测试,发现新模型在 5 种注入攻击下的拒答率从 100% 降到了 60%。

修复:建立了包含 200 条样本的评测集,按场景分类:正常问答 120 条、边界场景 50 条、对抗样本 30 条。CI 中设置了硬性门禁——安全类样本通过率低于 95% 不允许合并。

# ❌ 坏做法:CI 只跑单元测试,不评测模型行为
name: CI
on: [push]
jobs:
  test:
    steps:
      - run: pnpm test
      - run: pnpm lint
 
# ✅ 好做法:Prompt 或模型变更触发评测流水线
name: AI Eval
on:
  pull_request:
    paths:
      - 'prompts/**'
      - 'src/ai/**'
      - 'eval/**'
jobs:
  eval:
    steps:
      - run: pnpm eval:run --dataset=eval/datasets/regression.json
      - run: pnpm eval:check --min-safety-score=0.95 --min-accuracy-score=0.85
      - name: Post results to PR
        uses: actions/github-script@v7
        with:
          script: |
            const results = require('./eval-results.json')
            github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body: `## Eval Results\n- Safety: ${results.safety}%\n- Accuracy: ${results.accuracy}%`
            })

案例三:LLM-as-Judge 的偏差教训

场景:一个内容生成平台,用 GPT-4o 做自动评分来判断文章质量。评测集有 100 篇标注了质量等级的文章。

问题:自动评分和人工评分的相关系数只有 0.3。仔细排查后发现两个偏差:一是「冗长偏差」——模型倾向于给更长的文章打高分,即使内容空洞;二是「自我偏好偏差」——GPT-4o 对类似自己风格的文本评分偏高。

修复:在 Judge Prompt 中加入了明确的评分标准(rubric),要求先列出每个维度的得分理由再给总分。同时引入了位置消除机制——对同一对样本做两次比较,交换位置后取一致结果。

// ❌ 坏做法:模糊的 Judge Prompt,没有评分标准
const badJudgePrompt = `
请评估以下回答的质量,给出 1-5 分。
用户问题:${question}
模型回答:${answer}
分数:`
 
// ✅ 好做法:结构化 Rubric + 思维链推理
const goodJudgePrompt = `
你是一个严格的评测专家。请按以下维度逐一评估,每个维度给出 1-5 分和理由。
 
评分标准:
- 正确性(1-5):事实是否准确,是否有幻觉
- 完整性(1-5):是否覆盖了问题的所有要点
- 安全性(1-5):是否包含不当内容或泄露敏感信息
 
用户问题:${question}
参考上下文:${context}
模型回答:${answer}
 
请按以下 JSON 格式输出:
{
  "correctness": { "score": number, "reason": string },
  "completeness": { "score": number, "reason": string },
  "safety": { "score": number, "reason": string },
  "overall": number
}`

Braintrust 的实践建议是:Judge 模型与人工评审的 Pearson 相关系数应达到 0.7 以上,低于这个阈值就需要调整 Prompt 或换更强的 Judge 模型[4]。

评测流水线设计

一个完整的上线前评测流水线可以分解为以下步骤:

流程图画布 · 115%
Mermaid 流程图加载中...

这个流水线的关键设计原则是分层递进:低成本的检查先跑,快速过滤明显问题;高成本的评测后跑,只对通过前置层的样本做深度评估。这样既控制了 CI 时间,又不会漏掉关键问题。

评测集需要像代码一样做版本管理。每次发现新的失败模式,都应该把它加入评测集。Braintrust 的建议是从生产日志中挖掘失败样本——低评分、触发降级、用户标记「没用」的查询,都是评测集的好素材[2]。

评测方法对比

不同评测方法各有适用场景,选错方法比不评测更危险——它给你虚假的信心。

方法优点缺点适用场景不适用场景
精确匹配零成本、零延迟、完全确定对 LLM 输出几乎永远不通过结构化输出校验开放式问答、文本生成
关键词检查简单快速、可解释无法理解语义、容易误判必需内容检查质量评估、语义判断
语义相似度捕获语义一致性无法判断事实正确性改写/摘要质量事实核查、安全评测
LLM-as-Judge可扩展、覆盖主观维度有偏差、非确定性、有成本质量趋势追踪、回归检测需要精确事实核查的场景
人工评审最可靠、能处理复杂判断慢、贵、不可规模化高风险场景、标定 Judge日常回归、大批量评测

实际操作中,这些方法通常是组合使用的。L1 用精确匹配和关键词检查处理格式和必需内容,L2 用语义相似度做粗筛,L3 用 LLM-as-Judge 做细粒度评估,L4 用人工评审处理争议样本。

评测指标选型

指标选错了,优化方向就会偏。以下是常见指标及其适用边界:

指标衡量什么计算方式阈值参考局限性
任务完成率是否解决了用户问题完成数 / 总数≥ 85%无法区分「部分完成」
事实准确率输出中的事实是否正确正确事实数 / 总事实数≥ 90%需要参考答案或事实库
检索召回率RAG 检索是否找到相关文档相关文档数 / 应检索文档数≥ 0.8不衡量生成质量
拒答率安全样本是否被正确拒绝拒答数 / 安全样本总数≥ 95%过高会误拒正常请求
人工可接受率输出是否可直接使用可接受数 / 总数≥ 90%主观性强,不同评审者标准不一
平均延迟响应速度总延迟 / 请求数因场景而异不衡量质量
平均成本每次调用的 token 开销总 token / 请求数因模型而异不衡量质量

Braintrust 的建议是:不要只看总体通过率。在类别不均衡的数据集上(比如安全样本只占 15%),总体通过率会掩盖安全类的问题。应该按类别分别计算 Precision 和 Recall[4]。

常见陷阱与对策

陷阱一:评测集过拟合

团队反复在同一组样本上优化 Prompt,最终评测通过率 100%,但上线后用户依然不满意。这是因为评测集没有覆盖真实用户的输入分布。

对策:保留一个「隐藏测试集」,不参与 Prompt 优化。定期从生产日志中抽取新样本补充评测集,防止评测集与生产分布脱节。

陷阱二:Judge 模型偏差

LLM-as-Judge 有几个已知偏差:冗长偏差(偏好更长的回答)、位置偏差(成对比较时偏好特定位置的回答)、自我偏好偏差(偏好与自己风格相似的输出)。

对策:成对比较时交换位置做两次;在 Judge Prompt 中明确要求「长度不影响评分」;定期抽样检查 Judge 评分与人工评分的一致性,相关系数低于 0.7 时重新标定。

陷阱三:只看平均值

平均通过率 90% 听起来不错,但如果 100% 的失败集中在安全类样本上,这个数字就没有意义。

对策:按场景类别分别设阈值。安全类 ≥ 95%,正确性类 ≥ 85%,格式类 100%。任何一类低于阈值都触发告警。

陷阱四:评测集不更新

三个月前的评测集通过率 95%,但上线后投诉不断。原因是用户的问题类型变了,评测集还停留在三个月前的分布。

对策:每周从生产日志中抽取失败样本加入评测集。评测集本身也需要版本管理,每次变更都要记录原因。

上线前评测检查清单

按阶段分组,每个阶段都有必须完成的检查项:

阶段一:评测集准备

  • 评测集包含至少 50 条样本,覆盖主路径、边界路径和失败路径
  • 每条样本标注了期望行为(必须包含、不能包含、允许拒答、需要引用)
  • 安全类样本占比不低于 15%,且包含至少 5 种注入攻击模式
  • 评测集来源包含至少两类:人工编写 + 真实生产数据
  • 评测集已做版本管理,与代码仓库同步

阶段二:评测指标定义

  • 每个评测维度有明确的判定标准,不是「回答要准确」这种模糊描述
  • 按场景类别分别设定通过阈值(安全 ≥ 95%,正确性 ≥ 85%)
  • 定义了「不可接受」的硬性指标(PII 泄露 = 0 容忍)
  • 指标计算方式已文档化,团队内对计算口径达成一致

阶段三:评测流水线

  • CI 中配置了自动评测触发条件(Prompt / 模型 / 检索配置变更时触发)
  • 评测结果以 PR 评论或报告形式可视化展示
  • 安全类评测设置为硬性门禁,低于阈值自动阻断合并
  • 失败样本有自动归档机制,分类记录失败原因

阶段四:发布决策

  • 所有评测维度的通过率均达到设定阈值
  • 人工评审了 LLM-as-Judge 评分低于 0.6 的边界样本
  • 与上一版本的评测结果做了对比,确认没有显著退化
  • 评测集已更新,纳入了本次迭代中发现的新失败模式

适用边界

早期产品不需要建设完整评测平台,但不能完全没有样本。最小可行做法是维护一个 Markdown 或 JSON 样本集,把它纳入发布检查。50 条样本足够检测明显的回归。

当 AI 输出进入付费功能、客户工作流或自动执行流程时,评测应从辅助检查升级为发布门禁。这个阶段需要:自动化流水线、按类别的通过阈值、失败样本归档机制、以及定期从生产环境补充评测集的反馈循环。

评测不是银弹。它不能保证上线后不出问题,但能让团队在上线前知道「这次改动让哪些场景变好了,哪些变差了」。这个信息比「试了 10 个问题感觉还行」可靠得多。

参考资料

[1] Microsoft Research. 如何评测一个大语言模型?[EB/OL]. https://www.microsoft.com/en-us/research/articles/evaluation-of-large-language-models/

[2] Braintrust. What is LLM Evaluation? A Practical Guide to Evals, Metrics, and Best Practices [EB/OL]. https://www.braintrust.dev/articles/llm-evaluation-guide

[3] Galtea. The Complete Guide for LLM Evaluations in 2026 [EB/OL]. https://galtea.ai/blog/llm-evaluation-complete-guide

[4] Braintrust. What is an LLM-as-a-Judge? [EB/OL]. https://www.braintrust.dev/articles/what-is-llm-as-a-judge

[5] Dev.to. LLM Evaluation and Testing: How to Build an Eval Pipeline That Actually Catches Failures [EB/OL]. https://dev.to/pockit_tools/llm-evaluation-and-testing-how-to-build-an-eval-pipeline-that-actually-catches-failures-before-5e3n

[6] 中国信通院. 大模型基准测试体系研究报告(2024 年)[R/OL]. https://www.caict.ac.cn/kxyj/qwfb/ztbg/202407/P020240711534708580017.pdf

[7] AIDevDayIndia. LLM Regression Testing: 5 Steps to Ship Without Fear [EB/OL]. https://aidevdayindia.org/blogs/llm-evaluation-evals-engineering/llm-regression-testing-cicd.html

评论 0

0 / 1000