Chuyển đến nội dung chính

Những lỗi kỹ thuật khi xây RAG

RAG có thể cho kết quả kém dù vector database, embedding model và LLM đều hoạt động đúng. Bài viết phân tích những lỗi kỹ thuật khó phát hiện nhất trong pipeline RAG, từ mất thông tin khi chunking đến retrieval nhiễu, context sai và evaluation đánh lừa, kèm các case study để xác định lỗi nằm ở đâu.

Cảnh báo lỗi kỹ thuật trong hệ thống kiến trúc RAG
Nhận diện và khắc phục các lỗi kỹ thuật trong kiến trúc Retrieval-Augmented Generation (RAG)

Một hệ thống Retrieval-Augmented Generation (RAG) có thể chạy ổn về mặt phần mềm nhưng vẫn trả lời sai một cách rất thuyết phục. Nguyên nhân thường không nằm ở một model duy nhất mà xuất hiện tại ranh giới giữa ingestion, chunking, retrieval, reranking, context construction và generation.

Điều nguy hiểm là nhiều lỗi RAG không tạo exception hay log đỏ. Pipeline vẫn trả về document, LLM vẫn sinh câu trả lời hợp ngữ pháp, latency vẫn bình thường. Vì vậy, kỹ sư cần chẩn đoán RAG như một hệ thống nhiều tầng thay vì nhìn output cuối rồi kết luận rằng “LLM hallucinate”.

Lỗi đầu tiên: dữ liệu đúng nhưng bị phá hỏng trước khi retrieval

Nhiều đội bắt đầu debug từ vector database trong khi lỗi đã xảy ra từ ingestion. Parser có thể làm mất heading, tách sai bảng, bỏ metadata, nối hai cột PDF thành một câu hoặc cắt mất quan hệ giữa tiêu đề và đoạn văn. Khi dữ liệu đầu vào đã mất cấu trúc, embedding model không thể khôi phục thông tin chưa từng được lưu.

Một ví dụ phổ biến là tài liệu chính sách có cấu trúc:

Section: Enterprise Plan

Data retention: 90 days

Section: Standard Plan
Data retention: 30 days

Nếu chunking chỉ giữ câu “Data retention: 90 days” mà bỏ heading, chunk đó mất điều kiện Enterprise Plan. Khi người dùng hỏi thời gian lưu dữ liệu của Standard Plan, retriever vẫn có thể lấy nhầm chunk 90 ngày vì hai đoạn rất giống nhau về ngữ nghĩa.

Đây không phải lỗi embedding. Đó là lỗi semantic boundary: ranh giới chunk không giữ đủ ngữ cảnh để một đoạn đứng độc lập vẫn có nghĩa.

Một sai lầm khác là chọn chunk size như một hằng số mang tính kinh nghiệm, chẳng hạn cứ 500 token thì cắt. Con số này có thể phù hợp với prose nhưng không phù hợp với API reference, bảng giá, hợp đồng hoặc tài liệu có cấu trúc phân cấp.

Chunk quá nhỏ làm mất quan hệ giữa các câu. Chunk quá lớn lại chứa nhiều chủ đề, khiến embedding trở thành một biểu diễn trung bình của nhiều ý khác nhau. Khi đó query có thể chỉ khớp với một phần nhỏ nhưng vẫn phải cạnh tranh với toàn bộ nội dung của chunk.

Case study: chatbot nội bộ trả sai chính sách nghỉ phép

Giả sử handbook có hai mục “Full-time Employees” và “Contractors”. Cả hai đều chứa câu “Annual leave is subject to manager approval”, nhưng số ngày nghỉ khác nhau. Parser loại heading và chunk từng paragraph riêng lẻ.

Query “Contractor được nghỉ phép bao nhiêu ngày?” retrieval được một chunk nói về full-time vì nội dung hai đoạn gần giống nhau. Reranker cũng không sửa được vì chunk không còn metadata để phân biệt loại nhân sự.

Cách chẩn đoán đúng: lấy chính document đã được index ra xem, không chỉ xem document gốc. Nếu người đọc không xác định được chunk đang nói về đối tượng nào thì retriever cũng không có đủ tín hiệu để làm việc đó.

