evaluation: add PromptIter regression loop#2278
Conversation
Add a deterministic evaluation, failure-attribution, PromptIter optimization, validation-regression, acceptance-gate, and audit-report pipeline. Include runnable train and validation fixtures, generated reports, extensive tests, and Chinese learning documentation. Also make PromptIter backward schemas compatible with OpenAI-compatible providers that reject empty enums and zero maxItems while retaining strict response validation. Fixes trpc-group#2003 RELEASE NOTES: Added an API-key-free PromptIter regression loop example with explainable failure attribution, configurable safety gates, and JSON/Markdown audit reports.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughEnglishOverview
Public API and compatibility implications (exported Go surface)This PR significantly expands the exported API in Core workflow interfaces/constructors/execution
Data models/constants for evaluation, deltas, attribution, gating, config, and reports
Loaders/validators/utilities
Compatibility questions to confirm before downstream adoption
Behavioral and operational risks
Recommended validation
中文概览
公共 API 与兼容性影响(导出 Go 表面)本 PR 在 核心工作流接口/构造/执行
用于评测/归因/门禁/配置/报告的导出数据模型与常量
加载/校验/工具
下游采用前建议确认的兼容性问题
行为与运行风险
建议验证
WalkthroughThe pull request adds a deterministic PromptIter regression workflow with strict validation, local evaluation, multilingual failure attribution, candidate provenance checks, delta and gate evaluation, atomic JSON/Markdown reporting, runnable example data, and a backwarder schema compatibility fix. ChangesPromptIter regression workflow
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
All contributors have signed the CLA ✍️ ✅ |
|
I have read the CLA Document and I hereby sign the CLA |
|
recheck |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
evaluation/workflow/promptiter/backwarder/backwarder.go (1)
312-321: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDead empty-collection conditional in both backward schema helpers. Removing
maxItems: 0left thelen(...) == 0branch returning the exact same array schema as the fallthroughreturn, so the conditional no longer does anything in either helper.
evaluation/workflow/promptiter/backwarder/backwarder.go#L312-L321: drop theif len(surfaceIDs) == 0block and keep the singlereturninbackwardGradientArraySchema.evaluation/workflow/promptiter/backwarder/backwarder.go#L362-L371: drop theif len(predecessorStepIDs) == 0block and keep the singlereturninbackwardPropagationArraySchema.中文
两个 backward schema 辅助函数中的空集合条件已成死代码。 去掉
maxItems: 0后,len(...) == 0分支返回的数组 schema 与后续return完全相同,两个函数中的该条件判断均已无实际作用,建议直接删除并保留单个return。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@evaluation/workflow/promptiter/backwarder/backwarder.go` around lines 312 - 321, Remove the redundant empty-collection conditional from backwardGradientArraySchema at evaluation/workflow/promptiter/backwarder/backwarder.go:312-321 and retain one array-schema return. Apply the same cleanup to backwardPropagationArraySchema at evaluation/workflow/promptiter/backwarder/backwarder.go:362-371, removing its len(predecessorStepIDs) branch and preserving the shared return.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@evaluation/workflow/promptiter/backwarder/backwarder.go`:
- Around line 312-321: Remove the redundant empty-collection conditional from
backwardGradientArraySchema at
evaluation/workflow/promptiter/backwarder/backwarder.go:312-321 and retain one
array-schema return. Apply the same cleanup to backwardPropagationArraySchema at
evaluation/workflow/promptiter/backwarder/backwarder.go:362-371, removing its
len(predecessorStepIDs) branch and preserving the shared return.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 71d7452e-3be1-41bf-afa4-019a444ea724
📒 Files selected for processing (35)
evaluation/go.modevaluation/workflow/promptiter/backwarder/backwarder.goevaluation/workflow/promptiter/backwarder/backwarder_test.goevaluation/workflow/promptiter/regression/attribution.goevaluation/workflow/promptiter/regression/attribution_negation_test.goevaluation/workflow/promptiter/regression/binding_test.goevaluation/workflow/promptiter/regression/config.goevaluation/workflow/promptiter/regression/delta.goevaluation/workflow/promptiter/regression/delta_gate_test.goevaluation/workflow/promptiter/regression/evaluator.goevaluation/workflow/promptiter/regression/evaluator_attribution_test.goevaluation/workflow/promptiter/regression/gate.goevaluation/workflow/promptiter/regression/load.goevaluation/workflow/promptiter/regression/load_test.goevaluation/workflow/promptiter/regression/optimizer.goevaluation/workflow/promptiter/regression/pipeline.goevaluation/workflow/promptiter/regression/report.goevaluation/workflow/promptiter/regression/report_pipeline_test.goevaluation/workflow/promptiter/regression/similarity.goevaluation/workflow/promptiter/regression/similarity_test.goevaluation/workflow/promptiter/regression/strict_trace_test.goevaluation/workflow/promptiter/regression/types.goevaluation/workflow/promptiter/regression/usage.goexamples/evaluation/promptiter_regression_loop/DESIGN.mdexamples/evaluation/promptiter_regression_loop/LEARNING_GUIDE.zh_CN.mdexamples/evaluation/promptiter_regression_loop/README.mdexamples/evaluation/promptiter_regression_loop/baseline_prompt.txtexamples/evaluation/promptiter_regression_loop/data/metrics.jsonexamples/evaluation/promptiter_regression_loop/data/train.evalset.jsonexamples/evaluation/promptiter_regression_loop/data/validation.evalset.jsonexamples/evaluation/promptiter_regression_loop/main.goexamples/evaluation/promptiter_regression_loop/main_test.goexamples/evaluation/promptiter_regression_loop/promptiter.jsonexamples/evaluation/promptiter_regression_loop/sample_output/optimization_report.jsonexamples/evaluation/promptiter_regression_loop/sample_output/optimization_report.md
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #2278 +/- ##
===================================================
- Coverage 89.86563% 89.80154% -0.06409%
===================================================
Files 1144 1162 +18
Lines 198483 206590 +8107
===================================================
+ Hits 178368 185521 +7153
- Misses 12602 13167 +565
- Partials 7513 7902 +389
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
recheck |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
evaluation/workflow/promptiter/regression/codecov_boundaries_test.go (1)
334-359: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winGate test mutates shared pointer-backed summaries and relies on manual resets.
GateInputis copied by value, butBaselineValidation/CandidateValidationare pointers, soinput.BaselineValidation.Usage.ModelCalls = 1(Line 351) andinput.CandidateValidation.Usage.ToolCalls = 1(Line 356) mutate the sharedbaseline/candidatesummaries in place. Correctness then hinges on the manual resets at Lines 354 and 359 holding, because the samebaseline/candidateare reused downstream (e.g.,ComputeDelta(baseline, regressed)at Line 373 and the overflow check at Lines 404-409). A future edit that reorders these sub-checks or forgets a reset would silently break isolation without an obvious failure. Consider cloning the summaries (orvalid) per sub-check so each assertion runs against pristine state.中文
门禁测试就地修改共享指针字段并依赖手动复位。
GateInput按值拷贝,但BaselineValidation/CandidateValidation是指针,因此第 351、356 行通过input修改的其实是共享的baseline/candidate。正确性依赖第 354、359 行的手动复位,而这两个对象在后续(第 373 行ComputeDelta、第 404-409 行溢出用例)被复用。若日后重排子用例或漏掉复位,隔离会被悄悄破坏且不易察觉。建议为每个子检查克隆 summary(或valid),使断言基于干净状态运行。(依据 *_test.go 路径规范:优先保证测试对外部可观测行为的确定性与隔离性。)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@evaluation/workflow/promptiter/regression/codecov_boundaries_test.go` around lines 334 - 359, Isolate each validation sub-check in the gate test from the shared pointer-backed baseline and candidate summaries. Update the cases around EvaluateGate, especially the baseline and candidate gate usage checks, to clone valid or the relevant summaries before mutation, then remove reliance on manual resets so later ComputeDelta and overflow checks always use pristine baseline and candidate data.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@evaluation/workflow/promptiter/regression/codecov_boundaries_test.go`:
- Around line 334-359: Isolate each validation sub-check in the gate test from
the shared pointer-backed baseline and candidate summaries. Update the cases
around EvaluateGate, especially the baseline and candidate gate usage checks, to
clone valid or the relevant summaries before mutation, then remove reliance on
manual resets so later ComputeDelta and overflow checks always use pristine
baseline and candidate data.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 7562c387-c810-47c4-afa2-67bb44a14ce8
📒 Files selected for processing (1)
evaluation/workflow/promptiter/regression/codecov_boundaries_test.go
What changed
本 PR 完成 #2003 要求的“评测 → 失败归因 → Prompt 优化 → 验证集回归 → 接受门禁 → 产物审计”自动闭环,并提供无需 API Key 即可复现的完整样例。
1. 新增可复用的回归闭环包
在
evaluation/workflow/promptiter/regression新增以下能力:Pipeline:依次运行 baseline train/validation、训练失败归因、PromptIter 候选生成、候选 train/validation 重跑、逐 case delta、gate 决策和报告组装;所有候选轮次均保留,最终只选择通过 gate 且验证集得分最高的候选。LocalEvaluator:支持 deterministic fake model 与 strict trace replay;按 final response、tool trajectory、route、structured output、knowledge recall 和 LLM rubric 等信号加权评分。final_response_mismatch、tool_call_error、tool_parameter_error、route_error、format_error、knowledge_retrieval_insufficient,每个失败 case 至少包含一个带证据与置信度的可解释原因;针对中文否定表达、错误/失败状态和互相矛盾的 trace 信号做了保守判定。Profile、PatchSet、SurfaceID等领域契约,根据训练集归因生成确定性的 instruction patch;候选 Prompt、Profile override 和 PatchSet value 必须完全绑定。new_pass、new_failure、improved、regressed、不变、缺失和意外 case,并给出各 metric delta;case/metric 覆盖不完整时 fail closed。EvaluationSummary保存实际passThreshold,delta/gate 会重新推导 pass 状态并拒绝阈值漂移,防止伪造Passed绕过门禁。optimization_report.json和人类可读的optimization_report.md,记录 baseline、每轮 candidate、逐 case delta、归因统计、gate 每项判定与拒绝原因、Prompt/哈希、seed、fake/trace 配置、模型配置、usage、cost 和 latency。2. 新增完整可运行样例
新增
examples/evaluation/promptiter_regression_loop:3. 改善 OpenAI-compatible structured output 兼容性
修复 PromptIter backward schema 在空 surface/predecessor 集合时生成
enum: []和maxItems: 0的问题。部分 OpenAI-compatible provider 会在 grammar 编译阶段拒绝这类 schema;现在空集合仍声明合法 item shape,但省略空 enum/零 maxItems,运行时 sanitizer 继续严格拒绝模型返回任何无效 surface 或 predecessor,因此兼容性提升不会放宽业务约束。4. 文档与测试
DESIGN.md用 300–500 字说明失败归因、接受策略、防过拟合、PromptIter 接入和审计方式。LEARNING_GUIDE.zh_CN.md详细介绍 Evaluation、PromptIter、闭环架构与原理,并逐段走读核心实现、样例数据、报告和生产接入方式。Why
现有 Evaluation Service 与 PromptIter 分别解决“如何评价”和“如何生成候选”,但缺少生产落地所需的验证集隔离、逐 case 回归、过拟合阻断、预算限制和审计证据。本实现将两者通过稳定接口组合起来,并以 fake/trace 模式提供离线确定性基准;生产环境可以替换
Evaluator/Optimizeradapter,同时复用同一套 delta、gate 和 report 逻辑。Result
默认样例结果:
candidate-overfitcandidate-balanced0.522041,validation0.720000。0.797193,validation0.856667。unchanged_failure,证明系统不会把“改了 Prompt”误判为“所有 case 已修复”。0.59s,显著低于 3 分钟验收限制。How to run
无需设置任何 API Key:
输出:
output/optimization_report.jsonoutput/optimization_report.md也可以通过
-timeout修改总超时,或在promptiter.json中切换fake/trace模式及调整 gate、seed、候选 patch 和预算。Testing
已执行并通过:
evaluation/workflow/promptiter/regression当前 statement coverage 为78.3%。同时使用真实 OpenAI-compatible endpoint 完成过 PromptIter backward 与一轮 train/validation 闭环 smoke test;凭据仅通过进程环境传入,未写入代码、配置、报告或 Git 历史。Notes for reviewers
pipeline.go的数据隔离/候选选择、delta.go的完整性检查、gate.go的 fail-closed 策略、evaluator.go/attribution.go的证据判定,以及 backward schema 空集合兼容性修改。Fixes #2003
RELEASE NOTES: Added an API-key-free PromptIter regression loop example with explainable failure attribution, configurable safety gates, and JSON/Markdown audit reports.