Structured Outputs với API OpenAI-compatible: hướng dẫn JSON Schema
Hướng dẫn thực tế về JSON Schema strict trong Responses và Chat Completions, validation nhiều lớp, xử lý lỗi và kiểm thử route.
Structured Outputs cho phép ứng dụng yêu cầu JSON tuân theo một Schema xác định, thay vì chỉ bảo mô hình “trả về JSON”. Với API OpenAI-compatible, cùng một JSON Schema có thể dùng qua Responses hoặc Chat Completions, nhưng wrapper field khác nhau và phải xác minh trên model cùng route thực tế.
Mẫu production an toàn có ba lớp: dùng strict khi mô hình hỗ trợ, parse và validate lại JSON trong ứng dụng, sau đó áp dụng business rule xác định. Tuân thủ Schema giảm lỗi định dạng nhưng không chứng minh câu trả lời đúng về mặt sự thật hoặc ngữ nghĩa.
Structured Outputs không phải JSON mode
| Phương pháp | JSON hợp lệ | Bắt buộc theo Schema | Trường hợp sử dụng |
|---|---|---|---|
| Chỉ Prompt | Không được bảo đảm | Không | Prototype chấp nhận lỗi parsing |
| JSON mode | Có nếu được hỗ trợ và hoàn tất | Không | JSON linh hoạt do ứng dụng validate |
Structured Outputs với strict: true |
Có, nếu xử lý completion và refusal | Có trong subset được hỗ trợ | Trích xuất typed và application workflow |
Hướng dẫn OpenAI Structured Outputs khuyến nghị cách này thay cho JSON mode khi model và endpoint hỗ trợ. Structured response format trả về một data object có thể dự đoán; Function Calling yêu cầu ứng dụng thực hiện hành động. Schema có thể tương tự, nhưng Call ID và result message thuộc contract khác.
Định nghĩa Schema trước khi chọn endpoint
Workflow phân loại hỗ trợ cần bốn field:
{
"type": "object",
"properties": {
"category": { "type": "string", "enum": ["billing", "technical", "account"] },
"priority": { "type": "integer", "minimum": 1, "maximum": 3 },
"requires_human": { "type": "boolean" },
"summary": { "type": "string" }
},
"required": ["category", "priority", "requires_human", "summary"],
"additionalProperties": false
}
Đặt mọi property là required và additionalProperties: false tạo object ổn định. Điều đó không làm mọi JSON Schema keyword trở nên portable. OpenAI hỗ trợ subset được ghi rõ; provider khác có thể hỗ trợ subset khác hoặc không có Strict Schema Mode.
Gửi Schema bằng Responses API
Responses đặt Schema dưới text.format:
{
"model": "<MODEL_WITH_VERIFIED_STRUCTURED_OUTPUT_SUPPORT>",
"input": "The customer was charged twice and wants a refund.",
"text": {
"format": {
"type": "json_schema",
"name": "support_ticket",
"schema": {
"type": "object",
"properties": {
"category": { "type": "string", "enum": ["billing", "technical", "account"] },
"priority": { "type": "integer", "minimum": 1, "maximum": 3 },
"requires_human": { "type": "boolean" },
"summary": { "type": "string" }
},
"required": ["category", "priority", "requires_human", "summary"],
"additionalProperties": false
},
"strict": true
}
}
}
Gửi tới POST https://modelflare.dev/v1/responses với Authorization: Bearer <YOUR_API_KEY>. Nội dung sinh ra nằm trong typed output items. SDK có thể cung cấp helper, nhưng HTTP client phải tìm text output hoàn tất và parse JSON rõ ràng.
Gửi cùng Schema bằng Chat Completions
Chat Completions dùng response_format.json_schema:
{
"model": "<MODEL_WITH_VERIFIED_STRUCTURED_OUTPUT_SUPPORT>",
"messages": [
{ "role": "user", "content": "The customer was charged twice and wants a refund." }
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "support_ticket",
"schema": {
"type": "object",
"properties": {
"category": { "type": "string", "enum": ["billing", "technical", "account"] },
"priority": { "type": "integer", "minimum": 1, "maximum": 3 },
"requires_human": { "type": "boolean" },
"summary": { "type": "string" }
},
"required": ["category", "priority", "requires_human", "summary"],
"additionalProperties": false
},
"strict": true
}
}
}
JSON thường là string tại choices[0].message.content và vẫn cần parse.
| Mục đích | Responses API | Chat Completions |
|---|---|---|
| Container | text.format |
response_format.json_schema |
| Type | text.format.type |
response_format.type |
| Name | text.format.name |
response_format.json_schema.name |
| Schema | text.format.schema |
response_format.json_schema.schema |
| Strict | text.format.strict |
response_format.json_schema.strict |
| Result | Output items / helper | choices[0].message.content |
Lớp tương thích của Modelflare chuyển đổi hai wrapper trên route OpenAI/Codex được hỗ trợ, nhưng không thể tạo Structured Outputs trong upstream model không có tính năng này. Với Raw Chat Completions Pass-through, contract của provider là Source of Truth.
Validate cấu trúc và ý nghĩa riêng biệt
{
"category": "billing",
"priority": 2,
"requires_human": true,
"summary": "Customer reports a duplicate charge and requests a refund."
}
Validate cấu trúc
JSON Schema validator kiểm tra required property, property ngoài dự kiến, type, enum và range. Ngay cả khi có Strict Adherence, validation trong ứng dụng vẫn bảo vệ trước route không hỗ trợ, lỗi tích hợp, truncation và thay đổi contract.
Validate ngữ nghĩa và nghiệp vụ
Schema không biết khách hàng có thật sự bị tính phí hai lần, priority: 2 có đúng hay ai được duyệt hoàn tiền. Hãy xem object là phân loại đề xuất, so sánh với dữ liệu có thẩm quyền, và thực thi quyền cùng financial limit bằng code xác định. JSON hợp lệ không được vượt qua authorization, billing hoặc security boundary.
Xử lý output không đầy đủ và ngoại lệ
Refusal
Kiểm tra Status và refusal representation trước khi tìm JSON. Từ chối vì an toàn không phải parsing error.
Truncation và Output Limit
Nếu generation dừng trước khi object đóng, Schema không thể khôi phục phần thiếu. Kiểm tra Completion Status và Stop Reason, đặt Output Limit đủ nhưng có giới hạn.
Keyword không được hỗ trợ
Bắt đầu với Objects, Arrays, Primitive Types, Enums, Required và Additional Properties rõ ràng. Xem tài liệu provider trước khi dùng References, recursion, Union phức tạp hoặc advanced validation.
Latency khi dùng Schema lần đầu
Một số provider preprocess và cache Schema mới. Tái sử dụng Schema ổn định, có version và đo First Use riêng với Steady State.
Model hoặc route không tương thích
Endpoint có thể nhận Chat Completions thường nhưng từ chối json_schema hoặc bỏ qua strict. Response 200 có JSON không chứng minh Strict Adherence. Phải thử input invalid và edge case.
Chạy ma trận tương thích
| Kiểm thử | Bằng chứng cần lưu |
|---|---|
| Required Object tối thiểu | Status, model, route, parsed object, validation result |
| Mọi Enum | Sinh và parse từng giá trị |
| Thiếu thông tin | Giá trị giới hạn hoặc yêu cầu làm rõ |
| Safety Input | Refusal format và xử lý ứng dụng |
| Output Limit thấp | Completion Status và truncation |
| Feature không hỗ trợ | Error rõ ràng hoặc constraint bị bỏ qua |
| Wrapper Responses và Chat | Object ứng dụng tương đương |
| Stable Schema lặp lại | First Use so với Steady State |
Giữ nguyên Schema, Prompt, Region, Streaming Mode và Output Limit, đồng thời ghi ngày kiểm thử.
Chọn endpoint sau khi thử workflow
Dùng Responses cho typed output items, streaming events hoặc Tool workflow rộng hơn. Dùng Chat Completions cho tích hợp dựa trên messages khi route hỗ trợ response_format. Xem Responses API và Chat Completions.
Dù chọn cách nào:
- giữ một Source of Truth JSON Schema có version;
- chỉ thay wrapper, không thay ý nghĩa;
- validate response hoàn tất;
- áp dụng business rule xác định sau cấu trúc;
- theo dõi parsing, refusal, truncation và compatibility failure riêng.
Bắt đầu migration với Hướng dẫn OpenAI-Compatible API, và dùng Hướng dẫn AI API Streaming cho stream không đầy đủ. Kiểm tra Models & Pricing, sau đó thử Structured Outputs trên route thực tế của API Key.
Structured Outputs thu hẹp phản hồi mô hình thành interface đáng tin cậy hơn, nhưng không thay thế xác minh sự thật, authorization hay billing logic. “OpenAI-compatible” vẫn là tuyên bố cần kiểm thử theo từng tính năng.