Cách sửa: prepend heading vào chunk, lưu metadata như employee_type, policy_section và source_version, sau đó áp dụng metadata filtering khi query có điều kiện rõ ràng.

Retrieval trả về kết quả “có vẻ liên quan” nhưng không trả lời được câu hỏi

Đây là lỗi khó nhận ra nhất khi đánh giá bằng mắt. Một document có thể nói đúng chủ đề nhưng không chứa answer-bearing evidence, tức bằng chứng trực tiếp cần để trả lời câu hỏi.

Ví dụ query “Làm thế nào reset API key?” và document retrieved nói “API key dùng để xác thực request”. Đây là semantic match tốt về chủ đề API key nhưng không trả lời thao tác reset.

Dense retrieval đặc biệt dễ gặp trường hợp này vì embedding tối ưu similarity ngữ nghĩa, không đảm bảo quan hệ “document này chứa câu trả lời”. Lexical search cũng có vấn đề ngược lại: nó có thể ưu tiên document chứa nhiều keyword nhưng sai intent.

Vì vậy, đánh giá retrieval chỉ bằng cosine similarity hoặc xem top-1 “có liên quan không” là chưa đủ. Ít nhất cần phân biệt:

  • Topical relevance: document có cùng chủ đề.
  • Answer relevance: document thực sự chứa thông tin cần để trả lời.
  • Coverage: tập retrieved documents có đủ mọi phần của câu hỏi.

Một query multi-hop có thể cần hai document khác nhau. Top-1 chính xác vẫn chưa đủ nếu câu trả lời cuối cần kết hợp nhiều bằng chứng.

Case study: semantic search bỏ sót mã lỗi chính xác

Một hệ thống hỗ trợ kỹ thuật dùng dense retrieval cho tài liệu troubleshooting. Người dùng hỏi: “Lỗi E042 khi đồng bộ dữ liệu là gì?”. Vector search trả về các đoạn mô tả lỗi đồng bộ nói chung, trong khi document chứa chính xác chuỗi “E042” nằm ở vị trí thấp.

Lý do là mã lỗi gần như không mang ý nghĩa ngữ nghĩa đối với embedding model. Với identifier, version, tên hàm, SKU hoặc error code, exact lexical overlap thường quan trọng hơn semantic similarity.

Nếu chuyển hoàn toàn sang BM25, hệ thống lại có thể yếu với query diễn đạt tự nhiên. Cách phù hợp hơn là hybrid retrieval: kết hợp lexical và dense search rồi rerank trên tập ứng viên hợp nhất.

Bài học ở đây không phải hybrid luôn tốt hơn dense. Điều quan trọng là xác định loại tín hiệu chứa thông tin: khái niệm ngữ nghĩa, từ khóa chính xác, metadata hay quan hệ cấu trúc.

Top-k lớn không chữa được retrieval kém

Một phản ứng thường gặp khi recall thấp là tăng top_k từ 5 lên 20 hoặc 50. Điều này đôi khi giúp tìm được document bị bỏ sót, nhưng đồng thời đưa nhiều nhiễu hơn vào context.

RAG không chỉ cần retrieval recall cao mà còn cần context precision: phần lớn token gửi cho generator phải hữu ích. Nếu relevant document đứng thứ 18 và 17 document trước đều nhiễu, retrieval thực tế vẫn có vấn đề.

Có thể hình dung hai pipeline:

Pipeline Retrieved Context cuối
A Top-5, 4 chunk liên quan Ngắn, tập trung
B Top-30, 5 chunk liên quan 25 chunk nhiễu cạnh tranh attention

Pipeline B có retrieval recall cao hơn nhưng chưa chắc tạo câu trả lời tốt hơn. Generator phải phân biệt bằng chứng với nội dung gần chủ đề nhưng không phù hợp.

Reranker tồn tại chính để giải quyết một phần vấn đề này. Retriever đầu tiên tối ưu recall trên tập lớn, sau đó reranker đánh giá cặp query-document kỹ hơn để chọn tập nhỏ hơn.

Tuy nhiên, reranking cũng có giới hạn. Nếu relevant document không lọt vào candidate set ban đầu, reranker không thể “cứu” nó. Ngược lại, nếu candidate set quá lớn, latency của reranking tăng đáng kể.

