RAG nâng cao 5 — Biến đổi & định tuyến câu hỏi

13 thg 7, 2026 3 lượt xem
#ai
#rag
#routing
#hyde
#query-rewriting

RAG nâng cao 1 — Tổng quanRAG nâng cao 3 — Hybrid Search ta đã bàn cách đánh chỉ mụctruy hồi cho tốt. Ở RAG nâng cao 4 — Reranking ta lọc lại kết quả sau khi truy hồi. Nhưng có một khâu đứng trước tất cả thường bị bỏ quên: chính bản thân câu hỏi của người dùng. Nếu câu hỏi đưa vào retriever mơ hồ, thiếu từ khoá, chứa nhiều ý hay đại từ trỏ ngược hội thoại, thì dù index tốt và reranker mạnh đến đâu, hệ thống vẫn tìm nhầm đoạn. Bài này gom các kỹ thuật biến đổi câu hỏi (query transformation)định tuyến (routing) — cải thiện RAG từ phía đầu vào.

Vì sao câu hỏi người dùng thường "khó tìm"

Truy vấn thực tế của người dùng ngân hàng khác xa câu hỏi mẫu đẹp đẽ trong demo. Chúng thường vướng bốn loại vấn đề:

  • Mơ hồ, thiếu ngữ cảnh. "Vay mua nhà cần gì?" — thiếu từ khoá then chốt như điều kiện tín dụng, thu nhập chứng minh, tài sản bảo đảm. Đoạn tài liệu chuẩn lại viết bằng ngôn ngữ nghiệp vụ ("hồ sơ tài chính chứng minh khả năng trả nợ") nên vector của câu hỏi ngắn không đủ tín hiệu để khớp.
  • Thiếu từ khoá / quá ngắn. Câu hỏi 3–5 từ tạo embedding "loãng", nằm ở vùng trung tính, không đủ đặc trưng để tách khỏi hàng nghìn đoạn khác.
  • Nhiều ý trong một câu. "So sánh lãi suất và điều kiện giải ngân giữa gói vay mua nhà và vay tiêu dùng?" — một lần truy hồi khó lấy đủ mọi mảnh.
  • Đại từ và ngữ cảnh hội thoại. Trong chatbot đa lượt, người dùng hỏi tiếp "Thế cái đó áp dụng cho khách hàng doanh nghiệp không?". Từ "cái đó" chỉ có nghĩa khi biết lượt trước; gửi thẳng vào retriever thì vô nghĩa về mặt ngữ nghĩa.

Ý tưởng chung: đừng truy hồi thẳng câu hỏi thô. Hãy dùng một (hoặc vài) lời gọi LLM để viết lại, mở rộng, tách nhỏ hoặc điều hướng câu hỏi thành dạng mà retriever "thích" hơn.

Các kỹ thuật biến đổi câu hỏi

1. Query rewriting (viết lại câu hỏi)

Nhờ LLM viết lại câu hỏi thành một phiên bản rõ ràng, đủ từ khoá, tự chứa ngữ cảnh. Hai công dụng chính:

  • Làm giàu từ khoá và chuẩn hoá thuật ngữ. "Vay mua nhà cần gì?" → "Điều kiện và hồ sơ vay mua nhà: yêu cầu thu nhập, tài sản bảo đảm, tỷ lệ cho vay trên giá trị tài sản (LTV), thời hạn vay". Bản viết lại có nhiều từ khoá trùng với tài liệu nghiệp vụ hơn.
  • Giải nghĩa đại từ theo lịch sử hội thoại (query contextualization). Đây là bước gần như bắt buộc cho chatbot đa lượt. LLM nhận cả lịch sử hội thoại và câu hỏi mới, rồi viết lại thành một câu độc lập (standalone): "Thế cái đó áp dụng cho khách hàng doanh nghiệp không?" → "Gói vay mua nhà lãi suất ưu đãi 8,5%/năm có áp dụng cho khách hàng doanh nghiệp không?".

