Skip to content

Latest commit

 

History

History
190 lines (138 loc) · 11.2 KB

File metadata and controls

190 lines (138 loc) · 11.2 KB

M4 Engineering Verification — Eval-loop v2

Status: ✅ engineering-verified(Phase A+B 完成 2026-06-01,billing-adapted) CI: .github/workflows/eng-m4.yml 编写完毕;结构性 smoke 本地验证通过;GitHub 自动跑 deferred:billing(finding-011 继承限制) v1 baseline: weighted_score 0.712,71 case,judge schema_failures 0,case_errors 2(首个有意义的 baseline;此前所有 baseline 均为 async-gen 缺陷产生的伪像,已作废) Owner: 本 session 协作产出 Source-of-truth M4 docs:

  • Spec: docs/superpowers/specs/ M4 相关条目
  • 硬标准: 07-Phase7-实战篇-从零到生产.md + 08-可观测与可评估Agent深度设计.md 依赖前提:M0/M1/M2a/M2b/M2b-Obs/M2c/M3 engineering-verified。M4 在其基础上闭合 eval 循环。

1. Scope — M4 Eval-loop v2

M4 分三个 Phase:

  • Phase A:修复 M3 deferred findings(016/017/018/019/010/020)
  • Phase B:校准 v1 baseline(修复 eval 管线自身的 finding-021 ~ finding-026,跑出可信的第一条 baseline)
  • Phase C(deferred):3 轮 prompt 优化迭代(advisor prompt → baseline 提升 → 写 insight doc)

Phase A+B 已 engineering-verified(本文档所覆盖范围)。Phase C 推迟——在 v1 baseline 稳定后的下一 session 执行。


2. The Finding Saga — 12 个 Finding 的修复链

Phase A+B 期间共修复 12 个 finding(含此前 deferred 的)。finding-024 是核心:它揭示了 agent 自 M2b 起从未真正执行工具调用,所有此前的 eval baseline 均为伪像。

