Zum Inhalt springen
Strukturierte Ausgaben

Strukturierte Ausgaben

Fordern Sie die Antwort als JSON an: ein beliebiges JSON-Objekt oder JSON, das einem von Ihnen gesendeten Schema folgt. Verwenden Sie es, wenn ein Programm statt eines Menschen die Antwort liest.

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)

Das JSON ist der Text der Antwort, in choices[0].message.content:

200 JSON
{
  "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}
  }
}

Die Modi von response_format

response_format ist ein Feld von /v1/chat/completions. Ohne es ist die Antwort gewöhnlicher Text.

Modus Wert Was Sie erhalten
JSON-Objekt {"type": "json_object"} Die Antwort ist JSON ohne vorgeschriebene Form. Sagen Sie im Prompt, welche Schlüssel Sie wollen.
JSON-Schema {"type": "json_schema", "json_schema": {"name": "…", "schema": {…}}} Die Antwort folgt dem Schema, das Sie senden: seinen Schlüsseln, Typen und Pflichtfeldern.
Strict "strict": true Ein Feld von json_schema, kein dritter Modus. Es ist true, wenn Sie nicht false senden.
Feld Typ Standard Beschreibung Angewendet von
type string json_object oder json_schema. Innerhalb von response_format erforderlich. text wird akzeptiert und ergibt eine gewöhnliche Textantwort. Jedes Modell, das den Modus annimmt
json_schema.schema object Das JSON-Schema, dem die Antwort folgt. Senden Sie es, sobald type json_schema ist. Jedes Modell, das den Modus annimmt
json_schema.name string Eine Bezeichnung für das Schema, wie im OpenAI-Format. Gehostete Open-Weight-Modelle
json_schema.strict boolean true Ob die Antwort dem Schema genau folgen muss. Die Shannon-Modelle wenden jedes Schema als strict an. Gehostete Open-Weight-Modelle

Der JSON-Objekt-Modus braucht kein Schema. Nennen Sie die Schlüssel im Prompt:

Request-Body
{
  "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"}
}

Unterstützung pro Modell

Modell json_object json_schema
Jedes Shannon-Modell (shannon-*) Ja Ja
Gehostete Open-Weight-Modelle, außer den unten genannten Ja Ja
Laguna-S-2.1-W4A16-AUTOROUND-REAP — —
inkling-W4A16-AUTOROUND-REAP Ja —

GET /v1/models meldet dasselbe pro ID: capabilities.json_schema bei jedem Modell und capabilities.response_format bei den gehosteten Open-Weight-Modellen. Modelle & Preise

Unterstützte Schema-Schlüsselwörter

Was ein Modell von Ihrem Schema erhält, hängt vom Modell und vom Endpunkt ab:

Modelle /v1/chat/completions /v1/responses
Shannon-Modelle Die Schlüsselwort-Teilmenge unten, als strict angewendet. Das Schema so, wie Sie es senden, als strict angewendet.
Gehostete Open-Weight-Modelle Das Schema so, wie Sie es senden. strict ist true, wenn Sie es nicht senden. Das Schema so, wie Sie es senden. strict ist true, wenn Sie es nicht senden.

Die Schlüsselwort-Teilmenge der Shannon-Modelle bei /v1/chat/completions:

Schlüsselwort Wie es gelesen wird
Gelesene Schlüsselwörter type, format, title, description, nullable, enum, items, properties, required, minItems, maxItems, minimum, maximum, minLength, maxLength, pattern, anyOf, default
$ref Wird aus $defs oder definitions auf oberster Ebene des Schemas aufgelöst. Schlüsselwörter, die neben dem $ref stehen, wie description, bleiben erhalten. Ein Verweis ohne passende Definition wird als {"type": "object"} gelesen.
allOf Die Member werden zu einem Schema zusammengeführt. Setzen zwei Member dasselbe Schlüsselwort, zählt das spätere.
oneOf Wird als anyOf gelesen.
Schemas, die auf sich selbst verweisen Auf 24 Ebenen aufgelöst. Eine tiefere Ebene wird als {"type": "object"} gelesen.
Außerhalb der Teilmenge Jedes andere Schlüsselwort, zum Beispiel additionalProperties, const, multipleOf, uniqueItems, exclusiveMinimum, exclusiveMaximum, patternProperties, prefixItems, minProperties, maxProperties, not und if / then / else. Sie sind nicht Teil des Schemas, das das Modell erhält.

