# Từ nút thumbs-down đến bộ eval: biến lời phàn nàn của người dùng thành test case

> Khi khách hàng gửi bạn một file toàn những lượt bấm “không hài lòng”, việc đầu tiên là đọc trace và gắn nhãn, không phải đếm số lượt bấm.

Bản gốc: https://fdetimes.net/vi/bach-khoa/bien-phan-hoi-nguoi-dung-thanh-du-lieu-eval/

Tuần thứ ba triển khai chatbot nội bộ cho khách, trưởng nhóm vận hành gửi bạn file xuất từ hệ thống. Trong đó có vài trăm dòng, dòng nào cũng là một lượt người dùng bấm thumbs-down, và lời nhắn kèm theo chỉ có một câu: "Bot trả lời sai nhiều quá, sửa giúp anh."

Trong tình huống này, nhiều engineer làm theo phản xạ: sửa prompt, thử lại vài câu hỏi trong file, thấy ổn thì deploy. Hai tuần sau, số lượt thumbs-down vẫn y như cũ, và không ai trả lời được bản sửa đó có làm hỏng thứ gì khác hay không.

Cách làm đúng là coi file thumbs-down là nguyên liệu để xây một bộ eval, chứ không phải danh sách bug cần vá từng cái. Nếu bạn muốn làm FDE, đây là kỹ năng nên luyện trước khi một file như thế nằm trong hộp thư của bạn.

## Thumbs-down là tín hiệu hay là nhãn?

Braintrust định nghĩa user feedback là những tín hiệu tường minh như thumbs up/down hoặc điểm đánh giá, được ghi lại từ người dùng cuối trong production và gắn vào trace. Chữ quan trọng ở đây là "gắn vào trace". Cú bấm chỉ có giá trị khi bạn mở được toàn bộ input, context đã truy xuất và output phía sau nó.

Nhưng một cú bấm không nói lỗi nằm ở đâu. Người dùng có thể bấm vì bot trích sai tài liệu, vì câu trả lời quá dài, hoặc chỉ vì không thích nghe sự thật.

Vì thế Hamel Husain và Shreya Shankar xếp việc "sắp xếp theo user feedback" vào nhóm kỹ thuật lấy mẫu nâng cao. Feedback giúp bạn tìm trace lỗi nhanh hơn, còn phần xác định lỗi là gì thì vẫn phải do người đọc làm.

**Điểm mấu chốt:** Một cú thumbs-down là lời mời đọc trace, chưa phải một nhãn lỗi.

LangSmith mô tả một quy trình thường gặp đi đúng theo hướng này: mọi datapoint có phản hồi tiêu cực được đẩy vào annotation queue để người xem xét, không đi thẳng vào dataset. Ngược lại, datapoint được phản hồi tích cực thường được lọc ra và chuyển vào dataset luôn.

## Làm thử với một chatbot hỏi đáp chính sách

Thử hình dung chatbot trả lời câu hỏi về chính sách nghỉ phép cho nhân viên của khách hàng. Bạn có một tuần log, trong đó một phần trace bị thumbs-down. Bước đầu tiên là đừng chỉ lấy phần bị thumbs-down.

Langfuse mô tả bước một của error analysis là lấy một mẫu đại diện từ traffic production. Eugene Yan cũng bắt đầu product eval bằng việc lấy mẫu input và output từ các request LLM thật.

Lý do rất thực tế: người bấm thumbs-down chỉ là một nhóm người dùng nhất định, nên nhiều lỗi bạn sẽ không bao giờ thấy nếu chỉ nhìn vào họ. Hãy trộn trace bị thumbs-down với một lượng trace ngẫu nhiên tương đương.

Đoạn code dưới đây chỉ minh họa ý tưởng, với giả định bạn đã xuất được trace ra dạng danh sách dict:

