Saltar al contenido

Resultados estructurados: obtener JSON confiable a partir de un modelo de lenguaje

Blog / Publicado 

La primera versión de cada integración de LLM analiza la prosa. Solicita "los tres riesgos principales, uno por línea", los divide en nuevas líneas y funciona hasta el día en que el modelo escribe una oración introductoria primero. Existen salidas estructuradas para finalizar ese ciclo: le entrega al modelo un esquema JSON, el decodificador está restringido para que no pueda emitir nada que lo viole y obtiene una carga útil con los campos que solicitó. Esa garantía es real pero más limitada de lo que parece, y la diferencia es dónde viven los insectos.

Qué cubre realmente la garantía

Garantías de decodificación restringidas forma. La respuesta se analizará como JSON, tendrá sus claves, los tipos coincidirán y los campos de enumeración contendrán uno de los valores enumerados. Esta es una gran mejora con respecto al aviso y la esperanza.

No garantiza nada sobre contenido. Un campo escrito como una cadena contendrá una cadena; si esa cadena es precisa o se inventó para satisfacer el esquema, no cambia con respecto a antes. De hecho, un esquema estricto hace que la invención sea un poco más probable, porque un campo obligatorio debe completarse con algo y el modelo no tiene forma de decir "no presente en la fuente". Éste es el fallo más común en la producción: una necesidad invoice_number en un documento que no tiene ninguno.

Diseñe a su alrededor. Permitir nulo donde la ausencia sea posible, agregar un explícito found: boolean o un "unknown" miembro de enumeración y nunca haga que un campo sea obligatorio a menos que la respuesta realmente exista en cada entrada.

Diseñar un esquema que un modelo pueda completar

Los esquemas escritos para validación y los esquemas escritos para generación tienen un aspecto diferente. Algunas reglas que se aplican a todos los proveedores:

Los proveedores también restringen qué palabras clave del esquema JSON admiten en modo estricto: oneOf, las restricciones de patrón, los límites numéricos y la recursividad suelen limitarse o ignorarse. Suponga que el esquema solo restringe la estructura y aplique sus reglas comerciales usted mismo después del análisis.

Validar de todos modos

Incluso con un modo estricto, valide cada respuesta antes de que llegue a su base de datos. El modo estricto puede deshabilitarse mediante un cambio de configuración, una ruta alternativa puede llegar a un modelo que no lo admite, un reintento de red puede devolver un objeto de error y la respuesta puede ser truncada por un límite de token en la mitad del objeto, lo que produce JSON no válido sin modo de esquema.

Cuando una carga útil falla, la pregunta útil es qué campo y por qué. El Validador de esquemas JSON toma el documento y el esquema e informa una línea por problema, con la ruta del puntero JSON, la palabra clave que falló y el valor realmente encontrado. Ésa es exactamente la forma que desea para dos propósitos: arreglar su esquema durante el desarrollo y retroalimentarlo en un reintento: un informe de validación fallido pegado en un mensaje de seguimiento es un aviso de reparación notablemente efectivo, ya que el modelo puede ver exactamente en qué se equivocó.

Limite los reintentos a uno o dos. A un modelo que falla dos veces en un esquema generalmente se le solicita algo que la entrada no contiene, y el tercer intento lo inventará.

De una carga útil de muestra al código

La mayoría de los esquemas comienzan como una respuesta de muestra que alguien pegó en un chat. Convertir eso en código mecanografiado y validado a mano es tedioso y propenso a errores, así que no lo hagas.

Pegue la muestra en Esquema JSON a Zod y obtienes un esquema Zod más el tipo TypeScript inferido. Infiere por campo en lugar de escribir todo como una cadena: los valores que parecen correos electrónicos, URL, UUID o fechas ISO se obtienen .email(), .url(), .uuid() y .datetime() en lugar de un desnudo z.string(), las matrices llevan su tipo de elemento, y un campo cuyo tipo varía según las apariciones se convierte en una unión en lugar de seleccionar silenciosamente el primero que vio. Vale la pena alimentar deliberadamente este último comportamiento: pegue tres o cuatro respuestas reales concatenadas, no una, de modo que los campos opcionales y polimórficos aparezcan como uniones en lugar de estar bloqueados en lo que sea que contenga la primera muestra.

Si solo necesita tipos y no validación en tiempo de ejecución, porque la carga útil proviene de una fuente en la que ya confía, JSON a mecanografiado produce las interfaces directamente, con objetos anidados divididos como subinterfaces con nombre en lugar de blobs anónimos insertados.

Mantenga recta la dirección de la verdad: una definición de esquema, con todo lo demás generado a partir de ella. Un esquema Zod y un esquema JSON mantenidos por separado no estarán de acuerdo dentro de un mes, y el desacuerdo surgirá como un error de análisis de producción en lugar de una falla de prueba.

leyendo lo que volvió

Las respuestas de los modelos llegan minimizadas en una línea, lo que hace que mirarlas sea miserable. El formateador JSON los sangra y los clasifica en algo legible, y su validación detecta el caso de truncamiento de inmediato: una carga útil que termina en la mitad de la cadena es la firma de un límite de token de acierto, y la solución es un límite de salida más alto o un esquema más pequeño, no un cambio rápido.

Cuando compare lo que dos modelos produjeron a partir de la misma entrada, o compruebe si un cambio rápido alteró la salida de una manera que no pretendía, diferencie las cargas útiles formateadas en lugar de leer ambas. Las diferencias estructurales que son invisibles en una pared de JSON (un campo que silenciosamente se convirtió en una cadena de dígitos en lugar de un número) se destacan inmediatamente en una diferencia.

Versionado

Los esquemas cambian y la salida del modelo cambia con ellos. Coloque un campo de versión en la carga útil desde el primer día, de modo que los registros almacenados tengan la forma en la que fueron escritos. Actualizar eso después de tener un millón de filas de JSON sin etiquetar es el tipo de migración para la que nadie programa tiempo.

Todas estas herramientas se ejecutan localmente en su navegador, lo cual es más importante de lo habitual para este flujo de trabajo: las cargas útiles de muestra que está convirtiendo en esquemas suelen ser respuestas API reales con datos reales del cliente, y no deben cargarse en un servicio de formato para ser embellecidas.

Escrito por Ján Turský

Creador de TextArray: crea herramientas gratuitas que priorizan la privacidad y se ejecutan completamente en su navegador.