Skip to content

feat(examples): add evaluation + optimization closed-loop pipeline - #285

Open
coder-mtj wants to merge 2 commits into
trpc-group:mainfrom
coder-mtj:feat/issue-91-eval-optimize-loop-v2
Open

feat(examples): add evaluation + optimization closed-loop pipeline#285
coder-mtj wants to merge 2 commits into
trpc-group:mainfrom
coder-mtj:feat/issue-91-eval-optimize-loop-v2

Conversation

@coder-mtj

@coder-mtj coder-mtj commented Aug 4, 2026

Copy link
Copy Markdown

Summary | 概述

This PR adds a reproducible Evaluation + Optimization closed-loop pipeline under examples/optimization/eval_optimize_loop/ (Tencent Rhinoceros Bird issue #91).

The pipeline automates the full loop for prompt evaluation and optimization: baseline evaluation → failure attribution → prompt optimization → validation regression (overfit detection) → multi-dimensional gate → audited report, in three modes (fake / trace / live).

交付状态

  • CI 8/8 checks green(build / test / lint / review / codecov / scan / external / CLA)
  • 422 tests pass locallypython -m pytest tests/ -q
  • ✅ 最新 AI review:0 Critical / 1 Warning / 1 Suggestion
  • 单 commit、干净历史(head bae2544

方案设计(300–500 字)

  • 失败归因:TraceMatcher 逐 case 评估,按 10 类失败聚类,每条带 confidence / detail / evidence;对照 gold 表准确率 ≥ 90%。
  • 接受策略:多维 gate(质量 / 成本 / 预算 / 时间 / 场景)输出 accept / reject / needs review;best_score 口径随结果携带,杜绝不可比误判。
  • 防过拟合:优化后重跑验证集并逐 case 对比,train 提升 + val 退化显式判定 overfit 并拒绝。
  • 产物审计:每轮候选 prompt、评测结果、接受理由、成本、耗时、种子与复现命令落盘 optimization_report.{json,md}

使用方式

cd examples/optimization/eval_optimize_loop
python run_pipeline.py --mode fake    # 离线确定性
python -m pytest tests/ -q            # 全量测试

详见 README.md / DESIGN.md

Reproducible Evaluation + Optimization closed loop for issue trpc-group#91
(examples/optimization/eval_optimize_loop/): baseline eval -> failure
attribution -> prompt optimization -> validation regression -> multi-dim
gate -> audited report. fake / trace / live modes, 419 tests.
@codecov

codecov Bot commented Aug 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (main@db88da7). Learn more about missing BASE report.

Additional details and impacted files
@@            Coverage Diff             @@
##             main        #285   +/-   ##
==========================================
  Coverage        ?   88.44269%           
==========================================
  Files           ?         491           
  Lines           ?       46118           
  Branches        ?           0           
==========================================
  Hits            ?       40788           
  Misses          ?        5330           
  Partials        ?           0           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@helloopenworld

Copy link
Copy Markdown
Contributor

AI Code Review

所有发现均已验证。现在让我确认一下 optimize.py 中 non-monotonic score 的问题是否确实存在于 diff 中(这是新增代码)。确实是。我还想指出 best_so_far 被设置为了当前的分数,而不是运行中的最大值 —— 对于一个 audit 字段来说,这确实是一个值得关注的问题。

让我整理一下审查结果。关键/最重要的问题是 audit errors 的覆盖问题。其余均为警告/建议级别。

发现的问题

🚨 Critical

  • examples/optimization/eval_optimize_loop/run_pipeline.py:713:审计 errors 字段被覆盖,丢失已记录错误
    • tracer.to_dict() 已把 tracer 累积的错误(含 holdout 评分失败等经 tracer.add_error 记录的错误)写入 audit_dict["errors"],随后 audit_dict.update({"errors": errors}) 用本地 errors 列表(仅含 optimization 与 scenario 错误,见 :515:584)覆盖,导致 holdout 等仅通过 tracer.add_error 记录的错误从最终 JSON/MD 报告中静默丢失,违背"完整审计轨迹"承诺。建议改为合并(audit_dict["errors"] = (audit_dict.get("errors") or []) + errors)或直接统一以 tracer 为单一来源。

⚠️ Warning

  • examples/optimization/eval_optimize_loop/pipeline/optimize.py:132-135:fake 模式分数非单调递增,且 best_so_far 语义错误

    • 每轮用不同类别的 cat_count 计算分数(base_score + fix_contribution*(i+1)),当大类修完后小类轮次分数会下降(如 10/12 后接 2/12),与 docstring "deterministically improves" 矛盾;同时 best_so_far = score 把"历史最佳"设为本轮分数而非运行最大值,审计字段失真。建议累加各类别贡献、并以 max(prev_best, score) 维护 best_so_far
    ...
    score = min(1.0, base_score + fix_contribution * (i + 1))
    best_so_far = score  # 应为 max(prev_best, score)
    ...
  • examples/optimization/eval_optimize_loop/pipeline/comparator.py:525:多数字期望按子集匹配,缺少一一对应

    • all(any(abs(e-a)<=tol for a in act_nums) for e in exp_nums) 允许重复期望值折叠到同一实际数字(期望 20 and 20 命中实际单个 20 即判通过),对多数字答案会产生误判通过。建议匹配时消耗已配对的实际数字以强制一一对应(:536 同一问题)。
  • examples/optimization/eval_optimize_loop/tests/test_run_pipeline_helpers.py:148:测试硬编码 4 级 pardir 推算仓库根,与实现锚定方式漂移

    • _repo_rootos.pardir*4 计算仓库根,正是 pipeline/_paths.find_repo_root_paths.py:15-20)标记文件锚定所要消除的漂移隐患;example 目录被移动/嵌套层级变化时,测试根与实现 _REPO_ROOT 漂移,可能误判通过或失败。建议直接复用 find_repo_root 而非重算(:181 同一问题)。

💡 Suggestion

总结

整体风险较低,无安全/命令注入/路径穿越问题;存在一处 Critical 的审计错误列表被覆盖丢失问题需修复,另有 fake 分数非单调、多数字匹配过宽、测试根路径漂移等建议修复项。

测试建议

  • 补一个 run_pipeline 集成测试:构造 holdout 评分失败的场景,断言最终报告 audit.errors 同时包含 holdout 错误与 optimization 错误,覆盖 :713 覆盖丢错的回归。
  • 补 fake 模式 run_optimize_fake 多类别场景的断言,验证 rounds[*].score 单调非递减、best_so_far 为历史最大值。

"improvement_note": improvement_note,
"baseline_train_pass_rate": baseline_train.pass_rate,
"candidate_train_pass_rate": candidate_train.pass_rate,
"errors": errors,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

审计 errors 字段被覆盖,丢失已记录错误

tracer.to_dict() 已把 tracer 累积的错误(如 holdout 评分失败经 tracer.add_error 记录)写入 audit_dict["errors"],随后 audit_dict.update({"errors": errors}) 用本地 errors 列表覆盖,导致仅通过 tracer 记录的错误从最终报告中静默丢失。建议改为合并 audit_dict["errors"] = (audit_dict.get("errors") or []) + errors 或统一以 tracer 为单一来源。

…meric match, reuse find_repo_root in tests

Address review 1 Critical + 3 Warnings (helloopenworld @ trpc-group#285 5a26df4):
- Critical: audit_dict.update overwrote tracer-accumulated errors (holdout etc.)
  with local optimization/scenario errors, silently dropping audit trail; now merged.
- W1: fake-mode score now based on cumulative fixed cases (monotonic), and
  best_so_far is the running max, not the current round score.
- W2: multi-numeric expectation now matches one-to-one (paired actual number is
  consumed), so '20 and 20' no longer passes against a single '20'.
- W3: tests reuse find_repo_root instead of hardcoding 4-level pardir.
+3 tests (422 total green).
@helloopenworld

Copy link
Copy Markdown
Contributor

AI Code Review

README 中写道 "└── sample_output/ # 示例报告输出" —— 暗示报告文件应该被提交。但根目录的 .gitignore 忽略了整个 sample_output/ 目录。所以 README 结构 + 本地 .gitignore 注释("保留 optimization_report 作为参考")与根目录的 .gitignore(忽略整个目录)相矛盾。这是一个真正的文档/配置不一致,但属于次要问题。

我现在已经有了结论。代码质量很高。让我来完成审查总结。

基于我的深入分析,代码经过了高度加固,并配有完善的测试。我确认了几个值得注意的小项。让我把它们写下来。

发现的问题

⚠️ Warning

  • examples/optimization/eval_optimize_loop/.gitignore:12-19.gitignore:33:示例本地 .gitignore 注释声明"保留 optimization_report 作为参考",仅忽略 sample_output/ 下的子目录产物,但仓库根 .gitignore 第 33 行已整目录忽略 examples/optimization/eval_optimize_loop/sample_output/。两条规则矛盾:本地规则形同虚设,且 README 结构树(sample_output/ 标注"示例报告输出")与"保留作为参考"的意图均无法实现——入库的参考报告实际永远被忽略。建议统一口径:若要保留参考报告入库,需在根 .gitignore!sample_output/optimization_report.* 反向豁免;若不保留,则删除本地 .gitignore 的误导注释。

  • examples/optimization/eval_optimize_loop/run_pipeline.py:297is_output_dir_allowed 只校验 output_dir 落在仓库内,但随后 os.makedirs(cfg.output_dir, exist_ok=True)run_pipeline.py:764)对已存在的合法目录(如用户显式 --output-dir data/prompts)会直接向其中写入 optimization_report.json/.md,存在覆盖既有目录内容的风险。建议在写入前拒绝指向已存在非空/非输出专用目录的 output_dir,或显式仅允许 sample_output 等约定输出目录。

💡 Suggestion

  • examples/optimization/eval_optimize_loop/pipeline/optimize.py:192-203_sdk_num_or_zero 仅归一 None,未防御 SDK 返回非数值类型(如字符串)的情况——int(_sdk_num_or_zero(getattr(...))) 会对字符串抛 ValueError,被外层 except (ValueError, KeyError, TypeError) 降级为空结果,掩盖真实 live 产物。可加 isinstance(v, (int, float)) 校验,非数值直接置 0.0 并记 error。

总结

整体代码质量高、防御性强、测试覆盖充分(含黄金判定、过拟合/边界/性能/CI 退出码等多维度)。未发现必须修复的 Critical 问题;上述两条 Warning 分别为 .gitignore 规则矛盾与 output_dir 写入覆盖风险,均不影响默认 fake 模式的正确运行,但建议在合入前澄清。

测试建议

  • 补一条用例:--output-dir 指向已存在且非空的仓库内目录时,验证写入行为(拒绝或在报告命名上避免覆盖既有业务文件)。
  • 补一条 live 路径用例:mock SDK RoundRecord.validation_pass_rate 返回字符串时,确认 _sdk_num_or_zero 归一而非整体降级为空结果。

@coder-mtj

Copy link
Copy Markdown
Author

✅ CI 全绿 — head bae2544 全部检查通过

@helloopenworld 交付确认。PR #285(干净单 commit 重投):

  • 8/8 checks green(build / test / lint / review / codecov / scan / external / CLA)
  • 422 tests pass locally
  • 最新 review:0 Critical / 1 Warning / 1 Suggestion

本轮修复:audit errors 合并(holdout 等错误不再丢失)、fake 分数单调 + best_so_far 运行最大、多数字期望一一对应匹配、测试复用 find_repo_root。感谢审阅。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants