
Error Analysis: Đọc Trace Thật Trước Khi Build Evaluator
Sai lầm phổ biến nhất khi làm eval không phải thiếu công cụ, mà là viết evaluator trước khi biết sản phẩm đang hỏng ở đâu. Error analysis là quy trình đọc trace thật, gán nhãn tay, và để chính dữ liệu chỉ ra loại lỗi cần đo.
Thuộc chuỗi bài: LLM Evals: Đo lường chất lượng AI trước khi nó âm thầm phá sản phẩm
Một team ship tính năng LLM, viết evaluator ngay ngày đầu để "phủ những trường hợp cơ bản", rồi nhìn nó xanh liên tục suốt nhiều tuần trong khi phàn nàn từ người dùng vẫn rỉ rả kéo đến. Evaluator không hỏng - nó chỉ đang chấm sai thứ, vì chưa ai đọc thật những gì người dùng thật gõ vào và model thật trả lời ra trước khi quyết định cần đo cái gì.
Error analysis sửa lại đúng thứ tự: đọc trace thật trước, để chính những lỗi thấy được định nghĩa evaluator cần kiểm tra gì, rồi mới viết assertion hay rubric.
Từ Trace Thô Tới Evaluator Nhắm Đúng Lỗi
Vì sao viết evaluator trước khi đọc trace luôn thất bại
Phần lớn eval suite bắt đầu từ trực giác: một PM hay engineer liệt kê những lỗi họ đoán là quan trọng - "phải lịch sự", "JSON phải hợp lệ" - rồi viết check cho đúng những thứ đó. Check pass, dashboard nhìn khoẻ mạnh, team ship với đầy tự tin. Rồi traffic thật lộ ra một lỗi không ai từng ghi xuống: một tông giọng nghe lạnh lùng trước một dạng khiếu nại cụ thể, một agent đặt vé báo thành công trong khi booking thật lại sai. Evaluator chỉ kiểm tra được những lỗi mà ai đó đã biết trước để tìm - nó không tự phát hiện ra những lỗi chưa ai lường tới. Đọc trace thật trước khi viết bất kỳ assertion nào là cách duy nhất để đổi những lỗi đoán được lấy những lỗi thật sự tồn tại.
Quy trình: Từ Transcript Thô Tới Một Quyết Định Đạt Hay Không Đạt
Cơ chế thực hiện cố tình không có gì hào nhoáng. Lấy một lô transcript thật - trộn lẫn từ traffic gần đây, không tự chọn tay những case "thú vị", vì việc chọn lọc đó chỉ đưa lại đúng loại giả định mà mình đang cố thoát ra. Đọc từng cái từ đầu tới cuối: input, toàn bộ output, mọi lệnh gọi tool, trạng thái cuối cùng để lại. Với mỗi trace, chỉ hỏi một câu - người dùng có coi đây là một kết quả tốt không - rồi ghi lại một phán quyết nhị phân kèm một dòng lý do. Lý do quan trọng hơn phán quyết: chỉ ghi "fail" thì chẳng có gì để hành động, còn "fail - trích chính sách đúng nhưng không hề ghi nhận việc khách nhận hàng hỏng" thì chỉ thẳng ra cái cần sửa.
Nhãn Nhị Phân, Không Phải Thang Điểm
Thang 1-5 nghe có vẻ chính xác hơn đạt/không đạt, nhưng thực tế phần lớn chỉ tạo ra tranh cãi về ranh giới giữa điểm 3 và điểm 4 - cuộc tranh luận ngốn thời gian review mà không sinh ra tín hiệu hành động được. Nhãn nhị phân buộc phải quyết: cái này đủ tốt để ship nguyên trạng, hay không? Đó chính là quyết định mà một team đang ship cần, và giữ nhãn nhất quán giữa trace thứ 30 và trace thứ 3 của cùng một người review dễ hơn nhiều so với một thang năm điểm.
Ai Sở Hữu Định Nghĩa "Tốt"
Mỗi tính năng cần một người - không phải một uỷ ban luân phiên - làm chủ định nghĩa "thế nào là tốt" cho tính năng đó. Chia sẻ quyền này cho nhiều người review mà không có một chuẩn chung, tường minh sẽ tạo ra nhãn trôi dạt: cùng một trace, người này gọi là đạt, người kia gọi là không đạt, và taxonomy sinh ra chỉ là nhiễu chứ không phải tín hiệu. Người sở hữu không cần tự tay đọc mọi trace mãi mãi, nhưng họ đặt ra chuẩn để cả team hiệu chỉnh theo, và họ vẫn phải đủ gần dữ liệu thô để chuẩn đó không âm thầm mục ruỗng.
Đọc Trace Xây Taxonomy, Từng Nhãn Một
Mỗi trace nhận một nhãn nhị phân và một lý do ngắn. Đọc đủ nhiều, vài dạng lỗi giống nhau bắt đầu lặp lại — sự lặp lại đó chính là taxonomy.
Tôi muốn hoàn tiền, hàng nhận được bị hỏng.
Theo chính sách 4.2, yêu cầu hoàn tiền cho hàng hỏng cần ảnh chụp gửi trong 48 giờ sau khi nhận hàng. Yêu cầu của bạn đã quá thời hạn này.
Trích dẫn chính sách đúng, nhưng nghe lạnh lùng — không có một câu nào ghi nhận việc khách nhận hàng hỏng.
Khi một dạng lỗi lặp lại đủ nhiều, nó chuyển từ một ghi chú đơn lẻ thành một category có tên riêng, đáng để viết evaluator nhắm vào.
Từ Nhãn Cá Nhân Tới Một Taxonomy Lỗi Dùng Chung
Một trace fail đơn lẻ chỉ là một điểm dữ liệu. Cùng một dạng lỗi xuất hiện lặp lại ở sáu, tám, mười trace mới là thứ đáng đặt tên và đáng viết evaluator riêng cho nó. Cách đặt tên rất quan trọng: một category tên "câu trả lời tệ" không chỉ ra được gì, trong khi "transcript đọc đúng nhưng outcome ghi lại lại sai" chỉ thẳng cho engineer tiếp theo biết cần viết check cho đúng loại bug nào. Xây dựng taxonomy này chính là sản phẩm thật sự của error analysis - những evaluator viết sau đó chỉ đơn giản là tự động hoá lại các category mà quá trình đọc này đã tìm ra.
Open Coding vs Closed Coding: Khi Nào Dùng Cách Nào
Nghiên cứu định tính có một phân biệt hữu ích ở đây. Ở đầu một đợt đọc - khoảng 15-20 trace đầu tiên - dùng open coding: không có category định trước, chỉ ghi chú tự do về việc gì đã sai theo đúng ngôn ngữ của từng trace. Ép trace vào một nhóm có sẵn quá sớm sẽ che mất những dạng lỗi không khớp với các nhóm đã có. Khi một vài category bắt đầu lặp lại, chuyển sang closed coding: kiểm tra từng trace mới với danh sách category hiện có trước, chỉ thêm category mới khi thật sự không khớp vào đâu cả. Cú chuyển đó biến một đống ghi chú rời rạc thành một taxonomy đủ ổn định để xây evaluator dựa vào.
Chi Phí Đọc Trace So Với Chi Phí Bỏ Qua Error Analysis
Kịch bản mẫu: đọc và gán nhãn 30 trace đầu ở mức $75/giờ đọc, tìm ra phần lớn category lỗi trước khi viết evaluator.
Đã thấy ~4/7 category lỗi (55%)
+2 category mới (cộng dồn 85%)
Không còn category mới — dấu hiệu nên dừng
Bao Nhiêu Trace Là Đủ, Và Dấu Hiệu Để Dừng Đọc
Câu trả lời trung thực là: đọc tới khi trace mới không còn dạy thêm được gì mới. Thực tế, với một tính năng được định phạm vi rõ, 20-30 trace đầu thường đã lộ ra phần lớn các category lỗi hay lặp lại - sau mốc đó, trace thêm vào chủ yếu chỉ xác nhận lại category đã có chứ không lộ ra category mới. Điểm bão hoà đó - chứ không phải một con số cố định chọn trước - mới là tín hiệu thật để dừng đọc và bắt đầu viết evaluator. Dừng quá sớm nghĩa là evaluator bỏ sót những lỗi phổ biến; đọc quá lâu sau điểm bão hoà chủ yếu chỉ đốt thời gian review mà không đổi được gì trong thứ sắp được xây.
Giữ Vòng Lặp Mở, Error Analysis Không Phải Việc Làm Một Lần
Những trace từng quan trọng lúc mới launch sẽ không còn là những trace quan trọng sau lần nâng cấp model tiếp theo, một lần viết lại prompt, hay khi một nhóm người dùng mới xuất hiện. Mỗi thay đổi đó đều làm dịch chuyển hình dạng của traffic "thật", nghĩa là taxonomy dựng từ đợt đọc trước có thể lỗi thời đúng vào lúc nó quan trọng nhất. Coi error analysis là một thói quen chạy lại ở mỗi thay đổi đáng kể, không phải một bước làm một lần lúc onboarding rồi bỏ đó - vòng lặp giữa việc thấy một lỗi thật và cập nhật lại thứ đang được đo chính là thứ giữ cho eval suite còn trung thực.
Cạm Bẫy Thường Gặp Khi Làm Error Analysis
Vài lỗi lặp lại ở hầu hết các team: nhảy thẳng sang dùng LLM-as-judge trước khi có bất kỳ người nào đọc dù chỉ một trace, khiến judge được hiệu chỉnh theo một chuẩn không thuộc về ai cả; coi error analysis là nghi lễ của tuần launch thay vì một thói quen lặp lại; giao hẳn việc gán nhãn cho một đội tách rời khỏi quyết định sản phẩm, làm đứt vòng phản hồi vốn là lý do khiến việc đọc này đáng giá ngay từ đầu; và đặt tên category theo triệu chứng thay vì theo cơ chế, tạo ra một taxonomy mà không ai hành động theo được. Tránh được những điều này, error analysis sẽ làm đúng việc nó cần làm: thay một phỏng đoán về chỗ hỏng bằng một danh sách những gì thật sự đang hỏng, viết bằng chính ngôn ngữ của những người sẽ phải sửa nó.