AI 应用 A/B 测试与效果评估框架搭建指南 2026:让模型升级不再靠猜
2026-09-03 · 约 11 分钟阅读
上线 AI 应用后,最难的决策永远是"该不该升级模型 / Prompt"——靠人肉抽检 50 条样本说"差不多"是典型的幻觉。靠谱的做法是建立离线评测 + 在线 A/B 测试 + 用户反馈的三层评估体系。本文讲清楚怎么把这套体系从零搭起来。
一、为什么 LLM 应用评估比传统软件更难
传统软件是确定性的:给定输入,输出是固定的,写好单元测试就能保证质量。
LLM 应用则不同:
- 输出不确定:同一 Prompt 两次调用结果可能不一样
- 质量主观:"好答案"的标准因场景而异,没有单一真值
- 依赖上下文:历史对话长度、检索召回质量都影响最终效果
- 业务影响滞后:模型升级后用户流失可能 2 周后才显现
这意味着评测体系是 LLM 应用的必备基础设施——没有评测,模型升级就是赌博。
二、评估体系的三层金字塔
┌──────────────────────────┐
│ L3 在线 A/B 测试 │ 真实用户流量,统计显著性
├──────────────────────────┤
│ L2 在线用户反馈 │ 👍/👎、转化、停留、评论
├──────────────────────────┤
│ L1 离线评测 │ 标准化样本集 + 自动评分
└──────────────────────────┘
三层缺一不可:
- 只做离线评测:你的离线集可能与真实分布脱节
- 只看用户反馈:样本量不够时噪声淹没信号
- 只跑 A/B:失败时排查成本高,没法定位是 Prompt、检索还是其他环节出问题
三、第一层:离线评测集构建
3.1 评测样本的三个来源
| 来源 | 占比建议 | 优点 |
|---|---|---|
| 真实历史请求(脱敏后) | 50-60% | 最贴近线上分布 |
| 人工编写的边界用例 | 20-30% | 覆盖已知 tricky 场景 |
| 对抗生成样本 | 10-20% | 压力测试 |
3.2 样本集最少多少条
经验值:
- MVP 阶段:200-500 条足够做基本对比
- 稳定阶段:1000-3000 条,能跑出统计显著性
- 高风险场景(医疗/法律):5000+ 条 + 持续扩充
3.3 评测样本的元数据
每条样本至少包含:
{
"id": "eval-001",
"input": {"messages": [...], "context": "..."},
"expected_output": "...", // 可选:参考答案
"criteria": { // 评分标准
"must_contain": ["退款流程"],
"must_not_contain": ["无法处理"],
"json_schema": {...} // 强制结构化
},
"metadata": {
"category": "refund",
"difficulty": "medium",
"source": "prod-2026-08"
}
}
3.4 样本持续扩充机制
最关键的一条:每周从线上抽 50-100 条新样本进入评测集。模型在进化,用户行为也在变化,样本集不能一成不变。
四、自动评分方法
4.1 三大流派
| 方法 | 优点 | 缺点 |
|---|---|---|
| 规则匹配 | 简单、可解释 | 覆盖不了语义质量 |
| 传统 NLP 指标 (BLEU/ROUGE) | 易上手 | 和人类判断相关性低 |
| LLM-as-Judge | 灵活、可扩展 | 成本、需要校准 |
4.2 LLM-as-Judge 实战
用更强的模型当裁判,评估业务模型:
JUDGE_PROMPT = """
你是资深的 [客服场景] 质量评估专家。
请按以下标准评估被测模型的回答质量:
1. 准确性 (0-10): 是否包含错误信息?
2. 完整性 (0-10): 是否覆盖用户问题的所有方面?
3. 语气 (0-10): 是否礼貌、专业?
4. 是否包含禁止内容 (是/否): {forbidden_list}
用户问题:{question}
被测回答:{answer}
参考答案:{reference}
请按以下 JSON 格式输出:
{
"accuracy": 8,
"completeness": 9,
"tone": 10,
"contains_forbidden": false,
"overall": 9,
"reasoning": "..."
}
"""
4.3 LLM-as-Judge 的几个坑
1. 位置偏差:把候选 A 放前面时常打高分——评估时随机化顺序,跑两次取平均
2. 自恋偏差:GPT-5 倾向给 GPT-5 系列高分,Claude 倾向给 Claude 系列高分——用不同家族的模型做裁判
3. 长度偏差:裁判倾向给长答案打高分——必要时按 token 归一化
4. 校准:定期把 LLM-as-Judge 评分与人类评分对比,确保相关性 > 0.7
4.4 评估指标选择
按场景:
| 场景 | 推荐指标 |
|---|---|
| 分类 / 抽取 | 准确率 / F1 |
| 生成质量 | LLM-as-Judge + 人类评测小集 |
| 检索质量 | Recall@K, MRR, NDCG@10 |
| RAG 端到端 | RAGAS(faithfulness, context relevance, answer relevance) |
| 工具调用 | 工具调用准确率、参数准确率 |
五、离线评测工具对比
| 工具 | 特点 |
|---|---|
| DeepEval | Python 主流框架,集成 20+ 指标(含 G-Eval, Hallucination, Bias) |
| RAGAS | RAG 端到端评测标杆 |
| Promptfoo | Prompt 对比 + CI 集成友好 |
| OpenAI Evals | 官方开源,灵活但需要自己搭 |
| Braintrust | 商业平台,全流程管理 |
5.1 DeepEval 实战示例
from deepeval import evaluate
from deepeval.metrics import AnswerRelevancyMetric, FaithfulnessMetric
from deepeval.test_case import LLMTestCase
test_case = LLMTestCase(
input="用户问:如何申请退款?",
actual_output="您好,申请退款需要...",
expected_output="您好,请按以下步骤申请退款...",
retrieval_context=["退款政策文档片段..."]
)
# 多维度评分
metrics = [
AnswerRelevancyMetric(threshold=0.7),
FaithfulnessMetric(threshold=0.8),
]
evaluate([test_case], metrics=metrics)
5.2 Promptfoo 实战示例
promptfooconfig.yaml:
prompts:
- file://prompts/customer-support-v1.txt
- file://prompts/customer-support-v2.txt
providers:
- openai:gpt-5.6
- anthropic:claude-opus-5
tests:
- file://eval-data/refund-questions.jsonl
defaultTest:
options:
runSerially: true
跑:npx promptfoo eval,自动生成对比报告。
六、第二层:在线用户反馈
6.1 反馈采集三件套
| 类型 | 实现 |
|---|---|
| 显式反馈 | 👍/👎 按钮、文字评论框 |
| 隐式反馈 | 停留时间、复制率、点赞数、追问次数 |
| 业务反馈 | 转化率、退订率、客服升级率 |
6.2 反馈到 trace 的关联
每次反馈都要能定位到具体的 trace_id / span_id:
@app.post("/feedback")
async def submit_feedback(req: FeedbackRequest):
# 关联到具体的 LLM 调用
span = trace_store.get_span(req.trace_id, req.span_id)
feedback_record = {
"trace_id": req.trace_id,
"span_id": req.span_id,
"rating": req.rating,
"comment": req.comment,
"user_segment": get_user_segment(req.user_id),
"model_version": span.attributes["gen_ai.request.model"],
"prompt_version": span.attributes["app.prompt_version"],
"submitted_at": datetime.utcnow(),
}
feedback_store.save(feedback_record)
return {"ok": True}
七、第三层:在线 A/B 测试
7.1 A/B 测试的常见误区
| 误区 | 正确做法 |
|---|---|
| 跑 3 天就结论 | 至少覆盖一个完整业务周期 |
| 看单一指标就决定 | 综合主要指标 + 辅助指标 |
| 改一个变量 | 一次只改一个(模型/Prompt/参数) |
| 不分用户群 | 按新老用户/付费/地区分桶看 |
7.2 实验分流设计
import hashlib
def get_experiment_bucket(user_id, experiment_name):
h = hashlib.md5(f"{user_id}:{experiment_name}".encode()).hexdigest()
return int(h[:8], 16) % 100 # 0-99
def route_to_experiment(user_id):
bucket = get_experiment_bucket(user_id, "model_upgrade_2026_09")
if bucket < 50:
return "control" # 旧版本
elif bucket < 90:
return "treatment_a" # 新模型 A
else:
return "treatment_b" # 新模型 B
7.3 多少样本才够
A/B 测试样本量公式:
n = 16 * p * (1-p) / (delta²)
其中 p 是基线转化率,delta 是希望检测出的最小差异。
举例:基线 60%,想检测 3% 的差异:
n = 16 * 0.6 * 0.4 / (0.03²) ≈ 4267
每个组至少 4000+ 样本,跑 5-7 天才能得出统计显著性结论。
7.4 A/B 必看的几个核心指标
| 指标 | 含义 | 备注 |
|---|---|---|
| 点赞率 | 👍 / 总回答数 | 短周期可见 |
| 转化率 | 完成业务目标 / 总回答数 | 周期长 |
| 平均对话轮次 | 完成目标的对话长度 | 越短越好 |
| 跳出率 | 一轮就放弃的比例 | 越低越好 |
| API 成本 | 每次任务的 token 消耗 | 必须监控 |
八、Prompt / 模型升级 SOP
把评估体系串成一个标准流程:
1. 离线评测(新模型 vs 老模型在新数据集上跑分)
↓ 通过门槛(综合分提升 ≥ 3%)
2. 内部 dogfooding(团队使用 1 周)
↓ 没有明显问题
3. 灰度上线(5% 流量,跑 3 天)
↓ 关键指标无显著下降
4. 扩大灰度(20% → 50% → 100%)
↓ 持续监控用户反馈
5. 全面上线 + 保留旧版本作为 fallback
每个环节都必须有明确的退出条件和回滚预案。
九、避坑要点
1. 不要只跑单一指标——综合看准确率、相关性、毒性、安全性、成本
2. 离线集要分难度等级——简单题全对不代表难题也对
3. A/B 至少跑 1-2 周——业务有周期性,工作日和周末用户行为差异很大
4. 回滚机制必须随时可用——出问题时秒级切换回上一个版本
5. 多模型并存——GPT-5.6、Claude Opus 5、Gemini 3.1 都准备一份,问题模型挂了秒切
十、工具与资源
- 评测框架:DeepEval、RAGAS、Promptfoo、Braintrust
- A/B 测试平台:内部用 Redis 分桶足够;规模大的上 Eppo / Statsig
- 追踪 + 反馈:Langfuse、Arize Phoenix(都支持 trace ↔ feedback 关联)
- CI 集成:Promptfoo 可在 GitHub Actions 上跑,把评测变成发布门槛
十一、立即开始
最简单的一步:从历史日志里抽 100 条真实请求 + 写 50 条边界用例,用 DeepEval 或 Promptfoo 跑一次基线评测。有了基线,以后每次 Prompt 改动就有了对比基准。
至于跑评测用什么模型,可以直接对接兼容 OpenAI 协议的 AI API 中转站——同一套评测代码可以随时切到不同模型对比效果。openairouter.net 整理了主流中转站的模型支持、价格折扣和稳定性数据,方便你按评测场景挑出最合适的供应商。