Skip to content

08-测评驱动迭代

没有测评集的迭代是闭门造车。本章讲怎么建测评集、怎么自动跑批、怎么打分、怎么把 Bad case 流转到下一轮模式手册治理。


cost-query V2 阶段没有正式测评集,团队靠”凭感觉”改 SKILL.md。结果是:

  • 改一个 bug 时不知道有没有引入新 bug;
  • 业务方反馈”这题答得不对”时,没法验证”修完之后真的好了”;
  • 模式手册扩展时不知道新模式有没有破坏已有能力;
  • 项目交接给新人时没有客观的能力基线。

V3 引入 35 题问题集 + headless 跑批后,团队第一次有了”客观看正确率”的能力。每次改动跑一次测评,正确率往上走还是往下走一目了然。

测评集不是 QA 工具,是问数技能能力的客观度量衡

  • 改 SKILL.md / 模式手册 / 编译器 → 跑测评 → 看正确率变化;
  • 业务方加新需求 → 加测评题 → 看现有技能能不能答;
  • 团队成员换人 → 看测评分能不能保持;
  • 业务方挑战结论 → 用测评结果对比说服。

没有测评集你做的所有改动都是”赌”,有测评集才是”工程”。


阶段题数覆盖目标
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 道测评题。

除常规题外,必须有 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 项信息(期望路径 / 关键参数 / 期望结论 / 期望边界 / 评分要点)。


来源 1:业务方真实问题(首选)

Section titled “来源 1:业务方真实问题(首选)”

让业务方提供 30-50 道他们日常会问的问题。这些问题代表真实使用场景,最有价值。

操作:

  • 业务方头脑风暴 30 分钟,每人写 10-20 道问题;
  • 团队整理去重,按 L1-L4 + 模式分类;
  • 业务方再走一遍,确认每题的”期望答案”长什么样。

业务方一般不会主动想”如果数据库没数据怎么办”这种边界。测评团队补足这部分。

上线后业务方反馈的”这题答不好”——必须进入测评集。

开发过程中发现的”LLM 在 X 场景容易错”——抽象成测评题。


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

如果不接 cctest,自建简化版:

# eval-runner.py(伪代码)
import subprocess
import 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)
  1. 每题独立进程:避免上下文污染。同一会话里前题对话历史会带到后题,污染判断;
  2. stream-json 输出:能完整解析 LLM 跑了哪些工具、耗时、是否报错、命中行数;
  3. 阶段 A 与阶段 B 分离:执行与评分用不同 LLM 实例,避免评分员看到自己的答案;
  4. 评分员对路径与结论分别打分:路径分(CLI 调用质量)+ 结论分(业务结论质量)解耦,能分别看哪部分需要改进。

cctest 支持两种阶段 A 模式:

  • 共用会话(默认):所有题在同一 claude -p 会话中按顺序问,前题历史会带到后题;
  • 独立会话:每题独立进程,题间无上下文。

共用会话模拟真实使用场景(用户连续问),暴露”前题口径偏见污染后题”等问题;独立会话评估单题能力。两种模式都跑能发现不同问题。


cost-query 用”CLI 一致性(60)+ 结论一致性(40)= 100”分维评分。

评分点:

  • 是否选对二级指令;
  • 是否选对模式(如 M1.6 而不是 M1.1);
  • 关键参数是否写对(cityName / measureGroups / 时间窗等);
  • 是否多调用了不必要的工具;
  • 是否发生了重试(错一次再重试 = 扣分)。

CLI 路径质量与”数据答得对不对”解耦:即便最终结论错了,只要 CLI 路径精炼、零冗余、零报错,CLI 分接近满分。这样能区分”模型能力问题”vs”数据底座问题”。

评分点:

  • 数值是否正确;
  • 是否标注口径(业态 / 阶段 / 时间窗 / 样本量);
  • 是否按样本降级表降级表达(样本不足不强判断);
  • 是否合理处理 0 行 / 全 NULL 场景;
  • 是否给出 L1-L4 对应的输出深度;
  • 是否守住数据底线(不补数 / 不混业态)。
扣分场景示例:
- 没标口径:扣 5-10 分
- 样本 < 5 但给强结论:扣 10-15 分
- 数据库没数据但补数:扣 30-40 分(违反高危红线)
- 用户挑战时立刻认错补数:扣 30-40 分
- 暴露内部技术细节(cube / DSL 名):扣 5-10 分

