وقتی خروجی مدل را کد شما میخواند، نه آدم، متن آزاد به کار نمیآید. با response_format از مدل میخواهید پاسخ را JSON برگرداند؛
یا فقط «یک JSON معتبر» (json_object)، یا دقیقاً با طرحوارهای (Schema) که خودتان تعریف کردهاید (json_schema).
دو حالت#
| حالت | چه تضمینی میدهد | کجا کار میکند |
|---|---|---|
{"type": "json_schema", "strict": true} | پاسخ دقیقاً شکل طرحوارهٔ شماست: کلیدهای الزامی، نوعها، مقدارهای مجاز. | مدلهای تازهٔ OpenAI (سری gpt-4o، gpt-4.1 و gpt-5) و بسیاری از مدلهای OpenRouter که این قابلیت را دارند. |
{"type": "json_object"} | پاسخ یک JSON معتبر است؛ شکلش را باید در پرامپت بگویید و در کد بسنجید. | بیشتر مدلهایی که capabilities.json آنها true است، از جمله Gemini و DeepSeek. |
طرحوارهٔ دقیق با json_schema#
import json
schema = {
"type": "object",
"additionalProperties": False,
"required": ["name", "price", "tags"],
"properties": {
"name": {"type": "string"},
"price": {"type": "number", "description": "USD"},
"tags": {"type": "array", "items": {"type": "string"}},
},
}
reply = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "Extract product data from the text."},
{"role": "user", "content": "The new ergonomic keyboard costs 49.90 dollars; wireless, backlit."},
],
response_format={
"type": "json_schema",
"json_schema": {"name": "product", "strict": True, "schema": schema},
},
)
product = json.loads(reply.choices[0].message.content)
print(product["name"], product["price"])
قاعدههای strict: true که بیشترین خطا را میسازند:
- همهٔ کلیدهای
propertiesباید درrequiredهم باشند. برای کلید اختیاری، نوعش را["string", "null"]بگذارید. "additionalProperties": falseدر هر شیء لازم است.- بعضی ویژگیهای JSON Schema (مثل
formatیاminLengthدر بعضی مدلها) پشتیبانی نمیشوند؛ اعتبارسنجی دقیقتر را در کد انجام دهید.
با کلاسهای Pydantic و Zod#
SDK رسمی OpenAI طرحواره را از مدل دادهای شما میسازد و پاسخ را هم parse میکند؛ با گیسو هم همینطور کار میکند:
# The openai SDK can build the schema from a Pydantic model and parse the answer for you.
from pydantic import BaseModel
class Product(BaseModel):
name: str
price: float
tags: list[str]
# older SDK versions: client.beta.chat.completions.parse(...)
completion = client.chat.completions.parse(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "The new ergonomic keyboard costs 49.90 dollars; wireless, backlit."}],
response_format=Product,
)
product = completion.choices[0].message.parsed # a Product instance
import { z } from "zod";
import { zodResponseFormat } from "openai/helpers/zod";
const Product = z.object({ name: z.string(), price: z.number(), tags: z.array(z.string()) });
// older SDK versions: client.beta.chat.completions.parse(...)
const completion = await client.chat.completions.parse({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "The new ergonomic keyboard costs 49.90 dollars; wireless, backlit." }],
response_format: zodResponseFormat(Product, "product"),
});
console.log(completion.choices[0].message.parsed);
حالت json_object#
در این حالت باید کلمهٔ JSON و شکل خروجی را در پیامها بگویید؛ OpenAI بدون آن درخواست را رد میکند:
curl https://gisoo.pro/api/v1/chat/completions \
-H "Authorization: Bearer $GISOO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [
{"role": "system", "content": "Return JSON with keys sentiment (positive|neutral|negative) and reason."},
{"role": "user", "content": "The delivery was late but support fixed it fast."}
],
"response_format": {"type": "json_object"}
}'
همیشه اعتبارسنجی کنید#
حتی در حالت JSON هم ممکن است پاسخ ناقص برسد؛ مثلاً اگر به سقف max_tokens برسد (finish_reason: "length") JSON وسط کار بریده میشود.
پاسخ را parse و با طرحواره بسنجید و اگر معتبر نبود، یک بار دیگر با توضیح خطا بپرسید:
# pip install jsonschema — never trust an answer blindly, even in JSON mode
import json
from jsonschema import validate, ValidationError
def ask_json(messages, schema, retries=2):
for _ in range(retries + 1):
reply = client.chat.completions.create(
model="gemini-3.6-flash",
messages=messages,
response_format={"type": "json_object"},
)
try:
data = json.loads(reply.choices[0].message.content)
validate(data, schema)
return data
except (json.JSONDecodeError, ValidationError) as err:
messages = messages + [{"role": "user", "content": f"Your last answer was invalid ({err}). Reply with valid JSON only."}]
raise RuntimeError("no valid JSON")
اگر مدل باید کاری انجام دهد (جستوجو، ثبت، محاسبه)، فراخوانی ابزار مناسبتر است. اگر فقط دادهای را بیرون بکشد یا دستهبندی کند، خروجی ساختاریافته سادهتر و ارزانتر است.
پاسخ پرسشتان را پیدا نکردید؟
شناسهٔ درخواست (هدر X-Request-Id) را با پرسشتان در تیکت بفرستید تا دقیق بررسی کنیم.