Skip to content

Server API e tool calling: integra ds4 con qualsiasi agente

Uno degli aspetti più potenti di ds4 è il server API. Non devi usare solo il CLI o l’agente nativo: puoi esporre DeepSeek V4 come servizio compatibile con gli standard del settore, in modo da collegarci qualsiasi agente o applicazione che parli OpenAI, Anthropic o Responses API.

Il binario ds4-server viene compilato insieme a ds4. Per avviarlo con una configurazione di base:

Terminal window
./ds4-server --ctx 100000 --kv-disk-dir /tmp/ds4-kv --kv-disk-space-mb 8192

Parametri fondamentali:

ParametroEsempioSpiegazione
--ctx100000Dimensione massima del contesto (in token)
--kv-disk-dir/tmp/ds4-kvDirectory per la cache KV su disco (capitolo 6)
--kv-disk-space-mb8192Spazio massimo per la cache (8 GB)
--host0.0.0.0Ascolta su tutte le interfacce (default: 127.0.0.1)
--port8000Porta (default: 8000)
--corsAbilita header CORS per richieste da browser (non espone su LAN; usa anche --host 0.0.0.0)
--power50Riduce l’uso della GPU (50% della potenza)

Una volta avviato, il server risponde su http://localhost:8000 (o l’IP/porta configurata).

ds4-server implementa quattro famiglie di API:

Restituisce la lista dei modelli disponibili caricati dal server. Utile per verificare che il server sia vivo e quale modello è attivo.

Terminal window
curl http://localhost:8000/v1/models

2. OpenAI Chat Completions (POST /v1/chat/completions)

Section titled “2. OpenAI Chat Completions (POST /v1/chat/completions)”

L’endpoint più comune, usato da OpenCode, Pi e molti altri.

Terminal window
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-flash",
"messages": [{"role": "user", "content": "Ciao, chi sei?"}],
"stream": true
}'

Campi supportati:

  • messages, max_tokens / max_completion_tokens
  • temperature, top_p, top_k, min_p, seed
  • stream, stream_options.include_usage
  • tools, tool_choice

3. OpenAI Responses API (POST /v1/responses)

Section titled “3. OpenAI Responses API (POST /v1/responses)”

Endpoint più recente, preferito da Codex CLI. Supporta il formato “reasoning” (thinking) nativamente.

Terminal window
curl http://localhost:8000/v1/responses \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-flash",
"input": "Spiega le reti neurali",
"reasoning": {"effort": "high"}
}'

4. Anthropic-compatible (POST /v1/messages)

Section titled “4. Anthropic-compatible (POST /v1/messages)”

Usato da Claude Code e altri client che parlano il formato Anthropic.

Terminal window
curl http://localhost:8000/v1/messages \
-H "Content-Type: application/json" \
-H "x-api-key: dsv4-local" \
-d '{
"model": "deepseek-v4-flash",
"messages": [{"role": "user", "content": "Ciao"}],
"max_tokens": 1000
}'

Nota: l’API key non è verificata (puoi mettere qualsiasi stringa), ma deve essere presente. Il server non implementa autenticazione reale.

Altri endpoint

  • GET /v1/models/deepseek-v4-flash – dettagli del modello Flash
  • POST /v1/completions – completamenti non-chat (compatibilità OpenAI)

Come anticipato nei capitoli 2 e 6, DeepSeek V4 utilizza il formato DSML per le chiamate a tool. Il server traduce automaticamente tra il formato standard OpenAI/Anthropic e DSML.

Flusso tipico con tool calling

  1. Il client invia una richiesta con tools (definizione degli strumenti disponibili).
  2. Il server converte le definizioni in DSML e le inietta nel prompt.
  3. Il modello genera un blocco DSML, ad esempio:
