Output strutturati
Richiedi la risposta come JSON: un qualsiasi oggetto JSON, oppure JSON conforme a uno schema che invii. Usalo quando a leggere la risposta è un programma, non una persona.
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"]
}
}
}
}' Il JSON è il testo della risposta, in 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}
}
} Le modalità di response_format
response_format è un campo di /v1/chat/completions. Senza di esso la risposta è un normale testo.
| Modalità | Valore | Cosa ottieni |
|---|---|---|
| Oggetto JSON | {"type": "json_object"} | La risposta è JSON senza una forma prescritta. Indica nel prompt quali chiavi vuoi. |
| Schema JSON | {"type": "json_schema", "json_schema": {"name": "…", "schema": {…}}} | La risposta segue lo schema che invii: le sue chiavi, i tipi e i campi obbligatori. |
| Strict | "strict": true | Un campo di json_schema, non una terza modalità. È true a meno che tu non invii false. |
| Campo | Tipo | Default | Descrizione | Applicato da |
|---|---|---|---|---|
type | string | json_object o json_schema. Obbligatorio dentro response_format. text è accettato e dà una normale risposta di testo. | Ogni modello che accetta la modalità | |
json_schema.schema | object | Il JSON Schema che la risposta segue. Invialo ogni volta che type è json_schema. | Ogni modello che accetta la modalità | |
json_schema.name | string | Un'etichetta per lo schema, come nel formato OpenAI. | Modelli open-weight ospitati | |
json_schema.strict | boolean | true | Indica se la risposta deve seguire esattamente lo schema. I modelli Shannon applicano ogni schema come strict. | Modelli open-weight ospitati |
La modalità oggetto JSON non richiede uno schema. Indica le chiavi nel prompt:
{
"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"}
} Supporto per modello
| Modello | json_object | json_schema |
|---|---|---|
Ogni modello Shannon (shannon-*) | Sì | Sì |
| Modelli open-weight ospitati, tranne quelli indicati qui sotto | Sì | Sì |
Laguna-S-2.1-W4A16-AUTOROUND-REAP | — | — |
inkling-W4A16-AUTOROUND-REAP | Sì | — |
GET /v1/models riporta lo stesso per ogni id: capabilities.json_schema su ogni modello, e capabilities.response_format sui modelli open-weight ospitati. Modelli e prezzi
Parole chiave di schema supportate
Ciò che un modello riceve del tuo schema dipende dal modello e dall'endpoint:
| Modelli | /v1/chat/completions | /v1/responses |
|---|---|---|
| Modelli Shannon | Il sottoinsieme di parole chiave qui sotto, applicato come strict. | Lo schema come lo invii, applicato come strict. |
| Modelli open-weight ospitati | Lo schema come lo invii. strict è true a meno che tu non lo invii. | Lo schema come lo invii. strict è true a meno che tu non lo invii. |
Il sottoinsieme di parole chiave dei modelli Shannon su /v1/chat/completions:
| Parola chiave | Come viene letto |
|---|---|
| Parole chiave lette | type, format, title, description, nullable, enum, items, properties, required, minItems, maxItems, minimum, maximum, minLength, maxLength, pattern, anyOf, default |
$ref | Risolto da $defs o definitions al livello superiore dello schema. Le parole chiave scritte accanto a $ref, come description, vengono mantenute. Un riferimento senza una definizione corrispondente viene letto come {"type": "object"}. |
allOf | I membri vengono fusi in un unico schema. Dove due membri impostano la stessa parola chiave, conta il successivo. |
oneOf | Letto come anyOf. |
| Schemi che si riferiscono a sé stessi | Espansi fino a 24 livelli. Un livello più profondo viene letto come {"type": "object"}. |
| Fuori dal sottoinsieme | Ogni altra parola chiave, per esempio additionalProperties, const, multipleOf, uniqueItems, exclusiveMinimum, exclusiveMaximum, patternProperties, prefixItems, minProperties, maxProperties, not e if / then / else. Non fanno parte dello schema che il modello riceve. |
Su /v1/responses: text.format
/v1/responses scrive la stessa richiesta come text.format. Lo schema sta direttamente in format, accanto a name e strict, non sotto una chiave json_schema. Per la modalità oggetto JSON invia {"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"]
}
}
}
} Il JSON è il text della parte output_text dell'elemento message:
{
"output": [
{
"id": "msg_7e1d3c5b9a2f4d6e8c0b1a3f5e7d9c2b",
"type": "message",
"role": "assistant",
"status": "completed",
"content": [
{
"type": "output_text",
"text": "{\"name\":\"John Doe\",\"age\":30,\"occupation\":\"engineer\"}",
"annotations": []
}
]
}
]
} Il supporto per modello e gli errori sono gli stessi di /v1/chat/completions. Responses API
Su /v1/messages: un tool come schema
Il formato Messages non ha un campo per l'output strutturato. Per ottenere JSON dagli stessi modelli, chiama /v1/chat/completions o /v1/responses con la stessa chiave.
Per restare su /v1/messages, descrivi l'oggetto come tool: metti il tuo schema in input_schema e indica il tool in tool_choice. L'input del blocco tool_use è allora il tuo oggetto, già analizzato. Un tool_choice indicato per nome viene applicato dai modelli open-weight ospitati.
{
"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"}
}
]
} Verifica che stop_reason sia tool_use prima di leggere il blocco. Chiamata di funzioni
Come arriva il JSON
- Il JSON è una stringa. La risposta non ha accanto un oggetto già analizzato: esegui il tuo parser JSON su
message.content. - Con
stream: trueil JSON arriva a pezzi indelta.content. Uniscili e analizza una volta sola a stream terminato; un pezzo da solo non è JSON valido. - Un modello open-weight ospitato risponde a una richiesta con
response_formatsenza testo di ragionamento:reasoning_contentènull.
Controlla ciò che ricevi
Lo schema guida il modo in cui il modello scrive. L'API non confronta la risposta finita con il tuo schema, quindi il controllo finale spetta al tuo codice:
- Esegui il parsing dentro un gestore di errori, come fa l'esempio in cima.
- Convalida l'oggetto analizzato con lo stesso schema nel tuo codice, per esempio con una libreria JSON Schema, Pydantic o Zod.
- Una risposta lunga può terminare prima che il JSON sia completo. Una risposta senza streaming riporta
finish_reasonsolo comestopotool_calls, quindi il segnale è un errore di parsing. Richiedi di nuovo, oppure chiedi un oggetto più piccolo.
Errori
| Stato | Tipo | Messaggio | Quando |
|---|---|---|---|
400 | invalid_request_error | <id> does not accept response_format | Il modello non accetta nessuna delle due modalità. |
400 | invalid_request_error | <id> does not accept response_format json_schema; use json_object | Il modello accetta json_object e hai inviato json_schema. |
422 | invalid_request_error | Failed to deserialize the JSON body into the target type: … | response_format non ha type, oppure non è un oggetto JSON. |
Le due risposte 400 vengono inviate prima che venga prelevato qualcosa dal tuo saldo. Gestione errori