AI, LLMs, N8N, RAG

Vượt Ngoài RAG Tiêu Chuẩn: Khắc phục Vấn đề 'Mất Ngữ cảnh' bằng Kỹ thuật Truy xuất Nâng cao

Khám phá Late Chunking và Contextual Retrieval để nâng cao độ chính xác và giảm ảo giác cho hệ thống RAG của bạn.

Agent RAG của bạn đang gặp khó khăn về độ chính xác hay tự bịa đặt thông tin? Thủ phạm có thể là 'vấn đề mất ngữ cảnh', nơi việc chunking (chia nhỏ văn bản) tách rời thông tin quan trọng khỏi ý nghĩa ban đầu của nó. Bài viết này đi sâu vào lý do tại sao RAG tiêu chuẩn không hiệu quả và giới thiệu ha...…
Vượt Ngoài RAG Tiêu Chuẩn: Khắc phục Vấn đề 'Mất Ngữ cảnh' bằng Kỹ thuật Truy xuất Nâng cao
<a href="http://www.youtube.com/@TheAIAutomators">The AI Automators</a> The AI Automators Follow

Agent RAG của bạn đang gặp khó khăn về độ chính xác hay tự bịa đặt thông tin? Thủ phạm có thể là 'vấn đề mất ngữ cảnh', nơi việc chunking (chia nhỏ văn bản) tách rời thông tin quan trọng khỏi ý nghĩa ban đầu của nó. Bài viết này đi sâu vào lý do tại sao RAG tiêu chuẩn không hiệu quả và giới thiệu hai kỹ thuật mạnh mẽ—Late Chunking và Contextual Retrieval—để vượt qua thách thức này. Nếu bạn đang xây dựng hoặc tinh chỉnh các hệ thống RAG và muốn có các phản hồi AI đáng tin cậy, nhận biết ngữ cảnh tốt hơn, hãy đọc tiếp để tìm hiểu cách các phương pháp này hoạt động và cách triển khai chúng.

Gót chân Achilles của RAG Tiêu chuẩn: Vấn đề Mất Ngữ cảnh

Nếu bạn đã từng xây dựng một agent Retrieval-Augmented Generation (RAG), có lẽ bạn đã phải đối mặt với sự thất vọng về các câu trả lời không chính xác hoặc hiện tượng ảo giác hoàn toàn. Thông thường, đây không phải lỗi của chính Mô hình Ngôn ngữ Lớn (LLM), mà là một vấn đề cơ bản trong cách thông tin được chuẩn bị: vấn đề mất ngữ cảnh.

Chúng ta hãy minh họa bằng một ví dụ đơn giản sử dụng bài viết trên Wikipedia về Berlin:

Hãy tưởng tượng chúng ta chia bài viết thành các câu (chunks):

  1. "Berlin là thủ đô của Đức."
  2. "Dân số của nó là X." (Ám chỉ Berlin)
  3. "Thành phố này là một trong các bang của Đức." (Ám chỉ Berlin)

Trong RAG tiêu chuẩn, mỗi chunk thường được xử lý độc lập. Chúng được chuyển thành các vector embeddings và lưu trữ. Vấn đề là gì? Chỉ có chunk đầu tiên đề cập rõ ràng đến "Berlin." Các chunk thứ hai và thứ ba dựa vào ngữ cảnh của chunk đầu tiên để được hiểu.

Khi được xử lý riêng lẻ, các chunk tiếp theo này mất đi kết nối với "Berlin." Trong quá trình truy xuất, một truy vấn về "Berlin" có thể dễ dàng tìm thấy chunk đầu tiên nhưng bỏ lỡ những chunk khác, vì chúng thiếu từ khóa và embeddings của chúng không phản ánh ngữ cảnh cần thiết.

Điều này dẫn đến:

  • Câu trả lời không đầy đủ: Hệ thống RAG không truy xuất được tất cả thông tin liên quan.
  • Câu trả lời không chính xác / Ảo giác: Các chunk không liên quan có thể đạt điểm cao hơn và được cung cấp cho LLM, dẫn dắt nó đi sai hướng.

