Chunk đã có embedding. Giờ ta lưu chúng vào vector store và cấu hình cách tìm. Retrieval tốt = agent trả lời đúng; retrieval kém thì prompt giỏi mấy cũng vô ích.
Vector store là gì?
Là cơ sở dữ liệu chuyên lưu vector và tìm nhanh k vector gần nhất (nearest neighbors) với một vector truy vấn. Lựa chọn phổ biến:
- FAISS / Chroma: chạy local, gọn, hợp để bắt đầu và thử nghiệm.
- Qdrant / Weaviate / Milvus: mạnh về metadata filtering, hợp production.
- pgvector (Postgres): tiện nếu đã có Postgres, kết hợp dữ liệu quan hệ.
Bước 1: Nạp (upsert) chunk vào store
for c in chunks:
store.upsert(
id=c["chunk_id"],
vector=c["vector"],
payload={
"text": c["text"],
"doc_id": c["doc_id"],
"title": c["title"],
"page": c["page"],
"access": c["access"], # để lọc quyền
"version": c["version"],
},
)
Luôn lưu kèm payload/metadata — bạn cần nó để trích dẫn và lọc.
Bước 2: Truy vấn top-k
def retrieve(question, k=5, user_groups=None):
q_vec = embed_model.encode(question)
flt = {"access": {"in": user_groups}} if user_groups else None
return store.search(vector=q_vec, top_k=k, filter=flt)
k là số chunk lấy về. k quá nhỏ → thiếu thông tin; quá lớn → nhiễu và tốn token. Bắt đầu với k=4–6.
Bước 3: Nâng chất lượng bằng hybrid search
Embedding (dense) giỏi bắt ngữ nghĩa nhưng đôi khi trượt từ khóa chính xác như mã sản phẩm "SKU-4471" hay tên riêng. Hybrid search kết hợp:
- Dense (vector) — hiểu nghĩa.
- Sparse/keyword (BM25) — khớp từ khóa/mã chính xác.
Bước 4: Re-ranking (tùy chọn nhưng đáng giá)
Lấy top-20 từ vector search, rồi dùng cross-encoder re-ranker chấm lại độ liên quan giữa câu hỏi và từng chunk, giữ top-5. Tốn thêm một chút độ trễ nhưng thường tăng độ chính xác rõ rệt.
Khung tư duy: đường ống retrieval
câu hỏi
→ (hybrid) dense + BM25 → top-20
→ lọc metadata (quyền, version hiện hành)
→ re-rank → top-5
→ đưa vào prompt
Ví dụ: lọc quyền truy cập
Nhân viên thường hỏi "lương của CEO?". Chunk lương lãnh đạo có access: ["finance", "board"]. Nếu người hỏi thuộc ["all-staff"], bộ lọc metadata loại chunk đó khỏi kết quả — agent trả lời "Tôi không tìm thấy thông tin bạn được phép xem". Bảo mật thực thi ở tầng retrieval, không phụ thuộc vào việc LLM "tự giác".
Checklist cấu hình retrieval
- [ ] Lưu đầy đủ metadata trong payload (doc_id, title, page, access, version).
- [ ] Bắt đầu
k=4–6, tinh chỉnh bằng câu hỏi thật. - [ ] Bật lọc metadata: chỉ lấy version hiện hành, đúng quyền.
- [ ] Cân nhắc hybrid search cho tài liệu có mã/tên riêng.
- [ ] Cân nhắc re-ranking nếu độ chính xác chưa đạt.
Sai lầm thường gặp
- Chỉ dùng dense, trượt truy vấn theo mã sản phẩm/số hợp đồng — hãy thêm keyword.
kquá lớn làm prompt ngập nhiễu, LLM lấy nhầm chunk sai.- Không lọc version → chunk cũ và mới cùng về, agent trả lời mâu thuẫn.
- Đẩy kiểm soát quyền cho LLM ("đừng tiết lộ lương") — không đáng tin. Lọc ở retrieval.
- Quên lưu text trong payload → tìm được id nhưng không có nội dung để đưa vào prompt.
Ghi nhớ: retrieval là điểm nghẽn chất lượng
Rất nhiều đội đổ công sức vào prompt và chọn model đắt tiền, nhưng bỏ bê retrieval. Thực tế, nếu chunk đúng không được lấy về, không prompt nào cứu được — LLM đơn giản là không có thông tin để trả lời đúng. Hãy đầu tư thời gian tinh chỉnh k, hybrid search và re-ranking; đo bằng Recall@k (bài 6) trước khi kết luận "model kém". Trong đa số dự án Q&A nội bộ thất bại, thủ phạm là retrieval chứ không phải khả năng sinh của LLM.
Bài 5: viết prompt để LLM trả lời có trích dẫn và biết nói "không biết".