
LLM strukturerade utdata är mekanismen som garanterar att ett språkmodells svar överensstämmer med ett fördefinierat schema -- inte bara giltig JSON, utan schemagiltig JSON med exakt de fält, typer och begränsningar du angett. Alla stora leverantörer stöder detta nu som standard, och det har förändrat hur produktions-LLM-applikationer byggs.
Snabbsammanfattning: Strukturerade Utdata i Korthet
Om du har ont om tid, här är läget 2026:
| Aspekt | Detaljer |
|---|---|
| Vad det är | Schemadrivna svar från LLM:er -- garanterad struktur, inte "bästa möjliga" |
| Vem stöder det | OpenAI, Anthropic, Gemini, Cohere, xAI (Grok), plus lokalt via Ollama/vLLM |
| Nyckelmekanismen | Begränsad avkodning -- ogiltiga tokens maskeras före sampling |
| JSON-läge vs. Strikt läge | JSON-läge = bara giltig syntax. Strikt läge = fullständig schemaöverensstämmelse |
| Python-bibliotek | Pydantic (BaseModel + Field) för schemadefinition |
| TypeScript-bibliotek | Zod (z.object + .describe) för schemadefinition |
| Bästa startmetod | OpenAI med Pydantic eller Zod via nativt SDK |
| Bästa produktionsbibliotek | Instructor (Python) eller nativt SDK (TypeScript) |
| Största fallgropen | Att lägga resonemangsfältet EFTER svarsfältet -- modellen bestämmer innan den tänker |
| Latensskostnaden | 50-200ms vid första anropet (schemakompilering), cachelagrat efteråt |
Låt oss nu gå igenom varje del.
Vad Är LLM Strukturerade Utdata?
Strukturerade utdata är skillnaden mellan att hoppas att ett LLM returnerar giltig JSON och att garantera det. När du aktiverar strukturerade utdata kan modellen fysiskt inte producera tokens som bryter mot ditt schema. Du definierar ett JSON Schema (eller en Pydantic-modell, eller ett Zod-schema), skickar det till API:t och får tillbaka ett svar som matchar det varje gång.
Varför spelar detta roll? Före strukturerade utdata skrev utvecklare sköra regex-parsers, omslöt varje LLM-anrop i try/catch JSON.parse-block, och fick ändå hantera "nästan rätta" svar -- giltig JSON som saknade ett fält eller hade fel typ. Hela den felklassen är borta.
Det finns tre nivåer av strukturtillämpning, och de representerar en tydlig evolution:
- Promptteknik -- "Returnera gärna JSON med dessa fält." Opålitligt. Modellen kanske följer 80-90% av gångerna.
- JSON-läge -- Garanterar syntaktiskt giltig JSON, men tillämpar inte ditt schema. Du kan få
{"foo": "bar"}när du förväntade dig{"name": string, "age": number}. - Strikt läge / Begränsad avkodning -- Garanterar 100% schemaöverensstämmelse. Modellen kan bokstavligen inte producera ogiltiga tokens. Det är vad "strukturerade utdata" betyder 2026.
Från och med tidigt 2026 stöder OpenAI, Anthropic och Google Gemini alla native strukturerade utdata. Ekosystemet har konvergerat.
Slutsats: Om du analyserar LLM-svar med regex eller JSON.parse i produktion gör du det på det svåra sättet. Native strukturerade utdata eliminerar hela den felklassen.
JSON-läge vs. Strikt läge: Vad Har Egentligen Förändrats?
Den här distinktionen förvirrar många utvecklare eftersom namnen låter liknande. Det är de inte.
| Funktion | JSON-läge | Strikt läge (Strukturerade Utdata) |
|---|---|---|
| API-parameter | type: "json_object" | type: "json_schema" med strict: true |
| Garanterar giltig JSON | Ja | Ja |
| Garanterar schemaöverensstämmelse | Nej | Ja |
| Mekanism | Post-hoc tokenbias | Begränsad avkodning (FSM) |
| Kan returnera oväntade fält | Ja | Nej |
| Kan utelämna obligatoriska fält | Ja | Nej |
| Typpåtvingande | Inget | Fullständigt (string, number, array, osv.) | | När man använder det | Du har inget schema i förväg | Allt i produktion |
Tidslinjen: OpenAI introducerade JSON-läge i slutet av 2023. Det var ett steg framåt, men utvecklare insåg snabbt att "giltig JSON" inte räckte -- de behövde schemagiltig JSON. I augusti 2024 lanserade OpenAI Strukturerade Utdata med Strikt läge, som använder begränsad avkodning för att garantera schemaöverensstämmelse. Mot 2025-2026 hade alla stora leverantörer antagit samma tillvägagångssätt.
JSON-läge har fortfarande ett smalt användningsfall: när du verkligen inte känner till svarets form i förväg och bara vill ha någon giltig JSON för ostrukturerad utforskning. Men det är sällsynt i produktion.
Slutsats: Använd strikt läge för allt i produktion. JSON-läge är effektivt föråldrat för schemaanknutna användningsfall. Om du har ett schema (och det bör du ha), använd type: "json_schema" med strict: true.
Hur Fungerar Egentligen Begränsad Avkodning?
Här är mekanismen som gör 100% schemaöverensstämmelse möjlig -- inte 99,9%, utan bokstavligen 100%.
När du skickar ett JSON Schema till en leverantör med Strikt läge aktiverat kompileras schemat till en ändlig tillståndsmaskin (FSM). Denna FSM representerar varje giltig väg genom ditt schema. Vid varje tokengenerseringssteg kontrollerar slutledningsenginen vilka tokens som håller utdatan på en giltig väg och vilka som inte gör det. Ogiltiga tokens får sina logits satta till negativt oändlighet före sampling, vilket innebär att de har nollsannolikhet att väljas.
<!-- IMAGE: constrained-decoding diagram showing FSM token masking during structured output generation -->Tänk på det som automatisk komplettering på steroider. Om modellen precis har producerat {"rating": och ditt schema säger att rating är ett heltal, är de enda tillåtna nästa tokens siffertokens. Citationstecken, bokstäver, hakparenteser -- allt maskerat. Modellen kan inte producera "fem" även om den "vill".
Det här är samma kärnmekanism som används av XGrammar (motorn bakom vLLM, SGLang och de flesta lokala slutledningsservrar) och Outlines (Python-biblioteket med öppen källkod för begränsad generering). API-leverantörerna har bara byggt in det i sin slutledningsinfrastruktur.
Det finns ett avvägningsbyte att känna till: den första begäran med ett nytt schema ger en kompileringslatenstillskott (vanligtvis 50-200ms) medan FSM byggs. Efterföljande begäranden med samma schema använder en cachelagrad FSM och lägger till nästan noll overhead. Det finns också en subtil kvalitetshänsyn -- att begränsa tokenvokabulären kan ibland minska utdatakvaliteten för kreativa eller fritextfält, så håll dina scheman fokuserade på verkligt strukturerad data.
Slutsats: Begränsad avkodning är det som separerar "fungerar vanligtvis" från "fungerar alltid." Det är ingenjörsarbetet som gör strukturerade utdata produktionsredo.
Implementering hos Flera Leverantörer: OpenAI, Anthropic och Gemini
Här är något som ingen av de andra guiderna visar dig: samma extraktionsuppgift implementerad hos alla tre stora leverantörer. Vi extraherar en strukturerad produktrecension från ostrukturerad text. Se även vår bästa LLM structured output-bibliotek.
Pydantic-schemat (delat mellan alla leverantörer):
from pydantic import BaseModel, Field
from typing import Literal
class ProductReview(BaseModel):
reasoning: str = Field(description="Think through the review before scoring")
rating: int = Field(description="Rating from 1-5", ge=1, le=5)
sentiment: Literal["positive", "negative", "neutral"]
pros: list[str] = Field(description="Key positive points")
cons: list[str] = Field(description="Key negative points")
summary: str = Field(description="One-sentence summary")OpenAI-implementering
from openai import OpenAI
client = OpenAI()
response = client.beta.chat.completions.parse(
model="gpt-4o-2024-08-06",
messages=[
{"role": "system", "content": "Extract a structured review from the text."},
{"role": "user", "content": review_text}
],
response_format=ProductReview, # Pydantic-modell direkt
)
review = response.choices[0].message.parsed # Typad ProductReview-objektOpenAI:s implementering är den mest mognadsna. parse()-metoden accepterar en Pydantic-modell direkt och returnerar ett typad objekt. En begränsning: OpenAI:s Strikt läge stöder en delmängd av JSON Schema -- ingen $ref, begränsad anyOf, och alla fält måste vara obligatoriska med additionalProperties: false.
Anthropic-implementering
from anthropic import Anthropic
client = Anthropic()
response = client.messages.create(
model="claude-sonnet-4-5-20250514",
max_tokens=1024,
messages=[
{"role": "user", "content": f"Extract a structured review:\n\n{review_text}"}
],
output_config={
"format": {
"type": "json_schema",
"json_schema": ProductReview.model_json_schema()
}
}
)
import json
review_data = json.loads(response.content[0].text)
review = ProductReview(**review_data)Anthropics native strukturerade utdata använder output_config.format med ett JSON Schema. Det nådde GA i tidigt 2026. Anthropic stöder också det äldre mönstret att definiera ett "falskt" verktyg och extrahera via tool_use -- det fungerar fortfarande, men native strukturerade utdata är renare för ren extraktion.
Gemini-implementering
from google import genai
client = genai.Client()
response = client.models.generate_content(
model="gemini-2.0-flash",
contents=f"Extract a structured review:\n\n{review_text}",
config={
"response_mime_type": "application/json",
"response_schema": ProductReview, # Pydantic-modell direkt
}
)
import json
review = ProductReview(**json.loads(response.text))Gemini stöder Pydantic-modeller direkt i Python SDK via response_schema. En unik funktion: Gemini respekterar propertyOrdering i schemat, så du kan styra fältutdataordningen (användbart för resonemang-först-mönstret).
Leverantörsjämförelse
| Funktion | OpenAI | Anthropic | Gemini |
|---|---|---|---|
| API-parameter | response_format | output_config.format | response_schema |
| Schemainmatning | Pydantic eller JSON Schema | JSON Schema | Pydantic eller JSON Schema |
| Strikt läge | strict: true | Implicit med json_schema | Implicit |
| Streaming | Ja (partiell JSON) | Ja | Ja |
| Hantering av avvisanden | message.refusal-fält | Felsvar | Felsvar |
| Verktygsanvändning alternativ | Ja | Ja (ursprunglig metod) | Ja |
| Schemakompileringscache | Ja (serversidan) | Ja | Ja |
| Egenskapsordning | Inget nativt stöd | Nej | Ja (propertyOrdering) |
Slutsats: OpenAI har den mest polerade DX med sin parse()-metod. Anthropic erbjuder de mest kapabla underliggande modellerna. Geminis egenskapsordning är unikt användbar. Alla tre klarar uppgiften -- välj baserat på din befintliga leverantörsrelation.
Pydantic-mönster för Python-utvecklare
Pydantic är de facto-standarden för att definiera strukturerade utdatascheman i Python. Här är mönstren som spelar roll.
Grundschema med Beskrivningar
from pydantic import BaseModel, Field
from typing import Literal, Optional
class ExtractedEntity(BaseModel):
reasoning: str = Field(description="Think step by step about the entity")
name: str = Field(description="Full name of the entity")
entity_type: Literal["person", "company", "location"]
confidence: float = Field(description="Confidence score 0.0-1.0", ge=0.0, le=1.0)
context: Optional[str] = Field(description="Surrounding context, if relevant")Dessa description-strängar är inte bara för dokumentation -- de blir en del av JSON Schema som skickas till modellen och påverkar direkt vad modellen genererar. Tänk på dem som promptteknik inom schemat.
Nästlade Modeller
class Address(BaseModel):
street: str
city: str
country: str
postal_code: Optional[str] = None
class Company(BaseModel):
reasoning: str = Field(description="Analysis of the company details")
name: str
industry: Literal["tech", "finance", "healthcare", "retail", "other"]
headquarters: Address # Nästlad modell
key_products: list[str] = Field(description="Top 3 products or services")Håll nästlingen till max 2-3 nivåer. Djupt nästlade scheman ökar felfrekvensen och saktar ner schemakompileringen.
Resonemang-Först-Mönstret
Det här är det enskilt mest inflytelserika schemadesignmönstret. Placera ett reasoning-fält före dina svarsfält:
# Dåligt -- modellen bestämmer sig för ett svar innan den tänker
class ClassificationBad(BaseModel):
category: Literal["spam", "ham"]
confidence: float
# Bra -- modellen resonerar igenom problemet först
class ClassificationGood(BaseModel):
reasoning: str = Field(description="Analyze the text before classifying")
category: Literal["spam", "ham"]
confidence: float = Field(ge=0.0, le=1.0)LLM:er genererar tokens från vänster till höger. Fältordningen är promptordningen. Resonemang först innebär att modellen måste arbeta igenom problemet innan den binder sig till en kategori. Det är tankekedja inbakat i schemat.
JSON Schema-export
# Generera JSON Schema för vilken Pydantic-modell som helst
schema = ProductReview.model_json_schema()
# Skicka detta till vilken leverantör som helst som accepterar rå JSON SchemaSlutsats: Pydantic + beskrivande fält + resonemang-först-ordning är Python-triaden för strukturerade utdata. Behärska dessa tre mönster och du hanterar 90% av användningsfallen.
Zod-mönster för TypeScript-utvecklare
Zod är TypeScript-motsvarigheten till Pydantic -- och lika central för arbetsflöden med strukturerade utdata.
Grundschema med Beskrivningar
import { z } from "zod";
const ProductReview = z.object({
reasoning: z.string().describe("Think through the review before scoring"),
rating: z.number().int().min(1).max(5),
sentiment: z.enum(["positive", "negative", "neutral"]),
pros: z.array(z.string()).describe("Key positive points"),
cons: z.array(z.string()).describe("Key negative points"),
summary: z.string().describe("One-sentence summary"),
});
// Härleda TypeScript-typen automatiskt
type ProductReview = z.infer<typeof ProductReview>;Precis som Pydantics Field(description=...) blir Zods .describe() en del av JSON Schema och guidar modellens utdata.
Integration med OpenAI Node SDK
import OpenAI from "openai";
import { zodResponseFormat } from "openai/helpers/zod";
const client = new OpenAI();
const response = await client.beta.chat.completions.parse({
model: "gpt-4o-2024-08-06",
messages: [
{ role: "system", content: "Extract a structured review." },
{ role: "user", content: reviewText },
],
response_format: zodResponseFormat(ProductReview, "product_review"),
});
const review = response.choices[0].message.parsed; // Typad!Integration med Vercel AI SDK
import { generateObject } from "ai";
import { openai } from "@ai-sdk/openai";
const { object: review } = await generateObject({
model: openai("gpt-4o"),
schema: ProductReview,
prompt: `Extract a structured review:\n\n${reviewText}`,
});
// review är fullt typad som ProductReviewVercel AI SDK använder Zod nativt med generateObject(), vilket gör det till den renaste TypeScript-integrationen. Det fungerar med OpenAI, Anthropic, Gemini och andra leverantörer via ett enhetligt API.
JSON Schema-konvertering
import { zodToJsonSchema } from "zod-to-json-schema";
const jsonSchema = zodToJsonSchema(ProductReview);
// Använd med vilken leverantör som helst som accepterar rå JSON SchemaSlutsats: Zod + .describe() + Vercel AI SDK är TypeScript-stacken för strukturerade utdata. Om du är i Node/Next.js-ekosystemet är detta vägen med minst motstånd.
Strukturerade Utdata vs. Funktionsanrop: När Använder Du Vad?
Det här är en av de vanligaste förvirringskällorna. Båda involverar scheman, båda returnerar strukturerad data -- men de löser olika problem.
Strukturerade utdata säger: "Ge mig data i denna exakta form." Det är för extraktion, klassificering och formatering. Du drar ut strukturerad information från ostrukturerad text.
Funktionsanrop (verktygsanvändning) säger: "Här är åtgärder du kan vidta -- bestäm vilken du ska köra och ge argumenten." Det är för agentarbetsflöden där modellen väljer bland flera verktyg och utlöser åtgärder.
Förvirringen är historiskt förståelig. Anthropics ursprungliga "strukturerade utdata" var bokstavligen funktionsanrop -- du definierade ett falskt verktyg kallat extract_review och grep argumenten. Det fungerar fortfarande, men native strukturerade utdata är enklare för ren extraktion.
| Scenario | Bästa tillvägagångssätt | Varför |
|---|---|---|
| Extrahera data från text | Strukturerade utdata | Direkt, lägre latens, enstaka schema |
| Klassificera i kategorier | Strukturerade utdata | Ett svar, ett schema |
| Agent som bestämmer vilket verktyg att anropa | Funktionsanrop | Modellen väljer bland flera verktyg |
| Fler-stegs-orkestrering | Funktionsanrop | Sekventiella verktygsanrop |
| Extrahera data OCH bestämma nästa åtgärd | Båda | Strukturerade utdata för extraktion, funktionsanrop för orkestrering |
Strukturerade utdata driver verktygsanropspipelinen i AI-agentsystem. Se vår guide om AI-agenter för företag för hur dessa passar in i produktionsarbetsflöden.
Slutsats: Använd strukturerade utdata när du vet vilken form data ska ha. Använd funktionsanrop när modellen behöver välja en åtgärd. I praktiken använder de flesta applikationer båda -- strukturerade utdata för dataextraktion och funktionsanrop för agentorkestrering.
Produktionsmönster: Fel, Återförsök och Streaming
Att få strukturerade utdata att fungera i en demo är enkelt. Att hålla dem pålitliga i produktion kräver att hantera tre saker: avvisanden, valideringsfel och streaming. Du kan också vara intresserad av guide till LLM function calling.
Hantering av Avvisanden
Ibland vägrar en modell att generera din begärda utdata -- typiskt för att säkerhetsfilter flaggade inmatningen. När detta händer returnerar API:er för strukturerade utdata inte ditt schema. De returnerar ett avvisande.
response = client.beta.chat.completions.parse(
model="gpt-4o-2024-08-06",
messages=messages,
response_format=ProductReview,
)
# Kontrollera ALLTID avvisandet innan du kommer åt analyserat innehåll
if response.choices[0].message.refusal:
print(f"Model refused: {response.choices[0].message.refusal}")
else:
review = response.choices[0].message.parsedOm du hoppar över avvisandekontrollen och försöker komma åt .parsed vid ett avvisande får du None och ett förvirrande nedströmsfel. Kontrollera alltid först.
Återförsöksmönster med Valideringsfeedback
Schemaöverensstämmelse garanteras av begränsad avkodning, men semantisk korrekthet är det inte. Modellen kan returnera {"rating": 1, "sentiment": "positive"} -- giltigt schema, motsägelsefullt innehåll. Det är där validering + återförsök kommer in.
import instructor
client = instructor.from_openai(OpenAI())
# Instructor hanterar återförsök automatiskt
review = client.chat.completions.create(
model="gpt-4o",
response_model=ProductReview,
max_retries=3, # Återförsök med valideringsfelsfeedback
messages=[
{"role": "user", "content": review_text}
],
)Instructor skickar tillbaka valideringsfelet till modellen vid återförsök, så att den kan korrigera sig. För manuella återförsöksmönster utan Instructor:
from pydantic import ValidationError
for attempt in range(3):
try:
response = client.beta.chat.completions.parse(
model="gpt-4o-2024-08-06",
messages=messages,
response_format=ProductReview,
)
review = response.choices[0].message.parsed
# Kör ytterligare semantisk validering här
break
except ValidationError as e:
messages.append({"role": "assistant", "content": str(response)})
messages.append({"role": "user", "content": f"Validation error: {e}. Fix it."})Streaming av Strukturerade Utdata
För stora strukturerade svar -- långa arrayer, många fält, komplexa nästlade objekt -- låter streaming dig rendera partiella resultat progressivt.
import instructor
client = instructor.from_openai(OpenAI())
# Streama partiella resultat allt eftersom fälten fylls i
review_stream = client.chat.completions.create_partial(
model="gpt-4o",
response_model=ProductReview,
messages=[{"role": "user", "content": review_text}],
)
for partial_review in review_stream:
# Fält fylls i ett i taget allt eftersom tokens streamas
if partial_review.summary:
print(f"Summary so far: {partial_review.summary}")En fallgrop: Enskilda streaming-bitar är inte schemgiltiga på egen hand. reasoning-fältet kan vara ifyllt medan rating fortfarande är None. Planera ditt gränssnitt därefter -- visa ett laddningstillstånd för icke-ifyllda fält.
Slutsats: Avvisandekontroller är icke-förhandlingsbara. Återförsök med valideringsfeedback fångar semantiska fel. Streaming är värt det för svar som tar mer än ett par sekunder.
Jämförelse av Bibliotek för Strukturerade Utdata
Du kan använda strukturerade utdata via native API:er, men bibliotek lägger till validering, återförsök, streaming och stöd för flera leverantörer. Här är läget.
Instructor är det mest populära alternativet med 11K+ GitHub-stjärnor och 3M+ månatliga nedladdningar. Det omsluter OpenAI, Anthropic, Gemini, Cohere, Ollama och mer med ett enhetligt Pydantic-baserat gränssnitt. Nyckelfunktioner: automatiska återförsök med valideringsfeedback, streaming via create_partial() och enkel installation (instructor.from_openai(client)). Om du är ett Python-team, börja här.
BAML tar ett annat tillvägagångssätt: schema-först via ett anpassat DSL. Du definierar scheman i .baml-filer och auto-genererar klienter för Python, TypeScript, Ruby och mer. Dess SAP-algoritm (schema-aligned parsing) hanterar smidigt röriga modellutdata. Bäst för tvärspråkliga team eller när du vill ha kontrakt mellan ditt LLM-lager och applikationslagret. Avvägning: extra byggsteg och ny syntax att lära sig.
LangChain erbjuder .with_structured_output(schema) för leverantörsoberoende strukturerade utdata. Bekvämt om du redan är i LangChain-ekosystemet. Avvägning: det är ett tungt beroende, och abstraktionen kan dölja leverantörsspecifika funktioner du kanske behöver.
Native API:er -- direkta anrop med response_format / output_config -- kräver inga beroenden utöver leverantörens SDK. Du får full kontroll och full insyn. Bäst för enkla användningsfall eller team som föredrar minimal abstraktion.
| Bibliotek | Språk | Leverantörer | Auto-återförsök | Streaming | GitHub-stjärnor | Inlärningskurva |
|---|---|---|---|---|---|---|
| Instructor | Python, TS | 15+ | Ja | Ja | 11K+ | Låg |
| BAML | Python, TS, Ruby, Go | Alla (DSL-agnostisk) | Ja | Ja | 7K+ | Medel |
| LangChain | Python, TS | 20+ | Delvis | Ja | 100K+ | Medel-Hög |
| Native API:er | Valfri | 1 per SDK | Nej | Ja | N/A | Låg |
Att välja rätt bibliotek för strukturerade utdata är en del av ett bredare AI-stackbeslut. Vi bryter ner hela stacken i vår guide för Bästa AI-stack för SaaS.
Se vår Bästa bibliotek för LLM Strukturerade Utdata [kommer snart] för en djupgående jämförelse av Instructor, BAML, Mirascope och mer.
Slutsats: Börja med Instructor för Python, native API:er för TypeScript. Gå till BAML om du behöver tvärspråkliga schemakontrakt. Undvik LangChain bara för strukturerade utdata -- det är överdrivet.
Bästa Praxis för Schemadesign (och Vanliga Misstag)
Ditt schemadesign påverkar direkt utdatakvaliteten. Här är mönstren som spelar roll och misstagen som kostar dig noggrannhet.
Sätta Resonemang Före Svar
Vi täckte detta i Pydantic-avsnittet, men det förtjänar att upprepas eftersom det är det mest inflytelserika designbeslutet:
# Innan: modellen gissar svaret, rationaliserar det sedan
class Bad(BaseModel):
answer: str
reasoning: str
# Efter: modellen tänker först, binder sig sedan
class Good(BaseModel):
reasoning: str = Field(description="Think step by step")
answer: strLLM:er genererar från vänster till höger. Fältordning är promptordning. Resonemang först innebär att modellen måste arbeta igenom problemet innan den binder sig till ett svar.
Anti-mönster-tabellen
| Misstag | Problem | Åtgärd |
|---|---|---|
| Resonemangsfält efter svar | Modellen bestämmer innan den tänker | Flytta resonemang före svar |
| Djupt nästlat (4+ nivåer) | Högre felfrekvens, långsammare kompilering | Platta ut till 2-3 nivåer |
| Inga fältbeskrivningar | Modellen gissar vad du vill | Lägg till .describe() / Field(description=...) |
| Saknad null-hantering | Modellen hallucinerar ett värde för att fylla fältet | Använd Optional / .nullable() |
| Alltför stora scheman (50+ fält) | Kompileringstimeout, kvalitetsförsämring | Dela upp i flera anrop |
| Vaga enum-alternativ | Modellen väljer fel kategori | Använd specifika, icke-överlappande alternativ |
Hantera Null-värden Explicit
Om ett fält kanske inte har data i källtexten, gör det valfritt. Att tvinga ett obligatoriskt fält när data inte finns leder till hallucination:. Läs mer om guide till LLM-utvärdering.
class PersonInfo(BaseModel):
name: str # Alltid närvarande
email: Optional[str] = Field(None, description="Email if mentioned, null otherwise")
phone: Optional[str] = Field(None, description="Phone if mentioned, null otherwise")Hålla Scheman Fokuserade
Ett schema per uppgift. Försök inte extrahera allt i ett enda massivt schema. Om du behöver 50+ fält, dela upp i flera extraktionsanrop. OpenAI:s strikta läge har praktiska gränser för schemakomplexitet, och även när det fungerar försämrar mycket stora scheman utdatakvaliteten.
Slutsats: Resonemang-först, beskrivande fält, explicita null-värden och fokuserade scheman. Gör dessa fyra rätt och din noggrannhet för strukturerade utdata ökar mätbart.
Strukturerade Utdata med Lokala LLM:er
Du behöver ingen API-leverantör för strukturerade utdata. Lokala slutledningsenginer stöder det via grammatikbaserad begränsad avkodning -- samma grundläggande mekanism, som körs på din egen hårdvara.
Ollama
Den enklaste vägen för lokala strukturerade utdata. Ollama accepterar ett JSON Schema via format-parametern:
import ollama
from pydantic import BaseModel
class Country(BaseModel):
name: str
capital: str
languages: list[str]
response = ollama.chat(
model="llama3.2",
messages=[{"role": "user", "content": "Tell me about Japan."}],
format=Country.model_json_schema(),
)
import json
country = Country(**json.loads(response.message.content))Ollama använder XGrammar internt för begränsad avkodning. Samma garanti som API-leverantörerna: 100% schemaöverensstämmelse.
vLLM och SGLang
För produktionskvalitets lokal slutledning stöder vLLM och SGLang båda strukturerade utdata via guided_json- och guided_regex-parametrar. XGrammar är standardbackenden och levererar nästan noll overhead på JSON-generering -- upp till 3,5x snabbare än alternativa grammatikmotorer.
Outlines
Outlines är Python-biblioteket med öppen källkod som pionjärade grammatikbaserad begränsad generering. Det fungerar med vilken Hugging Face-modell som helst och stöder JSON Schema-, regex- och fullständiga kontextfria grammatik (CFG/EBNF)-begränsningar. Det är också integrerat i vLLM och SGLang som ett grammatikbackendalternativ.
Den viktigaste skillnaden från API-leverantörer: lokal strukturerad utdata har inga begränsningar för schemadelmängder. Du kontrollerar grammatiken helt. Men modellkvaliteten varierar mer -- en lokal 7B-parametermodell matchar inte GPT-4o eller Claude på komplexa extraktionsuppgifter. Schemat är alltid giltigt; innehållskvaliteten beror på modellen.
Slutsats: Ollama för utveckling, vLLM/SGLang med XGrammar för produktion. Lokal strukturerad utdata är tillräckligt mogen för de flesta användningsfall, med förbehållet att mindre modeller producerar innehåll av lägre kvalitet inom schemat.
Vanliga Frågor
Vad är strukturerade utdata i LLM:er?
Strukturerade utdata är en mekanism som garanterar att ett LLM:s svar överensstämmer med ett fördefinierat JSON Schema. Till skillnad från ren text eller ens JSON-läge använder strukturerade utdata begränsad avkodning för att säkerställa att varje fält, typ och begränsning i ditt schema uppfylls -- 100% av gångerna, inte "vanligtvis".
Vad är skillnaden mellan JSON-läge och Strukturerade Utdata?
JSON-läge garanterar syntaktiskt giltig JSON men tillämpar inte ditt schema -- du kan få vilket giltigt JSON-objekt som helst. Strukturerade Utdata (Strikt läge) garanterar fullständig schemaöverensstämmelse via begränsad avkodning. Använd Strikt läge för produktion; JSON-läge är bara relevant när du inte har ett schema i förväg.
Vilka LLM-leverantörer stöder strukturerade utdata som standard?
OpenAI (sedan augusti 2024), Google Gemini (2024, utökat 2026), Anthropic (beta november 2025, GA tidigt 2026), Cohere och xAI (Grok) stöder alla native strukturerade utdata. På den lokala sidan stöder Ollama, vLLM och SGLang det via grammatikbaserad begränsad avkodning.
Hur garanterar begränsad avkodning schemaöverensstämmelse?
JSON Schema kompileras till en ändlig tillståndsmaskin (FSM). Vid varje tokengenerseringssteg är endast tokens tillåtna som håller utdatan på en giltig väg genom FSM -- ogiltiga tokens får sina logits satta till negativt oändlighet. Det innebär att ogiltiga tokens har nollsannolikhet att genereras, vilket ger dig en matematisk garanti, inte en statistisk.
Bör jag använda strukturerade utdata eller funktionsanrop?
Använd strukturerade utdata för extraktion och klassificering -- när du vill ha data i en specifik form. Använd funktionsanrop för agentarbetsflöden -- när modellen behöver bestämma vilken åtgärd den ska vidta. Många produktionsapplikationer använder båda: strukturerade utdata för dataextraktion och funktionsanrop för orkestrering.
Kan jag strömma strukturerade utdata?
Ja. OpenAI stöder streaming med parse()-metoden, och Instructor tillhandahåller create_partial() för att streama Pydantic-modeller som fylls fält för fält. Tänk på att enskilda streaming-bitar inte är individuellt schemgiltiga -- fält fylls i inkrementellt.
Vad är Instructor-biblioteket?
Instructor är det mest populära biblioteket för strukturerade utdata (11K+ GitHub-stjärnor, 3M+ månatliga nedladdningar). Det omsluter leverantörs-SDK:er med Pydantic-baserad validering, automatiska återförsök med valideringsfeedback och streamingstöd. Det fungerar med OpenAI, Anthropic, Gemini, Cohere, Ollama och 10+ andra leverantörer.
Fungerar strukturerade utdata med lokala LLM:er?
Ja. Ollama stöder strukturerade utdata via format-parametern med JSON Schema. vLLM och SGLang stöder det via guided_json-parametrar. Alla tre använder XGrammar eller Outlines för begränsad avkodning. Garantin för schemaöverensstämmelse är densamma som API-leverantörerna; innehållskvaliteten beror på modellen.
Vilka är vanliga schemadesignmisstag?
De främsta misstagen: lägga resonemangsfältet efter svarsfältet (modellen bestämmer innan den tänker), djupt nästlade scheman (4+ nivåer ökar fel), saknade fältbeskrivningar (modellen gissar avsikten), ingen null-hantering för valfria data (tvingar hallucination) och alltför stora scheman (50+ fält försämrar kvaliteten).
Lägger strukturerade utdata till latens?
Det finns en schemakompileringsoverhead vid den första begäran -- typiskt 50-200ms medan FSM byggs. Efterföljande begäranden med samma schema använder en cachelagrad FSM och lägger till nästan noll latens. För de flesta applikationer är detta försumbart jämfört med den totala modellinferenstiden.
Kan jag använda strukturerade utdata med bilder eller multimodala inmatningar?
Ja. Strukturerade utdata gäller svars-formatet, inte inmatningen. Du kan skicka en bild till GPT-4o eller Gemini med ett strukturerat utdataschema och få tillbaka en schemaöverensstämmande analys av bilden. Det är kraftfullt för visuella extraktionsarbetsflöden -- extrahera strukturerad data från kvitton, formulär eller produktbilder.