Files
ThothII/docs/general/pi-configuration.md
T

10 KiB

Configurazione dei modelli in Pi: built-in, utente, progetto

Pi (il coding agent che orchestra il workflow NL→SQL) può risolvere un provider/model in tre modi diversi. Non sono alternativi: coesistono, e la scelta di quale usare dipende da quanto è standard l'endpoint e da quanto deve essere ampia la visibilità del modello (tutti i progetti vs. un progetto solo).

ThothII operator note: ThothII runs Pi only in Docker Compose. Paths under ~/.pi/agent/ in this document describe Pi's container-side behavior. Operators edit deploy/pi/models.json and deploy/pi/settings.json in the ThothII project root and use the protected host credential file selected by PI_AUTH_FILE; they do not edit files inside the running container.

Credenziali nel backend container

In produzione configurare una sola sorgente generica: il bundle THT_SECRETS_FILE con la voce THT_MODEL_API_KEY (predefinito della distribuzione unificata), oppure THT_MODEL_API_KEY_FILE come secret file assoluto. Non mettere il valore della chiave in .env. PiProcessManager rilegge e valida la sorgente per ogni processo, normalizza il provider selezionato e passa al solo child Pi la variabile nativa appropriata (ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, ZAI_API_KEY, ecc.). Il percorso generico, le chiavi di provider non selezionati e il vecchio PI_PROVIDER_API_KEY vengono rimossi dall'ambiente del child. Provider locali come ollama, lmstudio e aritmolab continuano senza chiave; un provider hosted non mappato o un secret mancante/non sicuro fallisce prima dello spawn con errore sanitizzato.

La sorgente generica supporta soltanto provider con una singola chiave: ant-ling, anthropic, cerebras, deepseek, fireworks, github-copilot, google (anche tramite alias gemini), google-vertex in modalità API key, groq, huggingface, kimi-coding, minimax, minimax-cn, mistral, moonshotai, moonshotai-cn, nvidia, openai, opencode, opencode-go, openrouter, together, vercel-ai-gateway, xai, i quattro provider xiaomi*, zai e zai-coding-cn.

