Wir haben die OpenAI-kompatible Schnittstelle mit tiefergehenden Optimierungen speziell für die Claude-Modellreihe aufgewertet. Sie können Denkprozesse und Caching nun präziser und komfortabler steuern. Verschachteltes Denken in Mehrfachkonversationen ist jetzt benutzerfreundlicher und lässt sich ohne zusätzliche Parameter nahtlos integrieren. Außerdem werden die Beta-Funktionen unterstützt, die Anthropic anbietet.
1. Modell-Denkprozess (Extended Thinking)
1.1 Vorteile des verschachtelten Denkens
Wenn verschachteltes Denken nicht aktiviert ist, führt das Modell das Denken nur einmal zu Beginn eines Assistenten-Zuges aus; nachfolgende Antworten werden nach Erhalt der Tool-Ergebnisse direkt erzeugt, ohne neue Denkblöcke zu produzieren:
User → [Thinking] → Tool Call → Tool Result → Response
Wenn verschachteltes Denken aktiviert ist, fügt das Modell jedes Mal, wenn es ein Tool-Ergebnis erhält, einen neuen Denkblock ein und bildet so eine Argumentationskette:
User → [Thinking] → Tool Call → Tool Result → [Thinking] → Response
↑ Interleaved Thinking
Dadurch kann das Modell:
- auf Grundlage von Tool-Ergebnissen eine Folgeüberlegung anstellen, statt die Ausgaben einfach aneinanderzureihen.
- Überlegungen über mehrere Tool-Aufrufe hinweg verketten, wobei jede Entscheidung auf der Analyse des vorherigen Schritts beruht.
Referenz: Anthropic Interleaved Thinking
1.2 Denken aktivieren
Sie können das Denken auf vier Arten aktivieren; wählen Sie eine davon aus:
| Methode | Beispiel | Beschreibung |
|---|---|---|
reasoning_effort |
"reasoning_effort": "low" |
OpenAI-Standardparameter, auf oberster Ebene des Request-Bodys platziert |
reasoning.effort |
"reasoning": {"effort": "low"} |
Entspricht der vorherigen Methode, innerhalb des reasoning-Objekts platziert |
reasoning.max_tokens |
"reasoning": {"max_tokens": 1024} |
Steuert die maximale Anzahl an Tokens für das Denken präzise |
Modellname mit -think |
"model": "claude-sonnet-4-5-think" |
Der einfachste Weg, es sind keine zusätzlichen Parameter nötig |
Priorität (bei Verwendung mehrerer Methoden):reasoning_effort>reasoning.max_tokens>reasoning.effort>-think-Suffix
Mögliche Werte für effort: minimal / low / medium / high / xhigh
1.3 Rückgabe des Denkprozesses
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 Mehrfachkonversationen unverändert zurückgegeben werden müssen; die interne Struktur kann sich zwischen Anbietern unterscheiden.
Beispiel ohne Streaming (unwichtige Felder weggelassen):
{
"choices": [{
"message": {
"role": "assistant",
"content": "Hello! How can I help you today?",
"reasoning_content": "The user is just saying hello...",
"reasoning_details": {
"type": "thinking",
"thinking": "The user is just saying hello...",
"signature": "Er8CCkYI..."
}
}
}]
}
In Streaming-Antworten wird der Denkinhalt stückweise über delta.reasoning_content und delta.reasoning_details gesendet. Die vollständige Logik zum Zusammenfügen beim Streaming finden Sie im vollständigen Beispiel unten.
1.4 Denkprozess in Mehrfachkonversationen beibehalten (Verschachteltes Denken ist integriert, es sind keine zusätzlichen Parameter nötig)
Damit das Modell seine Denkfähigkeiten in Mehrfachkonversationen fortsetzen kann, fügen Sie die zuvor zurückgegebenen reasoning_details unverändert in die Assistenten-Nachricht der nächsten Runde ein:
messages = [
{"role": "user", "content": "What's the weather like 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": "rainy"}',
}
]
AIHubMix aktiviert verschachteltes Denken automatisch, sobald es historische Denkinformationen in der Anfrage erkennt. So kann das Modell nach Erhalt der Tool-Aufrufergebnisse weiter tiefgehend nachdenken, ohne dass zusätzliche Parameter nötig sind.
1.5 Vollständiges Beispiel
Die folgenden zwei Beispiele zeigen den vollständigen Ablauf eines mehrstufigen Tool-Aufrufs mit verschachteltem Denken: Benutzeranfrage → Modell denkt nach und ruft ein Tool auf → Tool-Ergebnisse einfügen (unter Beibehaltung von reasoning_details) → Modell gibt per verschachteltem Denken die finale Antwort.
Ohne Streaming · Verschachteltes Denken
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": "Get current weather for a location",
"parameters": {
"type": "object",
"properties": {"location": {"type": "string", "description": "City name"}},
"required": ["location"]
}
}
}]
# ── Mock tool execution ───────────────────────────────────────
WEATHER_DB = {
"boston": {"temperature": "45°F (7°C)", "condition": "rainy", "humidity": "85%", "wind": "15 mph NE"},
"tokyo": {"temperature": "72°F (22°C)", "condition": "sunny", "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": "clear"}))
return "{}"
# ── Multi-turn conversation loop ─────────────────────────────
messages = [
{"role": "user", "content": "What's the weather like in Boston? Then recommend what to wear."}
]
turn = 0
while True:
turn += 1
print(f"\n── Turn {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
# Print thinking process
if msg.reasoning_content:
label = "Interleaved Thinking" if turn > 1 else "Thinking"
print(f"[{label}] {msg.reasoning_content}")
# Print response content
if msg.content:
print(f"[Response] {msg.content}")
# Print tool calls
if msg.tool_calls:
for tc in msg.tool_calls:
print(f"[Tool Call: {tc.function.name}] {tc.function.arguments}")
# Build assistant message, preserve reasoning_details (critical!)
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 # pass back unmodified
messages.append(assistant_msg)
# No tool_calls means conversation is done
if not msg.tool_calls:
break
# Execute tools and append results to messages
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 · Verschachteltes Denken
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 execution ─────────────────────────
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a location",
"parameters": {
"type": "object",
"properties": {"location": {"type": "string", "description": "City name"}},
"required": ["location"]
}
}
}]
WEATHER_DB = {
"boston": {"temperature": "45°F (7°C)", "condition": "rainy", "humidity": "85%", "wind": "15 mph NE"},
"tokyo": {"temperature": "72°F (22°C)", "condition": "sunny", "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": "clear"}))
return "{}"
# ── Stream response collector ────────────────────────────────
def stream_and_collect(turn: int, **kwargs):
"""Stream response, print thinking/content in real-time, accumulate reasoning_details/tool_calls."""
rd = {} # accumulated reasoning_details
content = "" # accumulated response text
tc_map = {} # accumulated tool_calls (by index)
cur = "none" # current output section: 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
# ── Handle thinking ──
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
# Print thinking chunks in real-time
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()
# ── Handle content ──
if delta.content:
if cur != "content":
if cur == "thinking":
sys.stdout.write("\n")
cur = "content"
sys.stdout.write("\n[Response] ")
sys.stdout.write(delta.content)
sys.stdout.flush()
content += delta.content
# ── Handle tool_calls ──
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 ""
# End current output section
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,
}
# ── Multi-turn conversation loop ─────────────────────────────
messages = [
{"role": "user", "content": "What's the weather like in Boston? Then recommend what to wear."}
]
turn = 0
while True:
turn += 1
print(f"\n── Turn {turn} ──")
result = stream_and_collect(
turn,
model="claude-sonnet-4-5",
messages=messages,
tools=tools,
extra_body={"reasoning": {"max_tokens": 2000}},
)
# Print tool calls
if result["tool_calls"]:
for tc in result["tool_calls"]:
print(f"[Tool Call: {tc['function']['name']}] {tc['function']['arguments']}")
# Build assistant message, preserve reasoning_details (critical!)
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"] # pass back unmodified
messages.append(assistant_msg)
# No tool_calls means conversation is done
if not result["tool_calls"]:
break
# Execute tools and append results to messages
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
Effort-Modus:
- Opus 4.6 / Sonnet 4.6 und neuer: wird auf die native Adaptive-Thinking-Effort-Stufe von Anthropic abgebildet.
- Andere Modelle: berechnet mit der Formel für
budget_tokens:
budget_tokens = max(min(max_tokens × effort_ratio, 128000), 1024)
| effort | effort_ratio |
|---|---|
| xhigh | 0.95 |
| high | 0.80 |
| medium | 0.50 |
| low | 0.20 |
| minimal | 0.10 |
Zuordnung der Adaptive-Thinking-Effort-Stufen:
| Eingehender Effort | Opus 4.6 | Sonnet 4.6 |
|---|---|---|
| xhigh | max | high |
| high | high | high |
| medium | medium | medium |
| low | low | low |
| minimal | low | low |
max_tokens-Modus: Wird direkt als Anthropic-budget_tokens übernommen.
-think-Suffix: Opus/Sonnet 4.6+ verwendet Adaptive Thinking (effort=medium); andere Modelle setzen budget_tokens = min(10240, max_tokens - 1), mit einem Standardwert von max_tokens von 4096.
2. Prompt-Caching
Sie können Prompt-Caching verwenden, wenn Sie über die Chat-Schnittstelle Anfragen an das Claude-Modell stellen. Indem Sie cache_control-Haltepunkte in Nachrichten setzen, können große Textblöcke (etwa Rollenbeschreibungen, RAG-Daten, Buchkapitel usw.) zur Wiederverwendung gecacht werden. Nachfolgende Anfragen treffen dann direkt den Cache, was die Kosten deutlich senkt.
Offizielle Claude-Dokumentation: Prompt Caching
2.1 Caching-Kosten
| Vorgang | Preismultiplikator (im Verhältnis zum ursprünglichen Input-Preis) |
|---|---|
| Cache-Schreibvorgang (5-Minuten-TTL) | 1.25x |
| Cache-Schreibvorgang (1-Stunden-TTL) | 2x |
| Cache-Lesevorgang | 0.1x |
2.2 Unterstützte Modelle und minimale Cache-Länge
| Modell | Minimale Anzahl an Cache-Tokens |
|---|---|
| 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 |
Begrenzung der Haltepunkte: Maximal 4 cache_control-Haltepunkte pro Anfrage.2.3 Cache-TTL
| TTL | Syntax | Anwendungsszenarien |
|---|---|---|
| 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 die 1-Stunden-TTL sind höher, können aber in langen Sitzungen die Gesamtkosten senken, weil wiederholte Schreibvorgänge entfallen. Alle Claude-Modelle ab Version 4.5 unterstützen von allen Anbietern (einschließlich Anthropic, Amazon Bedrock, Google Vertex AI) die 1-Stunden-TTL.
2.4 Verwendung
Sie können Cache-Haltepunkte über das Feld cache_control in system, user (einschließlich Bilder) und tools setzen. Die folgenden Beispiele zeigen nur die grundlegende Struktur und lassen große Textblöcke weg.
Caching von System-Nachrichten (Standard-TTL von 5 Minuten):
{
"model": "claude-opus-4-5",
"messages": [
{
"role": "system",
"content": [
{"type": "text", "text": "You are an AI assistant"},
{
"type": "text",
"text": "(long context)",
"cache_control": {"type": "ephemeral"}
}
]
},
{
"role": "user",
"content": [{"type": "text", "text": "Hello"}]
}
]
}
Caching von Benutzer-Nachrichten (1-Stunden-TTL):
{
"model": "claude-opus-4-5",
"messages": [
{
"role": "system",
"content": [{"type": "text", "text": "You are an AI assistant"}]
},
{
"role": "user",
"content": [
{
"type": "text",
"text": "(long context)",
"cache_control": {"type": "ephemeral", "ttl": "1h"}
},
{"type": "text", "text": "Hello"}
]
}
]
}
Caching von Bild-Nachrichten:
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {"detail": "auto", "url": "data:image/jpeg;base64,/9j/4AAQ..."},
"cache_control": {"type": "ephemeral"}
},
{"type": "text", "text": "What's this?"}
]
}
Caching von Tool-Definitionen:
cache_control wird auf der obersten Ebene des Tool-Objekts platziert (neben type und function):
{
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a location",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
},
"cache_control": {"type": "ephemeral", "ttl": "1h"}
}]
}
2.5 Cache-Status einsehen
Das Feld usage der Antwort enthält claude_cache_tokens_details mit detaillierten Cache-Informationen:
Erste Anfrage (Cache wird erstellt):
{
"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
}
}
}
Folgeanfragen (Cache-Treffer):
{
"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 Cache mit 5-Minuten-TTL geschrieben wurden |
cache_write_1_hour_input_tokens |
Anzahl der Tokens, die in den Cache mit 1-Stunden-TTL geschrieben wurden |
prompt_tokens_details.cached_tokens |
Anzahl der gecachten Tokens bei einem Cache-Treffer, kompatibel mit dem OpenAI-Format |
3. Request-Header für anthropic-beta
Sie können Beta-Funktionen des Claude-Modells über den HTTP-Header anthropic-beta aktivieren; AIHubMix leitet diesen an die Anthropic-API weiter.
Verwendung
Fügen Sie anthropic-beta dem Request-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": "You are an AI assistant"},
{
"type": "text",
"text": "(long context)",
"cache_control": {"type": "ephemeral"}
}
]
},
{"role": "user", "content": [{"type": "text", "text": "hello"}]}
]
}'
Die verfügbaren Beta-Bezeichner finden Sie in der Anthropic-API-Dokumentation.
Zuletzt aktualisiert: 2026-06-01



