CYBERSOFT
Đăng nhập

Xây eval harness và guardrails cho AI test agent: đo lường, golden dataset và cổng hồi quy

Chuyên nâng caoDịch vụ SaaSAI AgentNâng caoKinh nghiệmTip
🗓 1 tháng trước21 phút đọc·👁 1,271 lượt xem👤 167 người đọc

Cách đo và bảo vệ một AI test agent: task success rate, precision/recall của bug tìm được, tỉ lệ false-positive, cost mỗi run, golden dataset, cổng hồi quy cho chính agent, guardrails (hành động cấm, giới hạn scope, cổng phê duyệt) và cách chống non-determinism che giấu hồi quy.

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.
Eval harness cho agent cũng là một hệ thống cần kiểm thử: nếu ground truth trong bộ vàng sai, mọi chỉ số đều sai theo. Hãy review golden dataset kỹ như review code sản phẩm.

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.

Eval harness: golden dataset → metrics → regression gate Golden dataset task + oracle kỳ vọngseed dữ liệu cố địnhbug đã biết (labelled)edge: timeout/refundphiên bản hoá (v1..vN) Metrics task success rateprecision / recall bugfalse-positive ratecost / run · latencyflakiness (n lần chạy) Gate so baselineΔrecall ≥ 0FP ≤ ngưỡngcost ≤ budgetfail → chặn merge Chạy k lần/seed cố định → dùng trung vị, chống non-determinism che giấu hồi quy
Golden dataset (task+oracle+seed+nhãn bug) → metrics → regression gate so với baseline.
typescript
// 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.

typescript
// 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.

💡 Báo cáo chỉ số dạng bảng theo phiên bản golden: mỗi dòng một lần đo, cột là success/precision/recall/FP/cost. Xu hướng qua thời gian quan trọng hơn con số một lần.

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.

🔒

Nội dung bị khoá

Bạn đang xem bản xem trước. Đăng nhập để mở khoá toàn bộ bài viết và tất cả tài liệu Tester/QA.

Đã xem 25% nội dung
  • Đọc trọn vẹn mọi bài viết
  • Lưu bài & ghi chú cá nhân
  • Theo dõi tiến độ đã đọc
  • Luyện phỏng vấn, ISTQB, Mock
Đăng nhập để đọc tiếp

Chưa có mã? Lấy mã qua Fanpage / Zalo CyberSoft.

0

💬 Bình luận (0)

Bạn có thể đọc mọi bình luận. Đăng nhập để bình luận

Chưa có bình luận nào. Hãy là người đầu tiên!