Skip to content
DigitalNeuron
Herramientas y productos

Análisis: cómo obtener resultados legibles por máquina de un modelo de lenguaje y por qué «devolver JSON» no es una especificación

Todo producto que integra un modelo en un flujo de procesamiento acaba necesitando resultados estructurados fiables. Los tipos de fallos son bien conocidos y las soluciones tienen poco de vistoso. Una guía práctica.

Por DigitalNeuron Desk7 min de lectura

Respuesta rápida

¿Cómo conseguir que un modelo de lenguaje devuelva datos estructurados fiables?

Utilice la decodificación restringida o el modo con aplicación obligatoria de esquemas de la plataforma cuando estén disponibles, porque hacen que una sintaxis incorrecta sea imposible, no solo improbable. Después, diseñe el esquema pensando en el modelo: que sea plano, con pocos campos obligatorios, enumeraciones explícitas, una forma clara de expresar incertidumbre y ningún campo que exija cálculos aritméticos. Valide cada respuesta con el esquema y trate la corrección semántica —que los valores sean correctos, no solo que la estructura sea válida— como un problema aparte que la validación no resuelve.

Claves

  • La decodificación restringida por esquemas resuelve la sintaxis, no el significado. Una respuesta puede ser un JSON perfectamente válido y estar completamente equivocada.
  • Diseñar el esquema es diseñar el prompt. Cada nombre de campo, valor de enumeración y descripción constituye una instrucción que el modelo lee.
  • Ofrezca al modelo una forma válida de indicar 'no consta' o 'no es seguro'. De lo contrario, un campo obligatorio se convierte en una invitación a inventar un valor.
  • Nunca pida al modelo que calcule totales, porcentajes o fechas que puedan derivarse. Extraiga los datos de entrada y haga el cálculo mediante código.
  • Valide la respuesta y vuelva a solicitarla una vez, adjuntando el error de validación. Un único turno de corrección específico subsana la mayoría de los fallos residuales a menor coste que un bucle de reintentos.

En el momento en que un modelo de lenguaje deja de escribir para una persona y empieza a escribir para un programa, entra en juego un conjunto de exigencias distinto. La prosa puede ser aproximadamente correcta. Un campo llamado total_amount no puede serlo.

La mayoría de los equipos lo descubren en el mismo orden. Piden JSON en el prompt y funciona. Lo lanzan a producción. Una semana después, el parser falla porque el modelo envolvió el objeto en un bloque de código, o añadió una frase amable antes de él, o generó una coma sobrante. Añaden una función de limpieza. Funciona. Un mes después, un campo que debería haber sido null contiene un valor inventado pero plausible, y no falla nada en absoluto, lo cual es mucho peor.

Esos dos fallos son de naturaleza distinta, y confundirlos es la razón por la que el problema tarda tanto en resolverse.

Dos problemas con un solo nombre

El fallo sintáctico es una salida que no se puede parsear o que no coincide con el esquema. Es ruidoso, inmediato y perfectamente solucionable.

El fallo semántico es una salida que se parsea sin problemas pero que dice algo incorrecto. Una fecha expresada con seguridad que nunca apareció en el documento. Una categoría que encaja en la enumeración pero no en el contenido. Un total que no coincide con sus partidas.

La decodificación restringida —los modos de aplicación de esquemas que ya ofrecen todas las grandes plataformas— elimina casi por completo la primera categoría. Funciona restringiendo qué tokens están permitidos en cada paso de generación, de modo que resulta imposible producir una salida fuera de la gramática definida. Se trata de un cambio real respecto a las peticiones basadas en prompts, que son sugerencias que el modelo suele respetar, y la diferencia se nota en la cola de la distribución: esa solicitud entre mil que antes fallaba es precisamente la que hace saltar una alerta a medianoche.

No hace absolutamente nada por la segunda categoría, y existe un riesgo real en cómo se interpreta esto psicológicamente. Los equipos que adoptan la aplicación de esquemas suelen dejar de validar, porque la plataforma "garantiza" el esquema. La garantía se refiere a la forma. Cada pregunta restante —¿es este el valor correcto?, ¿concuerdan estos campos entre sí?, ¿está esta fecha dentro del rango plausible?— sigue siendo responsabilidad de quien construye el sistema.

