Bỏ qua để đến nội dung
Search & RAG

5.4 Trần không vượt được: recall@k của stage 1

Đây là mục quan trọng nhất của Phần 5. Nếu bạn chỉ đọc một mục, đọc mục này — vì nó là chỗ tiền bị đổ sai hướng nhiều nhất trong các hệ RAG thật.

Reranker không thể xếp lại thứ nó chưa được đưa cho.

Gọi k là số ứng viên bạn đưa vào reranker. Mọi tài liệu liên quan không nằm trong k đó thì không tồn tại đối với reranker, với LLM, và với người dùng.

Hệ quả là một bất đẳng thức không có ngoại lệ:

chaˆˊt lượng cuoˆˊi cuˋng    recall@k của stage 1\text{chất lượng cuối cùng} \;\le\; \text{recall@}k \text{ của stage 1}

Reranker giỏi tới đâu cũng chỉ đưa bạn tới cái trần đó, không bao giờ vượt. Nếu recall@100 = 0,70 thì 30% truy vấn đã thua từ trước khi reranker được gọi.

Đo cùng một hệ thống, ba con số này nói ba chuyện hoàn toàn khác nhau:

Số đoÝ nghĩaNếu nó thấp thì sửa ở đâu
recall@k của stage 1 (k = số đưa vào rerank)trần. Tài liệu đúng có được lấy về khôngRetrieval: tokenizer, hybrid, chunking, embedding
nDCG@5 trước rerankthứ tự hiện tại tệ đến đâu— (đây là mốc để so)
nDCG@5 sau rerankreranker mua được bao nhiêu phần khoảng cách tới trầnReranker: đổi model, đổi k, fine-tune

Khoảng cách recall@k − nDCG@5(trước)toàn bộ dư địa mà reranker có thể ăn. Nếu khoảng cách đó nhỏ, reranker sẽ không cho bạn gì cả — dù nó là model tốt nhất thế giới.

Làm đúng thứ tự này, đừng đảo:

1. Đo recall@k của stage 1, với k đúng bằng số bạn định đưa vào reranker.
├── recall@k thấp (< ~0,8) ──► DỪNG. Không mua reranker.
│ Tiền phải vào retrieval:
│ tokenizer → hybrid → chunking → embedding
└── recall@k cao, nDCG@5 thấp ──► ĐÚNG bệnh. Reranker chữa được.
Đây là hình dạng "lấy đúng, xếp sai".

Lỗi phổ biến: thấy chất lượng RAG kém → cắm reranker → không khá lên → kết luận “reranker không hiệu quả”. Sai chẩn đoán, không phải sai thuốc. Bệnh nằm ở stage 1 và reranker chưa bao giờ được nhìn thấy tài liệu đúng.

Số thật trên corpus của cẩm nang — và vì sao nó không đại diện

Phần tiêu đề “Số thật trên corpus của cẩm nang — và vì sao nó không đại diện”

Baseline BM25 trên data/corpus.jsonl + data/goldenset.jsonl. Cột nDCG@5 có trong bảng baseline của Phụ lục — Lộ trình & baseline; cột recall@5 là số đo cùng lần chạy đó, nằm trong nhật ký làm việc không thuộc repo (xem cuối mục):

nDCG@5recall@5
Tổng0.7870.778
Lớp A — lexical/exact0.9710.917
Lớp B — paraphrase0.4560.667
Lớp C — multi-hop0.8340.778
Lớp D — phủ định0.8880.750

Nhìn lớp B: nDCG@5 = 0.456 trong khi recall@5 = 0.667. Khoảng cách 0,21 — có dư địa, nhưng không lớn. Và lớp B là lớp mà Tầng 0 — vocabulary mismatch đã chỉ ra: BM25 trả về top-1 là “Bảo trì định kỳ” cho câu hỏi “dùng miễn phí trước khi quyết định mua”, nDCG = 0.00. Tài liệu đúng (d003 — Gói Dùng Thử) không có từ nào chung với câu hỏi. Reranker không cứu được truy vấn đó nếu d003 không được lấy về.

Bây giờ đến phần trung thực, và nó là một bài học về phương pháp:

Corpus này chỉ có 50 tài liệu. Nếu bạn rerank k = 50, reranker nhìn thấy toàn bộ corpus — recall@50 = 1,0 theo định nghĩa, và trần biến mất.

Nghĩa là mọi con số “reranker cải thiện X%” đo trên một corpus 50 doc đều phóng đại so với production, nơi k = 100 trên 10 triệu tài liệu và trần rất thật. Đây chính xác là bẫy được mô tả ở Phần 2 — 7. Bảy lỗi phương pháp.

Module 4 của cẩm nang (Reranking) chưa được đo. Phần 5 vì vậy không đưa ra con số “cải thiện bao nhiêu” nào của riêng cẩm nang; mọi con số định lượng trong Phần 5 đều là số dẫn từ nguồn ngoài kèm link, hoặc toán học tay có nói rõ giả định.

k là chỗ hai đường cong gặp nhau:

recall@k chi phí rerank
│ ╭──────────── bão hoà │ ╱ tuyến tính
│ ╭─╯ │ ╱
│ ╭─╯ │ ╱
│ ╭─╯ │╱
└──┴──┴──┴──┴──► k └──────────────► k
10 25 50 100 200 10 25 50 100 200

Recall bão hoà, chi phí tuyến tính. Nên tồn tại một k mà sau đó bạn trả tiền để mua gần như không gì. Cách tìm nó:

  1. Đo recall@k của stage 1 tại k = 10, 25, 50, 100, 200 trên golden set của bạn.
  2. Tìm chỗ đường cong bẹt lại — thường recall@k tăng dưới 1 điểm phần trăm mỗi khi k gấp đôi.
  3. Chọn k ở đó. Đo lại latency p95 để chắc nó nằm trong budget (5.9).

Lưu ý một chuyện phản trực giác: k quá lớn có thể làm chất lượng tệ hơn, không chỉ đắt hơn — reranker có thêm cơ hội để một tài liệu nhiễu ăn điểm cao ngẫu nhiên. Bằng chứng và cơ chế ở 5.13.

Bạn đo đượcChẩn đoánViệc cần làm
recall@100 < 0,7stage 1 bỏ sót nhiềuKhông mua reranker. Sửa tokenizer, thêm hybrid, xem lại chunking
recall@100 ≈ 0,95, nDCG@5 ≈ 0,5lấy đúng, xếp saiĐúng bệnh của reranker. Làm ngay
recall@100 ≈ nDCG@5, cả hai caođã gần trầnReranker cho rất ít. Đầu tư vào tầng khác
recall@10 ≈ recall@100stage 1 đã xếp tốtGiảm k xuống 10–25, tiết kiệm mà không mất gì
recall@k cao nhưng RAG vẫn bịalỗi ở tầng generationTầng 8 — Context assembly, không phải reranker

Nên áp dụng vào AI Agent: trước khi viết dòng code reranker đầu tiên, thêm một dòng log recall@k vào pipeline đánh giá. Một con số đó quyết định bạn có nên làm tiếp hay không, và nó rẻ hơn mọi thứ khác trong Phần 5.

Phần 5 — Reranker