Presentamos salidas estructuradas en la API
Presentamos salidas estructuradas en la API, las salidas del modelo ahora se adhieren de forma más fiable a esquemas JSON suministrados por el desarrollador.

El año pasado en DevDay, presentamos el modo JSON, un bloque de construcción útil para desarrolladores que buscan crear aplicaciones fiables con nuestros modelos. Aunque el modo JSON mejora la fiabilidad del modelo para generar salidas JSON válidas, no garantiza que la respuesta del modelo se ajustará a un esquema particular. Hoy presentamos salidas estructuradas en la API, una característica nueva para garantizar que las salidas generadas por el modelo coincidan exactamente con los esquemas JSON provistos por los desarrolladores.
Generar datos estructurados a partir de salidas no estructuradas es uno de los casos de uso principales para la IA en las aplicaciones actuales. Los desarrolladores usan la API de OpenAI para crear asistentes potentes que tengan la capacidad de traer datos y responder preguntas mediante llamada a función(se abre en una nueva ventana), extraer datos estructurados para entrada de datos y crear flujos de trabajo de agentes de varios pasos que permitan a los modelos de lenguaje grandes (LLM) tomar medidas. Los desarrolladores han estado trabajando durante mucho tiempo en torno a las limitaciones de los LLM en esta área mediante herramientas de fuente abierta, consultas y recuperación de solicitudes de manera reiterada para garantizar que las salidas del modelo coincidan con los formatos necesarios para interoperar con sus sistemas. Las salidas estructuradas resuelven este problema al limitar los modelos de OpenAI para que coincidan con los esquemas suministrados por el desarrollador y entrenar nuestros modelos para comprender mejor esquemas complicados.
En nuestras evaluaciones de esquema JSON a continuación, nuestro modelo nuevo gpt-4o-2024-08-06 con salidas estructuradas obtiene una puntuación perfecta del 100 %. En comparación, gpt-4-0613 obtiene una puntuación de menos del 40 %.
Con salidas estructuradas, gpt-4o-2024-08-06 logra una fiabilidad del 100 % en nuestras evaluaciones, lo que coincide perfectamente con los esquemas de salida.
Presentamos salidas estructuradas en dos formas en la API:
1. Llamada a función: Las salidas estructuradas mediante herramientas está disponible al establecer strict: true dentro de la definición de función. Esta característica funciona con todos los modelos que admiten herramientas, incluidos todos los modelos gpt-4-0613 y gpt-3.5-turbo-0613 y posteriores. Cuando las salidas estructuradas están habilitadas, las salidas del modelo coincidirán con la definición de herramienta suministrada.
2. Una opción nueva para el parámetro response_format: los desarrolladores ahora pueden suministrar un esquema JSON mediante json_schema, una opción nueva para el parámetro response_format. Esto resulta útil cuando el modelo no llama a una herramienta, sino que responde al usuario de forma estructurada. Esta característica funciona con nuestros modelos GPT‑4o más nuevos: gpt-4o-2024-08-06, lanzado hoy, y gpt-4o-mini-2024-07-18. Cuando se suministra un response_format con strict: true, las salidas del modelo coincidirán con el esquema suministrado.
La seguridad es la máxima prioridad para OpenAI, la nueva funcionalidad de salidas estructuradas cumplirá con nuestras políticas de seguridad existentes y aún permitirá que el modelo rechace una solicitud insegura. Para que el desarrollo sea más simple, existe un nuevo valor de cadena refusal en respuestas de la API que permite a los desarrolladores detectar de forma programática si el modelo generó un rechazo en lugar de una salida que coincida con el esquema. Cuando la respuesta no incluye un rechazo y la respuesta del modelo no se modificó de forma prematura (según se indica en finish_reason), la respuesta del modelo producirá de forma fiable un JSON válido que coincida con el esquema suministrado.
Se actualizaron nuestros kits de desarrollo de software (SDK) Python y Node con soporte nativo para salidas estructuradas. Proveer un esquema para herramientas o como un formato de respuesta es tan fácil como suministrar un objeto Pydantic o Zod, y nuestros SDK manejarán la conversión de tipo de datos a un esquema JSON compatible, lo que deserializa la respuesta JSON en la estructura de datos ingresados automáticamente y analiza los rechazos si surgen.
Los siguientes ejemplos muestran soporte nativo para salidas estructuradas con llamada a función.
El soporte a salidas estructuradas nativas también está disponible para response_format.
Con frecuencia los desarrolladores usan modelos de OpenAI para generar datos estructurados para distintos casos de uso. Estos son algunos otros ejemplos:
Por ejemplo, los desarrolladores pueden usar salidas estructuradas para crear aplicaciones de generación de código o interfaz de usuario. Todos los siguientes ejemplos usan el mismo response_format y se pueden usar para generar interfaces de usuario distintas en función de la entrada del usuario.
Eres un asistente de interfaz de usuario Tu trabajo es ayudar a los usuarios a visualizar las ideas de su sitio web y aplicaciones.Puede ser útil para darle al modelo un campo separado de cadena de pensamiento para mejorar la calidad final de la respuesta.
Por ejemplo, instruir al modelo para extraer cosas como para hacer, fechas de entrega y tareas de notas de reunión.
Adoptamos un enfoque de dos partes para mejorar la fiabilidad de las salidas de modelo que coinciden con el esquema JSON. En primer lugar, entrenamos nuestro modelo más reciente gpt-4o-2024-08-06 para comprender esquemas complicados y cómo producir mejores salidas que coincidan con estos. Sin embargo, el comportamiento del modelo es inherentemente no determinista, a pesar de que las mejoras del rendimiento del modelo (93 % en nuestro punto de referencia), aún no alcanzan la fiabilidad que los desarrolladores necesitan para crear aplicaciones sólidas. Entonces también adoptamos un enfoque determinista basado en ingeniería para limitar las salidas del modelo y lograr una fiabilidad del 100 %.
Nuestro enfoque se basa en una técnica conocida como muestreo limitado o decodificación limitada. De forma predeterminada, cuando se toman muestras de los modelos para producir salidas, son completamente ilimitadas y pueden seleccionar cualquier token de vocabulario como la siguiente salida. Esta flexibilidad es lo que permite a los modelos cometer errores; por ejemplo, por lo general son libres para tomar muestras de un token de corchetes en cualquier momento, incluso cuando eso no produciría JSON válido. A fin de forzar salidas válidas, limitamos nuestros modelos a solo tokens que serían válidos de acuerdo con el esquema suministrado en lugar de todos los token disponibles.
Implementar esta limitación puede resultar desafiante en la práctica, dado que los tokens que son válidos difieren a lo largo de la salida del modelo. Digamos que tenemos el siguiente esquema:
Los tokens que son válidos al comienzo de la salida incluyen cosas como {, {“, {\n, etc. Sin embargo, una vez que el modelo ya tomó la muestra {“val, entonces { ya no es un token válido. Por lo tanto, necesitamos implementar decodificación limitada dinámica y determinar qué tokens son válidos una vez que se genera cada token en lugar de por adelantado al comienzo de la respuesta.
Para hacerlo, convertimos el esquema JSON suministrado en gramática libre de contexto (CFG). La gramática es un conjunto de normas que define un lenguaje y una gramática libre de contexto es una gramática que cumple con normas específicas. Puedes pensar en JSON y el esquema JSON como lenguajes particulares con reglas para definir qué es válido dentro del lenguaje. Así como en inglés no es válido tener una oración sin verbo, en JSON no es válido tener una coma final.
Por lo tanto, para cada esquema JSON, calculamos una gramática que representa ese esquema y procesamos previamente sus componentes para que sea fácilmente accesible durante el muestreo del modelo. Esto es porque la primer solicitud con un esquema nuevo provoca una penalidad de latencia; debemos procesar previamente el esquema para generar este artefacto que podemos usar de forma eficiente durante el muestreo.
Mientras tomamos muestras, después de cada token, nuestro motor de inferencia determinará qué tokens son válidos para producirse a continuación en función de los tokens generados previamente y las reglas dentro de la gramática que indica qué tokens son válidos a continuación. A continuación, usamos esta lista de tokens para enmascarar el siguiente paso de muestreo, el que reduce de forma efectiva la probabilidad de tokens no válidos a 0. Debido a que procesamos previamente el esquema, podemos usar una estructura de datos en caché para hacerlo de forma eficiente, con gastos de estructura de latencia mínima.
Los enfoques alternativos a este problema a menudo usan máquinas de estado finito (FSM) o expresiones regulares (regexes), por lo general, implementadas con FSM para una decodificación limitada. Estas funcionan de forma similar, ya que actualizan dinámicamente qué tokens son válidos después de su generación, pero tienen diferencias clave del enfoque CFG. En particular, las CFG pueden expresar una clase más amplia de lenguajes que las FSM. En la práctica, esto no importa para esquemas muy simples como el esquema devalue que se muestra arriba. Sin embargo, descubrimos que la diferencia es significativa para esquemas más complejos que comprenden estructuras de datos anidados y recurrentes. Como ejemplo, las FSM generalmente no pueden expresar tipos recurrentes, lo que significa que los enfoques basados en FSM pueden luchar para coincidir con paréntesis en JSON profundamente anidados. El siguiente es un esquema recurrente de muestra que es admitido en la API de OpenAI con salidas estructuradas, pero no sería posible expresar con una FSM.
Ten en cuenta que cada elemento de interfaz de usuario puede tener hijos arbitrarios que hacen referencia al esquema raíz de forma recurrente. El enfoque de CFG se da el lujo de esta flexibilidad.
Existen algunas limitaciones para tener en cuenta cuando usamos salidas estructuradas:
- Las salidas estructuradas permiten solo un subconjunto de esquema JSON, que se detalla en nuestros documentos(se abre en una nueva ventana). Esto nos ayuda a garantizar el mejor rendimiento posible.
- La primera respuesta de la API con un nuevo esquema generará latencia adicional, pero las respuestas posteriores serán rápidas sin penalidad de latencia. Esto se debe a que durante la primera solicitud, procesamos el esquema según se indica arriba y, a continuación, almacenamos estos artefactos para una reutilización rápida posterior. Los esquemas típicos demoran menos de 10 segundos en procesar la primera solicitud, pero esquemas más complejos pueden demorar hasta un minuto.
- El modelo puede no seguir el esquema si este elige rechazar una solicitud insegura. Si el modelo elige rechazar, el mensaje de devolución tendrá el conjunto booleano
refusalestablecido en verdadero para indicarlo. - Es posible que el modelo no siga el esquema si la generación alcanza
max_tokensu otra condición de parada antes de terminar. - Las salidas estructuradas no evitan todos los tipos de errores de modelo. Por ejemplo, el modelo puede aún cometer errores dentro de los valores del objeto JSON (p. ej., hacer un paso de forma incorrecta en una ecuación matemática). Si los desarrolladores encuentran errores, recomendamos proporcionar ejemplos en las instrucciones del sistema o dividir tareas en subtareas más sencillas.
- Las salidas estructuradas no son compatibles con las llamadas a función paralelas. Cuando se genera una llamada a función paralela, es posible que no coincida con esquemas suministrados. Establece
parallel_tool_calls: falsepara deshabilitar la llamada a función paralela. - Los esquemas JSON suministrados con salidas estructuradas no son una retención de datos cero(se abre en una nueva ventana) (ZDR) elegible.
Por lo general, las salidas estructuradas están disponibles hoy en la API.
Las salidas estructuradas con llamada a función están disponibles en todos los modelos que admiten esta función en la API. Esto incluye nuestros modelos más nuevos (gpt-4o, gpt-4o-mini), todos los modelos después e incluso gpt-4-0613y gpt-3.5-turbo-0613 y cualquier modelo con ajuste de precisión que admita la llamada a función. Esta funcionalidad está disponible en la API de Chat Completions, API de Assistants y API de Batch. Las salidas estructuradas con llamada a función también son compatibles con entradas de visión.
Las salidas estructuradas con formatos de respuesta están disponibles en gpt-4o-mini y gpt-4o-2024-08-06 y cualquier ajuste de precisión basado en estos modelos. Esta funcionalidad está disponible en la API de Chat Completions, API de Assistants y API de Batch. Las salidas estructuradas con formatos de respuesta también son compatibles con entradas de visión.
Al pasar a los nuevos gpt-4o-2024-08-06, los desarrolladores ahorran un 50 % en entradas (2,50 USD/millón de tokens de entrada) y 33 % en salidas (10,00 USD/millón de tokens de salida) en comparación con gpt-4o-2024-05-13.
Para comenzar a usar salidas estructuradas, consulta nuestros documentos(se abre en una nueva ventana).
Las salidas estructuradas se inspiran a partir de un excelente trabajo de la comunidad de fuente abierta: principalmente, las bibliotecas outlines(se abre en una nueva ventana), jsonformer(se abre en una nueva ventana), instructor(se abre en una nueva ventana), guidance(se abre en una nueva ventana) y lark(se abre en una nueva ventana).
Autor
Michelle PokrassContribuidores clave
Chris Colby, Melody Guan, Michelle Pokrass, Ted Sanders, Brian Zhang
Agradecimientos
John Allard, Filipe de Avila Belbute Peres, Ilan Bigio, Owen Campbell-Moore, Chen Ding, Atty Eleti, Elie Georges, Katia Gil Guzman, Jeff Harris, Johannes Heidecke, Beth Hoover, Romain Huet, Tomer Kaftan, Jillian Khoo, Karolis Kosas, Ryan Liu, Kevin Lu, Lindsay McCallum, Rohan Nuttall, Joe Palermo, Leher Pathak, Ishaan Singal, Felipe Petroski Such, Freddie Sulit, David Weedon