Hướng dẫn

Đánh giá AI agent: cách xây dựng evals và đo độ tin cậy thay vì cảm tính

Cập nhật: · Skillaria.Top

Đánh giá AI agent là việc chạy định kỳ một bộ tác vụ thực cố định, kiểm tra kết quả tự động và tính các chỉ số, chứ không phải cảm nhận từ vài phiên thành công. Điều cốt lõi là đo không chỉ pass@k (ít nhất một trong k lần thử thành công) mà còn pass^k (cả k lần thử đều thành công), bởi chính sự ổn định quyết định có thể giao việc cho agent mà không cần giám sát hay không.

Vì sao cần đánh giá AI agent khi đã thấy rõ nó làm việc được

Chính vì «thấy» nên mới dễ sai. Trong một tuần, agent không bị kẹt lần nào sau khi sửa prompt — đó là nhờ sửa đúng hay chỉ vì tuần đó toàn việc đơn giản? Một kỹ sư tin rằng mẫu mới đã thay đổi tất cả, người thứ hai đọc cùng log và không thấy khác biệt gì. Cả hai đều đúng ở mức độ họ chưa đếm gì cả.

Đánh giá AI agent (evals) thay cảm tính bằng con số. Bạn lấy một bộ tác vụ cố định, chạy agent, kiểm tra kết quả tự động và so sánh các chỉ số trước và sau khi thay đổi. Khi đó, cuộc tranh luận «đã tốt hơn chưa» được giải quyết bằng một bảng số liệu, không phải bằng uy tín của ai.

Không có evals, mọi thay đổi của harness — prompt, AGENTS.md, bộ công cụ, mô hình — đều là một canh bạc mù quáng. Có evals, mỗi thay đổi là một thí nghiệm với kết quả đo được.

Vì sao «cảm tính» đánh lừa

Cảm nhận về cách agent làm việc mắc ba lỗi có hệ thống, và cả ba đều đẩy về phía tin tưởng sai lệch.

  • Thiên lệch người sống sót. Các lần chạy thành công được nhớ và kể cho đồng nghiệp, còn các lần thất bại được chạy lại và bị quên. Độ tin cậy tính trên các lần thành công không cho biết agent thực sự gãy ở đâu.
  • Mẫu quá nhỏ. Ba tác vụ thành công liên tiếp là chuyện bình thường ngay cả với một agent chỉ làm đúng một nửa số lần. Xác suất là 0,5³ = 12,5%, tức khoảng cứ tám chuỗi thì có một chuỗi như vậy.
  • Giọng điệu chắc chắn. Agent viết «xong, tất cả test đều chạy qua» với cùng một sự chắc chắn dù điều đó đúng hay sai. Mức tự tin của mô hình không được hiệu chỉnh: giọng điệu của câu trả lời không phải tín hiệu về tính đúng đắn.

Từ đó có một quy tắc: mọi thứ không được ghi lại và đếm lại đều coi là chưa đo.

pass@k và pass^k: hai chỉ số hay bị nhầm

Agent không mang tính xác định: cùng một tác vụ khi chạy lại có thể thành công, cũng có thể thất bại. Vì vậy người ta chạy một tác vụ nhiều lần và tính một trong hai chỉ số.

pass@k — ít nhất một trong k lần thử thành công

Chỉ số này xuất phát từ đánh giá sinh code. Nó trả lời câu hỏi «hệ thống có khả năng giải quyết tác vụ hay không nếu cho nó nhiều lần thử». Đây là chỉ số trung thực cho tình huống con người chọn phương án tốt nhất trong vài lựa chọn, hoặc khi có kiểm tra tự động đáng tin cậy loại bỏ các kết quả hỏng.

pass^k — cả k lần thử đều thành công

Chỉ số này trả lời một câu hỏi khác: «agent giải quyết tác vụ ổn định đến mức nào». Nó mô tả công việc không cần giám sát — khi agent được chạy rất nhiều lần và mỗi lần thất bại đều tốn tiền hoặc thời gian.

Khoảng cách giữa hai chỉ số rất lớn. Giả sử agent giải được tác vụ với xác suất 70% mỗi lần thử và các lần thử độc lập nhau:

kpass@k = 1 − 0,3^kpass^k = 0,7^k
170%70%
397,3%34,3%
599,8%16,8%
10~100%2,8%

Nhìn pass@5, agent trông gần như hoàn hảo; nhìn pass^5, nó không đáng tin. Cả hai con số đều đúng, chỉ là mô tả những điều khác nhau. Nếu bạn định để agent làm việc tự động, hãy nhìn pass^k: nó gần hơn với những gì bạn sẽ thấy trong công việc thực tế.

Cách tính trong thực tế

