Abbiamo aggiornato l'interfaccia compatibile con OpenAI con ottimizzazioni più profonde specificamente per i modelli della serie Claude. Ora puoi controllare il pensiero e il caching in modo più preciso e conveniente. Il pensiero intercalato nelle conversazioni a più turni è ora più user-friendly, consentendo un'integrazione senza soluzione di continuità senza parametri aggiuntivi. Supporta anche l'attivazione delle funzionalità beta offerte da Anthropic.
1. Pensiero del Modello (Pensiero Esteso)
1.1 Vantaggi del Pensiero Intercalato
Quando il pensiero intercalato non è abilitato, il modello esegue il pensiero solo una volta all'inizio di un turno dell'assistente; le risposte successive vengono generate direttamente dopo aver ricevuto i risultati degli strumenti, senza produrre nuovi blocchi di pensiero:
User → [Pensiero] → Chiamata Strumento → Risultato Strumento → Risposta
Quando il pensiero intercalato è abilitato, il modello inserisce un nuovo blocco di pensiero ogni volta che riceve un risultato dello strumento, formando una catena di ragionamento:
User → [Pensiero] → Chiamata Strumento → Risultato Strumento → [Pensiero] → Risposta
↑ Pensiero Intercalato
Questo consente al modello di:
- Eseguire un ragionamento secondario basato sui risultati degli strumenti, piuttosto che semplicemente concatenare le uscite.
- Collegare il ragionamento tra più chiamate agli strumenti, dove ogni decisione si basa sull'analisi del passo precedente.
Riferimento: Pensiero Intercalato di Anthropic
1.2 Abilitare il Pensiero
Puoi abilitare il pensiero in quattro modi, scegliendo uno di essi:
| Metodo | Esempio | Descrizione |
|---|---|---|
reasoning_effort |
"reasoning_effort": "low" |
Parametro standard di OpenAI, posizionato a livello superiore del corpo della richiesta |
reasoning.effort |
"reasoning": {"effort": "low"} |
Equivalente al metodo precedente, posizionato all'interno dell'oggetto di ragionamento |
reasoning.max_tokens |
"reasoning": {"max_tokens": 1024} |
Controlla precisamente il numero massimo di token per il pensiero |
Nome del modello con -think |
"model": "claude-sonnet-4-5-think" |
Il modo più semplice, non richiede parametri aggiuntivi |
Priorità (quando vengono utilizzati più metodi):reasoning_effort>reasoning.max_tokens>reasoning.effort>-thinksuffisso
Valori possibili per l'impegno: minimal / low / medium / high / xhigh
1.3 Restituzione del Pensiero
Il messaggio di risposta includerà due nuovi campi:
reasoning_content: Contenuto del pensiero (stringa), per una facile visualizzazione.reasoning_details: Informazioni strutturate complete sul pensiero, che devono essere restituite così come sono nelle conversazioni a più turni; la struttura interna può differire tra i fornitori.
Esempio non in streaming (omettendo campi non correlati):
{
"choices": [{
"message": {
"role": "assistant",
"content": "Ciao! Come posso aiutarti oggi?",
"reasoning_content": "L'utente sta solo dicendo ciao...",
"reasoning_details": {
"type": "thinking",
"thinking": "L'utente sta solo dicendo ciao...",
"signature": "Er8CCkYI..."
}
}
}]
}
Nei risultati in streaming, il contenuto del pensiero sarà inviato in blocchi tramite delta.reasoning_content e delta.reasoning_details. Per la logica completa di concatenazione in streaming, fare riferimento all'esempio completo qui sotto.
1.4 Mantenere il Pensiero nelle Conversazioni a Più Turni (Il Pensiero Intercalato è integrato, non sono necessari parametri aggiuntivi)
Per consentire al modello di continuare le sue capacità di ragionamento nelle conversazioni a più turni, basta inserire il reasoning_details restituito in precedenza così com'è nel messaggio dell'assistente del turno successivo:
messages = [
{"role": "user", "content": "Che tempo fa a 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 abiliterà automaticamente il pensiero intercalato quando rileva informazioni storiche sul pensiero nella richiesta, consentendo al modello di continuare un ragionamento profondo dopo aver ricevuto i risultati delle chiamate agli strumenti senza richiedere parametri aggiuntivi.
1.5 Esempio Completo
I seguenti due esempi dimostrano il processo completo di chiamata agli strumenti a più turni + pensiero intercalato: richiesta dell'utente → il modello pensa e chiama uno strumento → inietta i risultati dello strumento (preservando reasoning_details) → il modello pensiero intercalato fornisce la risposta finale.
Non in streaming · Pensiero Intercalato
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-***"),
)
# ── Definizione dello strumento ───────────────────────────────────────────
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Ottieni il meteo attuale per una località",
"parameters": {
"type": "object",
"properties": {"location": {"type": "string", "description": "Nome della città"}},
"required": ["location"]
}
}
}]
# ── Esecuzione simulata dello strumento ─────────────────────────────────────
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 "{}"
# ── Ciclo di conversazione a più turni ─────────────────────────────
messages = [
{"role": "user", "content": "Che tempo fa a Boston? Poi consiglia cosa indossare."}
]
turn = 0
while True:
turn += 1
print(f"\n── Turno {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
# Stampa il processo di pensiero
if msg.reasoning_content:
label = "Pensiero Intercalato" if turn > 1 else "Pensiero"
print(f"[{label}] {msg.reasoning_content}")
# Stampa il contenuto della risposta
if msg.content:
print(f"[Risposta] {msg.content}")
# Stampa le chiamate agli strumenti
if msg.tool_calls:
for tc in msg.tool_calls:
print(f"[Chiamata Strumento: {tc.function.name}] {tc.function.arguments}")
# Costruisci il messaggio dell'assistente, preserva reasoning_details (critico!)
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 # restituisci non modificato
messages.append(assistant_msg)
# Nessuna tool_calls significa che la conversazione è finita
if not msg.tool_calls:
break
# Esegui strumenti e aggiungi risultati ai messaggi
for tc in msg.tool_calls:
args = json.loads(tc.function.arguments)
result = execute_tool(tc.function.name, args)
print(f"[Risultato Strumento: {tc.function.name}] {result}")
messages.append({"role": "tool", "tool_call_id": tc.id, "content": result})
Streaming · Pensiero Intercalato
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-***"),
)
# ── Definizione dello strumento & esecuzione simulata ─────────────────────────
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Ottieni il meteo attuale per una località",
"parameters": {
"type": "object",
"properties": {"location": {"type": "string", "description": "Nome della città"}},
"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 "{}"
# ── Collettore di risposta in streaming ────────────────────────────────
def stream_and_collect(turn: int, **kwargs):
"""Stream di risposta, stampa pensiero/contenuto in tempo reale, accumula reasoning_details/tool_calls."""
rd = {} # reasoning_details accumulati
content = "" # testo di risposta accumulato
tc_map = {} # tool_calls accumulati (per indice)
cur = "none" # sezione di output corrente: 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
# ── Gestisci il pensiero ──
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
# Stampa i blocchi di pensiero in tempo reale
thinking_chunk = rd_delta.get("thinking", "")
if thinking_chunk:
if cur != "thinking":
cur = "thinking"
label = "Pensiero Intercalato" if turn > 1 else "Pensiero"
sys.stdout.write(f"\n[{label}] ")
sys.stdout.write(thinking_chunk)
sys.stdout.flush()
# ── Gestisci il contenuto ──
if delta.content:
if cur != "content":
if cur == "thinking":
sys.stdout.write("\n")
cur = "content"
sys.stdout.write("\n[Risposta] ")
sys.stdout.write(delta.content)
sys.stdout.flush()
content += delta.content
# ── Gestisci 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 ""
# Termina la sezione di output corrente
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,
}
# ── Ciclo di conversazione a più turni ─────────────────────────────
messages = [
{"role": "user", "content": "Che tempo fa a Boston? Poi consiglia cosa indossare."}
]
turn = 0
while True:
turn += 1
print(f"\n── Turno {turn} ──")
result = stream_and_collect(
turn,
model="claude-sonnet-4-5",
messages=messages,
tools=tools,
extra_body={"reasoning": {"max_tokens": 2000}},
)
# Stampa le chiamate agli strumenti
if result["tool_calls"]:
for tc in result["tool_calls"]:
print(f"[Chiamata Strumento: {tc['function']['name']}] {tc['function']['arguments']}")
# Costruisci il messaggio dell'assistente, preserva reasoning_details (critico!)
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"] # restituisci non modificato
messages.append(assistant_msg)
# Nessuna tool_calls significa che la conversazione è finita
if not result["tool_calls"]:
break
# Esegui strumenti e aggiungi risultati ai messaggi
for tc in result["tool_calls"]:
args = json.loads(tc["function"]["arguments"])
tool_result = execute_tool(tc["function"]["name"], args)
print(f"[Risultato Strumento: {tc['function']['name']}] {tool_result}")
messages.append({"role": "tool", "tool_call_id": tc["id"], "content": tool_result})
1.6 Regole di Mappatura dell'Intensità del Pensiero
Modalità di Impegno:
- Opus 4.6 / Sonnet 4.6 e superiori: mappa al livello di impegno Pensiero Adattivo nativo di Anthropic.
- Altri modelli: calcolato utilizzando la formula per
budget_tokens:
budget_tokens = max(min(max_tokens × effort_ratio, 128000), 1024)
| impegno | effort_ratio |
|---|---|
| xhigh | 0.95 |
| high | 0.80 |
| medium | 0.50 |
| low | 0.20 |
| minimal | 0.10 |
Mappatura dell'Impegno del Pensiero Adattivo:
| Impegno in Entrata | Opus 4.6 | Sonnet 4.6 |
|---|---|---|
| xhigh | max | high |
| high | high | high |
| medium | medium | medium |
| low | low | low |
| minimal | low | low |
Modalità max_tokens: Assegnato direttamente come budget_tokens di Anthropic.
-think suffisso: Opus/Sonnet 4.6+ utilizza il pensiero adattivo (impegno=medio); altri modelli impostano budget_tokens = min(10240, max_tokens - 1), con un max_tokens predefinito di 4096.
2. Caching dei Prompt
Puoi utilizzare il Caching dei Prompt quando fai richieste al modello Claude tramite l'interfaccia Chat. Impostando i punti di interruzione cache_control nei messaggi, grandi blocchi di testo (come schede di ruolo, dati RAG, capitoli di libri, ecc.) possono essere memorizzati per riutilizzo, consentendo alle richieste successive di colpire direttamente la cache e ridurre significativamente i costi.
Documentazione ufficiale di Claude: Caching dei Prompt
2.1 Costi di Caching
| Operazione | Moltiplicatore di Prezzo (rispetto al prezzo di input originale) |
|---|---|
| Scrittura Cache (TTL di 5 minuti) | 1.25x |
| Scrittura Cache (TTL di 1 ora) | 2x |
| Lettura Cache | 0.1x |
2.2 Modelli Supportati e Lunghezza Minima della Cache
| Modello | Conteggio Minimo di Token nella Cache |
|---|---|
| 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 (deprecato) | 1024 |
| Claude Haiku 4.5 | 4096 |
| Claude Haiku 3.5 (deprecato) / Haiku 3 | 2048 |
Limite di Quantità dei Punti di Interruzione: Un massimo di 4 cache_control punti di interruzione per richiesta.2.3 TTL della Cache
| TTL | Sintassi | Scenari Applicabili |
|---|---|---|
| 5 minuti (predefinito) | "cache_control": {"type": "ephemeral"} |
Sessioni brevi, richieste di routine |
| 1 ora | "cache_control": {"type": "ephemeral", "ttl": "1h"} |
Sessioni lunghe, per evitare scritture ripetute nella cache |
I costi di scrittura per TTL di 1 ora sono più elevati, ma possono risparmiare spese totali riducendo le scritture ripetute in sessioni lunghe. Tutti i modelli da Claude 4.5 in poi di tutti i fornitori (inclusi Anthropic, Amazon Bedrock, Google Vertex AI) supportano TTL di 1 ora.
2.4 Utilizzo
Puoi impostare i punti di interruzione della cache utilizzando il campo cache_control in system, user (inclusi immagini) e tools. I seguenti esempi mostrano solo la struttura chiave, omettendo grandi blocchi di testo.
Caching del Messaggio di Sistema (TTL predefinito di 5 minuti):
{
"model": "claude-opus-4-5",
"messages": [
{
"role": "system",
"content": [
{"type": "text", "text": "Sei un assistente AI"},
{
"type": "text",
"text": "(lungo contesto)",
"cache_control": {"type": "ephemeral"}
}
]
},
{
"role": "user",
"content": [{"type": "text", "text": "Ciao"}]
}
]
}
Caching del Messaggio dell'Utente (TTL di 1 ora):
{
"model": "claude-opus-4-5",
"messages": [
{
"role": "system",
"content": [{"type": "text", "text": "Sei un assistente AI"}]
},
{
"role": "user",
"content": [
{
"type": "text",
"text": "(lungo contesto)",
"cache_control": {"type": "ephemeral", "ttl": "1h"}
},
{"type": "text", "text": "Ciao"}
]
}
]
}
Caching del Messaggio Immagine:
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {"detail": "auto", "url": "data:image/jpeg;base64,/9j/4AAQ..."},
"cache_control": {"type": "ephemeral"}
},
{"type": "text", "text": "Cos'è questo?"}
]
}
Caching della Definizione dello Strumento:
cache_control è posizionato a livello superiore dell'oggetto strumento (insieme a type e function):
{
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Ottieni il meteo attuale per una località",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
},
"cache_control": {"type": "ephemeral", "ttl": "1h"}
}]
}
2.5 Visualizzazione dello Stato della Cache
Il campo usage della risposta restituirà claude_cache_tokens_details, registrando informazioni dettagliate sulla cache:
Prima Richiesta (Creazione della Cache):
{
"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
}
}
}
Richieste Successive (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
}
}
}
| Campo | Significato |
|---|---|
cache_creation_input_tokens |
Numero di token scritti nella cache in questa richiesta |
cache_read_input_tokens |
Numero di token letti dalla cache in questa richiesta |
cache_write_5_minutes_input_tokens |
Numero di token scritti nella cache TTL di 5 minuti |
cache_write_1_hour_input_tokens |
Numero di token scritti nella cache TTL di 1 ora |
prompt_tokens_details.cached_tokens |
Numero di token memorizzati nella cache quando la cache viene colpita, compatibile con il formato OpenAI |
3. Intestazione della Richiesta per anthropic-beta
Puoi abilitare le funzionalità beta del modello Claude tramite l'intestazione HTTP anthropic-beta, che AIHubMix passerà all'API di Anthropic.
Utilizzo
Aggiungi anthropic-beta all'intestazione della richiesta, con il valore che corrisponde all'identificatore della funzionalità beta:
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": "Sei un assistente AI"},
{
"type": "text",
"text": "(lungo contesto)",
"cache_control": {"type": "ephemeral"}
}
]
},
{"role": "user", "content": [{"type": "text", "text": "ciao"}]}
]
}'
Per identificatori beta specifici disponibili, fare riferimento alla Documentazione API di Anthropic.
Ultimo aggiornamento: 2026-06-01