مخرجات منظمة
اطلب الإجابة بصيغة JSON: أي كائن JSON، أو JSON يتبع مخططاً ترسله. استخدمه عندما يقرأ الرد برنامج لا شخص.
POST https://api.shannon-ai.com/v1/chat/completions
import json
from openai import OpenAI
client = OpenAI(api_key="YOUR_API_KEY", base_url="https://api.shannon-ai.com/v1")
response = client.chat.completions.create(
model="Kimi-K3-3BIT-REAP",
messages=[
{"role": "user", "content": "Extract the person: John Doe, 30 years old, engineer."}
],
response_format={
"type": "json_schema",
"json_schema": {
"name": "person",
"strict": True,
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"occupation": {"type": "string"},
},
"required": ["name", "age", "occupation"],
},
},
},
)
# The JSON arrives as text in message.content: parse it, then check it.
try:
person = json.loads(response.choices[0].message.content)
except json.JSONDecodeError:
person = None # ask again, or report the failure
print(person) import OpenAI from "openai";
const client = new OpenAI({ apiKey: "YOUR_API_KEY", baseURL: "https://api.shannon-ai.com/v1" });
const response = await client.chat.completions.create({
model: "Kimi-K3-3BIT-REAP",
messages: [
{ role: "user", content: "Extract the person: John Doe, 30 years old, engineer." },
],
response_format: {
type: "json_schema",
json_schema: {
name: "person",
strict: true,
schema: {
type: "object",
properties: {
name: { type: "string" },
age: { type: "integer" },
occupation: { type: "string" },
},
required: ["name", "age", "occupation"],
},
},
},
});
// The JSON arrives as text in message.content: parse it, then check it.
let person = null;
try {
person = JSON.parse(response.choices[0].message.content);
} catch {
// ask again, or report the failure
}
console.log(person); curl https://api.shannon-ai.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "Kimi-K3-3BIT-REAP",
"messages": [
{"role": "user", "content": "Extract the person: John Doe, 30 years old, engineer."}
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "person",
"strict": true,
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"occupation": {"type": "string"}
},
"required": ["name", "age", "occupation"]
}
}
}
}' JSON هو نص الإجابة، في choices[0].message.content:
{
"id": "chatcmpl-0c4e7a1b9d2f4e6a8b3c5d7e9f1a2b3c",
"object": "chat.completion",
"created": 1791590400,
"model": "Kimi-K3-3BIT-REAP",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "{\"name\":\"John Doe\",\"age\":30,\"occupation\":\"engineer\"}",
"reasoning_content": null
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 96,
"completion_tokens": 19,
"total_tokens": 115,
"prompt_tokens_details": {"cached_tokens": 0},
"completion_tokens_details": {"reasoning_tokens": 0}
}
} الأوضاع المتاحة في الحقل response_format
response_format حقل في /v1/chat/completions. وبدونه تكون الإجابة نصاً عادياً.
| الوضع | القيمة | ما تحصل عليه |
|---|---|---|
| كائن JSON | {"type": "json_object"} | الإجابة JSON دون شكل محدد. اذكر في المطالبة المفاتيح التي تريدها. |
| مخطط JSON | {"type": "json_schema", "json_schema": {"name": "…", "schema": {…}}} | تتبع الإجابة المخطط الذي ترسله: مفاتيحه وأنواعه وحقوله المطلوبة. |
| صارم (Strict) | "strict": true | حقل في json_schema، وليس وضعاً ثالثاً. قيمته true ما لم ترسل false. |
| الحقل | النوع | الافتراضي | الوصف | يطبّقه |
|---|---|---|---|---|
type | string | json_object أو json_schema. مطلوب داخل response_format. يُقبل text ويعطي إجابة نصية عادية. | كل نموذج يقبل هذا الوضع | |
json_schema.schema | object | مخطط JSON Schema الذي تتبعه الإجابة. أرسله كلما كانت قيمة type هي json_schema. | كل نموذج يقبل هذا الوضع | |
json_schema.name | string | تسمية للمخطط، كما في صيغة OpenAI. | النماذج المفتوحة الأوزان المستضافة | |
json_schema.strict | boolean | true | هل يجب أن تتبع الإجابة المخطط تماماً. تطبّق نماذج Shannon كل مخطط بصرامة (strict). | النماذج المفتوحة الأوزان المستضافة |
وضع كائن JSON لا يحتاج إلى مخطط. سمِّ المفاتيح في المطالبة:
{
"model": "shannon-3",
"messages": [
{
"role": "user",
"content": "Name the capital of France. Answer as JSON with the keys city and country."
}
],
"response_format": {"type": "json_object"}
} الدعم لكل نموذج
| النموذج | json_object | json_schema |
|---|---|---|
كل نموذج Shannon (shannon-*) | نعم | نعم |
| النماذج المفتوحة الأوزان المستضافة، عدا المذكورة أدناه | نعم | نعم |
Laguna-S-2.1-W4A16-AUTOROUND-REAP | — | — |
inkling-W4A16-AUTOROUND-REAP | نعم | — |
يبلّغ GET /v1/models بالشيء نفسه لكل معرّف: capabilities.json_schema في كل نموذج، وcapabilities.response_format في النماذج المفتوحة الأوزان المستضافة. النماذج والأسعار
كلمات المخطط المفتاحية المدعومة
ما يتلقاه النموذج من مخططك يعتمد على النموذج وعلى نقطة النهاية:
| النماذج | /v1/chat/completions | /v1/responses |
|---|---|---|
| نماذج Shannon | مجموعة الكلمات المفتاحية الفرعية أدناه، وتُطبَّق بصرامة (strict). | المخطط كما ترسله، ويُطبَّق بصرامة (strict). |
| النماذج المفتوحة الأوزان المستضافة | المخطط كما ترسله. وتكون strict هي true ما لم ترسلها. | المخطط كما ترسله. وتكون strict هي true ما لم ترسلها. |
المجموعة الفرعية من الكلمات المفتاحية في نماذج Shannon على /v1/chat/completions:
| الكلمة المفتاحية | كيف يُقرأ |
|---|---|
| الكلمات المفتاحية المقروءة | type, format, title, description, nullable, enum, items, properties, required, minItems, maxItems, minimum, maximum, minLength, maxLength, pattern, anyOf, default |
$ref | يُحَلّ من $defs أو definitions في المستوى الأعلى من المخطط. وتُحفظ الكلمات المفتاحية المكتوبة بجانب $ref، مثل description. والإشارة التي لا تعريف مطابقاً لها تُقرأ كـ {"type": "object"}. |
allOf | تُدمج الأعضاء في مخطط واحد. وعندما يضبط عضوان الكلمة المفتاحية نفسها، يُعتمد الأخير. |
oneOf | تُقرأ كـ anyOf. |
| المخططات التي تشير إلى نفسها | تُوسَّع إلى 24 مستوى. والمستوى الأعمق يُقرأ كـ {"type": "object"}. |
| خارج المجموعة الفرعية | كل كلمة مفتاحية أخرى، مثل additionalProperties وconst وmultipleOf وuniqueItems وexclusiveMinimum وexclusiveMaximum وpatternProperties وprefixItems وminProperties وmaxProperties وnot وif / then / else. وهذه ليست جزءاً من المخطط الذي يتلقاه النموذج. |
على نقطة النهاية /v1/responses: الحقل text.format
يكتب /v1/responses الطلب نفسه على شكل text.format. ويوجد المخطط مباشرة في format، بجانب name وstrict، لا تحت المفتاح json_schema. ولوضع كائن JSON أرسل {"format": {"type": "json_object"}}.
{
"model": "Kimi-K3-3BIT-REAP",
"input": "Extract the person: John Doe, 30 years old, engineer.",
"text": {
"format": {
"type": "json_schema",
"name": "person",
"strict": true,
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"occupation": {"type": "string"}
},
"required": ["name", "age", "occupation"]
}
}
}
} JSON هو text في جزء output_text من عنصر message:
{
"output": [
{
"id": "msg_7e1d3c5b9a2f4d6e8c0b1a3f5e7d9c2b",
"type": "message",
"role": "assistant",
"status": "completed",
"content": [
{
"type": "output_text",
"text": "{\"name\":\"John Doe\",\"age\":30,\"occupation\":\"engineer\"}",
"annotations": []
}
]
}
]
} الدعم لكل نموذج والأخطاء هي نفسها في /v1/chat/completions. Responses API
على /v1/messages: أداة بوصفها المخطط
ليس في صيغة Messages حقل للمخرجات المنظمة. وللحصول على JSON من النماذج نفسها، استدعِ /v1/chat/completions أو /v1/responses بالمفتاح نفسه.
للبقاء على /v1/messages، صِف الكائن كأداة: ضع مخططك في input_schema وسمِّ الأداة في tool_choice. عندئذٍ يكون input في كتلة tool_use هو كائنك، محلَّلاً أصلاً. وتطبّق النماذج المفتوحة الأوزان المستضافة tool_choice المسمّى.
{
"model": "Kimi-K3-3BIT-REAP",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "Extract the person: John Doe, 30 years old, engineer."
}
],
"tools": [
{
"name": "record_person",
"description": "Record the extracted person.",
"input_schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"occupation": {"type": "string"}
},
"required": ["name", "age", "occupation"]
}
}
],
"tool_choice": {"type": "tool", "name": "record_person"}
} {
"stop_reason": "tool_use",
"content": [
{
"type": "tool_use",
"id": "toolu_4b8d2f6a1c3e4a5b9d7f0e2c4a6b8d1f",
"name": "record_person",
"input": {"name": "John Doe", "age": 30, "occupation": "engineer"}
}
]
} تحقق من أن stop_reason هو tool_use قبل أن تقرأ الكتلة. استدعاء الدوال
كيف يصل JSON
- JSON سلسلة نصية. ولا يوجد كائن محلَّل بجانبها في الرد: شغّل محلل JSON لديك على
message.content. - مع
stream: trueيصل JSON في قطعdelta.content. اجمعها وحلّلها بعد انتهاء البث؛ فالقطعة وحدها ليست JSON صالحاً. - يجيب النموذج المفتوح الأوزان المستضاف عن طلب
response_formatدون نص استدلال: فتكونreasoning_contentهيnull.
تحقق مما تتلقاه
يوجّه المخطط طريقة كتابة النموذج. ولا تقارن API الإجابة النهائية بمخططك، ولذلك يجري كودك الفحص الأخير:
- حلّل داخل معالج أخطاء، كما يفعل المثال في الأعلى.
- تحقق من الكائن المحلَّل بالمخطط نفسه في كودك، مثلاً بمكتبة JSON Schema أو Pydantic أو Zod.
- قد تنتهي الإجابة الطويلة قبل اكتمال JSON. والرد غير المبثوث لا يبلّغ عن
finish_reasonإلا بالقيمتينstopأوtool_calls، ولذلك فإن خطأ التحليل هو الإشارة. اطلب مجدداً، أو اطلب كائناً أصغر.
الأخطاء
| الحالة | النوع | الرسالة | متى |
|---|---|---|---|
400 | invalid_request_error | <id> does not accept response_format | النموذج لا يقبل أياً من الوضعين. |
400 | invalid_request_error | <id> does not accept response_format json_schema; use json_object | النموذج يقبل json_object وقد أرسلت json_schema. |
422 | invalid_request_error | Failed to deserialize the JSON body into the target type: … | ليس في response_format حقل type، أو أنه ليس كائن JSON. |
يُرسَل الردّان 400 قبل أن يُخصم أي شيء من رصيدك. معالجة الأخطاء