Skip to Content
TutorialsStructured Outputs

Structured Outputs

Structured Outputs allow the model to generate data that strictly conforms to JSON Schema, rather than free text. This makes output results more controllable and easier to parse, especially suitable for scenarios like data extraction, API response formatting, and configuration generation.


Core Concepts

FeatureDescriptionUse Cases
JSON Schema ConstraintDefine output structure through SchemaData extraction, API responses
Strict ModeForce model to follow Schema, reject invalid outputProduction environment, automated processes
Nested Structure SupportSupport objects, arrays, nested objectsComplex data structures
Type SafetyAutomatically verify field types (string, number, boolean, etc.)Type-sensitive applications

Quick Selection Guide:

  • Need structured data: Use response_format to specify JSON Schema
  • Only need valid JSON: Use json_object mode (no Schema required)
  • Complex data extraction: Use together with tool calling (Function Calling)

Why Use Structured Outputs?

Pain Points of Traditional Methods

# Traditional method: Let model generate freely, then manually parse response = client.chat.completions.create( model="Ling-2.6-flash", messages=[{ "role": "user", "content": "Extract name and age from the following text: Zhang San, 25 years old" }] ) # Output might be: # "Name: Zhang San, Age: 25" # "{'name': 'Zhang San', 'age': 25}" # "According to the text, the name is Zhang San, age is 25 years old" # Requires complex regex or LLM to parse again, unreliable

Advantages of Structured Outputs

# Structured outputs: Get data conforming to Schema directly response = client.chat.completions.create( model="Ling-2.6-flash", messages=[{ "role": "user", "content": "Extract name and age from the following text: Zhang San, 25 years old" }], response_format={ "type": "json_schema", "json_schema": { "name": "person_info", "schema": { "type": "object", "properties": { "name": {"type": "string"}, "age": {"type": "integer"} }, "required": ["name", "age"] } } } ) # Output strictly is: # {"name": "Zhang San", "age": 25} # Can be directly parsed as Python object import json data = json.loads(response.choices[0].message.content) print(data["name"]) # Zhang San

Quick Start

Basic Usage: JSON Object Mode

If you only need to ensure output is valid JSON, without strictly constraining structure:

from openai import OpenAI client = OpenAI( base_url="https://api.ant-ling.com/v1", api_key="YOUR_API_KEY" ) response = client.chat.completions.create( model="Ling-2.6-flash", messages=[{ "role": "user", "content": "List three renewable energy sources, return as JSON array" }], response_format={"type": "json_object"} ) import json data = json.loads(response.choices[0].message.content) print(data) # Output: ["solar", "wind", "hydro"] or similar valid JSON

Advanced Usage: JSON Schema Strict Mode

Precisely control output structure through JSON Schema:

from openai import OpenAI client = OpenAI( base_url="https://api.ant-ling.com/v1", api_key="YOUR_API_KEY" ) response = client.chat.completions.create( model="Ling-2.6-flash", messages=[{ "role": "user", "content": """Analyze the following product review: "This phone has great battery life, but the price is a bit expensive." Extract sentiment tendency and key points.""" }], response_format={ "type": "json_schema", "json_schema": { "name": "sentiment_analysis", "schema": { "type": "object", "properties": { "overall_sentiment": { "type": "string", "enum": ["positive", "neutral", "negative"], "description": "Overall sentiment tendency" }, "key_points": { "type": "array", "items": { "type": "object", "properties": { "aspect": { "type": "string", "description": "Aspect of review" }, "sentiment": { "type": "string", "enum": ["positive", "neutral", "negative"], "description": "Sentiment for this aspect" }, "mention": { "type": "string", "description": "Original mention" } }, "required": ["aspect", "sentiment", "mention"] } } }, "required": ["overall_sentiment", "key_points"] } } } ) import json result = json.loads(response.choices[0].message.content) print(json.dumps(result, ensure_ascii=False, indent=2))

Example Output:

{ "overall_sentiment": "neutral", "key_points": [ { "aspect": "battery life", "sentiment": "positive", "mention": "battery life is great" }, { "aspect": "price", "sentiment": "negative", "mention": "price is a bit expensive" } ] }

JSON Schema Details

Supported Types

JSON Schema TypeDescriptionExample
stringString"name": {"type": "string"}
integerInteger"age": {"type": "integer"}
numberNumber (including decimals)"price": {"type": "number"}
booleanBoolean"active": {"type": "boolean"}
arrayArray"tags": {"type": "array", "items": {"type": "string"}}
objectObject"address": {"type": "object", "properties": {...}}

Common Constraints

{ "type": "object", "properties": { "username": { "type": "string", "minLength": 3, "maxLength": 20, "description": "Username, 3-20 characters" }, "email": { "type": "string", "format": "email", "description": "Email address" }, "age": { "type": "integer", "minimum": 0, "maximum": 150, "description": "Age" }, "role": { "type": "string", "enum": ["user", "admin", "guest"], "description": "User role" }, "tags": { "type": "array", "items": { "type": "string" }, "maxItems": 10, "description": "Tag list" } }, "required": ["username", "email"] }

Nested Structures

{ "type": "object", "properties": { "company": { "type": "object", "properties": { "name": { "type": "string" }, "address": { "type": "object", "properties": { "city": { "type": "string" }, "country": { "type": "string" } }, "required": ["city", "country"] } }, "required": ["name"] }, "employees": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "department": { "type": "string" } }, "required": ["name"] } } }, "required": ["company"] }

