Skip to Content

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ẻ + nhanh

Reranker Models phổ biến

ModelProviderGiáGhi chú
Cohere RerankAPI$2/1000 queriesBest quality, production-ready
Jina RerankerAPI$0.02/1000Cheap alternative
BGE-RerankerOpen SourceFreeSelf-host, good quality
ColBERTOpen SourceFreeToken-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 2024

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 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

MetricTop-10 Retrieval OnlyTop-50 → Rerank → Top-5
Accuracy (có answer)72%91%
Context tokens50002000
LLM cost/query$0.05$0.02
Latency200ms350ms (+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
RerankerModel chấm điểm relevance
Cross-encoderXem Q và D cùng lúc
Bi-encoderEmbed 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