Ôn tập nhanh: RAG và Chunking

  • RAG: Nâng cao các phản hồi của LLM bằng cách đầu tiên truy xuất các đoạn thông tin liên quan (chunks) từ một cơ sở tri thức. Điều này cung cấp cho LLM dữ liệu cụ thể, kịp thời.
  • Chunking: Quá trình chia tài liệu thành các phân đoạn có thể quản lý được cho RAG. Các chiến lược khác nhau (câu, đoạn, kích thước cố định, chồng lấp), và lựa chọn tốt nhất phụ thuộc vào dữ liệu.

Kỹ thuật 1: Late Chunking - Embedding Trước với Ngữ cảnh

Được giới thiệu bởi Jina AI vào cuối năm ngoái, Late Chunking đảo ngược quy trình RAG tiêu chuẩn, tận dụng các mô hình embedding ngữ cảnh dài.

  • RAG Tiêu chuẩn: Chia nhỏ tài liệu thành chunks ➔ Embeds các chunks (Ngữ cảnh thường bị mất)
  • Late Chunking: Embeds toàn bộ tài liệu (bảo toàn ngữ cảnh) ➔ Chia nhỏ văn bản tài liệu thành chunks ➔ Liên kết embeddings với các text chunks

Late Chunking Hoạt động Như thế nào

  1. Tải & Embed Tài liệu: Tải toàn bộ tài liệu (hoặc một phần lớn) vào một mô hình embedding ngữ cảnh dài. Mô hình tạo ra embeddings cho tất cả các tokens đồng thời, nắm bắt ngữ cảnh tổng thể.
  2. Chunk Văn bản Tài liệu: Áp dụng chiến lược chunking ưa thích của bạn (ví dụ: câu, đoạn) chỉ cho văn bản.
  3. Liên kết Embeddings: Ánh xạ các token embeddings được tạo ở bước 1 với các text chunks tương ứng từ bước 2.
  4. Gộp Embeddings (Pooling): Kết hợp các token embeddings cho mỗi chunk thành một vector đại diện duy nhất (ví dụ: thông qua lấy trung bình/pooling).
  5. Lưu trữ Embeddings: Lưu trữ các chunk embeddings nhận biết ngữ cảnh này trong cơ sở dữ liệu vector.

Bởi vì các embeddings ban đầu đã nắm bắt được toàn bộ ngữ cảnh, các chunks như "Dân số của nó là X" giữ lại kết nối với "Berlin" trong biểu diễn vector của chúng.

Yêu cầu chính: Các mô hình embedding ngữ cảnh dài là rất cần thiết. Kiểm tra Hugging Face Embedding Leaderboard để biết các tùy chọn như của Mistral và Qwen (lên đến 32k tokens). Ví dụ sử dụng mô hình V3 của Jina AI (~8k tokens).

Ghi chú Triển khai trên N8N

Việc triển khai late chunking trong N8N hiện tại đòi hỏi một số công việc tùy chỉnh, vì các node gốc không hỗ trợ đầy đủ các mô hình hoặc tham số cần thiết (như cờ use_late_chunking của Jina).

Quy trình được mô tả bao gồm:

  • Tìm nạp và trích xuất văn bản (ví dụ: từ PDF).
  • Xử lý Tài liệu Rất Lớn: Nếu tài liệu vượt quá giới hạn ngữ cảnh của mô hình embedding (ví dụ: ~8k tokens của Jina V3), hãy tạo một bản tóm tắt của toàn bộ tài liệu trước. Bản tóm tắt này sau đó được thêm vào đầu các chunk lớn trước khi embedding để giữ lại một phần ngữ cảnh tổng thể.
  • Chunking Lớn (Code Node): Chia tài liệu thành các chunk lớn phù hợp với giới hạn của mô hình embedding (ví dụ: 28.000 ký tự cho Jina V3). Cần có JavaScript tùy chỉnh vì các bộ chia văn bản của N8N được gắn với các node vector store.
  • Lặp & Chunking Chi tiết (Code Node): Bên trong mỗi chunk lớn, áp dụng chunking chi tiết hơn (ví dụ: 1000 ký tự, chồng lấp 200). Một lần nữa, sử dụng JS tùy chỉnh.
  • Tổng hợp & Thêm Tóm tắt: Thu thập các chunk chi tiết từ chunk lớn. Thêm bản tóm tắt tài liệu tổng thể vào đầu nếu đã tạo.
  • Embed qua API (HTTP Request Node): Gửi danh sách các chunk chi tiết cùng nhau đến API embedding của Jina AI, bật use_late_chunking và đặt task_type thành retrieval_passage.
  • Định dạng & Upsert (Code Node, HTTP Request Node): Chuẩn bị dữ liệu (embeddings, văn bản, ID) cho vector store (ví dụ: Quadrant) và upsert qua API của nó.

