Đánh giá chất lượng RAG
“Thử vài câu thấy ổn” không phải là đánh giá. Bài này xây một quy trình đo được, lặp lại được, để mỗi thay đổi về chunk, mô hình hay prompt đều có số liệu chứng minh.
Hai tầng cần đo
Đo riêng từng tầng để biết lỗi nằm ở đâu:
| Tầng | Câu hỏi cần trả lời | Chỉ số |
|---|---|---|
| Truy xuất | Đoạn chứa đáp án có được lấy về, và ở thứ hạng cao không? | Recall@k, Precision@k, MRR, nDCG |
| Sinh | Câu trả lời có trung thực với nguồn, đúng và đúng trọng tâm không? | Faithfulness, answer relevance, correctness, tỉ lệ trích dẫn đúng |
Bộ câu hỏi vàng (golden set)
Mỗi mục gồm câu hỏi, đáp án chuẩn và (các) đoạn tài liệu chứa đáp án:
{
"question": "Hạn nộp chứng từ hoàn ứng là bao lâu?",
"reference_answer": "30 ngày kể từ ngày phát sinh chi phí.",
"relevant_chunks": ["finance-reimburse-v3#7"],
"type": "tra-cuu-du-kien"
}
- Quy mô khởi đầu: 50–200 câu là đủ để thấy khác biệt giữa các cấu hình.
- Lấy từ câu hỏi thật (log tìm kiếm, ticket hỗ trợ) thay vì chỉ tự nghĩ ra.
- Đa dạng loại câu: tra cứu dữ kiện, giải thích quy trình, so sánh, câu hỏi có mã số/tên riêng.
- Bắt buộc có câu không có đáp án trong kho — để đo khả năng nói “không biết”.
- Có thể dùng LLM sinh nháp câu hỏi từ tài liệu, nhưng người phải duyệt.
Chỉ số truy xuất
Bốn câu hỏi, mỗi câu đúng một đoạn liên quan — chính giả thiết này làm ba công thức so sánh được trực tiếp với nhau:
Câu hỏi Đoạn đúng ở hạng Recall@5 1/rank 1/log2(rank+1)
Q1 1 1 1.0000 1.0000
Q2 3 1 0.3333 0.5000
Q3 không có trong top-5 0 0.0000 0.0000
Q4 2 1 0.5000 0.6309
Recall@5 = 3/4 = 0.7500 MRR = 0.4583 nDCG@5 = 0.5327
Ba con số lệch nhau vì mỗi công thức chiết khấu thứ hạng một kiểu. Ở hạng 2, 1/rank đã cắt một nửa còn 0,5000 trong khi 1/log₂(rank+1) vẫn cho 0,6309;
tới hạng 5 là 0,2000 so với 0,3869. Vậy MRR là chỉ số khắt khe nhất với mọi thứ không đứng đầu — cũng là chỉ số nhúc nhích mạnh nhất khi bạn thêm một tầng rerank.
Chỉ số câu trả lời
- Faithfulness (groundedness): mọi khẳng định trong câu trả lời có được ngữ cảnh hỗ trợ không. Thấp = mô hình đang bịa thêm.
- Answer relevance: câu trả lời có đúng trọng tâm câu hỏi không, hay lan man.
- Correctness: so với đáp án chuẩn, câu trả lời đúng không.
- Citation accuracy: mã nguồn được trích có thật sự chứa ý đó không.
- Refusal đúng lúc: với câu không có đáp án, hệ thống có từ chối không; với câu có đáp án, có từ chối nhầm không.
Chấm các chỉ số này ở quy mô lớn thường dùng LLM làm giám khảo (LLM-as-judge) với rubric rõ ràng. Hãy chấm tay một mẫu nhỏ để kiểm tra giám khảo có đồng thuận với người không, trước khi tin vào con số. Các thư viện như RAGAS, DeepEval, TruLens cung cấp sẵn nhiều chỉ số kiểu này.
Quy trình đánh giá
- Cố định bộ câu hỏi vàng và phiên bản dữ liệu.
- Chạy cấu hình hiện tại, lưu kết quả làm baseline.
- Thay đổi một yếu tố (kích thước chunk, mô hình embedding, rerank, prompt…).
- Chạy lại, so từng chỉ số và xem các câu bị tệ đi — không chỉ nhìn trung bình.
- Giữ thay đổi nếu tốt hơn; đưa việc chạy đánh giá vào CI để tránh thụt lùi.
A xếp đoạn đúng ở hạng 1, –, 2, 2. B xếp ở hạng 2, 2, 1, –.
Cả hai đều cho Recall@5 = 0,75, MRR = 0,500, nDCG@5 = 0,5655 — ba số tổng hợp trùng nhau tới bốn chữ số thập phân. Nhưng A hỏng câu Q2 còn B hỏng câu Q4. Chuyện đó có nghiêm trọng hay không hoàn toàn phụ thuộc vào việc người dùng thật sự hỏi câu nào, và không con số trung bình nào nói cho bạn biết. Hãy giữ bảng theo từng câu, và so bảng.
Theo dõi trên production
| Tín hiệu | Ý nghĩa khi xấu đi |
|---|---|
| Tỉ lệ “không tìm thấy thông tin” | Tăng: thiếu tài liệu, index lỗi, hoặc câu hỏi mới ngoài phạm vi |
| Phản hồi 👍/👎 và câu hỏi lại ngay sau đó | Người dùng không hài lòng với câu trả lời |
| Điểm liên quan của top-1 | Giảm dần: dữ liệu và câu hỏi đang lệch nhau |
| Độ trễ p95, token mỗi câu hỏi | Chi phí và trải nghiệm |
| Độ tươi của index | Tài liệu mới chưa được lập chỉ mục |
Lưu lại (có kiểm soát quyền riêng tư) câu hỏi, các đoạn đã truy xuất và câu trả lời. Những câu bị 👎 là nguồn tốt nhất để bổ sung bộ câu hỏi vàng.