Menu
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Đang tải...

Bài 23 — Advanced RAG Techniques

AI Product Manager Bài 23/60

Mở đầu — vì sao bài này quan trọng

Ở Bài 22, bạn đã dựng được một pipeline RAG cơ bản hoàn chỉnh: chia tài liệu thành chunk, nhúng (embed) chúng thành vector, lưu vào vector database, và khi người dùng hỏi thì lấy ra vài chunk gần nhất rồi đưa cho LLM trả lời. Pipeline này chạy được, demo ấn tượng, sếp gật gù. Nhưng rồi bạn đưa nó vào tay người dùng thật, và mọi thứ bắt đầu rạn nứt.

Người dùng hỏi "Chính sách đổi trả của shop thế nào?" thì hệ thống lấy nhầm đoạn nói về chính sách giao hàng. Người dùng hỏi "So sánh gói Basic và Pro" thì RAG chỉ lấy được phần nói về gói Basic vì câu hỏi nghiêng về từ đó. Khách hỏi một câu dài ba dòng thì retrieval trả về toàn chunk không liên quan, vì câu hỏi quá "loãng" về mặt ngữ nghĩa.

Đây chính là ranh giới giữa một RAG demo và một RAG sản phẩm. Naive RAG — embed một lần, retrieve một lần — đủ để gây ấn tượng nhưng không đủ để vận hành. Bài này là bộ công cụ để bạn vượt qua ranh giới đó. Chúng ta sẽ đi sâu vào các kỹ thuật RAG nâng cao, mà trọng tâm là multi-vector retrieval (mỗi tài liệu được biểu diễn bằng nhiều vector khác nhau), cùng các kỹ thuật bổ trợ như query transformation, re-ranking, và contextual retrieval. Đây đều là những thứ một AI Product Manager cần hiểu để biết khi nào chất lượng retrieval đang kém, vì sao kém, và phải đầu tư vào đâu để cải thiện.

Khái niệm cốt lõi

Vấn đề gốc của naive RAG: một chunk, một vector

Trong RAG cơ bản, mỗi chunk văn bản được biến thành đúng một vector. Vector đó phải gánh toàn bộ ý nghĩa của chunk. Nhưng câu hỏi của người dùng và nội dung tài liệu thường không "khớp" nhau về mặt ngôn ngữ.

Ví dụ, tài liệu viết: "Quý khách có thể yêu cầu hoàn tiền trong vòng 7 ngày kể từ khi nhận hàng nếu sản phẩm còn nguyên tem niêm phong." Người dùng lại hỏi: "Mua rồi không thích trả lại được không?" Hai câu này nói về cùng một chuyện, nhưng vector của chúng có thể nằm khá xa nhau trong không gian ngữ nghĩa. Đây gọi là semantic gap — khoảng cách giữa cách người hỏi diễn đạt và cách tài liệu diễn đạt.

Multi-vector retrieval và các kỹ thuật nâng cao đều xoay quanh một ý tưởng: thay vì ép một vector duy nhất gánh tất cả, ta tạo ra nhiều biểu diễn khác nhau cho cùng một nội dung, để tăng xác suất có ít nhất một biểu diễn khớp với câu hỏi.

Multi-vector retrieval — trái tim của bài học

Ý tưởng cốt lõi: mỗi document (hoặc mỗi chunk) không chỉ có một vector, mà có nhiều vector ở nhiều cấp độ trừu tượng khác nhau. Khi truy vấn, ta đối chiếu câu hỏi với loại vector phù hợp nhất.

Các loại vector thường dùng cho một tài liệu:

  • Title embedding — vector nhúng từ tiêu đề. Bắt được chủ đề tổng quát. Hữu ích khi người dùng hỏi mơ hồ ở mức "tài liệu này nói về gì".
  • Summary embedding — vector nhúng từ bản tóm tắt ngắn của tài liệu (thường do LLM sinh ra). Bắt được ý chính mà không bị nhiễu bởi chi tiết vụn vặt.
  • Chunk embeddings — các vector nhúng từ từng đoạn nhỏ. Bắt được chi tiết cụ thể, con số, điều khoản.
  • Hypothetical question embeddings — đây là kỹ thuật rất mạnh: với mỗi chunk, bạn dùng LLM sinh ra 3–5 câu hỏi mà chunk đó có thể trả lời, rồi embed chính các câu hỏi đó. Vì người dùng cũng đang đặt câu hỏi, nên "question khớp question" thường gần nhau hơn "question khớp answer" rất nhiều. Đây gọi là HyDE đảo ngược, hay reverse-HyDE.
