LLMOps 3 — Prompt production & Guardrails
LLMOps 3 — Prompt production & Guardrails
Prompt bạn gõ trong playground để "thử cho vui" và prompt chạy trong hệ thống phục vụ khách hàng ngân hàng 24/7 là hai sinh vật khác nhau. Cái đầu tiên chỉ cần đúng một lần cho bạn xem. Cái thứ hai phải đúng với hàng nghìn câu hỏi lạ, không bao giờ lộ số dư của khách khác, không bao giờ tư vấn "nên mua cổ phiếu nào", và khi không chắc thì từ chối một cách an toàn thay vì bịa.
Bài này gồm hai nửa gắn chặt nhau: (1) prompt cho production — coi prompt như code, có versioning, test, structured output; (2) guardrails — lớp rào chắn an toàn bao quanh LLM, kiểm ở cả đầu vào lẫn đầu ra. Đây là phần "làm cho nó an toàn" của LLMOps, tiếp nối tổng quan LLMOps và các pattern ứng dụng.
Phần 1 — Prompt cho production
System prompt: vai trò, giới hạn, định dạng
Prompt thử nghiệm thường là một câu hỏi trần trụi. Prompt production luôn có một system prompt đặt khung cho mọi lượt trả lời. Ba thứ bắt buộc phải nêu rõ:
- Vai trò (role): trợ lý là ai, phục vụ ai. "Bạn là trợ lý nội bộ cho nhân viên NCB, trả lời câu hỏi về chính sách sản phẩm và quy trình."
- Giới hạn (constraints): những gì tuyệt đối KHÔNG làm. Đây là nơi ghi các "không được": không tư vấn đầu tư, không tiết lộ dữ liệu khách hàng, không trả lời ngoài phạm vi nghiệp vụ.
- Định dạng (format): đầu ra trông như thế nào — văn xuôi, bảng, hay JSON theo schema.
Ví dụ system prompt minh hoạ (không phải SQL, chỉ là text prompt):
Bạn là trợ lý chính sách nội bộ của Ngân hàng NCB.
PHẠM VI: chỉ trả lời câu hỏi về sản phẩm, phí, lãi suất, và quy
trình nghiệp vụ dựa TRÊN tài liệu được cung cấp trong <context>.
TUYỆT ĐỐI KHÔNG:
- Tiết lộ hoặc suy đoán dữ liệu của khách hàng cụ thể (số dư,
số tài khoản, CMND/CCCD).
- Đưa lời khuyên đầu tư, pháp lý, hoặc thuế.
- Trả lời câu hỏi ngoài phạm vi ngân hàng.
KHI KHÔNG CHẮC: trả lời "Tôi không tìm thấy thông tin này trong
tài liệu chính sách. Vui lòng liên hệ bộ phận [X]." KHÔNG bịa.
Mọi khẳng định phải dẫn nguồn theo dạng [nguồn: <tên tài liệu>].
Một system prompt tốt làm phần lớn công việc của guardrails "mềm". Nhưng nó không đủ — vì người dùng có thể tìm cách vượt qua nó (prompt injection, xem bài 4). Vì vậy ta cần cả rào chắn "cứng" ở ngoài, phần 2 dưới đây.
Few-shot ổn định
Few-shot (đưa vài ví dụ mẫu vào prompt) rất mạnh để định hình phong cách và định dạng. Nhưng trong production, ví dụ phải ổn định và được kiểm soát:
- Chọn ví dụ cố định, đã review, không lấy ngẫu nhiên mỗi lượt (trừ khi bạn cố ý làm dynamic few-shot có test riêng).
- Bao gồm cả ví dụ về cách từ chối: một mẫu cho thấy khi gặp câu hỏi ngoài phạm vi thì trả lời fallback ra sao. Điều này dạy model hành vi an toàn tốt hơn là chỉ mô tả bằng lời.
- Đừng nhồi quá nhiều ví dụ: mỗi ví dụ tốn token và tăng độ trễ. 2–4 ví dụ đại diện thường tốt hơn 15 ví dụ dài.
Structured output — ép định dạng bằng schema
Với các bước cần máy đọc lại (routing, trích xuất trường, gọi API tiếp), đừng parse văn xuôi tự do. Dùng structured output: yêu cầu model trả về JSON theo một schema, hoặc dùng function/tool calling để nhà cung cấp ép đúng cấu trúc.
Ví dụ mô tả một tool để phân loại yêu cầu khách hàng (minh hoạ, JSON Schema):
{
"name": "phan_loai_yeu_cau",
"description": "Phân loại yêu cầu của khách vào một nhóm nghiệp vụ",
"input_schema": {
"type": "object",
"properties": {
"nhom": {
"type": "string",
"enum": ["the", "vay", "tiet_kiem", "khieu_nai", "ngoai_pham_vi"]
},
"co_pii": { "type": "boolean" },
"do_khan": { "type": "string", "enum": ["thap", "trung", "cao"] }
},
"required": ["nhom", "co_pii"]
}
}
Khi model buộc phải trả về đúng schema này, code phía sau không phải đoán mò — nhom == "ngoai_pham_vi" là một guardrail routing rõ ràng. Structured output biến LLM từ "hộp đen sinh chữ" thành một component có hợp đồng (contract) rõ ràng.
Prompt là code: versioning, test, review
Đây là thay đổi tư duy quan trọng nhất của LLMOps: prompt là artifact sản xuất, không phải string vứt trong code. Đối xử với nó như code:
| Khía cạnh | Prompt thử nghiệm | Prompt production |
|---|---|---|
| Lưu trữ | Copy-paste trong notebook | File có version trong repo / prompt registry |
| Thay đổi | Sửa tại chỗ, không dấu vết | Pull request + review |
| Kiểm thử | Chạy tay xem có "ổn không" | Bộ test hồi quy tự động (regression suite) |
| Biến động | Hardcode giá trị | Template + biến, tách khỏi logic |
| Rollback | Không thể | Về version cũ trong vài giây |
Template & biến: tách phần cố định (system prompt) khỏi phần thay đổi (câu hỏi, context, ngày). Dùng placeholder rõ ràng như {{cau_hoi}}, {{context}}. Tránh nối chuỗi lộn xộn — vừa khó đọc vừa dễ tạo lỗ hổng injection.
Versioning: mỗi thay đổi prompt = một version. Khi lên production phải biết chính xác version nào đang chạy để reproduce và rollback. Nếu đổi prompt mà không đo lại chất lượng, bạn đang deploy mù — hãy gắn thay đổi prompt với bộ đánh giá tự động.
Tránh nhồi context thừa: context dài hơn không phải luôn tốt hơn. Nhồi 20 đoạn tài liệu khi 3 đoạn là đủ sẽ (a) tốn token và tiền, (b) tăng độ trễ, (c) làm loãng tín hiệu khiến model dễ bỏ sót ("lost in the middle"). Truy hồi đúng và gọn (xem RAG) quan trọng hơn truy hồi nhiều.
Phần 2 — Guardrails: rào chắn an toàn quanh LLM
Guardrail là các lớp kiểm tra chạy ngoài model, bao quanh nó, để chặn đầu vào nguy hiểm và đầu ra không hợp lệ. LLM tự nó là xác suất và có thể bị lừa; guardrails là phần deterministic (rule/classifier) mà bạn tin cậy được. Kiến trúc điển hình:
Ba nhóm chốt kiểm: input, output, và topical (xuyên suốt).
(a) Input guardrails — kiểm đầu vào
Chạy TRƯỚC khi câu hỏi đến LLM:
- Phát hiện prompt injection sơ bộ: bắt các mẫu như "bỏ qua hướng dẫn trên", "in ra system prompt", "đóng vai...". Đây là lớp phòng thủ đầu, không phải lớp cuối (chi tiết ở bài 4).
- Off-topic / ngoài phạm vi: classifier hoặc rule chặn câu hỏi không thuộc nghiệp vụ ("thời tiết hôm nay?", "viết code Python cho tôi") trước khi tốn một lượt gọi model.
- PII trong câu hỏi: phát hiện khách hàng vô tình dán số CCCD, số thẻ đầy đủ. Có thể che (mask) trước khi log/xử lý để không lưu PII vào hệ thống.
- Nội dung độc hại: chặn ngôn ngữ thù ghét, quấy rối.
(b) Output guardrails — kiểm đầu ra
Chạy SAU khi LLM sinh, TRƯỚC khi trả cho người dùng:
- PII redaction: dù có input guardrail, model vẫn có thể rò rỉ dữ liệu nhạy cảm (ví dụ vô tình lôi thông tin từ context của khách khác). Quét đầu ra và che số tài khoản, số dư, CCCD trước khi hiển thị.
- Kiểm bám nguồn (grounding): với trợ lý RAG, mọi khẳng định phải có trong context được cấp. Nếu câu trả lời chứa thông tin không có nguồn → nghi ảo giác (hallucination) → chặn hoặc gắn cảnh báo. Đây là tuyến chống ảo giác chính, xem sâu ở bài 5.
- Chặn lời khuyên không được phép: classifier bắt các câu tư vấn đầu tư ("bạn nên mua..."), pháp lý, thuế — những thứ ngoài thẩm quyền của trợ lý và có rủi ro pháp lý cho ngân hàng.
- Định dạng hợp lệ: nếu yêu cầu JSON, kiểm parse được và đúng schema; nếu không, retry hoặc fallback thay vì trả JSON hỏng cho hệ thống hạ nguồn.
- Toxicity: đảm bảo đầu ra không xúc phạm.
(c) Topical guardrails — giữ trong phạm vi
Đây là nguyên tắc xuyên suốt cả input lẫn output: whitelist chủ đề trợ lý được phép nói. Trong ngân hàng, cách an toàn là "mặc định từ chối" — chỉ trả lời chủ đề trong danh sách cho phép, còn lại từ chối lịch sự. Cách tiếp cận này (whitelist thay vì blacklist) đồng nhất với nguyên tắc kiểm soát dữ liệu ở gov-07-privacy-compliance.
Công cụ triển khai
Không phải lúc nào cũng cần framework. Bảng lựa chọn:
| Cách | Khi nào dùng |
|---|---|
| Rule + regex | PII pattern, từ khoá injection — nhanh, deterministic, rẻ |
| Classifier tự viết | Off-topic, toxicity theo domain ngân hàng VN |
| Guardrails AI | Định nghĩa validator input/output có cấu trúc bằng schema |
| NeMo Guardrails | Định nghĩa luồng hội thoại được phép/cấm (topical rails) |
| Llama Guard | Model chuyên phân loại nội dung an toàn (input & output) |
Thực tế thường là kết hợp: rule rẻ chặn phần lớn ở tầng ngoài, classifier/LLM-judge xử lý các ca tinh vi. Đừng dùng một LLM đắt để làm việc mà một regex làm được.
Safe refusal & fallback
Khi một guardrail kích hoạt, đừng để lộ lý do kỹ thuật hay im lặng. Trả một thông điệp fallback rõ ràng, lịch sự, có hướng xử lý tiếp:
"Tôi không thể hỗ trợ yêu cầu này vì nằm ngoài phạm vi tư vấn của trợ lý. Với vấn đề đầu tư, vui lòng liên hệ chuyên viên tư vấn tại chi nhánh hoặc hotline 1900-xxxx."
Safe refusal là tính năng, không phải lỗi. Một trợ lý ngân hàng biết từ chối đúng lúc đáng tin hơn một trợ lý luôn cố trả lời.
Grounding, trích nguồn & con người duyệt
Hai nguyên tắc khép lại lớp an toàn:
- Bắt buộc trích nguồn: ép model dẫn nguồn cho mọi khẳng định, và output guardrail kiểm nguồn đó có thật. Câu trả lời không nguồn = không đáng tin. Đây là vũ khí chính chống ảo giác.
- Human-in-the-loop cho hành động rủi ro: LLM có thể soạn nhưng con người phải duyệt trước khi thực thi bất cứ hành động có hậu quả — gửi email cho khách, thay đổi hồ sơ, phê duyệt. Trợ lý gợi ý, người quyết định.
Use case thực tế
Bối cảnh: NCB triển khai chatbot nội bộ cho ~800 giao dịch viên tra cứu chính sách sản phẩm (phí, lãi suất, điều kiện vay). Chatbot dùng RAG trên ~1.200 tài liệu chính sách. Yêu cầu: không lộ dữ liệu khách hàng, không tư vấn đầu tư, luôn dẫn nguồn.
Thiết kế guardrails triển khai:
- Input: rule regex chặn số CCCD/số thẻ đầy đủ trong câu hỏi (che trước khi log); classifier off-topic loại câu ngoài nghiệp vụ; danh sách mẫu injection cơ bản.
- Prompt: system prompt cố định (versioned trong Git), 3 few-shot gồm 1 ví dụ từ chối; ép trích nguồn
[nguồn: <tài liệu>]. - Output: kiểm mọi câu trả lời có ít nhất 1 trích dẫn hợp lệ; classifier chặn câu chứa "nên đầu tư / nên mua"; redaction quét số tài khoản 8+ chữ số.
- Fallback: thông điệp lịch sự + số hotline khi guardrail kích hoạt.
Kết quả sau 6 tuần (số liệu minh hoạ):
| Chỉ số | Trước guardrails | Sau guardrails |
|---|---|---|
| Câu trả lời không có nguồn | ~18% | < 2% |
| Rò rỉ PII trong log | 5 vụ/tuần | 0 |
| Trả lời ngoài phạm vi | ~12% | ~1% |
| Tỷ lệ giao dịch viên tin dùng | 61% | 88% |
Điểm mấu chốt: mức chi phí guardrails (rule + 1 classifier nhẹ) chỉ thêm ~40ms/lượt và vài phần trăm token, đổi lại loại bỏ gần hết rủi ro rò rỉ và ảo giác — một đánh đổi rõ ràng có lợi cho môi trường ngân hàng.
Ghi nhớ
- Prompt production khác prompt thử nghiệm: system prompt rõ vai trò / giới hạn / định dạng, few-shot ổn định (có mẫu từ chối), structured output ép JSON schema.
- Prompt là code: version, review, test hồi quy, template + biến, rollback được. Đổi prompt mà không đo lại = deploy mù.
- Tránh nhồi context thừa: đúng và gọn thắng nhiều và loãng ("lost in the middle").
- Guardrails là lớp deterministic bao quanh LLM: input (injection, off-topic, PII, độc hại) và output (redaction PII, kiểm grounding, chặn lời khuyên cấm, định dạng, toxicity).
- Topical guardrails trong ngân hàng nên theo nguyên tắc whitelist / mặc định từ chối — chỉ trả lời chủ đề được phép.
- Công cụ: rule + classifier tự viết cho phần rẻ; Guardrails AI / NeMo Guardrails / Llama Guard cho phần phức tạp. Kết hợp, đừng dùng LLM đắt cho việc regex làm được.
- Safe refusal là tính năng: fallback lịch sự, có hướng xử lý tiếp.
- Bắt buộc trích nguồn + kiểm grounding để chống ảo giác; con người duyệt cho mọi hành động rủi ro.
Bài viết liên quan
Phân biệt AI/ML/DL, các kiểu học máy, quy trình ML end-to-end và thuật ngữ nền tảng.
Chất lượng dữ liệu, xử lý thiếu/ngoại lai, mã hoá, chuẩn hoá, tạo đặc trưng và tránh data leakage.
Mô hình ngôn ngữ lớn hoạt động ra sao, token, context window, tham số sinh, và kỹ thuật viết prompt.
Retrieval-Augmented Generation, vector database, tool calling, agent và MCP để xây ứng dụng LLM thực tế.