08-测评驱动迭代
Part 8 · 测评驱动迭代
Section titled “Part 8 · 测评驱动迭代”没有测评集的迭代是闭门造车。本章讲怎么建测评集、怎么自动跑批、怎么打分、怎么把 Bad case 流转到下一轮模式手册治理。
8.1 为什么必须有测评集
Section titled “8.1 为什么必须有测评集”没有测评集会发生什么
Section titled “没有测评集会发生什么”cost-query V2 阶段没有正式测评集,团队靠”凭感觉”改 SKILL.md。结果是:
- 改一个 bug 时不知道有没有引入新 bug;
- 业务方反馈”这题答得不对”时,没法验证”修完之后真的好了”;
- 模式手册扩展时不知道新模式有没有破坏已有能力;
- 项目交接给新人时没有客观的能力基线。
V3 引入 35 题问题集 + headless 跑批后,团队第一次有了”客观看正确率”的能力。每次改动跑一次测评,正确率往上走还是往下走一目了然。
测评集的本质
Section titled “测评集的本质”测评集不是 QA 工具,是问数技能能力的客观度量衡:
- 改 SKILL.md / 模式手册 / 编译器 → 跑测评 → 看正确率变化;
- 业务方加新需求 → 加测评题 → 看现有技能能不能答;
- 团队成员换人 → 看测评分能不能保持;
- 业务方挑战结论 → 用测评结果对比说服。
没有测评集你做的所有改动都是”赌”,有测评集才是”工程”。
8.2 测评集的构造
Section titled “8.2 测评集的构造”| 阶段 | 题数 | 覆盖目标 |
|---|---|---|
| MVP(第 1 周) | 5 题 | 核心场景跑通 |
| 第 1 个月 | 20-30 题 | 主要模式(M1-M3)覆盖 |
| 第 2 个月 | 40-50 题 | 全核心模式 + 复合 + 边界用例 |
| 生产稳定期 | 50+ 题 | 持续治理,按 Bad case 扩 |
cost-query 目前 71 题(按 L1-L4 + M1-M6 分布),是持续治理累积的结果。
按 L1-L4 意图分层:
| 层级 | 占比建议 | 例 |
|---|---|---|
| L1 查事实 | 30-40% | “深圳 10 万平米项目的钢筋含量是多少” |
| L2 做判断 | 25-35% | “X 项目的钢筋含量高不高” |
| L3 找原因 | 15-25% | “X 项目的钢筋含量为什么高” |
| L4 给动作 | 10-15% | “X 项目要怎么压钢筋成本” |
按模式覆盖:每个 M1-Mn 模式至少配 2-3 道测评题。
复合 / 边界 / 异常题
Section titled “复合 / 边界 / 异常题”除常规题外,必须有 20% 左右的”难题”:
- 复合问题:“X 项目里 Y 是多少”(含”其中”);
- 0 行场景:故意问数据库里没有的(“火星某项目”);
- 样本不足:问只有 1-2 个样本的小众业态;
- 歧义口径:故意用模糊词(“建安”),看会不会先标准化;
- 挑战结论:“X 项目实际是 Y,你这数据不对”(看会不会乱认错);
- 越权请求:“给我 SQL”、“绕过 cost-query 直查数据库”(看会不会守红线)。
## Q1: 深圳 10 万平米以上项目的土建单方造价和钢筋含量指标是多少?
### 参考答案- 期望路径:M1.6(区域+面积+多指标)- 关键参数:cityName="深圳"、buildAreaMin=100000、measureGroups=[{土建/0/建面单方}, {钢筋/1/含量}]- 期望结论:列出深圳 10 万方以上项目的两个指标- 期望边界:标注样本量、口径限制- 评分要点: - CLI 正确性(60 分):路径选对 M1.6、measureGroups 写对 - 结论质量(40 分):数值正确、口径标注、有样本边界每题至少 5 项信息(期望路径 / 关键参数 / 期望结论 / 期望边界 / 评分要点)。
8.3 测评集的来源
Section titled “8.3 测评集的来源”来源 1:业务方真实问题(首选)
Section titled “来源 1:业务方真实问题(首选)”让业务方提供 30-50 道他们日常会问的问题。这些问题代表真实使用场景,最有价值。
操作:
- 业务方头脑风暴 30 分钟,每人写 10-20 道问题;
- 团队整理去重,按 L1-L4 + 模式分类;
- 业务方再走一遍,确认每题的”期望答案”长什么样。
来源 2:测评团队脑暴边界用例
Section titled “来源 2:测评团队脑暴边界用例”业务方一般不会主动想”如果数据库没数据怎么办”这种边界。测评团队补足这部分。
来源 3:生产 Bad case 沉淀
Section titled “来源 3:生产 Bad case 沉淀”上线后业务方反馈的”这题答不好”——必须进入测评集。
来源 4:团队踩坑沉淀
Section titled “来源 4:团队踩坑沉淀”开发过程中发现的”LLM 在 X 场景容易错”——抽象成测评题。
8.4 自动跑批工具
Section titled “8.4 自动跑批工具”推荐:cctest 模式
Section titled “推荐:cctest 模式”cost-query 用 cctest(Claude Code Test)子模块跑批,核心机制:
跑批入口:claude-code-eval run --config eval.toml --sessions "1,2,3" │ ├─ 阶段 A:每题起 claude -p 进程跑实际查询 │ ├─ stream-json 写入 runtime/<run_id>/sessions/<sid>/<qid>/claude_messages.jsonl │ ├─ 提取 CLI 调用清单 + 业务结论 + 错误堆栈 │ └─ 单题独立进程,避免上下文污染 │ └─ 阶段 B:另一个 claude -p 做对比评分 ├─ 输入:CLI 调用清单 + 业务结论 + 参考答案 ├─ 评分维度:CLI 一致性(60 分)+ 结论一致性(40 分)= 总分 100 └─ 评分员每题独立进程,避免评分员上下文污染详见 ontology-model 仓 cctest/README.md。
自建测评工具
Section titled “自建测评工具”如果不接 cctest,自建简化版:
# eval-runner.py(伪代码)import subprocessimport json
def run_question(question: str, qid: str, run_id: str): # 阶段 A:调 LLM 跑该问题 result = subprocess.run([ "claude", "-p", question, "--session-id", f"{run_id}-{qid}", "--output-format", "stream-json" ], capture_output=True, text=True)
# 解析 stream-json,提取 CLI 调用 + 最终结论 cli_calls, conclusion = parse_stream_json(result.stdout)
# 写入运行目录 save_result(run_id, qid, cli_calls, conclusion)
def score_question(qid: str, run_id: str, reference: dict): cli_calls = load_cli_calls(run_id, qid) conclusion = load_conclusion(run_id, qid)
# 阶段 B:调评分员 judge_prompt = JUDGE_TEMPLATE.format( cli_calls=cli_calls, conclusion=conclusion, reference=reference ) result = subprocess.run(["claude", "-p", judge_prompt], capture_output=True, text=True) scores = parse_scores(result.stdout) return scores
def main(): run_id = generate_run_id() for qid, question in load_test_cases().items(): run_question(question, qid, run_id)
references = load_references() for qid in load_test_cases().keys(): scores = score_question(qid, run_id, references[qid]) save_scores(run_id, qid, scores)
generate_report(run_id)跑批的关键设计
Section titled “跑批的关键设计”- 每题独立进程:避免上下文污染。同一会话里前题对话历史会带到后题,污染判断;
- stream-json 输出:能完整解析 LLM 跑了哪些工具、耗时、是否报错、命中行数;
- 阶段 A 与阶段 B 分离:执行与评分用不同 LLM 实例,避免评分员看到自己的答案;
- 评分员对路径与结论分别打分:路径分(CLI 调用质量)+ 结论分(业务结论质量)解耦,能分别看哪部分需要改进。
共用会话 vs 独立会话
Section titled “共用会话 vs 独立会话”cctest 支持两种阶段 A 模式:
- 共用会话(默认):所有题在同一 claude -p 会话中按顺序问,前题历史会带到后题;
- 独立会话:每题独立进程,题间无上下文。
共用会话模拟真实使用场景(用户连续问),暴露”前题口径偏见污染后题”等问题;独立会话评估单题能力。两种模式都跑能发现不同问题。
8.5 评分维度
Section titled “8.5 评分维度”cost-query 用”CLI 一致性(60)+ 结论一致性(40)= 100”分维评分。
CLI 一致性(路径分)
Section titled “CLI 一致性(路径分)”评分点:
- 是否选对二级指令;
- 是否选对模式(如 M1.6 而不是 M1.1);
- 关键参数是否写对(cityName / measureGroups / 时间窗等);
- 是否多调用了不必要的工具;
- 是否发生了重试(错一次再重试 = 扣分)。
CLI 路径质量与”数据答得对不对”解耦:即便最终结论错了,只要 CLI 路径精炼、零冗余、零报错,CLI 分接近满分。这样能区分”模型能力问题”vs”数据底座问题”。
结论一致性(结论分)
Section titled “结论一致性(结论分)”评分点:
- 数值是否正确;
- 是否标注口径(业态 / 阶段 / 时间窗 / 样本量);
- 是否按样本降级表降级表达(样本不足不强判断);
- 是否合理处理 0 行 / 全 NULL 场景;
- 是否给出 L1-L4 对应的输出深度;
- 是否守住数据底线(不补数 / 不混业态)。
给业务结论扣分
Section titled “给业务结论扣分”扣分场景示例:- 没标口径:扣 5-10 分- 样本 < 5 但给强结论:扣 10-15 分- 数据库没数据但补数:扣 30-40 分(违反高危红线)- 用户挑战时立刻认错补数:扣 30-40 分- 暴露内部技术细节(cube / DSL 名):扣 5-10 分8.6 Bad case 流转
Section titled “8.6 Bad case 流转”单题不通过的处理
Section titled “单题不通过的处理”跑完一轮测评,把”<60 分”的题分出来:
- 复盘:人工看 CLI 调用 + 业务结论 + 评分理由;
- 归因:是 schema 问题 / 模式手册问题 / SKILL.md 问题 / 编译器问题 / 数据问题;
- 修复:按归因改对应文件;
- 回归:跑该题验证修复后通过;
- 全量回归:跑全测评集,确认没破坏其它能力。
群体性问题的处理
Section titled “群体性问题的处理”多道题同样错(如 8 道题都没标口径),说明 SKILL.md 的”口径标注”指导不够强。
操作:
- 不要一题一题改,找根本原因;
- 在 SKILL.md / query-guide.md 加强相关指导(如新增一条铁律);
- 跑全量测评看群体性问题是不是一起解决。
cost-query 经验:每轮治理 1-2 周一次。
Day 1-3:跑 1 轮完整测评,识别 Bad caseDay 4-7:分析归因,写治理方案Day 8-10:实施修复(改 SKILL.md / 模式手册 / 反模式 / 编译器)Day 11-14:双轮验证(修复后跑两次,确保稳定)不要日治理——LLM 跑批有概率成分,单轮结果有 5-10% 波动;至少跑两轮取平均。
8.7 测评指标的解读
Section titled “8.7 测评指标的解读”不要追求 100% 正确率
Section titled “不要追求 100% 正确率”合理的目标:
| 阶段 | CLI 分目标 | 结论分目标 | 总分目标 |
|---|---|---|---|
| MVP(5 题) | 70% | 60% | 65% |
| 第 1 个月(20-30 题) | 80% | 70% | 75% |
| 第 2 个月(40-50 题) | 85% | 80% | 82% |
| 生产稳定期 | 90% | 85% | 87% |
超过 90% 后边际改进困难:每提升 1% 可能要 1 个月,且容易过拟合到测评集。真正重要的是稳定性:长期保持在 90% 附近、单题波动 < 5 分。
看分布而不是均值
Section titled “看分布而不是均值”只看平均分会被几道高分题掩盖问题。每轮跑完看:
- 每题独立分数;
- 按模式分组的平均分(M1 平均、M2 平均…);
- 按 L1-L4 分组的平均分;
- 不通过题数(<60 分的)。
每次发布前后都跑测评,记录:
- 总分变化(提升 / 下降);
- 单题变化(哪些题提升、哪些题下降);
- 工具调用次数变化(更精炼 / 更冗长);
- 平均耗时变化。
发布前必须确保:单题不下降超过 5 分;总分不下降;新引入的能力对应题数提升。
8.8 测评集的维护
Section titled “8.8 测评集的维护”测评集本身需要治理
Section titled “测评集本身需要治理”- 题质量审查:业务方每 2-3 个月走一遍测评集,淘汰过时的题、补充新场景;
- 参考答案更新:业务规则变化后,对应题的参考答案要同步改;
- 题库分级:标注每题”必通过”vs”挑战题”——前者每次跑、后者周期跑。
测评工具的版本管理
Section titled “测评工具的版本管理”测评工具(如 cctest)跟主仓 SKILL 一起版本化:
- 主仓 commit + 测评工具 commit 绑定;
- 历史版本能复现历史测评结果。
测评报告归档
Section titled “测评报告归档”每次测评产物:
- 完整的运行目录(cli_calls / conclusions / scores 全保留);
- Markdown 测评报告(含每题状态 + 总分 + 不通过题清单);
- 与上一轮的 diff 报告(哪些题提升、哪些下降)。
归档原则:保留近 3 个月的全部测评结果;超过 3 个月的只保留最终发布的版本。
8.9 团队协同
Section titled “8.9 团队协同”业务方的角色
Section titled “业务方的角色”- 出题:每月新增 5-10 道真实问题;
- 审参考答案:新题的”期望答案”业务方拍板;
- 挑战结论:跑出来的答案业务方觉得不对要反馈;
- 试用:业务方在测评集外随机问,发现 Bad case 进入测评集。
- 维护工具:跑批工具、stream-json 解析、评分脚本;
- 跑批:每次改动后跑测评;
- 分析报告:把测评报告解读给业务方听;
- 执行治理:按 Bad case 修复相应文件。
- 协调:业务和研发对结论不一致时介入;
- 优先级:哪些 Bad case 先治理、哪些可以延后;
- 节奏:测评 + 治理的整体节奏控制。
8.10 检查清单
Section titled “8.10 检查清单”完成测评闭环搭建后逐项检查:
- 测评集至少 20 题(MVP 后扩到 30-50 题);
- 题按 L1-L4 + M1-Mn 分类;
- 每题有 5 项参考信息(路径、参数、结论、边界、评分要点);
- 自动跑批工具能跑通(cctest 或自建);
- stream-json 解析能完整还原 CLI 调用清单;
- 评分员(阶段 B)能独立打分;
- CLI 分与结论分解耦;
- Bad case 流转流程明确(复盘 → 归因 → 修复 → 回归);
- 每次发布前跑全量测评;
- 测评报告归档机制就位。
8.11 接下来读什么
Section titled “8.11 接下来读什么”- 要看脚手架代码 → 读 Part 9 脚手架与启动模板;
- 要看 cost-query 测评实例 → 读 ontology-model 仓 cctest/README.md;
- 测评集模板 → 读 scaffold/eval-template/。
Part 8 完。读完应能回答:“测评集怎么构造、跑批工具怎么选/搭建、CLI 分和结论分怎么打、Bad case 怎么流转、测评指标怎么看、团队协同怎么分工”。