Khi một câu hỏi đến, hệ thống có thể tìm trên tất cả các loại vector này (trong cùng một index hoặc nhiều index), rồi gộp kết quả. Điểm tinh tế: dù bạn match được vào title vector hay question vector, thứ bạn trả về cho LLM vẫn là chunk văn bản gốc đầy đủ. Vector chỉ là "cánh cửa" để tìm ra chunk; nội dung trả về là chunk thật. Mô hình này gọi là parent-child retrieval: nhiều vector con (child) cùng trỏ về một document cha (parent).

Query transformation — sửa câu hỏi trước khi tìm

Bên cạnh việc làm giàu phía tài liệu, ta cũng có thể làm giàu phía câu hỏi:

  • Query rewriting: dùng LLM viết lại câu hỏi cho rõ ràng, bỏ từ thừa. "Ờ thì cái món áo khoác hôm trước mình xem ấy còn size M không nhỉ" → "Áo khoác X còn size M không?"
  • Query decomposition: tách một câu hỏi phức tạp thành nhiều câu con. "So sánh gói Basic và Pro về giá và tính năng" → tách thành "Giá gói Basic?", "Giá gói Pro?", "Tính năng gói Basic?", "Tính năng gói Pro?", retrieve riêng từng câu rồi gộp.
  • HyDE (Hypothetical Document Embeddings): dùng LLM sinh ra một câu trả lời giả định cho câu hỏi, rồi embed câu trả lời giả đó để tìm — vì "answer khớp answer" gần hơn "question khớp answer".

Re-ranking — lọc lại sau khi tìm

Retrieval ban đầu (dùng vector similarity) nhanh nhưng thô. Một bước nâng cao là: lấy về nhiều kết quả hơn cần thiết (ví dụ top 20), rồi dùng một mô hình re-ranker (cross-encoder như Cohere Rerank, BGE-reranker) chấm điểm lại từng cặp (câu hỏi, chunk) một cách kỹ lưỡng, và chỉ giữ lại top 5 tốt nhất đưa cho LLM. Re-ranker chậm hơn nhưng chính xác hơn nhiều vì nó nhìn cả câu hỏi và chunk cùng lúc, thay vì so hai vector đã nén sẵn.

Contextual retrieval — vá lỗi mất ngữ cảnh của chunk

Một lỗi kinh điển: khi cắt chunk, một đoạn viết "Mức phí này áp dụng cho năm thứ hai" bị tách khỏi đoạn nói "Gói bảo hiểm An Tâm". Chunk đó mất ngữ cảnh, embed ra một vector vô nghĩa. Kỹ thuật contextual retrieval (Anthropic giới thiệu năm 2024): trước khi embed mỗi chunk, dùng LLM thêm một câu ngữ cảnh ngắn vào đầu chunk — "Đoạn này thuộc gói bảo hiểm An Tâm, mục phí thường niên" — rồi mới embed. Việc này giảm tỷ lệ retrieval thất bại đáng kể.

Tình huống thực tế

Ví dụ 1: Tiki và bài toán hỏi đáp chính sách bán hàng

Giả sử đội product của một sàn thương mại điện tử lớn như Tiki xây trợ lý AI trả lời câu hỏi của người bán (seller) về chính sách: phí sàn, chính sách hoàn hàng, quy định đăng sản phẩm. Họ có khoảng 400 trang tài liệu chính sách.

Phiên bản naive RAG đầu tiên đạt độ chính xác retrieval (đoạn đúng nằm trong top 5) chỉ khoảng 68%. Vấn đề: seller hỏi theo ngôn ngữ đời thường ("bị phạt vì đăng sai danh mục thì gỡ kiểu gì"), còn tài liệu viết theo văn phong pháp lý ("trường hợp vi phạm phân loại ngành hàng, gian hàng cần thực hiện điều chỉnh theo quy trình...").

Đội triển khai hypothetical question embeddings: với mỗi đoạn chính sách, họ dùng LLM sinh 4 câu hỏi đời thường mà đoạn đó trả lời được, rồi embed các câu hỏi này song song với chunk gốc. Khi seller hỏi, câu hỏi của họ khớp với các câu hỏi giả định gần hơn hẳn so với khớp văn bản pháp lý. Độ chính xác retrieval nhảy lên 89%. Bài học: khi có mismatch về văn phong giữa người hỏi và tài liệu, multi-vector bằng câu hỏi giả định là vũ khí hiệu quả nhất, và chi phí chỉ là một lần sinh câu hỏi lúc index (offline, không ảnh hưởng latency lúc chat).

Ví dụ 2: Một fintech Đông Nam Á và câu hỏi so sánh sản phẩm

