>_ DevTrendses

Idioma

Inicio

Lenguajes

Secciones

Frontend Backend Móvil DevOps AI / ML GameDev Blockchain Embebidos Seguridad
Python

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 transformers y llama.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:

  1. 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.
  2. 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.
  3. 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.
  4. 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