RAG: trao dữ liệu của bạn cho mô hình
Kiến thức của LLM đóng băng tại điểm cắt huấn luyện; tài liệu của bạn đổi hằng tuần. Sinh-tăng-cường-truy-xuất (RAG) rã đông nó: lúc truy vấn, lấy các lát liên quan của dữ liệu bạn, dán vào prompt, và để mô hình trả lời từ bằng chứng kèm trích dẫn. Mô hình lo suy luận; chỉ mục lo trí nhớ.
Pipeline, một ví dụ tính sẵn
Lấy một cẩm nang bảo trì 12,000-token và đi nó từ đầu đến cuối:
- Chia đoạn. Tách theo tiêu đề trước (các mục sống nguyên vẹn), rồi tách lại mục nào quá ~400 token, giữ ~60 token chồng lấn (10–15%). Kích thước đoạn hợp lý chạy 200–800 token. Kết quả: chừng 35 đoạn.
- Nhúng. Mỗi đoạn thành một vector — bge-m3 nhả 1,024 số thực mỗi đoạn. Trên CPU việc này tốn vài giây cho cả cẩm nang.
- Lập chỉ mục. Lưu vector + văn bản + metadata (tệp nguồn, đường dẫn tiêu đề) vào một kho vector.
- Truy xuất. Nhúng câu hỏi, lấy top k = 5 đoạn theo độ tương đồng cosin (4–10 là dải tỉnh táo).
- Sinh. Lắp prompt: chỉ dẫn, 5 đoạn với thẻ ID, câu hỏi.
Chia đoạn theo ranh giới ngữ nghĩa thắng cửa sổ cố định. Một bảng tách khỏi hàng tiêu đề, hay một quy trình đánh số cắt ngang ở bước 4, là rác không truy xuất được bất kể embedder giỏi cỡ nào.
Hai thứ thêm tự trả tiền ngay lập tức: lưu đường dẫn tiêu đề (manual › §4 › Bolts) làm metadata để lọc và trích dẫn chính xác, và nhúng câu hỏi đúng nguyên văn người dùng gõ — việc "dọn dẹp" tiền xử lý thường làm truy xuất tệ hơn, không phải tốt hơn.
Embedding: yêu cầu đa ngôn ngữ
Embedder quyết định "tương tự" nghĩa là gì. Cho kho tiếng Hàn và kho lai tiếng-Hàn/tiếng-Anh, lựa chọn hẹp — embedder chỉ-tiếng-Anh thất bại âm thầm trên truy vấn tiếng Hàn, trả về các đoạn trông-đúng-nhưng-sai:
| Mô hình | Chiều | Ghi chú |
|---|---|---|
| bge-m3 | 1024 | đa ngôn ngữ, tiếng Hàn mạnh — mặc định cục bộ an toàn |
| nomic-embed-text-v1.5 | 768 | tiếng Anh chắc, ngữ cảnh dài |
| all-MiniLM-L6-v2 | 384 | nhanh, trọng tiếng Anh, yếu tiếng Hàn |
Mô hình embedding tí hon (0.1–0.6B tham số); một lõi CPU nhai through hàng nghìn đoạn — suy luận CPU. Nhúng kho một lần, nhúng truy vấn lúc hỏi. Giữ embedder đóng băng cho mỗi chỉ mục: đổi mô hình giữa-chừng-chỉ-mục tạo vector từ các không gian khác nhau, và điểm tương đồng thành nhiễu.
Kho vector
| Kho | Khi nào |
|---|---|
| sqlite-vec | một người dùng, tới ~1M vector, không vận hành — nó là một tệp |
| ChromaDB | nguyên mẫu local-first với bộ lọc metadata |
| Qdrant | sản xuất: lọc, tìm kiếm lai, quy mô |
Cả ba chạy cục bộ. Bắt đầu với sqlite-vec; dời khi bạn thực sự đụng tường nó, không trước.
Lắp ráp prompt
Answer only from the excerpts below. Cite every claim as [n].
If the excerpts do not contain the answer, reply "not in the docs".
[1] (manual §4.2) Torque the M8 bolt to 12 Nm after lubrication...
[2] (manual §7.1) Do not re-use stretch bolts...
Question: what torque spec applies to the M8 bolt?
Trích dẫn cho người dùng kiểm chứng thay vì tin tưởng. Lối thoát "not in the docs" quan trọng: thiếu nó, mô hình bịa một câu trả lời thay vì thất bại khuôn dạng.
Tìm kiếm lai và xếp lại hạng
Tìm kiếm thuần vector lạc các chuỗi chính xác — mã lỗi, tên hàm, số hiệu linh kiện — mà tìm từ khóa đóng đinh. Lai = BM25 + vector, trộn bằng hợp nhất hạng nghịch đảo; nó gần như miễn phí và chắc chắn tốt hơn từng cái đơn lẻ.
Vì chất lượng, thêm một reranker: truy xuất 20–50 ứng viên, xếp lại xuống top 5 bằng cross-encoder (họ bge-reranker — cùng câu chuyện đa ngôn ngữ như bge-m3). Reranker đọc đoạn và truy vấn cùng nhau, điều embedder đơn-vector không làm được. Công thức rẻ phủ đa số nhu cầu: truy xuất lai 25, xếp lại còn 5.
Chẩn đoán: hụt truy xuất hay hụt sinh?
Trước khi tinh chỉnh bất cứ gì, trả lời một câu: đoạn đúng có được truy xuất không?
- In các đoạn top-k cho một truy vấn đang thất bại, kèm điểm.
- Nếu đoạn chứa câu trả lời không trong danh sách, đó là vấn đề truy xuất — sửa chia đoạn, embedding, hoặc tăng k.
- Nếu nó có trong danh sách nhưng câu trả lời sai, đó là vấn đề sinh — mô hình to hơn, prompt tốt hơn, xếp lại để đẩy nhiễu ra.
Riêng phép kiểm này tiết kiệm hàng giờ tinh chỉnh nhầm nửa pipeline.
Các chế độ thất bại
| Triệu chứng | Nguyên nhân | Cách sửa |
|---|---|---|
| Đúng tài liệu được truy xuất, sai câu trả lời | nhiễu trong top-k | xếp lại; co k |
| Câu trả lời có trong tài liệu nhưng không bao giờ lộ | top-k bỏ đói hoặc ranh giới xấu | tăng k; chia đoạn theo tiêu đề |
| Tự tin nhưng lỗi thời | chỉ mục cũ hơn tài liệu | lập lại chỉ mục khi có thay đổi |
| Truy vấn tiếng Hàn hụt tài liệu tiếng Anh | embedding đơn ngôn ngữ | bge-m3 |
| Trích dẫn chỉ sai đoạn | đoạn mất metadata nguồn | lưu nguồn + tiêu đề mỗi đoạn |
Đo lường, đừng cảm tính
Giữ một bộ vàng 20–50 câu hỏi thật có đáp án đã biết. Chấm hai con số riêng: tỉ lệ trúng truy xuất (đoạn đúng có trong top-k không?) và tính đúng đắn của câu trả lời. Theo dõi chúng sau mỗi thay đổi kích thước đoạn, embedder, hay k. Làm RAG không có bộ vàng là chiêm tinh.
Khi nào nên tinh chỉnh thay vì vậy
Tinh chỉnh đổi hành vi — định dạng, phong cách, thuật ngữ. Nó là cách kém để thêm sự kiện: mô hình không thể trích dẫn thứ nó được tinh chỉnh trên, và tài liệu mới nghĩa là một lần huấn luyện mới. Quy tắc ngón tay: sự kiện → RAG, hành vi → LoRA, cả hai chỉ khi bạn đã cạn kiệt prompting: tinh chỉnh.
Các chồng tầng cục bộ, từ nhỏ nhất
Open WebUI tích hợp sẵn tải tài liệu và truy xuất lai — bắt đầu ở đó và bạn có thể chẳng bao giờ phải viết code pipeline. Lõi trung thực của RAG là ~50 dòng; viết nó một lần để bạn biết các framework đang làm gì:
chunks = chunk_by_header(read("manual.md"), max_tokens=400, overlap=60)
index = [(embed(c), c) for c in chunks] # làm một lần
def answer(question):
hits = topk_by_cosine(embed(question), index, k=5)
ctx = "\n\n".join("[{}] {}".format(i, c) for i, (v, c) in enumerate(hits))
prompt = TEMPLATE.replace("{ctx}", ctx).replace("{q}", question)
return chat(prompt) # mô hình cục bộ nhỏ là đủ
Với tay về LlamaIndex hay LangChain khi bạn cần quyền, làm mới định kỳ, hay bộ khung đánh giá — không phải cho vòng lặp phía trên. Riêng với tài liệu tiếng Hàn, embedding đa ngôn ngữ (bge-m3) không phải tùy chọn, và chia đoạn theo tiêu đề nên tôn trọng cấu trúc tài liệu tiếng Hàn (tiêu đề 장/절) như cách nó tôn trọng tiêu đề ## markdown.
Liên quan: tinh chỉnh · prompting · đầu ra có cấu trúc · suy luận CPU