Saltar al contenido principal
En escenarios de salida estructurada, el JSON que devuelve el modelo a veces no se puede parsear: la salida se trunca por max_tokens, incluye comas finales o el contenido viene envuelto en un bloque de código Markdown. Por lo general, la aplicación tiene que escribir lógica de reintento o de reparación manual para estos casos. La reparación de salida estructurada (Structured Output Repair) es una capacidad a nivel de Key, desactivada por defecto. Una vez activada, para las solicitudes no en streaming que declaran una salida JSON estructurada, cuando el JSON devuelto por el modelo presenta errores de formato, la pasarela de AIHubMix lo repara automáticamente a un JSON válido y parseable antes de devolverlo; el código del cliente no necesita ningún cambio.
Este interruptor está desactivado por defecto; mientras no se active, todas las respuestas se devuelven tal cual. El interruptor se configura de forma independiente por Key y surte efecto de inmediato tras activarlo.

Ir a la página de gestión de Keys para configurarlo

Cree o edite una Key y active el interruptor «Reparación de salida estructurada» (Structured Output Repair).
Activar el interruptor de reparación de salida estructurada en el panel de edición de Key de AIHubMix

1. Condiciones de aplicación

La reparación solo se produce cuando se cumplen todas las condiciones siguientes:
  1. La Key usada en la solicitud tiene activada la «Reparación de salida estructurada».
  2. La solicitud es no en streaming (no tiene stream: true).
  3. La solicitud declara una salida JSON estructurada (los campos de declaración de cada protocolo se indican en la tabla siguiente).
  4. El contenido de texto devuelto por el modelo no se puede parsear como JSON.
ProtocoloEndpointCampo de declaración de salida estructurada
Chat Completions/v1/chat/completionsresponse_format.type con valor json_object o json_schema
Responses/v1/responsestext.format.type con valor json_schema o json_object
Claude Messages/v1/messagesoutput_config.format.type con valor json_schema
Gemini/gemini/v1beta/models/{model}:generateContentgenerationConfig.responseMimeType con valor application/json, o responseSchema definido
Cuando el contenido ya es JSON válido no se realiza ningún cambio y se devuelve tal cual.

2. Errores de formato reparables

Truncamiento de la salida que deja paréntesis / comillas sin cerrar (por ejemplo, finish_reason con valor length):
Antes
{"items": [{"name": "Widget", "price": 9.99}, {"name": "Gad
Después
{"items": [{"name": "Widget", "price": 9.99}, {"name": "Gad"}]}
Envoltura en un bloque de código Markdown:
Antes
```json
{"status": "ok", "count": 3}
```
Después
{"status": "ok", "count": 3}
Comas finales:
Antes
{"a": 1, "b": 2,}
Después
{"a": 1, "b": 2}
Comillas simples:
Antes
{'name': 'Widget'}
Después
{"name": "Widget"}
Nombres de clave sin comillas:
Antes
{name: "Widget", price: 9.99}
Después
{"name": "Widget", "price": 9.99}
Texto y JSON mezclados (JSON con texto explicativo antes o después):
Antes
Here is the JSON you requested: {"name": "Widget", "price": 9.99}
Después
{"name": "Widget", "price": 9.99}
La reparación adopta una estrategia conservadora:
  • La reparación solo completa o normaliza la sintaxis JSON; el contenido de los valores y las cadenas se mantiene tal cual, sin pérdida de precisión ni reescritura.
  • El resultado de la reparación debe ser un objeto o un array JSON válido y con una diferencia razonable respecto al original; si no se cumple alguna de estas condiciones, se descarta la reparación y se devuelve el contenido original tal cual.

3. Cómo saber si una respuesta ha sido reparada

Cuando se produce una reparación, hay dos señales programables / consultables:
  1. Cabecera de respuesta X-JSON-Repaired: true (esta cabecera no aparece cuando no ha habido reparación).
  2. Nota en el registro de llamadas: en la página de registros de llamadas, la columna de notas de la solicitud correspondiente muestra This request gateway automatically corrected the JSON format issue in the model output.
El consumo de tokens y la facturación se calculan según la salida original del modelo; la reparación no altera el resultado de la facturación.

4. Ejemplo completo

Tomando como ejemplo la generación de información de un producto, la solicitud usa json_schema para declarar la salida estructurada; con el interruptor activado, aunque la salida del modelo presente los errores de formato anteriores, el content obtenido se puede parsear directamente:
import json
import os
import requests

response = requests.post(
    "https://aihubmix.com/v1/chat/completions",
    headers={
        "Authorization": f"Bearer {os.environ['AIHUBMIX_API_KEY']}",
        "Content-Type": "application/json",
    },
    json={
        "model": "gpt-5.2",
        "messages": [
            {"role": "user", "content": "Generate a product listing for a wireless keyboard."}
        ],
        "response_format": {
            "type": "json_schema",
            "json_schema": {
                "name": "product",
                "schema": {
                    "type": "object",
                    "properties": {
                        "name": {"type": "string"},
                        "price": {"type": "number"},
                        "description": {"type": "string"},
                    },
                    "required": ["name", "price"],
                    "additionalProperties": False,
                },
            },
        },
    },
)

repaired = response.headers.get("X-JSON-Repaired") == "true"
product = json.loads(response.json()["choices"][0]["message"]["content"])
print(product, "repaired:", repaired)
const response = await fetch("https://aihubmix.com/v1/chat/completions", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.AIHUBMIX_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "gpt-5.2",
    messages: [
      { role: "user", content: "Generate a product listing for a wireless keyboard." },
    ],
    response_format: {
      type: "json_schema",
      json_schema: {
        name: "product",
        schema: {
          type: "object",
          properties: {
            name: { type: "string" },
            price: { type: "number" },
            description: { type: "string" },
          },
          required: ["name", "price"],
          additionalProperties: false,
        },
      },
    },
  }),
});