Chạy mỗi tác vụ n lần (ví dụ 5) và ghi số lần thành công c. Với pass^k, xấp xỉ bằng tỷ lệ các lần chạy mà cả k lần liên tiếp đều thành công; đơn giản hơn là ước lượng xác suất thành công p = c / n rồi nâng lên lũy thừa. Với một bộ tác vụ, lấy trung bình theo các tác vụ.

import json
from statistics import mean

# results.jsonl: {"task": "add-pagination", "runs": [true, true, false, true, true]}
rows = [json.loads(line) for line in open("results.jsonl")]

def pass_at_k(runs, k):
    p = sum(runs) / len(runs)
    return 1 - (1 - p) ** k

def pass_pow_k(runs, k):
    p = sum(runs) / len(runs)
    return p ** k

for k in (1, 3, 5):
    print(k,
          round(mean(pass_at_k(r["runs"], k) for r in rows), 3),
          round(mean(pass_pow_k(r["runs"], k) for r in rows), 3))

Ước lượng qua p mũ k khá thô khi n nhỏ, nhưng để so sánh các phiên bản harness với nhau thì thường đủ dùng. Quan trọng hơn là n và bộ tác vụ không thay đổi giữa các lần so sánh.

Cách xây dựng bộ tác vụ cho evals

Bộ tác vụ là tài sản chính. Chỉ số tốt trên tác vụ tồi thì đo sai thứ.

Lấy tác vụ từ chính thực tế của bạn

Các benchmark công khai như SWE-bench hữu ích để so sánh mô hình, nhưng tác vụ của chúng đã được chọn lọc: mô tả rõ ràng, có sẵn test. Trong repository của bạn, yêu cầu thường mơ hồ và có chỗ không có test, nên con số trên benchmark gần như luôn cao hơn những gì agent đạt được ở chỗ bạn. Nguồn tác vụ tốt nhất là các ticket đã đóng và những lần agent thất bại thực tế được ghi trong nhật ký.

Thành phần của bộ tác vụ

  • 20–50 tác vụ để bắt đầu. Ít hơn thì nhiễu sẽ nuốt mất khác biệt giữa các phiên bản. Nhiều hơn thì mỗi lần chạy đắt và sẽ không còn ai chạy nữa.
  • Nhiều loại khác nhau: tính năng mới, sửa lỗi, refactor, tác vụ trên module của người khác, tác vụ có bẫy (đáp án đúng là «không nên làm như vậy» hoặc «cần làm rõ thêm»).
  • Mỗi tác vụ thất bại trong công việc thực tế trở thành một test. Nhờ vậy bộ tác vụ lớn lên cùng với hiểu biết về chỗ agent yếu, và hồi quy không bị bỏ qua.
  • Trạng thái ban đầu cố định: một commit cụ thể, các phụ thuộc đã được ghim, môi trường giống nhau. Nếu không, bạn đo sự trôi dạt của môi trường chứ không đo agent.

Định dạng tác vụ

Mỗi tác vụ gồm một mô tả, trạng thái ban đầu và tiêu chí thành công có thể kiểm tra mà không cần người.

id: add-pagination
repo_ref: 3f2c1ab
prompt: |
  Thêm phân trang cho GET /payments: tham số limit (mặc định 20, tối đa 100)
  và cursor. Phản hồi chứa next_cursor.
check:
  - pytest tests/test_payments_pagination.py
  - mypy app/
limits:
  max_changed_files: 6

Hãy để ý: tiêu chí thành công chính là Definition of Done được viết bằng lệnh. Nếu bạn không viết được tiêu chí cho một tác vụ, đó là dấu hiệu rằng tác vụ đó cũng đang được giao cho agent một cách mơ hồ.

Kiểm tra tự động hay LLM làm giám khảo

Có thể kiểm tra kết quả bằng code hoặc bằng một mô hình khác. Mỗi cách có phạm vi riêng.

Kiểm tra tự động (code)LLM làm giám khảo
Kiểm tra gìTest, kiểu dữ liệu, linter, E2E, kích thước diff, tệp bị cấmĐáp ứng yêu cầu, dễ đọc, phong cách, chất lượng giải thích
Tính xác địnhHoàn toànKhông: điểm thay đổi giữa các lần chạy
Chi phíGần như miễn phíThêm một lần gọi mô hình cho mỗi tác vụ
Rủi ro chínhKhông kiểm tra hết: test xanh nhưng tính năng saiGiám khảo đồng ý với một lời giải chắc chắn nhưng sai

Quy tắc: code trước, giám khảo đặt lên trên

Mọi thứ có thể kiểm tra một cách xác định thì hãy kiểm tra xác định. Chỉ thêm LLM làm giám khảo cho những thuộc tính mà code không diễn đạt được, và không bao giờ dùng nó thay cho test.

