Hoe je een neuraal netwerk geldige JSON laat uitvoeren zonder workarounds en herhaalde verzoeken
Iedereen die heeft geprobeerd een taalmodel te koppelen aan een echte backend, is dit probleem tegengekomen. Je schrijft een gedetailleerde prompt, vraagt het model om strikt JSON te retourneren met de vereiste structuur, test het op tien voorbeelden — alles werkt prima. Maar bij het honderdste verzoek vergeet het neurale netwerk plotseling een aanhalingsteken te sluiten, voegt het de zin "Hier is je antwoord!" toe aan het begin van de reactie, of verzint een niet-bestaand veld. Als gevolg daarvan gooit Pydantic een validatiefout en crasht je service.
Meestal lossen ontwikkelaars dit probleem op door herhaalde verzoeken naar de API te sturen, complexe reguliere expressies, of te proberen het gecorrumpeerde antwoord te "repareren" nadat het is gegenereerd. De ontwikkelaars van het .txt-team kozen een andere aanpak en creëerden Outlines — een bibliotheek die het tekstgeneratieproces begeleidt op individueel tokenniveau.

Hoe gecontroleerde generatie werkt
De meeste frameworks werken met LLMs als een black box: ze sturen tekst en wachten op een kant-en-klare string. Outlines onderschept de controle tijdens het samplen. Bij elke generatiestap controleert de bibliotheek welke tokens uit de vocabulaire van het model overeenkomen met het opgegeven schema en welke de regels schenden.
Als je om een getal vraagt, zet de bibliotheek gewoon de samplingkans op nul voor alle tokens die letters of leestekens bevatten. Het model kan fysiek geen ongeldig symbool selecteren. Het resultaat is geen hoop op geldige JSON, maar een gegarandeerd correcte structuur vanaf de eerste poging.
Deze aanpak bespaart tokens en tijd. Je hoeft het model niet meer in de prompt te vragen "geen extra tekst toe te voegen" of regeneratie uit te voeren wanneer het parsen mislukt.
Wat de bibliotheek kan doen
De interface van Outlines probeert vertrouwde Python-typesyntax na te bootsen. Je geeft simpelweg het gewenste datatype samen met de prompt door.
Antwoordopties vastleggen
Als je een keuze uit een beperkte set waarden nodig hebt, definieer je dit via Literal of Enum. Het model zal geen lange redenering schrijven — het voert onmiddellijk een van de opgegeven waarden uit.
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
Generatie op basis van Pydantic-schema's
Voor complexe objecten kun je standaard Pydantic-modellen gebruiken. Outlines bouwt een grammatica op basis van het schema en zorgt ervoor dat de responsstructuur volledig conform is.
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
Reguliere expressies en grammatica's
Als Pydantic-modellen te omslachtig zijn voor je taak, kun je een strikte reguliere expressie definiëren. Dit is handig voor het extraheren van telefoonnummers, datums, postcodes of het creëren van interne DSL's.
Met welke modellen het werkt
Outlines past zich aan je stack aan. De bibliotheek ondersteunt meerdere modi:
- Lokale inferentie via
transformersenllama.cpp - Server-oplossingen op basis van vLLM en Ollama
- Externe API's zoals OpenAI en Gemini
Het grootste voordeel van de bibliotheek wordt gerealiseerd bij het werken met je eigen lokale modellen of on-premises inferentie-servers. Daar biedt directe token-maskeringscontrole een 100% garantie op structuur en versnelt de werking.
Productiegebruiksscenario's
In de praktijk pakt de bibliotheek verschillende veelvoorkomende ontwikkelingstaken tegelijk aan:
- Automatische ticket sortering. Categorie, urgentie en tags extraheren uit inkomende klant-e-mails zonder het risico op een gebroken object.
- Entiteit extractie met verwerking van onvolledige data. Via
Union-typen kun je het model toestaan om ofwel een ingevuld object of een expliciete string met een bericht over ontbrekende informatie te retourneren. - Functieaanroepen. Je kunt een gewone Python-functie aan het model doorgeven, en Outlines extraheert automatisch typen uit de argumenten om correcte aanroepparameters te vormen.
- Productcatalogus categorisering. Productbeschrijvingen snel parsen naar categorieën, merken en belangrijke kenmerken.
Beperkingen en nuances
Met alle voordelen is het belangrijk om de specificaties van de technologie te begrijpen. Het berekenen van maskers voor tokens vereist extra resources. Als je Pydantic-schema bestaat uit tientallen geneste objecten en complexe reguliere expressies, kan de grammaticavoorbereiding voordat de generatie begint enige tijd kosten.
Bovendien, als je uitsluitend via de OpenAI API werkt, zal de bibliotheek de interne mechanismen van de provider gebruiken (Structured Outputs / JSON Mode). In dit geval fungeert Outlines als een handige uniforme interface, maar het samplingproces zelf wordt gecontroleerd door de OpenAI-server.
Outlines lost een echt technisch probleem op dat elk team tegenkomt bij het in productie nemen van LLMs. Het project verwijdert onstabiliteit uit de generatie en maakt het mogelijk om met neurale netwerken te werken als gewone getypte functies. Als je backend-services of autonome agenten bouwt op basis van open modellen, verdient dit gereedschap zeker een plaats in je toolkit.
Gerelateerde projecten