Một schema lỏng lẻo là nguồn gốc của 80% lỗi "model trả gần đúng". Bài này dạy bạn viết JSON Schema đủ chặt để loại bỏ trạng thái không hợp lệ ngay từ gốc, thay vì bắt lỗi ở hạ nguồn.
Nguyên tắc vàng: "Make invalid states unrepresentable"
Nếu một trường chỉ được nhận 3 giá trị, hãy dùng enum, đừng để string tự do. Nếu một object bắt buộc có 4 trường, hãy khai required cả 4 và đặt additionalProperties: false. Mỗi ràng buộc bạn thêm là một class bug bạn xóa.
Ví dụ: schema phân loại ticket hỗ trợ
{
"type": "object",
"properties": {
"category": {
"type": "string",
"enum": ["billing", "technical", "account", "other"]
},
"priority": {
"type": "string",
"enum": ["low", "medium", "high", "urgent"]
},
"summary": { "type": "string", "maxLength": 200 },
"needs_human": { "type": "boolean" }
},
"required": ["category", "priority", "summary", "needs_human"],
"additionalProperties": false
}
So với việc để category là string tự do, enum đảm bảo bạn không bao giờ nhận "Billing " (thừa dấu cách) hay "hoá đơn" (tiếng Việt) làm vỡ nhánh switch của bạn.
Các bước thiết kế schema
- Bắt đầu từ dữ liệu code cần, không phải từ những gì model "có thể nói". Vẽ struct/type đích trước.
- Đóng mọi cửa mở: đặt
additionalProperties: falseđể model không tự bịa thêm trường. - Ràng buộc miền giá trị: dùng
enumcho tập hữu hạn,minimum/maximumcho số,pattern/formatcho chuỗi (email, date-time). - Khai báo
requiredrõ ràng: nhiều model coi trường không required là "được phép bỏ", gây thiếu dữ liệu. - Dùng
descriptionnhư micro-prompt: mô tả từng trường hướng dẫn model điền đúng ngữ nghĩa, ví dụ"priority": mô tả "urgent chỉ khi ảnh hưởng thanh toán hoặc bảo mật". - Mô hình hóa quan hệ bằng nesting/array, tránh nhồi nhiều thứ vào một chuỗi.
Kỹ thuật nâng cao
- Discriminated union: khi output có nhiều "loại", thêm trường
typelàm nhãn phân biệt, mỗi loại có schema riêng. Giúp code branch an toàn. - Trường lý do (reasoning) đặt TRƯỚC kết quả: ví dụ đặt
analysistrướcdecision. Vì model sinh token tuần tự, cho nó "nghĩ" trước khi "chốt" giúp chất lượng tăng. - Tránh lồng quá sâu: schema sâu >3-4 tầng làm model dễ lạc; cân nhắc tách phẳng.
Khung tư duy: schema là hợp đồng hai chiều
Schema vừa nói với model "tao cần đúng hình này", vừa nói với code "mày sẽ luôn nhận đúng hình này". Coi nó như interface trong lập trình: chặt chẽ ở đây thì hạ nguồn sạch sẽ.
Checklist review schema
- [ ] Mọi trường tập hữu hạn đã dùng
enumchưa? - [ ] Đã đặt
additionalProperties: false? - [ ]
requiredliệt kê đủ trường bắt buộc? - [ ] Số/chuỗi có ràng buộc miền (min/max/format)?
- [ ] Trường suy luận đặt trước trường kết luận?
- [ ] Mỗi trường có
descriptionđủ rõ?
Sai lầm thường gặp
- Dùng
stringcho mọi thứ. Ngày tháng, enum, số... để string tự do là mời gọi output lệch chuẩn. - Quên
additionalProperties: false. Model rảnh tay bịa thêm trườngnotehayconfidencekhông lường trước, làm validate hoặc DB insert lỗi. - Không đặt
required. Bạn tưởng model sẽ luôn điền, nhưng khi ngữ cảnh mơ hồ nó sẽ bỏ trống. - Nhồi nhiều dữ liệu vào một chuỗi (kiểu
"Minh|high|billing") rồi tự tách — mất hết lợi ích của structured output. enumbằng tiếng Việt có dấu khó khớp; nên dùng khóa tiếng Anh không dấu, hiển thị tiếng Việt ở tầng UI.