Typical Use Cases

1. Data Extraction and Parsing

Extract structured information from unstructured text:

schema = { "name": "invoice_extraction", "schema": { "type": "object", "properties": { "invoice_number": {"type": "string"}, "date": {"type": "string", "format": "date"}, "vendor": {"type": "string"}, "items": { "type": "array", "items": { "type": "object", "properties": { "description": {"type": "string"}, "quantity": {"type": "integer"}, "unit_price": {"type": "number"} } } }, "total_amount": {"type": "number"} }, "required": ["invoice_number", "date", "total_amount"] } }

2. API Response Formatting

Ensure model output conforms to the format expected by backend API:

schema = { "name": "api_response", "schema": { "type": "object", "properties": { "status": { "type": "string", "enum": ["success", "error"] }, "data": {"type": "object"}, "message": {"type": "string"}, "timestamp": {"type": "string", "format": "date-time"} }, "required": ["status"] } }

3. Configuration Generation

Generate configuration files conforming to specific format:

schema = { "name": "app_config", "schema": { "type": "object", "properties": { "app_name": {"type": "string"}, "version": {"type": "string"}, "features": { "type": "object", "properties": { "dark_mode": {"type": "boolean"}, "notifications": {"type": "boolean"}, "max_items": {"type": "integer", "minimum": 1} } } }, "required": ["app_name", "version"] } }

4. Multi-step Reasoning Results

Decompose complex reasoning process into structured steps:

schema = { "name": "math_solution", "schema": { "type": "object", "properties": { "problem": {"type": "string"}, "steps": { "type": "array", "items": { "type": "object", "properties": { "step_number": {"type": "integer"}, "description": {"type": "string"}, "calculation": {"type": "string"} } } }, "final_answer": {"type": "string"}, "verification": {"type": "string"} }, "required": ["problem", "steps", "final_answer"] } }

Comparison with Tool Calling

FeatureStructured OutputsTool Calling (Function Calling)
Main PurposeFormat model responseLet model call external functions
Execution TimeOnly format outputMay trigger actual function execution
Interaction ModeSingle responseMay have multiple rounds of interaction
Use CasesData extraction, formattingNeed external data or operations
Schema Definitionresponse_formattools parameter

Selection Advice:

  • Only need structured data → Use Structured Outputs
  • Need to call APIs, query databases, etc. → Use Tool Calling

Best Practices

1. Provide Clear Descriptions

Add description to fields in Schema to help model understand intent:

{ "properties": { "confidence": { "type": "number", "minimum": 0, "maximum": 1, "description": "Confidence score, 0 means completely uncertain, 1 means completely certain" } } }

2. Use Required Wisely

Mark required fields clearly, but don’t over-constrain:

{ "properties": { "name": { "type": "string" }, "email": { "type": "string" }, "phone": { "type": "string" } }, "required": ["name"] // phone and email are optional, adapt to different scenarios }

3. Use enum to Limit Values

When fields have fixed options, use enum to improve accuracy:

{ "sentiment": { "type": "string", "enum": ["positive", "neutral", "negative"] } }

4. Handle Large Arrays

For arrays that might be long, set reasonable limits:

{ "items": { "type": "array", "items": { "type": "string" }, "maxItems": 100, "description": "Return at most 100 items" } }

5. Combine with System Prompts

Use system prompts to further guide the model:

messages=[ { "role": "system", "content": "You are a data extraction assistant. Please extract key information from the text provided by the user, strictly return in the specified JSON Schema format." }, { "role": "user", "content": "Extract the following resume information: ..." } ]

Common Questions

Q1: What if the model doesn’t follow Schema?

  • Check if Schema syntax is correct (can use online JSON Schema validation tools)
  • Ensure Schema is not too complex, split into multiple simple Schemas if needed
  • Clearly state output format requirements in prompts
  • Use more powerful models (e.g., Ling-2.6-1T/Ling-2.6-flash)

Q2: How to handle optional fields?

Don’t set all fields as required, for optional fields:

{ "properties": { "required_field": { "type": "string" }, "optional_field": { "type": ["string", "null"], "description": "Optional field, return null when no value" } }, "required": ["required_field"] }

Q3: How complex can Schema be?

It is recommended to follow these principles:

  • Nested levels not exceeding 3-4
  • Array item structures remain consistent
  • Total number of fields controlled within 20
  • Too complex Schema may affect model performance

Q4: Does streaming output support structured outputs?

Yes. After enabling streaming, the model will gradually generate JSON content:

response = client.chat.completions.create( model="Ling-2.6-flash", messages=messages, response_format={"type": "json_schema", "json_schema": schema}, stream=True # Enable streaming ) # Need to accumulate all chunks before parsing JSON content = "" for chunk in response: if chunk.choices[0].delta.content: content += chunk.choices[0].delta.content # Parse after stream ends data = json.loads(content)

Q5: Does structured output increase latency?

Structured outputs require additional validation and constraint processing, may have slight latency increase. It is recommended to:

  • For scenarios with high real-time requirements, weigh the necessity of using structured outputs
  • Use simpler Schema to reduce processing time
  • Consider caching results for common queries

  • Streaming - Get structured responses in real-time
  • Quickstart - Complete your first API call in 5 minutes
  • Model Selection - Learn about characteristics of Ling, Ring, Ming models

JSON Schema Reference

For more JSON Schema syntax and advanced features, please refer to JSON Schema Official Documentation .

Was this page helpful?
Last updated on