Case study: tăng top-k làm chatbot chính xác kém hơn

Một chatbot sản phẩm thường bỏ sót câu trả lời nên đội kỹ thuật tăng top-k từ 8 lên 40. Recall offline tăng vì relevant chunk xuất hiện thường xuyên hơn trong tập retrieved. Nhưng user-facing answer lại có thêm nhiều trường hợp trộn thông tin giữa các phiên bản sản phẩm.

Phân tích context cho thấy top-40 chứa tài liệu của nhiều version. LLM thấy cùng một cấu hình với ba giá trị khác nhau và chọn một giá trị không thuộc phiên bản mà người dùng hỏi.

Lỗi thực sự không phải top-k quá nhỏ mà là không áp dụng version filtering trước retrieval. Sau khi lọc metadata theo phiên bản và rerank tập ứng viên nhỏ hơn, việc tăng top-k không còn cần thiết.

Context đúng tài liệu nhưng sai cách đóng gói

Ngay cả khi retrieval đã đúng, bước xây context vẫn có thể làm hỏng bằng chứng. Một lỗi phổ biến là concatenate chunk theo score rồi gửi nguyên văn vào prompt mà không kiểm tra trùng lặp, thứ tự, nguồn hoặc xung đột.

Nếu chunk overlap lớn, ba kết quả đầu có thể thực chất là cùng một đoạn văn với vùng giao nhau. Khi đó context 3.000 token có vẻ chứa ba nguồn nhưng thực tế chỉ có một thông tin bị lặp ba lần.

Duplication không chỉ lãng phí token. Nó còn làm một bằng chứng có vẻ “mạnh” hơn vì xuất hiện nhiều lần, dù thực chất đến từ cùng document.

Một vấn đề khác là mất metadata khi xây prompt. Nếu context chỉ chứa text mà không có source, timestamp hoặc version, model không có cơ sở để ưu tiên tài liệu mới hơn khi hai nguồn mâu thuẫn.

Context nên được coi là một cấu trúc dữ liệu, không phải một chuỗi văn bản lớn. Ví dụ:

context = [
    {
        "text": "The API timeout is 30 seconds.",
        "source": "api-guide-v3",
        "version": "3.2",
        "score": 0.92
    }
]

Metadata này có thể được dùng để deduplicate, sort, group theo nguồn hoặc tạo citation. Nếu bỏ metadata quá sớm, nhiều bước xử lý sau đó trở nên khó hoặc không thể thực hiện.

Case study: hai tài liệu cùng đúng nhưng khác thời điểm

Kho dữ liệu chứa tài liệu năm trước ghi “maximum upload size: 50 MB” và tài liệu mới ghi “maximum upload size: 100 MB”. Cả hai đều được retrieval vì query rất rõ.

Nếu prompt không chứa timestamp hoặc version, LLM chỉ thấy hai phát biểu mâu thuẫn. Nó có thể chọn 50 MB, chọn 100 MB hoặc trả lời mơ hồ.

Giải pháp không phải prompt “hãy trả lời chính xác hơn”, mà là xử lý freshness tại retrieval hoặc context layer. Tùy domain, hệ thống có thể lọc document hết hiệu lực, ưu tiên version mới nhất hoặc truyền effective date vào prompt để model có tiêu chí giải quyết xung đột.

Grounding thất bại vì generator được phép suy diễn quá xa bằng chứng

RAG không tự động biến LLM thành một hệ thống grounded. Retrieval chỉ cung cấp dữ liệu; generator vẫn có thể bổ sung kiến thức từ pretraining, suy luận quá mức hoặc lấp khoảng trống bằng một chi tiết nghe hợp lý.

Ví dụ context nói:

“The service supports SSO for enterprise accounts.”

Nếu người dùng hỏi “SSO dùng SAML hay OIDC?”, câu trả lời đúng theo bằng chứng là không đủ thông tin. Một LLM có thể đoán SAML vì đây là lựa chọn phổ biến trong enterprise software. Câu trả lời nghe hợp lý nhưng không grounded.

Để giảm lỗi này, prompt cần phân biệt rõ ba trạng thái:

  • Bằng chứng trực tiếp hỗ trợ câu trả lời.
  • Bằng chứng chỉ hỗ trợ một phần.
  • Không có đủ bằng chứng.

