RAG với hy4: cách nối model 4B vào kho tri thức và tìm kiếm vector
RAG với hy4: cách nối model 4B vào kho tri thức và tìm kiếm vector
Câu hỏi "model 4B chạy RAG được không" chỉ có câu trả lờ thật nếu bạn nói rõ model 4B làm gì. Câu trả lời là: làm các khâu nhẹ trong đường ống thì rất đủ, còn tổng hợp văn dài thì dễ vấp ngã. hy4 rất hợp với vai trước: model dense 4,22 tỷ tham số, ngữ cảnh gốc 256K, Q4_K_M chỉ 2,6GB, chạy được trên hầu hết máy. Bài này đưa một bộ hoàn chỉnh: vector store tại chỗ, embedding bge-m3, hy4 làm viết lại truy vấn và sinh câu trả lời, cùng năm lỗi bạn sẽ gặp thật.
Tóm tắt 30 giây
hy4 có ba vai giá trị cao trong RAG: viết lại truy vấn (biến câu hỏi nói miệng thành từ khoá tìm kiếm), định tuyến ý định (quyết định đi vào kho nào), và sinh câu trả lời ngắn (trả lờời dưới 300 từ dựa trên đoạn trích). Tổng hợp nhiều tài liệu và suy luận nhiều bước giao cho model lớn trên cloud. Phía vector dùng embedding mở như bge-m3, vì danh mục cloud EXAIV hiện chưa có model embedding nào.
Định vai trò trước: 4B nên làm gì, không nên làm gì
Đường ống RAG có ít nhất hai vai: bên truy hồi "tìm tài liệu" và bên sinh "tổ chức câu trả lờời". Hai việc này đòi hỏi rất khác nhau từ model:
| Khâu | Yêu cầu từ model | hy4 có phù hợp không |
|---|---|---|
| Viết lại và mở rộng truy vấn | chỉ cần hiểu câu hỏi, tạo từ khoá | rất phù hợp |
| Phân loại ý định, định tuyến | chỉ cần xuất một nhãn | rất phù hợp, thậm chí 0,5B cũng xoay |
| Tóm tắt và trích xuất | cần bao phủ điểm chính của bản gốc | phù hợp |
| Trả lờng ngắn có căn cứ | cần trung thực, không bịa | phù hợp kèm prompt nghiêm ngặt |
| Tổng hợp văn dài trên nhiều tài liệu | cần suy luận dài và nhất quán | không phù hợp, chọn model lớn |
| Suy luận nhiều bước | cần các bước trung gian | không phù hợp |
Vì sao model nhỏ hợp với nửa đầu của đường ống
Nửa đầu xuất ra văn bản ngắn hoặc nhãn, nơi sai lầm rẻ và dễ kiểm chứng; nửa sau xuất ra văn bản dài, nơi sai lầm đắt và khó truy vết. Đặt 4B ở nửa đầu, một lần viết lại kém vẫn còn truy hồi để bù lại; đặt 4B ở nửa sau, mỗi câu bịa đều đối diện trực tiếp với người dùng.
Một bộ hoàn chỉnh chạy được
Bước 1: khởi động máy chủ suy luận tại chỗ
./llama-server -m ./hunyuan4b/Q4_K_M.gguf \
--host 127.0.0.1 --port 8080 \
--ctx-size 32768 --jinja
Điểm cuối được mở ra là API tương thích OpenAI chuẩn, phía dưới trỏ thẳng vào http://127.0.0.1:8080/v1.
Bước 2: chia nhỏ tài liệu
from pathlib import Path
import re
def load_docs(folder: str) -> list[str]:
chunks = []
for p in sorted(Path(folder).glob("**/*.md")):
text = p.read_text(encoding="utf-8")
sections = re.split(r"\n(?=#{1,3} )", text)
for sec in sections:
if len(sec) < 200:
continue
for i in range(0, len(sec), 1200):
piece = sec[i:i + 1200]
if len(piece.strip()) > 50:
chunks.append(sec.split("\n")[0] + "\n" + piece)
return chunks
chunks = load_docs("./docs")
print(len(chunks))
Nguyên tắc đầu tiên khi chia nhỏ: không được cắt đứt đơn vị nghĩa
Chia theo số ký tự cố định sẽ cắt đôi một bảng hoặc một đoạn mô tả API, khiến đoạn truy hồi được đọc lên bị thiếu và model chỉ còn đoán. Hãy chia theo thứ bậc tiêu đề trước, rồi mới chia theo độ dài, và giữ tiêu đề làm tiền tố để gắn lại — tiêu đề chính là mỏ neo truy hồi tốt nhất.
Bước 3: nhúng (embedding tại chỗ)
from sentence_transformers import SentenceTransformer
embed_model = SentenceTransformer("BAAI/bge-m3")
vectors = embed_model.encode(chunks, normalize_embeddings=True, batch_size=32)
bge-m3 là một trong những model embedding đa ngôn ngữ mở được tải nhiều nhất trong cộng đồng, hỗ trợ hỗn hợp Trung-Anh và văn bản dài.
Vì sao không dùng embedding trên cloud
Thứ nhất, danh mục cloud EXAIV hiện không có model thuộc loại embedding; thứ hai, lượng yêu cầu embedding lớn nhưng mỗi yêu cầu rẻ, nên đưa lên cloud lại thành phần chi phí đắt nhất; thứ ba, model embedding chỉ vài trăm MB đến hơn một GB, chạy tại chỗ gần như không tốn chi phí vận hành và nhanh hơn.
Bước 4: truy hồi và xếp lại
import numpy as np
query_vec = embed_model.encode([query], normalize_embeddings=True)[0]
scores = np.dot(vectors, query_vec)
top_idx = np.argsort(-scores)[:20]
from sentence_transformers import CrossEncoder
reranker = CrossEncoder("BAAI/bge-reranker-v2-m3")
pairs = [[query, chunks[i]] for i in top_idx]
rerank_scores = reranker.predict(pairs)
final_idx = [top_idx[i] for i in np.argsort(-rerank_scores)[:4]]
Xếp lại là bước có hiệu quả cao nhất về chi phí
Truy hồi vector là bộ lọc thô (rẻ, nhanh, phủ rộng), còn xếp lại bằng cross-encoder là bộ lọc tinh (chậm hơn, đắt hơn, nhưng thứ tự chính xác hơn nhiều). Nhiều hệ RAG vấp trở ngại ở thứ tự truy hồi chứ không phải model sinh. Dành công sức biến top-20 thành top-4 sạch thường hiệu quả hơn việc đổi model sinh 4B sang 7B.
Bước 5: viết lại truy vấn và sinh câu trả lờng bằng hy4
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:8080/v1", api_key="local")
def rewrite(query: str) -> str:
r = client.chat.completions.create(
model="local-model",
messages=[
{"role": "system", "content": "Viết lại câu hỏi của người dùng thành 3 cụm từ khoá dùng cho tìm kiếm vector, mỗi dòng một cụm, không giải thích."},
{"role": "user", "content": query},
],
temperature=0.1,
)
return r.choices[0].message.content
def answer(query: str, context_chunks: list[str]) -> str:
context = "\n\n---\n\n".join(context_chunks)
r = client.chat.completions.create(
model="local-model",
messages=[
{"role": "system", "content":
"Bạn là trợ lý kho tri thức. Chỉ trả lờng dựa trên tài liệu được cung cấp. "
"Nếu tài liệu không đề cập, hãy nói rõ là chưa có trong tài liệu, đừng suy đoán. "
"Trả lờng dưới 300 từ và đánh dấu nguồn ở cuối câu bằng [đoạn N]."},
{"role": "user", "content": f"Tài liệu:\n{context}\n\nCâu hỏi: {query}"},
],
temperature=0.2,
)
return r.choices[0].message.content
rewritten = rewrite(query)
print(answer(query, [chunks[i] for i in final_idx]))
Ghi cứng ba ràng buộc trong prompt
Chỉ trả lờng dựa trên tài liệu, nói rõ khi tài liệu không đề cập, và trích số đoạn. Ba dòng này làm giảm tỷ lệ bịa của model 4B một cách đáng kể. Model 4B không tự quyết định mình có nên bịa hay không, nhưng có thể bị ràng buộc bằng chỉ thị.
Năm lỗi bạn sẽ gặp
Lỗi một: chia nhỏ cắt đứt ngữ nghĩa
Biểu hiện là đoạn truy hồi đọc lên bị mất nửa câu. Cách sửa là chia theo thứ bậc tiêu đề và giữ tiêu đề làm tiền tố, sau đó mới chia lại theo ranh giới câu.
Lỗi hai: chỉ truy hồi không xếp lại
Biểu hiện là tài liệu đúng được lấy về nhưng xếp ở vị trí 12 và bị top-4 loại bỏ. Cách sửa là tăng số lượng truy hồi và thêm bộ xếp lại, hoặc dùng nhiều phiên bản viết lại truy vấn để truy riêng rồi gộp kết quả.
Lỗi ba: prompt không ràng buộc
Biểu hiện là model bù kính bằng kiến thức huấn luyện, tự tin trả lờng dù tài liệu không có. Cách sửa là thêm chỉ thị "nếu chưa có trong tài liệu thì nói rõ", trích số đoạn, và hạ temperature xuống dưới 0,2.
Lỗi bốn: coi truy hồi là hỏi đáp
Biểu hiện là người dùng hỏi "tính năng này dùng thế nào" và model trả lờng bằng đoạn giới thiệu sản phẩm về chức năng của nó. Cách sửa là phân loại câu hỏi trước (tra sự thật, hướng dẫn thao tác, xử lý sự cố) và dùng mẫu prompt khác nhau cho từng loại.
Lỗi năm: nhồi quá đầy ngữ cảnh
Biểu hiện là hy4 không tìm thấy câu quan trọng giữa lượng tài liệu lớn và bắt đầu lặp lại. hy4 hỗ trợ ngữ cảnh 256K một cách gốc, nhưng chứa được không đồng nghĩa dùng tốt. Một lần chỉ nên cho 4 đến 8 đoạn, vượt quá thì nén trước rồi mới gửi.
Khi nào không nên dùng model 4B để sinh
| Tình huống | Lựa chọn tốt hơn |
|---|---|
| Cần tổng hợp trên hơn 5 nguồn | model lớn trên cloud |
| Đầu ra là báo cáo dài, văn thảo | model lớn trên cloud |
| Truy hồi kém, không lấy được tài liệu | sửa phần truy hồi, đừng đổi model sinh |
| Hỏi đáp số lượng lớn, yêu cầu độ trễ thấp | hy4 hay các model nhẹ tương tự |
| Tài liệu gốc dài và cần tóm tắt dài | model mạnh hơn về ngữ cảnh, hoặc tóm tắt tầng trước |
FAQ
Model 4B chạy RAG đủ dùng không?
hy4 hỗ trợ ngữ cảnh dài bao nhiêu?
Nên dùng model embedding nào?
Có cần xếp lại không?
Làm sao giảm lãng bịa của model?
Làm sao nối điểm cuối hy4 tại chỗ vào ứng dụng hiện có?
Đọc tiếp
- Trang model hy4 — thông số, ma trận quantization và cách tính bộ nhớ
- Ghi chú kênh hy4-preview — kênh ngữ cảnh 1M
- Triển khai hy4 với GGUF — các bước đầy đủ để máy chủ chạy
- Kết nối hy4 với Ollama — đưa điểm cuối tại chỗ vào công cụ phát triển
- Open WebUI với Hunyuan tại chỗ — giao diện trò chuyện tự lưu trữ
- Hướng dẫn kỹ năng ngữ cảnh — cách tổ chức thông tin trong ngân sách cửa sổ
- Hướng dẫn chọn model embedding — bge, gte, jina và e5 so ra sao
- Hướng dẫn chọn model hy4 — các kích thước và phân chia với A13B
Nguồn dữ liệu
Số liệu tải và thông số theo repositori chính thức thời gian thực, lấy mẫu tháng 11 năm 2026.