Skip to main content

Salida estructurada

Al realizar tareas de extracción de información o generación de datos estructurados, un modelo puede devolver texto adicional (como ```json ) que interrumpe el análisis posterior. Habilitar la salida estructurada garantiza que el modelo devuelva una cadena JSON válida. El modo JSON Schema también le permite un control preciso sobre la estructura y los tipos de salida, lo que elimina la necesidad de validaciones o reintentos adicionales.

Uso

La salida estructurada admite dos modos: JSON Object y JSON Schema.
  • Modo JSON Object: Garantiza que la salida sea una cadena JSON válida, pero no asegura una estructura específica. Uso:
    1. Establezca el parámetroresponse_format: En el cuerpo de la solicitud, establezca response_format en {"type": "json_object"}.
    2. Incluya la palabra clave JSON en su indicación: El mensaje del sistema o del usuario debe contener la palabra "JSON" (sin distinción entre mayúsculas y minúsculas); de lo contrario, la API devuelve: 'messages' must contain the word 'json' in some form, to use 'response_format' of type 'json_object'.
  • Modo JSON Schema: Asegura que la salida cumpla con una estructura especificada. Uso: establezca response_format en {"type": "json_schema", "json_schema": {..., "strict": true}}.
    No se requiere la palabra clave JSON en el prompt.
Los parámetros anteriores se aplican a la API Chat Completions. Si utiliza la API Responses, configure text.format en su lugar; el formato del valor es el mismo. Consulte los ejemplos a continuación. En el modo JSON Object, la API Responses también exige que el prompt contenga la palabra "JSON"; de lo contrario, se devuelve un error 400.
Comparación de características:

Función

Modo JSON Object

Modo JSON Schema

Genera JSON válido

Sí

Sí

Sigue estrictamente el esquema

No

Sí

Modelos compatibles

La mayoría de los modelos Qwen

Solo modelos qwen-plus seleccionados

Configuración de response_format

{"type": "json_object"}

{"type": "json_schema", "json_schema": {..., "strict": true}}

Requisito del prompt

Debe incluir "JSON"

Se recomienda describir explícitamente

Caso de uso

Salida JSON flexible

Validación precisa del esquema

Modelos admitidos

Los modelos etiquetados como "modo sin pensamiento" solo admiten salida estructurada en modo sin pensamiento.
  • JSON Object
  • JSON Schema
  • Qwen
  • Kimi
  • GLM
  • DeepSeek
  • Modelos de generación de texto
    • Qwen-Max: qwen4-max-preview (solo Token Plan), serie Qwen3.8-Max, serie Qwen3.7-Max
    • Qwen-Max (modo sin pensamiento): serie Qwen3.6-Max, serie Qwen3-Max, serie Qwen-Max
    • Qwen-Plus: serie Qwen3.7-Plus
    • Qwen-Plus (modo sin pensamiento): serie Qwen3.6-Plus, serie Qwen3.5-Plus, serie Qwen-Plus
    • Qwen-Flash: serie Qwen3.8-Flash, serie Qwen3.7-Flash
    • Qwen-Flash (modo sin pensamiento): serie Qwen3.6-Flash, serie Qwen3.5-Flash, serie Qwen-Flash
    • Qwen-Turbo (modo sin razonamiento): serie Qwen-Turbo
    • Qwen-Coder: serie Qwen3-Coder
    • Qwen-Long: serie Qwen-Long
    • Serie de código abierto Qwen3.8
    • Serie de código abierto Qwen3.6 (modo sin razonamiento)
    • Serie de código abierto Qwen3.5 (modo sin razonamiento)
    • Serie de código abierto Qwen3 (modo sin razonamiento)
    • Serie de código abierto Qwen3-Coder
    • Serie de código abierto Qwen2.5 (excluyendo modelos de matemáticas y codificación)
  • Modelos multimodales
    • Qwen-VL (modo sin pensamiento): serie Qwen3-VL-Plus, serie Qwen3-VL-Flash, serie Qwen-VL-Max (excluyendo las versiones más recientes y las instantáneas), serie Qwen-VL-Plus (excluyendo las versiones más recientes y las instantáneas)
    • Qwen-Omni: series Qwen3.8-Omni-Flash, Qwen3.5-Omni-Plus
    • Serie de código abierto Qwen3-VL (modo sin razonamiento)

Introducción

Este ejemplo extrae información estructurada de un perfil personal.
El modo JSON Object no garantiza nombres de clave ni tipos de campo estables. Los resultados pueden variar entre diferentes indicaciones o llamadas. Para imponer una estructura fija, utilice el modo JSON Schema.
Obtenga una clave de API y exporte la clave de API como variable de entorno. Si utiliza el SDK de OpenAI o el SDK de DashScope para realizar llamadas, instale el SDK.
  • API Chat Completions compatible con OpenAI
  • API de Responses compatible con OpenAI
  • DashScope
  • Python
  • Node.js
  • curl
from openai import OpenAI
import os

client = OpenAI(
    # API keys differ by region. If you haven't configured an environment variable, replace the next line with: api_key="sk-xxx"
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # If you use Beijing region models, replace base_url with: https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/compatible-mode/v1
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)

completion = client.chat.completions.create(
    model="qwen3.8-max",
    messages=[
        {
            "role": "system",
            "content": "Extract the user's name and age, and return them in JSON format"
        },
        {
            "role": "user",
            "content": "Hi everyone, my name is Alex Brown, I'm 34 years old, my email is alexbrown@example.com, and I enjoy playing basketball and traveling",
        },
    ],
    response_format={"type": "json_object"}
)

json_string = completion.choices[0].message.content
print(json_string)

Respuesta

{
  "Name": "Alex Brown",
  "Age": 34
}

Procesamiento de datos de imagen y video

Los modelos multimodales también admiten salida estructurada para imágenes y videos. Utilice el modo JSON para extraer datos estructurados de contenido visual, como valores de campos de recibos, ubicaciones de objetos en imágenes o eventos en video.
Para conocer los límites de archivos de imagen y video, consulte Comprensión de imágenes y videos .
  • Compatible con OpenAI
  • DashScope
  • Python
  • Node.js
  • curl
import os
from openai import OpenAI

client = OpenAI(
    # API keys differ by region. Get an API key: https://www.alibabacloud.com/help/model-studio/get-api-key
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # For Beijing region models, replace base_url with: https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/compatible-mode/v1
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1"
)

completion = client.chat.completions.create(
    model="qwen3-vl-plus",
    messages=[
        {
            "role": "system",
            "content": [{"type": "text", "text": "You are a helpful assistant."}],
        },
        {
            "role": "user",
            "content": [
                {
                    "type": "image_url",
                    "image_url": {
                        "url": "http://duguang-labelling.oss-cn-shanghai.aliyuncs.com/demo_ocr/receipt_zh_demo.jpg"
                    },
                },
                {"type": "text", "text": "Extract ticket (array type, including travel_date, trains, seat_num, arrival_site, price) and invoice information (array type, including invoice_code and invoice_number) from the image. Output a JSON containing both ticket and invoice arrays"},
            ],
        },
    ],
    response_format={"type": "json_object"}
)
json_string = completion.choices[0].message.content
print(json_string)

Respuesta

{
  "ticket": [
    {
      "travel_date": "2013-06-29",
      "trains": "stream",
      "seat_num": "371",
      "arrival_site": "Development Zone",
      "price": "8.00"
    }
  ],
  "invoice": [
    {
      "invoice_code": "221021325353",
      "invoice_number": "10283819"
    }
  ]
}

Optimizar prompts

Indicaciones ambiguas como "devolver información del usuario" conducen a estructuras de salida impredecibles. Para obtener resultados confiables, describa el esquema esperado en su indicación: especifique nombres de campos, tipos, estado obligatorio u opcional, restricciones de formato (como el formato de fecha) e incluya ejemplos.
  • Compatible con OpenAI
  • DashScope
  • Python
  • Node.js
from openai import OpenAI
import os
import json
import textwrap  # Handles indentation for multi-line strings to improve code readability

# Predefined example responses to show the model the expected output format
# Example 1: Complete response with all fields
example1_response = json.dumps(
    {
        "info": {"name": "Alice", "age": "25 years old", "email": "alice@example.com"},
        "hobby": ["singing"]
    },
    ensure_ascii=False
)
# Example 2: Response with multiple hobbies
example2_response = json.dumps(
    {
        "info": {"name": "Bob", "age": "30 years old", "email": "bob@example.com"},
        "hobby": ["dancing", "swimming"]
    },
    ensure_ascii=False
)
# Example 3: Response without hobby field (hobby is optional)
example3_response = json.dumps(
    {
        "info": {"name": "Dave", "age": "28 years old", "email": "dave@example.com"}
    },
    ensure_ascii=False
)
# Example 4: Another response without hobby field
example4_response = json.dumps(
    {
        "info": {"name": "Sun Qi", "age": "35 years old", "email": "sunqi@example.com"}
    },
    ensure_ascii=False
)

# Initialize the OpenAI client
client = OpenAI(
    # If you haven't configured an environment variable, replace the next line with: api_key="sk-xxx"
    # API keys differ by region. Get an API key: https://www.alibabacloud.com/help/model-studio/get-api-key
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # This is the Beijing region base_url. If you use Singapore region models, replace base_url with: https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1
    base_url="https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/compatible-mode/v1",
)

# dedent removes common leading whitespace from each line, allowing the string to be indented nicely in code without including extra spaces at runtime
system_prompt = textwrap.dedent(f"""\
    Extract personal information from the user input and output it in the specified JSON Schema format:

    [Output format requirements]
    The output must strictly follow this JSON structure:
    {{
      "info": {{
        "name": "string type, required field, user's name",
        "age": "string type, required field, format 'number years old', e.g., '25 years old'",
        "email": "string type, required field, standard email format, e.g., 'user@example.com'"
      }},
      "hobby": ["string array type, optional field, contains all user hobbies; omit entirely if not mentioned"]
    }}

    [Field extraction rules]
    1. name: Identify the user's name from the text, must extract
    2. age: Identify age information, convert to 'number years old' format, must extract
    3. email: Identify email address, keep original format, must extract
    4. hobby: Identify user hobbies, output as string array; omit hobby field entirely if hobbies are not mentioned

    [Reference examples]
    Example 1 (with hobby):
    Q: My name is Alice, I'm 25 years old, my email is alice@example.com, and my hobby is singing
    A: {example1_response}

    Example 2 (with multiple hobbies):
    Q: My name is Bob, I'm 30 years old, my email is bob@example.com, and I enjoy dancing and swimming
    A: {example2_response}

    Example 3 (without hobby):
    Q: My name is Dave, I'm 28 years old, and my email is dave@example.com
    A: {example3_response}

    Example 4 (without hobby):
    Q: I'm Sun Qi, 35 years old, and my email is sunqi@example.com
    A: {example4_response}

    Extract information and output JSON strictly according to the above format and rules. Do not include the hobby field if the user doesn't mention hobbies.\
""")

# Call the model API for information extraction
completion = client.chat.completions.create(
    model="qwen3.8-max",
    messages=[
        {
            "role": "system",
            "content": system_prompt
        },
        {
            "role": "user",
            "content": "Hi everyone, my name is Alex Brown, I'm 34 years old, my email is alexbrown@example.com, and I enjoy playing basketball and traveling",
        },
    ],
    response_format={"type": "json_object"},  # Specify JSON format return
)

# Extract and print the model-generated JSON result
json_string = completion.choices[0].message.content
print(json_string)

Respuesta

{
  "info": {
    "name": "Alex Brown",
    "age": "34 years old",
    "email": "alexbrown@example.com"
  },
  "hobby": ["Basketball", "Traveling"]
}

Obtención de salida estructurada

Establecer response_format type en json_object devuelve una cadena JSON válida, pero es posible que la estructura no coincida con sus expectativas; adecuado para escenarios simples. Para el análisis automatizado, la interoperabilidad de API y otros escenarios complejos que requieren restricciones de tipo estrictas, establezca type en json_schema para forzar al modelo a generar contenido que se ajuste estrictamente a un formato especificado. El formato de response_format y ejemplo:
Las entradas multimodales (imagen, video, audio, etc.) no admiten json_schema y recurrirán automáticamente a json_object; las restricciones del esquema no surtirán efecto.
{
  "type": "json_schema",
  "json_schema": {
    "name": "schema_name",       // Name of the schema
    "strict": true,              // Recommended: strictly follow the format
    "schema": {
      "type": "object",
      "properties": {...},       // Define field structure (see example on right)
      "required": [...],         // List of required fields
      "additionalProperties": false  // Recommended: only output defined fields
    }
  }
}
El ejemplo anterior obliga al modelo a generar un objeto JSON con dos campos obligatorios (name y age) y un campo opcional email.
Los modelos de la región de Singapore aún no son compatibles.

Cómo usar

Con el método parse del SDK de OpenAI, puede pasar directamente una clase Pydantic de Python o un objeto Zod de Node.js. El SDK lo convierte automáticamente a un JSON Schema, sin necesidad de escribir JSON complejo manualmente. Para el SDK de DashScope, construya el JSON Schema manualmente siguiendo el formato anterior.
  • API Chat Completions compatible con OpenAI
  • API de Responses compatible con OpenAI
  • DashScope

Python

from pydantic import BaseModel, Field
from openai import OpenAI
import os

client = OpenAI(
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # The following URL is for the Singapore region. Replace {WorkspaceId} with your actual Workspace ID. URLs vary by region.
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1"
)

class UserInfo(BaseModel):
    name: str = Field(description="User name")
    age: int = Field(description="User age in years")

completion = client.chat.completions.parse(
    model="qwen3.8-max",
    messages=[
        {"role": "system", "content": "Extract name and age information."},
        {"role": "user", "content": "My name is Liu Wu, I'm 25 years old."},
    ],
    response_format=UserInfo,
)

result = completion.choices[0].message.parsed
print(f"Name: {result.name}, Age: {result.age}")

Node.js

import OpenAI from "openai";
import { zodResponseFormat } from "openai/helpers/zod";
import { z } from "zod";

const openai = new OpenAI(
    {
        apiKey: process.env.DASHSCOPE_API_KEY,
        // The following URL is for the Singapore region. Replace {WorkspaceId} with your actual Workspace ID. URLs vary by region.
        baseURL: "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1"
    }
);

const UserInfo = z.object({
  name: z.string().describe("User name"),
  age: z.number().int().describe("User age in years"),
});

const completion = await openai.chat.completions.parse({
  model: "qwen3.8-max",
  messages: [
    { role: "system", content: "Extract name and age information." },
    { role: "user", content: "My name is Liu Wu, I'm 25 years old." },
  ],
  response_format: zodResponseFormat(UserInfo, "user_info"),
});

const userInfo = completion.choices[0].message.parsed;
console.log(`Name: ${userInfo.name}`);
console.log(`Age: ${userInfo.age}`);
Ejecutar el código produce la siguiente salida:
Name: Liu Wu, Age: 25

Guía de configuración

Siga estas directrices al utilizar JSON Schema para obtener una salida estructurada más confiable:
  • Declaración de campos obligatorios Se recomienda listar los campos obligatorios en el arreglo required. Los campos opcionales pueden omitirse, por ejemplo:
{
  "properties": {
    "name": {"type": "string"},
    "age": {"type": "integer"},
    "email": {"type": "string"}
  },
  "required": ["name", "age"]
}
Si la entrada no proporciona información de correo electrónico, la salida no contendrá este campo.
  • Implementación de campos opcionales Además de omitirlo de required, también puede permitir el tipo null:
{
  "properties": {
    "name": {"type": "string"},
    "email": {"type": ["string", "null"]}  // Can be string or null
  },
  "required": ["name", "email"]  // Both in required
}
La salida siempre incluirá el campo email, pero su valor puede ser null.
  • Configuración de additionalProperties Controla si se permiten campos adicionales no definidos en el esquema:
{
  "properties": {"name": {"type": "string"}},
  "required": ["name"],
  "additionalProperties": true  // Allow extra fields
}
Entrada de ejemplo: "I'm Zhang San, 25 years old"; salida: {"name": "Zhang San", "age": 25} (incluye el campo age no definido).

Valor

Comportamiento

Caso de uso

false

Solo generar campos definidos

Control preciso de la estructura

true

Permitir campos adicionales

Capturar más información

  • Palabras clave de JSON Schema admitidas A continuación se listan las palabras clave admitidas por el modo JSON Schema (modo estricto). Las palabras clave marcadas como "no admitidas" devuelven un error 400 al enviarse. Para consultar las definiciones completas de las palabras clave, véase la especificación de JSON Schema. Palabras clave comunes a nivel de esquema

    Palabra clave

    Descripción

    type

    Admite string, number, integer, boolean, null, array, object; también se admiten tipos de unión como ["string", "null"]

    enum / const

    enum restringe el valor a un conjunto de valores permitidos; const lo restringe a un único valor fijo

    $defs + $ref

    Se admiten referencias locales (por ejemplo, #/$defs/address); las referencias URL externas no causan errores, pero no tienen efecto

    anyOf / oneOf / allOf / not

    Se admiten restricciones de composición y condicionales. Tenga en cuenta que oneOf no garantiza estrictamente la semántica de exactamente uno

    if / then / else

    Se admiten esquemas condicionales, lo que permite reglas de validación dinámicas basadas en valores de campo

    title / description / default / examples

    Aceptados como sugerencias semánticas para el modelo; no se aplican como restricciones estrictas

    $schema / $id / $comment

    Identificadores de metadatos; aceptados sin afectar el comportamiento de validación

    deprecated / readOnly / writeOnly

    Palabras clave de anotación; aceptadas sin afectar el comportamiento de validación

    Palabras clave específicas de tipo

    Tipo

    Palabras clave admitidas

    Palabras clave no admitidas (error 400)

    string

    minLength, maxLength, pattern, format (por ejemplo, email, date), contentMediaType, contentEncoding

    -

    number / integer

    minimum, maximum, exclusiveMinimum, exclusiveMaximum

    multipleOf

    array

    items, prefixItems (modo tupla), minItems, maxItems, unevaluatedItems

    uniqueItems, contains, minContains, maxContains, additionalItems

    object

    properties, required, additionalProperties, minProperties, maxProperties, dependentRequired, dependentSchemas, unevaluatedProperties

    patternProperties, propertyNames

Puesta en marcha

  • Validar antes de pasar a procesos posteriores Al utilizar el modo JSON Object, valide la salida antes de pasarla a servicios posteriores. Utilice una biblioteca como jsonschema (Python), Ajv (JavaScript) o Everit (Java) para asegurarse de que cumple con el JSON Schema esperado, evitando fallos de análisis posteriores, pérdida de datos o interrupciones en la lógica de negocio debido a campos faltantes, errores de tipo o formatos mal formados. En caso de fallo, reintente la solicitud o utilice un modelo para reescribir la salida.
  • No configure max_tokens No configure max_tokens cuando la salida estructurada esté habilitada. Este parámetro limita el número de tokens de salida y su valor predeterminado es el máximo del modelo. Configurarlo puede truncar la cadena JSON a mitad de la generación, produciendo un JSON no válido que falla al analizarse.
  • Utilizar el SDK para generar esquemas Utilice el SDK para generar esquemas automáticamente. Esto evita errores derivados del mantenimiento manual y proporciona validación y análisis automáticos.
    Python
    from pydantic import BaseModel, Field
    from typing import Optional
    from openai import OpenAI
    import os
    
    client = OpenAI(
        api_key=os.getenv("DASHSCOPE_API_KEY"),
        # The following URL is for the Singapore region. Replace {WorkspaceId} with your actual Workspace ID. URLs vary by region.
        base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1"
    )
    class UserInfo(BaseModel):
        name: str = Field(description="User name")
        age: int = Field(description="User age")
        email: Optional[str] = None  # Optional field
    
    completion = client.chat.completions.parse(
        model="qwen3.8-max",
        messages=[
            {"role": "system", "content": "Extract name and age information."},
            {"role": "user", "content": "My name is Liu Wu, I'm 25 years old."},
        ],
        response_format=UserInfo  # Pass the Pydantic model directly
    )
    
    result = completion.choices[0].message.parsed  # Type-safe parsed result
    print(f"Name: {result.name}, Age: {result.age}")
    

Códigos de error

Si la llamada al modelo falla y devuelve un mensaje de error, consulte Códigos de error para su resolución.