Nhưng instruction chỉ là một lớp bảo vệ. Với hệ thống quan trọng, nên kiểm tra câu trả lời sau generation bằng citation verification hoặc entailment-style checking: mỗi claim quan trọng phải ánh xạ được về một đoạn nguồn hỗ trợ nó.

Một lỗi kiến trúc thường gặp là yêu cầu model tạo citation sau khi đã viết xong câu trả lời nhưng không giữ mapping giữa chunk và source. Lúc này model có thể gán citation “có vẻ đúng” thay vì citation thực sự hỗ trợ claim.

Thiết kế tốt hơn là gán ID cho từng context item trước generation:

[D1] API timeout is 30 seconds.
[D2] Retry is enabled for HTTP 503 responses.

Sau đó yêu cầu mỗi claim có thể kiểm chứng phải tham chiếu ID tương ứng. Citation lúc này là một phần của generation protocol thay vì lớp trang trí thêm ở cuối.

Evaluation sai khiến đội ngũ tối ưu nhầm tầng

Một trong những lỗi tốn kém nhất là chỉ đo chất lượng câu trả lời cuối. Nếu accuracy giảm, bạn biết hệ thống có vấn đề nhưng không biết vấn đề ở retrieval hay generation.

RAG nên được đánh giá theo tầng. Ở retrieval layer, cần biết relevant evidence có được lấy ra không và đứng ở đâu. Ở context layer, cần kiểm tra lượng nhiễu, duplication và coverage. Ở generation layer, cần đo answer correctness và mức độ claim được hỗ trợ bởi context.

Một failure matrix đơn giản có thể giúp chẩn đoán:

Retrieval Answer Khả năng lỗi
Sai Sai Ingestion, query, retrieval hoặc filtering
Đúng Sai Context construction hoặc generation
Sai Đúng Model trả lời từ parametric knowledge; grounding có vấn đề
Đúng Đúng Case thành công, nhưng vẫn cần kiểm tra citation

Trường hợp thứ ba đặc biệt nguy hiểm. Nếu retrieval sai nhưng model vẫn trả lời đúng nhờ kiến thức đã học, metric answer accuracy vẫn đẹp. Nhưng khi dữ liệu nội bộ thay đổi hoặc câu hỏi nằm ngoài kiến thức pretraining, hệ thống sẽ thất bại.

Case study: benchmark tốt nhưng production thất bại

Một đội xây bộ test từ 100 câu hỏi phổ biến và đạt kết quả tốt. Tuy nhiên, phần lớn câu hỏi là kiến thức chung mà LLM có thể tự trả lời. Retrieval thực tế đóng góp rất ít.

Khi đưa vào production với tài liệu nội bộ, câu trả lời giảm chất lượng mạnh. Benchmark trước đó đã đo năng lực của LLM nhiều hơn năng lực của RAG.

Một evaluation set tốt nên chứa câu hỏi mà câu trả lời phụ thuộc vào corpus, bao gồm phiên bản, chính sách nội bộ, identifier, trường hợp multi-hop và câu hỏi không có câu trả lời. Nhóm cuối rất quan trọng vì một RAG production phải biết khi nào nên từ chối suy đoán.

Cách debug RAG theo thứ tự thay vì thử model ngẫu nhiên

Khi RAG trả lời sai, thay embedding model hoặc LLM ngay thường là cách debug kém hiệu quả. Một quy trình tốt hơn là lần theo đường đi của một query cụ thể.

  1. Kiểm tra source: corpus có thực sự chứa câu trả lời không?
  2. Kiểm tra indexed chunk: sau parsing và chunking, bằng chứng còn nguyên nghĩa không?
  3. Kiểm tra candidate retrieval: relevant chunk có xuất hiện trong top-k không?
  4. Kiểm tra reranking: nếu có, relevant chunk có bị đẩy xuống sai không?
  5. Kiểm tra context cuối: generator thực sự nhìn thấy những chunk nào?
  6. Kiểm tra answer-to-source: từng claim trong câu trả lời được hỗ trợ bởi đoạn nào?

