Reranking
Khái niệm cơ bản
Phần tiêu đề “Khái niệm cơ bản”Tưởng tượng bạn đang tuyển dụng…
- Vòng 1 (Retrieval): Lọc 50 CV từ 10,000 đơn bằng keyword matching → Nhanh, nhưng nhiều false positives.
- Vòng 2 (Reranking): HR senior đọc kỹ 50 CV, chọn ra 5 người interview → Chậm, nhưng chính xác.
Reranking = Vòng phỏng vấn chuyên sâu cho documents.
Vấn đề với Embeddings
Phần tiêu đề “Vấn đề với Embeddings”Embeddings đo Similarity (độ tương đồng), không phải Relevance (độ liên quan).
Query: "Ai phát minh ra bóng đèn?"
Embedding similarity cao:1. "Lịch sử đèn điện qua các thời kỳ" (0.85)2. "Thomas Edison và các phát minh" (0.82)3. "Cách chọn bóng đèn LED tiết kiệm điện" (0.80)
Thực tế relevance:1. "Thomas Edison và các phát minh" ← Có câu trả lời!2. "Lịch sử đèn điện" ← Có thể có3. "Cách chọn bóng đèn LED" ← Không liên quan!Reranker hiểu context sâu hơn và sẽ đưa doc 2 lên đầu.
Bi-encoder vs Cross-encoder
Phần tiêu đề “Bi-encoder vs Cross-encoder”Bi-encoder (Embeddings - Fast)
Phần tiêu đề “Bi-encoder (Embeddings - Fast)”Query: "Ai phát minh bóng đèn?" → [0.1, 0.3, ...]Doc: "Edison phát minh bóng đèn 1879" → [0.2, 0.4, ...]Similarity = cosine([Q], [D])- ✅ Nhanh (query 1 lần, docs indexed sẵn)
- ❌ Không thấy interaction giữa Q và D
Cross-encoder (Reranker - Accurate)
Phần tiêu đề “Cross-encoder (Reranker - Accurate)”Input: "[Query] Ai phát minh bóng đèn? [SEP] [Doc] Edison phát minh..."Output: Relevance Score = 0.95- ✅ Thấy cả Q và D cùng lúc → Hiểu context
- ❌ Chậm (phải tính cho từng cặp Q-D)
Pipeline có Reranking
Phần tiêu đề “Pipeline có Reranking”User Query │ ▼[Retrieval] ← Vector Search (top 50) │ ▼[Reranking] ← Cross-encoder (score 50 docs) │ ▼[Top-K Selection] ← Chọn 3-5 docs score cao nhất │ ▼[LLM Generation] ← Ít docs = ít tokens = rẻ + nhanhReranker Models phổ biến
Phần tiêu đề “Reranker Models phổ biến”| Model | Provider | Giá | Ghi chú |
|---|---|---|---|
| Cohere Rerank | API | $2/1000 queries | Best quality, production-ready |
| Jina Reranker | API | $0.02/1000 | Cheap alternative |
| BGE-Reranker | Open Source | Free | Self-host, good quality |
| ColBERT | Open Source | Free | Token-level matching |
Code: Cohere Rerank
Phần tiêu đề “Code: Cohere Rerank”import cohere
co = cohere.Client("xxx")
# Giả sử đã retrieve 20 docsdocs = [ "Edison phát minh bóng đèn năm 1879", "Lịch sử các loại đèn chiếu sáng", "Top 10 bóng đèn LED tiết kiệm điện 2024", # ... 17 docs nữa]
query = "Ai phát minh ra bóng đèn?"
# Rerankresponse = co.rerank( model="rerank-english-v3.0", query=query, documents=docs, top_n=3 # Chỉ lấy top 3)
for result in response.results: print(f"Score: {result.relevance_score:.3f}") print(f"Doc: {docs[result.index]}\n")Output:
Score: 0.945Doc: Edison phát minh bóng đèn năm 1879
Score: 0.721Doc: Lịch sử các loại đèn chiếu sáng
Score: 0.234Doc: Top 10 bóng đèn LED tiết kiệm điện 2024Code: BGE-Reranker (Self-hosted)
Phần tiêu đề “Code: BGE-Reranker (Self-hosted)”from sentence_transformers import CrossEncoder
# Load model (first time will download)reranker = CrossEncoder("BAAI/bge-reranker-base")
query = "Ai phát minh ra bóng đèn?"docs = [ "Edison phát minh bóng đèn năm 1879", "Top 10 bóng đèn LED tiết kiệm điện",]
# Score pairspairs = [[query, doc] for doc in docs]scores = reranker.predict(pairs)
# Sort by scoreranked = sorted(zip(docs, scores), key=lambda x: x[1], reverse=True)for doc, score in ranked: print(f"{score:.3f}: {doc}")Benchmark: Retrieval vs Retrieval + Rerank
Phần tiêu đề “Benchmark: Retrieval vs Retrieval + Rerank”| Metric | Top-10 Retrieval Only | Top-50 → Rerank → Top-5 |
|---|---|---|
| Accuracy (có answer) | 72% | 91% |
| Context tokens | 5000 | 2000 |
| LLM cost/query | $0.05 | $0.02 |
| Latency | 200ms | 350ms (+rerank time) |
💡 Trade-off: +150ms latency nhưng +19% accuracy và -60% cost!
Bài tập thực hành
Phần tiêu đề “Bài tập thực hành”Mục tiêu
Phần tiêu đề “Mục tiêu”So sánh kết quả với và không có Reranking.
# pip install cohere chromadb
import chromadbimport cohere
# Setupclient = chromadb.PersistentClient("./db")collection = client.get_collection("docs")co = cohere.Client("your-api-key")
def search_without_rerank(query: str, k: int = 5): results = collection.query(query_texts=[query], n_results=k) return results["documents"][0]
def search_with_rerank(query: str, retrieve_k: int = 20, top_k: int = 5): # Step 1: Retrieve more results = collection.query(query_texts=[query], n_results=retrieve_k) docs = results["documents"][0]
# Step 2: Rerank reranked = co.rerank(query=query, documents=docs, top_n=top_k)
return [docs[r.index] for r in reranked.results]
# Comparequery = "Chính sách nghỉ phép như thế nào?"
print("Without Rerank:")for doc in search_without_rerank(query): print(f"- {doc[:50]}...")
print("\nWith Rerank:")for doc in search_with_rerank(query): print(f"- {doc[:50]}...")Quan sát
Phần tiêu đề “Quan sát”- Document nào bị “đẩy xuống” sau rerank?
- Document nào “nhảy lên” top?
- Relevance có cải thiện không?
Tóm tắt
Phần tiêu đề “Tóm tắt”| Khái niệm | Ý nghĩa |
|---|---|
| Reranker | Model chấm điểm relevance |
| Cross-encoder | Xem Q và D cùng lúc |
| Bi-encoder | Embed riêng Q và D |
| Trade-off | +latency, +accuracy, -cost |
Bài tiếp theo: Modular RAG - Kiến trúc RAG nâng cao.