Thông tin từ Thử nghiệm: Trong các thử nghiệm với quy định F1, late chunking đã cung cấp câu trả lời chính xác và truy xuất thông tin chi tiết hơn so với thiết lập RAG cơ bản, cho thấy sự cải thiện về mức độ liên quan của chunk.

Đánh giá: Các benchmark của Jina AI cho thấy late chunking cải thiện đáng kể khả năng truy xuất, đặc biệt đối với các tài liệu dài hơn nơi nhiều ngữ cảnh có thể bị mất.

Kỹ thuật 2: Contextual Retrieval - Bổ sung Ngữ cảnh do LLM Tạo ra

Được giới thiệu bởi Anthropic, Contextual Retrieval sử dụng sức mạnh của LLM ngữ cảnh dài (không phải mô hình embedding) để bổ sung ngữ cảnh một cách rõ ràng cho mỗi chunk trước khi embedding.

Contextual Retrieval Hoạt động Như thế nào

  1. Tải & Chunk Tài liệu: Chia tài liệu thành các chunk bằng chiến lược ưa thích của bạn.
  2. Tạo Mô tả Ngữ cảnh (LLM): Đối với mỗi chunk:
    • Gửi chunk tài liệu gốc đầy đủ đến một LLM ngữ cảnh dài.
    • Prompt LLM tạo một mô tả ngắn gọn (ví dụ: một câu) giải thích cách chunk này liên quan đến toàn bộ tài liệu.
  3. Kết hợp Văn bản: Thêm mô tả của LLM vào đầu văn bản chunk gốc.
  4. Embed Văn bản Kết hợp: Sử dụng một mô hình embedding tiêu chuẩn để embed chunk đã được tăng cường mô tả này.
  5. Lưu trữ Embedding: Lưu trữ embedding giàu ngữ cảnh kết quả.

Sử dụng ví dụ về Berlin, đối với "Dân số của nó là X," LLM có thể tạo ra: "Chunk này cung cấp dữ liệu dân số cho Berlin." Văn bản được embed sẽ là: "Chunk này cung cấp dữ liệu dân số cho Berlin. Dân số của nó là X."

Sức mạnh của Context Caching

Việc gọi LLM cho mỗi chunk, có khả năng gửi một tài liệu lớn mỗi lần, nghe có vẻ chậm và tốn kém. Context Caching (hoặc prompt caching), được cung cấp bởi các mô hình như Gemini của Google và Claude của Anthropic, làm cho điều này khả thi.

Cách Caching Giúp ích: Tài liệu lớn được gửi và cache một lần. Các lệnh gọi tiếp theo chỉ cần gửi chunk mới và prompt, tham chiếu đến ID tài liệu đã được cache. Điều này giảm đáng kể thời gian xử lý và chi phí.

Ghi chú Triển khai trên N8N

Điều này cũng đòi hỏi thiết lập N8N tùy chỉnh, tận dụng LLM có caching (ví dụ: Gemini 1.5 Flash).

Quy trình bao gồm:

  • Tìm nạp và trích xuất văn bản.
  • Ước tính Tokens & Caching (Code Node, HTTP Request Node): Kiểm tra xem tài liệu có đủ lớn để caching hay không (ví dụ: >32k tokens cho Gemini). Nếu có, gọi API cacheContents của Gemini, lưu trữ ID cache được trả về.
  • Chunking Chi tiết (Code Node): Chia văn bản tài liệu thành các chunk.
  • Lặp & Xử lý theo Lô (Loop Over Items Node): Xử lý các chunk theo lô (ví dụ: 25) với độ trễ (ví dụ: 30 giây) để tránh chạm giới hạn tỷ lệ API của LLM (đặc biệt là tokens-per-minute).
  • Tạo Prompt (Code Node): Xây dựng prompt cho LLM, bao gồm hướng dẫn (prompt đề xuất của Anthropic hoạt động tốt), văn bản chunk và tham chiếu tài liệu đã được cache.
  • Tạo Mô tả (Gemini Node / HTTP Request Node): Gọi LLM (ví dụ: Gemini 1.5 Flash) với prompt.
  • Kết hợp Văn bản (Code Node): Thêm mô tả được tạo vào đầu văn bản chunk.
  • Embed & Upsert (Quadrant Output Node): Sử dụng một mô hình embedding tiêu chuẩn (ví dụ: OpenAI Ada) để embed văn bản kết hợp. Cấu hình bộ chia văn bản của node với kích thước chunk cực lớn để ngăn chặn việc re-chunking. Upsert vào vector store.

Thách thức & Cân nhắc:

  • Rate Limits: Việc chạm đến giới hạn API của LLM (đặc biệt là giới hạn token, thường bao gồm cả các token đã cache) là một trở ngại lớn. Xử lý theo lô, độ trễ và logic thử lại là rất cần thiết.
  • Thời gian Nhập liệu: Phương pháp này chậm hơn nhiều so với RAG tiêu chuẩn hoặc late chunking (ví dụ: 27 phút cho một tệp PDF 180 trang).
  • Chi phí: Mặc dù caching giảm chi phí đáng kể so với không caching, nó vẫn tốn kém hơn các phương pháp chỉ dùng embedding. Ví dụ tài liệu F1 tốn khoảng $1.30 để xử lý với Gemini 1.5 Flash. Điều này có thể không khả thi đối với các bộ dữ liệu khổng lồ nhưng có thể chấp nhận được đối với thông tin có giá trị cao nơi độ chính xác là tối quan trọng.

Thông tin từ Thử nghiệm: Contextual retrieval tạo ra các câu trả lời chi tiết và kỹ lưỡng nhất trong các thử nghiệm F1. Các mô tả do LLM tạo ra đã làm rõ các thuật ngữ kỹ thuật một cách hiệu quả, có khả năng dẫn đến mức độ liên quan truy xuất vượt trội.

Đánh giá: Các benchmark của Anthropic cho thấy contextual retrieval giảm đáng kể các lỗi truy xuất (cải thiện 35%, 67% với một reranker như Cohere).

Kết luận: Lựa chọn Kỹ thuật Phù hợp

Cả Late Chunking và Contextual Retrieval đều cung cấp các giải pháp hấp dẫn cho vấn đề mất ngữ cảnh trong RAG, giúp tăng cường đáng kể độ chính xác truy xuất.

  • Late Chunking:
    • Ưu điểm: Thời gian nhập liệu nhanh hơn, chi phí thấp hơn Contextual Retrieval, tận dụng ngữ cảnh tốt.
    • Nhược điểm: Yêu cầu các mô hình embedding ngữ cảnh dài cụ thể, cần triển khai tùy chỉnh trong các công cụ như N8N hiện tại.
  • Contextual Retrieval:
    • Ưu điểm: Embedding ngữ cảnh tuyệt vời thông qua mô tả của LLM, sử dụng các mô hình embedding tiêu chuẩn.
    • Nhược điểm: Thời gian nhập liệu chậm hơn nhiều, chi phí cao hơn (ngay cả với caching), dễ gặp sự cố rate limiting của LLM, yêu cầu LLM ngữ cảnh dài có caching.

Cách tiếp cận tốt nhất phụ thuộc vào nhu cầu cụ thể của bạn:

  • Cân nhắc Late Chunking nếu bạn có quyền truy cập vào các mô hình embedding phù hợp và ưu tiên tốc độ và chi phí thấp hơn.
  • Cân nhắc Contextual Retrieval cho các bộ dữ liệu nhỏ hơn, có giá trị cao, nơi độ chính xác tối đa biện minh cho thời gian nhập liệu và chi phí cao hơn, miễn là bạn có thể quản lý được rate limits.

Cuối cùng, việc thử nghiệm các kỹ thuật này với dữ liệu và trường hợp sử dụng của riêng bạn là rất quan trọng để xác định con đường tối ưu phía trước.

Tài nguyên Liên quan