Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Bài 2 — Thiết kế JSON Schema chặt cho output

Đã đọc 0/8 mục · còn khoảng 3 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

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 enum cho tập hữu hạn, minimum/maximum cho số, pattern/format cho chuỗi (email, date-time).
  • Khai báo required rõ 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 description như 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 type là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 analysis trước decision. 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 enum chưa?
  • [ ] Đã đặt additionalProperties: false?
  • [ ] required liệ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 string cho 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ường note hay confidence khô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.
  • enum bằ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.
Schema chặt là nền móng. Bài 3 sẽ chỉ cách validate và xử lý khi model vẫn trả lệch dù schema đã chặt.

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi