Sự chuyển dịch từ RAG sang Native Long Context
Năm ngoái, đội ngũ của tôi đã gặp phải một bài toán khó. Chúng tôi đang xây dựng một hệ thống kiểm định tự động cho các tài liệu tuân thủ dài 500 trang—tương đương khoảng 350.000 token chứa đầy thuật ngữ pháp lý dày đặc. Vào thời điểm đó, chúng tôi sử dụng Retrieval-Augmented Generation (RAG) tiêu chuẩn. Chúng tôi chia nhỏ văn bản (chunking), tạo embedding và lấy ra các đoạn snippet top-k. Cách này hiệu quả với các sự kiện cơ bản, nhưng thất bại ngay khi LLM cần kết nối một điều khoản trách nhiệm ở trang 12 với một văn bản miễn trừ bồi thường ở trang 480.
Cuộc chơi đã thay đổi với sự xuất hiện của Gemini 1.5 Pro (ngữ cảnh 2 triệu token) và Claude 3.5 Sonnet (200.000 token). Chúng tôi ngừng việc săn tìm các đoạn nhỏ phù hợp và bắt đầu đưa toàn bộ tài liệu vào mô hình. Tuy nhiên, cửa sổ ngữ cảnh lớn hơn cũng mang lại những vấn đề lớn hơn. Việc chỉ đơn giản đổ một triệu token vào prompt không đảm bảo sẽ có câu trả lời đúng. Dưới đây là cách tôi quản lý các ngữ cảnh khổng lồ này mà không làm tăng chi phí quá mức hay giảm độ chính xác.
Các mô hình kiến trúc cho tài liệu khổng lồ
Khi dữ liệu của bạn vượt quá 100.000 token, bạn thường có ba hướng đi. Chọn sai hướng thường dẫn đến hóa đơn thanh toán khổng lồ hoặc mô hình gặp hiện tượng ảo giác (hallucination).
1. RAG truyền thống (Lựa chọn tiết kiệm)
Phương pháp này dựa vào cơ sở dữ liệu vector để truy xuất các đoạn văn bản. Nó cực kỳ rẻ, thường tốn ít hơn 0,01 USD cho mỗi truy vấn. Tuy nhiên, LLM chỉ nhìn thấy một phần rất nhỏ của tài liệu. Nó thiếu ‘khả năng nhận thức tổng thể’ (global awareness), nghĩa là nó không thể tóm tắt toàn bộ một cuốn sách hoặc tìm ra những điểm mâu thuẫn giữa các chương.
2. Native Long Context (Tiêu chuẩn vàng)
Bạn đưa mọi từ ngữ vào prompt. LLM sẽ nhìn thấy bức tranh toàn cảnh. Điều này hoàn hảo cho các suy luận phức tạp, nhưng nó chậm. Xử lý một tài liệu 200.000 token trên GPT-4o có thể tốn hơn 1,00 USD cho mỗi tin nhắn và mất 30 giây để phản hồi.
3. Context Caching (Giải pháp lai tối ưu)
Các nhà cung cấp như Anthropic và Google hiện cho phép bạn ‘đóng băng’ một tài liệu trên máy chủ của họ. Bạn trả phí một lần để xử lý văn bản. Các câu hỏi tiếp theo sẽ rẻ hơn khoảng 90% và nhanh hơn 80%. Trong các thử nghiệm thực tế của tôi, điều này đã biến thời gian chờ 20 giây thành phản hồi 4 giây cho các cuộc hội thoại nhiều lượt.
Các sự đánh đổi: Chi phí và Hiệu suất
Đừng rơi vào cái bẫy suy nghĩ rằng nhiều token hơn luôn mang lại kết quả tốt hơn. Kinh nghiệm của tôi cho thấy hiệu suất của LLM thường đạt đến ngưỡng bão hòa từ lâu trước khi cửa sổ ngữ cảnh đầy.
- RAG truyền thống: Tốc độ cao và chi phí thấp, nhưng nó giống như nhìn một bức tranh tường qua một ống hút. Bạn sẽ bỏ lỡ ngữ cảnh.
- Native Long Context: Khả năng suy luận đáng kinh ngạc, nhưng bạn phải đối mặt với hiện tượng ‘Lost in the Middle’ (Mất thông tin ở giữa). Các mô hình thường quên các sự kiện nằm sâu ở giữa một prompt dài.
- Context Caching: Tốt nhất cho người dùng lặp lại. Nó cắt giảm độ trễ, mặc dù bạn bị ràng buộc vào API của một nhà cung cấp cụ thể.
Chiến lược sẵn sàng cho môi trường Production
Đối với các ứng dụng doanh nghiệp, tôi sử dụng Chiến lược ngữ cảnh hai tầng. Tôi kết hợp một mô hình hơn 100.000 token với Context Caching. Thay vì yêu cầu mô hình tìm một “cây kim” ngay lập tức, tôi yêu cầu nó tạo ra một ‘sơ đồ tài liệu’ (document map) trước. Sơ đồ này sẽ dẫn dắt truy vấn cuối cùng đến đúng phần cần tìm.
Nếu bạn đang xử lý hơn 2.000 trang (trên 1 triệu token), hãy sử dụng Long-Context RAG. Thay vì các đoạn snippet 500 token, hãy trích xuất các ‘mega-chunk’ 5.000 token. Điều này giúp mô hình có đủ chi tiết xung quanh để duy trì luồng logic trong khi vẫn giữ chi phí ở mức quản lý được.
Kiểm tra độ chính xác với ‘Needle In A Haystack’ (NIAH)
Làm thế nào để chứng minh mô hình của bạn không tự bịa ra mọi thứ? Hãy sử dụng bài kiểm tra Needle In A Haystack (Kim đáy bể). Bạn giấu một sự thật ngẫu nhiên (cây kim), ví dụ như ‘Màu sắc yêu thích của CEO là màu hoa cà’, vào giữa một báo cáo tài chính 100.000 từ (đống cỏ khô). Sau đó, bạn yêu cầu mô hình tìm nó.
Tôi nhận thấy rằng many mô hình quảng cáo có cửa sổ 128k bắt đầu thất bại khi ‘cây kim’ được đặt ở độ sâu từ 40% đến 70%. Độ chính xác có thể giảm từ 99% ở đầu tài liệu xuống chỉ còn 65% ở giữa.
Code: Chạy thử nghiệm NIAH của riêng bạn
Bạn có thể tự động hóa việc này bằng Python và tiktoken. Script này đặt một sự thật vào một độ sâu cụ thể để xem mô hình có còn ‘nhìn thấy’ nó hay không.
import tiktoken
def create_haystack(base_text, needle, depth_percent, model_name="gpt-4o"):
encoder = tiktoken.encoding_for_model(model_name)
tokens = encoder.encode(base_text)
# Tính toán điểm chèn
insert_at = int(len(tokens) * (depth_percent / 100))
# Chèn "cây kim"
full_context = tokens[:insert_at] + encoder.encode(f"\n{needle}\n") + tokens[insert_at:]
return encoder.decode(full_context)
# Kiểm tra nhanh: Đặt bí mật ở độ sâu 60%
secret = "Mật khẩu máy chủ là 'Blue-Monkey-99'."
big_doc = "Văn bản mẫu của doanh nghiệp... " * 2000
prompt = create_haystack(big_doc, secret, 60)
# Đếm số lượng token để kiểm tra kích thước
print(f"Kích thước ngữ cảnh: {len(encoder.encode(prompt))} token")
Các mẹo tối ưu hóa xương máu
- Sử dụng Tokenizer chính xác: Đừng bao giờ đoán số lượng token của bạn. OpenAI và Anthropic sử dụng logic khác nhau. Đếm sai chỉ 5% cũng có thể khiến API cắt mất phần cuối tài liệu của bạn.
- Zero Temperature: Thiết lập
temperature=0cho các tác vụ truy xuất. Bạn muốn mô hình đóng vai một thủ thư chuẩn xác, chứ không phải một nhà văn sáng tạo. - Prompt Engineering: Chỉ dẫn mô hình chính xác nơi cần tìm. Thêm câu lệnh ‘Hãy quét toàn bộ văn bản thật kỹ trước khi trả lời’ có thể tăng tỷ lệ truy xuất thêm 15% trong các bài benchmark của tôi.
Tăng tốc phản hồi
Việc chờ đợi 30 giây để LLM đọc một tài liệu sẽ giết chết trải nghiệm người dùng. Streaming là yếu tố bắt buộc. Nó cho phép người dùng nhìn thấy những từ đầu tiên của câu trả lời trong khi mô hình vẫn đang xử lý phần dữ liệu còn lại. Nếu bạn dùng Google Gemini, Context Caching API của họ là công cụ tốt nhất để giảm Thời gian phản hồi token đầu tiên (TTFT) cho các truy vấn lặp lại.
# Ví dụ về Caching trên Google Gemini
from google.generativeai import caching
import datetime
# Lưu tài liệu vào cache trong 1 giờ để tiết kiệm 90% chi phí truy vấn
file_cache = caching.CachedContent.create(
model='models/gemini-1.5-pro-001',
contents=[large_document_string],
ttl=datetime.timedelta(hours=1),
)
Quản lý ngữ cảnh dài không chỉ là việc có một chiếc xô lớn hơn. Đó là việc biết cách đổ đầy nó. Bằng cách sử dụng kiểm tra NIAH để tìm ra điểm giới hạn của mô hình và triển khai caching để tiết kiệm chi phí, bạn có thể xây dựng các công cụ AI xử lý các tập dữ liệu khổng lồ với độ chính xác cực cao.

