Bỏ qua để đến nội dung
Search & RAG

Tầng 10 — Production

Ví dụ ngân sách 800 ms p95 cho một lượt trả lời:

query normalise + rewrite 50 ms (bỏ được nếu không cần)
BM25 5 ms
dense embed truy vấn 30 ms (network tới API embedding)
ANN search 15 ms
rerank top-50 (cross-encoder) 60 ms
context assembly 5 ms
LLM generation (streaming) 600 ms (time-to-first-token là cái người dùng cảm nhận)

Bài học: generation chiếm phần lớn ngân sách. Tối ưu retrieval từ 100 ms xuống 50 ms gần như không ai cảm nhận được. Nhưng streaming để giảm time-to-first-token thì cảm nhận được ngay.

  1. Cache embedding của truy vấn (theo hash chuỗi đã chuẩn hoá) — rẻ, tỷ lệ hit cao.
  2. Cache kết quả retrieval — hiệu quả nếu phân bố truy vấn lệch (thường là vậy).
  3. Cache câu trả lời cuối (semantic cache: truy vấn gần giống dùng lại đáp án) — tiết kiệm nhiều nhất nhưng rủi ro nhất: hai truy vấn gần nhau về embedding có thể cần đáp án khác nhau. Cần ngưỡng chặt và phải đo tỷ lệ trả sai.

Riêng với LLM: prompt caching là món rẻ nhất. Đặt phần tĩnh (system prompt, hướng dẫn) lên trước, phần động (context vừa retrieve, câu hỏi) xuống sau — vì cache là khớp tiền tố, một byte đổi ở đầu làm mất cache toàn bộ phía sau.

Full reindex là kẻ thù. Cần: index tăng trưởng (thêm/sửa/xoá theo tài liệu), phiên bản hoá chunk, và tombstone cho tài liệu đã xoá — quên tombstone là bug rò rỉ dữ liệu, không chỉ là bug chất lượng.

Với mỗi truy vấn: truy vấn gốc, truy vấn sau chuẩn hoá, chunk id được lấy + điểm, chunk id được đưa vào prompt, câu trả lời, phản hồi người dùng, latency từng chặng. Không có log này thì mọi cải thiện sau đây đều là đoán:

  • truy vấn không có kết quả → lỗ hổng nội dung hoặc lỗi tokenizer
  • truy vấn có kết quả nhưng người dùng hỏi lại → lỗi ranking
  • chunk chưa bao giờ được lấy → index rác, hoặc chunking sai
Phần 4 — Lý thuyết