Quy trình này giúp phân biệt một lỗi retrieval với một lỗi generation. Nếu bằng chứng chưa bao giờ vào context, thay prompt generation gần như vô nghĩa. Nếu bằng chứng đã ở vị trí rõ ràng nhưng LLM vẫn trả lời sai, lúc đó mới nên tập trung vào prompt, model hoặc structured generation.

Trong production, nên log tối thiểu query gốc, query sau transformation, document ID được retrieval, score, thứ tự sau reranking, context thực tế gửi cho model và citation của output. Không có trace này, việc debug thường biến thành đoán.

Nguyên tắc quan trọng: đừng tối ưu RAG dựa trên output cuối trước khi biết lỗi nằm ở tầng nào. Một câu trả lời sai có thể bắt nguồn từ parser, chunk boundary, metadata, retrieval, reranking, context packing hoặc generator; mỗi nguyên nhân cần một cách sửa khác nhau.

RAG đáng tin cậy không được tạo ra bằng cách ghép vector database với LLM rồi tăng top-k cho đến khi kết quả có vẻ ổn. Nó cần một pipeline mà mỗi tầng đều quan sát được, đánh giá được và có tiêu chí lỗi rõ ràng.

Khi xây RAG, câu hỏi quan trọng nhất không phải “model nào mạnh nhất?” mà là bằng chứng đã bị mất, biến dạng hay nhiễu ở bước nào?. Trả lời được câu hỏi đó giúp kỹ sư sửa đúng tầng, giảm chi phí thử nghiệm và xây hệ thống retrieval có khả năng kiểm chứng thay vì chỉ tạo ra câu trả lời nghe hợp lý.

© The CS Note · THE CS NOTE

Nội dung gốc thuộc tác giả. Vui lòng không đăng lại toàn văn khi chưa được phép, trừ trường hợp pháp luật hoặc giấy phép áp dụng cho phép. Nội dung của bên thứ ba tuân theo quyền và giấy phép tương ứng.

Nguồn gốc: Những lỗi kỹ thuật khi xây RAG

Về trang chủ Về đầu bài

Bài Đăng Phổ Biến

Bài toán tháp Hà nội

Trải nghiệm Tháp Hà Nội Kéo thả đĩa hoặc chạm vào các nút bên dưới để di chuyển. Bạn phải chuyển toàn bộ đĩa sang cột ngoài cùng bên phải (Cột 3) mà không đặt đĩa to lên đĩa nhỏ. Cột 1 Cột 2 Cột 3 Điều khiển & Chế độ Số lượng đĩa 4 Tốc độ máy giải ↪ Undo ↻ Chơi lại 🤖 Máy tự giải Thống kê ván chơi Nước đã đi 0 Thời gian 00:00 Tối thiểu cần 15 Kỷ lục của bạn - Lịch sử và Nguồn gốc Truyền thuyết Bài toán Tháp Hà Nội (hay Tháp Brahma) là một trò chơi xếp hình toán học kinh điển được giới thiệu lần đầu vào năm 1883 bởi nhà toán học người Pháp Édouard L...

Bài toán phân tích cảm xúc trong văn bản

Bài toán phân tích cảm xúc (sentiment analysis) là một bài toán NLP nhằm xác định thái độ hoặc cảm xúc được thể hiện trong văn bản. Ví dụ, từ một đánh giá như “Điện thoại đẹp, chạy nhanh nhưng pin hơi yếu”, hệ thống có thể nhận biết rằng người dùng có cả nhận xét tích cực và tiêu cực. Điểm thú vị của bài toán nằm ở khoảng cách giữa cách con người hiểu ngôn ngữ và cách máy tính xử lý dữ liệu. Một hệ thống phân tích cảm xúc cần biến văn bản tự nhiên thành dữ liệu có cấu trúc, học được các mẫu ngôn ngữ từ dữ liệu huấn luyện và đưa ra dự đoán hợp lý trên những câu chưa từng gặp. 1. Bài toán phân tích cảm xúc bắt đầu từ đâu? Hãy tưởng tượng một cửa hàng trực tuyến có hàng nghìn đánh giá mỗi ngày. Con người có thể đọc từng đánh giá để biết khách hàng hài lòng hay không, nhưng việc này nhanh chóng trở nên tốn thời gian khi dữ liệu tăng lên. NLP có thể biến bài toán đó thành một bài toán phân loại. Với mỗi văn bản, hệ thống nhận vào một chuỗi ký...

