LLM strukturierte Ausgabe: JSON-Schema-Erzwingung und zuverlässige Tool-Aufrufe
Im Produktionsbetrieb Alarm: Agent-Tool-Aufruf schlägt fehl, fünf Retries hintereinander – alles Parameterformatfehler. Im Log: Das Feld city sollte "北京" sein, das LLM liefert {"name": "北京", "id": null}. Parser bricht ab, die gesamte Datenpipeline steht still.
Das war ein großer Fehler, den wir letztes Jahr gemacht haben.
Seitdem habe ich mich systematisch mit strukturierter LLM-Ausgabe beschäftigt – von OpenAI Structured Outputs über Anthropic Tool Use bis Instructor Auto-Retry und Outlines constrained Decoding. Anfangs dachte ich, ein „besserer Prompt“ reiche – tatsächlich ist es eine Frage der Zuverlässigkeitsarchitektur, nicht des Promptings.
Dieser Artikel stellt die dreistufige Zuverlässigkeitsarchitektur vor: Parameter-Validierung, Fehler-Retry, constrained Decoding. Am Ende vergleichen wir OpenAI, Claude und Gemini und geben produktionsreife Code-Vorlagen mit.
1. Warum strukturierte Ausgabe das Fundament jedes Agents ist
Zuerst das Problem „Format Drift“ – kein Einzelfall, sondern der Albtraum jedes Agent-Entwicklers.
Drei Formen des Format Drift
Erstens: fehlende Felder. Sie erwarten ein Objekt mit name, age, email – das LLM liefert {"name": "张三"}. Die anderen Felder fehlen. Nicht immer, aber gelegentlich. In Produktion bedeutet „gelegentlich“ „unweigerlich“.
Zweitens: Typfehler. In der Doku steht klar: user_id ist Integer. Das LLM liefert "user_id": "12345" als String. Pydantic wirft einen Fehler, die gesamte Aufrufkette bricht ab.
Drittens: überflüssiger Inhalt. Am heimtückischsten. Sie wollen JSON – davor kommt „Here is the response:“, danach „I hope this helps!“. Der JSON-Parser scheitert.
OpenAIs offizielle Daten sprechen für sich: JSON Mode (nur gültiges JSON) scheitert in 5–10 % der Fälle, Structured Outputs (Schema-Erzwingung) unter 0,1 % – zwei Größenordnungen Unterschied.
Warum das so wichtig ist
„Parsing schlägt fehl – ein paar Retries mehr.“ Klingt einfach.
Retry ist aber nicht kostenlos.
API-Kosten. Ein GPT-4-Aufruf kostet schnell ein paar Cent, fünf Retries multiplizieren das. Bei 100.000 Anfragen pro Tag und durchschnittlich zwei Retries pro Request – rechnen Sie selbst.
Latenz. Ein Aufruf dauert zwei Sekunden, drei Retries: über sechs Sekunden Wartezeit. In Echtzeit-Dialogen inakzeptabel.
Nutzererlebnis. Wetteranfrage, Agent hängt zehn Sekunden, dann „Systemfehler“. Beim nächsten Mal kommt der Nutzer nicht wieder.
Strukturierte Ausgabe ist kein Nice-to-have, sondern das Fundament stabiler Agent-Systeme. Die Lösung liegt nicht in „besseren Prompts“, sondern in zuverlässiger Architektur.
2. Dreistufige Zuverlässigkeitsarchitektur
Diese Architektur habe ich nach vielen Fehlschlägen zusammengestellt. Kein Allheilmittel – aber sie senkt Formatfehler von 5–10 % auf nahezu null.
L1: Parameter-Validierung – erste Verteidigungslinie
Einfaches Prinzip: Pydantic definiert die erwartete Struktur, erzwingt Typkonvertierung, Whitelist-Filter.
from pydantic import BaseModel, Field, field_validator
from typing import Optional, List
from datetime import datetime
class ToolCallParams(BaseModel):
"""工具调用参数模型"""
city: str = Field(..., min_length=1, max_length=50, description="城市名称")
date: Optional[datetime] = Field(None, description="查询日期")
units: str = Field("metric", pattern="^(metric|imperial)$")
@field_validator("city")
@classmethod
def validate_city(cls, v: str) -> str:
# 白名单校验
allowed_cities = {"北京", "上海", "广州", "深圳", "杭州"}
if v not in allowed_cities:
raise ValueError(f"不支持的城市: {v},目前支持: {allowed_cities}")
return v
Pydantic übernimmt drei Dinge: Typkonvertierung (String "123" → Integer 123), Erkennung fehlender Felder, benutzerdefinierte Validierung. Die wichtigste und grundlegendste Schicht.
L2: Fehler-Retry – Selbstkorrektur mit Feedback
Schlägt die LLM-Antwort bei der Validierung fehl, wird nicht blind wiederholt – die Fehlermeldung geht zurück ans Modell zur Korrektur. Instructor kapselt diese Logik elegant.
import instructor
from openai import OpenAI
from pydantic import ValidationError
client = instructor.patch(OpenAI())
def get_weather_with_retry(user_query: str, max_retries: int = 3):
"""带错误反馈的重试机制"""
messages = [{"role": "user", "content": user_query}]
for attempt in range(max_retries):
try:
response = client.chat.completions.create(
model="gpt-4o",
response_model=ToolCallParams, # Pydantic 模型
messages=messages,
temperature=0.1 # 结构化输出用低温
)
return response # 自动校验通过
except ValidationError as e:
# 把错误喂给 LLM 让它修正
error_msg = f"参数校验失败: {str(e)}\n请修正后重新返回正确的 JSON 格式。"
messages.append({"role": "assistant", "content": "生成参数中..."})
messages.append({"role": "user", "content": error_msg})
if attempt == max_retries - 1:
raise Exception(f"重试 {max_retries} 次后仍然失败: {e}")
# 使用示例
result = get_weather_with_retry("帮我查一下北京明天的天气")
Kernidee: Das LLM rät nicht blind – es weiß, was falsch ist und warum. Mit Feedback korrigiert es. In Tests stieg die Retry-Erfolgsrate von 60 % auf über 95 %.
L3: Constrained Decoding – Fehler an der Quelle verhindern
L1 und L2 sind nachträgliche Korrektur, L3 ist Prävention.
Beim constrained Decoding wird bei jedem generierten Token per Finite-State-Machine (FSM) der Auswahlbereich eingeschränkt – nur Schema-konforme Token-Sequenzen sind möglich. Wie eine Bremse: ungültige Ausgabe ist technisch ausgeschlossen.
Zwei gängige Implementierungen:
Outlines (Open Source, für lokale Modelle):
from outlines import models, generate
import json
# 加载本地模型
model = models.transformers("Qwen/Qwen2.5-7B-Instruct")
# 定义 Schema
schema = {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"}
},
"required": ["name", "age"]
}
# 创建受约束生成器
generator = generate.json(model, schema)
result = generator("提取用户信息: 张三今年28岁")
# 100% 符合 Schema,不需要任何重试
vLLM guided_json (für große deployte Modelle):
from vllm import LLM, SamplingParams
llm = LLM(model="Qwen/Qwen2.5-72B-Instruct")
sampling_params = SamplingParams(
temperature=0.0,
guided_decoding_backend="outlines",
guided_json={ # 直接传 JSON Schema
"type": "object",
"properties": {
"tool_name": {"type": "string"},
"arguments": {"type": "object"}
}
}
)
L3 kostet Kompilierungs-Overhead – die FSM muss pro Schema vorab aufgebaut werden. Bei häufig wechselnden Schemas entsteht Verzögerung. Für die meisten Agent-Anwendungen sind Schemas stabil – der Overhead ist akzeptabel.
Welche Schichten wann?
| Szenario | Empfehlung |
|---|---|
| OpenAI API | L1 + L2 (Pydantic + Instructor) |
| Claude API | L1 + L2 (Claude ohne Strict Mode) |
| Lokales Modell | L1 + L3 (Outlines/vLLM guided_json) |
| Höchste Zuverlässigkeit | L1 + L2 + L3 kombiniert |
3. Anbietervergleich: OpenAI, Claude, Gemini
Die Unterschiede zwischen Anbietern sind groß – ohne Vergleich landen Sie schnell in Fallstricken.
OpenAI: Strict Mode, erzwungene Konformität
Im August 2024 führte OpenAI Structured Outputs ein – derzeit die zuverlässigste kommerzielle API-Lösung.
Kernmechanismus: Parameter strict: true. Die Ausgabe wird auf das definierte JSON Schema gezwungen – 100 % Konformität. Unter der Haube: Grammar-based Constrained Decoding, ähnlich wie Outlines.
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "提取用户信息"}],
response_format={
"type": "json_schema",
"json_schema": {
"name": "user_info",
"strict": True, # 关键参数
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"}
},
"required": ["name", "age"]
}
}
}
)
# 输出 100% 符合 Schema
OpenAI-Angabe: Strict Mode unter 0,1 % Fehlerrate. In der Praxis keine Formatfehler – mit Einschränkung: rekursive Schemas nicht unterstützt, komplexe Verschachtelung erfordert Workarounds.
Anthropic Claude: Tool Use ohne Garantie
Claude nutzt Tool Use für strukturierte Ausgabe: Tool definieren, Claude ruft es mit Parametern auf. Aber: Der strict-Parameter kann gesetzt werden – wird laut offizieller Doku ignoriert. Keine Schema-Garantie.
Original aus der Anthropic-Dokumentation (Stand April 2026):
“The
strictparameter is currently ignored for tool definitions. Claude will make a best effort to provide valid arguments, but does not guarantee schema compliance.”
Es wird sein Bestes geben – ohne Garantie. Bei Claude-Tool-Aufrufen unbedingt L1 (Parameter-Validierung) und L2 (Fehler-Retry) einplanen.
import anthropic
client = anthropic.Anthropic()
# Claude 的工具定义
tools = [{
"name": "get_weather",
"input_schema": {
"type": "object",
"properties": {
"city": {"type": "string"}
},
"required": ["city"]
}
}]
response = client.messages.create(
model="claude-3.5-sonnet",
max_tokens=1024,
tools=tools,
messages=[{"role": "user", "content": "北京天气"}]
)
# 重要:必须手动校验 tool_use 的参数
for block in response.content:
if block.type == "tool_use":
# 这里要做 Pydantic 校验
validated_params = ToolCallParams.model_validate(block.input)
Google Gemini: Controlled Generation
Gemini nutzt Controlled Generation über response_schema.
import google.generativeai as genai
model = genai.GenerativeModel('gemini-1.5-pro')
response = model.generate_content(
"提取用户信息",
generation_config={
"response_mime_type": "application/json",
"response_schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"}
},
"required": ["name", "age"]
}
}
)
Gemini liegt zwischen OpenAI und Claude – Constraint vorhanden, aber ohne OpenAIs harte Erzwingung. In Tests etwa 1–2 % Fehlerrate: besser als JSON Mode, schwächer als Strict Mode.
Open-Source-Modelle: Outlines/vLLM
Qwen, Llama, Mistral etc. haben keine native strukturierte Ausgabe – externe Tools nötig: Outlines und vLLM guided_json.
Interessant: Open-Source plus Outlines kann zuverlässiger sein als manche kommerzielle APIs – die FSM ist harte Constraint, kein „best effort“.
Entscheidungshilfe
| Anforderung | Empfehlung | Grund |
|---|---|---|
| Reine API, maximale Stabilität | OpenAI Structured Outputs | <0,1 % Fehlerrate |
| Komplexes Reasoning + Tools | Claude + L1/L2 | Starke Reasoning-Fähigkeit, eigene Validierung |
| Private Modell-Deployment | Qwen/Llama + Outlines | Kostenkontrolle, hohe Zuverlässigkeit |
| Höchste Format-Anforderungen (Finanz, Medizin) | OpenAI Strict oder Outlines | Nahezu null Fehler |
| Schneller Prototyp | Instructor + beliebige API | Gekapselt, Auto-Retry |
4. Produktionsreife Code-Vorlagen
Vier Vorlagen, die ich in Produktion validiert habe – direkt anpassbar.
Vorlage 1: OpenAI Structured Outputs – vollständiges Beispiel
"""
OpenAI Structured Outputs 完整示例
适用于:工具调用、数据提取、报表生成等场景
"""
from openai import OpenAI
from pydantic import BaseModel, Field
from typing import List, Optional
import json
# 1. 定义 Pydantic 模型
class SearchQuery(BaseModel):
"""搜索查询参数"""
keywords: List[str] = Field(
...,
min_length=1,
max_length=5,
description="搜索关键词列表"
)
filters: Optional[dict] = Field(
default=None,
description="可选的过滤条件"
)
limit: int = Field(
default=10,
ge=1,
le=100,
description="返回结果数量"
)
# 2. Pydantic 模型转 JSON Schema
def model_to_schema(model: type[BaseModel]) -> dict:
"""将 Pydantic 模型转换为 JSON Schema"""
schema = model.model_json_schema()
# 清理 Pydantic 添加的元数据
schema.pop("title", None)
for prop in schema.get("properties", {}).values():
prop.pop("title", None)
return schema
# 3. 结构化输出调用
client = OpenAI()
def extract_search_params(user_input: str) -> SearchQuery:
"""从用户输入提取搜索参数"""
schema = model_to_schema(SearchQuery)
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "system",
"content": "你是一个搜索助手,帮助用户提取搜索参数。"
},
{"role": "user", "content": user_input}
],
response_format={
"type": "json_schema",
"json_schema": {
"name": "search_query",
"strict": True,
"schema": schema
}
},
temperature=0.1 # 结构化输出用低温
)
# 4. 解析并二次校验
raw_content = response.choices[0].message.content
data = json.loads(raw_content)
return SearchQuery.model_validate(data)
# 使用示例
if __name__ == "__main__":
query = extract_search_params(
"我想找一些关于 Python 异步编程的文章,只要最近一个月的,最多 20 条"
)
print(query)
# SearchQuery(keywords=['Python', '异步编程'], filters={'date_range': 'last_month'}, limit=20)
Vorlage 2: Instructor Auto-Retry
"""
Instructor 自动重试示例
适用于:Claude API、OpenAI JSON Mode(非 Strict)、需要容错的场景
"""
import instructor
from openai import OpenAI
from pydantic import BaseModel, Field, ValidationError
class AgentAction(BaseModel):
"""Agent 行动决策"""
action_type: str = Field(
...,
pattern="^(search|execute|respond|clarify)$"
)
parameters: dict = Field(default_factory=dict)
reasoning: str = Field(..., min_length=10)
# patch OpenAI client
client = instructor.patch(OpenAI())
def get_agent_decision(
context: str,
user_request: str,
max_retries: int = 3
) -> AgentAction:
"""
获取 Agent 的行动决策,带自动重试
Args:
context: 当前对话上下文
user_request: 用户请求
max_retries: 最大重试次数
Returns:
AgentAction: 校验后的行动决策
"""
messages = [
{"role": "system", "content": "你是一个智能助手,分析用户需求并决定下一步行动。"},
{"role": "user", "content": f"上下文: {context}\n\n用户请求: {user_request}"}
]
try:
response = client.chat.completions.create(
model="gpt-4o",
response_model=AgentAction, # Instructor 自动校验
messages=messages,
max_retries=max_retries, # 内置重试
temperature=0.1
)
return response
except ValidationError as e:
# Instructor 已经重试了 max_retries 次
raise Exception(f"格式错误无法修复,请检查模型定义: {e}")
# 使用示例
decision = get_agent_decision(
context="用户正在查询天气信息",
user_request="帮我查北京明天的天气,要是晴天就推荐户外活动"
)
print(f"行动类型: {decision.action_type}")
print(f"参数: {decision.parameters}")
print(f"推理过程: {decision.reasoning}")
Vorlage 3: Outlines – lokales Modell
"""
Outlines 本地模型结构化输出示例
适用于:私有部署、成本敏感、隐私要求高的场景
"""
from outlines import models, generate
from pydantic import BaseModel
from typing import List
import json
# 定义数据结构
class ProductInfo(BaseModel):
"""商品信息"""
name: str
price: float
category: str
tags: List[str]
# 加载模型(第一次加载会有几秒延迟)
model = models.transformers("Qwen/Qwen2.5-7B-Instruct")
# 创建结构化生成器
# 注意:schema 会在首次调用时编译为 FSM,有约 1-2 秒开销
schema_str = json.dumps(ProductInfo.model_json_schema())
generator = generate.json(model, schema_str)
def extract_product_info(description: str) -> ProductInfo:
"""
从商品描述提取结构化信息
Args:
description: 商品描述文本
Returns:
ProductInfo: 结构化的商品信息
"""
prompt = f"从以下商品描述中提取关键信息,以 JSON 格式返回:\n{description}"
# 生成结果 100% 符合 Schema
result = generator(prompt)
# 转换为 Pydantic 模型(二次校验,确保万无一失)
return ProductInfo.model_validate(result)
# 使用示例
description = """
这款蓝牙耳机采用最新的降噪技术,价格 299 元,
属于数码配件类,适合运动、通勤等场景使用。
"""
product = extract_product_info(description)
print(product)
# ProductInfo(name='蓝牙耳机', price=299.0, category='数码配件', tags=['运动', '通勤'])
Vorlage 4: Vollständiger Tool-Aufruf-Ablauf
"""
完整的工具调用参数验证流程
包含:Schema 定义 → LLM 调用 → 参数校验 → 失败重试 → 工具执行
"""
from openai import OpenAI
from pydantic import BaseModel, Field, field_validator, ValidationError
from typing import Callable, Dict, Any
import json
# 1. 定义工具参数模型
class WeatherQueryParams(BaseModel):
"""天气查询工具参数"""
city: str = Field(..., min_length=1, max_length=50)
date_offset: int = Field(default=0, ge=-7, le=7, description="日期偏移,0表示今天")
@field_validator("city")
@classmethod
def validate_city(cls, v: str) -> str:
allowed = {"北京", "上海", "广州", "深圳", "杭州", "成都", "武汉"}
if v not in allowed:
raise ValueError(f"不支持的城市,可选: {allowed}")
return v
# 2. 工具调用管理器
class ToolCallManager:
"""管理工具调用的完整流程"""
def __init__(self):
self.client = OpenAI()
self.tools: Dict[str, Callable] = {}
def register_tool(self, name: str, func: Callable, param_model: type[BaseModel]):
"""注册工具"""
self.tools[name] = {
"function": func,
"param_model": param_model
}
def execute_with_retry(
self,
tool_name: str,
user_request: str,
max_retries: int = 3
) -> Any:
"""执行工具调用,带重试"""
tool_config = self.tools[tool_name]
param_model = tool_config["param_model"]
schema = param_model.model_json_schema()
messages = [
{"role": "system", "content": f"提取工具 '{tool_name}' 的调用参数"},
{"role": "user", "content": user_request}
]
for attempt in range(max_retries):
try:
# 调用 LLM 获取参数
response = self.client.chat.completions.create(
model="gpt-4o",
messages=messages,
response_format={
"type": "json_schema",
"json_schema": {
"name": tool_name,
"strict": True,
"schema": schema
}
},
temperature=0.1
)
# 校验参数
params = param_model.model_validate_json(
response.choices[0].message.content
)
# 执行工具
return tool_config["function"](params)
except ValidationError as e:
# 反馈错误,让 LLM 修正
messages.append({
"role": "user",
"content": f"参数校验失败: {e}\n请修正参数格式。"
})
continue
raise Exception(f"工具调用失败,重试 {max_retries} 次后仍无法通过校验")
# 3. 使用示例
def get_weather(params: WeatherQueryParams) -> str:
"""模拟天气查询"""
# 这里是实际的 API 调用逻辑
return f"{params.city} 未来 {params.date_offset} 天天气晴朗"
manager = ToolCallManager()
manager.register_tool("get_weather", get_weather, WeatherQueryParams)
result = manager.execute_with_retry(
"get_weather",
"帮我查一下北京明天的天气"
)
print(result) # 北京未来 1 天天气晴朗
Diese Vorlagen decken die häufigsten Szenarien ab – nach Bedarf kombinieren und anpassen.
5. Best Practices für Produktion
Code allein reicht nicht – in Produktion zählen Details.
Temperature: nicht zu hoch
Für strukturierte Ausgabe: 0,0–0,2. OpenAI empfiehlt diesen Bereich, in der Praxis am stabilsten.
Hohe Temperature macht Ausgaben „kreativer“ und zufälliger. Zufälligkeit ist der Feind strukturierter Ausgabe – Sie brauchen Determinismus. Bei Temperature 0,7 lag die Fehlerrate bei 15 %, bei 0,1 praktisch keine Formatprobleme mehr.
Retry-Strategie: nicht jeden Fehler retryen
Vor dem Retry den Fehlertyp prüfen:
| Fehlertyp | Retry? | Grund |
|---|---|---|
| Parameterformat (fehlende Felder, falscher Typ) | Ja + Fehlerfeedback | LLM kann korrigieren |
| API-Fehler (429, 500) | Ja + Backoff | Temporäres Serverproblem |
| Business-Validierung (Stadt nicht in Whitelist) | Nein, Fehler zurückgeben | Nutzerbestätigung nötig |
| Tool-Ausführung fehlgeschlagen (leeres Ergebnis) | Nein, Fallback | Tool-Problem, kein LLM-Problem |
Unbegrenztes Retry bei Whitelist-Verletzung: LLM rät zehnmal falsch, dann Timeout. Fehlertypen trennen.
Performance-Overhead im Vergleich
| Ansatz | Latenz | Kosten | Zuverlässigkeit |
|---|---|---|---|
| Prompt-Constraint (ohne Spezialparameter) | +0 ms | +0 % | 5–10 % Fehler |
| JSON Mode (nur OpenAI) | +50 ms | +0 % | 2–5 % Fehler |
| Structured Outputs (Strict) | +100 ms | +0 % | <0,1 % Fehler |
| Instructor Retry | +200–500 ms/Retry | × Retry-Kosten | Nahe 0 % Fehler |
| Outlines FSM | +1–2 s (Erstkompilierung) | +0 % | 100 % Konformität |
Abwägung: maximale Stabilität → Structured Outputs oder Outlines; schneller Prototyp → Instructor; knappes Budget → JSON Mode plus manuelle Validierung.
Monitoring: drei Pflichtmetriken
Nach dem Go-Live unbedingt beobachten:
- Format-Fehlerrate: Anteil fehlgeschlagener Validierungen. Über 1 % → Ursache suchen.
- Durchschnittliche Retry-Anzahl: Normal 0,5–1,5. Über 2 → Modell oder Schema prüfen.
- Durchschnittliche Latenz: Strukturierte Ausgabe +50–200 ms gegenüber normaler Ausgabe – im Rahmen halten.
Mit Prometheus + Grafana wöchentlich auswerten. Einmal sprang die Retry-Anzahl von 0,8 auf 2,5 – Ursache: Schema geändert, Code nicht synchronisiert. Monitoring hat rechtzeitig gewarnt.
Fazit
Kernbotschaft: Strukturierte Ausgabe ist 2026 kein ungelöstes Problem – mit der richtigen Methode.
Die dreistufige Architektur (Parameter-Validierung + Fehler-Retry + constrained Decoding) deckt alles ab – vom „läuft irgendwie“ bis „läuft stabil“. Bei der Anbieterwahl: OpenAI Strict Mode am stabilsten, Claude erfordert eigene Validierung, Open-Source plus Outlines oft überraschend zuverlässig.
Code-Vorlagen stehen in Kapitel 4 – anpassen und einsetzen. Wer gerade mit Agent-Entwicklung startet: mit Instructor beginnen – gut gekapselt, Auto-Retry und Fehlerfeedback eingebaut. Später bei Bedarf Outlines für 100 % harte Konformität.
Bei Fragen gerne kommentieren oder direkt melden. Hoffentlich erspart Ihnen dieser Artikel ein paar Fehltritte.
OpenAI Structured Outputs – vollständiger Ablauf
Von der Pydantic-Modelldefinition bis zum strukturierten API-Aufruf
⏱️ Estimated time: 15 min
- 1
Step 1: Pydantic-Datenmodell definieren
Pydantic-Modellklasse mit Field-Constraints anlegen:
• `Field(..., min_length=1, max_length=50)` für Stringlängen
• `Field(default=10, ge=1, le=100)` für numerische Bereiche
• `@field_validator` für benutzerdefinierte Logik (z. B. Whitelist-Filter)
• `Optional[T]` für optionale Felder - 2
Step 2: Pydantic-Modell in JSON Schema konvertieren
Mit `model.model_json_schema()` konvertieren:
```python
schema = SearchQuery.model_json_schema()
schema.pop("title", None) # Pydantic-Metadaten entfernen
```
Schema muss OpenAI Structured Outputs Anforderungen entsprechen. - 3
Step 3: OpenAI API mit Strict Mode aufrufen
In der API-Anfrage `response_format` setzen:
• `type: "json_schema"` – strukturierter Ausgabetyp
• `strict: True` – erzwungene Konformität
• `json_schema.name` – Schema-Name (frei wählbar)
• `json_schema.schema` – konvertiertes JSON Schema aus dem vorherigen Schritt - 4
Step 4: Antwort parsen und erneut validieren
Strict Mode garantiert 100 % Konformität – dennoch zweite Validierung empfohlen:
• `json.loads()` für die Antwortzeichenkette
• `model.model_validate(data)` für Pydantic-Prüfung
• `ValidationError` abfangen und Grenzfälle behandeln - 5
Step 5: Temperature-Parameter konfigurieren
Niedrige Temperature für strukturierte Ausgabe:
```python
temperature=0.1 # empfohlen 0.0–0.2
```
Hohe Temperature erhöht Zufälligkeit und gefährdet Formatstabilität.
FAQ
Was tun bei fehlerhaftem JSON aus dem LLM?
• L1 Parameter-Validierung: Pydantic-Modelle mit automatischer Typkonvertierung und Feldprüfung
• L2 Fehler-Retry: Instructor-Bibliothek mit automatischem Retry und Fehlerrückmeldung ans LLM
• L3 Constrained Decoding: Outlines oder vLLM guided_json – Konformität bereits bei der Generierung
Unterschied zwischen OpenAI und Claude bei strukturierter Ausgabe?
Welches Schema für strukturierte Ausgabe wählen?
• **OpenAI API**: Structured Outputs + Strict Mode (stabilste Option)
• **Claude API**: Pydantic + Instructor-Retry (eigene Validierung nötig)
• **Lokales Modell**: Outlines oder vLLM guided_json (kosteneffizient, hohe Zuverlässigkeit)
• **Schneller Prototyp**: Instructor (gut gekapselt, sofort einsetzbar)
• **Finanz/Medizin**: OpenAI Strict oder Outlines (nahezu null Fehler)
Wie Temperature einstellen?
Wie hoch ist der Performance-Overhead?
• **Prompt-Constraint**: +0 ms Latenz, 5–10 % Fehlerrate
• **JSON Mode**: +50 ms, 2–5 % Fehlerrate
• **Structured Outputs**: +100 ms, <0,1 % Fehlerrate
• **Instructor Retry**: +200–500 ms pro Retry, nahe 0 % Fehlerrate
• **Outlines FSM**: +1–2 s Erstkompilierung, 100 % Konformität
Abwägung nach Zuverlässigkeitsbedarf und Budget.
Welche Fehler retryen, welche nicht?
**Retry sinnvoll**:
• Parameterformat (fehlende Felder, falscher Typ) – LLM kann korrigieren
• API-Fehler (429, 500) – temporäre Serverprobleme
**Kein Retry**:
• Business-Validierung (Stadt nicht in Whitelist) – Nutzerbestätigung nötig
• Tool-Ausführung fehlgeschlagen (leeres Ergebnis) – Fallback statt Retry
Unbegrenztes Retry führt zu Timeouts – Fehlertypen trennen für effiziente Verarbeitung.
14 Min. Lesezeit · Veröffentlicht am: 6. Mai 2026 · Aktualisiert am: 9. Juli 2026
AI Agent Engineering Guide
Wenn du über die Suche hier gelandet bist, kommst du am schnellsten weiter, indem du zum vorherigen oder nächsten Beitrag dieser Serie springst.
Vorheriger
LangGraph vs AutoGen: Zustandsverfolgung im Vergleich – Checkpoint-Mechanismus, Timeout-Wiederherstellung und Auswahlentscheidung
LangGraph vs AutoGen Zustandsverfolgung im Tiefenvergleich: 12 Dimensionen von Checkpoint-Mechanismus, Timeout-Wiederherstellung und verteilter Unterstützung – mit echten Fallstricken, Auswahlentscheidungsbaum und lauffähigem Code.
Teil 11 von 16
Nächster
Agent-Bewertungsbenchmarks in der Praxis: Leitfaden von AgentBench bis DeepEval
Agent-Bewertungsbenchmarks und Performance-Test-Frameworks im Überblick: Vergleich von AgentBench, WebArena, τ-Bench und drei weiteren Benchmarks, DeepEval auf Komponentenebene, mit vollständigen Codebeispielen.
Teil 13 von 16
Ähnliche Beiträge
Agent Sandbox aufbauen: Vollständiger Leitfaden für sichere KI-Codeausführung

Agent Sandbox aufbauen: Vollständiger Leitfaden für sichere KI-Codeausführung
KI-Agent-Entwicklung in der Praxis: Architekturdesign und Implementierungsleitfaden


Kommentare
Melde dich mit GitHub an, um einen Kommentar zu hinterlassen