Wir haben die OpenAI-kompatible Schnittstelle mit tiefergehenden Optimierungen speziell für die Claude-Modellreihe aktualisiert. Sie können jetzt Denken und Caching präziser und bequemer steuern. Interleaved Thinking in mehrteiligen Gesprächen ist jetzt benutzerfreundlicher, was eine nahtlose Integration ohne zusätzliche Parameter ermöglicht. Es unterstützt auch die Aktivierung der von Anthropic angebotenen Beta-Funktionen.
1. Modelldenken (Erweitertes Denken)
1.1 Vorteile des Interleaved Thinking
Wenn Interleaved Thinking nicht aktiviert ist, führt das Modell das Denken nur einmal zu Beginn eines Assistenten-Durchgangs aus; nachfolgende Antworten werden direkt nach Erhalt der Tool-Ergebnisse generiert, ohne neue Denkblöcke zu produzieren:
User → [Thinking] → Tool Call → Tool Result → Response
Wenn Interleaved Thinking aktiviert ist, fügt das Modell jedes Mal, wenn es ein Tool-Ergebnis erhält, einen neuen Denkblock ein und bildet eine Kette von Überlegungen:
User → [Thinking] → Tool Call → Tool Result → [Thinking] → Response
↑ Interleaved Thinking
- Sekundäres Denken basierend auf Tool-Ergebnissen durchzuführen, anstatt einfach Ausgaben zu verketten.
- Überlegungen zwischen mehreren Tool-Aufrufen zu verknüpfen, wobei jede Entscheidung auf der Analyse des vorherigen Schrittes basiert.
Referenz: Anthropic Interleaved Thinking
1.2 Aktivierung des Denkens
Sie können das Denken auf vier Arten aktivieren, indem Sie eine davon auswählen:
| Methode | Beispiel | Beschreibung |
|---|---|---|
reasoning_effort |
"reasoning_effort": "low" |
OpenAI-Standardparameter, der auf der obersten Ebene des Anfragekörpers platziert ist |
reasoning.effort |
"reasoning": {"effort": "low"} |
Entspricht der vorherigen Methode, die innerhalb des Denkobjekts platziert ist |
reasoning.max_tokens |
"reasoning": {"max_tokens": 1024} |
Steuert präzise die maximale Anzahl von Tokens für das Denken |
Modellname mit -think |
"model": "claude-sonnet-4-5-think" |
Der einfachste Weg, erfordert keine zusätzlichen Parameter |
Priorität (wenn mehrere Methoden verwendet werden):reasoning_effort>reasoning.max_tokens>reasoning.effort>-thinkSuffix
Mögliche Werte für den Aufwand: minimal / low / medium / high / xhigh
1.3 Rückgabe des Denkens
Die Antwortnachricht enthält zwei neue Felder:
reasoning_content: Denkinhalt (String), zur einfachen Anzeige.reasoning_details: Vollständige strukturierte Informationen über das Denken, die in mehrteiligen Gesprächen unverändert zurückgegeben werden müssen; die interne Struktur kann zwischen Anbietern variieren.
Beispiel ohne Streaming (ohne nicht verwandte Felder):
{
"choices": [{
"message": {
"role": "assistant",
"content": "Hallo! Wie kann ich Ihnen heute helfen?",
"reasoning_content": "Der Benutzer sagt nur Hallo...",
"reasoning_details": {
"type": "thinking",
"thinking": "Der Benutzer sagt nur Hallo...",
"signature": "Er8CCkYI..."
}
}
}]
}
In Streaming-Antworten wird der Denkinhalt in Teilen über delta.reasoning_content und delta.reasoning_details gesendet. Für die vollständige Streaming-Verkettungslogik siehe das vollständige Beispiel unten.
1.4 Beibehaltung des Denkens in mehrteiligen Gesprächen (Interleaved Thinking ist integriert, keine zusätzlichen Parameter erforderlich)
Um es dem Modell zu ermöglichen, seine Denkfähigkeiten in mehrteiligen Gesprächen fortzusetzen, fügen Sie einfach die zuvor zurückgegebenen reasoning_details unverändert in die nächste Runde der Assistenten-Nachricht ein:
messages = [
{"role": "user", "content": "Wie ist das Wetter in Boston?"},
{
"role": "assistant",
"content": response.choices[0].message.content,
"tool_calls": response.choices[0].message.tool_calls,
"reasoning_details": response.choices[0].message.reasoning_details,
},
{
"role": "tool",
"tool_call_id": "toolu_xxx",
"content": '{"temperature": 45, "condition": "regnerisch"}',
}
]
AIHubMix wird automatisch Interleaved Thinking aktivieren, wenn es historische Denkinformationen in der Anfrage erkennt, sodass das Modell nach Erhalt der Tool-Aufruf-Ergebnisse ohne zusätzliche Parameter tiefes Denken fortsetzen kann.
1.5 Vollständiges Beispiel
Die folgenden zwei Beispiele demonstrieren den vollständigen mehrteiligen Tool Call + Interleaved Thinking-Prozess: Benutzeranfrage → Modell denkt und ruft ein Tool auf → injiziert Tool-Ergebnisse (beibehaltung von reasoning_details) → Modell Interleaved Thinking gibt die endgültige Antwort.
Kein Streaming · Interleaved Thinking
import os
import json
from openai import OpenAI
client = OpenAI(
base_url="https://aihubmix.com/v1",
api_key=os.environ.get("AIHUBMIX_API_KEY", "sk-***"),
)
# ── Tool-Definition ───────────────────────────────────────────
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Aktuelles Wetter für einen Standort abrufen",
"parameters": {
"type": "object",
"properties": {"location": {"type": "string", "description": "Stadtname"}},
"required": ["location"]
}
}
}]
# ── Mock-Tool-Ausführung ───────────────────────────────────────
WEATHER_DB = {
"boston": {"temperature": "45°F (7°C)", "condition": "regnerisch", "humidity": "85%", "wind": "15 mph NE"},
"tokyo": {"temperature": "72°F (22°C)", "condition": "sonnig", "humidity": "45%", "wind": "5 mph S"},
}
def execute_tool(name: str, args: dict) -> str:
if name == "get_weather":
key = next((k for k in WEATHER_DB if k in args.get("location", "").lower()), None)
return json.dumps(WEATHER_DB.get(key, {"temperature": "65°F", "condition": "klar"}))
return "{}"
# ── Mehrteilige Gesprächsschleife ─────────────────────────────
messages = [
{"role": "user", "content": "Wie ist das Wetter in Boston? Dann empfehlen Sie, was man tragen sollte."}
]
turn = 0
while True:
turn += 1
print(f"\n── Runde {turn} ──")
response = client.chat.completions.create(
model="claude-sonnet-4-5",
messages=messages,
tools=tools,
extra_body={"reasoning": {"max_tokens": 2000}},
)
msg = response.choices[0].message
# Denkprozess ausgeben
if msg.reasoning_content:
label = "Interleaved Thinking" if turn > 1 else "Thinking"
print(f"[{label}] {msg.reasoning_content}")
# Antwortinhalt ausgeben
if msg.content:
print(f"[Antwort] {msg.content}")
# Tool-Aufrufe ausgeben
if msg.tool_calls:
for tc in msg.tool_calls:
print(f"[Tool Call: {tc.function.name}] {tc.function.arguments}")
# Assistenten-Nachricht erstellen, reasoning_details beibehalten (kritisch!)
assistant_msg = {"role": "assistant", "content": msg.content}
if msg.tool_calls:
assistant_msg["tool_calls"] = msg.tool_calls
if msg.reasoning_details:
assistant_msg["reasoning_details"] = msg.reasoning_details # unverändert zurückgeben
messages.append(assistant_msg)
# Keine Tool-Aufrufe bedeutet, dass das Gespräch beendet ist
if not msg.tool_calls:
break
# Tools ausführen und Ergebnisse zu den Nachrichten hinzufügen
for tc in msg.tool_calls:
args = json.loads(tc.function.arguments)
result = execute_tool(tc.function.name, args)
print(f"[Tool Result: {tc.function.name}] {result}")
messages.append({"role": "tool", "tool_call_id": tc.id, "content": result})
Streaming · Interleaved Thinking
import os
import sys
import json
from openai import OpenAI
client = OpenAI(
base_url="https://aihubmix.com/v1",
api_key=os.environ.get("AIHUBMIX_API_KEY", "sk-***"),
)
# ── Tool-Definition & Mock-Ausführung ─────────────────────────
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Aktuelles Wetter für einen Standort abrufen",
"parameters": {
"type": "object",
"properties": {"location": {"type": "string", "description": "Stadtname"}},
"required": ["location"]
}
}
}]
WEATHER_DB = {
"boston": {"temperature": "45°F (7°C)", "condition": "regnerisch", "humidity": "85%", "wind": "15 mph NE"},
"tokyo": {"temperature": "72°F (22°C)", "condition": "sonnig", "humidity": "45%", "wind": "5 mph S"},
}
def execute_tool(name: str, args: dict) -> str:
if name == "get_weather":
key = next((k for k in WEATHER_DB if k in args.get("location", "").lower()), None)
return json.dumps(WEATHER_DB.get(key, {"temperature": "65°F", "condition": "klar"}))
return "{}"
# ── Stream-Antwortsammler ────────────────────────────────
def stream_and_collect(turn: int, **kwargs):
"""Stream-Antwort, Denken/Inhalt in Echtzeit ausgeben, reasoning_details/tool_calls sammeln."""
rd = {} # gesammelte reasoning_details
content = "" # gesammelter Antworttext
tc_map = {} # gesammelte tool_calls (nach Index)
cur = "none" # aktueller Ausgabebereich: none / thinking / content
stream = client.chat.completions.create(stream=True, **kwargs)
for chunk in stream:
if not chunk.choices:
continue
delta = chunk.choices[0].delta
# ── Denken behandeln ──
rd_delta = getattr(delta, "reasoning_details", None)
if rd_delta and isinstance(rd_delta, dict):
for k, v in rd_delta.items():
if k == "type":
rd[k] = v
elif isinstance(v, str):
rd[k] = rd.get(k, "") + v
elif v is not None:
rd[k] = v
# Denkblöcke in Echtzeit ausgeben
thinking_chunk = rd_delta.get("thinking", "")
if thinking_chunk:
if cur != "thinking":
cur = "thinking"
label = "Interleaved Thinking" if turn > 1 else "Thinking"
sys.stdout.write(f"\n[{label}] ")
sys.stdout.write(thinking_chunk)
sys.stdout.flush()
# ── Inhalt behandeln ──
if delta.content:
if cur != "content":
if cur == "thinking":
sys.stdout.write("\n")
cur = "content"
sys.stdout.write("\n[Antwort] ")
sys.stdout.write(delta.content)
sys.stdout.flush()
content += delta.content
# ── Tool-Aufrufe behandeln ──
for tc in delta.tool_calls or []:
i = tc.index
if i not in tc_map:
tc_map[i] = {"id": "", "type": "function",
"function": {"name": "", "arguments": ""}}
if tc.id:
tc_map[i]["id"] = tc.id
if tc.function:
tc_map[i]["function"]["name"] += tc.function.name or ""
tc_map[i]["function"]["arguments"] += tc.function.arguments or ""
# Aktuellen Ausgabebereich beenden
if cur in ("thinking", "content"):
sys.stdout.write("\n")
tool_calls = [tc_map[i] for i in sorted(tc_map)] if tc_map else None
return {
"content": content or None,
"reasoning_details": rd or None,
"tool_calls": tool_calls,
}
# ── Mehrteilige Gesprächsschleife ─────────────────────────────
messages = [
{"role": "user", "content": "Wie ist das Wetter in Boston? Dann empfehlen Sie, was man tragen sollte."}
]
turn = 0
while True:
turn += 1
print(f"\n── Runde {turn} ──")
result = stream_and_collect(
turn,
model="claude-sonnet-4-5",
messages=messages,
tools=tools,
extra_body={"reasoning": {"max_tokens": 2000}},
)
# Tool-Aufrufe ausgeben
if result["tool_calls"]:
for tc in result["tool_calls"]:
print(f"[Tool Call: {tc['function']['name']}] {tc['function']['arguments']}")
# Assistenten-Nachricht erstellen, reasoning_details beibehalten (kritisch!)
assistant_msg = {"role": "assistant", "content": result["content"]}
if result["tool_calls"]:
assistant_msg["tool_calls"] = result["tool_calls"]
if result["reasoning_details"]:
assistant_msg["reasoning_details"] = result["reasoning_details"] # unverändert zurückgeben
messages.append(assistant_msg)
# Keine Tool-Aufrufe bedeutet, dass das Gespräch beendet ist
if not result["tool_calls"]:
break
# Tools ausführen und Ergebnisse zu den Nachrichten hinzufügen
for tc in result["tool_calls"]:
args = json.loads(tc["function"]["arguments"])
tool_result = execute_tool(tc["function"]["name"], args)
print(f"[Tool Result: {tc['function']['name']}] {tool_result}")
messages.append({"role": "tool", "tool_call_id": tc["id"], "content": tool_result})
1.6 Regeln zur Zuordnung der Denkintensität
Aufwandsmodus:
- Opus 4.6 / Sonnet 4.6 und höher: wird auf Anthropics natives Adaptive Thinking Aufwand-Niveau abgebildet.
- Andere Modelle: berechnet mit der Formel für
budget_tokens:
budget_tokens = max(min(max_tokens × effort_ratio, 128000), 1024)
| Aufwand | Aufwandsverhältnis |
|---|---|
| xhigh | 0.95 |
| hoch | 0.80 |
| mittel | 0.50 |
| niedrig | 0.20 |
| minimal | 0.10 |
Zuordnung des adaptiven Denkaufwands:
| Eingehender Aufwand | Opus 4.6 | Sonnet 4.6 |
|---|---|---|
| xhigh | max | hoch |
| hoch | hoch | hoch |
| mittel | mittel | mittel |
| niedrig | niedrig | niedrig |
| minimal | niedrig | niedrig |
max_tokens-Modus: Direkt zugewiesen als Anthropics budget_tokens.
-think Suffix: Opus/Sonnet 4.6+ verwendet adaptives Denken (Aufwand=mittel); andere Modelle setzen budget_tokens = min(10240, max_tokens - 1), mit einem Standard max_tokens von 4096.
2. Prompt-Caching
Sie können Prompt-Caching verwenden, wenn Sie Anfragen an das Claude-Modell über die Chat-Schnittstelle stellen. Durch das Setzen von cache_control Breakpoints in Nachrichten können große Textblöcke (wie Rollenbeschreibungen, RAG-Daten, Buchkapitel usw.) für die Wiederverwendung zwischengespeichert werden, sodass nachfolgende Anfragen direkt auf den Cache zugreifen und die Kosten erheblich senken können.
Offizielle Dokumentation zu Claude: Prompt-Caching
2.1 Caching-Kosten
| Operation | Preisfaktor (relativ zum ursprünglichen Eingabepreis) |
|---|---|
| Cache-Schreibung (5 Minuten TTL) | 1.25x |
| Cache-Schreibung (1 Stunde TTL) | 2x |
| Cache-Lesen | 0.1x |
2.2 Unterstützte Modelle und minimale Cache-Länge
| Modell | Minimale Cache-Token-Anzahl |
|---|---|
| Claude Opus 4.8 | 1024 |
| Claude Opus 4.7 | 2048 |
| Claude Opus 4.6 / Opus 4.5 | 4096 |
| Claude Sonnet 4.6 / Sonnet 4.5 / Opus 4.1 / Opus 4 / Sonnet 4 / Sonnet 3.7 (veraltet) | 1024 |
| Claude Haiku 4.5 | 4096 |
| Claude Haiku 3.5 (veraltet) / Haiku 3 | 2048 |
Grenze für die Anzahl der Breakpoints: Maximal 4 cache_control Breakpoints pro Anfrage.2.3 Cache TTL
| TTL | Syntax | Anwendbare Szenarien |
|---|---|---|
| 5 Minuten (Standard) | "cache_control": {"type": "ephemeral"} |
Kurze Sitzungen, routinemäßige Anfragen |
| 1 Stunde | "cache_control": {"type": "ephemeral", "ttl": "1h"} |
Lange Sitzungen, um wiederholte Cache-Schreibvorgänge zu vermeiden |
Die Schreibkosten für 1 Stunde TTL sind höher, aber sie können die Gesamtausgaben senken, indem sie wiederholte Schreibvorgänge in langen Sitzungen reduzieren. Alle Modelle von Claude 4.5 und höher von allen Anbietern (einschließlich Anthropic, Amazon Bedrock, Google Vertex AI) unterstützen 1 Stunde TTL.
2.4 Verwendung
Sie können Cache-Breakpoints mit dem cache_control Feld in system, user (einschließlich Bilder) und tools festlegen. Die folgenden Beispiele zeigen nur die Schlüsselstruktur und lassen große Textblöcke weg.
Systemnachricht-Caching (Standard 5 Minuten TTL):
{
"model": "claude-opus-4-5",
"messages": [
{
"role": "system",
"content": [
{"type": "text", "text": "Sie sind ein KI-Assistent"},
{
"type": "text",
"text": "(langer Kontext)",
"cache_control": {"type": "ephemeral"}
}
]
},
{
"role": "user",
"content": [{"type": "text", "text": "Hallo"}]
}
]
}
Benutzernachricht-Caching (1 Stunde TTL):
{
"model": "claude-opus-4-5",
"messages": [
{
"role": "system",
"content": [{"type": "text", "text": "Sie sind ein KI-Assistent"}]
},
{
"role": "user",
"content": [
{
"type": "text",
"text": "(langer Kontext)",
"cache_control": {"type": "ephemeral", "ttl": "1h"}
},
{"type": "text", "text": "Hallo"}
]
}
]
}
Bildnachricht-Caching:
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {"detail": "auto", "url": "data:image/jpeg;base64,/9j/4AAQ..."},
"cache_control": {"type": "ephemeral"}
},
{"type": "text", "text": "Was ist das?"}
]
}
Tool-Definitions-Caching:
cache_control wird auf der obersten Ebene des Tool-Objekts platziert (neben type und function):
{
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Aktuelles Wetter für einen Standort abrufen",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
},
"cache_control": {"type": "ephemeral", "ttl": "1h"}
}]
}
2.5 Cache-Status anzeigen
Das usage der Antwort gibt claude_cache_tokens_details zurück, das detaillierte Cache-Informationen aufzeichnet:
Erste Anfrage (Cache erstellen):
{
"usage": {
"prompt_tokens": 22,
"completion_tokens": 890,
"total_tokens": 912,
"claude_cache_tokens_details": {
"cache_creation_input_tokens": 6266,
"cache_read_input_tokens": 0,
"cache_write_5_minutes_input_tokens": 6266,
"cache_write_1_hour_input_tokens": 0
}
}
}
Nachfolgende Anfragen (Cache-Hit):
{
"usage": {
"prompt_tokens": 22,
"completion_tokens": 810,
"total_tokens": 832,
"prompt_tokens_details": {
"cached_tokens": 6266
},
"claude_cache_tokens_details": {
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 6266,
"cache_write_5_minutes_input_tokens": 0,
"cache_write_1_hour_input_tokens": 0
}
}
}
| Feld | Bedeutung |
|---|---|
cache_creation_input_tokens |
Anzahl der Tokens, die in dieser Anfrage in den Cache geschrieben wurden |
cache_read_input_tokens |
Anzahl der Tokens, die in dieser Anfrage aus dem Cache gelesen wurden |
cache_write_5_minutes_input_tokens |
Anzahl der Tokens, die in den 5-Minuten-TTL-Cache geschrieben wurden |
cache_write_1_hour_input_tokens |
Anzahl der Tokens, die in den 1-Stunden-TTL-Cache geschrieben wurden |
prompt_tokens_details.cached_tokens |
Anzahl der zwischengespeicherten Tokens, wenn der Cache getroffen wird, kompatibel mit dem OpenAI-Format |
3. Anfrage-Header für anthropic-beta
Sie können Beta-Funktionen des Claude-Modells über den HTTP-Header anthropic-beta aktivieren, den AIHubMix an die Anthropic-API weiterleitet.
Verwendung
Fügen Sie anthropic-beta zum Anfrage-Header hinzu, wobei der Wert der entsprechende Beta-Funktionsbezeichner ist:
curl "https://aihubmix.com/v1/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $AIHUBMIX_API_KEY" \
-H "anthropic-beta: context-1m-2025-08-07" \
-d '{
"model": "claude-opus-4-5",
"messages": [
{
"role": "system",
"content": [
{"type": "text", "text": "Sie sind ein KI-Assistent"},
{
"type": "text",
"text": "(langer Kontext)",
"cache_control": {"type": "ephemeral"}
}
]
},
{"role": "user", "content": [{"type": "text", "text": "Hallo"}]}
]
}'
Für spezifische verfügbare Beta-Bezeichner siehe die Anthropic API-Dokumentation.
Zuletzt aktualisiert: 2026-06-01