LLM 应用的评估体系:Metrics、LLM-as-Judge 与 A/B 测试

前言

上一篇讲了 observability——能看到每次调用的细节。但光”看到”不够,你还要”判断好坏”

  • Prompt A 和 Prompt B 哪个回答用户问题更好?
  • 升级 embedding 模型后,检索质量是否真的提升了
  • 换 LLM 后,业务指标是否变化

这些问题没有标准答案。传统软件的单元测试只能验证输出符合预期,但 LLM 输出本质上不确定——同一个 prompt 两次结果可能不同。

这一篇覆盖:

  1. 5 类评估指标:从硬指标到 LLM-as-Judge
  2. 离线评估集:怎么构造 + 怎么跑
  3. 在线 A/B 测试:生产环境对比
  4. Braintrust / Ragas 实战

一、5 类评估指标

[Mermaid] 视觉化:

图 1:5 类评估指标

1. 硬指标(Hard Metrics)

适合答案唯一的场景:

import { ExactMatch, BLEU } from 'autoevals';

ExactMatch({ output: 'Paris', expected: 'Paris' });      // 1.0
BLEU({ output: 'Hello world', expected: 'Hello' }); // 0.5

适用:分类、命名实体识别、答案抽取(用工具调用做结构化输出)。

2. Embedding 相似度

适合答案开放但语义应相近

import { embeddingSimilarity } from 'autoevals';

const score = await embeddingSimilarity({
  output: '巴黎是法国的首都',
  expected: 'Paris is the capital of France',
});
// 0.92(语义接近)

陷阱:embedding 模型本身的偏差会影响评分结果,容易”自我循环”

3. LLM-as-Judge

用更强的模型给答案打分。生产 LLM 评估的主力:

import { LLMClassifierFromTemplate } from 'autoevals';

// LLM-as-Judge:用 LLM 当裁判评估输出质量
// LLMClassifierFromTemplate 需要自定义 promptTemplate 和 choiceScores
const judge = LLMClassifierFromTemplate({
  name: 'answer-quality',
  promptTemplate: `你是一个严格的评估员。给定预期答案和实际答案,判断实际答案是否正确且简洁。

预期:{{expected}}
实际:{{output}}

只输出一个选项:A(完全正确)或 B(不正确或不简洁)`,
  choiceScores: { A: 1, B: 0 },
  model: 'gpt-4o',  // 用更强的模型当裁判
});

const evalResult = await judge({
  output: '巴黎是法国的首都',
  expected: 'Paris is the capital of France',
});
// → { score: 1, choice: 'A' }

优点:能评估开放性回答,捕捉语义细节 陷阱

  • 评委偏差:LLM 评委有自己的偏好
  • 位置偏差:把”好答案”放在前面/后面会改变评分
  • 自评偏差:让 GPT-4 评 GPT-4 输出,分数偏高

缓解

  • 用多个评委取平均
  • 调换答案 / 期望的位置各评一次取平均
  • 比生产环境所用模型更强的模型当评委(如 GPT-4o 评 GPT-4o-mini)

4. 任务特定指标(Task-Specific)

RAG:Ragas 指标

Ragas 是 RAG 评估的事实标准:

  • Faithfulness(忠实度):答案是否忠于检索到的 context
  • Context Precision:检索的 chunks 是否相关
  • Context Recall:相关 chunks 是否都被检索到
  • Answer Relevance:答案是否回答了问题
import { evaluate } from 'ragas';
import { openai } from '@ai-sdk/openai';

const result = await evaluate({
  dataset: {
    questions: ['什么是 Transformer?'],
    contexts: [['Transformer 是一种...']],
    answers: ['Transformer 是 2017 年提出的...'],
    ground_truths: ['Transformer 是 Google 2017 年提出的神经网络架构...'],
  },
  metrics: [faithfulness, contextPrecision, contextRecall, answerRelevancy],
  llm: openai('gpt-4o'),  // 评委 LLM
  embeddings: openai.embedding('text-embedding-3-small'),
});

console.log(result);  // { faithfulness: 0.9, contextPrecision: 0.85, ... }

Agent:任务成功率

Agent 评估需要看工具调用 + 最终结果

function agentEval({ input, expectedTools, actualOutput, toolCalls }) {
  const toolsUsed = new Set(toolCalls.map(t => t.name));
  const expectedToolsSet = new Set(expectedTools);
  
  return {
    toolRecall: intersectionSize(toolsUsed, expectedToolsSet) / expectedToolsSet.size,
    toolPrecision: intersectionSize(toolsUsed, expectedToolsSet) / toolsUsed.size,
    taskSuccess: actualOutput.includes('订单已预订'),
  };
}