const repaired = response.headers.get("X-JSON-Repaired") === "true";
const data = await response.json();
const product = JSON.parse(data.choices[0].message.content);
console.log(product, "repaired:", repaired);
curl -sD - https://aihubmix.com/v1/chat/completions \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-5.2",
    "messages": [
      {"role": "user", "content": "Generate a product listing for a wireless keyboard."}
    ],
    "response_format": {
      "type": "json_schema",
      "json_schema": {
        "name": "product",
        "schema": {
          "type": "object",
          "properties": {
            "name": {"type": "string"},
            "price": {"type": "number"},
            "description": {"type": "string"}
          },
          "required": ["name", "price"],
          "additionalProperties": false
        }
      }
    }
  }'
Si quiere observar una reparación de forma activa, puede fijar max_tokens en un valor pequeño (por ejemplo, 80) para que la salida se trunque: el finish_reason de la respuesta será length, el content será el JSON válido ya reparado y la cabecera de respuesta incluirá X-JSON-Repaired: true.

5. Límites y notas

Las solicitudes en streaming (stream: true) no se reparan y se reenvían tal cual. Cuando necesite la capacidad de reparación, use solicitudes no en streaming.
La reparación garantiza que el contenido se pueda parsear como JSON; los datos que falten por truncamiento no se pueden recuperar. Se recomienda comprobar también finish_reason / stop_reason y, cuando la salida esté truncada, aumentar max_tokens según sea necesario y reintentar.
  • Reparación de sintaxis: si los nombres y tipos de los campos se ajustan a su schema es algo que la aplicación aún debe validar.
  • Los parámetros de llamada a herramientas quedan fuera del alcance de la reparación: el JSON de los parámetros de tool_calls / function_call no se repara; los parámetros de las herramientas deben ser siempre validados por la aplicación antes de su ejecución.
  • Las salidas con varios bloques de texto no se reparan: cuando la salida del modelo incluye varios bloques de texto (por ejemplo, cuando Gemini devuelve varios parts), se devuelve tal cual.
  • El contenido de razonamiento no se ve afectado: el texto de razonamiento como reasoning_content o la parte thought de Gemini no participa en la reparación.

Preguntas frecuentes (FAQ)

¿La reparación modifica los valores numéricos o el texto del contenido devuelto? No. La reparación solo completa o normaliza la sintaxis JSON (cierra paréntesis, elimina comas finales, normaliza comillas, retira las marcas de bloque de código); el contenido de los valores y las cadenas se mantiene tal cual lo produjo el modelo. ¿Activar el interruptor afecta a las solicitudes normales que no declaran salida estructurada? No. Las solicitudes que no declaran campos de salida estructurada como response_format, así como todas las solicitudes en streaming, devuelven su respuesta tal cual. ¿La reparación genera facturación adicional o altera el consumo de tokens? No. El consumo de tokens y la facturación se calculan según la salida original del modelo; el proceso de reparación no genera ningún coste adicional. ¿El JSON reparado cumple siempre el schema que definí? La reparación garantiza que el contenido se pueda parsear como JSON; que los nombres y tipos de los campos cumplan el schema depende de la propia salida del modelo, por lo que se recomienda que la aplicación conserve la validación del schema.