Retrieval đưa về đúng chunk là chưa đủ. Bước sinh (generate) phải bắt LLM chỉ dùng chunk đó, trích dẫn nguồn, và biết nói không biết. Đây là nơi tạo ra niềm tin cho người dùng nội bộ.
Nguyên tắc: grounded generation
"Grounded" nghĩa là câu trả lời neo vào ngữ cảnh được cung cấp, không lấy từ "trí nhớ" của mô hình. Ta ép điều này qua ba đòn bẩy: cấu trúc prompt, chỉ dẫn rõ ràng, và định dạng trích dẫn bắt buộc.
Bước 1: Đánh số nguồn trong ngữ cảnh
Gắn nhãn mỗi chunk để LLM trích dẫn lại được:
[1] (Sổ tay nhân viên 2026, tr.5) Nhân viên chính thức được 14 ngày phép/năm...
[2] (Chính sách công tác, tr.2) Công tác phí được hoàn trong 7 ngày làm việc...
Bước 2: Viết system prompt chặt
Bạn là trợ lý Q&A nội bộ. Quy tắc:
1. CHỈ trả lời dựa trên phần "Ngữ cảnh" bên dưới.
2. Nếu ngữ cảnh KHÔNG chứa câu trả lời, nói đúng câu:
"Tôi không tìm thấy thông tin này trong tài liệu."
3. Sau mỗi ý, ghi trích dẫn dạng [số] tương ứng nguồn.
4. KHÔNG suy đoán, KHÔNG dùng kiến thức ngoài ngữ cảnh.
5. Trả lời ngắn gọn, tiếng Việt.
Bước 3: Ghép prompt hoàn chỉnh
def build_prompt(question, chunks):
ctx = "\n".join(
f"[{i+1}] ({c['title']}, tr.{c['page']}) {c['text']}"
for i, c in enumerate(chunks)
)
return [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": f"Ngữ cảnh:\n{ctx}\n\nCâu hỏi: {question}"},
]
Bước 4: Bắt buộc "đường lui" (abstention)
Cho phép — và khen thưởng — việc nói "không biết". Một agent nội bộ nói "tôi không tìm thấy" an toàn hơn nhiều một agent bịa. Kiểm tra: hỏi một câu chắc chắn không có trong tài liệu; nếu agent vẫn bịa, prompt của bạn chưa đủ chặt.
Bước 5: Định dạng đầu ra kèm nguồn
Trả về cho người dùng câu trả lời + danh sách nguồn có link, để họ bấm vào kiểm chứng:
{
"answer": "Nhân viên chính thức được 14 ngày phép/năm [1].",
"sources": [
{"n": 1, "title": "Sổ tay nhân viên 2026", "page": 5,
"url": "https://drive.company/hr-handbook#p5"}
]
}
Khung tư duy: 3 lớp phòng bịa
- Retrieval đúng — không có chunk sai để bịa dựa vào.
- Prompt chặt — cấm dùng kiến thức ngoài, buộc trích dẫn.
- Hậu kiểm — kiểm tra mỗi câu có [số] nguồn; nếu answer nói có thông tin nhưng không có nguồn → gắn cờ.
Ví dụ tình huống
Câu hỏi: "Công ty có hỗ trợ học phí tiếng Anh không?" Ngữ cảnh không đề cập.
- Prompt lỏng: "Nhiều công ty hỗ trợ học phí, bạn nên hỏi HR..." → bịa, vô dụng.
- Prompt chặt: "Tôi không tìm thấy thông tin này trong tài liệu." → đúng, an toàn. Người dùng biết cần hỏi HR trực tiếp.
Checklist prompt
- [ ] Ngữ cảnh có đánh số + tiêu đề + trang cho mỗi nguồn.
- [ ] System prompt cấm dùng kiến thức ngoài ngữ cảnh.
- [ ] Có câu "không biết" chuẩn hóa, được phép dùng.
- [ ] Bắt buộc trích dẫn [số] sau mỗi ý.
- [ ] Đầu ra trả kèm
sourcescó URL để kiểm chứng. - [ ] Đã test với câu "ngoài tài liệu" để chắc agent không bịa.
Sai lầm thường gặp
- Không đánh số nguồn → LLM "trích dẫn" chung chung, không kiểm chứng được.
- Quên cho phép nói 'không biết' → agent bịa khi thiếu ngữ cảnh.
- Trộn nhiều chunk không nhãn → không truy được câu trả lời đến từ đâu.
- Prompt quá dài dòng, mâu thuẫn → LLM bỏ qua quy tắc quan trọng.
- Tin rằng có trích dẫn là chắc đúng — vẫn cần hậu kiểm nguồn có thật khớp nội dung.