<tool_calls>
<get_weather>
{"city": "Roma"}
  1. Il server parseggia il DSML, lo converte in un oggetto tool call standard (OpenAI o Anthropic) e lo restituisce al client.
  2. Il client esegue il tool e invia il risultato in una nuova richiesta, includendo l’ID della tool call.
  3. Il server cerca l’esatta sequenza DSML che aveva generato per quella tool call (grazie alla mappa tool-id salvata in RAM e su disco) e la re-inietta nel prompt. La KV cache rimane valida.

Perché l’exact replay è fondamentale
Se il server riformattasse il risultato del tool in DSML in modo leggermente diverso (spazi, maiuscole, ordine dei campi), il prompt renderizzato cambierebbe e la KV cache non corrisponderebbe più. Si dovrebbe rifare il prefill da zero, con un forte aumento della latenza.

Con l’exact replay, invece, i byte originali vengono riutilizzati, e la conversazione procede velocemente.

Disabilitare l’exact replay (non raccomandato)
Se per qualsiasi motivo vuoi disabilitare l’exact replay (ad esempio per test), puoi usare:

Terminal window
./ds4-server --disable-exact-dsml-tool-replay

In questo caso, il server cadrà sempre sulla canonicalizzazione (deterministica) del DSML, che è meno efficiente ma ancora funzionante.

Codex CLI utilizza l’endpoint Responses API. Configura il file ~/.codex/config.toml (o la variabile d’ambiente):

[model_providers.ds4]
name = "DS4"
base_url = "http://127.0.0.1:8000/v1"
wire_api = "responses"
stream_idle_timeout_ms = 1000000

Poi esegui:

Terminal window
codex --model deepseek-v4-flash -c model_provider=ds4

Crea uno script ~/bin/claude-ds4:

#!/bin/sh
unset ANTHROPIC_API_KEY
export ANTHROPIC_BASE_URL="http://127.0.0.1:8000"
export ANTHROPIC_AUTH_TOKEN="dsv4-local"
export ANTHROPIC_MODEL="deepseek-v4-flash"
export ANTHROPIC_DEFAULT_SONNET_MODEL="deepseek-v4-flash"
export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1
exec claude "$@"

Poi usa claude-ds4 come comando.

Aggiungi un provider a ~/.pi/agent/models.json:

{
"providers": {
"ds4": {
"name": "ds4.c local",
"baseUrl": "http://127.0.0.1:8000/v1",
"api": "openai-completions",
"apiKey": "dsv4-local",
"compat": {
"supportsStore": false,
"supportsReasoningEffort": true,
"thinkingFormat": "deepseek",
"maxTokensField": "max_tokens"
},
"models": [
{
"id": "deepseek-v4-flash",
"name": "DeepSeek V4 Flash (ds4.c local)",
"reasoning": true,
"contextWindow": 100000,
"maxTokens": 384000
}
]
}
}
}

Poi imposta defaultProvider a ds4 in ~/.pi/agent/settings.json.

Configura ~/.config/opencode/opencode.json:

{
"provider": {
"ds4": {
"name": "ds4.c (local)",
"npm": "@ai-sdk/openai-compatible",
"options": {
"baseURL": "http://127.0.0.1:8000/v1",
"apiKey": "dsv4-local"
},
"models": {
"deepseek-v4-flash": {
"name": "DeepSeek V4 Flash (ds4.c local)",
"limit": { "context": 100000, "output": 384000 }
}
}
}
},
"agent": {
"ds4": {
"description": "DeepSeek V4 Flash served by local ds4-server",
"model": "ds4/deepseek-v4-flash",
"temperature": 0
}
}
}

Il server adotta le seguenti regole per la modalità di ragionamento:

Richiesta clientModalità effettiva
Nessun parametro di thinking (default)Thinking (normale)
thinking: {"type":"disabled"} o think: falseNon-thinking
reasoning_effort: "max" (OpenAI) + contesto sufficienteThink Max (più profondo)
reasoning_effort: "xhigh"Thinking normale (non Max)

Nota: Think Max viene applicato solo se il contesto è abbastanza grande (secondo la raccomandazione del modello). Altrimenti decade a thinking normale.

I parametri di sampling predefiniti nel server sono:

  • temperature = 1
  • top_p = 1
  • min_p = 0.05