El esquema forma parte del prompt

Esta es la reformulación más útil disponible, y es la que con más frecuencia se pasa por alto. El modelo lee el esquema. Los nombres de campo, los valores de las enumeraciones, las descripciones y el orden son todos instrucciones, y compiten con el prompt del sistema por influencia.

Lo cual significa que las decisiones de diseño del esquema tienen consecuencias sobre la calidad.

Nombra los campos como se los describirías a una persona. is_urgent produce mejores resultados que flag2. Una descripción en el propio campo —"verdadero solo si el cliente indica un plazo dentro de las próximas 48 horas"— suele ser más eficaz que esa misma frase en el prompt del sistema, porque está situada justo al lado de la decisión.

Usa enumeraciones en lugar de cadenas libres siempre que el espacio de valores sea cerrado. Un campo category de texto libre genera una larga cola de cuasi-sinónimos que el código posterior tiene que normalizar eternamente. Una enumeración toma la decisión en el momento de la generación.

Mantén el esquema plano. Los objetos profundamente anidados aumentan tanto la probabilidad de error estructural como el radio de impacto cuando una rama falla. Si el dominio es genuinamente jerárquico, dos llamadas suelen ser más fiables que una única respuesta muy anidada, y además son más fáciles de evaluar, porque se puede ver en qué etapa falló.

Ordena los campos de modo que el razonamiento preceda a las conclusiones. Un esquema en el que un campo reasoning o evidence_quote aparece antes que classification produce clasificaciones medible mente mejores que el orden inverso, porque el modelo genera de izquierda a derecha y el campo anterior condiciona al posterior. Este es el único lugar donde una pequeña cantidad de prosa generada justifica su coste dentro de una respuesta estructurada.

Dale al modelo una salida airosa

La causa más común de valores inventados es un esquema que no ofrece ninguna alternativa legítima a inventar uno.

Si contract_end_date es una cadena obligatoria y no nula, y el contrato no indica una fecha de finalización, el modelo debe producir algo. Producirá algo plausible. Nada en el pipeline lo objetará.

La solución es hacer que la ausencia sea expresable: campos anulables, un valor explícito not_stated en la enumeración, o un booleano independiente que condicione el valor. Combinado con una instrucción clara de que la ausencia es una respuesta aceptable y esperada, esto elimina una buena parte de los valores de campo alucinados, y cuesta una sola línea de esquema.

La misma lógica se extiende a la confianza. Una enumeración confidence con tres valores —alta, media, baja— resulta más útil que una puntuación numérica, porque los modelos están mal calibrados en la autoevaluación numérica, pero son razonablemente consistentes con categorías gruesas. Envía el nivel bajo a revisión humana y habrás convertido un problema de precisión en un problema de capacidad de procesamiento, que es un problema mucho mejor de tener.

No le pidas al modelo que haga aritmética

Un esquema que contiene subtotal, tax y total está pidiendo tres valores cuando uno se puede derivar de los otros. El modelo rellenará los tres, y en ocasiones no coincidirán entre sí.

Extrae los datos de entrada. Calcula los valores derivados en el código. La misma regla se aplica a la aritmética de fechas, los porcentajes, los recuentos y cualquier conversión de unidades. No se trata de una afirmación sobre la capacidad del modelo: es que un cálculo determinista tiene una tasa de error de cero y uno generado no la tiene, y no hay razón para aceptar el segundo cuando el primero está disponible.

La validación y el único intento de reparación

Valida cada respuesta, incluidas las que provienen de endpoints con aplicación de esquema. Cuando la validación falla, la respuesta más eficaz es un único intento de reparación que incluya el error concreto, no un reintento a ciegas. Devolver "el campo priority debe ser uno de low, medium, high; devolviste 'urgent'" resuelve la gran mayoría de los fallos residuales en un solo turno adicional.

Limítalo a uno. Los bucles de reintento sin límite ante una entrada adversaria o genuinamente ambigua convierten un fallo visible en un coste invisible, y suprimen precisamente la señal que se necesita: que algo en esta entrada no encaja con el esquema diseñado.

