15 分钟手工搭一套 LLM 评测集:不用 MLflow,不用平台
每次换模型、改提示词、调 temperature,你想知道结果会变好还是变坏,但只能拿刚生成的那几段读一遍,凭感觉说"感觉差不多"。这套流程撑得过 demo,撑不过生产:感觉不稳定,跨人不对齐,过两周你自己也记不清上次到底是什么水平。

15 分钟手工搭一套 LLM 评测集:不用 MLflow,不用平台
每次换模型、改提示词、调 temperature,你想知道结果会变好还是变坏,但只能拿刚生成的那几段读一遍,凭感觉说"感觉差不多"。这套流程撑得过 demo,撑不过生产:感觉不稳定,跨人不对齐,过两周你自己也记不清上次到底是什么水平。
评测集是解药,但它不一定要重。下面这套方案,一个 JSON 文件加一个 Python 脚本,15 分钟能跑起来,只需要你手头有一份真实的任务列表。
第一步:题从哪来
**永远不要手写理想化的题目。** 去翻生产日志或 beta 用户反馈,把最近 30 天里"答错了"或"用户追问了第二遍"的请求筛出来,每个 case 就是一个未来的测试题。
筛的时候留三种:
- 答错答案的(有明确对错)
- 答对但很啰嗦或很离谱的(质量问题)
- 边界场景(超长输入、中英混排、模糊指令)
10~20 个就够开始。50 个以上才是"维护一套评测"的负担,前 20 个价值最大——它们全部来自你的真实失败记忆。
第二步:每道题长什么样
一个 JSON 数组,每题三个字段:
{
"id": "invoice-overflow-001",
"prompt": "这是一张 $47.99 的账单,套餐是 $45,请处理差额",
"expect": {
"contains_any": ["$2.99", "2.99"],
"max_tokens": 200
}
}
`expect` 是断言层,按任务类型挑:
- **事实性任务**(计算、提取、翻译):`contains_any` / `not_contains` / 精确匹配,能自动化判分的直接判
- **格式任务**(要 JSON、要表格):加 `json_valid: true`,或做一次 schema 检查
- **风格任务**(写文案、改写):别硬写关键词,在 `expect_notes` 里留一句人话,跑完人眼扫一遍,60 秒一个 case,比维护脆弱的关键词更快
关键原则:**能自动断言的绝不人眼判,人眼判的只留给真正主观的部分。** 如果一半的 `expect` 你写了又删、不知道写什么,说明这类题不适合进当前版本的评测集。
第三步:跑分和对比
脚本核心 20 行:循环每题调一次 API,收集输出和耗时,对 `expect` 跑断言,输出一个表格:
| case | 通过 | 耗时 | 备注 |
|------|------|------|------|
| invoice-overflow-001 | ✅ | 2.3s | |
| mt-fallback-zh-003 | ❌ | 4.1s | 漏了"半宽括号要保留" |
对比用法值钱的地方在这里:换模型/改提示词之前跑一版,把输出存进 `runs/20260901-before/`,改完跑进 `runs/20260901-after/`,diff 两个文件夹。重点看三类变化:
1. **以前对的现在错了**(回归,最严重,优先修)
2. **以前错的现在对了**(改善,先确认它为什么对)
3. **两边都错但错法变了**(中性,记一笔,观察趋势)
别追求一次覆盖所有维度。第一版只回答一个问题:**这次改动,家里的 case 掉了几道。**
三个常见的坑
**坑一:题目泄露。** 如果线上用户会接同一个提示词,评测题里的 prompt 一旦出现在对外文档、错误信息或日志里,等于开了作弊通道。题目 ID 和 prompt 不要外泄。
**坑二:temperature=0 的假确定性。** 很多模型 0 温度下输出仍有微幅波动,两次跑分输出不一样,不代表模型变坏或变好。判断"回归"至少连跑 2 次,两次都错才记。
**坑三:集子只进不出。** "连续 5 次全对且从未再出错的 case"移到 `archive/` 子目录。留在主集里的,应该永远是能区分模型高低的题,而不是全公司历史上的题。
从哪里开始
打开今天的 API 日志,筛出 10 个"答得不理想"的请求,写成 JSON,补上断言,跑一次、存档,评测 v0.1 就有了。下一次改提示词或换模型之前先跑 v0.1,你会拿到一个数字,而不是一个感觉。这个数字,就是你和下一个版本之间的那份合同。
留言区
欢迎分享你的想法!
加载留言中…