Contextual Retrieval — Nâng cấp RAG với embeddings ngữ cảnh
Điểm nổi bật
Nhấn để đến mục tương ứng
- 1 Hành động cụ thể: Trong RAG truyền thống, tài liệu được chia thành các chunk nhỏ để embedding và truy xuất hiệu quả. Phần này hướng dẫn bạn cách triển khai thực tế, không chỉ lý thuyết suông.
- 2 Một điều ít người đề cập: Pipeline gồm 5 bước tiến hóa: Baseline RAG — Chunk + Embed + Cosine similarity 87% Pass@10 Contextual Embeddings — Thêm. Hiểu rõ bối cảnh áp dụng sẽ quyết định 80% thành công khi triển khai.
- 3 Nội dung cốt lõi: Ý tưởng cốt lõi: dùng Claude sinh một đoạn mô tả ngắn 2-3 câu cho mỗi chunk, giải thích chunk đó chứa gì và nằm ở đâu. Nắm vững phần này sẽ giúp bạn áp dụng hiệu quả hơn 70% so với đọc lướt toàn bài.
- 4 Bước đầu tiên bạn nên làm: BM25 thuật toán xếp hạng keyword xác suất bổ khuyết điểm này. Áp dụng đúng cách sẽ thấy kết quả rõ rệt từ tuần đầu tiên.
- 5 Một điều ít người đề cập: Mỗi kỹ thuật thêm complexity và chi phí: Contextual Embeddings : Chi phí ingestion một lần ~$3 cho 737 chunks với. Hiểu rõ bối cảnh áp dụng sẽ quyết định 80% thành công khi triển khai.
Trong bài hướng dẫn này, bạn sẽ xây dựng hệ thống Contextual Retrieval — một kỹ thuật nâng cấp RAG giúp giảm tỷ lệ truy xuất sai đến 35%. Chúng ta sẽ đi qua từng bước: RAG cơ bản → Contextual Embeddings → BM25 Hybrid Search → Reranking, với kết quả đo lường cụ thể trên dataset thực.
Bài viết dựa trên Claude Cookbooks chính thức của Anthropic, được dịch và biên soạn lại cho độc giả Việt Nam.
Vấn đề của RAG truyền thống
Trong RAG truyền thống, tài liệu được chia thành các chunk nhỏ để embedding và truy xuất hiệu quả. Tuy nhiên, điều này tạo ra một vấn đề quan trọng: mỗi chunk riêng lẻ thiếu ngữ cảnh từ tài liệu gốc.
Ví dụ, một chunk chứa đoạn code def process_data(input): không cho biết nó thuộc file nào, module nào, hay giải quyết bài toán gì. Khi người dùng hỏi "Làm sao xử lý dữ liệu đầu vào?", hệ thống có thể trả về chunk không liên quan vì embedding không capture đủ context.
Contextual Embeddings giải quyết vấn đề này bằng cách thêm mô tả ngữ cảnh vào mỗi chunk trước khi embedding.
Kiến trúc hệ thống
Pipeline gồm 5 bước tiến hóa:
- Baseline RAG — Chunk + Embed + Cosine similarity (87% Pass@10)
- Contextual Embeddings — Thêm context cho mỗi chunk (92% Pass@10)
- Contextual BM25 — Kết hợp semantic + keyword search (93% Pass@10)
- Reranking — Dùng model chuyên biệt sắp xếp lại kết quả (95% Pass@10)
Bước 1: Baseline RAG — Điểm xuất phát (87%)
Pipeline cơ bản nhất gồm 3 bước:
- Chunk tài liệu theo heading — mỗi chunk chứa nội dung dưới một subheading
- Embed mỗi chunk thành vector bằng Voyage AI
- Cosine similarity để tìm chunk liên quan nhất khi có query
Với dataset 737 chunks từ 9 codebase và 248 câu hỏi đánh giá, baseline đạt:
- Pass@5: 80.92%
- Pass@10: 87.15%
- Pass@20: 90.06%
Tốt, nhưng vẫn bỏ sót 13% golden chunks trong top 10 kết quả.
Bước 2: Contextual Embeddings — Thêm ngữ cảnh (92%)
Ý tưởng cốt lõi: dùng Claude sinh một đoạn mô tả ngắn (2-3 câu) cho mỗi chunk, giải thích chunk đó chứa gì và nằm ở đâu trong tài liệu gốc. Đoạn mô tả này được ghép vào trước chunk trước khi embedding.
Cách hoạt động
def generate_context(document, chunk):
"""Dùng Claude sinh ngữ cảnh cho chunk"""
response = client.messages.create(
model="claude-haiku-4-5",
messages=[{
"role": "user",
"content": f"""Đây là tài liệu nguồn:
<document>{document}</document>
Đây là chunk cần thêm ngữ cảnh:
<chunk>{chunk}</chunk>
Viết 2-3 câu ngắn mô tả chunk này chứa gì
và vị trí của nó trong tài liệu. Chỉ trả về
mô tả, không giải thích thêm."""
}],
max_tokens=200
)
return response.content[0].text
# Ghép context + chunk rồi mới embed
contextualized_text = context + "\n\n" + chunk
embedding = voyage_client.embed(contextualized_text)
Prompt Caching — Giảm chi phí 69%
Vì tất cả chunks cùng một tài liệu đều cần context từ cùng document đó, prompt caching phát huy tác dụng cực lớn:
- Chunk đầu tiên: Ghi toàn bộ document vào cache (trả phí nhỏ)
- Các chunk sau: Đọc document từ cache (giảm 90% chi phí token)
- Cache tồn tại 5 phút — đủ thời gian xử lý tất cả chunks trong một document
Trên dataset 737 chunks: 61.83% input tokens được đọc từ cache. Chi phí giảm từ ~$9.20 xuống ~$2.85 (tiết kiệm 69%).
Kết quả
Contextual Embeddings cải thiện đáng kể:
- Pass@5: 80.92% → 88.12% (+7.2 điểm)
- Pass@10: 87.15% → 92.34% (+5.2 điểm)
- Pass@20: 90.06% → 94.29% (+4.2 điểm)
Giảm 30-40% lỗi truy xuất ở mọi mức k. Cải thiện mạnh nhất ở Pass@5 — chunk đúng không chỉ được tìm thấy nhiều hơn mà còn xếp hạng cao hơn.
Bước 3: Contextual BM25 — Hybrid Search (93%)
Semantic search (embedding) giỏi hiểu ý nghĩa, nhưng có thể bỏ sót các keyword chính xác. BM25 (thuật toán xếp hạng keyword xác suất) bổ khuyết điểm này.
Kết hợp hai nguồn bằng Reciprocal Rank Fusion
def retrieve_hybrid(query, k=10):
# 1. Lấy top 150 từ semantic search
semantic_results = vector_db.search(query, k=150)
# 2. Lấy top 150 từ BM25 (search cả chunk + context)
bm25_results = elasticsearch.search(query, k=150)
# 3. Kết hợp bằng weighted Reciprocal Rank Fusion
# 80% trọng số cho semantic, 20% cho BM25
combined = reciprocal_rank_fusion(
semantic_results,
bm25_results,
weights=[0.8, 0.2]
)
return combined[:k]
Thay vì search raw chunk, BM25 search cả chunk lẫn contextual description — nghĩa là keyword có thể match trong mô tả ngữ cảnh mà Claude đã sinh.
Kết quả: 93.21% Pass@10 — BM25 bắt được các query mà semantic search bỏ sót (tên hàm cụ thể, thuật ngữ chuyên ngành).
Bước 4: Reranking — Tinh chỉnh thứ hạng (95%)
Reranking là kỹ thuật 2 giai đoạn:
- Giai đoạn 1 — Truy xuất rộng: Lấy nhiều ứng viên hơn cần thiết (100 chunks)
- Giai đoạn 2 — Chọn lọc chính xác: Dùng reranking model (Cohere rerank-english-v3.0) chấm điểm và chỉ giữ top-k
Tại sao hiệu quả? Embedding và BM25 được tối ưu cho tốc độ trên hàng triệu tài liệu. Reranking model chậm hơn nhưng chính xác hơn — có thể phân tích sâu trên tập nhỏ ứng viên.
Kết quả: 95.26% Pass@10 — giảm 47% lỗi truy xuất so với baseline.
Tổng kết: So sánh các kỹ thuật
| Approach | Pass@5 | Pass@10 | Pass@20 |
|---|---|---|---|
| Baseline RAG | 80.92% | 87.15% | 90.06% |
| + Contextual Embeddings | 88.12% | 92.34% | 94.29% |
| + Hybrid Search (BM25) | 86.43% | 93.21% | 94.99% |
| + Reranking | 92.15% | 95.26% | 97.45% |
Trade-offs và khuyến nghị
Mỗi kỹ thuật thêm complexity và chi phí:
- Contextual Embeddings: Chi phí ingestion một lần (~$3 cho 737 chunks với prompt caching). Không có chi phí per-query.
- Hybrid Search: Cần hạ tầng Elasticsearch. Không thêm chi phí per-query.
- Reranking: Thêm 100-200ms latency và ~$0.002 per query.
Chọn approach theo nhu cầu
- Volume cao, tiết kiệm chi phí: Contextual Embeddings alone (92% Pass@10, không có per-query costs)
- Accuracy tối đa, chấp nhận latency: Full reranking pipeline (95% Pass@10)
- Cân bằng production: Hybrid search (93% Pass@10, không per-query costs)
Áp dụng thực tế
Contextual Retrieval áp dụng cho mọi loại dữ liệu:
- Knowledge base nội bộ — FAQ, tài liệu quy trình công ty
- Codebase documentation — API docs, README, code comments
- Tài liệu pháp lý — Hợp đồng, quy định, luật
- Tài liệu tài chính — Báo cáo, phân tích, dữ liệu thị trường
Khuyến nghị: Bắt đầu với Contextual Embeddings — đây là kỹ thuật cho ROI tốt nhất (cải thiện lớn nhất với chi phí thấp nhất). Chỉ thêm BM25 và reranking khi cần tối ưu thêm 2-3%.
Bước tiếp theo: Đọc thêm về RAG với Claude và Prompt Caching để hiểu sâu hơn về hai kỹ thuật nền tảng.
Bài viết liên quan
Bai viet co huu ich khong?
Bản quyền thuộc về tác giả. Vui lòng dẫn nguồn khi chia sẻ.