Finding Title(一行) Fix commit Status
010 SSE last token duplicated 7a38421 fixed
016 Tantivy BM25 422/400:DSL metachars(-/://)+ >200-char query db691ce, cfe7e80, 253d39f fixed
017 TEI rerank 总是 5s-timeout(Rosetta emulation 下 bge-reranker-v2-m3 per-call 慢) d54ed26 fixed
018 Self-Eval hits iter cap(016/017 下游症状,随 016/017 修复自愈) 7210f20 fixed
019 auth 错误被分类为 INTERNAL_ERROR 而非 UPSTREAM_LLM_ERROR 8ce8655 fixed
020 advisor 偶发输出良性 https:// URL(观察,非 M3 多模态缺陷) closed-observation
021 HyDE/multi_query ValidationError ABORT 整个 gold-set 批次 08b70a8 fixed
022 run_gold_set 单 case 异常中止整个 71-case 批次 a4dfb93 fixed
023 eval 从 terminal state 读 advisor 输出全为空(被 024 supersede) b78eaa1 superseded-by-024
024 CORE:agent 工具调用循环从未真正执行(async-gen state 传播缺陷,自 M2b 起) b3d0118, 9726c49 fixed
025 judge JSON 截断:中文 reasoning_brief unicode escape 膨胀超过 max_tokens=2048,46/71 case 评分丢失 88ea956 fixed
026 run_gold_set case 级无限挂起(工具循环真正运行后,hang 不被 exception 保护覆盖) ee3b7be fixed

Finding-024 详解(Headline)

现象:advisor 生成了含 2 个 ToolUseBlock 的响应(Langfuse 可见),但 _route_after_advisor 始终看到 _pending_tool_use=False → 路由永远到 ENDtool_dispatch_node 从未执行 → 所有工具(get_product_details / compare_products / emit_cards 等)从未运行 → advisor 的输出只是开场白 preamble → 不含真实规格数据,不含商品卡片。

Root causeadvisor_nodetool_dispatch_node 被实现为 async generator(用 yield 流式推送 token),同时原地修改 state dict。LangGraph StateGraph 的 channel 系统只 commit 节点函数 RETURN 的 delta dict;yield 的原地 mutation 不进 channel,router 读到的永远是 init state。

Fix(user-approved §4 locked-core refactor)

  1. 两节点改为普通 async defRETURN state delta dict
  2. 流式 token/card/tool 事件改用 get_stream_writer() 写入 custom stream channel
  3. run_graphGRAPH.astream(stream_mode=["custom","updates","debug"])
  4. 消费侧(SSE handler + run_gold_set)适配新 stream 格式
  5. SpanHook 从实时 debug task/task_result 事件取 latency_ms + input(恢复真实可观测数据)

Live 验证(首次真正运行工具循环):tool_dispatch 节点执行 → get_product_details×2 + emit_cards 执行 → CardEvent 发出 → final_answer 含真实规格(5300mAh / 90W)。


3. V1 Baseline — 首个有意义的 baseline

重要:M2b-Obs 起到 finding-024 修复前,所有 eval baseline 都是在"工具从未运行,advisor 只输出开场白"的条件下产生的,属于统计伪像。以下是 finding-024 修复 + eval 管线修复(021-026)后产出的第一个可信 baseline(commit 3d3e0d0)。

核心指标

指标
weighted_score 0.712
case_count 71
judge schema_failures 0(judge JSON 截断问题已彻底修复)
case_errors 2(error_005、error_103 — 空 query → advisor empty-content 400)
CI gate exit 1(2 个 errored case safety=0.0 < SAFETY_FLOOR=0.5 → 正确行为,informative 非 run failure)

5 维度分解

维度 权重 得分 说明
task_completion 30% 0.701 任务完成度基线合理
output_quality 30% 0.713 输出质量,真实规格数据驱动
process_quality 20% 0.885 最强维度,工具循环 + 推理链完整
efficiency 10% 0.291 最弱维度——retrieval ~35s/case,latency-bound
safety 10% 0.819 安全行为良好(除 2 个 empty-query edge case)

5 类别分解

类别 得分 说明
happy 0.696 主流路径
edge 0.715
error 0.623(最低) 2 个 errored case 拉低
adversarial 0.818 对抗场景表现最好
regression 0.685

Cohort 对比

Cohort 得分
cross-modal(有图) 0.705
no-image(纯文) 0.714

跨模态与纯文本得分基本持平(±0.009),多模态路径与文本路径质量相当。

Efficiency 分析

efficiency=0.291 是当前最明显的优化方向。主要瓶颈:

  • TEI reranker latency(Rosetta emulation 下 bge-reranker-v2-m3 每次 ~10s)
  • Self-Eval LLM 仲裁(finding-018 修复后 iter cap 消失,但仍有 1 轮 LLM 调用)
  • 整体 retrieval pipeline ~35s/case

Phase C prompt 优化可部分改善(减少不必要的工具调用轮次);硬件/部署优化(TEI native arm64 / batch size 调整)是长期项。


4. Meta-lesson — 验证 Agent 必须检查工具是否真正运行

教训:M2b / M2b-Obs / M2c / M3 的工程验证(共 4 个 session)均声称"工具接入"和"卡片出库",但实际上工具循环从未执行。这 4 次验证的检查项包括:

  • 单测通过(工具定义 / dispatch cap / emit_cards 路由)
  • SSE 事件流有文字输出(token + done)
  • Langfuse trace 有 span 树
  • CI workflow 绿

这些检查全部通过,但工具循环仍然没有运行。 原因:上述检查都是结构性或流式检查,没有一项直接验证"工具 X 的返回值出现在 advisor 的后续 LLM 上下文中"或"emit_cards 的 product_id 来自真实 Postgres 数据"。

正确的工具执行验证清单

  1. _pending_tool_use 在 router 被读到时是 True(不是 init state)
  2. tool_dispatch_node 的执行日志/span 真实出现在 trace 里
  3. final_answer 包含只有工具调用才能获得的真实规格数据(如"5300mAh / 90W")
  4. CardEvent 中的 product_id 与 Postgres 中真实存在的 product 对应
  5. gold-set 评分中 process_quality(包含工具调用链评分)显著高于零

finding-024 之后,上述 5 项均已通过。这条 meta-lesson 应成为后续里程碑(M5/M6)工程验证的标准检查项之一。


5. Billing-adapted CI(finding-011 继承限制)

eng-m4.yml 与 M3 保持一致的"结构性 smoke"策略:

  • CI 内(structural-only)
    • J1:advisor_node / tool_dispatch_node 不再 yield state dict(finding-024 回归守卫)
    • J2:run_gold_set 有 per-case try/except(finding-022 回归守卫)
    • J3:run_gold_set 有 per-case timeout(finding-026 回归守卫)
    • J4:judge max_tokens >= 4096(finding-025 回归守卫)
    • 全量 unit/structural test suite(not integration, not e2e)
    • gold-set load validation(import + assert 71 cases,NO real run)
    • ruff lint + format check
  • 本地 only(需要真 LLM):真实 eval 运行、baseline 校准、Langfuse/Grafana 面板

finding-011 已确立"CI 只做结构性 smoke,真 LLM 流本地跑"的策略。GitHub Actions 自动跑等账单恢复后激活;不削弱实质验证。


6. Status Summary

Phase 状态
Phase A — 修复 deferred findings(010/016-020) ✅ 完成
Phase B — 修复 eval 管线(021-026)+ 跑 v1 baseline ✅ 完成
Phase C — 3 轮 prompt 优化迭代 ⏳ deferred(下一 session)

2 个遗留 errored case(error_005 / error_103,空 query → empty-content 400):advisor 在空 query 时返回 empty-content 会触发 Anthropic 400,导致 safety=0.0。Phase C 修复方向:orchestrator 或 intent 层加空 query 守卫,在到达 advisor 前截断。

efficiency 提升空间:TEI reranker 改用 native arm64 镜像(如可用)、batch size 从 20 降到 8(finding-017 临时修复方向的改进空间)、advisor prompt 压缩减少工具调用轮次——这些都是 Phase C 的优化方向。


Progress log

2026-06-01 · Phase A — deferred findings 修复

  • finding-016:Tantivy BM25 client 加 content-guard(T3,db691ce)+ server 端 sanitize DSL metachars + 提升 length bound(T9a,cfe7e80, 253d39f
  • finding-017:TEI reranker candidates 20→8 + timeout 5s→10s(d54ed26
  • finding-018:016/017 修复后 Self-Eval iter cap 自愈 + 回归守卫(7210f20
  • finding-019:FallbackChain 用尽时保留最后一个 typed exception(8ce8655,M2a 锁定层,user-approved)
  • finding-010:SSE last token dedup by chunk object identity(7a38421
  • finding-020:closed-observation(advisor URL 行为待 Phase C spot-check)

2026-06-01 · Phase B — eval 管线修复 + v1 baseline 校准

  • finding-021:HyDE/multi_query ValidationError 降级到 passthrough(08b70a8
  • finding-022:run_gold_set per-case try/except + systemic-failure guard(a4dfb93
  • finding-023:eval-side stream reconstruction(b78eaa1,被 024 supersede)
  • finding-024:CORE refactor — nodes return delta + get_stream_writer + astream debug mode(b3d0118, 9726c49
  • finding-025:judge max_tokens 2048→4096 + terse reasoning_brief + truncate-not-reject(88ea956
  • finding-026:run_gold_set per-case timeout 300s(ee3b7be
  • v1 baseline 跑出(commit 3d3e0d0):weighted_score 0.712,71 case,0 schema_failures,2 errored case
  • eng-m4.yml 编写完毕(结构性 smoke,4 J-级守卫 + unit + gold-load + ruff)
  • M4 wrap 文档写完(本文件 + _findings.md 追加 + README M4 行更新 + m2b/m3 更正注)