没有评测,你就不敢改任何东西------AI 应用评测第一课(E01)
系列《AI 应用生产化手册》第 1 篇(共 30 篇)|配套开源项目:github.com/ChenYingbo/...
一、先看三个每天都在发生的场景
- 改了个提示词,不知道改好了还是改坏了------凭感觉上线,被用户骂回来。
- 换了更强的模型,线上质量反而下降------没人能证明"换之前到底什么样"。
- 客服答错了一个关键问题------但错误是概率性的,复现不出来,投诉也只能道歉。
这三个困境指向同一个根因:你没有评测。没有评测 = 没有"改没改好"的判断依据 = 每次变更都是赌。
本系列的第一课就从这里开始:AI 应用和传统软件最大的不同是"非确定性"------代码要么对要么错,大模型输出没有"标准答案"。没有评测体系,你的应用永远停在"能跑",到不了"敢上线"。
二、原理:为什么传统测试失效
传统软件测试是确定性的:输入 → 预期输出,断言相等即可。AI 应用有三个传统测试接不住的特性:
| 特性 | 传统测试 | AI 应用 |
|---|---|---|
| 输出 | 确定(断言相等) | 不确定(语义正确 ≠ 字符串相等) |
| 边界 | 有限可枚举 | 无限(自然语言输入空间) |
| 故障 | 必现 | 概率性(同一问题 10 次 8 对 2 错) |
所以 AI 应用的测试从"断言"变成"评估(Eval)":给输出打分、统计、对比。
评测金字塔(三层结构)
kotlin
▲ 端到端评测(E2E)
▲▲ 模拟真实用户完整流程,数量少、成本高
▲▲▲ 场景评测(Scenario)
▲▲▲▲ 多轮对话/带工具调用/复杂任务,覆盖关键业务路径
▲▲▲▲▲ 单元评测(Unit)
▲▲▲▲▲▲ 单轮问答/单点能力,数量大、跑得快、进 CI
- 单元层:单轮、单能力,量大、便宜,CI 里每次变更都跑
- 场景层:关键业务路径(客服完整处理一次投诉),贵一些,发布前跑
- 端到端层:真实用户流程模拟,最贵,发布前抽查 + 线上采样
原则:下层数量多、跑得勤;上层数量少、跑得精。 没有下层,上层测不出问题在哪一层。
指标体系:质量 × 成本 × 延迟
| 维度 | 指标 | 说明 |
|---|---|---|
| 质量 | 正确率 | 答案是否正确(知识库问答尤其关键) |
| 忠实度(Faithfulness) | 答案是否忠于给定上下文,有没有编造(幻觉) | |
| 相关性(Relevance) | 答的是不是用户问的 | |
| 工具正确率 | Agent 场景:工具选对没有 | |
| 成本 | Token 消耗/请求 | 每次请求烧多少 token |
| 延迟 | P50 / P95 / P99 | 用户体感 |
关键认知:忠实度 ≠ 正确率。 模型可能"答得对但依据是编的"------知识库场景这是最危险的错误:看起来对,实际不可信。
离线评测 vs 在线评测
| 离线评测 | 在线评测 | |
|---|---|---|
| 时机 | 变更前(CI/发布门禁) | 上线后(持续) |
| 数据 | 固定评测集 | 真实线上流量采样 |
| 回答 | "这次改动让质量升还是降" | "线上真实表现如何" |
| 工具 | DeepEval / Ragas / promptfoo | 可观测平台 |
两件事缺一不可:先离线把好变更关,再在线盯线上表现。
三、动手:跑一次"没有评测"的实验
感受"没有评测集的代价":跑通最简问答接口,手工给 10 个问题打分,建立第一版手工评分基线。
bash
git clone https://github.com/ChenYingbo/ai-prod-demo.git && cd ai-prod-demo
cp .env.example .env # 填入一个模型 API Key(DeepSeek 即可)
docker compose up -d litellm
source .venv/bin/activate && pip install -r requirements.txt
uvicorn app.main:app --reload --port 8000
# 跑 10 个评测问题(本文配套实验,实测 10/10 全部真实回答,单题 1-3 秒)
python scripts/ask.py -f eval/e01_questions.txt --json > eval/e01_raw.json
10 问评测清单(覆盖不同难度与风险)
| # | 问题 | 设计意图 |
|---|---|---|
| 1 | 什么是 RAG?一句话解释 | 定义类(简单) |
| 2 | 向量数据库和关系型数据库的区别 | 对比类(中等) |
| 3 | 我们公司的报销流程是什么? | 无上下文(观察缺知识时是否编造) |
| 4 | 写 Python 代码计算两个日期相差天数 | 代码生成(中等) |
| 5 | temperature 调大会有什么影响 | 技术概念(中等) |
| 6 | 2024 巴黎奥运会中国多少金牌 | 事实数字(幻觉高风险) |
| 7 | 帮我总结这篇文章 | 缺上下文(应追问而不是硬编) |
| 8 | Spring 事务失效的常见场景 | 技术深问(较难) |
| 9 | 你昨天说的方案再讲一遍 | 伪多轮(观察记忆缺失处理) |
| 10 | 1 加 1 等于几 | 简单基线 |
评分表模板(1-5 分)
| # | 正确性 | 忠实度 | 相关性 | 备注 |
|---|---|---|---|---|
| 1 | ||||
| ... | ||||
| 10 | ||||
| 均值 |
评分标准:正确性 =答案本身对不对;忠实度 =有没有编造依据(5=完全基于事实 1=明显幻觉);相关性=答的是不是问的。
实验后要回答的三个问题
- 哪些问题答得最差?是缺知识 (如 #3 #7)还是模型本身不行(如 #6 #8)?
- 如果把"缺知识"的问题接上 RAG(检索真实知识库),哪些能救回来?
- 现在你敢不敢改提示词然后判断"改好了"?------这就是 E02 评测集要解决的事。
四、真实踩坑(本文配套项目实测)
以下全部是本项目真实踩过、修过的:
- 网关没起来就调应用 :
/api/chat返回 502------先curl http://localhost:4000/health/liveliness确认网关 - 缓存污染 :故障阶段的兜底答案被 SQLite 缓存,重复提问直接命中"抱歉,服务不可用"------清缓存(
rm data/llm_cache.db)后才拿到真实回答。这是 C02 缓存的经典坑:缓存会把错误也缓存下来 --json输出被污染:命令行工具把人类可读输出和 JSON 混在同一 stdout,重定向后文件解析失败------JSON 模式人类输出必须走 stderr- 成功路径没被测试覆盖 :接口"正常回答"路径曾因一个变量未定义直接 500,而所有测试都只测了校验/拒绝路径------测试必须覆盖成功路径,否则上线即事故
- 评分标准不一致:同一个答案上午 4 分下午 3 分------先写死评分标准再打分(上面 3.4 节)
- 把"忠实度"和"正确性"混为一谈:模型答对了但依据是编的,是最容易被放过的幻觉
- 10 个问题太少没有代表性:这只是第一版基线,E02 会扩到 30 条并覆盖边界 case
五、小结
这一篇建立了三个认知:
- 评测金字塔:单元层(多、快、进 CI)→ 场景层 → 端到端层(少、精、上线前)
- 三维指标:质量(正确率/忠实度/相关性)× 成本 × 延迟
- 忠实度 ≠ 正确率:答对但依据是编的,比答错更危险
配套项目:github.com/ChenYingbo/... (30 篇教程的每个知识点都在项目里真实存在)
明天(E02):《评测集构建》------把 10 个随手问题,升级成 30 条结构化评测集。 收藏 + 关注,每天一篇,30 天把 AI 应用送上生产。