```python
import csv, random

def build_review_sheet(traces, n_neg=30, n_rand=30, out="review.csv"):
neg = [t for t in traces if t.get("feedback") == "thumbs_down"]
rest = [t for t in traces if t.get("feedback") != "thumbs_down"]
sample = random.sample(neg, min(n_neg, len(neg))) + \
random.sample(rest, min(n_rand, len(rest)))
with open(out, "w", newline="") as f:
w = csv.writer(f)
w.writerow(["trace_id", "feedback", "question", "answer",
"first_error_note", "category", "pass_fail"])
for t in sample:
w.writerow([t["id"], t.get("feedback", ""), t["input"],
t["output"], "", "", ""])
```

Ba cột cuối được để trống có chủ đích, vì đó là phần việc của con người. Ở bước open coding, bạn đọc từng trace và ghi chú tự do, giống như viết nhật ký.

Langfuse đưa ra một quy tắc nên làm theo: chỉ ghi lại thứ *đầu tiên* bị sai trong mỗi trace. Lỗi đầu tiên thường kéo theo các lỗi phía sau, nên nếu ghi hết thì bạn sẽ đếm một nguyên nhân thành nhiều lần.

Sau khi đọc xong, bảng tính của bạn có thể trông như sau (các dòng dưới đây là ví dụ giả định):

| trace_id | feedback | first_error_note | category | pass_fail |
|---|---|---|---|---|
| t-014 | thumbs_down | Trả lời theo quy định nghỉ phép cũ, tài liệu mới không được truy xuất | Retrieval sai phiên bản | fail |
| t-022 | thumbs_down | Trả lời đúng, người dùng không đồng ý với chính sách | Không phải lỗi hệ thống | pass |
| t-031 | (không có) | Bịa ra số ngày phép cho hợp đồng thời vụ | Bịa thông tin | fail |
| t-047 | thumbs_down | Không hỏi lại khi câu hỏi thiếu loại hợp đồng | Không làm rõ câu hỏi | fail |

Hai dòng t-022 và t-031 cho thấy vì sao không thể bỏ qua bước đọc trace. Một trace bị thumbs-down hóa ra lại pass, còn một trace không ai bấm gì lại là lỗi nghiêm trọng nhất bảng. Nếu bạn lấy lượt bấm làm nhãn thì cả hai đều bị xếp sai.

## Pass/fail là đủ, và một bảng tính là đủ

Eugene Yan khuyên chỉ dùng nhãn nhị phân pass/fail hoặc win/lose, và bắt đầu đơn giản bằng bảng tính. Lời khuyên này hợp với bảng ở trên: mỗi dòng chỉ cần trả lời một câu "trace này có đạt không?", và để trả lời nhất quán, bạn buộc phải viết ra tiêu chí đạt cho từng nhóm lỗi.

Khi đã có cột category, bạn đếm số trace trong từng nhóm. Nhóm lớn nhất sẽ thành mục tiêu sửa đầu tiên, và các trace fail trong nhóm đó thành test case. Braintrust mô tả đúng động tác này: trace nhận thumbs-down thì được thêm vào eval set. Khác biệt là ở quy trình này, trace chỉ vào eval set sau khi đã được người đọc và gắn nhãn.

Còn trace được thumbs-up thì sao? Bạn có thể đưa chúng vào dataset như LangSmith mô tả, để làm test hồi quy giúp phát hiện khi một bản sửa làm hỏng những gì đang chạy tốt. Dù vậy, nên đọc lướt qua trước, vì người dùng cũng có thể bấm thumbs-up cho một câu trả lời nghe thuyết phục nhưng lại sai.

## Khi nào thì dừng đọc?

Hamel Husain và Shreya Shankar gọi điểm dừng là bão hòa lý thuyết, tức là lúc đọc thêm trace không còn làm lộ ra dạng lỗi mới hoặc làm thay đổi các nhóm lỗi đã có.