Một startup fintech ở Singapore làm chatbot tư vấn sản phẩm thẻ tín dụng. Người dùng liên tục hỏi kiểu so sánh: "Thẻ Platinum và thẻ Travel cái nào hoàn tiền cao hơn cho chi tiêu nước ngoài?"

Naive RAG thất bại vì câu hỏi chứa hai thực thể (hai loại thẻ) nhưng vector similarity thường chỉ kéo về tài liệu của một loại thẻ — loại nào "nặng ký" hơn về mặt ngữ nghĩa trong câu. Kết quả là chatbot trả lời thiếu, chỉ nói về một thẻ.

Họ áp dụng query decomposition: một LLM nhỏ tách câu hỏi thành "Thẻ Platinum hoàn tiền chi tiêu nước ngoài bao nhiêu?" và "Thẻ Travel hoàn tiền chi tiêu nước ngoài bao nhiêu?", retrieve độc lập cho từng câu, rồi đưa cả hai bộ chunk cho LLM tổng hợp câu trả lời so sánh. Tỷ lệ câu trả lời "đầy đủ cả hai vế" tăng từ 54% lên 92%. Họ cũng thêm một re-ranker để cắt từ 16 chunk xuống 6 chunk chất lượng nhất, giảm token và giảm cả hiện tượng LLM bị nhiễu. Bài học: với câu hỏi đa thực thể hoặc so sánh, decomposition gần như bắt buộc — vector similarity vốn không giỏi "chia đều sự chú ý".

Ví dụ 3: Trợ lý nội bộ cho ngân hàng và lỗi chunk mất ngữ cảnh

Một ngân hàng Việt Nam xây trợ lý tra cứu quy trình nghiệp vụ cho nhân viên chi nhánh. Tài liệu là các quy trình dài, nhiều bảng biểu, nhiều mục con kiểu "2.3.1", "2.3.2". Khi chunk theo độ dài cố định, rất nhiều đoạn bị mất tiêu đề mục cha, ví dụ một chunk ghi "Bước này cần phê duyệt cấp 2" mà không biết "bước này" thuộc quy trình mở tài khoản hay quy trình vay.

Đội áp dụng contextual retrieval: dùng LLM thêm vào đầu mỗi chunk một dòng ngữ cảnh sinh tự động ("Thuộc quy trình Mở tài khoản doanh nghiệp, mục Phê duyệt hồ sơ"). Họ kết hợp thêm summary embedding ở cấp tài liệu để xử lý câu hỏi tổng quát. Số lượng câu trả lời sai do "nhầm quy trình" giảm khoảng 70%. Bài học: với tài liệu có cấu trúc phân cấp sâu, đừng để chunk "mồ côi" ngữ cảnh — một câu ngữ cảnh thêm vào trước khi embed rẻ hơn nhiều so với một câu trả lời sai cho nhân viên ngân hàng.

Hướng dẫn từng bước

Đây là quy trình nâng cấp một pipeline RAG cơ bản lên cấp nâng cao. Bạn không cần làm hết một lúc — hãy thêm từng lớp và đo lường.

  • Thiết lập thước đo trước đã. Trước khi đụng vào kỹ thuật nào, hãy chuẩn bị một bộ 30–50 câu hỏi thật kèm đáp án/đoạn đúng mong đợi. Đo retrieval recall (đoạn đúng có nằm trong top-k không) và answer quality. Không có thước đo thì mọi "nâng cao" chỉ là cảm tính.
  • Thêm contextual retrieval cho khâu chunk. Với mỗi chunk, dùng LLM sinh một câu ngữ cảnh ngắn dựa trên tài liệu cha, ghép vào đầu chunk rồi mới embed. Đây thường là cải thiện rẻ và mạnh nhất, làm một lần lúc index.
  • Bổ sung multi-vector. Bắt đầu với hypothetical question embeddings: mỗi chunk sinh 3–5 câu hỏi, embed chúng, cho trỏ về chunk cha. Nếu tài liệu dài, thêm summary embedding và title embedding ở cấp document.
  • Thêm query transformation phía đầu vào. Tối thiểu là query rewriting để làm sạch câu hỏi. Nếu sản phẩm của bạn có nhiều câu hỏi so sánh/đa phần, thêm query decomposition.
  • Thêm re-ranking ở cuối. Retrieve rộng (top 15–20), đưa qua re-ranker, giữ top 4–6. Đây thường là cú nâng chất lượng lớn cuối cùng trước khi đến tay LLM.
  • Đo lại sau mỗi lớp. Ghi nhận recall và latency thay đổi thế nào. Mỗi kỹ thuật đều có cái giá về độ trễ và chi phí — bạn cần biết mình đang đánh đổi gì.

Lỗi thường gặp & mẹo

