Bỏ qua để vào nội dung chính
Prompt hợp đồng 4 phần: chặn LLM trôi output mỗi lần chạy

Prompt hợp đồng 4 phần: chặn LLM trôi output mỗi lần chạy

Bởi Hannah Cooper
12 thg 10, 20264 phút đọc

Viết prompt như hợp đồng bốn phần — role, task, constraints, output contract — để output không đổi dạng mỗi lần chạy, kèm đường thoát lỗi bắt được.

Cùng một prompt, chạy hai lần ra hai dạng output khác nhau: lần này bọc JSON trong markdown fence, lần sau thêm một câu dẫn. Parser phía sau vỡ, và bạn phát hiện lúc 3 giờ sáng.

Một bài trên Dev.to hôm qua gọi lỗi đó là drift, và đề xuất cách chữa gọn: viết prompt như một hợp đồng bốn phần thay vì viết như văn xuôi.

Bốn câu hỏi mọi prompt lặp lại phải trả lời

Theo tác giả, prompt nào cần hành xử giống nhau ở lần chạy thứ hai đều phải trả lời đủ bốn câu:

  • Role — ai đang nói, và tối ưu cho điều gì.
  • Task — một deliverable duy nhất, không phải một danh sách.
  • Constraints — điều gì tuyệt đối không được xảy ra.
  • Output contract — hình dạng chính xác của câu trả lời hợp lệ, và phải làm gì khi input không thỏa được.

Thiếu phần nào thì model tự đoán phần đó. Bài viết đưa ví dụ prompt kiểu văn xuôi — "tóm tắt review này và cho biết nó tích cực hay tiêu cực, có thể nêu than phiền chính, ngắn gọn thôi" — và nhận xét rằng nó hỏng theo năm cách khác nhau tùy input, không cách nào đoán trước được.

Bản hợp đồng thì dài hơn, và tác giả coi đó chính là điểm mạnh: mỗi dòng thêm vào là một quyết định bạn ra một lần, thay vì để model ra lại mỗi lần chạy.

Phần ai cũng bỏ qua: đường thoát hợp lệ

Schema không có đường thoát gây ra một kiểu hỏng rất cụ thể. Theo bài viết, khi input không khớp nổi schema, model sẽ bịa cho vừa khuôn — nó thà trả về một object đúng dạng nhưng sai nội dung còn hơn thừa nhận không làm được.

Cách xử lý là khai báo sẵn hình dạng thất bại, ví dụ {"error": "..."}, rồi validate ở phía code: parse JSON, kiểm tra đủ key bắt buộc, kiểm tra giá trị enum nằm trong tập cho phép. Khi đó drift biến thành một lỗi ồn ào bắt được ngay, thay vì một câu trả lời sai lặng lẽ trôi qua ba hệ thống phía sau.

Ràng buộc mạnh đều mang dạng phủ định

Bài viết tách rõ ràng buộc vô dụng khỏi ràng buộc có tác dụng. "Hãy chính xác" không làm được gì. Những câu sau thì chặn đúng một kiểu lỗi cụ thể:

  • "Không bịa ra than phiền không có trong văn bản" — chặn chi tiết bịa.
  • "Không lời dẫn, không markdown fence" — chặn việc model bọc JSON trong khối code.
  • "Một deliverable duy nhất" — chặn việc model trả lời ba câu hỏi bạn không hỏi.
  • "Nếu X thì làm Y" — cho model một lối ra hợp lệ, nhờ đó giảm bịa.

Điểm chung: tất cả đều phủ định hoặc có điều kiện. Như tác giả viết, "hãy hữu ích" là thứ không thể chứng minh sai, còn "không được bịa" thì kiểm tra được.

Bốn lưu ý khi áp dụng

Kiểm thử hợp đồng, đừng kiểm thử cảm giác: giữ 20-50 cặp input/expected và chạy lại mỗi lần động vào prompt, vì một thay đổi "nghe hay hơn" có thể làm hỏng 10% trường hợp mà không ai thấy.

Đừng siết phần suy luận: nếu tác vụ cần nghĩ thì cho model chỗ để nghĩ, chỉ đừng để phần nghĩ lọt vào output — tác giả gợi ý tách hai lời gọi, một để suy luận, một để định dạng.

Quản lý phiên bản prompt như code: prompt là một dependency, không nằm trong git kèm changelog thì bạn không rollback được khi có regression.

Và nếu hệ thống của bạn có failover giữa nhiều model, output contract chính là thứ giữ cho phản hồi của các provider thay thế được cho nhau. Đó là lý do nên viết hợp đồng trước khi dựng router, không phải ngược lại.

Không spam, hủy đăng ký bất kỳ lúc nào.

Bài viết liên quan