Query rewriting rẻ, hiệu quả cao, và nên là kỹ thuật mặc định bật cho mọi hệ thống hội thoại.

2. Multi-query (sinh nhiều biến thể)

Một câu hỏi chỉ nhìn vấn đề từ một góc. Ý tưởng multi-query: nhờ LLM sinh 3–5 biến thể diễn đạt khác nhau của cùng câu hỏi, truy hồi từng biến thể, rồi hợp nhất danh sách kết quả (thường bằng Reciprocal Rank Fusion — xem cách hợp nhất ở RAG nâng cao 3).

Ví dụ "điều kiện vay mua nhà" → các biến thể:

  1. "Ngân hàng yêu cầu gì để duyệt khoản vay mua nhà?"
  2. "Hồ sơ chứng minh thu nhập cho vay mua bất động sản gồm những gì?"
  3. "Tỷ lệ cho vay tối đa và tài sản bảo đảm khi vay mua nhà?"

Mỗi biến thể "chạm" vào một vùng ngữ nghĩa khác nhau, nên tăng recall rõ rệt — giảm khả năng bỏ sót đoạn liên quan chỉ vì cách diễn đạt lệch. Cái giá: nhiều lời gọi retriever hơn (và một lời gọi LLM để sinh biến thể).

3. HyDE — Hypothetical Document Embeddings

Vấn đề gốc của dense retrieval: ta so embedding của câu hỏi với embedding của đoạn tài liệu, nhưng câu hỏi và câu trả lời có "hình dạng" ngôn ngữ rất khác nhau (một câu hỏi ngắn 8 từ vs. một đoạn văn 120 từ). Khoảng cách đó gọi là asymmetry giữa query và document.

HyDE (Hypothetical Document Embeddings) lật ngược vấn đề: thay vì embed câu hỏi, ta nhờ LLM viết một câu trả lời giả định — cứ trả lời như thể biết đáp án, kể cả có thể sai chi tiết — rồi embed đoạn giả định đó để đi tìm. Trực giác: đoạn văn trả lời giả định có "hình dạng" giống tài liệu thật hơn nhiều so với câu hỏi ngắn, nên khớp vector tốt hơn.

Ví dụ với "điều kiện vay mua nhà?", LLM sinh đoạn giả định: "Để vay mua nhà, khách hàng cần chứng minh thu nhập ổn định, có tài sản bảo đảm là chính bất động sản mua, tỷ lệ cho vay tối đa khoảng...% giá trị, thời hạn tới... năm." Ta embed đoạn này — không cần đúng số liệu, chỉ cần đúng chủ đề và văn phong để kéo về đúng vùng tài liệu.

Lưu ý: HyDE mạnh khi corpus có đoạn văn diễn giải dài; với truy vấn cần khớp mã/số hợp đồng thì hybrid + BM25 vẫn nhỉnh hơn. HyDE có thể "ảo giác" lệch chủ đề nếu câu hỏi quá lạ — khi đó nên kết hợp cả embedding câu hỏi gốc.

4. Query decomposition (tách câu hỏi)

Với câu hỏi phức tạp, đa bước hoặc so sánh, ta tách thành các câu con (sub-questions), truy hồi và trả lời từng phần, rồi tổng hợp thành đáp án cuối. Ví dụ:

"So sánh điều kiện và lãi suất giữa gói vay mua nhà và vay tiêu dùng, gói nào phù hợp cho khách thu nhập 20 triệu/tháng?"

tách thành:

  1. Điều kiện & lãi suất gói vay mua nhà?
  2. Điều kiện & lãi suất gói vay tiêu dùng?
  3. (Suy luận tổng hợp trên kết quả 1 + 2 với ràng buộc thu nhập.)

