客製化Models
透過 ~/.pi/agent/models.json 新增自訂提供者和模型(Ollama、vLLM、LM Studio、代理程式)。
目錄
- Minimal Example
- Full Example
- Supported APIs
- Provider Configuration
- Model Configuration
- Overriding Built-in Providers
- Per-model Overrides
- Anthropic Messages Compatibility
- OpenAI Compatibility
最小的例子
對於本機模型(Ollama、LM Studio、vLLM),每個模型僅需要 id:
{
"providers": {
"ollama": {
"baseUrl": "http://localhost:11434/v1",
"api": "openai-completions",
"apiKey": "ollama",
"models": [
{ "id": "llama3.1:8b" },
{ "id": "qwen2.5-coder:7b" }
]
}
}
}apiKey 值是一個佔位符,因為 Ollama 會忽略它。 pi 仍然將模型視為需要驗證才能出現在 /model 中,因此無金鑰本機伺服器應保留一個虛擬值,使用 /login 為該提供者保存金鑰,或在選擇模型時傳遞 --api-key。
有些 OpenAI 相容伺服器不理解用於推理模型的 developer 角色。對於這些提供程序,將 compat.supportsDeveloperRole 設定為 false,以便 pi 將系統提示作為 system 訊息發送。如果伺服器也不支援reasoning_effort,請將compat.supportsReasoningEffort也設定為false。
您可以在提供者層級設定 compat 以套用至所有模型,或在模型層級設定 compat 以覆寫特定模型。這通常適用於 Ollama、vLLM、SGLang 和類似的 OpenAI 相容伺服器。
{
"providers": {
"ollama": {
"baseUrl": "http://localhost:11434/v1",
"api": "openai-completions",
"apiKey": "ollama",
"compat": {
"supportsDeveloperRole": false,
"supportsReasoningEffort": false
},
"models": [
{
"id": "gpt-oss:20b",
"reasoning": true
}
]
}
}
}完整範例
當您需要特定值時覆蓋預設值:
{
"providers": {
"ollama": {
"baseUrl": "http://localhost:11434/v1",
"api": "openai-completions",
"apiKey": "ollama",
"models": [
{
"id": "llama3.1:8b",
"name": "Llama 3.1 8B (Local)",
"reasoning": false,
"input": ["text"],
"contextWindow": 128000,
"maxTokens": 32000,
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 }
}
]
}
}
}每次打開 /model 時,檔案都會重新載入。在會議期間編輯;無需重新啟動。
谷歌AI工作室範例
使用 google-generative-ai 和 baseUrl 從 Google AI Studio 新增模型,包括自訂 Gemma 4 條目:
{
"providers": {
"my-google": {
"baseUrl": "https://generativelanguage.googleapis.com/v1beta",
"api": "google-generative-ai",
"apiKey": "$GEMINI_API_KEY",
"models": [
{
"id": "gemma-4-31b-it",
"name": "Gemma 4 31B",
"input": ["text", "image"],
"contextWindow": 262144,
"reasoning": true
}
]
}
}
}將自訂模型新增至 google-generative-ai API 類型時需要baseUrl。
支持APIs
| API | 描述 |
|---|---|
openai-completions |
OpenAI 聊天完成(最相容) |
openai-responses |
OpenAI 回應 API |
anthropic-messages |
人擇資訊API |
google-generative-ai |
谷歌生成人工智慧 |
在提供程序層級(所有模型的預設值)或模型層級(每個模型覆蓋)設定 api。
提供者配置
| 場地 | 描述 |
|---|---|
baseUrl |
API 端點 URL |
api |
API類型(見上文) |
apiKey |
可選的 API key 配置(請參閱下面的值解析)。當 auth 由 /login/auth.json 或 CLI --api-key 提供時省略。 |
oauth |
動態 OAuth 提供者類型。目前支援"radius";需要網關baseUrl。 |
headers |
自訂標頭(請參閱下面的值解析) |
authHeader |
設定true自動新增Authorization: Bearer <apiKey> |
models |
模型配置數組 |
modelOverrides |
每個模型覆蓋此提供者上的內建或擴展註冊模型 |
對於具有 models 的提供程序,非內建提供者配置需要提供程式或模型層級的 baseUrl 和 api 值。載入檔案不需要apiKey:當透過/login/auth.json、CLI--api-key或提供者apiKey配置驗證時,模型變得可用。如果未配置身份驗證,則模型會加載,但在/model和--list-models中保持不可用。
價值解析
apiKey 和 headers 欄位支援指令執行、環境插值和文字:
- Shell 指令: 開頭的
"!command"將整個值作為指令執行並使用 stdout"apiKey": "!security find-generic-password -ws 'anthropic'" "apiKey": "!op read 'op://vault/item/credential'" - 環境內插:
"$ENV_VAR"或"${ENV_VAR}"使用命名變數的值。插值適用於較大的文字。"apiKey": "$MY_API_KEY" "apiKey": "${KEY_PREFIX}_${KEY_SUFFIX}"$FOO_BAR是變數FOO_BAR;當BAR是文字文字時,使用${FOO}_BAR。缺少環境變數會導致該值無法解析。 - 轉義:
"quot;發出文字"quot;;"$!"發出文字"!"而不觸發指令執行。"apiKey": "$literal-dollar-prefix" "apiKey": "$!literal-bang-prefix" - 字面值: 直接使用。普通大寫字串(例如
MY_API_KEY)是文字;使用$MY_API_KEY作為環境變數。"apiKey": "sk-..."
對於 models.json,shell 命令在請求時解析。 pi 故意不對任意指令套用內建 TTL、過時重複使用或復原邏輯。不同的命令需要不同的快取和失敗策略,並且 pi 無法推斷出正確的策略。
如果您的命令速度慢、成本高、速率受限,或者應該在暫時性故障時繼續使用先前的值,請將其包裝在您自己的腳本或命令中,以實現您想要的快取或 TTL 行為。
/model 可用性檢查使用設定的身份驗證存在並且不執行 shell 命令。
自訂標頭
{
"providers": {
"custom-proxy": {
"baseUrl": "https://proxy.example.com/v1",
"apiKey": "$MY_API_KEY",
"api": "anthropic-messages",
"headers": {
"x-portkey-api-key": "$PORTKEY_API_KEY",
"x-secret": "!op read 'op://vault/item/secret'"
},
"models": [...]
}
}
}型號配置
| 場地 | 必需的 | 預設 | 描述 |
|---|---|---|---|
id |
是的 | — | 型號標識符(傳遞給API) |
name |
不 | id |
人類可讀的模型標籤。用於匹配(--model模式)並顯示為輔助模型詳細資訊文字。 |
api |
不 | 提供者的api |
覆蓋此模型的提供者的 API |
reasoning |
不 | false |
支援擴展思維 |
thinkingLevelMap |
不 | 省略 | 將 pi 思維等級對應到提供者值並標記不支援的等級(見下文) |
input |
不 | ["text"] |
輸入類型:["text"]或["text", "image"] |
contextWindow |
不 | 128000 |
上下文視窗大小(以標記為單位) |
maxTokens |
不 | 16384 |
最大輸出令牌 |
samplingParams |
不 | 省略 | 採樣參數逐字合併到每個請求正文中(見下文) |
cost |
不 | 全為零 | 每百萬代幣費率以及可選的請求範圍輸入定價層 |
compat |
不 | 提供者compat |
提供者相容性覆蓋。兩者都設定時,與提供者等級 compat 合併。 |
成本層提供完整的替代費率集,並在總輸入使用量 (input + cacheRead + cacheWrite) 超過 inputTokensAbove 時應用於完整請求。當多個等級匹配時,閾值最高的獲勝。
{
"cost": {
"input": 5,
"output": 30,
"cacheRead": 0.5,
"cacheWrite": 6.25,
"tiers": [
{
"inputTokensAbove": 272000,
"input": 10,
"output": 45,
"cacheRead": 1,
"cacheWrite": 12.5
}
]
}
}當前行為:
/model、--list-models和互動式頁腳按模型id顯示條目。- 配置的
name用於模型匹配和輔助模型詳細文字。它不會取代頁尾/狀態列模型 ID。
採樣參數
samplingParams 是一個自由格式的對象,在欄位 pi 設定自身之後,逐字合併到模型的每個請求主體中,因此它的鍵獲勝。使用它來發送 pi 不建模的取樣參數 - 包括特定於伺服器的參數,例如 llama.cpp 的 min_p 或 vLLM 的 top_k:
{
"id": "deepseek-v4-flash",
"samplingParams": {
"temperature": 1.0,
"top_p": 0.95,
"top_k": 0,
"min_p": 0.0
}
}僅相容於 OpenAI 的 API 適用(openai-completions、openai-responses、azure-openai-responses);其他API忽略它。鍵會覆蓋 pi 的命名請求字段(例如,這裡的 temperature 鍵擊敗了請求級別的溫度),因此更喜歡將其作為模型採樣事實的單一來源。在 modelOverrides 中,samplingParams 將每個鍵與基本模型的值合併。
思維層次圖
在模型上使用thinkingLevelMap來描述特定於模型的思維控制。關鍵在於 pi 思考層次:off、minimal、low、medium、high、xhigh、max。地圖可能包含漏洞;例如,模型可以公開 high 和 max,而不公開 xhigh。
值是三態的:
| 價值 | 意義 |
|---|---|
| 省略 | 標準級別到high使用提供者的預設映射;不支援擴展 xhigh 和 max 級別 |
| 細繩 | 支援等級並將該值傳送給提供者 |
null |
水平儀不受支撐且隱藏/跳過/夾住 |
僅支援 off、high 和 max 推理的模型範例:
{
"id": "deepseek-v4-pro",
"reasoning": true,
"thinkingLevelMap": {
"minimal": null,
"low": null,
"medium": null,
"high": "high",
"xhigh": null,
"max": "max"
}
}思維不能被禁用的模型範例:
{
"id": "always-thinking-model",
"reasoning": true,
"thinkingLevelMap": {
"off": null
}
}遷移:使用compat.reasoningEffortMap的舊配置應將該映射移動到模型層級thinkingLevelMap。對於不應出現在 UI 中的級別,請使用 null。
覆蓋內建 Providers
透過代理路由內建提供者,無需重新定義模型:
{
"providers": {
"anthropic": {
"baseUrl": "https://my-proxy.example.com/v1"
}
}
}所有內建 Anthropic 型號仍然可用。現有的 OAuth 或 API key 身份驗證繼續有效。
若要將自訂模型合併到內建提供者中,請包含 models 陣列:
{
"providers": {
"anthropic": {
"baseUrl": "https://my-proxy.example.com/v1",
"apiKey": "$ANTHROPIC_API_KEY",
"api": "anthropic-messages",
"models": [...]
}
}
}合併語意:
- 保留內建模型。
- 自訂模型由
id在提供者中更新。 - 如果自訂模型
id與內建模型id匹配,則自訂模型將取代該內建模型。 - 如果自訂模型
id是新的,它將與內建模型一起新增。
每個模型的覆蓋
使用 modelOverrides 自訂內建模型和匹配擴充註冊的模型,而無需替換提供者的完整模型清單。
{
"providers": {
"openrouter": {
"modelOverrides": {
"anthropic/claude-sonnet-4": {
"name": "Claude Sonnet 4 (Bedrock Route)",
"compat": {
"openRouterRouting": {
"only": ["amazon-bedrock"]
}
}
}
}
}
}
}modelOverrides 每個模型支援這些欄位:name、reasoning、thinkingLevelMap、input、cost(部分)、contextWindow、maxTokens、samplingParams(依鍵合併)、headers、compat。
Direct OpenAI GPT-5.6 Sol、Terra 和 Luna 預設為 272000 上下文窗口,因此請求保留在 OpenAI 的短上下文定價層內。要選擇 OpenAI 的 1.05M 上下文窗口,請為您使用的每個模型增加它:
{
"providers": {
"openai": {
"modelOverrides": {
"gpt-5.6-sol": {
"contextWindow": 1050000
}
}
}
}
}覆蓋保留內建定價元資料。總輸入令牌超過 272K 的請求對整個請求使用 GPT-5.6 的長上下文速率。需要時,對 gpt-5.6-terra 或 gpt-5.6-luna 應用相同的覆蓋。
行為注意事項:
modelOverrides適用於內建提供者模型和匹配的擴展註冊提供者模型。- 未知的型號 ID 將被忽略。
- 您可以將提供者等級
baseUrl/headers與modelOverrides結合。 - 覆蓋
name僅更改模型匹配和次要詳細文本;頁腳和主要型號列表繼續顯示型號id。 - 如果也為提供者定義了
models,則自訂模型將在內建覆蓋後合併。具有相同id的自訂模型將取代覆蓋的內建模型條目。
人擇訊息相容性
對於使用api: "anthropic-messages"的提供者或代理,請使用compat來控制特定於人類的請求相容性。
預設 pi 發送每個工具 eager_input_streaming: true。如果代理程式或與 Anthropic 相容的後端拒絕該字段,請將 supportsEagerToolInputStreaming 設為 false。 Pi 將省略 tools[].eager_input_streaming 並為支援工具的請求發送舊版 fine-grained-tool-streaming-2025-05-14 beta 標頭。
有些人擇模型需要適應性思考(thinking.type: "adaptive"加output_config.effort),而不是傳統的預算為基礎的思維有效負荷。內建模型會自動設定此項。對於路由到這些模型的自訂提供者或別名,請將 forceAdaptiveThinking 設定為 true。
一些與人類兼容的提供者發出帶有空簽名的思維塊,並且仍然期望它們重播。僅針對這些提供者將 allowEmptySignature 設定為 true;真正的人擇拒絕空洞的思維簽名。
內建人擇模型在其模型元資料中啟用 supportsStrictTools。當自訂 Anthropic 相容模型的端點接受嚴格的 JSON 模式工具定義時,必須將其設為 true。
{
"providers": {
"anthropic-proxy": {
"baseUrl": "https://proxy.example.com",
"api": "anthropic-messages",
"apiKey": "$ANTHROPIC_PROXY_KEY",
"compat": {
"supportsEagerToolInputStreaming": false,
"supportsLongCacheRetention": true,
"forceAdaptiveThinking": true,
"allowEmptySignature": true
},
"models": [
{
"id": "claude-opus-4-7",
"reasoning": true,
"input": ["text", "image"]
}
]
}
}
}| 場地 | 描述 |
|---|---|
supportsEagerToolInputStreaming |
提供者是否接受每個工具eager_input_streaming。預設值:true。設定為 false 可忽略該字段,並在啟用工具的請求上使用舊版細粒度工具流式傳輸 Beta 標頭。 |
supportsLongCacheRetention |
當快取保留為 long 時,提供者是否接受 Anthropic 長快取保留 (cache_control.ttl: "1h")。預設值:true。 |
sendSessionAffinityHeaders |
啟用快取時是否從會話 ID 傳送x-session-affinity。預設值:自動偵測已知提供者。 |
supportsCacheControlOnTools |
提供者是否接受工具定義上的人類風格 cache_control 標記。預設值:true。 |
forceAdaptiveThinking |
是否為該模型發送自適應思維(thinking.type: "adaptive"加output_config.effort)。內建自適應模型會自動設定此值。預設值:false。 |
allowEmptySignature |
是否將空思維簽名重播為signature: "",而不是將思維轉換為文字。預設值:false。 |
supportsStrictTools |
提供者是否接受嚴格的JSON-模式工具定義。預設值:false;內建的人擇模型在產生的元資料中啟用它。 |
OpenAI 相容性
對於具有部分 OpenAI 相容性的供應商,請使用 compat 欄位。
- 提供者等級
compat將預設值套用至該提供者下的所有模型。 - 模型等級
compat覆寫該模型的提供者等級值。
{
"providers": {
"local-llm": {
"baseUrl": "http://localhost:8080/v1",
"api": "openai-completions",
"compat": {
"supportsUsageInStreaming": false,
"maxTokensField": "max_tokens"
},
"models": [...]
}
}
}| 場地 | 描述 |
|---|---|
supportsStore |
提供者支援store字段 |
supportsDeveloperRole |
使用 developer 與 system 角色 |
supportsReasoningEffort |
支援reasoning_effort參數 |
supportsUsageInStreaming |
支援stream_options: { include_usage: true }(預設:true) |
supportsFinishReason |
流式響應是否包含finish_reason。當 false 時,pi 在流結束時推斷出 stop 或 toolUse。預設值:true。 |
maxTokensField |
使用 max_completion_tokens 或 max_tokens |
requiresToolResultName |
在工具結果訊息中包含 name |
requiresAssistantAfterToolResult |
在工具結果之後的用戶訊息之前插入輔助訊息 |
requiresThinkingAsText |
將思維區塊轉換為純文本 |
requiresReasoningContentOnAssistantMessages |
啟用推理時,在所有重播的助手訊息中包含空 reasoning_content |
thinkingFormat |
使用 reasoning_effort、openrouter、deepseek、together、baseten、zai、qwen、chat-template 或 qwen-chat-template 思維參數 |
chatTemplateKwargs |
chat_template_kwargs thinkingFormat: "chat-template" 值;使用 { "$var": "thinking.enabled" } 或 { "$var": "thinking.effort" } 取得 pi 控制的思維值 |
chatTemplateArgs |
chat_template_args thinkingFormat: "baseten" 值;使用 { "$var": "thinking.enabled" } 或 { "$var": "thinking.effort" } 取得 pi 控制的思維值 |
cacheControlFormat |
在系統提示、最後一個工具定義以及最後一個使用者、助手或工具結果文字內容上使用人類風格的 cache_control 標記。目前僅支援anthropic。 |
sendSessionAffinityHeaders |
對於openai-completions,啟用快取時從會話 ID 傳送會話親和性標頭。預設值:false。 |
sessionAffinityFormat |
對於 openai-completions 和 openai-responses,會話親和性標頭格式:openai 會傳送 session_id/x-client-request-id(completions 也會傳送 x-session-affinity),openai-nosession 會省略包含底線的 session_id 標頭,openrouter 會傳送 x-session-id。不影響 prompt_cache_key 主體參數。預設:自動偵測。 |
supportsStrictMode |
提供者是否接受嚴格的JSON-模式函數工具定義。預設值取決於 API;內建 OpenAI 模型攜帶明確的能力元資料。 |
supportsOpenAIGrammarTools |
相容 OpenAI 的API是否發出自訂 Lark/regex 語法工具。當 false 時,語法約束工具回退到正常功能工具。預設值:false;內建模型目錄支援 OpenAI、OpenAI Codex、Azure OpenAI、GitHub Copilot、opencode 和 Cloudflare AI Gateway 上的 GPT-5+ 模型。 |
deferredToolsMode |
使用特定於提供者的延遲工具序列化。 Kimi 的 OpenAI 相容聊天完成格式目前僅支援 "kimi"。 |
supportsLongCacheRetention |
當快取保留為long時,提供者是否接受長緩存保留:對於OpenAI提示緩存,prompt_cache_retention: "24h",或當cacheControlFormat為anthropic時,cache_control.ttl: "1h"。預設值:true。 |
openRouterRouting |
OpenRouter 供應商的路由首選項。該物件按原樣發送到 OpenRouter API request 的 provider 欄位中。 |
vercelGatewayRouting |
用於選擇供應商的 Vercel AI 閘道路由配置 (only、order) |
openrouter 使用reasoning: { effort }。啟用 supportsReasoningEffort 時,together 使用reasoning: { enabled },也使用reasoning_effort。 qwen 使用頂級enable_thinking。對於需要 chat_template_kwargs.enable_thinking 和 preserve_thinking 的本地 Qwen 相容伺服器,請使用 qwen-chat-template。對於需要可設定 chat_template_kwargs 的 vLLM/Hugging Face 聊天模板,請使用 chat-template,例如對於 DeepSeek V3.x 模板,請使用 chatTemplateKwargs: { "thinking": { "$var": "thinking.enabled" } }。對於透過 chat_template_args 公開切換控制並可選擇支援頂級 reasoning_effort 的提供程序,將 thinkingFormat: "baseten" 與 chatTemplateArgs 結合使用。
cacheControlFormat: "anthropic" 適用於與 OpenAI 相容的提供程序,透過文字內容和工具定義上的 cache_control 標記公開人類風格的提示快取。
例子:
{
"providers": {
"openrouter": {
"baseUrl": "https://openrouter.ai/api/v1",
"apiKey": "$OPENROUTER_API_KEY",
"api": "openai-completions",
"models": [
{
"id": "openrouter/anthropic/claude-3.5-sonnet",
"name": "OpenRouter Claude 3.5 Sonnet",
"compat": {
"openRouterRouting": {
"allow_fallbacks": true,
"require_parameters": false,
"data_collection": "deny",
"zdr": true,
"enforce_distillable_text": false,
"order": ["anthropic", "amazon-bedrock", "google-vertex"],
"only": ["anthropic", "amazon-bedrock"],
"ignore": ["gmicloud", "friendli"],
"quantizations": ["fp16", "bf16"],
"sort": {
"by": "price",
"partition": "model"
},
"max_price": {
"prompt": 10,
"completion": 20
},
"preferred_min_throughput": {
"p50": 100,
"p90": 50
},
"preferred_max_latency": {
"p50": 1,
"p90": 3,
"p99": 5
}
}
}
}
]
}
}
}Vercel AI 閘道範例:
{
"providers": {
"vercel-ai-gateway": {
"baseUrl": "https://ai-gateway.vercel.sh/v1",
"apiKey": "$AI_GATEWAY_API_KEY",
"api": "openai-completions",
"models": [
{
"id": "moonshotai/kimi-k2.5",
"name": "Kimi K2.5 (Fireworks via Vercel)",
"reasoning": true,
"input": ["text", "image"],
"cost": { "input": 0.6, "output": 3, "cacheRead": 0, "cacheWrite": 0 },
"contextWindow": 262144,
"maxTokens": 262144,
"compat": {
"vercelGatewayRouting": {
"only": ["fireworks", "novita"],
"order": ["fireworks", "novita"]
}
}
}
]
}
}
}