1. Vì sao một AI test agent cần eval harness riêng
Một AI test agent là phần mềm, và giống mọi phần mềm, nó có thể hồi quy. Nhưng khác code thường, agent phi xác định: cùng đầu vào có thể cho hành vi khác vì model, temperature, hay dữ liệu đổi. Vì vậy ta không thể tin 'nó chạy được hôm qua'. Eval harness là bộ khung đo lường lặp lại được: một tập bài toán có oracle đã biết, chạy agent trên đó, và đo các chỉ số khách quan. Nếu không có harness, mọi thay đổi prompt hay nâng model đều là canh bạc — bạn không biết agent đang tốt lên hay tệ đi.
Điểm oracle-first trở lại ở đây với sức nặng gấp đôi. Để đo agent, mỗi bài trong bộ eval phải có oracle rõ: kết quả đúng là gì, bug nào đáng lẽ phải bắt được. Chỉ khi biết sự thật (ground truth) ta mới tính được đúng-sai của agent. Harness không đo 'agent nói gì' mà đo 'agent có kết luận khớp sự thật không'. Đây là khác biệt sống còn giữa một agent thực sự tìm bug và một agent chỉ tạo ra văn bản nghe hợp lý.
- Agent phi xác định → cần đo lặp lại, không tin 'chạy được lần trước'.
- Mỗi bài eval có ground truth: kết quả đúng + bug cần bắt.
- Harness đo kết luận khớp sự thật, không đo văn bản nghe hay.
2. Golden dataset: bộ bài toán có oracle đã biết
Golden dataset là trái tim của harness. Mỗi mục gồm: mô tả task, seed dữ liệu cố định để tái tạo, oracle kỳ vọng (kết quả đúng), và nhãn về bug — bài này có bug gì đã cấy sẵn, hay là bài 'sạch' để đo false-positive. Bộ vàng phải phủ cả hai phía: bài CÓ bug (đo recall — agent có bắt được không) và bài KHÔNG bug (đo false-positive — agent có bịa bug không). Thiếu vế 'sạch', bạn không bao giờ biết agent có hay la làng.
Bug cấy vào bộ vàng nên phản ánh lỗi thật ở domain lớn: sai làm tròn tiền tệ trong ngân hàng, race condition khi hai người đặt cùng ghế, mất idempotency khiến trừ tiền hai lần, rò rỉ dữ liệu cross-tenant trong SaaS. Mỗi bug đi kèm oracle chính xác để chấm. Bộ vàng cũng phải được phiên bản hoá: khi thêm bug mới hay sửa oracle, ta bump version và giữ lịch sử, để so sánh chỉ số qua thời gian là công bằng. Một bộ vàng đông cứng, được review, chính là hợp đồng chất lượng cho agent.
// Một mục golden dataset: có seed, oracle, và nhãn bug (kể cả bài 'sạch').
interface GoldenCase {
id: string;
version: number; // phiên bản hoá để so công bằng
task: string; // mục tiêu giao cho agent
seed: number; // dữ liệu cố định → tái tạo
clock: string; // freeze thời gian
oracle: OracleSpec; // kết quả đúng-sai
plantedBugs: string[]; // [] = bài SẠCH (đo false-positive)
}
const golden: GoldenCase[] = [
{ id:"bank-round-01", version:3, task:"Chuyển 100.005đ giữa 2 ví",
seed:42, clock:"2026-07-01T00:00:00Z",
oracle:{ name:"tong_bao_toan", invariant:"sum(before)==sum(after)" },
plantedBugs:["lam_tron_sai_0.005"] },
{ id:"bank-clean-01", version:3, task:"Xem lịch sử giao dịch",
seed:42, clock:"2026-07-01T00:00:00Z",
oracle:{ name:"hien_thi_dung", invariant:"rows==expected" },
plantedBugs:[] }, // bài sạch: agent KHÔNG được báo bug
];❓ Vì sao golden dataset phải có cả bài 'sạch' (không cấy bug)?
Để đo false-positive rate — tỉ lệ agent bịa ra bug không tồn tại. Nếu bộ vàng chỉ có bài có bug, một agent 'báo bug với mọi thứ' sẽ đạt recall 100% nhưng vô dụng vì làm ngập cảnh báo giả. Bài sạch buộc agent phải im lặng khi không có gì sai, và cho phép tính precision cùng false-positive một cách trung thực.
3. Metrics cốt lõi: success, precision/recall, false-positive
Bốn chỉ số nền tảng. Task success rate: tỉ lệ bài agent hoàn thành đúng oracle. Precision của bug tìm được: trong các bug agent báo, bao nhiêu phần trăm là thật. Recall: trong các bug thật (đã cấy), agent bắt được bao nhiêu phần trăm. False-positive rate: trên các bài sạch, bao nhiêu lần agent báo bug sai. Precision cao mà recall thấp nghĩa là agent thận trọng nhưng bỏ sót; recall cao mà precision thấp nghĩa là agent bắt nhiều nhưng ồn. Không có một con số duy nhất tốt — phải nhìn cả cụm.
Bên cạnh chất lượng phát hiện, đo hiệu quả kinh tế: cost per run (USD/token trung bình mỗi lần chạy) và cost per bug thật tìm được. Một agent recall cao nhưng tốn 5 USD/bug có thể đắt hơn kiểm tay ở nhiều đội. Thêm latency (thời gian mỗi lần chạy) vì nó quyết định agent có nằm được trong pipeline hay không. Cuối cùng, mọi chỉ số phải chạy trên bộ vàng phiên bản cố định, nếu không so sánh giữa hai lần đo là khập khiễng.
// Tính precision/recall/false-positive từ kết quả agent vs ground truth.
interface Score { taskSuccess:number; precision:number; recall:number;
falsePositiveRate:number; costPerRun:number; costPerBug:number; }
function scoreRun(cases: GoldenCase[], results: AgentResult[]): Score {
let tp=0, fp=0, fn=0, ok=0, usd=0;
for (let i=0;i<cases.length;i++){
const truth = new Set(cases[i].plantedBugs);
const found = new Set(results[i].reportedBugs);
if (results[i].oracleMet === (truth.size===0)) ok++; // hoàn thành đúng
for (const b of found) truth.has(b) ? tp++ : fp++; // đúng vs bịa
for (const b of truth) if(!found.has(b)) fn++; // bỏ sót
usd += results[i].costUsd;
}
const cleanFp = results.filter((r,i)=>cases[i].plantedBugs.length===0 && r.reportedBugs.length>0).length;
return {
taskSuccess: ok/cases.length,
precision: tp/(tp+fp || 1),
recall: tp/(tp+fn || 1),
falsePositiveRate: cleanFp / cases.filter(c=>c.plantedBugs.length===0).length,
costPerRun: usd/cases.length,
costPerBug: usd/(tp || 1),
};
}❓ Precision 95% nhưng recall 40% nói lên điều gì về agent?
Agent rất thận trọng: gần như mọi bug nó báo đều thật (ít bịa), nhưng nó bỏ sót 60% bug thật. Với vai trò 'kính lúp khám phá', bỏ sót nhiều là vấn đề vì nhiều bug lọt lưới. Cần cải thiện recall (oracle mạnh hơn, khám phá rộng hơn) mà không kéo precision xuống. Không được coi 'precision cao' là đủ tốt khi mục tiêu là tìm bug.
4. Regression gate cho chính agent
Khi bạn đổi prompt, đổi tool, hay nâng model, agent có thể tốt lên ở vài chỗ và tệ đi ở chỗ khác. Regression gate là cổng tự động so kết quả eval mới với một baseline đã lưu và chặn thay đổi nếu chỉ số quan trọng tụt. Quy tắc gate điển hình: recall không được giảm, false-positive không vượt ngưỡng, và cost per run không tăng quá biên. Gate này bảo vệ chính agent — nó là 'test hồi quy' cho một hệ thống mà bạn không thể assert từng dòng như code thường.
Cẩn trọng: vì agent phi xác định, một chỉ số tụt nhẹ có thể là nhiễu chứ không phải hồi quy thật. Vì thế gate phải dựa trên nhiều lần chạy và biên tin cậy, không phải một lần đo. Ta chạy mỗi bài k lần với seed cố định, lấy trung vị hoặc khoảng tin cậy, rồi mới so baseline. Gate cũng nên phân biệt 'hồi quy cứng' (recall tụt rõ) với 'dao động trong biên' để không chặn merge oan. Chương 5 sẽ đi sâu vào cách chống non-determinism che giấu chính hồi quy này.
💬 Bình luận (0)
Chưa có bình luận nào. Hãy là người đầu tiên!