コンテンツにスキップ

カスタムモデル

~/.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.supportsDeveloperRolefalse に設定し、pi がシステムプロンプトを system メッセージとして送信するようにします。サーバーが reasoning_effort もサポートしない場合は、compat.supportsReasoningEffortfalse に設定してください。

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 を開くたびにファイルが再読み込みされます。セッション中に編集でき、再起動は不要です。

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説明
openai-completionsOpenAI Chat Completions(最も互換性が高い)
openai-responsesOpenAI Responses API
anthropic-messagesAnthropic Messages API
google-generative-aiGoogle Generative AI

api はプロバイダーレベル(すべてのモデルのデフォルト)またはモデルレベル(モデルごとに上書き)で設定します。

フィールド説明
baseUrlAPI エンドポイント URL
apiAPI タイプ(上記参照)
apiKeyAPI キー(下記の値解決を参照)
headersカスタムヘッダー(下記の値解決を参照)
authHeadertrue に設定すると Authorization: Bearer <apiKey> を自動追加
modelsモデル設定の配列
modelOverridesこのプロバイダーの組み込みモデルに対するモデルごとの上書き

apiKeyheaders フィールドは、コマンド実行、環境変数補間、リテラルをサポートします:

  • 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 コマンドは実行しません。

{
"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 は置き換えません。

モデルに thinkingLevelMap を使用して、モデル固有の思考制御を記述します。キーは pi の思考レベル:offminimallowmediumhighxhigh

値は三状態:

意味
省略レベルはサポートされ、プロバイダーのデフォルトマッピングを使用
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 が新規の場合、組み込みモデルと並んで追加される。

modelOverrides を使用して、プロバイダーの完全なモデルリストを置き換えずに特定の組み込みモデルをカスタマイズします。

{
"providers": {
"openrouter": {
"modelOverrides": {
"anthropic/claude-sonnet-4": {
"name": "Claude Sonnet 4 (Bedrock Route)",
"compat": {
"openRouterRouting": {
"only": ["amazon-bedrock"]
}
}
}
}
}
}
}

modelOverrides はモデルごとに次のフィールドをサポート:namereasoninginputcost(部分)、contextWindowmaxTokensheaderscompat

動作メモ:

  • modelOverrides は組み込みプロバイダーモデルに適用される。
  • 不明なモデル ID は無視される。
  • プロバイダーレベルの baseUrl/headersmodelOverrides を組み合わせ可能。
  • name の上書きはモデルマッチングと二次詳細テキストのみ変更。フッターとプライマリモデルリストは引き続きモデル id を表示。
  • プロバイダーに models も定義されている場合、カスタムモデルは組み込み上書きの後にマージされる。同じ id のカスタムモデルは上書きされた組み込みモデルエントリを置き換える。

api: "anthropic-messages" を使用するプロバイダーまたはプロキシでは、compat を使用して Anthropic 固有のリクエスト互換性を制御します。

デフォルトでは pi はツールごとに eager_input_streaming: true を送信します。プロキシまたは Anthropic 互換バックエンドがそのフィールドを拒否する場合、supportsEagerToolInputStreamingfalse に設定してください。Pi は tools[].eager_input_streaming を省略し、ツール有効リクエストではレガシーの fine-grained-tool-streaming-2025-05-14 beta ヘッダーを送信します。

一部の Anthropic モデルは、レガシーの予算ベース思考ペイロードではなく、適応的思考(thinking.type: "adaptive" および output_config.effort)を必要とします。組み込みモデルはこれを自動設定します。それらのモデルにルーティングするカスタムプロバイダーまたはエイリアスでは、forceAdaptiveThinkingtrue に設定してください。

一部の Anthropic 互換プロバイダーは空の署名付き思考ブロックを出力し、リプレイ時にもそれらを期待します。それらのプロバイダーにのみ allowEmptySignaturetrue に設定してください。本物の 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 を受け入れるか。デフォルト:truefalse に設定するとそのフィールドを省略し、ツール有効リクエストでレガシーの細粒度ツールストリーミング 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 互換性を持つプロバイダーでは、compat フィールドを使用します。

  • プロバイダーレベルの compat はそのプロバイダー下のすべてのモデルにデフォルトを適用。
  • モデルレベルの compat はそのモデルのプロバイダーレベル値を上書き。
{
"providers": {
"local-llm": {
"baseUrl": "http://localhost:8080/v1",
"api": "openai-completions",
"compat": {
"supportsUsageInStreaming": false,
"maxTokensField": "max_tokens"
},
"models": [...]
}
}
}
フィールド説明
supportsStoreプロバイダーが store フィールドをサポート
supportsDeveloperRoledevelopersystem ロールのどちらを使用するか
supportsReasoningEffortreasoning_effort パラメータのサポート
supportsUsageInStreamingstream_options: { include_usage: true } をサポート(デフォルト:true
maxTokensFieldmax_completion_tokens または max_tokens を使用
requiresToolResultNameツール結果メッセージに name を含める
requiresAssistantAfterToolResultツール結果後の user メッセージの前に assistant メッセージを挿入
requiresThinkingAsText思考ブロックをプレーンテキストに変換
requiresReasoningContentOnAssistantMessages推論有効時、リプレイされたすべての assistant メッセージに空の reasoning_content を含める
thinkingFormatreasoning_effortopenrouterdeepseektogetherzaiqwen、または qwen-chat-template 思考パラメータを使用
cacheControlFormatシステムプロンプト、最後のツール定義、最後の user/assistant テキストコンテンツに Anthropic 形式の cache_control マーカーを使用。現在 anthropic のみサポート。
supportsStrictModeツール定義に strict フィールドを含める
supportsLongCacheRetentionキャッシュ保持が long のとき、プロバイダーが長キャッシュ保持を受け入れるか:OpenAI プロンプトキャッシュの prompt_cache_retention: "24h"、または cacheControlFormatanthropic の場合の cache_control.ttl: "1h"。デフォルト:true
openRouterRoutingOpenRouter プロバイダールーティング設定。このオブジェクトは OpenRouter API リクエストprovider フィールドにそのまま送信される。
vercelGatewayRoutingプロバイダー選択用の Vercel AI Gateway ルーティング設定(onlyorder

openrouterreasoning: { effort } を使用。togetherreasoning: { 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"]
}
}
}
]
}
}
}