Lỗi: nhồi tất cả kỹ thuật cùng lúc. Nhiều đội bật multi-vector + decomposition + HyDE + re-ranking ngay từ đầu, rồi khi chất lượng vẫn kém thì không biết khâu nào hỏng. Hãy thêm từng lớp, đo từng bước.

Lỗi: quên rằng vector chỉ để tìm, không phải để trả về. Trong multi-vector, người mới hay vô tình đưa cả câu hỏi giả định hoặc bản tóm tắt vào context cho LLM. Sai. Vector con chỉ dùng để định vị; thứ đưa vào prompt phải là chunk gốc đầy đủ.

Lỗi: bỏ qua latency. Query decomposition tạo 4 truy vấn song song, HyDE thêm một lần gọi LLM, re-ranking thêm một bước. Cộng dồn lại, thời gian phản hồi có thể tăng từ 1 giây lên 4–5 giây. Với chatbot real-time, đó là khác biệt sống còn. Mẹo: chạy các bước offline được (sinh câu hỏi, sinh ngữ cảnh, tóm tắt) lúc index; chỉ giữ những gì bắt buộc phải online.

Lỗi: re-rank quá ít ứng viên. Re-ranker chỉ sắp xếp lại những gì retrieval đã đưa lên. Nếu retrieval ban đầu top-5 mà đoạn đúng đứng thứ 12, re-ranker không cứu được. Hãy retrieve rộng (15–20) rồi mới re-rank.

Mẹo: đo "recall ở tầng retrieval" tách biệt với "chất lượng câu trả lời". Nếu câu trả lời sai, hãy xác định lỗi nằm ở retrieval (lấy nhầm đoạn) hay ở generation (lấy đúng đoạn nhưng LLM trả lời sai). Hai lỗi này cần hai cách chữa hoàn toàn khác nhau, và RAG nâng cao chủ yếu chữa lỗi loại đầu.

Mẹo: contextual retrieval thường cho ROI cao nhất với chi phí thấp nhất. Nếu chỉ được làm một thứ, hãy làm việc này trước.

Bài tập thực hành

  • Chẩn đoán semantic gap. Lấy 10 câu hỏi thật của người dùng (hoặc tự nghĩ) và 10 đoạn tài liệu chứa câu trả lời. Viết ra cách diễn đạt khác nhau giữa câu hỏi và tài liệu. Đánh dấu những cặp mà bạn dự đoán naive RAG sẽ khớp kém — đây là nơi multi-vector sẽ giúp.
  • Thiết kế multi-vector trên giấy. Chọn một tài liệu thật (ví dụ chính sách bảo hành của một sản phẩm). Liệt kê: title embedding sẽ là gì, summary embedding nội dung ra sao, và viết tay 4 câu hỏi giả định cho một đoạn cụ thể. Tự đánh giá: các câu hỏi giả định này có giống cách khách thật hỏi không?
  • Xử lý câu hỏi phức tạp. Lấy câu "So sánh gói Free và gói Premium về dung lượng lưu trữ và hỗ trợ kỹ thuật", tự thực hiện query decomposition thành các câu con, và mô tả bạn sẽ gộp kết quả thế nào.
  • Lập kế hoạch đo lường. Viết ra bộ chỉ số bạn sẽ theo dõi khi nâng cấp RAG: retrieval recall@5, latency p95, chi phí token mỗi truy vấn. Với mỗi kỹ thuật trong bài, dự đoán nó tác động lên ba chỉ số này theo hướng nào.

Tóm tắt

Naive RAG đủ để demo, nhưng RAG sản phẩm cần các kỹ thuật nâng cao để vượt qua semantic gap — khoảng cách giữa cách người dùng hỏi và cách tài liệu viết. Trọng tâm của bài là multi-vector retrieval: mỗi tài liệu được biểu diễn bằng nhiều vector ở nhiều cấp (title, summary, chunk, và đặc biệt là câu hỏi giả định), tất cả cùng trỏ về chunk gốc theo mô hình parent-child. Bổ trợ cho nó là query transformation (rewriting, decomposition, HyDE) ở phía đầu vào, re-ranking ở phía đầu ra, và contextual retrieval để vá lỗi chunk mất ngữ cảnh.

Nguyên tắc vận hành quan trọng nhất cho một AI PM: thêm từng lớp một và luôn đo lường. Mỗi kỹ thuật đánh đổi giữa chất lượng, độ trễ và chi phí. Ưu tiên những gì chạy được offline lúc index (sinh câu hỏi, ngữ cảnh, tóm tắt) để giữ trải nghiệm real-time mượt mà. Và hãy nhớ: contextual retrieval thường là cú nâng rẻ-mà-mạnh nhất nếu bạn chỉ được chọn một thứ để làm trước.