7.9 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).
Credenziali nel backend container
In produzione configurare una sola sorgente generica, THT_MODEL_API_KEY_FILE, come secret file
assoluto e non il valore della chiave. PiProcessManager rilegge e valida il file 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.
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).
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
- L'endpoint è un'API pubblica già nota a Pi? → niente da fare, verifica con
pi --list-models. - È OpenAI-compatible, nessuna logica custom, e deve essere visibile ovunque? →
~/.pi/agent/models.json. - 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
│ ├── reserved-labels.mjs ← utility condivisa (NON auto-caricata; .mjs ignorato)
│ └── gate/ ← modulo usato da tht-gate.js
├── 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 |