We hebben de OpenAI-compatibele interface geüpgraded met diepere optimalisaties specifiek voor de Claude-serie modellen. Je kunt nu denken en caching preciezer en handiger controleren. Onderbroken denken in meerdaagse gesprekken is nu gebruiksvriendelijker, waardoor naadloze integratie mogelijk is zonder extra parameters. Het ondersteunt ook het inschakelen van de beta-functies die door Anthropic worden aangeboden.
1. Model Denken (Uitgebreid Denken)
1.1 Voordelen van Onderbroken Denken
Wanneer onderbroken denken niet is ingeschakeld, voert het model denken slechts één keer uit aan het begin van een assistent beurt; daaropvolgende reacties worden direct gegenereerd na het ontvangen van toolresultaten, zonder nieuwe denkblokken te produceren:
User → [Denken] → Tool Aanroep → Tool Resultaat → Reactie
Wanneer onderbroken denken is ingeschakeld, voegt het model elke keer dat het een toolresultaat ontvangt een nieuw denkblok toe, waardoor een keten van redenering ontstaat:
User → [Denken] → Tool Aanroep → Tool Resultaat → [Denken] → Reactie
↑ Onderbroken Denken
Dit stelt het model in staat om:
- Secundaire redenering uit te voeren op basis van toolresultaten, in plaats van simpelweg outputs aan elkaar te plakken.
- Redenering te koppelen tussen meerdere toolaanroepen, waarbij elke beslissing is gebaseerd op de analyse van de vorige stap.
Referentie: Anthropic Onderbroken Denken
1.2 Denken Inschakelen
Je kunt denken op vier manieren inschakelen, waarbij je er een van kunt kiezen:
| Methode | Voorbeeld | Beschrijving |
|---|---|---|
reasoning_effort |
"reasoning_effort": "low" |
OpenAI standaardparameter, geplaatst op het hoogste niveau van de aanvraagbody |
reasoning.effort |
"reasoning": {"effort": "low"} |
Equivalent aan de vorige methode, geplaatst binnen het redeneringsobject |
reasoning.max_tokens |
"reasoning": {"max_tokens": 1024} |
Beheert nauwkeurig het maximale aantal tokens voor denken |
Modelnaam met -think |
"model": "claude-sonnet-4-5-think" |
De eenvoudigste manier, vereist geen extra parameters |
Prioriteit (wanneer meerdere methoden worden gebruikt):reasoning_effort>reasoning.max_tokens>reasoning.effort>-thinksuffix
Mogelijke waarden voor inspanning: minimal / low / medium / high / xhigh
1.3 Denken Teruggeven
Het antwoordbericht bevat twee nieuwe velden:
reasoning_content: Denkinhoud (string), voor gemakkelijke weergave.reasoning_details: Volledige gestructureerde informatie over denken, die ongewijzigd moet worden teruggegeven in meerdaagse gesprekken; de interne structuur kan verschillen tussen aanbieders.
Niet-streaming voorbeeld (zonder niet-relevante velden):
{
"choices": [{
"message": {
"role": "assistant",
"content": "Hallo! Hoe kan ik je vandaag helpen?",
"reasoning_content": "De gebruiker zegt gewoon hallo...",
"reasoning_details": {
"type": "denken",
"thinking": "De gebruiker zegt gewoon hallo...",
"signature": "Er8CCkYI..."
}
}
}]
}
In streaming reacties zal de denkinhoud in stukken worden verzonden via delta.reasoning_content en delta.reasoning_details. Voor de volledige streaming concatenatielogica, zie het volledige voorbeeld hieronder.
1.4 Denken Behouden in Meerdaagse Gesprekken (Onderbroken Denken is ingebouwd, geen extra parameters nodig)
Om het model in staat te stellen zijn redeneervaardigheden voort te zetten in meerdaagse gesprekken, plaats je eenvoudig de eerder teruggegeven reasoning_details zoals het is in het volgende ronde assistentbericht:
messages = [
{"role": "user", "content": "Hoe is het weer 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": "regenachtig"}',
}
]
AIHubMix zal automatisch onderbroken denken inschakelen wanneer het historische denkinformatie in de aanvraag detecteert, waardoor het model diepere redenering kan voortzetten na het ontvangen van toolaanroepresultaten zonder extra parameters te vereisen.
1.5 Volledig Voorbeeld
De volgende twee voorbeelden demonstreren het volledige meerdaagse Tool Aanroep + onderbroken denkproces: gebruikersvraag → model denkt en roept een tool aan → injecteer toolresultaten (behoud reasoning_details) → model onderbroken denken geeft de uiteindelijke reactie.
Niet-streaming · Onderbroken 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 definitie ───────────────────────────────────────────
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Haal het huidige weer op voor een locatie",
"parameters": {
"type": "object",
"properties": {"location": {"type": "string", "description": "Stadsnaam"}},
"required": ["location"]
}
}
}]
# ── Mock tool uitvoering ───────────────────────────────────────
WEATHER_DB = {
"boston": {"temperature": "45°F (7°C)", "condition": "regenachtig", "humidity": "85%", "wind": "15 mph NE"},
"tokyo": {"temperature": "72°F (22°C)", "condition": "zonnig", "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": "helder"}))
return "{}"
# ── Meerdaagse gesprekslus ─────────────────────────────
messages = [
{"role": "user", "content": "Hoe is het weer in Boston? Aanbevelingen voor wat te dragen."}
]
turn = 0
while True:
turn += 1
print(f"\n── Beurt {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 denkproces
if msg.reasoning_content:
label = "Onderbroken Denken" if turn > 1 else "Denken"
print(f"[{label}] {msg.reasoning_content}")
# Print reactie-inhoud
if msg.content:
print(f"[Reactie] {msg.content}")
# Print toolaanroepen
if msg.tool_calls:
for tc in msg.tool_calls:
print(f"[Tool Aanroep: {tc.function.name}] {tc.function.arguments}")
# Bouw assistentbericht, behoud reasoning_details (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 # ongewijzigd teruggeven
messages.append(assistant_msg)
# Geen tool_calls betekent dat het gesprek is afgelopen
if not msg.tool_calls:
break
# Voer tools uit en voeg resultaten toe aan berichten
for tc in msg.tool_calls:
args = json.loads(tc.function.arguments)
result = execute_tool(tc.function.name, args)
print(f"[Tool Resultaat: {tc.function.name}] {result}")
messages.append({"role": "tool", "tool_call_id": tc.id, "content": result})
Streaming · Onderbroken 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 definitie & mock uitvoering ─────────────────────────
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Haal het huidige weer op voor een locatie",
"parameters": {
"type": "object",
"properties": {"location": {"type": "string", "description": "Stadsnaam"}},
"required": ["location"]
}
}
}]
WEATHER_DB = {
"boston": {"temperature": "45°F (7°C)", "condition": "regenachtig", "humidity": "85%", "wind": "15 mph NE"},
"tokyo": {"temperature": "72°F (22°C)", "condition": "zonnig", "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": "helder"}))
return "{}"
# ── Stream respons verzamelaar ────────────────────────────────
def stream_and_collect(turn: int, **kwargs):
"""Stream respons, print denken/inhoud in real-time, accumuleer reasoning_details/tool_calls."""
rd = {} # geaccumuleerde reasoning_details
content = "" # geaccumuleerde respons tekst
tc_map = {} # geaccumuleerde tool_calls (per index)
cur = "none" # huidige output sectie: none / denken / inhoud
stream = client.chat.completions.create(stream=True, **kwargs)
for chunk in stream:
if not chunk.choices:
continue
delta = chunk.choices[0].delta
# ── Behandel denken ──
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 denkstukken in real-time
thinking_chunk = rd_delta.get("thinking", "")
if thinking_chunk:
if cur != "denken":
cur = "denken"
label = "Onderbroken Denken" if turn > 1 else "Denken"
sys.stdout.write(f"\n[{label}] ")
sys.stdout.write(thinking_chunk)
sys.stdout.flush()
# ── Behandel inhoud ──
if delta.content:
if cur != "inhoud":
if cur == "denken":
sys.stdout.write("\n")
cur = "inhoud"
sys.stdout.write("\n[Reactie] ")
sys.stdout.write(delta.content)
sys.stdout.flush()
content += delta.content
# ── Behandel 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 ""
# Eind huidige output sectie
if cur in ("denken", "inhoud"):
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,
}
# ── Meerdaagse gesprekslus ─────────────────────────────
messages = [
{"role": "user", "content": "Hoe is het weer in Boston? Aanbevelingen voor wat te dragen."}
]
turn = 0
while True:
turn += 1
print(f"\n── Beurt {turn} ──")
result = stream_and_collect(
turn,
model="claude-sonnet-4-5",
messages=messages,
tools=tools,
extra_body={"reasoning": {"max_tokens": 2000}},
)
# Print toolaanroepen
if result["tool_calls"]:
for tc in result["tool_calls"]:
print(f"[Tool Aanroep: {tc['function']['name']}] {tc['function']['arguments']}")
# Bouw assistentbericht, behoud reasoning_details (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"] # ongewijzigd teruggeven
messages.append(assistant_msg)
# Geen tool_calls betekent dat het gesprek is afgelopen
if not result["tool_calls"]:
break
# Voer tools uit en voeg resultaten toe aan berichten
for tc in result["tool_calls"]:
args = json.loads(tc["function"]["arguments"])
tool_result = execute_tool(tc["function"]["name"], args)
print(f"[Tool Resultaat: {tc['function']['name']}] {tool_result}")
messages.append({"role": "tool", "tool_call_id": tc["id"], "content": tool_result})
1.6 Regels voor Denken Intensiteit Mapping
Inspanning Modus:
- Opus 4.6 / Sonnet 4.6 en hoger: map naar Anthropic's native Adaptief Denken inspanningsniveau.
- Andere modellen: berekend met de formule voor
budget_tokens:
budget_tokens = max(min(max_tokens × effort_ratio, 128000), 1024)
| inspanning | inspanning_ratio |
|---|---|
| xhigh | 0.95 |
| high | 0.80 |
| medium | 0.50 |
| low | 0.20 |
| minimal | 0.10 |
Adaptieve Denken Inspanning Mapping:
| Binnenkomende Inspanning | Opus 4.6 | Sonnet 4.6 |
|---|---|---|
| xhigh | max | high |
| high | high | high |
| medium | medium | medium |
| low | low | low |
| minimal | low | low |
max_tokens Modus: Direct toegewezen als Anthropic's budget_tokens.
-think suffix: Opus/Sonnet 4.6+ gebruikt adaptief denken (inspanning=medium); andere modellen stellen budget_tokens = min(10240, max_tokens - 1), met een standaard max_tokens van 4096.
2. Prompt Caching
Je kunt Prompt Caching gebruiken bij het doen van aanvragen aan het Claude-model via de Chat-interface. Door cache_control breekpunten in berichten in te stellen, kunnen grote tekstblokken (zoals rolkaarten, RAG-gegevens, boekhoofdstukken, enz.) worden gecached voor hergebruik, waardoor daaropvolgende aanvragen direct de cache kunnen aanspreken en de kosten aanzienlijk kunnen verlagen.
Claude Officiële Documentatie: Prompt Caching
2.1 Caching Kosten
| Operatie | Prijsvermenigvuldiger (ten opzichte van originele invoerprijs) |
|---|---|
| Cache Schrijven (5-minuten TTL) | 1.25x |
| Cache Schrijven (1-uur TTL) | 2x |
| Cache Lezen | 0.1x |
2.2 Ondersteunde Modellen en Minimale Cache Lengte
| Model | Minimale Cache Token Aantal |
|---|---|
| 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 (verouderd) | 1024 |
| Claude Haiku 4.5 | 4096 |
| Claude Haiku 3.5 (verouderd) / Haiku 3 | 2048 |
Breakpoint Hoeveelheidslimiet: Een maximum van 4 cache_control breekpunten per aanvraag.2.3 Cache TTL
| TTL | Syntax | Toepasselijke Scenario's |
|---|---|---|
| 5 minuten (standaard) | "cache_control": {"type": "ephemeral"} |
Korte sessies, routine aanvragen |
| 1 uur | "cache_control": {"type": "ephemeral", "ttl": "1h"} |
Lange sessies, om herhaalde cache schrijfacties te vermijden |
Schrijfkosten voor 1-uur TTL zijn hoger, maar ze kunnen totale uitgaven besparen door herhaalde schrijfacties in lange sessies te verminderen. Alle modellen vanaf Claude 4.5 en later van alle aanbieders (inclusief Anthropic, Amazon Bedrock, Google Vertex AI) ondersteunen 1-uur TTL.
2.4 Gebruik
Je kunt cache breekpunten instellen met behulp van het cache_control veld in system, user (inclusief afbeeldingen), en tools. De volgende voorbeelden tonen alleen de sleutelstructuur, waarbij grote tekstblokken zijn weggelaten.
Systeembericht Caching (standaard 5-minuten TTL):
{
"model": "claude-opus-4-5",
"messages": [
{
"role": "system",
"content": [
{"type": "text", "text": "Je bent een AI-assistent"},
{
"type": "text",
"text": "(lange context)",
"cache_control": {"type": "ephemeral"}
}
]
},
{
"role": "user",
"content": [{"type": "text", "text": "Hallo"}]
}
]
}
Gebruikersbericht Caching (1-uur TTL):
{
"model": "claude-opus-4-5",
"messages": [
{
"role": "system",
"content": [{"type": "text", "text": "Je bent een AI-assistent"}]
},
{
"role": "user",
"content": [
{
"type": "text",
"text": "(lange context)",
"cache_control": {"type": "ephemeral", "ttl": "1h"}
},
{"type": "text", "text": "Hallo"}
]
}
]
}
Afbeelding Bericht 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": "Wat is dit?"}
]
}
Tool Definitie Caching:
cache_control wordt geplaatst op het hoogste niveau van het toolobject (naast type en function):
{
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Haal het huidige weer op voor een locatie",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
},
"cache_control": {"type": "ephemeral", "ttl": "1h"}
}]
}
2.5 Cache Status Bekijken
De usage van de respons zal claude_cache_tokens_details retourneren, die gedetailleerde cache-informatie vastlegt:
Eerste Aanvraag (Cache Aanmaken):
{
"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
}
}
}
Vervolg Aanvragen (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
}
}
}
| Veld | Betekenis |
|---|---|
cache_creation_input_tokens |
Aantal tokens geschreven naar cache in deze aanvraag |
cache_read_input_tokens |
Aantal tokens gelezen uit cache in deze aanvraag |
cache_write_5_minutes_input_tokens |
Aantal tokens geschreven naar 5-minuten TTL cache |
cache_write_1_hour_input_tokens |
Aantal tokens geschreven naar 1-uur TTL cache |
prompt_tokens_details.cached_tokens |
Aantal gecachede tokens wanneer de cache wordt aangesproken, compatibel met OpenAI-formaat |
3. Aanvraagheader voor anthropic-beta
Je kunt beta-functies van het Claude-model inschakelen via de HTTP-header anthropic-beta, die AIHubMix doorgeeft aan de Anthropic API.
Gebruik
Voeg anthropic-beta toe aan de aanvraagheader, met de waarde als de bijbehorende beta-functie-identificator:
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": "Je bent een AI-assistent"},
{
"type": "text",
"text": "(lange context)",
"cache_control": {"type": "ephemeral"}
}
]
},
{"role": "user", "content": [{"type": "text", "text": "hallo"}]}
]
}'
Voor specifieke beschikbare beta-identificatoren, raadpleeg de Anthropic API Documentatie.
Laatste update: 2026-06-01