Làm cho LLM làm giám khảo hữu ích

  • Ngữ cảnh khác với bên sinh ra kết quả. Giám khảo không được thấy lập luận của agent — chỉ thấy tác vụ, tiêu chí và diff cuối cùng. Nếu không, nó sẽ lặp lại đúng những sai lầm đó: đây chính là N-phiên bản, hai góc nhìn độc lập thay vì một.
  • Rubric thay vì «chấm theo thang mười điểm». Các câu hỏi cụ thể trả lời có/không: «có kiểm tra giới hạn limit > 100 không», «có tệp nào ngoài app/payments bị thay đổi không».
  • Hiệu chỉnh bằng gán nhãn thủ công. Tự gán nhãn 20–30 kết quả và so sánh với phán quyết của giám khảo. Nếu độ trùng khớp thấp, hãy sửa rubric chứ không tin giám khảo hơn.
  • Bất đối xứng của lỗi. Báo «xong» sai đắt hơn báo «chưa xong» sai: cái trước lên production, cái sau chỉ tốn một lần chạy lại. Hãy cấu hình giám khảo để khi nghi ngờ thì bác bỏ.

Những chỉ số nào nên đo ngoài tỷ lệ thành công

Tỷ lệ tác vụ được giải quyết chỉ là phần nổi. Để biết nên sửa chỗ nào, cần các chỉ số độ tin cậy từ kỹ thuật cổ điển.

  • MTBF — số bước hoặc số tác vụ agent đi được cho đến khi bị kẹt. Cho thấy nó hỏng hiếm đến mức nào.
  • MTTR — thời gian cần để đưa hệ thống trở lại trạng thái làm việc sau sự cố. Giảm MTTR hầu như luôn rẻ hơn tăng MTBF: một tệp tiến độ tốt và môi trường có thể tái tạo giúp rút ngắn việc khôi phục nhiều lần.
  • Bán kính ảnh hưởng — một bước thất bại làm hỏng bao nhiêu code. Được giới hạn bằng giới hạn diff và cách ly bản sao làm việc.
  • Tỷ lệ «xong» giả — tác vụ mà agent báo thành công nhưng kiểm tra lại thất bại. Đây là chỉ số nguy hiểm nhất: nó cho biết có thể tin báo cáo của agent hay không.
  • Chi phí và thời gian — token và phút cho mỗi tác vụ. Một harness tăng thành công thêm 5% nhưng làm chi phí gấp đôi không phải lúc nào cũng thắng.

Nhật ký thất bại: evals từ công việc hằng ngày

Không phải đội nào cũng sẵn sàng xây ngay một bộ chạy thử. Phiên bản tối thiểu của đánh giá là nhật ký thất bại gồm ba cột.

| Tác vụ                  | Kết quả                            | Tầng          |
|-------------------------|------------------------------------|---------------|
| phân trang /payments    | «xong», 2 test đỏ                  | xác minh      |
| sửa timeout webhook     | 30 phút cho pip install            | môi trường    |
| refactor refunds        | cú pháp ORM cũ                     | ngữ cảnh      |

Tầng là một trong năm nơi agent có thể hỏng: đặc tả tác vụ, ngữ cảnh, môi trường thực thi, phản hồi xác minh, quản lý trạng thái. Sau hai mươi bản ghi, nút thắt thật sự sẽ hiện ra, và gần như chưa bao giờ nằm đúng chỗ bạn nghĩ. Mỗi dòng trong nhật ký là một ứng viên cho bộ tác vụ evals.

Vì sao mô hình mạnh hơn không cứu được

Phản ứng đầu tiên khi agent thất bại là chọn một mô hình đắt hơn. Đôi khi điều đó giúp, nhưng thường khoảng cách giữa benchmark và thực tế của bạn được lấp đầy không phải bởi mô hình mà bởi môi trường xung quanh nó.

Nếu agent mất nửa tiếng để dựng môi trường, đó là lỗi ở tầng môi trường, và mô hình hàng đầu cũng sẽ mất đúng nửa tiếng đó. Nếu agent nói «xong» khi test đang đỏ, đó là tầng xác minh: nó không có lệnh nào nói cho nó sự thật. Nếu nó viết code theo phong cách khác với dự án, nó chưa được cung cấp quy ước của dự án. Không vấn đề nào trong số này là về trí tuệ của mô hình.

Evals cho phép kiểm chứng điều này một cách trung thực. Chạy bộ tác vụ với mô hình hiện tại và với một mô hình đắt hơn; rồi chạy với mô hình hiện tại kèm thêm AGENTS.md có các lệnh kiểm tra. Thường thay đổi thứ hai mang lại nhiều cải thiện hơn thay đổi thứ nhất, với chi phí bằng không. Nhưng đừng tin điều này chỉ vì lời nói: chính để so sánh như vậy mà bộ tác vụ tồn tại.

