career-ops 的 Golden-set 评估机制:把"便宜模型能否胜任路由"变成可度量的数字
本文围绕 evals/README.md 展开,讲解 career-ops 中针对"廉价模型路由"(issue #1354)设计的 golden-set 评估体系:一套冻结参考标签的 10 例合成 JD 数据集,配合根目录的 eval-golden.mjs 评估框架,将"候选模型 X 是否足够好、可以把这类任务路由给它"从主观猜测变成一个可复现的数字。读完本文,你可以理解其标签方法论(agreement-with-reference)、---SCORE_SUMMARY--- 复用机制、replay/live 双运行模式,以及三个可调常量的默认值与调优方式。
这是什么:一个小标注集 + 一个复用既有契约的框架
该机制的核心目标非常明确:衡量一个候选廉价模型与参考标签的一致程度,从而回答"该模型能否接住某类任务"。它的关键设计选择是不引入新的评分面——直接复用仓库里每个 *-eval.mjs(如 openai-eval.mjs、gemini-eval.mjs、ollama-eval.mjs)已经在产出的 ---SCORE_SUMMARY--- 机器可读块(其中包含 SCORE 与 ARCHETYPE 字段)。因此 golden-set 评估框架不需要重新定义"模型输出长什么样",只需要比对这个既有契约。
README 将其状态标记为 v1:机制本身是设计不变量(design-invariant),当天即可运行;参考标签已冻结(10 个合成用例);门限阈值与单模型成本仍是可调常量;接入 CI 则有意延后。
标签方法论:一致性而非绝对正确
v1 的度量是 agreement-with-reference(与参考的一致性),不是绝对正确性。这一选择并非妥协,而是与其用途精确匹配:#1354 要回答的是"哪个便宜模型能扛住哪类任务",只要候选模型能复现参考判决,把该任务路由给它就是安全的。
参考标签的来源是:一个参考级(Claude 档 / premium)评估器在仓库自身评分标准下对每个合成 JD 的冻结判决。这里引用到的仓库自身标准位于 modes/_shared.md,具体是其中的 Scoring System 一节(五维度合成 1–5 全局分)与 Archetype Detection 一节(6 种 archetypes 的关键词分类法:AI Platform / LLMOps、Agentic / Automation、Technical AI PM、AI Solutions Architect、AI Forward Deployed、AI Transformation)。
两个标签字段地位不同:
archetype是门(gate)。它是 JD 本身的属性——由_shared.md中 6-archetype 关键词分类法决定,与用户 profile 无关,因此可复现、可精确比对(0/1 信号)。score(1–5)是参考模型的匹配判决。它天然相对 profile(profile-relative),但由于参考与候选在同一条件下评分,"与参考的距离"这一度量依然有意义。它是二级、带容差带的信号,不参与门控。
用例集的设计刻意偏向边缘 archetypes 而非容易的赢面:10 个用例覆盖全部 6 种 archetypes,其中 4 个是混合/歧义案例(platform-agentic-hybrid、pm-architect-ambiguous、forward-deployed-vs-architect、transformation-vs-pm)——这正是廉价模型最可能偏离参考的地方;分数区间覆盖 3.2–4.3,使容差带有真实的范围去捕捉红旗岗位上的漂移。
未来升级路径:人工精修标签。冻结参考判决是廉价且可复现的 v1 方案;后续可以用人工评分的 ground truth 替换或对账个别标签(把 provenance 翻转为 hand-curated),且无需改动框架。
目录布局与数据格式
evals/
golden/ 已标注用例 — 每例一个 JSON(合成 JD,无用户数据)
fixtures/ 录制的候选模型输出,供 CI 中 $0 确定性重放
README.md 说明文档
eval-golden.mjs 评估框架(根目录,与 openai-eval.mjs 平级)
Golden case 格式(evals/golden/*.json)
{
"id": "ai-platform-llmops",
"synthetic": true,
"jd": "<完整合成职位描述文本>",
"label": { "archetype": "AI Platform / LLMOps", "score": 4.2, "provenance": "reference-frozen-v1" }
}
字段约束(由框架启动时的校验强制执行,见 eval-golden.mjs):id 必须是字符串,jd 必须是字符串,label.archetype 必须是字符串,label.score 必须是数字,否则整个运行以错误退出。此外:
provenance记录标签的产生方式(v1 全部为reference-frozen-v1,未来人工标签翻转为hand-curated);- 边缘用例可携带
edge_note,解释参考为何如此裁决一个歧义 JD。以 evals/golden/platform-agentic-hybrid.json 为例,其edge_note写道:"hybrid platform+agentic; reference resolves to the platform mandate (observability/evals/reliability) — agentic is the domain, not the job"——即 JD 同时出现平台与 agentic 信号时,参考裁决依据是"mandate 是平台,agentic 只是领域"。 provenance与edge_note均为建议性字段,框架只硬性要求archetype(字符串)与score(数字)。- 所有 JD 都是合成的(
synthetic: true),保证数据集不触碰仓库的no-user-data保护线。
当前 10 个用例的 archetype 分布与分数(来自 evals/golden/ 各 JSON):Agentic / Automation 3.9、AI Forward Deployed 4.3 与 3.9、AI Platform / LLMOps 4.2 与 4.1、AI Solutions Architect 3.4 与 3.7、AI Transformation 3.6 与 3.2、Technical AI PM 4.0——合计 6 种 archetypes、10 例,分数恰在 3.2–4.3 区间。
Fixture 格式(evals/fixtures/)
Fixture 文件是录制好的候选模型输出,命名规则为 <case-id>__<model>.txt。关键实现细节在 eval-golden.mjs 的 fixtureModelId():
function fixtureModelId(m) {
return m.replace(/[^A-Za-z0-9._-]+/g, '-');
}
任何非 [A-Za-z0-9._-] 的连续字符(最典型的是斜杠型 provider id,如 deepseek/deepseek-chat)都被压平为单个 -,变成路径安全的文件名 token(<case>__deepseek-deepseek-chat.txt),确保 fixture 永远落在扁平目录里,不会误入"幽灵子目录"。Fixture 中只有 ---SCORE_SUMMARY--- 块会被解析,前面的说明性文字会被裁掉——这也是 fixture 能保持小而可审查的原因,可对照 evals/fixtures/platform-agentic-hybrid__cheap-stub.txt 查看一个完整实例。
框架工作流:从源码看 eval-golden.mjs
框架的完整执行链在 eval-golden.mjs 中(约 264 行),可以分四段理解。
1. 可调常量(v1 默认值)
const SCORE_TOLERANCE = 0.5; // |候选分数 - 标签分数| ≤ 0.5 才算一致
const MIN_ARCHETYPE_AGREEMENT = 0.8; // archetype 一致率需 ≥ 80% 才通过门
const COST_PER_RUN_USD = {}; // 各模型 $/run,待路由定价确定后填充
2. ---SCORE_SUMMARY--- 解析(与所有 eval 脚本共用契约)
function parseSummary(text) {
const block = text.match(/---SCORE_SUMMARY---\s*([\s\S]*?)---END_SUMMARY---/);
const field = (key) => {
const m = block && block[1].match(new RegExp(`${key}:\\s*(.+)`));
return m ? m[1].trim() : '';
};
return {
score: parseFloat(field('SCORE')),
archetype: (field('ARCHETYPE') || 'unknown').toLowerCase(),
};
}
块缺失或字段损坏时,score 得到 NaN、archetype 回落为 "unknown"——后续统计会把这些异常显式暴露而不是静默吞掉(见下文 summary 部分)。这个正则与 gemini-eval.mjs、openai-eval.mjs 中的解析逻辑同构:各 eval 脚本在 prompt 中要求模型在报告末尾输出该块(字段为 COMPANY / ROLE / SCORE / ARCHETYPE / LEGITIMACY),golden 框架则消费同一个块。
3. 获取候选模型输出:replay 与 live 两条路径
getCompletion() 是整个框架的枢纽(eval-golden.mjs):
- replay(默认):按
<case-id>__<fixtureModelId>.txt读取录制的 fixture。若 fixture 缺失,直接抛错missing replay fixture: … — record it or run --live——即"要么先录制,要么跑 live 产生真实输出"。整条路径离线、确定性、零成本。 - live:把该例 JD 写入临时目录的
jd.txt,然后spawnSync调用现有的 openai-eval.mjs,参数为--file <jd.txt> --model <model> --no-save,超时 360 秒。这样做的意义在于复用真实的 prompt 组装路径(含 cv.md 上下文与完整 Block A–G 报告要求),而不是在框架里复制一份 prompt;退出码非 0 时携带 stderr 前 200 字符抛错。
4. 门控与退出码
每例计算两个量:
archetypeMatch:候选 archetype(小写化)与标签的精确匹配;delta = |parsed.score - label.score|,scoreOk = delta ≤ SCORE_TOLERANCE。
汇总时:
- 门控只看 archetype:
passed = (archetypeHits / cases.length) >= MIN_ARCHETYPE_AGREEMENT,通过后process.exit(0),否则exit(1)。 mean |Δscore|只对有限的 delta 求均值;分数缺失/损坏的用例产生NaN并退出均值计算,同时以(N unscored)显式计数——源码注释点明了动机:"防止模型把失败藏在偏低的均值背后"。- live 模式下额外输出中位延迟(
median(latencies),空数组返回 0);$/run从COST_PER_RUN_USD查表,查不到则打印n/a — TODO(#1354)。
运行方式
对应 package.json 中的脚本 "eval:golden": "node eval-golden.mjs",两条命令:
npm run eval:golden -- --replay --model cheap-stub # 离线、确定性、$0
npm run eval:golden -- --live --model gpt-4o-mini # 经 openai-eval.mjs 真实调用(需要 key + cv.md)
也可以直接 node eval-golden.mjs --help 查看全部参数:--replay(默认)、--live、--model <id>(默认 cheap-stub)、--golden <dir>(默认 evals/golden)、--fixtures <dir>(默认取 --golden 目录的同级 fixtures,这样自定义 golden 目录能自动解析自己的 fixture)。
replay 是 CI 友好路径:不需要 API key、不需要 cv.md、完全确定性。当前仓库中 10 个用例各有一个 cheap-stub fixture,因此 replay 模式开箱即用。框架的典型输出形如:
golden-set eval — model "cheap-stub" (replay), 10 case(s)
✅ platform-agentic-hybrid: archetype ai platform / llmops vs ai platform / llmops (match); score 4.0 vs 4.1 (Δ0.10); replay
...
── summary ──
archetype agreement : 100% (gate ≥ 80%)
mean |Δscore| : 0.05 over 10/10 scored (tolerance ±0.5)
est. $/run : n/a — TODO(#1354)
✅ PASS — archetype agreement meets gate
可调参数与 CI 接入状态
README 把 #1354 的设计问题分成了"v1 已解决"与"仍可调整"两类。已解决的是参考标签的来源与集合规模(从 2 例扩到 10 例、覆盖全部 6 archetypes、分数跨度 3.2–4.3)。仍可调整的三项全部以命名常量形式落在 eval-golden.mjs 中:
| 设计问题 | 所在位置 | v1 默认值 |
|---|---|---|
SCORE 一致性:容差带宽度 |
eval-golden.mjs 中的 SCORE_TOLERANCE |
±0.5(按 distance-to-reference 的带,非精确匹配) |
| CI 门控的 archetype 一致率阈值 | eval-golden.mjs 中的 MIN_ARCHETYPE_AGREEMENT |
0.8 |
| 各模型 $/run 费率 | eval-golden.mjs 中的 COST_PER_RUN_USD |
空——需要真实 provider 费率 |
接入 CI 是有意延后的:README 明确说明,接入必需的 CI 任务(.github/workflows/test.yml)会在阈值被确认之前推迟,以免默认值让 main 变红。由于 replay 路径确定性且零成本,一旦阈值签核,随时可以接线。
小结:这套机制的可借鉴之处
- 度量与用途对齐:路由决策只需要"与参考判决的距离",而不是绝对正确性,这让"冻结参考模型判决"成为合法且廉价的 v1 标签方案,并保留人工精修(
provenance翻转)的升级通道。 - 复用既有机器可读契约:golden 框架没有发明新的输出格式,而是消费所有
*-eval.mjs已经在产出的---SCORE_SUMMARY---块,零新增评分面。 - 门控信号与观测信号分离:archetype 精确匹配做 0/1 门控,score 容差带只做观测,且未评分用例会以
unscored计数显式暴露,避免均值掩盖失败。 - $0 确定性重放:录制的 fixture + 路径安全的模型 id 压平,使整套评估可以在无 key、无
cv.md的环境里重复运行,为将来的 CI 门控铺好了路。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00