Los desarrolladores ahora pueden mantener bajo control el coste de corregir JSON malformado proveniente de modelos de lenguaje de gran tamaño (LLM) limitando los intentos de reparación a un máximo de dos, según muestra un sencillo bucle de Python. El patrón —generar, analizar, validar, reintentar, y luego aceptar o fallar— convierte un "JSON posiblemente válido" en una tasa de éxito medible y evita el uso descontrolado de tokens.

Por qué es importante un bucle de reparación

Los LLM suelen recibir instrucciones de "devolver un JSON", pero la salida frecuentemente contiene errores de sintaxis, claves faltantes o valores que rompen las reglas de negocio. Un sistema posterior que espere un payload estricto fallará o producirá resultados incorrectos si recibe dicha salida. Sin una forma sistemática de detectar y corregir estos problemas, los equipos terminan aceptando una alta tasa de fallos o desperdiciando dinero solicitando al modelo repetidamente hasta que lo haga bien.

Las tres capas de validación

Un bucle fiable separa la validación en:

  • Sintaxis – ¿se puede analizar la cadena como JSON?
  • Estructura – ¿contiene el objeto de nivel superior exactamente las claves esperadas?
  • Semántica – ¿respetan los valores las restricciones de dominio (por ejemplo, que una "category" pertenezca a un conjunto predefinido)?

Al detenerse en la primera capa que falle, el bucle puede proporcionar al modelo un mensaje de error preciso, lo que mejora drásticamente las posibilidades de una corrección acertada en el siguiente intento.

Ejemplo mínimo en Python

El siguiente código utiliza únicamente la biblioteca estándar. Define un esquema diminuto (un diccionario con las claves category y summary) y una lista fija de categorías permitidas.

import json

CATEGORIES = {"bug", "feature", "question"}

def validate(raw: str):
    try:
        value = json.loads(raw)
    except json.JSONDecodeError as exc:
        return None, f"syntax: {exc.msg}"

    if not isinstance(value, dict):
        return None, "shape: root must be an object"
    if set(value) != {"category", "summary"}:
        return None, "shape: expected category and summary"
    if value["category"] not in CATEGORIES:
        return None, "semantic: invalid category"
    if not isinstance(value["summary"], str) or not value["summary"].strip():
        return None, "semantic: summary must be text"

    return value, None

El bucle de reparación en sí mismo impone un límite estricto de intentos:

MAX_ATTEMPTS = 2
raw = model_response   # initial LLM output

for attempt in range(MAX_ATTEMPTS + 1):
    value, error = validate(raw)
    if error is None:
        break
    if attempt == MAX_ATTEMPTS:
        raise RuntimeError(f"failed after {MAX_ATTEMPTS} retries: {error}")

    # Send the error and schema back to the model for a fix
    raw = ask_model_to_repair(raw, error)

Si el JSON pasa la validación en el primer intento, el bucle termina inmediatamente. De lo contrario, reintenta enviando al modelo un payload conciso: la salida original, la cadena de error exacta y el esquema esperado. Tras dos intentos fallidos, el proceso se aborta con una excepción clara.

Dos reglas para reparaciones rentables

  1. Mantén los prompts de reparación concisos – Incluye solo el JSON sin procesar, el mensaje de error y el esquema. Añadir un historial de chat largo infla el uso de tokens y puede confundir al modelo, elevando el coste por reintento sin mejorar la precisión.

  2. Separa la validación de la verificación de hechos – El analizador puede detectar problemas estructurales, pero no puede verificar si una declaración de "summary" es verdadera. La verificación de hechos pertenece a una etapa posterior; intentar "reparar" una afirmación falsa solo hace que la mentira parezca más limpia.

Medición del éxito

Registrar el tipo de error de cada intento (sintaxis, estructura, semántica) y si el bucle tuvo éxito proporciona una métrica concreta: la proporción de respuestas de LLM que se vuelven utilizables dentro de los reintentos limitados. Los equipos pueden realizar un seguimiento de esto a lo largo del tiempo, comparar estilos de prompts o experimentar con diferentes definiciones de esquemas.

Posibles desventajas

Limitar el bucle significa que algunas salidas malformadas se descartarán una vez alcanzado el límite, lo que puede aumentar la tasa de fallos general si la calidad bruta del modelo es baja. En entornos donde cada respuesta es crítica, los desarrolladores podrían preferir un límite de reintentos más alto a cambio de tokens adicionales. El compromiso es explícito: más coste para una mayor cobertura, o presupuestos más ajustados con un límite predecible.

Qué observar a continuación

  • Ingeniería de prompts para la reparación – Refinar el formato del mensaje de error puede reducir el número de reintentos necesarios.
  • Analizadores alternativos – Algunas librerías ofrecen un análisis tolerante que puede autocorregir problemas menores; comparar su coste frente a un bucle limitado merece la pena.
  • Actualizaciones del modelo – Las versiones más recientes de los LLM pueden producir JSON más limpios de forma nativa, lo que potencialmente permitiría reducir aún más el límite de reintentos.

Un bucle de reparación de JSON limitado ofrece a los desarrolladores una herramienta práctica para convertir la salida difusa de un LLM en datos fiables sin que los costes se disparen. Al tratar la validación como un paso de primer nivel y limitar los reintentos, los equipos pueden mantener contentos tanto sus presupuestos como sus sistemas posteriores.