Đây chính là hạt nhân của agentic RAG: một vòng lặp lập kế hoạch → truy hồi → suy luận → truy hồi tiếp, thay vì một lượt tĩnh (chi tiết ở RAG nâng cao 7 — Agentic RAG). Decomposition đắt hơn (nhiều vòng LLM + retriever) nên chỉ nên kích hoạt khi phát hiện câu hỏi thực sự đa ý.

5. Step-back prompting (lùi một bước)

Đôi khi câu hỏi quá cụ thể khiến retriever chỉ tìm được mảnh vụn mà thiếu nền kiến thức. Step-back prompting nhờ LLM đặt một câu hỏi tổng quát hơn để lấy bối cảnh, rồi dùng cả nền đó lẫn câu hỏi gốc để trả lời.

Ví dụ: "Khách A vay 2 tỷ mua căn hộ 2,5 tỷ có được duyệt không?" → câu lùi bước: "Quy định về tỷ lệ cho vay tối đa (LTV) đối với vay mua nhà tại NCB là gì?". Truy hồi câu tổng quát lấy được quy tắc chung; sau đó LLM áp quy tắc vào tình huống cụ thể (2/2,5 = 80% LTV) để kết luận.

Routing — định tuyến câu hỏi tới đúng nguồn

Biến đổi câu hỏi giả định ta đã biết tìm ở đâu. Nhưng hệ thống thực tế có nhiều nguồn: kho tài liệu tín dụng, kho quy định nội bộ, một bảng SQL số liệu, một API tỷ giá, hay đơn giản là câu hỏi xã giao chẳng cần truy hồi gì. Routing là bước quyết định câu hỏi nên đi đường nào:

  • Chọn nguồn / collection. Câu hỏi về sản phẩm vay → vector store tín dụng; câu hỏi về quy trình mở tài khoản → collection vận hành.
  • Chọn công cụ (tool). "Có bao nhiêu khách hàng ở Hà Nội?" là câu định lượng → nên sinh SQL truy vấn cơ sở dữ liệu, KHÔNG phải tìm tài liệu văn bản. "Điều kiện vay là gì?" → tìm tài liệu.
  • Trả lời trực tiếp. "Chào bạn" hoặc câu hỏi mà LLM chắc chắn biết → bỏ qua retrieval, trả lời thẳng để giảm độ trễ.

Hai cách triển khai phổ biến:

  • Semantic router. Nhúng (embed) trước một tập câu ví dụ đại diện cho mỗi tuyến (route). Câu hỏi mới được embed và so cosine với từng nhóm; nhóm gần nhất thắng. Rất nhanh, rẻ (chỉ một phép embed, không tốn LLM), phù hợp phân loại vào số tuyến cố định.
  • LLM router (function calling). Đưa mô tả các nguồn/công cụ cho LLM và để nó chọn tool phù hợp. Linh hoạt hơn, xử lý được câu phức, nhưng tốn một lời gọi LLM. Đây là mắt xích cốt lõi khi thiết kế "khung" cho agent — xem Agent 1 — Harness Engineering.

Sơ đồ dưới đây gộp toàn bộ pipeline: chuẩn hoá ngữ cảnh, router chọn nhánh, rồi các nhánh truy hồi (với multi-query/HyDE) hoặc chuyển sang SQL / trả lời trực tiếp.

Đánh đổi: mỗi kỹ thuật là thêm một lời gọi LLM

Điểm cần khắc cốt: mọi kỹ thuật ở trên (trừ semantic router) đều thêm ít nhất một lời gọi LLM trước khi truy hồi. Điều đó nghĩa là thêm chi phí tokenđộ trễ. Trong một hệ thống trả lời realtime, chuỗi rewrite → multi-query → HyDE → decompose có thể cộng dồn 3–5 lời gọi LLM, đẩy p95 latency từ ~1s lên 4–6s.