Más allá del reintento, hay que contar con una alternativa determinista: un registro por defecto marcado para revisión, una vía basada en reglas o una cola para un humano. Un pipeline cuyo único modo de fallo es "vuelve a intentarlo" no tiene modo de fallo alguno, lo cual es un defecto de diseño y no una prestación.

Evaluar la salida estructurada

La salida estructurada resulta inusualmente cómoda de evaluar, y los equipos deberían aprovecharlo.

Como la salida es legible por máquina, la mayoría de las comprobaciones son exactas: validez del esquema, pertenencia a la enumeración, presencia de campos obligatorios, coherencia entre campos y precisión a nivel de campo frente a un conjunto etiquetado. La métrica a seguir es la precisión por campo, no la precisión del registro completo: un registro puntuado como una sola unidad oculta qué campo se está degradando, y normalmente es un campo, no toda la extracción.

Rastrea también la tasa de nulos. Una caída repentina de los nulos tras un cambio de prompt o de modelo suele significar que el modelo ha empezado a inventar valores donde antes se abstenía, y resulta invisible para cualquier comprobación que solo examine los registros válidos.

El resumen, sin adornos

Aquí no hay ninguna técnica ingeniosa. Activa la decodificación restringida. Diseña el esquema como si el modelo fuera a leerlo, porque lo hará. Permítele decir "no lo sé". Mantén la aritmética en el código. Valida de todos modos. Repara una vez, y luego recurre a la alternativa.

Cada una de estas medidas es barata, y juntas marcan la diferencia entre un modelo que es un componente más de tu sistema y un modelo que es una fuente ocasional de sorpresas dentro de él.

Preguntas frecuentes

¿Es la decodificación restringida lo mismo que pedir un JSON en el prompt?
No. Una petición en el prompt es una sugerencia que el modelo suele seguir. La decodificación restringida limita los tokens que pueden generarse en cada paso, de modo que sea imposible producir una salida ajena a la gramática. La diferencia se aprecia en los casos extremos, donde se concentran los fallos en producción.
¿Por qué inventa el modelo valores para los campos que marqué como obligatorios?
Porque un campo obligatorio que no admite un valor vacío equivale a una instrucción de producir algo. Permita que el campo sea nulo o añada un miembro de enumeración explícito como 'no_encontrado'; por lo general, los valores inventados dejarán de aparecer.
¿Debo utilizar esquemas con muchos niveles de anidamiento?
Es preferible una estructura plana. Un anidamiento profundo aumenta tanto la probabilidad de errores estructurales como el coste de un fallo parcial. Si el dominio es realmente jerárquico, considere hacer dos llamadas en lugar de solicitar una única respuesta con muchos niveles de anidamiento.
¿Cómo deben funcionar los reintentos?
Haga un intento de corrección que incluya el error de validación concreto y, si falla, recurra a un procedimiento determinista o a una persona. Los reintentos sin límite convierten una mala respuesta en una factura elevada y ocultan el problema subyacente.
¿Sigo necesitando validación si la API garantiza el esquema?
Sí. La garantía cubre la estructura, no los valores. La pertenencia a las enumeraciones, la coherencia entre campos, los intervalos y las comprobaciones referenciales siguen siendo responsabilidad suya.

Fuentes

  1. JSON Schema specification — JSON Schema
  2. Model Context Protocol — specification — Model Context Protocol
  3. OpenAPI Specification — OpenAPI Initiative
Etiquetasstructured outputJSON schematool usereliabilityintegration

Lecturas relacionadas

AWS incorpora el modelo de pesos abiertos Beam de Reflection AI para programación agéntica

AWS publicó una guía técnica para implementar Beam, el modelo de mezcla de expertos de pesos abiertos de Reflection AI para programación agéntica, en Amazon SageMaker. Beam cuenta con 501.000 millones de parámetros totales, 23.000 millones de parámetros activos y una longitud de contexto declarada de 1 millón de tokens, con sus pesos publicados en Hugging Face bajo la licencia Apache 2.0.

2 min de lectura