KAN cho phân đoạn khối u não với bộ BraTS 2020

Kolmogorov-Arnold Network (KAN) mở ra một hướng khác với MLP truyền thống: thay vì chỉ học các trọng số vô hướng trên mỗi kết nối, KAN có thể học những hàm phi tuyến một biến trên các cạnh . Khi đưa ý tưởng này vào kiến trúc encoder-decoder như U-Net, ta có thể sử dụng convolution để giữ cấu trúc không gian của ảnh MRI và dùng KAN để thực hiện các phép biến đổi phi tuyến mạnh hơn trên representation trung gian. Một bài toán phù hợp để nghiên cứu hướng này là phân đoạn u thần kinh đệm trên BraTS 2020 . Dataset cung cấp MRI đa mô thức và yêu cầu xác định các vùng Whole Tumor (WT), Tumor Core (TC) và Enhancing Tumor (ET). Đây là bài toán 3D có sự mất cân bằng voxel lớn, hình dạng khối u rất đa dạng và ranh giới giữa các mô bệnh lý không đơn giản. Lưu ý học thuật quan trọng: U-KAN gốc được công bố cho nhiều benchmark phân đoạn ảnh y tế nhưng không báo cáo kết quả BraTS 2020. Một công trình sau đó đã mở rộng U-KAN sang 3D MRI brain tumor segmentation , nhưng đánh giá trên BraTS 2...

Tách từ trong tiếng Việt Word Segmentation

Tách từ tiếng Việt là bài toán xác định ranh giới giữa các từ trong một chuỗi văn bản. Khó khăn nằm ở chỗ khoảng trắng trong tiếng Việt thường phân cách các âm tiết , nhưng một từ hoàn chỉnh có thể gồm nhiều âm tiết như “sinh viên” , “đại học” , “công nghệ” hay “tự nhiên” . Tách từ đúng giúp các hệ thống NLP dựa trên từ biểu diễn văn bản hợp lý hơn, đặc biệt trong tìm kiếm, TF-IDF, phân loại văn bản, gán nhãn từ loại và một số mô hình ngôn ngữ tiếng Việt. Tuy nhiên, với các Transformer sử dụng tokenizer dưới mức từ như subword hoặc SentencePiece, tách từ thủ công không phải lúc nào cũng là bước bắt buộc . Việc có cần tách từ trước hay không phụ thuộc vào mô hình và pipeline cụ thể. Tóm tắt nội dung Khoảng trắng trong tiếng Việt không phải lúc nào cũng là ranh giới từ ; nhiều từ gồm hai hoặc nhiều âm tiết. Word segmentation và tokenization có liên quan nhưng không hoàn toàn đồng nghĩa. Ba hướng chính gồm dựa trên từ điển, mô hình thống kê và mô hình học sâu . Tron...

KAN là gì? Mạng Kolmogorov-Arnold khác MLP thế nào?

Kolmogorov-Arnold Network (KAN) là một kiến trúc mạng nơ-ron trong đó mỗi cạnh không chỉ chứa một trọng số vô hướng mà mang một hàm một biến có thể học được . Đây là khác biệt cốt lõi so với Multi-Layer Perceptron (MLP), nơi các cạnh chủ yếu thực hiện phép nhân với trọng số còn hàm kích hoạt thường được áp dụng tại các node. KAN được lấy cảm hứng từ định lý biểu diễn Kolmogorov-Arnold và đặc biệt đáng chú ý trong các bài toán xấp xỉ hàm, mô hình hóa khoa học và symbolic regression. Tuy nhiên, KAN không nên được hiểu là kiến trúc đã thay thế MLP trong mọi bài toán Deep Learning; khả năng biểu diễn, chi phí tính toán và mức độ phù hợp của hai kiến trúc khác nhau theo từng nhiệm vụ. Tóm tắt nội dung MLP học chủ yếu trọng số trên các cạnh , còn KAN đặt hàm một biến học được trên từng cạnh . Một KAN layer cộng kết quả của nhiều hàm cạnh để tạo activation của node tiếp theo. KAN gốc sử dụng B-spline để tham số hóa các hàm phi tuyến trên cạnh. KAN có lợi thế đáng chú ý về trực...