Kỹ thuậtChi phí thêmLợi ích chínhKhi nào dùng
Query rewriting1 LLM callGiải nghĩa đại từ, thêm từ khoáMặc định cho chatbot đa lượt
Multi-query1 LLM + N retrievalTăng recallCâu mơ hồ, corpus đa dạng cách diễn đạt
HyDE1 LLM callKhớp query–document tốt hơnCorpus nhiều đoạn diễn giải dài
DecompositionNhiều LLM + retrievalXử lý câu đa bước/so sánhChỉ khi phát hiện câu phức
Step-back1 LLM + 1 retrievalLấy nền kiến thứcCâu quá cụ thể, thiếu bối cảnh
Semantic router1 embed (rất rẻ)Chọn đúng nguồn, giảm truy hồi thừaGần như luôn nên có

Nguyên tắc thực chiến: dùng có chọn lọc, đừng bật hết. Một pipeline tốt thường: (1) luôn rewrite/contextualize; (2) luôn route; (3) chỉ bật multi-query/HyDE/decomposition có điều kiện — dựa vào độ dài câu hỏi, độ tự tin của router, hoặc điểm retrieval lượt đầu thấp. Sau khi truy hồi vẫn nên rerank để cắt nhiễu do multi-query mang về.

Pseudocode minh hoạ

Đoạn dưới minh hoạ luồng route → (multi-query + HyDE) → hợp nhất, dùng SDK Anthropic với mô hình claude-opus-4-8. Đây là mã ý niệm để nắm luồng, không phải mã production (thiếu xử lý lỗi, cache, backoff, kiểm soát token).

# MINH HOẠ — không phải mã chạy thẳng production
from anthropic import Anthropic
client = Anthropic()
MODEL = "claude-opus-4-8"

def ask_llm(prompt: str) -> str:
    msg = client.messages.create(
        model=MODEL, max_tokens=1024,
        messages=[{"role": "user", "content": prompt}],
    )
    return msg.content[0].text

def route(question: str) -> str:
    # LLM router: chọn nhánh xử lý
    r = ask_llm(
        f"Phân loại câu hỏi vào MỘT nhãn: DOCS | SQL | DIRECT.\n"
        f"DOCS=cần tra tài liệu nghiệp vụ; SQL=cần đếm/tính số liệu; "
        f"DIRECT=xã giao/đã biết.\nCâu: {question}\nChỉ in nhãn."
    ).strip()
    return r

def multi_query(question: str, n: int = 4) -> list[str]:
    out = ask_llm(
        f"Viết {n} cách diễn đạt khác nhau cho câu hỏi, mỗi dòng một câu:\n{question}"
    )
    return [line.strip("-• ") for line in out.splitlines() if line.strip()]

def hyde(question: str) -> str:
    # Câu trả lời GIẢ ĐỊNH để embed, không cần đúng số liệu
    return ask_llm(
        f"Viết một đoạn trả lời giả định (3-4 câu) cho câu hỏi, "
        f"văn phong như tài liệu nghiệp vụ ngân hàng:\n{question}"
    )

def rrf_merge(ranked_lists, k: int = 60):
    scores = {}
    for lst in ranked_lists:
        for rank, doc_id in enumerate(lst):
            scores[doc_id] = scores.get(doc_id, 0) + 1 / (k + rank + 1)
    return sorted(scores, key=scores.get, reverse=True)

def answer(question: str, history: str = ""):
    # 1) Rewrite/contextualize theo lịch sử hội thoại
    standalone = ask_llm(
        f"Lịch sử:\n{history}\nCâu mới: {question}\n"
        f"Viết lại thành câu hỏi độc lập, đủ từ khoá."
    )
    branch = route(standalone)          # 2) Định tuyến
    if branch == "DIRECT":
        return ask_llm(standalone)
    if branch == "SQL":
        return run_sql_tool(standalone)  # sinh & chạy SQL ở lớp riêng

    # 3) DOCS: multi-query + HyDE rồi hợp nhất
    queries = multi_query(standalone) + [hyde(standalone)]
    ranked = [vector_search(embed(q), top_k=20) for q in queries]
    fused = rrf_merge(ranked)[:20]
    reranked = rerank(standalone, fused)[:5]   # xem bài Reranking
    context = "\n\n".join(fetch(d) for d in reranked)
    return ask_llm(f"Dựa trên ngữ cảnh:\n{context}\n\nTrả lời: {standalone}")

