docs/adr/0017-decode-eval-suite.mdXem bản gốc Bản dịch đầy đủ theo đúng cấu trúc tài liệu; code, liên kết và định danh kỹ thuật được giữ nguyên.
0017 — bộ decode eval: demo, benchmark, thăm dò hồi quy, khai thác Opik
Trạng thái: Đã chấp nhận Ngày: 2026-07-13
Bối cảnh
decode có dấu vết (ADR-0014) nhưng không có cách nào để trả lời "sự thay đổi này làm cho agent tốt hơn hay
tệ hơn?". Chúng tôi muốn: (a) bản trình diễn giới thiệu do con người đánh giá, (b) điểm chuẩn kết quả ("nó có thể thực hiện được
nhiệm vụ?"), (c) bộ hồi quy hành vi khai thác ("nó có hoạt động ĐÚNG không?" - công cụ phù hợp,
khác biệt tối thiểu, cổng được tôn trọng) và (d) thúc đẩy cơ sở hạ tầng đánh giá Opik (b) và (c) —
trong một cơ sở mã giáo dục nơi logic chấm điểm phải dễ đọc và cơ sở hạ tầng
được nhập khẩu, không trừu tượng. Hạn chế: tests/ gương src/ 1:1; bánh xe chỉ tàu
src/decode; việc truy tìm Opik hiện tại không được bị xáo trộn; make ci phải không có đánh giá (evals
cần khóa API và tốn tiền). Không phải mục tiêu: Bộ điều hợp băng ghế đầu cuối/bàn ghế SWE, giao diện người dùng bảng xếp hạng,
sự tham gia của proxy thông tin xác thực, best@k/majority-vote, mô phỏng người dùng.
Quyết định
- Vị trí: cấp cao nhất
evals/, khôngsrc/decode/evals/. Mã đánh giá là tài liệu khóa học về agent, không phải một phần của nó -[tool.hatch.build.targets.wheel]đã chỉ giao hàngsrc/decode, vì vậy bánh xe không bị ảnh hưởng với cấu hình xây dựng bằng không. Kiểm tra đơn vị cho mã khai thác trực tiếptests/unit/evals/(phản chiếuevals/chính xác nhưtests/unit/decode/gươngsrc/decode/): MỘT gốc pytest có nghĩa làmake unit-tests, pre-commit hooks và CI bao gồm khai thác ngoại tuyến logic miễn phí. Một ngoại lệ có chủ ý làevals/regression/test_thresholds.py- một mô-đun tốn tiền, yêu cầu chìa khóa được giữ BÊN NGOÀItestpathsvà chỉ được gọi bởimake eval-regression. - Bốn đường đua, ba phong cách phán đoán. Kỹ năng demo (do con người đánh giá, không có Opik, đơn giản
.decode/skills/demo-N-*/theo ADR-0004); Điểm chuẩn 20 nhiệm vụ (kết quả dự đoán); 20 đầu dò Bộ hồi quy (số liệu hành vi + một số đánh giá); harness Opik bên dưới. Demo chứng minh điều đó gây ấn tượng; điểm chuẩn chứng minh nó hoạt động; các cuộc thăm dò chứng tỏ nó hoạt động theo cách chúng tôi thiết kế (ADR-0002..0013 hành vi: kỷ luật công cụ đọc, chế độ kế hoạch, tôn trọng cổng, tồn tại khi nén). - Việc thực thi sử dụng lại đường nối hộp cát của chính bộ decode — không có cơ sở hạ tầng chạy mới. Các lần chạy điểm chuẩn nhận được một
Không gian làm việc mới cho mỗi tác vụ thông qua không gian làm việc hiện có
SandboxExecutor/DockerBackend(executor.start(tmp_workspace)+ cáidecode.tools.bashđường may thi hành - chính xácruntime/flow.py::_warm_headless_executormẫu);--sandbox modaltrao đổi trongModalBackendtrên cùng một đường may. Đầu dò hồi quy chạy trên máy chủ gốc (nonemode) trên các thư mục tạm thời - đủ nhanh cho nghi thức theo từng nhánh tính năng. Cơ chế tối thiểu sự lựa chọn: đường nối đã tồn tại và cách ly eval cũng là vấn đề tương tự cách ly hộp cát giải quyết. - Lái xe agent trong quá trình; công cụ gọi từ tin nhắn, không bao giờ gọi từ dấu vết. Một trình điều khiển
(
evals/harness/driver.py) chạy THỰC SỰbuild_agent()+AgentDeps+AgentTurnHandler+Runner(mô hình đã được chứng minh bởitests/integration/test_milestone1_capstone.py), với chế độ cổng/bộ phân giải/lịch sử điền sẵn có thể định cấu hình. Các lệnh gọi công cụ được trích xuất từ pydantic-aiToolCallParts trong lịch sử tin nhắn và cách sử dụng từ phần tóm tắtModelResponse.usage— phân tích cú pháp Dấu vết Opik cho sự thật cơ bản sẽ kết hợp với việc phân loại theo quy trình có thể quan sát được và nằm dưới độ trễ lấy mẫu/xuất. ý kiếnevaluate()nhiệm vụ fns được đồng bộ hóa, vì vậy trình điều khiển sẽ gửi mộtasyncio.run()giấy gói. - Xác minh rằng các lời tiên tri được ẩn giấu nhưng trung thực.
verify/tài sản chỉ được tiêm qua đường may SAU KHI agent kết thúc (agent không bao giờ có thể grep học sinh của chính mình);verify.shLÀ sự chấm điểm logic - một tập lệnh bash có thể đọc được, kiểu Terminal-Bench. Mỗi nhiệm vụ cam kết mộtsolution/và Khai thác pytest oracle-sanity chứng minh mỗi oracle CẢ HAI hướng (giải pháp→PASS, untouched→FAIL) trong CI thông thường, do đó, một oracle bị hỏng không thể âm thầm xếp loại mọi thứ lên hoặc xuống. - Hai bề mặt hồi quy, có chủ ý. (a) Bộ dữ liệu đơn giản + số liệu mã thông qua
evaluate()với cổng ngưỡng pytest (aggregate_evaluation_scores()≥ ngưỡng; vùng đồng bằng cơ sở thông quaget_experiments_by_namenhư cảnh báo); (b) Bộ thử nghiệm Opik 2.0 (get_or_create_test_suitekhẳng định bằng ngôn ngữ tự nhiên,run_tests→pass_rate) trên một tập con thăm dò nhỏ. Dự phòng trên mục đích: sự tương phản giữa các số liệu xác định và các xác nhận NL là điểm giảng dạy. - Định tuyến thẩm phán tuân theo nhà cung cấp decode. Xây dựng một nhà máy thẩm phán
GEval(model=<LiteLLM string>): mặc địnhgemini/gemini-2.5-flash;openrouter→openrouter/<model>;modal→openai/<model>+ điểm cuối base_url.EVAL_JUDGE_MODELghi đè. Giám khảo được dành riêng cho những gì mã không thể cho điểm (chất lượng, tính căn cứ, sự khác biệt tối thiểu về nhiệm vụ 19/15/20 và thẩm phán thăm dò); mọi thứ máy móc vẫn là mộtBaseMetric→ScoreResult. - Thử nghiệm + tổng hợp trên trục riêng của Opik.
--trials k→evaluate(trial_count=k); pass@1 / pass@k / pass^k / flakiness-rate và chi phí thành công trên mỗi đô la được chuẩn hóa theo chi phí được tính như sau các hàm thuần post-hoc trênevaluate()kết quảtest_results(đã cài đặtopik==1.9.8có khôngexperiment_scoring_functionsparam) và được đính kèm vào thử nghiệm dưới dạng dấu vết cho mỗi mục điểm phản hồi, có điểm trung bình cho mỗi thử nghiệm sẽ hiển thị chúng trên hàng thử nghiệm;experiment_configmô hình agent hồ sơ, nhà cung cấp, git sha. Chi phí đến từ việc sử dụng được ghi lại (+ dấu vết Opiktotal_costở đâu có sẵn). - Nhịp: thủ công, không bao giờ trong
make ci.make eval-benchmark/make eval-regressioncầnGEMINI_API_KEY+OPIK_API_KEY; nghi thức hồi quy được hợp nhất trước trên mỗi nhánh tính năng và mô-đun ngưỡng có thể trỏ tới CI sau này. Eval chạy đăng nhập dướiEVAL_PROJECT_NAME(decode-evals), do đó, việc theo dõi REPL trực tiếp (ADR-0014, dự ándecode/decode-<env>) không bao giờ bị ô nhiễm - harness không được chiến đấuinit_tracing(). - Đánh giá trực tuyến vẫn ở mức nhỏ. Một quy tắc đánh giá LLM trực tuyến của Opik được ghi lại + một quy tắc được viết theo kịch bản
cấp độ chủ đề
evaluate_threadschuyển qua các chủ đề của dự án TRỰC TIẾP - đánh giá sản xuất câu chuyện được kể ở quy mô demo.
Sơ đồ
flowchart LR
subgraph tracks["Eval tracks"]
D["Demo Skills<br/>.decode/skills/demo-N<br/>(human-judged)"]:::demo
B["Benchmark<br/>evals/benchmark/tasks/NNN<br/>task.yaml + setup/ + verify/ + solution/"]:::bench
R["Regression Probes<br/>evals/regression/cases<br/>fixtures + metrics"]:::reg
end
subgraph harness["evals/harness (not in wheel)"]
DRV["driver.py<br/>build_agent + Runner<br/>ToolCallParts + usage"]:::infra
MET["metrics.py<br/>BaseMetric → ScoreResult"]:::infra
JDG["judges.py<br/>GEval ← LiteLLM routing"]:::infra
AGG["aggregates.py<br/>pass@k · pass^k · $/success"]:::infra
end
subgraph exec["Execution"]
DK["SandboxExecutor<br/>DockerBackend (default)"]:::sbx
MD["ModalBackend<br/>--sandbox modal"]:::sbx
HN["Host-native none mode<br/>temp dirs"]:::sbx
end
subgraph opik["Opik"]
DS["datasets<br/>decode-benchmark-v1<br/>decode-regression-v1"]:::opik
EV["evaluate(trial_count)<br/>+ post-hoc aggregates<br/>→ trace feedback scores"]:::opik
TS["Test Suites<br/>run_tests → pass_rate"]:::opik
ON["online rule +<br/>evaluate_threads"]:::opik
end
GATE["pytest threshold gate<br/>make eval-regression<br/>(outside testpaths)"]:::gate
B --> DRV
R --> DRV
DRV --> DK
DRV -.-> MD
DRV --> HN
B -->|"verify.sh at grade time"| DK
DRV --> EV
MET --> EV
JDG --> EV
AGG --> EV
DS --> EV
EV --> GATE
R -.->|subset| TS
ON -.->|live traces| opik
classDef demo fill:#f9e79f,stroke:#b7950b,color:#1c2833
classDef bench fill:#aed6f1,stroke:#2471a3,color:#1c2833
classDef reg fill:#a9dfbf,stroke:#1e8449,color:#1c2833
classDef infra fill:#d7bde2,stroke:#7d3c98,color:#1c2833
classDef sbx fill:#f5b7b1,stroke:#c0392b,color:#1c2833
classDef opik fill:#fad7a0,stroke:#ca6f1e,color:#1c2833
classDef gate fill:#e5e8e8,stroke:#566573,color:#1c2833
hậu quả
- Tích cực: hồi quy về HÀNH VI của agent (không chỉ kết quả) trở nên có thể đo lường được trên mỗi đặc điểm
chi nhánh; việc chấm điểm vẫn minh bạch (verify.sh + số liệu có thể đọc được); không có sự cô lập mới
cơ sở hạ tầng (đường nối hộp cát được tái sử dụng); bánh xe,
make ci, và truy tìm trực tiếp đều không bị ảnh hưởng; oracle-sanity giúp 20 học sinh viết tay luôn trung thực. - Phủ định / được chấp nhận: Việc chạy eval tốn tiền thật và cần có khóa — do đó, nhịp điệu thủ công,
có nghĩa là bộ phần mềm chỉ bắt những gì ai đó chạy; Thẩm phán LLM ồn ào (giảm nhẹ: chỉ có thẩm phán
nơi mã không thể quyết định, ngưỡng không khớp chính xác, vượt qua^k để đảm bảo độ tin cậy); chạy thử k
nhân chi phí một cách tuyến tính; hai bề mặt hồi quy có nghĩa là có sự trùng lặp nào đó (được chấp nhận cho
tương phản);
evals/phát triển nguồn gốc thứ hai mà các cuộc kiểm tra phải phản ánh theo quy ước, được thực thi chỉ bằng cách xem xét. - Đường dẫn hoãn lại/nâng cấp: trỏ CI vào mô-đun ngưỡng; một
--sandbox modalmặc định một lần ma sát docker cắn; đầu dò 12 (MCP) kích hoạt khi nhà máy sản xuất công cụ MCP của bộ decode xuất xưởng; Bộ điều hợp băng ghế dự bị đầu cuối/SWE chỉ khi 20 nội bộ ngừng phân biệt đối xử giữa các agent các phiên bản.