I provider composti amazon-bedrock, azure-openai-responses, cloudflare-workers-ai e cloudflare-ai-gateway non sono rappresentabili da un solo file. La selezione fallisce prima dello spawn (anche durante l'elenco modelli); tutte le credenziali ambientali AWS, Azure e Cloudflare restano comunque rimosse. Servirà una futura configurazione dedicata per provider per supportare questi bundle senza ambiguità.

I tre livelli di provenienza di un modello

1. Built-in (compilato dentro Pi)

Pi viene distribuito con un elenco di modelli già noti (models.generated.js dentro il pacchetto @earendil-works/pi-ai): Anthropic, OpenAI, Google, e anche provider di terze parti con API pubblica ben nota come DeepSeek. Per questi non serve alcuna configurazione: bastano le credenziali (env var o pi auth).

deepseek/deepseek-v4-pro è così: è nella build di Pi perché api.deepseek.com è un'API pubblica documentata, non un endpoint interno.

2. models.json a livello utente (~/.pi/agent/models.json)

Per un endpoint OpenAI-compatible che non è tra i built-in — ma che non richiede nessuna logica di trasporto speciale — basta dichiararlo: baseUrl, apiKey, lista modelli. Questo file esiste solo a livello utente: non c'è un equivalente project-level (un ./.pi/models.json non viene letto).

Nelle installazioni gestite da ThothII il file deve essere interamente dichiarativo. ThothII rifiuta ricorsivamente qualsiasi valore JSON che inizi con !, anche dentro headers, models, modelOverrides, compat, array o campi non ancora conosciuti. Pi 0.80.3 tratterebbe quel prefisso come un comando shell al momento della richiesta; questa forma non è ammessa né dall'elenco gestito dei modelli né dallo smoke isolato. L'errore restituito è fisso e non include comando, percorso o secret.

Per i secret usare un riferimento ambiente come "$ZAI_API_KEY" o "${ZAI_API_KEY}". Il backend può popolare la variabile nativa del solo provider selezionato leggendo THT_MODEL_API_KEY_FILE, oppure dal bundle THT_SECRETS_FILE (THT_MODEL_API_KEY); in alternativa le credenziali possono arrivare dal file protetto montato con PI_AUTH_FILE, omettendo apiKey da models.json. Non esiste una sintassi di riferimento diretto a un secret file dentro models.json: con le sorgenti THT_MODEL_* il file viene letto da ThothII e trasformato nella variabile ambiente del child Pi; PI_AUTH_FILE viene invece montato come archivio credenziali Pi protetto. Per un punto esclamativo letterale iniziale, la sintassi Pi dichiarativa è $!, non !.

Esempio reale in uso su questa macchina — GLM (provider zai):

{
  "providers": {
    "zai": {
      "baseUrl": "https://api.z.ai/api/coding/paas/v4",
      "api": "openai-completions",
      "apiKey": "$ZAI_API_KEY",
      "models": [
        {
          "id": "glm-5.2",
          "name": "GLM-5.2",
          "reasoning": true,
          "contextWindow": 200000,
          "maxTokens": 131072
        }
      ]
    }
  }
}

Essendo a livello utente, GLM è visibile da qualsiasi progetto.

3. Estensione (.pi/extensions/*.js, utente o progetto)

Quando l'endpoint richiede codice — ad esempio conversione di eventi (thinking→text), un streamSimple custom, o comunque logica che un file dichiarativo non può esprimere — serve un'estensione Pi che chiama pi.registerProvider(...). Le estensioni possono vivere sia in ~/.pi/agent/extensions/ (tutti i progetti) sia in <progetto>/.pi/extensions/ (solo quel progetto, se Pi viene lanciato con quella cwd).

Esempio reale — il provider AritmoLab (Qwen), interno all'ospedale, usato solo da ThothII: harness/.pi/extensions/aritmolab-provider.js.

Tabella riassuntiva (stato attuale di questa macchina)

Modello Livello Perché Visibilità
deepseek/deepseek-v4-pro Built-in Pi API pubblica nota, già nella build Tutti i progetti
zai/glm-5.2 ~/.pi/agent/models.json Endpoint OpenAI-compatible custom (z.ai), nessuna logica speciale Tutti i progetti
aritmolab/qwen3.6-35b-a3b Estensione di progetto Endpoint interno ospedaliero + conversione eventi thinking→text custom Solo ThothII (cwd=harness/)

Come scegliere il livello giusto per un nuovo modello

  1. L'endpoint è un'API pubblica già nota a Pi? → niente da fare, verifica con pi --list-models.
  2. È OpenAI-compatible, nessuna logica custom, e deve essere visibile ovunque? → ~/.pi/agent/models.json.
  3. Serve codice custom (auth non standard, conversione eventi, trasporto non-OpenAI) oppure deve restare visibile a un solo progetto? → estensione, in ~/.pi/agent/extensions/ (globale) o <progetto>/.pi/extensions/ (locale).

Ambito utente vs. progetto — riepilogo generale

Oltre ai modelli, Pi carica altre risorse da due alberi paralleli: ~/.pi/agent/ (utente) e <cwd>/.pi/ (progetto, risolto in base alla directory da cui viene lanciato pi).

File/Directory Livello utente Livello progetto Auto-discovery Precedenza
models.json ~/.pi/agent/models.json non supportato no solo utente
settings.json ~/.pi/agent/settings.json ./.pi/settings.json no progetto sovrascrive utente
extensions/ ~/.pi/agent/extensions/ ./.pi/extensions/ sì (.ts/.js) uniti (progetto + utente)
prompts/ ~/.pi/agent/prompts/ ./.pi/prompts/ sì (.md) uniti
themes/ ~/.pi/agent/themes/ ./.pi/themes/ sì (.json) progetto preferito
skills/ ~/.pi/agent/skills/ ./.pi/skills/ sì (.md) uniti

Esempio reale: ThothII

harness/.pi/
├── extensions/
│   ├── aritmolab-provider.js    ← provider LLM solo-progetto
│   ├── tht-gate.js               ← gate human-in-the-loop
│   └── gate/
│       ├── core/                 ← enforcement e utility condivise del gate
│       ├── disambiguation/       ← policy F1/F3
│       └── memory/               ← policy F2/F8
├── settings.json                 ← (opzionale) override delle impostazioni utente
└── themes/
    └── thothii-mono.json         ← tema del progetto

Comportamento rispetto alla cwd

La directory da cui lanci pi determina quale .pi/ di progetto viene trovata:

# Da harness/ — trova harness/.pi/extensions/aritmolab-provider.js
cd /path/to/ThothII/harness
pi --model aritmolab/qwen3.6-35b-a3b "..."

# Dalla radice di ThothII — nessun .pi/ trovato lì o nei genitori, solo config utente
cd /path/to/ThothII
pi --model aritmolab/qwen3.6-35b-a3b "..."  # ❌ Error: model not found

Il backend di ThothII (PiProcessManager, list-models.ts, model-matrix.mjs) lancia sempre pi con cwd: harnessDir, per questo Qwen è visibile in produzione.


Trappola nell'auto-discovery: .mjs viene ignorato

Il pattern di auto-discovery delle estensioni in Pi è /\.(ts|js)$/ — non include .mjs.

.pi/extensions/
├── my-extension.js      ✅ auto-caricata
├── my-extension.ts      ✅ auto-caricata
├── my-extension.mjs     ❌ ignorata silenziosamente (non combacia col pattern)
└── shared-module.mjs    ✅ va bene per moduli helper (deliberatamente non caricato come estensione)

Se serve un modulo condiviso importato da un'estensione, usa .mjs proprio per evitare che venga trattato come estensione a sé.


Verifica

Elenco modelli

pi --list-models

Mostra i built-in + i modelli utente da models.json. Non mostra i provider registrati da estensione (come AritmoLab) — quelli vanno verificati con la cwd giusta.

Verifica che un'estensione sia caricata

cd harness   # o la cwd rilevante per il progetto
pi --mode rpc
# poi: {"type": "get_available_models", "id": "1"}

La risposta RPC include tutti i modelli disponibili, inclusi quelli da estensione.


Troubleshooting

Problema Causa Soluzione
Model "X/Y" not found lanciando da fuori progetto Il modello è registrato da un'estensione locale, non visibile fuori dalla cwd giusta Lancia pi dalla directory di progetto corretta (es. harness/)
Estensione non caricata pur essendo nella cartella giusta File .mjs invece di .js/.ts Rinomina in .js
Impostazioni di progetto non applicate settings.json di progetto ha errori di sintassi, o si sta lanciando pi dalla cwd sbagliata Valida il JSON, controlla la cwd