Một cách ước lượng thô là khi khoảng hai mươi trace liên tiếp đều xếp được vào những nhóm đã đặt tên; đó chỉ là mốc tham khảo, không phải ngưỡng cố định, và hệ thống càng đa dạng thì bạn càng nên đọc lâu hơn.

Bộ eval không làm một lần là xong. Langfuse coi những lời phàn nàn lặp lại (recurring complaints) là tín hiệu giám sát để mở thêm một vòng error analysis. Khi khách nhắn "lại bị như tuần trước", đó là lúc bạn kéo trace mới về bảng tính và đọc lại.

## Những cái bẫy hay gặp

Bẫy thứ nhất là coi số lượt thumbs-down là chỉ số chất lượng. Con số đó dao động theo việc người dùng có buồn bấm hay không, nên chỉ dùng nó để chọn trace cần đọc, đừng báo cáo cho khách như một metric.

Bẫy thứ hai là đặt sẵn danh sách nhóm lỗi trước khi đọc. Danh sách nghĩ ra từ đầu thường phản ánh nỗi lo của engineer chứ không phản ánh những gì người dùng thật sự gặp phải. Hãy để các nhóm lỗi tự hình thành từ phần ghi chú tự do.

Bẫy thứ ba là giao hết việc đọc trace cho người khác. Phần lớn hiểu biết về hệ thống đến từ chính lúc đọc trace, và khi ngồi với khách, một FDE từng đọc trace sẽ giải thích lỗi thuyết phục hơn hẳn người chỉ nhìn dashboard.

## Một vòng đọc trace, một dòng CV

Cách luyện nhanh nhất là tự đi hết một vòng trên log của bất kỳ ứng dụng LLM nào bạn có quyền truy cập, kể cả side project: lấy mẫu trộn, ghi lỗi đầu tiên, gom nhóm, gắn pass/fail, rồi chạy lại bộ eval sau lần sửa kế tiếp.

Trong lúc làm, hãy ghi lại số trace đã đọc, các nhóm lỗi tìm ra và tỷ lệ fail của nhóm lớn nhất trước và sau khi sửa.

Chính những con số đó là chất liệu cho CV. Một dòng như "đọc và gắn nhãn trace production, dựng bộ eval pass/fail cho nhóm lỗi retrieval, đo lại sau mỗi lần sửa prompt" cho nhà tuyển dụng FDE thấy bạn biết làm việc với dữ liệu thật, điều mà câu chung chung "cải thiện chất lượng chatbot" không làm được.

Đến trace thứ hai mươi, nhiều khả năng bạn sẽ thấy hệ thống của mình sai theo những cách mà chưa ai bấm thumbs-down để báo cho bạn.

**Thử ngay tuần này:**

- Lấy 30 trace bị thumbs-down từ một hệ thống bạn có quyền truy cập, kèm 30 trace ngẫu nhiên, rồi ghi chú thứ đầu tiên bị sai trong mỗi trace
- Gom các ghi chú thành nhóm lỗi, chọn nhóm lớn nhất và viết tiêu chí pass/fail một câu cho nhóm đó
- Đưa các trace đã gắn nhãn vào một file eval và chạy lại sau lần sửa prompt tiếp theo

## Nguồn

- [Q: Why is error analysis so important in AI evals, and how is it performed? (Hamel Husain & Shreya Shankar)](https://hamel.dev/blog/posts/evals-faq/why-is-error-analysis-so-important-in-llm-evals-and-how-is-it-performed.html)

- [Product Evals in Three Simple Steps](https://eugeneyan.com/writing/product-evals/)

- [Encyclopedia Evalica / Tracing and instrumentation / User feedback (Braintrust)](https://www.braintrust.dev/encyclopedia/user-feedback)

- [LangSmith: Production Monitoring & Automations](https://www.langchain.com/blog/langsmith-production-logging-automations)

- [Error analysis to evaluate LLM applications (Langfuse)](https://langfuse.com/blog/2025-08-29-error-analysis-to-evaluate-llm-applications)
