ai-machine-learning

Pålitlig JSON från Vilken LLM som Helst: Pydantic + Zod-Mönster för 2026

Skriven av Mert Batur
Uppdaterad May 12, 2026
15 läsning
Pålitlig JSON från Vilken LLM som Helst: Pydantic + Zod-Mönster för 2026

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:

AspektDetaljer
Vad det ärSchemadrivna svar från LLM:er -- garanterad struktur, inte "bästa möjliga"
Vem stöder detOpenAI, Anthropic, Gemini, Cohere, xAI (Grok), plus lokalt via Ollama/vLLM
NyckelmekanismenBegränsad avkodning -- ogiltiga tokens maskeras före sampling
JSON-läge vs. Strikt lägeJSON-läge = bara giltig syntax. Strikt läge = fullständig schemaöverensstämmelse
Python-bibliotekPydantic (BaseModel + Field) för schemadefinition
TypeScript-bibliotekZod (z.object + .describe) för schemadefinition
Bästa startmetodOpenAI med Pydantic eller Zod via nativt SDK
Bästa produktionsbibliotekInstructor (Python) eller nativt SDK (TypeScript)
Största fallgropenAtt lägga resonemangsfältet EFTER svarsfältet -- modellen bestämmer innan den tänker
Latensskostnaden50-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:

  1. Promptteknik -- "Returnera gärna JSON med dessa fält." Opålitligt. Modellen kanske följer 80-90% av gångerna.
  2. 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}.
  3. 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.

FunktionJSON-lägeStrikt läge (Strukturerade Utdata)
API-parametertype: "json_object"type: "json_schema" med strict: true
Garanterar giltig JSONJaJa
Garanterar schemaöverensstämmelseNejJa
MekanismPost-hoc tokenbiasBegränsad avkodning (FSM)
Kan returnera oväntade fältJaNej
Kan utelämna obligatoriska fältJaNej
<!-- | Typpåtvingande | Inget | Fullständigt (string, number, array, etc.) | -->

| 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):

python
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

python
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-objekt

OpenAI: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

python
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

python
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

FunktionOpenAIAnthropicGemini
API-parameterresponse_formatoutput_config.formatresponse_schema
SchemainmatningPydantic eller JSON SchemaJSON SchemaPydantic eller JSON Schema
Strikt lägestrict: trueImplicit med json_schemaImplicit
StreamingJa (partiell JSON)JaJa
Hantering av avvisandenmessage.refusal-fältFelsvarFelsvar
Verktygsanvändning alternativJaJa (ursprunglig metod)Ja
SchemakompileringscacheJa (serversidan)JaJa
EgenskapsordningInget nativt stödNejJa (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

python
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

python
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:

python
# 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

python
# 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 Schema

Slutsats: 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

typescript
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

typescript
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

typescript
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 ProductReview

Vercel 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

typescript
import { zodToJsonSchema } from "zod-to-json-schema";

const jsonSchema = zodToJsonSchema(ProductReview);
// Använd med vilken leverantör som helst som accepterar rå JSON Schema

Slutsats: 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.

ScenarioBästa tillvägagångssättVarför
Extrahera data från textStrukturerade utdataDirekt, lägre latens, enstaka schema
Klassificera i kategorierStrukturerade utdataEtt svar, ett schema
Agent som bestämmer vilket verktyg att anropaFunktionsanropModellen väljer bland flera verktyg
Fler-stegs-orkestreringFunktionsanropSekventiella verktygsanrop
Extrahera data OCH bestämma nästa åtgärdBådaStrukturerade 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.

python
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.parsed

Om 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.

python
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:

python
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.

python
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.

BibliotekSpråkLeverantörerAuto-återförsökStreamingGitHub-stjärnorInlärningskurva
InstructorPython, TS15+JaJa11K+Låg
BAMLPython, TS, Ruby, GoAlla (DSL-agnostisk)JaJa7K+Medel
LangChainPython, TS20+DelvisJa100K+Medel-Hög
Native API:erValfri1 per SDKNejJaN/ALå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:

python
# 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: str

LLM: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

MisstagProblemÅtgärd
Resonemangsfält efter svarModellen bestämmer innan den tänkerFlytta resonemang före svar
Djupt nästlat (4+ nivåer)Högre felfrekvens, långsammare kompileringPlatta ut till 2-3 nivåer
Inga fältbeskrivningarModellen gissar vad du villLägg till .describe() / Field(description=...)
Saknad null-hanteringModellen hallucinerar ett värde för att fylla fältetAnvänd Optional / .nullable()
Alltför stora scheman (50+ fält)Kompileringstimeout, kvalitetsförsämringDela upp i flera anrop
Vaga enum-alternativModellen väljer fel kategoriAnvä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.

python
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:

python
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.

Källor

Taggar

llm strukturerade utdatastructured outputsjson schemapydanticzodopenaianthropicgemini

Dela denna artikel

Starta ditt projekt

Redo att bygga något utöver det vanliga?

Låt oss göra verklighet av din idé. Vårt team hjälper dig gärna att bygga mjukvara som gör skillnad.