Bei /v1/responses: text.format

/v1/responses schreibt dieselbe Anfrage als text.format. Das Schema steht direkt in format, neben name und strict, nicht unter einem Schlüssel json_schema. Für den JSON-Objekt-Modus senden Sie {"format": {"type": "json_object"}}.

Request-Body
{
  "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"]
      }
    }
  }
}

Das JSON ist der text des output_text-Teils des Elements message:

200 JSON
{
  "output": [
    {
      "id": "msg_7e1d3c5b9a2f4d6e8c0b1a3f5e7d9c2b",
      "type": "message",
      "role": "assistant",
      "status": "completed",
      "content": [
        {
          "type": "output_text",
          "text": "{\"name\":\"John Doe\",\"age\":30,\"occupation\":\"engineer\"}",
          "annotations": []
        }
      ]
    }
  ]
}

Unterstützung pro Modell und Fehler sind dieselben wie bei /v1/chat/completions. Responses API

Bei /v1/messages: ein Tool als Schema

Das Messages-Format hat kein Feld für strukturierte Ausgabe. Für JSON von denselben Modellen rufen Sie /v1/chat/completions oder /v1/responses mit demselben Key auf.

Um bei /v1/messages zu bleiben, beschreiben Sie das Objekt als Tool: Legen Sie Ihr Schema in input_schema und nennen Sie das Tool in tool_choice. Der input des tool_use-Blocks ist dann Ihr Objekt, bereits geparst. Ein benanntes tool_choice wird von den gehosteten Open-Weight-Modellen angewendet.

Request-Body
{
  "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"}
}
200 JSON
{
  "stop_reason": "tool_use",
  "content": [
    {
      "type": "tool_use",
      "id": "toolu_4b8d2f6a1c3e4a5b9d7f0e2c4a6b8d1f",
      "name": "record_person",
      "input": {"name": "John Doe", "age": 30, "occupation": "engineer"}
    }
  ]
}

Prüfen Sie, ob stop_reason tool_use ist, bevor Sie den Block lesen. Funktionsaufrufe

Wie das JSON eintrifft

  • Das JSON ist ein String. Die Antwort enthält daneben kein geparstes Objekt: Lassen Sie Ihren JSON-Parser über message.content laufen.
  • Mit stream: true trifft das JSON in Stücken von delta.content ein. Fügen Sie sie zusammen und parsen Sie einmal, wenn der Stream beendet ist; ein einzelnes Stück ist kein gültiges JSON.
  • Ein gehostetes Open-Weight-Modell beantwortet eine Anfrage mit response_format ohne Reasoning-Text: reasoning_content ist null.

Prüfen, was Sie erhalten

Das Schema lenkt, wie das Modell schreibt. Die API vergleicht die fertige Antwort nicht mit Ihrem Schema, daher nimmt Ihr Code die abschließende Prüfung vor:

  • Parsen Sie innerhalb eines Fehler-Handlers, wie es das Beispiel ganz oben tut.
  • Validieren Sie das geparste Objekt mit demselben Schema in Ihrem eigenen Code, zum Beispiel mit einer JSON-Schema-Bibliothek, Pydantic oder Zod.
  • Eine lange Antwort kann enden, bevor das JSON vollständig ist. Eine nicht gestreamte Antwort meldet finish_reason nur als stop oder tool_calls, daher ist ein Parse-Fehler das Signal. Fragen Sie erneut oder verlangen Sie ein kleineres Objekt.

Fehler

Status Typ Nachricht Wann
400 invalid_request_error <id> does not accept response_format Das Modell nimmt keinen der beiden Modi an.
400 invalid_request_error <id> does not accept response_format json_schema; use json_object Das Modell nimmt json_object an, und Sie haben json_schema gesendet.
422 invalid_request_error Failed to deserialize the JSON body into the target type: … response_format hat keinen type oder ist kein JSON-Objekt.

Die beiden 400-Antworten werden gesendet, bevor etwas von Ihrem Guthaben abgebucht wird. Fehlerbehandlung