カスタムモデル
~/.pi/agent/models.json 経由でカスタムプロバイダーとモデル(Ollama、vLLM、LM Studio、プロキシ)を追加します。
ローカルモデル(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 は無視するため任意の値で構いません。
一部の OpenAI 互換サーバーは、推論対応モデル用の developer ロールを理解しません。そのようなプロバイダーでは compat.supportsDeveloperRole を false に設定し、pi がシステムプロンプトを system メッセージとして送信するようにします。サーバーが reasoning_effort もサポートしない場合は、compat.supportsReasoningEffort も false に設定してください。
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 を開くたびにファイルが再読み込みされます。セッション中に編集でき、再起動は不要です。
Google AI Studio の例
Section titled “Google AI Studio の例”baseUrl 付きの google-generative-ai を使用して、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 は必須です。
サポートされる API
Section titled “サポートされる API”| API | 説明 |
|---|---|
openai-completions | OpenAI Chat Completions(最も互換性が高い) |
openai-responses | OpenAI Responses API |
anthropic-messages | Anthropic Messages API |
google-generative-ai | Google Generative AI |
api はプロバイダーレベル(すべてのモデルのデフォルト)またはモデルレベル(モデルごとに上書き)で設定します。
プロバイダー設定
Section titled “プロバイダー設定”| フィールド | 説明 |
|---|---|
baseUrl | API エンドポイント URL |
api | API タイプ(上記参照) |
apiKey | API キー(下記の値解決を参照) |
headers | カスタムヘッダー(下記の値解決を参照) |
authHeader | true に設定すると Authorization: Bearer <apiKey> を自動追加 |
models | モデル設定の配列 |
modelOverrides | このプロバイダーの組み込みモデルに対するモデルごとの上書き |
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を使用してください。環境変数が存在しない場合、値は未解決のままになります。 - エスケープ:
"$$"はリテラルの"$"を出力;"$!"はコマンド実行をトリガーせずリテラルの"!"を出力"apiKey": "$$literal-dollar-prefix""apiKey": "$!literal-bang-prefix" - リテラル値: そのまま使用。
MY_API_KEYのようなプレーンな大文字文字列はリテラルです。環境変数には$MY_API_KEYを使用してください。"apiKey": "sk-..."
models.json では、shell コマンドはリクエスト時に解決されます。pi は任意のコマンドに対して組み込み TTL、古い値の再利用、またはリカバリロジックを意図的に適用しません。コマンドごとに異なるキャッシュと失敗戦略が必要であり、pi は適切なものを推測できません。
コマンドが遅い、コストが高い、レート制限がある、または一時的な失敗時に以前の値を使い続ける必要がある場合は、必要なキャッシュまたは TTL 動作を実装する独自のスクリプトまたはコマンドでラップしてください。
/model の可用性チェックは設定された auth の存在を使用し、shell コマンドは実行しません。
カスタムヘッダー
Section titled “カスタムヘッダー”{ "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 | 最大出力トークン数 |
cost | いいえ | すべてゼロ | {"input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0}(100万トークンあたり) |
compat | いいえ | プロバイダーの compat | プロバイダー互換性の上書き。両方設定されている場合、プロバイダーレベルの compat とマージ。 |
現在の動作:
/model、--list-models、インタラクティブフッターはモデルidでエントリを表示。- 設定された
nameはモデルマッチングと二次モデル詳細テキストに使用。フッター/ステータスバーのモデル id は置き換えません。
思考レベルマップ
Section titled “思考レベルマップ”モデルに thinkingLevelMap を使用して、モデル固有の思考制御を記述します。キーは pi の思考レベル:off、minimal、low、medium、high、xhigh。
値は三状態:
| 値 | 意味 |
|---|---|
| 省略 | レベルはサポートされ、プロバイダーのデフォルトマッピングを使用 |
| string | レベルはサポートされ、この値がプロバイダーに送信される |
null | レベルはサポートされず、非表示/スキップ/クランプされる |
off、high、max 推論のみをサポートするモデルの例:
{ "id": "deepseek-v4-pro", "reasoning": true, "thinkingLevelMap": { "minimal": null, "low": null, "medium": null, "high": "high", "xhigh": "max" }}思考を無効にできないモデルの例:
{ "id": "always-thinking-model", "reasoning": true, "thinkingLevelMap": { "off": null }}移行:compat.reasoningEffortMap を使用していた古い設定は、そのマッピングをモデルレベルの thinkingLevelMap に移行してください。UI に表示すべきでないレベルには null を使用します。
組み込みプロバイダーの上書き
Section titled “組み込みプロバイダーの上書き”モデルを再定義せずに、組み込みプロバイダーをプロキシ経由でルーティング:
{ "providers": { "anthropic": { "baseUrl": "https://my-proxy.example.com/v1" } }}すべての組み込み Anthropic モデルは引き続き利用可能。既存の OAuth または API キー auth も引き続き機能します。
カスタムモデルを組み込みプロバイダーにマージするには、models 配列を含めます:
{ "providers": { "anthropic": { "baseUrl": "https://my-proxy.example.com/v1", "apiKey": "$ANTHROPIC_API_KEY", "api": "anthropic-messages", "models": [...] } }}マージの意味:
- 組み込みモデルは保持される。
- カスタムモデルはプロバイダー内で
idごとに upsert される。 - カスタムモデルの
idが組み込みモデルのidと一致する場合、カスタムモデルがその組み込みモデルを置き換える。 - カスタムモデルの
idが新規の場合、組み込みモデルと並んで追加される。
モデルごとの上書き
Section titled “モデルごとの上書き”modelOverrides を使用して、プロバイダーの完全なモデルリストを置き換えずに特定の組み込みモデルをカスタマイズします。
{ "providers": { "openrouter": { "modelOverrides": { "anthropic/claude-sonnet-4": { "name": "Claude Sonnet 4 (Bedrock Route)", "compat": { "openRouterRouting": { "only": ["amazon-bedrock"] } } } } } }}modelOverrides はモデルごとに次のフィールドをサポート:name、reasoning、input、cost(部分)、contextWindow、maxTokens、headers、compat。
動作メモ:
modelOverridesは組み込みプロバイダーモデルに適用される。- 不明なモデル ID は無視される。
- プロバイダーレベルの
baseUrl/headersとmodelOverridesを組み合わせ可能。 nameの上書きはモデルマッチングと二次詳細テキストのみ変更。フッターとプライマリモデルリストは引き続きモデルidを表示。- プロバイダーに
modelsも定義されている場合、カスタムモデルは組み込み上書きの後にマージされる。同じidのカスタムモデルは上書きされた組み込みモデルエントリを置き換える。
Anthropic Messages 互換性
Section titled “Anthropic Messages 互換性”api: "anthropic-messages" を使用するプロバイダーまたはプロキシでは、compat を使用して Anthropic 固有のリクエスト互換性を制御します。
デフォルトでは pi はツールごとに eager_input_streaming: true を送信します。プロキシまたは Anthropic 互換バックエンドがそのフィールドを拒否する場合、supportsEagerToolInputStreaming を false に設定してください。Pi は tools[].eager_input_streaming を省略し、ツール有効リクエストではレガシーの fine-grained-tool-streaming-2025-05-14 beta ヘッダーを送信します。
一部の Anthropic モデルは、レガシーの予算ベース思考ペイロードではなく、適応的思考(thinking.type: "adaptive" および output_config.effort)を必要とします。組み込みモデルはこれを自動設定します。それらのモデルにルーティングするカスタムプロバイダーまたはエイリアスでは、forceAdaptiveThinking を true に設定してください。
一部の Anthropic 互換プロバイダーは空の署名付き思考ブロックを出力し、リプレイ時にもそれらを期待します。それらのプロバイダーにのみ allowEmptySignature を true に設定してください。本物の Anthropic は空の思考署名を拒否します。
{ "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 | プロバイダーがツール定義上の Anthropic 形式 cache_control マーカーを受け入れるか。デフォルト:true。 |
forceAdaptiveThinking | このモデルに適応的思考(thinking.type: "adaptive" および output_config.effort)を送信するか。組み込み適応モデルは自動設定。デフォルト:false。 |
allowEmptySignature | 思考をテキストに変換する代わりに、空の思考署名を signature: "" としてリプレイするか。デフォルト:false。 |
OpenAI 互換性
Section titled “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) |
maxTokensField | max_completion_tokens または max_tokens を使用 |
requiresToolResultName | ツール結果メッセージに name を含める |
requiresAssistantAfterToolResult | ツール結果後の user メッセージの前に assistant メッセージを挿入 |
requiresThinkingAsText | 思考ブロックをプレーンテキストに変換 |
requiresReasoningContentOnAssistantMessages | 推論有効時、リプレイされたすべての assistant メッセージに空の reasoning_content を含める |
thinkingFormat | reasoning_effort、openrouter、deepseek、together、zai、qwen、または qwen-chat-template 思考パラメータを使用 |
cacheControlFormat | システムプロンプト、最後のツール定義、最後の user/assistant テキストコンテンツに Anthropic 形式の cache_control マーカーを使用。現在 anthropic のみサポート。 |
supportsStrictMode | ツール定義に strict フィールドを含める |
supportsLongCacheRetention | キャッシュ保持が long のとき、プロバイダーが長キャッシュ保持を受け入れるか:OpenAI プロンプトキャッシュの prompt_cache_retention: "24h"、または cacheControlFormat が anthropic の場合の cache_control.ttl: "1h"。デフォルト:true。 |
openRouterRouting | OpenRouter プロバイダールーティング設定。このオブジェクトは OpenRouter API リクエスト の provider フィールドにそのまま送信される。 |
vercelGatewayRouting | プロバイダー選択用の Vercel AI Gateway ルーティング設定(only、order) |
openrouter は reasoning: { effort } を使用。together は reasoning: { enabled } を使用し、supportsReasoningEffort が有効な場合は reasoning_effort も使用。qwen はトップレベルの enable_thinking を使用。chat_template_kwargs.enable_thinking を必要とするローカル Qwen 互換サーバーには qwen-chat-template を使用。
cacheControlFormat: "anthropic" は、テキストコンテンツとツール定義上の cache_control マーカーを通じて Anthropic 形式のプロンプトキャッシュを公開する OpenAI 互換プロバイダー向けです。
例:
{ "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 Gateway の例:
{ "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"] } } } ] } }}