Các hàm embed, vector_search, rerank, fetch, run_sql_tool là lớp hạ tầng, không trình bày ở đây.

Use case thực tế

Bối cảnh. NCB triển khai trợ lý hỏi đáp nội bộ cho ~300 cán bộ tín dụng, tra cứu quy định sản phẩm vay. Câu hỏi thực tế rất "đời": ngắn, mơ hồ, hay hỏi nối tiếp. Ví dụ điển hình một cán bộ gõ: "điều kiện vay mua nhà?" rồi lượt sau "thế cái đó cho hộ kinh doanh thì sao?".

Trước cải tiến (RAG thô). Câu hỏi thô được embed và tìm thẳng trong một vector store gộp chung mọi loại tài liệu (vay, thẻ, tiết kiệm, quy trình vận hành). Vấn đề:

  • Câu 4 từ tạo embedding loãng → top-5 lẫn cả tài liệu vay tiêu dùng và thẻ tín dụng.
  • Câu nối tiếp có "cái đó" → truy hồi gần như ngẫu nhiên vì mất ngữ cảnh.
  • Đo trên bộ 120 câu hỏi nghiệp vụ (gán nhãn đoạn đúng thủ công): recall@5 ≈ 61%, tỷ lệ cán bộ đánh giá "trả lời hữu ích" ≈ 58%. Các con số này là ước lượng minh hoạ cho bối cảnh bài viết.

Sau cải tiến. Áp dụng pipeline: (1) rewrite/contextualize mọi câu theo lịch sử hội thoại — "cái đó cho hộ kinh doanh thì sao?" → "Điều kiện vay mua nhà đối với khách hàng là hộ kinh doanh cá thể tại NCB?"; (2) semantic router phân câu vào đúng collection (ở đây: kho tín dụng), loại nhiễu từ tài liệu thẻ/tiết kiệm; (3) multi-query (4 biến thể) + HyDE, hợp nhất RRF rồi rerank lấy top-5. Kết quả ước lượng: recall@5 ≈ 84%, "trả lời hữu ích" ≈ 82%. Đổi lại độ trễ p95 tăng từ ~1,1s lên ~3,4s và chi phí token/câu tăng ~3,5 lần.

Tối ưu chi phí. Để không phải trả giá đó cho mọi câu, NCB bật multi-query + HyDE có điều kiện: chỉ khi câu hỏi < 8 từ hoặc điểm retrieval lượt đầu dưới ngưỡng. Với câu đã rõ ("Phí tất toán trước hạn gói vay mua nhà 2024?"), hệ thống bỏ qua bước sinh biến thể, giữ độ trễ ~1,3s. Router thì luôn bật vì semantic router chỉ tốn một phép embed.

Về các câu định lượng. Một số câu như "Chi nhánh nào có dư nợ vay mua nhà cao nhất?" được router gắn nhãn SQL và chuyển sang lớp text-to-SQL truy vấn kho dữ liệu, thay vì tìm tài liệu văn bản — minh hoạ giá trị của routing trong việc chọn đúng công cụ, không chỉ đúng đoạn văn.

