Cómo hacer que una red neuronal genere JSON válido sin trucos ni reintentos
Cualquiera que haya intentado conectar un modelo de lenguaje a un backend real se ha encontrado con este problema. Escribes un prompt detallado, le pides al modelo que devuelva estrictamente JSON con la estructura requerida, lo pruebas con diez ejemplos: todo funciona perfectamente. Pero en la centésima solicitud, la red neuronal de repente olvida cerrar una comilla, añade la frase "Aquí está tu respuesta!" al principio de la respuesta, o inventa un campo que no existe. Como resultado, Pydantic lanza un error de validación y tu servicio se cae.
Por lo general, los desarrolladores resuelven este problema con reintentos a la API, expresiones regulares complejas o intentos de "corregir" la respuesta corrupta después de que se ha generado. Los desarrolladores del equipo .txt tomaron un enfoque diferente y crearon Outlines — una biblioteca que guía el proceso de generación de texto a nivel de token individual.

Cómo funciona la generación controlada
La mayoría de los frameworks trabajan con LLMs como una caja negra: envían texto y esperan una cadena lista. Outlines intercepta el control durante el muestreo. En cada paso de generación, la biblioteca verifica qué tokens del vocabulario del modelo coinciden con el esquema especificado y cuáles lo violan.
Si solicitaste un número, la biblioteca simplemente pone en cero la probabilidad de muestreo para todos los tokens que contienen letras o puntuación. El modelo físicamente no puede seleccionar un símbolo inválido. El resultado no es esperanza de JSON válido, sino una estructura correcta garantizada desde el primer intento.
Este enfoque ahorra tokens y tiempo. Ya no necesitas pedirle al modelo en el prompt "que no añada texto extra" ni ejecutar regeneraciones cuando el parsing falla.
Qué puede hacer la biblioteca
La interfaz de Outlines intenta imitar la sintaxis familiar de tipos de Python. Simplemente pasas el tipo de dato deseado junto con el prompt.
Fijación de opciones de respuesta
Si necesitas una elección de un conjunto limitado de valores, defínelo a través de Literal o Enum. El modelo no escribirá razonamientos largos: inmediatamente outputará uno de los valores especificados.
import outlines
from typing import Literal
from transformers import AutoTokenizer, AutoModelForCausalLM
model_name = "microsoft/Phi-3-mini-4k-instruct"
model = outlines.from_transformers(
AutoModelForCausalLM.from_pretrained(model_name, device_map="auto"),
AutoTokenizer.from_pretrained(model_name)
)
# Модель вернет строго одно из трех слов
sentiment = model(
"Оцени тональность ответа: 'Сервис работает отлично, спасибо!'",
Literal["Positive", "Negative", "Neutral"]
)
print(sentiment) # Positive
Generación a partir de esquemas Pydantic
Para objetos complejos, puedes usar modelos Pydantic estándar. Outlines construye una gramática basada en el esquema y asegura que la estructura de la respuesta se ajuste completamente a este.
from pydantic import BaseModel
from enum import Enum
class TicketPriority(str, Enum):
low = "low"
medium = "medium"
high = "high"
urgent = "urgent"
class ServiceTicket(BaseModel):
priority: TicketPriority
category: str
requires_manager: bool
summary: str
prompt = """
Проанализируй обращение:
Срочно! Не могу войти в личный кабинет после оплаты. Через час презентация клиенту!
"""
# Модель сгенерирует JSON, который точно совпадает со структурой ServiceTicket
ticket_json = model(prompt, ServiceTicket, max_new_tokens=200)
ticket = ServiceTicket.model_validate_json(ticket_json)
print(ticket.priority) # TicketPriority.urgent
print(ticket.requires_manager) # True
Expresiones regulares y gramáticas
Si los modelos Pydantic son demasiado engorrosos para tu tarea, puedes definir una expresión regular estricta. Esto es conveniente para extraer números de teléfono, fechas, códigos postales o crear DSLs internos.
Con qué modelos funciona
Outlines se adapta a tu stack. La biblioteca soporta múltiples modos:
- Inferencia local a través de
transformersyllama.cpp - Soluciones de servidor basadas en vLLM y Ollama
- APIs externas como OpenAI y Gemini
El mayor beneficio de la biblioteca se materializa al trabajar con tus propios modelos locales o servidores de inferencia on-premises. Ahí es donde el control directo de enmascaramiento de tokens proporciona una garantía del 100% de estructura y acelera la operación.
Casos de uso en producción
En la práctica, la biblioteca aborda varias tareas comunes de desarrollo a la vez:
- Clasificación automática de tickets. Extracción de categoría, urgencia y etiquetas de correos de clientes entrantes sin el riesgo de obtener un objeto corrupto.
- Extracción de entidades con manejo de datos incompletos. A través de tipos
Union, puedes permitir que el modelo devuelva un objeto lleno o una cadena explícita con un mensaje sobre información faltante. - Llamada a funciones. Puedes pasar una función Python regular al modelo, y Outlines automáticamente extrae los tipos de sus argumentos para formar parámetros de llamada correctos.
- Categorización de catálogos de productos. Parsing rápido de descripciones de productos en categorías, marcas y características clave.
Limitaciones y matices
Con todos los beneficios, es importante entender las specifics de la tecnología. Calcular máscaras para tokens requiere recursos adicionales. Si tu esquema Pydantic consiste en docenas de objetos anidados y expresiones regulares complejas, la preparación de la gramática antes de que comience la generación puede llevar algo de tiempo.
Además, si trabajas exclusivamente a través de la API de OpenAI, la biblioteca utilizará los mecanismos internos del proveedor (Structured Outputs / JSON Mode). En este caso, Outlines actúa como una interfaz unificada conveniente, pero el proceso de muestreo en sí es controlado por el servidor de OpenAI.
Outlines resuelve un problema real de ingeniería que cualquier equipo enfrenta al llevar LLMs a producción. El proyecto elimina la inestabilidad de la generación y permite trabajar con redes neuronales como funciones tipadas regulares. Si estás construyendo servicios backend o agentes autónomos basados en modelos abiertos, esta herramienta definitivamente merece un lugar en tu toolkit.
Proyectos relacionados