5. 业务指标

最终的真实指标

  • 用户点赞率 / 点赞数
  • 任务完成率(agent 是否真的完成了用户任务)
  • 用户留存(次日 / 7 日)
  • 投诉率

LLM 评估 ≠ 业务价值。所有 LLM 指标都是代理指标,最终看业务。

二、离线评估集:怎么构造 + 怎么跑

构造评估集的 4 个来源

  1. 生产数据回捞:从 observability 平台随机抽样 100-500 条真实对话
  2. 人工标注:让领域专家写 100-200 条”标准答案”
  3. 对抗样本:根据历史错误,专门构造容易出错的 query
  4. 合成数据:用 GPT-4 根据 schema 生成大量合成 case,人工 review 一部分

评估集大小

项目阶段评估集大小
早期原型50-100 条
上线前200-500 条
持续运营1000+ 条,每月补充

跑评估:Braintrust 实战

Braintrust 是当前最成熟的 LLM 评估平台之一:

import { Eval } from 'braintrust';
import { Factuality, LevenshteinScorer } from 'autoevals';

await Eval('customer-support-v3', {
  data: () => loadEvalDataset('support-100.json'),
  task: async (input) => {
    // 你的应用代码
    return generateReply(input);
  },
  scores: [Factuality, LevenshteinScorer],
  experimentName: 'prompt-v3-test',
});
// Eval 直接 await,不需双重 IIFE

Eval 会:

  1. 跑每条 input 通过 task
  2. 用每个 scorer 给 output 打分
  3. 聚合结果:平均分、按子集分、对比基线

持续评估(CI/CD)

# .github/workflows/eval.yml
- name: Run LLM eval
  run: |
    braintrust eval eval/rag-pipeline.py
    # 失败时阻断 PR 合并

每次 prompt / embedding / 模型变更后,自动跑回归,分数跌过阈值就报警。

三、在线 A/B 测试:生产环境对比

离线评估有局限——真实用户行为可能跟标注数据不一致。生产里必须 A/B:

图 2:A/B 测试流程

实现

// 路由层
function routeUser(userId: string) {
  const bucket = hashUserId(userId) % 100;
  return bucket < 50 ? 'version-a' : 'version-b';
}

// 应用层
const version = routeUser(userId);
const result = version === 'version-a' ? await oldPrompt(input) : await newPrompt(input);

// 记录
await observability.track({
  userId,
  version,
  input,
  output: result.text,
  userFeedback: await collectFeedback(userId),
});

A/B 测试的关键原则

  1. 按 user 路由(不是按 request)——同一个用户始终看到同一版本,体验一致
  2. 样本量足够——A/B 结论需要统计显著性,通常 1000+ 用户 / 每组
  3. 核心指标 + 护栏指标——护栏(延迟、成本)不能变差
  4. 新版本先小流量——5% → 20% → 50% → 100%,逐步放量
  5. 持续至少 1-2 周——覆盖工作日 / 周末的 user 行为差异

四、生产评估 pipeline

完整流程:

图 3:生产评估 pipeline

关键:离线分数提升 ≠ 在线业务提升,两者都要看

踩坑提醒

  1. 不要只用一个 LLM-as-Judge。评委偏差会导致分数虚高 / 虚低,用 2-3 个评委 + 调换位置
  2. 不要忽略 baseline。每次评估必须对比基线(如 gpt-4o / 历史版本),单看绝对分数没意义。
  3. 不要在线下评估里灌太多合成数据。合成数据会自我循环(用 GPT-4 生成,用 GPT-4 评估),结果失真。
  4. 不要 A/B 测试样本太少就下结论。< 500 / 组的结果几乎全是噪声,等显著性再决定。
  5. 不要用 prompt 评估 prompt。同模型评自己会产生自评偏差,用更强模型当评委

总结

5 个 takeaway:

  • 5 类指标:硬指标 / embedding / LLM-as-Judge / 任务特定 / 业务。业务指标才是终极指标
  • LLM-as-Judge 必备:用更强模型当评委,但要防位置偏差 + 自评偏差
  • 离线 + 在线结合:离线快速迭代(200-500 条 case),在线 A/B 验证(1000+ 用户)。
  • 评估集持续扩充:每月补充新 case,特别是历史错误的对抗样本
  • 不要只看分数:分数提升 ≠ 业务提升,两者都要看

下一篇LLM 成本与性能优化:Caching、Streaming 与模型路由 — 进入生产化收官篇。

参考资料

🔗 原文链接 分享让更多人看到

// 相关文章

评论