Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Bài 5 — Reranking: đẩy chunk đúng lên đầu

Đã đọc 0/9 mục · còn khoảng 3 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

Retrieval bằng embedding nhanh nhưng "thô": nó so sánh vector câu hỏi với vector chunk một cách độc lập. Reranking dùng một mô hình mạnh hơn để chấm điểm lại từng cặp (câu hỏi, chunk) cùng lúc, cho thứ hạng chính xác hơn nhiều. Đây là cách rẻ nhất để tăng chất lượng RAG.

Vì sao cần reranking

Embedding retrieval (bi-encoder) mã hóa câu hỏi và chunk riêng biệt rồi so vector. Nó bỏ lỡ tương tác chi tiết giữa từ trong câu hỏi và từ trong chunk. Reranker (cross-encoder) đưa cả câu hỏi và chunk vào cùng một lần chạy, nên hiểu quan hệ sâu hơn.

Mô hình 2 tầng kinh điển:

Retrieval (nhanh, top-30)  →  Rerank (chính xác, chọn top-5)  →  LLM
Retrieval lo "recall" (đừng bỏ sót), rerank lo "precision" (chọn đúng cái tốt nhất).

Các loại reranker

  • Cross-encoder (ví dụ bge-reranker-v2-m3): chạy local, nhanh, rẻ, chất lượng cao.
  • Reranker API (Cohere Rerank, Jina): tiện, không cần GPU, trả phí theo lượt.
  • LLM-as-reranker: nhờ LLM chấm điểm liên quan. Chất lượng cao nhưng đắt và chậm, dùng khi số chunk ít.

Ví dụ cụ thể

Câu hỏi: "phép năm chưa dùng có bị mất không?"

Retrieval top-5 trả về (theo điểm cosine):

  • "Đăng ký nghỉ phép qua hệ thống HR." (0.71)
  • "Phép năm chưa dùng vượt 5 ngày sẽ bị hủy vào 31/12." (0.69)
  • "Chế độ thai sản..." (0.66)
Embedding xếp chunk (1) trên vì nhiều từ "phép", nhưng chunk (2) mới trả lời đúng. Reranker đọc cả cặp và đẩy chunk (2) lên #1.

Các bước triển khai

  • Retrieval rộng (k = 20–30) để đảm bảo recall.
  • Rerank các chunk đó:
from sentence_transformers import CrossEncoder
reranker = CrossEncoder("BAAI/bge-reranker-v2-m3")

def rerank(query, candidates, top_n=5):
    pairs = [(query, c["text"]) for c in candidates]
    scores = reranker.predict(pairs)
    ranked = sorted(zip(candidates, scores), key=lambda x: x[1], reverse=True)
    return [c for c, s in ranked[:top_n]]
  • Đưa top-n sau rerank vào context LLM.
  • Đo lại recall@k trước và sau rerank trên cùng gold set để chứng minh cải thiện.

Ngưỡng điểm (score threshold)

Reranker cho điểm liên quan có thể dùng làm ngưỡng lọc. Nếu chunk tốt nhất vẫn dưới ngưỡng → agent nên nói "tôi không tìm thấy thông tin" thay vì bịa:

best = ranked[0]
if best[1] < THRESHOLD:
    return "Không tìm thấy thông tin đủ tin cậy trong tài liệu."
Đây là lá chắn chống hallucination mạnh nhất trong pipeline RAG.

Khung tư duy: retrieval rộng, rerank hẹp

  • Retrieval k lớn → không bỏ sót (tối đa recall).
  • Rerank chọn ít → context sạch, LLM tập trung (tối đa precision).
  • Ngưỡng rerank → biết khi nào nên từ chối trả lời.

Checklist reranking

  • [ ] Retrieval lấy đủ rộng (k ≥ 20) trước khi rerank.
  • [ ] Đo recall@5 trước/sau rerank để xác nhận có cải thiện.
  • [ ] Có ngưỡng điểm để từ chối khi không đủ tin cậy.
  • [ ] Cân nhắc độ trễ: rerank 30 chunk thêm bao nhiêu ms?
  • [ ] Log điểm rerank để debug khi câu trả lời sai.

Sai lầm thường gặp

  • Rerank trên top-3: nếu retrieval đã bỏ sót chunk đúng, rerank không có gì để cứu. Phải retrieval rộng trước.
  • Bỏ qua ngưỡng điểm: agent luôn trả lời kể cả khi chunk tốt nhất vẫn không liên quan → hallucinate.
  • Dùng LLM-as-reranker cho 30 chunk mỗi query: chậm và đắt gấp nhiều lần, giết trải nghiệm.
  • Không đo: thêm reranker nhưng không chứng minh nó cải thiện — có khi còn làm tệ hơn nếu chọn sai model.
Bài 6: viết lại truy vấn và các kỹ thuật retrieval nâng cao cho agent.

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi