Pi 官方文档

自定义模型

自定义模型

通过 ~/.pi/agent/models.json 添加自定义 Provider 和模型(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 角色。对于这类 Provider,把 compat.supportsDeveloperRole 设为 false,这样 pi 会改为把系统提示词作为 system message 发送。如果服务端也不支持 reasoning_effort,也把 compat.supportsReasoningEffort 设为 false

你可以在 Provider 级别设置 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 示例

使用带 baseUrlgoogle-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

API说明
openai-completionsOpenAI Chat Completions(兼容性最好)
openai-responsesOpenAI Responses API
anthropic-messagesAnthropic Messages API
google-generative-aiGoogle Generative AI

可以在 Provider 级别设置 api(作为所有模型的默认值),也可以在模型级别设置(按模型覆盖)。

Provider 配置

字段说明
baseUrlAPI 端点 URL
apiAPI 类型(见上)
apiKeyAPI key(见下面的值解析)
headers自定义请求头(见下面的值解析)
authHeader设为 true 时,自动添加 Authorization: Bearer <apiKey>
models模型配置数组
modelOverrides这个 Provider 上内置模型的按模型覆盖配置

值解析

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 的可用性检查只会使用已配置的认证信息,不会执行 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)
nameid人类可读的模型名称。用于匹配(--model 模式),并作为次要模型详情文本显示。
apiprovider 的 api为这个模型覆盖 Provider 的 API
reasoningfalse支持扩展思考
thinkingLevelMap省略将 pi 的思考等级映射到 Provider 值,并标记不支持的等级(见下文)
input["text"]输入类型:["text"]["text", "image"]
contextWindow128000上下文窗口大小,单位是 token
maxTokens16384最大输出 token 数
cost全为 0{\"input\": 0, \"output\": 0, \"cacheRead\": 0, \"cacheWrite\": 0}(按每百万 token 计)
compatprovider 的 compatProvider 兼容性覆盖配置。两者都设置时,会与 Provider 级别的 compat 合并。

当前行为:

  • /model--list-models 和交互式页脚都会按模型 id 显示条目。
  • 配置的 name 会用于模型匹配和次要模型详情文本。它不会替换页脚/状态栏里的模型 id。

Thinking Level Map

使用 thinkingLevelMap 在模型上描述模型特定的 thinking 控制。键是 pi thinking levels:offminimallowmediumhighxhigh

取值是三态:

取值含义
省略该级别受支持,并使用 Provider(模型提供方)的默认映射
字符串该级别受支持,并将这个值发送给 Provider(模型提供方)
null该级别不受支持,会被隐藏、跳过或裁掉

仅支持 off、high 和 max 推理的模型示例:

{
  "id": "deepseek-v4-pro",
  "reasoning": true,
  "thinkingLevelMap": {
    "minimal": null,
    "low": null,
    "medium": null,
    "high": "high",
    "xhigh": "max"
  }
}

对于无法关闭 thinking 的模型,示例:

{
  "id": "always-thinking-model",
  "reasoning": true,
  "thinkingLevelMap": {
    "off": null
  }
}

迁移:旧配置如果使用了 compat.reasoningEffortMap,应把这份映射迁移到模型级别的 thinkingLevelMap。对不应出现在 UI 中的级别,使用 null

覆盖内置 Providers

通过代理转发内置 Provider(模型提供方),而不用重新定义模型:

{
  "providers": {
    "anthropic": {
      "baseUrl": "https://my-proxy.example.com/v1"
    }
  }
}

所有内置 Anthropic 模型仍然可用。现有的 OAuth 或 API key 认证继续生效。

如果要把自定义模型合并到内置 Provider(模型提供方)中,请包含 models 数组:

{
  "providers": {
    "anthropic": {
      "baseUrl": "https://my-proxy.example.com/v1",
      "apiKey": "$ANTHROPIC_API_KEY",
      "api": "anthropic-messages",
      "models": [...]
    }
  }
}

合并语义:

  • 保留内置模型。
  • 自定义模型会按 Provider(模型提供方)内的 id 进行更新或插入。
  • 如果自定义模型的 id 与内置模型的 id 相同,自定义模型会替换该内置模型。
  • 如果自定义模型的 id 是新的,它会与内置模型并列添加。

按模型覆盖

使用 modelOverrides 来定制特定的内置模型,而不用替换 Provider(模型提供方)的完整模型列表。

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

modelOverrides 支持每个模型的这些字段:namereasoninginputcost(部分)、contextWindowmaxTokensheaderscompat

行为说明:

  • modelOverrides 会应用到内置 Provider(模型提供方)的模型上。
  • 未知的模型 ID 会被忽略。
  • 可以把 Provider(模型提供方)级别的 baseUrl/headersmodelOverrides 组合使用。
  • 覆盖 name 只会改变模型匹配和次级详情文本;页脚和主模型列表仍然显示模型 id
  • 如果某个 Provider(模型提供方)也定义了 models,自定义模型会在内置覆盖之后合并。相同 id 的自定义模型会替换已经被覆盖的内置模型条目。

Anthropic Messages 兼容性

对于使用 api: "anthropic-messages" 的 Provider(模型提供方)或代理,请用 compat 控制 Anthropic 特定的请求兼容性。

默认情况下,pi 会为每个 tool 发送 eager_input_streaming: true。如果代理或兼容 Anthropic 的后端拒绝这个字段,把 supportsEagerToolInputStreaming 设为 false。这样,Pi 会省略 tools[].eager_input_streaming,并在启用 tool 的请求中改发旧版 fine-grained-tool-streaming-2025-05-14 beta header。

有些 Anthropic 模型需要自适应 thinking(thinking.type: "adaptive" 加上 output_config.effort),而不是旧的基于 budget 的 thinking payload。内置模型会自动设置这一点。对于路由到这些模型的自定义 Provider(模型提供方)或别名,请将 forceAdaptiveThinking 设为 true

有些兼容 Anthropic 的 Provider(模型提供方)会输出带空签名的 thinking block,但在回放时仍然期望保留这些签名。只有这些 Provider(模型提供方)才把 allowEmptySignature 设为 true;真正的 Anthropic 会拒绝空的 thinking 签名。

{
  "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"]
        }
      ]
    }
  }
}
字段说明
supportsEagerToolInputStreamingProvider(模型提供方)是否接受按 tool 设置的 eager_input_streaming。默认:true。设为 false 后,会省略这个字段,并在启用 tool 的请求中使用旧版 fine-grained tool streaming beta header。
supportsLongCacheRetentionProvider(模型提供方)是否接受 Anthropic 的长缓存保留(cache_control.ttl: "1h"),前提是 cache retention 为 long。默认:true
sendSessionAffinityHeaders在启用缓存时,是否根据 session id 发送 x-session-affinity。默认:针对已知 Provider(模型提供方)自动检测。
supportsCacheControlOnToolsProvider(模型提供方)是否接受 Anthropic 风格的 cache_control 标记用于 tool 定义。默认:true
forceAdaptiveThinking是否为这个模型发送自适应 thinking(thinking.type: "adaptive" 加上 output_config.effort)。内置的自适应模型会自动设置这一点。默认:false
allowEmptySignature回放空的 thinking 签名时,是否保留为 signature: "",而不是把 thinking 转成文本。默认:false

OpenAI 兼容性

对于具备部分 OpenAI 兼容性的 Provider(模型提供方),请使用 compat 字段。

  • Provider 级别的 compat 会把默认值应用到该 Provider 下的所有模型。
  • 模型级别的 compat 会覆盖该模型的 Provider 级别值。
{
  "providers": {
    "local-llm": {
      "baseUrl": "http://localhost:8080/v1",
      "api": "openai-completions",
      "compat": {
        "supportsUsageInStreaming": false,
        "maxTokensField": "max_tokens"
      },
      "models": [...]
    }
  }
}
字段说明
supportsStoreProvider 支持 store 字段
supportsDeveloperRole使用 developer 还是 system 角色
supportsReasoningEffort支持 reasoning_effort 参数
supportsUsageInStreaming支持 stream_options: { include_usage: true }(默认:true
maxTokensField使用 max_completion_tokens 还是 max_tokens
requiresToolResultName在 tool result 消息中包含 name
requiresAssistantAfterToolResult在 tool results 之后、下一条 user 消息之前插入一条 assistant 消息
requiresThinkingAsText将 thinking blocks 转成纯文本
requiresReasoningContentOnAssistantMessages当启用 reasoning 时,在所有回放的 assistant 消息中包含空的 reasoning_content
thinkingFormat使用 reasoning_effortopenrouterdeepseektogetherzaiqwenchat-templateqwen-chat-template 的 thinking 参数
chatTemplateKwargsthinkingFormat: "chat-template" 时使用的 chat_template_kwargs 值;对于由 pi 控制的 thinking 值,使用 { "$var": "thinking.enabled" }{ "$var": "thinking.effort" }
cacheControlFormat在 system prompt、最后一个 tool 定义以及最后一段 user/assistant 文本内容上使用 Anthropic 风格的 cache_control 标记。目前只支持 anthropic
supportsStrictMode在 tool 定义中包含 strict 字段
supportsLongCacheRetention当 cache retention 为 long 时,Provider(模型提供方)是否接受长缓存保留:OpenAI prompt caching 使用 prompt_cache_retention: "24h"cacheControlFormatanthropic 时使用 cache_control.ttl: "1h"。默认:true
openRouterRoutingOpenRouter Provider(模型提供方)路由偏好。这个对象会原样放入 OpenRouter API requestprovider 字段。
vercelGatewayRouting用于 Provider(模型提供方)选择的 Vercel AI Gateway 路由配置(onlyorder

openrouter 使用 reasoning: { effort }together 使用 reasoning: { enabled },并且在启用 supportsReasoningEffort 时也会使用 reasoning_effortqwen 使用顶层的 enable_thinking。对于需要 chat_template_kwargs.enable_thinkingpreserve_thinking 的本地 Qwen 兼容服务器,请使用 qwen-chat-template。对于需要可配置 chat_template_kwargs 的 vLLM/Hugging Face chat templates,请使用 chat-template,例如 DeepSeek V3.x templates 的 chatTemplateKwargs: { "thinking": { "$var": "thinking.enabled" } }

cacheControlFormat: "anthropic" 适用于那些与 OpenAI 兼容、并通过文本内容和 tool 定义上的 cache_control 标记暴露 Anthropic 风格 prompt caching 的 Provider(模型提供方)。

示例:

{
  "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"]
            }
          }
        }
      ]
    }
  }
}

Pi 官方文档中文整理 · 机器初译,待人工校对

本文基于官方 MIT 文档翻译整理,不代表 pi.dev 官方中文站。同步 commit:8b97e75c,同步时间:2026/6/20

查看官方原文