Kế hoạch từng bước: đánh giá AI agent trong một tuần

  1. Ngày 1. Mở nhật ký thất bại và ghi mọi lỗi của agent kèm tầng gây lỗi.
  2. Ngày 2. Chọn 20 tác vụ từ các ticket đã đóng và nhật ký. Với mỗi tác vụ, ghi lại commit và viết tiêu chí thành công bằng lệnh.
  3. Ngày 3. Viết bộ chạy thử: bản sao làm việc sạch, chạy agent với prompt của tác vụ, chạy các kiểm tra, ghi kết quả vào JSONL.
  4. Ngày 4. Chạy mỗi tác vụ 3–5 lần. Tính pass@1, pass^3, tỷ lệ «xong» giả, chi phí trung bình.
  5. Ngày 5. Thay một thứ trong harness và chạy lại. Chỉ so sánh khi bộ tác vụ và số lần lặp giống nhau.

Thay đổi từng biến một lần. Nếu trong một thí nghiệm bạn đổi cùng lúc mô hình, prompt và công cụ, bạn sẽ không biết điều gì đã có tác dụng.

Lỗi thường gặp khi đánh giá agent

  • Một lần chạy cho mỗi tác vụ. Tính không xác định của agent khiến kết quả như xổ số. Tối thiểu ba lần lặp lại.
  • Bộ tác vụ thay đổi giữa các lần so sánh. Thêm tác vụ mới và đồng thời đổi prompt — các con số không còn so sánh được.
  • Agent thấy các test kiểm chứng. Nếu test nằm trong repository, agent có thể sửa code cho khớp với chúng hoặc chỉnh sửa chính chúng. Hãy giữ các kiểm tra ẩn bên ngoài bản sao làm việc và kiểm tra rằng agent không đụng vào các tệp test.
  • Báo cáo của agent thay cho kiểm tra. «Tất cả test đều chạy qua» trong câu trả lời của mô hình không phải là kết quả. Kết quả là mã trả về của lệnh do bộ chạy thử khởi chạy.
  • Chỉ nhìn pass@k. Một con số đẹp cho bài thuyết trình nhưng là dự báo tệ cho công việc tự động.

Tóm lại

Đánh giá AI agent là một bộ tác vụ thực cố định, các kiểm tra tự động và những chỉ số được tính lại sau mỗi thay đổi của harness. pass@k cho thấy agent có khả năng gì, còn pass^k cho thấy có thể tin nó làm việc không cần giám sát hay không. Kiểm tra tự động cho sự thật; LLM làm giám khảo với rubric và ngữ cảnh riêng bổ sung ở chỗ code bó tay. Còn nhật ký thất bại theo năm tầng cho biết nên sửa gì trước, và phần lớn thời gian đó không phải là mô hình. Các chỉ số độ tin cậy và vòng chẩn đoán được giải thích và thực hành trong khóa học harness engineering.

Câu hỏi thường gặp

Cần bao nhiêu tác vụ để đánh giá agent?

Để bắt đầu, 20–50 tác vụ thực với tiêu chí thành công tự động và mỗi tác vụ lặp 3–5 lần là đủ. Bộ nhỏ hơn sẽ không phân biệt được cải thiện với nhiễu, còn bộ lớn hơn thì đắt và sẽ không còn ai chạy.

Có thể đánh giá agent chỉ bằng benchmark công khai không?

Không. Benchmark công khai so sánh mô hình trên các tác vụ đã được chọn lọc với test có sẵn, còn yêu cầu và test trong repository của bạn khác. Để quyết định về harness của mình, bạn cần bộ tác vụ riêng.

pass@1 khác gì pass^1?

Không khác gì: với một lần thử, cả hai chỉ số đều bằng tỷ lệ lần chạy thành công. Chúng bắt đầu khác nhau khi k lớn hơn một.

LLM làm giám khảo có thể là cùng mô hình với agent không?

Có thể, nếu nó có ngữ cảnh riêng: chỉ thấy tác vụ, rubric và diff cuối cùng, không thấy lập luận của agent. Nhưng phán quyết của nó vẫn cần được đối chiếu với gán nhãn thủ công.

Nên chạy evals bao lâu một lần?

Sau mỗi thay đổi đáng kể của harness: prompt, tệp hướng dẫn, bộ công cụ, mô hình. Cũng nên chạy bộ tác vụ theo lịch để phát hiện sự trôi dạt của môi trường và phụ thuộc.

Học chủ đề này qua video

Chủ đề này được giảng chi tiết kèm thực hành trong khóa học “Harness Engineering: инженерия надёжности AI-агентов”.

Đến khóa học