Reranking
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
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
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)
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
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
| 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
import cohere
co = cohere.Client("xxx")
# Giả sử đã retrieve 20 docs
docs = [
"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?"
# Rerank
response = 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.945
Doc: Edison phát minh bóng đèn năm 1879
Score: 0.721
Doc: Lịch sử các loại đèn chiếu sáng
Score: 0.234
Doc: Top 10 bóng đèn LED tiết kiệm điện 2024Code: 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 pairs
pairs = [[query, doc] for doc in docs]
scores = reranker.predict(pairs)
# Sort by score
ranked = 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
| 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
Mục tiêu
So sánh kết quả với và không có Reranking.
Code
# pip install cohere chromadb
import chromadb
import cohere
# Setup
client = 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]
# Compare
query = "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
- 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
| 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.
Last updated on