Comment obliger un réseau de neurones à produire du JSON valide sans rustines ni nouvelles tentatives
Tout le monde qui a essayé de connecter un modèle de langage à un backend réel a rencontré ce problème. Vous écrivez une instruction détaillée, demandez au modèle de retourner strictement du JSON avec la structure requise, vous le testez sur dix exemples — tout fonctionne parfaitement. Mais à la centième requête, le réseau de neurones oublie soudain de fermer un guillemet, ajoute la phrase « Voici votre réponse ! » au début de la réponse, ou invente un champ qui n'existe pas. En conséquence, Pydantic lève une erreur de validation, et votre service plante.
Habituellement, les développeurs résolvent ce problème avec des nouvelles tentatives vers l'API, des expressions régulières complexes, ou des tentatives pour « corriger » la réponse corrompue après sa génération. Les développeurs de l'équipe .txt ont adopté une approche différente et ont créé Outlines — une bibliothèque qui guide le processus de génération de texte au niveau du token individuel.

Comment fonctionne la génération contrôlée
La plupart des frameworks traitent les LLMs comme une boîte noire : ils envoient du texte et attendent une chaîne prête. Outlines intercepte le contrôle pendant l'échantillonnage. À chaque étape de génération, la bibliothèque vérifie quels tokens du vocabulaire du modèle correspondent au schéma spécifié, et lesquels violent les règles.
Si vous avez demandé un nombre, la bibliothèque met simplement à zéro la probabilité d'échantillonnage pour tous les tokens contenant des lettres ou de la ponctuation. Le modèle ne peut physiquement pas sélectionner un symbole invalide. Le résultat n'est pas l'espoir d'un JSON valide, mais une structure garantie correcte dès la première tentative.
Cette approche économise des tokens et du temps. Vous n'avez plus besoin de demander au modèle dans l'instruction de « ne pas ajouter de texte supplémentaire » ou d'exécuter une régénération lorsque l'analyse échoue.
Ce que peut faire la bibliothèque
L'interface d'Outlines essaie de mimer la syntaxe familière des types Python. Vous passez simplement le type de données souhaité junto con l'instruction.
Fixation des options de réponse
Si vous avez besoin d'un choix parmi un ensemble limité de valeurs, définissez-le via Literal ou Enum. Le modèle n'écrira pas de raisonnement long — il produira immédiatement l'une des valeurs spécifiées.
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
Génération à partir de schémas Pydantic
Pour les objets complexes, vous pouvez utiliser les modèles Pydantic standard. Outlines construit une grammaire basée sur le schéma et garantit que la structure de la réponse est entièrement conforme.
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
Expressions régulières et grammaires
Si les modèles Pydantic sont trop lourds pour votre tâche, vous pouvez définir une expression régulière stricte. C'est pratique pour extraire des numéros de téléphone, des dates, des codes postaux, ou créer des DSL internes.
Avec quels modèles cela fonctionne-t-il
Outlines s'adapte à votre pile. La bibliothèque supporte plusieurs modes :
- Inférence locale via
transformersetllama.cpp - Solutions serveur basées sur vLLM et Ollama
- APIs externes comme OpenAI et Gemini
Le plus grand benefit de la bibliothèque se réalise lorsque vous travaillez avec vos propres modèles locaux ou des serveurs d'inférence sur site. C'est là que le contrôle direct du masquage des tokens fournit une garantie de structure à 100% et accélère l'opération.
Cas d'utilisation en production
En pratique, la bibliothèque aborde plusieurs tâches de développement courantes à la fois :
- Tri automatique des tickets. Extraire la catégorie, l'urgence et les tags des emails clients entrants sans le risque d'obtenir un objet cassé.
- Extraction d'entités avec gestion des données incomplètes. Via les types
Union, vous pouvez permettre au modèle de retourner soit un objet rempli, soit une chaîne explicite avec un message sur les informations manquantes. - Appel de fonctions. Vous pouvez passer une fonction Python régulière au modèle, et Outlines extrait automatiquement les types de ses arguments pour former les paramètres d'appel corrects.
- Catégorisation du catalogue produits. Analyser rapidement les descriptions de produits en catégories, marques et caractéristiques clés.
Limitations et nuances
Avec tous les avantages, il est important de comprendre les spécificités de la technologie. Le calcul des masques pour les tokens nécessite des ressources supplémentaires. Si votre schéma Pydantic se compose de dizaines d'objets imbriqués et d'expressions régulières complexes, la préparation de la grammaire avant le début de la génération peut prendre un certain temps.
De plus, si vous travaillez exclusivement via l'API OpenAI, la bibliothèque utilisera les mécanismes internes du fournisseur (Structured Outputs / JSON Mode). Dans ce cas, Outlines agit comme une interface unifiée pratique, mais le processus d'échantillonnage lui-même est contrôlé par le serveur OpenAI.
Outlines résout un véritable problème d'ingénierie que chaque équipe rencontre en amenant les LLMs en production. Le projet élimine l'instabilité de la génération et permet de travailler avec les réseaux de neurones comme des fonctions typées régulières. Si vous construisez des services backend ou des agents autonomes basés sur des modèles ouverts, cet outil mérite définitivement une place dans votre boîte à outils.
Projets similaires