Ghi nhớ

  • Chất lượng RAG bắt đầu từ câu hỏi: câu thô thường mơ hồ, thiếu từ khoá, đa ý hoặc chứa đại từ hội thoại — truy hồi thẳng dễ trượt.
  • Query rewriting / contextualize (giải nghĩa đại từ, chuẩn hoá thuật ngữ) là kỹ thuật rẻ, nên mặc định bật cho mọi chatbot đa lượt.
  • Multi-query tăng recall bằng cách sinh nhiều biến thể rồi hợp nhất (RRF); HyDE khớp query–document tốt hơn bằng cách embed một câu trả lời giả định thay vì câu hỏi ngắn.
  • Query decomposition tách câu đa bước/so sánh thành câu con — hạt nhân của agentic RAG; step-back lấy nền kiến thức tổng quát trước khi trả lời câu cụ thể.
  • Routing đưa câu hỏi tới đúng nguồn/công cụ (vector store nào, tài liệu vs SQL, hay trả lời trực tiếp): semantic router rẻ và nhanh, LLM router linh hoạt (xem harness engineering).
  • Mỗi kỹ thuật (trừ semantic router) thêm một lời gọi LLM → thêm chi phí và độ trễ. Dùng có chọn lọc, có điều kiện, và luôn rerank sau khi truy hồi để cắt nhiễu.

Nguồn tham khảo

  • Gao et al. (2022), "Precise Zero-Shot Dense Retrieval without Relevance Labels" — bài giới thiệu HyDE (Hypothetical Document Embeddings), arXiv:2212.10496
  • Zheng et al. (2023), "Take a Step Back: Evoking Reasoning via Abstraction in Large Language Models" — bài gốc về Step-Back Prompting, arXiv:2310.06117
  • Ma et al. (2023), "Query Rewriting for Retrieval-Augmented Large Language Models" — arXiv:2305.14283
  • LangChain Documentation — "MultiQueryRetriever" (kỹ thuật sinh nhiều biến thể câu hỏi)
  • Rackauckas (2024), "RAG-Fusion: A New Take on Retrieval-Augmented Generation" — arXiv:2402.03367
  • Anthropic Documentation — "Retrieval augmented generation" và hướng dẫn tool use / function calling

Bài viết liên quan

Đặt nền cho chuỗi AI: phân biệt ba vòng tròn lồng nhau AI ⊃ ML ⊃ DL và khác biệt bản chất giữa lập trình truyền thống với học từ dữ liệu. Giới thiệu ba kiểu học máy (supervised, unsupervised, reinforcement), phân loại descriptive/predictive/prescriptive, quy trình ML end-to-end, chia train/validation/test, overfitting/underfitting và các thuật ngữ nền tảng, gắn với ứng dụng ngân hàng NCB.

13 thg 7, 2026 18

Harness — lớp scaffolding quanh model (vòng lặp, tool, context, memory, verify, sub-agent) — mới là thứ quyết định agent chạy được hay chỉ là demo. Bài này mổ xẻ giải phẫu một harness, 7 kỹ năng cốt lõi khi xây agent, single vs multi-agent (kèm số liệu hiệu quả/chi phí), các repo nên dùng, và một quickstart Python dựng-là-chạy cho bối cảnh ngân hàng.

13 thg 7, 2026 15

Hiểu LLM từ gốc: bản chất dự đoán token, ba giai đoạn huấn luyện (pretraining, fine-tuning, RLHF), token, context window và các tham số sinh (temperature, top-p). Nắm hiện tượng hallucination và kỹ thuật prompt engineering (vai trò, few-shot, chain-of-thought, ràng buộc đầu ra), kèm ví dụ gọi API model Claude mới nhất với adaptive thinking.

13 thg 7, 2026 14

Vì sao dữ liệu quyết định chất lượng mô hình hơn cả thuật toán. Bài này đi qua toàn bộ pipeline chuẩn bị dữ liệu: phân loại dữ liệu, làm sạch (thiếu/ngoại lai/trùng lặp), mã hoá hạng mục, scaling, feature engineering, giảm chiều, và cách phòng data leakage — soi qua bài toán chấm điểm tín dụng.

13 thg 7, 2026 14

Cảm nhận của bạn

Bình luận

Bạn cần để viết bình luận.

Chưa có bình luận. Hãy là người đầu tiên chia sẻ!