
Η δομημένη έξοδος LLM είναι ο μηχανισμός που εγγυάται ότι η απάντηση ενός γλωσσικού μοντέλου συμμορφώνεται με ένα προκαθορισμένο σχήμα, όχι απλώς έγκυρο JSON, αλλά JSON σύμφωνο με το σχήμα με τα ακριβή πεδία, τύπους και περιορισμούς που ορίσατε. Κάθε μεγάλος πάροχος πλέον την υποστηρίζει εγγενώς, και αυτό έχει αλλάξει τον τρόπο με τον οποίο κατασκευάζονται οι εφαρμογές LLM σε περιβάλλον παραγωγής.
Συνοπτική Επισκόπηση: Δομημένες Έξοδοι με μια Ματιά
Αν έχετε λίγο χρόνο, ακολουθεί η κατάσταση το 2026:
| Πτυχή | Λεπτομέρειες |
|---|---|
| Τι είναι | Απαντήσεις από LLMs με επιβολή σχήματος, εγγυημένη δομή, όχι «κατά το δυνατόν» |
| Ποιος το υποστηρίζει | OpenAI, Anthropic, Gemini, Cohere, xAI (Grok), plus local via Ollama/vLLM |
| Κύριος μηχανισμός | Περιορισμένη αποκωδικοποίηση, τα άκυρα tokens маскируются πριν τη δειγματοληψία |
| JSON Mode vs Strict Mode | JSON Mode = μόνο έγκυρη σύνταξη. Strict Mode = πλήρης συμμόρφωση με το σχήμα |
| Βιβλιοθήκη Python | Pydantic (BaseModel + Field) για ορισμό σχήματος |
| Βιβλιοθήκη TypeScript | Zod (z.object + .describe) για ορισμό σχήματος |
| Καλύτερη αρχική προσέγγιση | OpenAI με Pydantic ή Zod μέσω του native SDK |
| Καλύτερη βιβλιοθήκη παραγωγής | Instructor (Python) ή native SDK (TypeScript) |
| Μεγαλύτερη παγίδα | Η τοποθέτηση του πεδίου συλλογισμού ΜΕΤΑ το πεδίο απάντησης, το μοντέλο αποφασίζει πριν σκεφτεί |
| Επιβάρυνση καθυστέρησης | 50-200ms στην πρώτη κλήση (συμβολοποίηση σχήματος), cached στη συνέχεια |
Τώρα, ας αναλύσουμε κάθε κομμάτι.
Τι είναι οι Δομημένες Έξοδοι LLM;
Η δομημένη έξοδος είναι η διαφορά μεταξύ της ελπίδας ότι ένα LLM θα επιστρέψει έγκυρο JSON και της εγγύησης ότι θα το κάνει. Όταν ενεργοποιείτε τη δομημένη έξοδο, το μοντέλο φυσικά δεν μπορεί να παράγει tokens που παραβιάζουν το σχήμα σας. Ορίζετε ένα JSON Schema (ή μοντέλο Pydantic, ή σχήμα Zod), το περνάτε στο API και λαμβάνετε πίσω μια απάντηση που ταιριάζει με αυτό κάθε φορά.
Γιατί έχει σημασία αυτό; Πριν από τη δομημένη έξοδο, οι προγραμματιστές έγραφαν εύθραυστους parsers regex, τύλιγαν κάθε κλήση LLM σε μπλοκ try/catch JSON.parse και εξακολουθούσαν να αντιμετωπίζουν απαντήσεις «σχεδόν σωστές», έγκυρο JSON που lacked ένα πεδίο ή είχε λάθος τύπο. Αυτή η entire class of bug has gone.
Υπάρχουν τρία επίπεδα επιβολής δομής, τα οποία αντιπροσωπεύουν μια σαφή εξέλιξη:
- Prompt engineering, «Παρακαλώ επιστρέψτε JSON με αυτά τα πεδία». Αναξιόπιστο. Το μοντέλο μπορεί να συμμορφωθεί το 80-90% των φορών.
- JSON Mode, Εγγυάται συντακτικά έγκυρο JSON, αλλά δεν επιβάλλει το σχήμα σας. Μπορεί να λάβετε
{"foo": "bar"}όταν περιμένατε{"name": string, "age": number}. - Strict Mode / Περιορισμένη αποκωδικοποίηση, Εγγυάται 100% συμμόρφωση με το σχήμα. Το μοντέλο κυριολεκτικά δεν μπορεί να εξάγει άκυρα tokens. Αυτό σημαίνει «δομημένη έξοδος» το 2026.
Από τις αρχές του 2026, τα OpenAI, Anthropic και Google Gemini υποστηρίζουν όλα εγγενή δομημένη έξοδο. Το οικοσύστημα έχει συγκλίνει.
Συμπέρασμα: Αν αναλύετε απαντήσεις LLM με regex ή JSON.parse σε παραγωγή, το κάνετε με τον δύσκολο τρόπο. Η εγγενής δομημένη έξοδος εξαλείφει ολόκληρο αυτόν τον τρόπο αστοχίας.
JSON Mode vs Strict Mode: Τι Άλλαξε Πραγματικά;
Αυτή η διάκριση μπερδεύει πολλούς προγραμματιστές επειδή τα ονόματα ακούγονται παρόμοια. Δεν είναι.
| Χαρακτηριστικό | JSON Mode | Strict Mode (Δομημένες Έξοδοι) |
|---|---|---|
| Παράμετρος API | type: "json_object" | type: "json_schema" με strict: true |
| Εγγυάται έγκυρο JSON | Ναι | Ναι |
| Εγγυάται συμμόρφωση σχήματος | Όχι | Ναι |
| Μηχανισμός | Post-hoc token bias | Περιορισμένη αποκωδικοποίηση (FSM) |
| Μπορεί να επιστρέψει απροσδόκητα πεδία | Ναι | Όχι |
| Μπορεί να παραλείψει απαιτούμενα πεδία | Ναι | Όχι |
| Επιβολή τύπου | Καμία | Πλήρης (string, number, array, κ.λπ.) |
| Πότε να χρησιμοποιηθεί | Δεν έχετε σχήμα εκ των προτέρων | Τα πάντα σε παραγωγή |
Το χρονοδιάγραμμα: Η OpenAI εισήγαγε το JSON Mode στα τέλη του 2023. Ήταν ένα βήμα προς τα εμπρός, αλλά οι προγραμματιστές σύντομα συνειδητοποίησαν ότι το «έγκυρο JSON» δεν ήταν αρκετό, χρειάζονταν JSON σύμφωνο με το σχήμα. Τον Αύγουστο του 2024, η OpenAI ξεκίνησε τις Δομημένες Έξοδες με Strict Mode, το οποίο χρησιμοποιεί περιορισμένη αποκωδικοποίηση για να εγγυηθεί τη συμμόρφωση με το σχήμα. Μέχρι το 2025-2026, κάθε μεγάλος πάροχος είχε υιοθετήσει την ίδια προσέγγιση.
Το JSON Mode έχει ακόμα μια στενή περίπτωση χρήσης: όταν πραγματικά δεν γνωρίζετε τη μορφή της απάντησης εκ των προτέρων και θέλετε απλώς κάποιο έγκυρο JSON για ανεξερεύνητη εξερεύνηση. Αλλά αυτό είναι σπάνιο σε παραγωγή.
Συμπέρασμα: Χρησιμοποιήστε το Strict Mode για τα πάντα σε παραγωγή. Το JSON Mode είναι ουσιαστικά deprecated για περιπτώσεις χρήσης δεσμευμένες από σχήμα. Αν έχετε ένα σχήμα (και θα πρέπει), χρησιμοποιήστε type: "json_schema" με strict: true.
Πώς Λειτουργεί Πραγματικά η Περιορισμένη Αποκωδικοποίηση;
Ακολουθεί ο μηχανισμός που καθιστά δυνατή τη συμμόρφωση με το σχήμα 100%, όχι 99,9%, αλλά κυριολεκτικά 100%.
Όταν στέλνετε ένα JSON Schema σε έναν πάροχο με ενεργοποιημένο το Strict Mode, το σχήμα μεταγλωττίζεται σε μια πεπερασμένη μηχανή καταστάσεων (FSM). Αυτή η FSM αντιπροσωπεύει κάθε έγκυρη διαδρομή μέσω του σχήματός σας. Σε κάθε βήμα παραγωγής token, ο κινητήρας συμπερασμάτων ελέγχει ποια tokens θα κρατούσαν την έξοδο σε έγκυρη διαδρομή και ποια όχι. Τα άκυρα tokens έχουν τους logits τους ρυθμισμένους σε αρνητικό άπειρο πριν τη δειγματοληψία, πράγμα που σημαίνει ότι έχουν μηδενική πιθανότητα να επιλεγούν.
<!-- IMAGE: constrained-decoding diagram showing FSM token masking during structured output generation -->Σκεφτείτε το σαν autocomplete με στεροειδή. Αν το μοντέλο έχει μόλις εξάγει {"rating": και το σχήμα σας λέει ότι το rating είναι integer, τα μόνα tokens που επιτρέπονται στη συνέχεια είναι ψηφία. Τα εισαγωγικά, τα γράμματα, οι αγκύλες, όλα mascherati. Το μοντέλο δεν μπορεί να εξάγει "five" ακόμη και αν «θέλει».
Αυτός είναι ο ίδιος βασικός μηχανισμός που χρησιμοποιείται από το XGrammar (τον κινητήρα πίσω από το vLLM, SGLang και τους περισσότερους τοπικούς servers συμπερασμάτων) και το Outlines (την open-source βιβλιοθήκη Python για περιορισμένη παραγωγή). Οι πάροχοι API το έχουν απλώς ενσωματώσει στις υποδομές συμπερασμάτων τους.
Υπάρχει μια αντάλλαξη που πρέπει να γνωρίζετε: το πρώτο αίτημα με ένα νέο σχήμα υφίσταται καθυστέρηση συμβολοποίησης (τυπικά 50-200ms) ενώ χτίζεται η FSM. Τα επόμενα αιτήματα με το ίδιο σχήμα χρησιμοποιούν μια cached FSM και προσθέτουν σχεδόν μηδενική επιβάρυνση. Υπάρχει επίσης μια λεπτή consideration ποιότητας, ο περιορισμός του λεξιλογίου tokens μπορεί περιστασιακά να μειώσει την ποιότητα εξόδου για δημιουργικά ή free-form πεδία, οπότε κρατήστε τα σχήματά σας εστιασμένα σε πραγματικά δομημένα δεδομένα.
Συμπέρασμα: Η περιορισμένη αποκωδικοποίηση είναι αυτό που χωρίζει το «συνήθως λειτουργεί» από το «πάντα λειτουργεί». Είναι η μηχανική που καθιστά τη δομημένη έξοδο έτοιμη για παραγωγή.
Υλοποίηση Πολλαπλών Παρόχων: OpenAI, Anthropic και Gemini
Εδώ είναι κάτι που κανένας άλλος οδηγός δεν σας δείχνει: η ίδια εργασία εξαγωγής υλοποιημένη και στους τρεις μεγάλους παρόχους. Θα εξάγουμε μια δομημένη κριτική προϊόντος από μη δομημένο κείμενο.
Το σχήμα Pydantic (κοινό για όλους τους παρόχους):
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
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 model directly
)
review = response.choices[0].message.parsed # Typed ProductReview objectΗ υλοποίηση της OpenAI είναι η πιο ώριμη. Η μέθοδος parse() δέχεται ένα μοντέλο Pydantic απευθείας και επιστρέφει ένα typed object. Ένας περιορισμός: το Strict Mode της OpenAI υποστηρίζει ένα υποσύνολο του JSON Schema, χωρίς $ref, περιορισμένο anyOf, και όλα τα πεδία πρέπει να είναι required με additionalProperties: false.
Υλοποίηση Anthropic
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)Η εγγενής δομημένη έξοδος της Anthropic χρησιμοποιεί το output_config.format με ένα JSON Schema. Έφτασε σε GA στις αρχές του 2026. Η Anthropic υποστηρίζει επίσης το older pattern του ορισμού ενός «fake» tool και εξαγωγής μέσω tool_use, αυτό ακόμα λειτουργεί αλλά η εγγενής δομημένη έξοδος είναι cleaner για pure extraction.
Υλοποίηση Gemini
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 model directly
}
)
import json
review = ProductReview(**json.loads(response.text))Το Gemini υποστηρίζει μοντέλα Pydantic απευθείας στο Python SDK μέσω του response_schema. Ένα unique feature: Το Gemini respects το propertyOrdering στο σχήμα, ώστε να μπορείτε να ελέγξετε τη σειρά εξόδου πεδίων (χρήσιμο για το pattern reasoning-first).
Σύγκριση Παρόχων
| Χαρακτηριστικό | OpenAI | Anthropic | Gemini |
|---|---|---|---|
| Παράμετρος API | response_format | output_config.format | response_schema |
| Είσοδος σχήματος | Pydantic ή JSON Schema | JSON Schema | Pydantic ή JSON Schema |
| Strict mode | strict: true | Implicit with json_schema | Implicit |
| Streaming | Ναι (partial JSON) | Ναι | Ναι |
| Διαχείριση άρνησης | Πεδίο message.refusal | Απόκριση σφάλματος | Απόκριση σφάλματος |
| Εναλλακτική tool-use | Ναι | Ναι (original method) | Ναι |
| Cache συμβολοποίησης σχήματος | Ναι (server-side) | Ναι | Ναι |
| Διάταξη ιδιοτήτων | Όχι εγγενής υποστήριξη | Όχι | Ναι (propertyOrdering) |
Συμπέρασμα: Η OpenAI έχει το πιο polished DX με τη μέθοδο parse(). Η Anthropic προσφέρει τα πιο capable underlying models. Η διάταξη ιδιοτήτων του Gemini είναι uniquely useful. Και οι τρεις κάνουν τη δουλειά, επιλέξτε βάσει της υπάρχουσας σχέσης σας με τον πάροχο.
Μοτίβα Pydantic για Προγραμματιστές Python
Το Pydantic είναι το de facto standard για τον ορισμό σχημάτων δομημένης εξόδου στην 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")Αυτά τα strings description δεν είναι απλώς για τεκμηρίωση, γίνονται μέρος του JSON Schema που στέλνεται στο μοντέλο και επηρεάζουν άμεσα τι παράγει το μοντέλο. Σκεφτείτε τα ως prompt engineering within το σχήμα.
Nested Models
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 # Nested model
key_products: list[str] = Field(description="Top 3 products or services")Κρατήστε το nesting σε max 2-3 levels. Τα deeply nested schemas αυξάνουν τα error rates και επιβραδύνουν τη συμβολοποίηση του σχήματος.
Το Pattern Reasoning-First
Αυτό είναι το single most impactful schema design pattern. Τοποθετήστε ένα πεδίο reasoning πριν από τα πεδία απάντησής σας:
# Reliable JSON from Any LLM: Pydantic + Zod Patterns for 2026
class ClassificationBad(BaseModel):
category: Literal["spam", "ham"]
confidence: float
# Good -- model reasons through the problem first
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)Τα LLMs παράγουν tokens από αριστερά προς τα δεξιά. Αν το category έρχεται πρώτο, το μοντέλο επιλέγει μια κατηγορία και μετά την rationalizes. Αν το reasoning έρχεται πρώτο, το μοντέλο work through the problem και then commits σε μια κατηγορία. Είναι chain-of-thought baked into the schema.
Εξαγωγή JSON Schema
# Generate the JSON Schema for any Pydantic model
schema = ProductReview.model_json_schema()
# Pass this to any provider that accepts raw JSON SchemaΣυμπέρασμα: Pydantic + descriptive fields + ordering reasoning-first είναι η Python structured output trifecta. Master these three patterns and you'll handle 90% of use cases.
Μοτίβα Zod για Προγραμματιστές TypeScript
Το Zod είναι το TypeScript equivalent του Pydantic, και είναι equally central στις workflows δομημένης εξόδου.
Βασικό Σχήμα με Περιγραφές
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"),
});
// Infer the TypeScript type automatically
type ProductReview = z.infer<typeof ProductReview>;Όπως το Field(description=...) του Pydantic, το .describe() του Zod γίνεται μέρος του JSON Schema και guides the model's output.
Ενσωμάτωση με 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; // Typed!Ενσωμάτωση με 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 is fully typed as ProductReviewΤο Vercel AI SDK χρησιμοποιεί εγγενώς το Zod με το generateObject(), καθιστώντας το την cleanest TypeScript integration. Λειτουργεί με OpenAI, Anthropic, Gemini και άλλους παρόχους μέσω ενός unified API.
Μετατροπή JSON Schema
import { zodToJsonSchema } from "zod-to-json-schema";
const jsonSchema = zodToJsonSchema(ProductReview);
// Use with any provider that accepts raw JSON SchemaΣυμπέρασμα: Zod + .describe() + το Vercel AI SDK είναι το TypeScript structured output stack. Αν είστε στο ecosystem Node/Next.js, αυτός είναι ο path of least resistance.
Δομημένη Έξοδος vs Function Calling: Πότε Χρησιμοποιείτε το Κάθε Ένα;
Αυτή είναι μία από τις πιο common sources of confusion. Και τα δύο involve schemas, και τα δύο επιστρέφουν δομημένα δεδομένα, αλλά λύνουν διαφορετικά προβλήματα.
Η δομημένη έξοδος λέει: «Δώσε μου δεδομένα σε αυτό το exact shape.» Είναι για extraction, classification και formatting. Extracting structured information out of unstructured text.
Το function calling (tool use) λέει: «Εδώ είναι actions που μπορείτε να αναλάβετε, decide which one to run and provide the arguments.» Είναι για agent workflows όπου το μοντέλο picks from multiple tools και triggers actions.
Η σύγχυση makes sense historically. Η original «δομημένη έξοδος» της Anthropic was literally function calling, would define a fake tool called extract_review and grab the arguments. That still works, but native structured output is simpler for pure extraction.
| Σενάριο | Καλύτερη Προσέγγιση | Γιατί |
|---|---|---|
| Εξαγωγή δεδομένων από κείμενο | Δομημένη έξοδος | Direct, lower latency, single schema |
| Ταξινόμηση σε κατηγορίες | Δομημένη έξοδος | One response, one schema |
| Agent deciding which tool to call | Function calling | Model chooses from multiple tools |
| Multi-step orchestration | Function calling | Sequential tool invocations |
| Εξαγωγή δεδομένων ΚΑΙ απόφαση next action | Και τα δύο | Δομημένη έξοδος για εξαγωγή, function calling για orchestration |
Η δομημένη έξοδος powers the tool-calling pipelines in AI agent systems. See our guide to AI agents for business for how these fit into production workflows.
Συμπέρασμα: Χρησιμοποιήστε δομημένη έξοδο όταν ξέρετε ποιο shape πρέπει να έχουν τα δεδομένα. Χρησιμοποιήστε function calling όταν το μοντέλο χρειάζεται να choose an action. Στην πράξη, most applications use both, structured output for data extraction and function calling for agent orchestration.
Production Patterns: Σφάλματα, Επαναλήψεις και Streaming
Το να κάνετε τη δομημένη έξοδο να λειτουργεί σε ένα demo είναι easy. Keeping it reliable in production requires handling three things: refusals, validation failures, and streaming.
Διαχείριση Άρνησης (Refusal Handling)
Sometimes a model refuses to generate your requested output, typically because safety filters flagged the input. When this happens, structured output APIs don't return your schema. They return a refusal.
response = client.beta.chat.completions.parse(
model="gpt-4o-2024-08-06",
messages=messages,
response_format=ProductReview,
)
# ALWAYS check for refusal before accessing parsed content
if response.choices[0].message.refusal:
print(f"Model refused: {response.choices[0].message.refusal}")
else:
review = response.choices[0].message.parsedIf you skip the refusal check and try to access .parsed on a refusal, you'll get None and a confusing downstream error. Check first, always.
Μοτίβα Επανάληψης με Validation Feedback
Η συμμόρφωση με το σχήμα είναι guaranteed by constrained decoding, but semantic correctness isn't. The model might return {"rating": 1, "sentiment": "positive"}, valid schema, contradictory content. That's where validation + retries come in.
import instructor
client = instructor.from_openai(OpenAI())
# Instructor handles retries automatically
review = client.chat.completions.create(
model="gpt-4o",
response_model=ProductReview,
max_retries=3, # Retries with validation error feedback
messages=[
{"role": "user", "content": review_text}
],
)Το Instructor feeds the validation error back to the model on retry, so it can self-correct. For manual retry patterns without 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
# Run additional semantic validation here
break
except ValidationError as e:
messages.append({"role": "assistant", "content": str(response)})
messages.append({"role": "user", "content": f"Validation error: {e}. Fix it."})Streaming Δομημένης Εξόδου
For large structured responses, long arrays, many fields, complex nested objects, streaming lets you render partial results progressively.
import instructor
client = instructor.from_openai(OpenAI())
# Stream partial results as fields populate
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:
# Fields populate one by one as tokens stream in
if partial_review.summary:
print(f"Summary so far: {partial_review.summary}")One gotcha: individual streaming chunks aren't schema-valid on their own. The reasoning field might be populated while rating is still None. Plan your UI accordingly, show a loading state for unpopulated fields.
Συμπέρασμα: Οι έλεγχοι άρνησης είναι non-negotiable. Οι επαναλήψεις με validation feedback catch semantic errors. Το streaming αξίζει για any response that takes more than a couple seconds.
Σύγκριση Βιβλιοθηκών Δομημένης Εξόδου
Μπορείτε να χρησιμοποιήσετε δομημένη έξοδο μέσω native APIs, but libraries add validation, retries, streaming, and multi-provider support. Here's the landscape.
Instructor is the most popular option at 11K+ GitHub stars and 3M+ monthly downloads. It wraps OpenAI, Anthropic, Gemini, Cohere, Ollama, and more with a unified Pydantic-based interface. Key features: automatic retries with validation feedback, streaming via create_partial(), and dead-simple setup (instructor.from_openai(client)). If you're a Python team, start here.
BAML takes a different approach: schema-first via a custom DSL. You define schemas in .baml files and auto-generate clients for Python, TypeScript, Ruby, and more. Its SAP (schema-aligned parsing) algorithm handles messy model outputs gracefully. Best for cross-language teams or when you want contracts between your LLM layer and application layer. Trade-off: extra build step and a new syntax to learn.
LangChain offers .with_structured_output(schema) for provider-agnostic structured output. Convenient if you're already in the LangChain ecosystem. Trade-off: it's a heavy dependency, and the abstraction can hide provider-specific features you might need.
Native APIs, direct calls with response_format / output_config, require zero dependencies beyond the provider SDK. You get full control and full visibility. Best for simple use cases or teams that prefer minimal abstraction.
| Βιβλιοθήκη | Γλώσσες | Πάροχοι | Auto Retries | Streaming | GitHub Stars | Learning Curve |
|---|---|---|---|---|---|---|
| Instructor | Python, TS | 15+ | Ναι | Ναι | 11K+ | Χαμηλή |
| BAML | Python, TS, Ruby, Go | All (DSL-agnostic) | Ναι | Ναι | 7K+ | Μέτρια |
| LangChain | Python, TS | 20+ | Partial | Ναι | 100K+ | Μέτρια-Υψηλή |
| Native APIs | Any | 1 per SDK | Όχι | Ναι | N/A | Χαμηλή |
Choosing the right structured output library is part of a broader AI stack decision. We break down the full stack in our Best AI Stack for SaaS guide.
See our Best Libraries for LLM Structured Outputs [coming soon] for an in-depth comparison of Instructor, BAML, Mirascope, and more.
Συμπέρασμα: Start with Instructor for Python, native APIs for TypeScript. Move to BAML if you need cross-language schema contracts. Avoid LangChain just for structured output, it's overkill.
Best Practices Σχεδιασμού Σχήματος (και Common Mistakes)
Your schema design directly impacts output quality. Here are the patterns that matter and the mistakes that cost you accuracy.
Put Reasoning Before Answers
We covered this in the Pydantic section, but it bears repeating because it's the highest-impact design decision:
# Before: model guesses the answer, then rationalizes
class Bad(BaseModel):
answer: str
reasoning: str
# After: model thinks first, then commits
class Good(BaseModel):
reasoning: str = Field(description="Think step by step")
answer: strLLMs generate left-to-right. Field order is prompt order. Reasoning first means the model has to work through the problem before committing to an answer.
Ο Πίνακας Anti-Pattern
| Λάθος | Πρόβλημα | Λύση |
|---|---|---|
| Πεδίο συλλογισμού μετά την απάντηση | Το μοντέλο αποφασίζει πριν σκεφτεί | Μετακινήστε το reasoning πριν την απάντηση |
| Deeply nested (4+ levels) | Higher error rate, slower compilation | Flatten to 2-3 levels |
| Χωρίς περιγραφές πεδίων | Το μοντέλο guesses what you want | Προσθέστε .describe() / Field(description=...) |
| Missing null handling | Το μοντέλο hallucinates a value to fill the field | Χρησιμοποιήστε Optional / .nullable() |
| Overly large schemas (50+ fields) | Compilation timeout, quality degradation | Split into multiple calls |
| Vague enum options | Το μοντέλο picks the wrong category | Use specific, non-overlapping options |
Handle Nulls Explicitly
If a field might not have data in the source text, make it optional. Forcing a required field when data doesn't exist leads to hallucination:
class PersonInfo(BaseModel):
name: str # Always present
email: Optional[str] = Field(None, description="Email if mentioned, null otherwise")
phone: Optional[str] = Field(None, description="Phone if mentioned, null otherwise")Keep Schemas Focused
One schema per task. Don't try to extract everything in a single massive schema. If you need 50+ fields, split into multiple extraction calls. OpenAI's Strict Mode has practical limits on schema complexity, and even when it works, very large schemas degrade output quality.
Συμπέρασμα: Reasoning-first, descriptive fields, explicit nulls, and focused schemas. Get these four right and your structured output accuracy jumps measurably.
Δομημένη Έξοδος με Local LLMs
You don't need an API provider for structured output. Local inference engines support it through grammar-based constrained decoding, the same fundamental mechanism, running on your own hardware.
Ollama
The easiest path for local structured output. Ollama accepts a JSON Schema via the format parameter:
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 uses XGrammar under the hood for constrained decoding. Same guarantee as the API providers: 100% schema compliance.
vLLM και SGLang
For production-grade local inference, vLLM and SGLang both support structured output through guided_json and guided_regex parameters. XGrammar is the default backend, delivering near-zero overhead on JSON generation, up to 3.5x faster than alternative grammar engines.
Outlines
Outlines is the open-source Python library that pioneered grammar-based constrained generation. It works with any Hugging Face model and supports JSON Schema, regex, and full context-free grammar (CFG/EBNF) constraints. It's also integrated into vLLM and SGLang as a grammar backend option.
The key difference from API providers: local structured output has no schema subset limitations. You control the grammar entirely. But model quality varies more, a 7B parameter local model won't match GPT-4o or Claude on complex extraction tasks. The schema will always be valid; the content quality depends on the model.
Συμπέρασμα: Ollama for development, vLLM/SGLang with XGrammar for production. Local structured output is mature enough for most use cases, with the caveat that smaller models produce lower-quality content within the schema.
FAQ
Τι είναι η δομημένη έξοδος στα LLMs;
Η δομημένη έξοδος είναι ένας μηχανισμός που εγγυάται ότι η απάντηση ενός LLM συμμορφώνεται με ένα προκαθορισμένο JSON Schema. Σε αντίθεση με το plain text ή even JSON Mode, η δομημένη έξοδος uses constrained decoding to ensure every field, type, and constraint in your schema is met -- 100% of the time, not «usually».
Ποια είναι η διαφορά μεταξύ JSON Mode και Δομημένων Εξόδων;
Το JSON Mode εγγυάται συντακτικά έγκυρο JSON αλλά δεν επιβάλλει το σχήμα σας, could get any valid JSON object. Οι Δομημένες Έξοδοι (Strict Mode) εγγυώνται πλήρη συμμόρφωση με το σχήμα μέσω περιορισμένης αποκωδικοποίησης. Χρησιμοποιήστε Strict Mode για παραγωγή· το JSON Mode είναι relevant only when you don't have a schema upfront.
Ποιοι πάροχοι LLM υποστηρίζουν εγγενώς δομημένη έξοδο;
OpenAI (since August 2024), Google Gemini (2024, expanded 2026), Anthropic (beta November 2025, GA early 2026), Cohere, and xAI (Grok) all support native structured output. On the local side, Ollama, vLLM, and SGLang support it through grammar-based constrained decoding.
Πώς η περιορισμένη αποκωδικοποίηση εγγυάται τη συμμόρφωση με το σχήμα;
Το JSON Schema μεταγλωττίζεται σε μια πεπερασμένη μηχανή καταστάσεων (FSM). At each token generation step, only tokens that keep the output on a valid path through the FSM are allowed, invalid tokens get their logits set to negative infinity. This means invalid tokens have zero probability of being generated, giving you a mathematical guarantee, not a statistical one.
Θα πρέπει να χρησιμοποιώ δομημένη έξοδο ή function calling;
Χρησιμοποιήστε δομημένη έξοδο για extraction και classification, when you want data in a specific shape. Χρησιμοποιήστε function calling για agent workflows, when the model needs to decide which action to take. Many production applications use both: structured output for data extraction and function calling for orchestration.
Μπορώ να κάνω streaming δομημένης εξόδου;
Ναι. Η OpenAI υποστηρίζει streaming με τη μέθοδο parse(), και το Instructor παρέχει create_partial() για streaming Pydantic models that populate field-by-field. Keep in mind that individual streaming chunks aren't individually schema-valid, fields populate incrementally.
Τι είναι η βιβλιοθήκη Instructor;
Το Instructor είναι η most popular structured output library (11K+ GitHub stars, 3M+ monthly downloads). It wraps provider SDKs with Pydantic-based validation, automatic retries with validation feedback, and streaming support. Works with OpenAI, Anthropic, Gemini, Cohere, Ollama, and 10+ other providers.
Λειτουργεί η δομημένη έξοδος με local LLMs;
Ναι. Το Ollama υποστηρίζει δομημένη έξοδο via the format parameter with JSON Schema. vLLM and SGLang support it through guided_json parameters. All three use XGrammar or Outlines for constrained decoding. The schema compliance guarantee is the same as API providers; content quality depends on the model.
Ποια είναι τα common mistakes στον σχεδιασμό σχήματος;
Τα top mistakes: putting the reasoning field after the answer field (model decides before thinking), deeply nested schemas (4+ levels increase errors), missing field descriptions (model guesses intent), no null handling for optional data (forces hallucination), and overly large schemas (50+ fields degrade quality).
Προσθέτει καθυστέρηση η δομημένη έξοδος;
Υπάρχει ένα overhead συμβολοποίησης σχήματος στο first request, typically 50-200ms while the FSM is built. Subsequent requests with the same schema use a cached FSM and add near-zero latency. For most applications, this is negligible compared to the overall model inference time.
Μπορώ να χρησιμοποιήσω δομημένη έξοδο με images ή multimodal inputs;
Ναι. Η δομημένη έξοδος applies to the response format, not the input. You can send an image to GPT-4o or Gemini with a structured output schema and get back a schema-compliant analysis of the image. This is powerful for visual extraction workflows, extracting structured data from receipts, forms, or product images.