Il min_p è un filtro di probabilità relativa: vengono considerati solo i token la cui probabilità è almeno min_p * max_probability. Funziona bene con temperature basse.

Il server supporta lo streaming sia per il testo che per i tool call.

OpenAI chat streaming:

  • Il reasoning (se presente) viene omesso dallo stream (o gestito separatamente a seconda del client).
  • I tool call vengono inviati come tool_calls[].function.arguments delta, con il primo chunk che contiene id e name, e i successivi i frammenti JSON.
  • Al termine, viene inviato un chunk finale con finish_reason.

Anthropic streaming:

  • I blocchi di thinking sono inviati come eventi separati.
  • I tool call sono inviati come blocchi tool_use completi (non delta).

Responses streaming:

  • Eventi response.output_text.delta, response.function_call_arguments.delta, e response.completed / response.incomplete.

Il server ha alcune caratteristiche importanti da conoscere:

  • Una sola sessione attiva in memoria: Non possono essere elaborate richieste concorrenti su conversazioni diverse. Se arriva una seconda richiesta mentre la prima è in corso, la seconda aspetta in coda.
  • Cache KV su disco (capitolo 6) mitiga questo limite: quando una richiesta con un prompt diverso sostituisce la sessione in memoria, la vecchia viene salvata su disco. Una successiva richiesta con lo stesso prompt la ripristinerà velocemente.
  • Prefill e generazione serializzati: Il server non esegue batching di richieste indipendenti. Ogni richiesta viene processata una alla volta.
  • Per applicazioni con molti utenti concorrenti, è meglio eseguire più istanze del server dietro un load balancer (ciascuna con il proprio modello caricato in memoria).
Terminal window
curl -N http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-flash",
"messages": [{"role": "user", "content": "Spiega il teorema di Pitagora"}],
"stream": true
}'

Esempio 2: Tool calling (definizione di una funzione)

Section titled “Esempio 2: Tool calling (definizione di una funzione)”
Terminal window
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-flash",
"messages": [{"role": "user", "content": "Che tempo fa a Roma?"}],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Ottieni il meteo di una città",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"}
},
"required": ["city"]
}
}
}],
"tool_choice": "auto"
}'

Il server risponderà con un oggetto tool call (non con testo normale). Il client dovrà eseguire la funzione e rinviare il risultato in un nuovo turno di conversazione.

  • Nessuna autenticazione: Chiunque possa raggiungere il server (anche via rete) può usarlo. Usa firewall o reverse proxy con autenticazione se necessario.
  • Solo una sessione alla volta: Come detto, non è un server per uso multi-utente pesante.
  • Tool call annidati non supportati: DeepSeek V4 non genera tool call dentro thinking o dentro altre tool call. Il server gestisce solo il caso piatto.
  • Il modello potrebbe non chiamare i tool: Dipende dal prompt e dalle definizioni. A volte il modello ignora i tool e risponde direttamente.

ds4-server è il ponte tra ds4 e l’ecosistema degli agenti di coding. Con la compatibilità OpenAI, Anthropic e Responses, puoi collegare praticamente qualsiasi cliente esistente. La cache KV su disco e l’exact replay dei tool call rendono l’esperienza fluida e veloce, nonostante la singola sessione attiva.

Consiglio pratico: Inizia con --ctx 100000 e --kv-disk-dir. La cache su disco migliora enormemente le prestazioni per conversazioni ripetute. Se hai problemi di memoria, riduci --ctx o usa --kv-disk-space-mb più basso.

💡 Verificare che il server sia vivo
Prima di configurare un agente, testa l’endpoint /v1/models con curl http://localhost:8000/v1/models. Dovresti ricevere un JSON con i dettagli del modello caricato.

⚠️ L’API key non è verificata
Per compatibilità, il server accetta qualsiasi stringa come API key (es. dsv4-local). Non fare affidamento su questo per la sicurezza: usa un reverse proxy con autenticazione se esponi il server su rete non fidata.