跑完一轮测评,把”<60 分”的题分出来:

  1. 复盘:人工看 CLI 调用 + 业务结论 + 评分理由;
  2. 归因:是 schema 问题 / 模式手册问题 / SKILL.md 问题 / 编译器问题 / 数据问题;
  3. 修复:按归因改对应文件;
  4. 回归:跑该题验证修复后通过;
  5. 全量回归:跑全测评集,确认没破坏其它能力。

多道题同样错(如 8 道题都没标口径),说明 SKILL.md 的”口径标注”指导不够强。

操作:

  • 不要一题一题改,找根本原因;
  • 在 SKILL.md / query-guide.md 加强相关指导(如新增一条铁律);
  • 跑全量测评看群体性问题是不是一起解决。

cost-query 经验:每轮治理 1-2 周一次。

Day 1-3:跑 1 轮完整测评,识别 Bad case
Day 4-7:分析归因,写治理方案
Day 8-10:实施修复(改 SKILL.md / 模式手册 / 反模式 / 编译器)
Day 11-14:双轮验证(修复后跑两次,确保稳定)

不要日治理——LLM 跑批有概率成分,单轮结果有 5-10% 波动;至少跑两轮取平均。


合理的目标:

阶段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 分。

只看平均分会被几道高分题掩盖问题。每轮跑完看:

  • 每题独立分数;
  • 按模式分组的平均分(M1 平均、M2 平均…);
  • 按 L1-L4 分组的平均分;
  • 不通过题数(<60 分的)。

每次发布前后都跑测评,记录:

  • 总分变化(提升 / 下降);
  • 单题变化(哪些题提升、哪些题下降);
  • 工具调用次数变化(更精炼 / 更冗长);
  • 平均耗时变化。

发布前必须确保:单题不下降超过 5 分;总分不下降;新引入的能力对应题数提升。


  • 题质量审查:业务方每 2-3 个月走一遍测评集,淘汰过时的题、补充新场景;
  • 参考答案更新:业务规则变化后,对应题的参考答案要同步改;
  • 题库分级:标注每题”必通过”vs”挑战题”——前者每次跑、后者周期跑。

测评工具(如 cctest)跟主仓 SKILL 一起版本化:

  • 主仓 commit + 测评工具 commit 绑定;
  • 历史版本能复现历史测评结果。

每次测评产物:

  • 完整的运行目录(cli_calls / conclusions / scores 全保留);
  • Markdown 测评报告(含每题状态 + 总分 + 不通过题清单);
  • 与上一轮的 diff 报告(哪些题提升、哪些下降)。

归档原则:保留近 3 个月的全部测评结果;超过 3 个月的只保留最终发布的版本。


  • 出题:每月新增 5-10 道真实问题;
  • 审参考答案:新题的”期望答案”业务方拍板;
  • 挑战结论:跑出来的答案业务方觉得不对要反馈;
  • 试用:业务方在测评集外随机问,发现 Bad case 进入测评集。
  • 维护工具:跑批工具、stream-json 解析、评分脚本;
  • 跑批:每次改动后跑测评;
  • 分析报告:把测评报告解读给业务方听;
  • 执行治理:按 Bad case 修复相应文件。
  • 协调:业务和研发对结论不一致时介入;
  • 优先级:哪些 Bad case 先治理、哪些可以延后;
  • 节奏:测评 + 治理的整体节奏控制。

完成测评闭环搭建后逐项检查:

  • 测评集至少 20 题(MVP 后扩到 30-50 题);
  • 题按 L1-L4 + M1-Mn 分类;
  • 每题有 5 项参考信息(路径、参数、结论、边界、评分要点);
  • 自动跑批工具能跑通(cctest 或自建);
  • stream-json 解析能完整还原 CLI 调用清单;
  • 评分员(阶段 B)能独立打分;
  • CLI 分与结论分解耦;
  • Bad case 流转流程明确(复盘 → 归因 → 修复 → 回归);
  • 每次发布前跑全量测评;
  • 测评报告归档机制就位。

Part 8 完。读完应能回答:“测评集怎么构造、跑批工具怎么选/搭建、CLI 分和结论分怎么打、Bad case 怎么流转、测评指标怎么看、团队协同怎么分工”。