Comparación de salida estructurada entre los principales proveedores de LLM: OpenAI, Gemini, Anthropic, Mistral y AWS Bedrock
Las APIs ligeramente diferentes requieren un enfoque especial.
Aquí tienes una comparación lado a lado del soporte de salida estructurada (obtención de JSON confiable) en los principales proveedores de LLM, junto con ejemplos mínimos en Python.

Ya hemos visto cómo solicitar salida estructurada del LLM alojado en Ollama. Una vez que el JSON está en la red, validación de salida estructurada de LLM en Python que es robusta recorre el análisis, las comprobaciones de Pydantic, los reintentos y las pruebas en tu servicio. Aquí revisamos cómo solicitar lo mismo a otros proveedores.
Matriz TL;DR
| Proveedor | Modo “JSON” nativo | Aplicación de Esquema JSON | Parámetro típico | Notas |
|---|---|---|---|---|
| OpenAI | Sí | Sí (de primera clase) | response_format={"type":"json_schema", ...} |
Funciona a través de la API de Respuestas o Chat Completions; también puede hacer llamadas a funciones. |
| Google Gemini | Sí | Sí (de primera clase) | response_schema= + response_mime_type="application/json" |
Devuelve JSON estrictamente validado cuando se establece el esquema. |
| Anthropic (Claude) | Indirecto | Sí (vía Uso de Herramientas con esquema JSON) | tools=[{input_schema=...}] + tool_choice |
Fuerza al modelo a “llamar” a tu herramienta definida por esquema; devuelve argumentos con forma de esquema. |
| Mistral | Sí | Parcial (solo JSON; sin esquema del lado del servidor) | response_format={"type":"json_object"} |
Garantiza JSON, pero validas contra tu esquema en el lado del cliente. |
| AWS Bedrock (plataforma) | Varía según el modelo | Sí (vía esquema de Herramienta/Converse) | toolConfig.tools[].toolSpec.inputSchema |
La API Converse de Bedrock valida la entrada de la herramienta contra un esquema JSON. |
Salida Estructurada de LLM: Información General
La salida estructurada de los LLM se refiere a la capacidad de los grandes modelos de lenguaje (LLMs) para generar respuestas que se adhieran estrictamente a un formato o estructura predefinida y específica, en lugar de producir texto libre. Esta salida estructurada puede estar en formatos como JSON, XML, tablas o plantillas, lo que hace que los datos sean legibles por máquina, consistentes y fácilmente analizables por software para su uso en diversas aplicaciones.
Las salidas estructuradas difieren de las salidas tradicionales de los LLM, que típicamente generan texto de lenguaje natural abierto. En cambio, las salidas estructuradas imponen un esquema o formato, como objetos JSON con claves y tipos de valores definidos, o clases específicas en la salida (por ejemplo, respuestas de opción múltiple, clases de sentimiento o formatos de filas de base de datos). Este enfoque mejora la fiabilidad, reduce los errores y las alucinaciones, y simplifica la integración en sistemas como bases de datos, APIs o flujos de trabajo.
La generación de salidas estructuradas en los LLM a menudo implica técnicas como:
- Especificar instrucciones detalladas en el prompt para guiar al modelo a producir la salida en el formato deseado.
- Utilizar herramientas de validación y análisis como Pydantic en Python para asegurar que la salida coincida con el esquema.
- A veces, imponer restricciones de decodificación basadas en gramática o autómatas de estados finitos para garantizar el cumplimiento a nivel de token con el formato.
Los beneficios de las salidas estructuradas de los LLM incluyen:
- Legibilidad por máquina y facilidad de integración.
- Reducción de la variabilidad y los errores.
- Mayor predictibilidad y verificabilidad para tareas que requieren formatos de datos consistentes.
Los desafíos incluyen diseñar esquemas efectivos, manejar datos anidados complejos y posibles limitaciones en las capacidades de razonamiento en comparación con la generación de texto libre.
En general, la salida estructurada permite que los LLM sean más útiles en aplicaciones que requieren datos precisos y formateados, en lugar de solo texto legible por humanos.
Ejemplos de Python para Salida Estructurada
Todos los fragmentos extraen información de evento como JSON: {título, fecha, ubicación}. Reemplaza las claves/modelos como desees.
1) OpenAI — Esquema JSON (estricto)
from openai import OpenAI
import json
client = OpenAI()
schema = {
"name": "Event",
"schema": {
"type": "object",
"properties": {
"title": {"type": "string"},
"date": {"type": "string", "description": "YYYY-MM-DD"},
"location": {"type": "string"}
},
"required": ["title", "date", "location"],
"additionalProperties": False
},
"strict": True
}
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "user", "content": "Extract the event from: 'PyData Sydney is on 2025-11-03 at Darling Harbour.'"}
],
response_format={"type": "json_schema", "json_schema": schema},
)
data = json.loads(resp.choices[0].message.content)
print(data)
La función Structured Outputs de OpenAI aplica este esquema en el lado del servidor.
2) Google Gemini — esquema de respuesta + MIME JSON
import google.generativeai as genai
from google.genai import types
# Configure with your API key
# genai.configure(api_key="your-api-key")
schema = types.Schema(
type=types.Type.OBJECT,
properties={
"title": types.Schema(type=types.Type.STRING),
"date": types.Schema(type=types.Type.STRING),
"location": types.Schema(type=types.Type.STRING),
},
required=["title", "date", "location"],
additional_properties=False,
)
resp = genai.generate_content(
model="gemini-2.0-flash",
contents="Extract the event from: 'PyData Sydney is on 2025-11-03 at Darling Harbour.'",
generation_config=genai.GenerationConfig(
response_mime_type="application/json",
response_schema=schema,
),
)
print(resp.text) # already valid JSON per schema
Gemini devolverá JSON estricto que cumpla con response_schema.
3) Anthropic (Claude) — Uso de Herramientas con esquema JSON
from anthropic import Anthropic
import json
client = Anthropic()
tool = {
"name": "extract_event",
"description": "Return event details.",
"input_schema": {
"type": "object",
"properties": {
"title": {"type": "string"},
"date": {"type": "string"},
"location": {"type": "string"}
},
"required": ["title", "date", "location"],
"additionalProperties": False
}
}
msg = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=256,
tools=[tool],
tool_choice={"type": "tool", "name": "extract_event"}, # force schema
messages=[{"role": "user", "content":
"Extract the event from: 'PyData Sydney is on 2025-11-03 at Darling Harbour.'"}],
)
# Claude will "call" the tool; grab the args (which match your schema)
tool_use = next(b for b in msg.content if b.type == "tool_use")
print(json.dumps(tool_use.input, indent=2))
Claude no tiene un interruptor genérico de “modo JSON”; en cambio, el Uso de Herramientas con un input_schema te proporciona argumentos validados con forma de esquema (y puedes forzar su uso).
4) Mistral — modo JSON (validación del lado del cliente)
from mistralai import Mistral
import json
client = Mistral()
resp = client.chat.complete(
model="mistral-large-latest",
messages=[{"role":"user","content":
"Return JSON with keys title, date (YYYY-MM-DD), location for: "
"'PyData Sydney is on 2025-11-03 at Darling Harbour.'"}],
response_format={"type": "json_object"} # guarantees valid JSON
)
data = json.loads(resp.choices[0].message.content)
print(data)
# Tip: validate `data` against your Pydantic/JSON Schema locally.
El json_object de Mistral aplica la forma JSON (no tu esquema exacto) — valida en el lado del cliente.
5) AWS Bedrock — Esquema de Herramienta API Converse (agnóstico al modelo)
import boto3, json
bedrock = boto3.client("bedrock-runtime", region_name="us-east-1")
model_id = "anthropic.claude-3-5-sonnet-20240620-v1:0"
tools = [{
"toolSpec": {
"name": "extract_event",
"inputSchema": {
"json": {
"type": "object",
"properties": {
"title": {"type": "string"},
"date": {"type": "string"},
"location": {"type": "string"}
},
"required": ["title","date","location"],
"additionalProperties": False
}
}
}
}]
resp = bedrock.converse(
modelId=model_id,
toolConfig={"tools": tools},
toolChoice={"tool": {"name": "extract_event"}}, # force schema
messages=[{"role":"user","content":[{"text":
"Extract the event from: 'PyData Sydney is on 2025-11-03 at Darling Harbour.'"}]}],
)
# Pull toolUse content
tool_use = next(
c["toolUse"] for c in resp["output"]["message"]["content"] if "toolUse" in c
)
print(json.dumps(tool_use["input"], indent=2))
Bedrock valida la entrada de la herramienta contra tu esquema JSON y muchos modelos alojados (por ejemplo, Claude) lo soportan a través de Converse.
Guía práctica y Validación
- Si deseas las garantías más fuertes del lado del servidor: salidas estructuradas de OpenAI o esquema de respuesta de Gemini.
- Si ya estás en Claude/Bedrock: define una Herramienta con un esquema JSON y fuerza su uso; lee los argumentos de la herramienta como tu objeto tipado.
- Si usas Mistral: habilita
json_objecty valida localmente (por ejemplo, con Pydantic).
Patrón de validación (funciona para todos)
from pydantic import BaseModel, ValidationError
class Event(BaseModel):
title: str
date: str
location: str
try:
event = Event.model_validate(data) # `data` from any provider
except ValidationError as e:
# handle / retry / ask model to fix with e.errors()
print(e)
Enlaces útiles
- https://platform.openai.com/docs/guides/structured-outputs
- https://ai.google.dev/gemini-api/docs/structured-output
- https://docs.mistral.ai/capabilities/structured-output/json_mode/
- https://aws.amazon.com/blogs/machine-learning/structured-data-response-with-amazon-bedrock-prompt-engineering-and-tool-use
- https://github.com/aws-samples/anthropic-on-aws/blob/main/complex-schema-tool-use/README.md
- https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-messages.html
- Cómo solicitar Salida Estructurada del LLM alojado en Ollama
- Hoja de trucos de Python
- AWS SAM + AWS SQS + Python PowerTools
- Comparación de rendimiento de AWS Lambda: JavaScript vs Python vs Golang