Pi 的配置、扩展、平台设置和 API 参考。

自定义模型

通过 ~/.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 会忽略它。pi 仍会把模型视为需要身份验证后才会出现在 /model 中,因此无 API Key 的本地服务器应保留一个虚拟值,使用 /login 为该 Provider 保存 API Key,或者在选择模型时传入 --api-key

一些 OpenAI 兼容服务器不理解推理模型使用的 developer 角色。对于这些 Provider,将 compat.supportsDeveloperRole 设置为 false,以便 pi 将系统提示作为 system 消息发送。如果服务器也不支持 reasoning_effort,也请将 compat.supportsReasoningEffort 设置为 false

可以在 Provider 级别设置 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 时,文件都会重新加载。可以在会话期间编辑;无需重启。

Google AI Studio 示例

使用 google-generative-aibaseUrl 从 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-completions OpenAI 聊天完成(最兼容)
openai-responses OpenAI 回应 API
anthropic-messages Anthropic Messages API
google-generative-ai Google Generative AI

在 Provider 级别(所有模型的默认值)或模型级别(每个模型覆盖)设置 api

Provider 配置

字段 描述
baseUrl API 端点 URL
api API 类型(见上文)
apiKey 可选的 API Key 配置(请参阅下面的值解析)。当 auth 由 /login/auth.json 或 CLI --api-key 提供时可以省略。
oauth 动态 OAuth Provider类型。目前支持 "radius";需要网关 baseUrl
headers 自定义标头(请参阅下面的值解析)
authHeader 设置 true 自动添加 Authorization: Bearer <apiKey>
models 模型配置数组
modelOverrides 每个模型覆盖此 Provider 上的内置或扩展注册模型

对于包含 models 的 Provider,非内置 Provider 配置需要在 Provider 或模型级别提供 baseUrlapi 值。加载文件不需要 apiKey:当通过 /login/auth.json、CLI --api-key 或 Provider apiKey 配置身份验证后,模型才会可用。如果未配置身份验证,模型会被加载,但在 /model--list-models 中仍不可用。

值解析

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。缺少环境变量会导致该值无法解析。
  • 转义: "$" 发出字面量 "
    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 Provider 的 api 覆盖此模型的 Provider API
reasoning false 支持扩展思考
thinkingLevelMap 省略 将 pi 的 thinking level 映射到 Provider 值,并标记不支持的级别(见下文)
input ["text"] 输入类型:["text"]["text", "image"]
contextWindow 128000 上下文窗口大小(以 token 为单位)
maxTokens 16384 最大输出 token 数
samplingParams 省略 采样参数逐字合并到每个请求 body 中(见下文)
cost 全为零 每百万 token 费率以及可选的请求范围输入定价层
compat Provider compat Provider 兼容性覆盖。当两者都设置时,会与 Provider 级别的 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-completionsopenai-responsesazure-openai-responses);其他 API 会忽略它。键会覆盖 pi 自身命名的请求字段(例如这里的 temperature 键会覆盖请求级温度),因此建议将它作为该模型采样参数的唯一来源。在 modelOverrides 中,samplingParams 会按键与基础模型的值合并。

Thinking Level Map

在模型上使用 thinkingLevelMap 描述特定于模型的 thinking 控制。键是 pi thinking level:offminimallowmediumhighxhighmax。映射可以不完整;例如,模型可以暴露 highmax,但不暴露 xhigh

值是三态的:

含义
省略 标准级别到 high 使用 Provider 的默认映射;扩展的 xhighmax 级别不受支持
字符串 该级别受支持,并将该值发送给 Provider
null 该级别不受支持,会被隐藏、跳过或夹紧到其他级别

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

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

thinking 不能被禁用的模型示例:

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

迁移:使用 compat.reasoningEffortMap 的旧配置应将该映射移动到模型级别的 thinkingLevelMap。对于不应出现在 UI 中的级别,请使用 null

覆盖内置 Provider

通过代理路由内置 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": [...]
    }
  }
}

合并语义:

  • 保留内置模型。
  • 自定义模型由 id 在 Provider 中更新。
  • 如果自定义模型 id 与内置模型 id 匹配,则自定义模型将替换该内置模型。
  • 如果自定义模型 id 是新的,它将与内置模型一起添加。

每个模型的覆盖

使用 modelOverrides 自定义内置模型和匹配扩展注册的模型,而无需替换 Provider 的完整模型列表。

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

modelOverrides 每个模型支持以下字段:namereasoningthinkingLevelMapinputcost(部分)、contextWindowmaxTokenssamplingParams(每个键合并)、headerscompat

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-terragpt-5.6-luna 应用相同的覆盖。

行为注意事项:

  • modelOverrides 适用于内置 Provider 模型和匹配的扩展注册 Provider 模型。
  • 未知的模型 ID 将被忽略。
  • 你可以将 Provider 级别 baseUrl/headersmodelOverrides 结合起来。
  • 覆盖 name 只会更改模型匹配和次要详情文本;页脚和主要模型列表仍会显示模型 id
  • 如果还为 Provider 定义了 models,则自定义模型会在内置覆盖后合并。具有相同 id 的自定义模型将替换覆盖后的内置模型条目。

Anthropic Messages 兼容性

对于使用 api: "anthropic-messages" 的 Provider 或代理,请使用 compat 控制 Anthropic-specific request compatibility。

默认情况下 pi 发送每个工具 eager_input_streaming: true。如果代理或与 Anthropic 兼容的后端拒绝该字段,请将 supportsEagerToolInputStreaming 设置为 false。 Pi 将省略 tools[].eager_input_streaming 并为支持工具的请求发送旧版 fine-grained-tool-streaming-2025-05-14 beta 标头。

一些 Anthropic 模型需要 adaptive thinking(thinking.type: "adaptive"output_config.effort),而不是旧版基于预算的 thinking payload。内置模型会自动设置。对于路由到这些模型的自定义 Provider 或别名,请将 forceAdaptiveThinking 设置为 true

一些 Anthropic-compatible Provider 会发出空 signature 的 thinking block,并且仍期望重放这些 signature。仅针对这些 Provider 将 allowEmptySignature 设置为 true;真正的 Anthropic 会拒绝空 thinking signature。

内置 Anthropic 模型会在模型元数据中启用 supportsStrictTools。自定义 Anthropic-compatible 模型的端点接受严格 JSON-schema 工具定义时,必须将其设置为 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 Provider 是否接受每个工具的 eager_input_streaming。默认值:true。设置为 false 可省略该字段,并在启用工具的请求上使用旧版细粒度工具流式传输 beta header。
supportsLongCacheRetention 当缓存保留为 long 时,Provider 是否接受 Anthropic 长缓存保留(cache_control.ttl: "1h")。默认值:true
sendSessionAffinityHeaders 启用缓存时是否从会话 ID 发送 x-session-affinity。默认值:自动检测已知 Provider。
supportsCacheControlOnTools Provider 是否接受工具定义上的 Anthropic 风格 cache_control 标记。默认值:true
forceAdaptiveThinking 是否为该模型发送 adaptive thinking(thinking.type: "adaptive"output_config.effort)。内置 adaptive 模型会自动设置此值。默认值:false
allowEmptySignature 是否将空 thinking signature 重放为 signature: "",而不是将 thinking 转换为文本。默认值:false
supportsStrictTools Provider 是否接受严格 JSON-schema 工具定义。默认值:false;内置 Anthropic 模型会在生成的元数据中启用它。

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": [...]
    }
  }
}
字段 描述
supportsStore Provider 支持 store 字段
supportsDeveloperRole 使用 developersystem 角色
supportsReasoningEffort 支持 reasoning_effort 参数
supportsUsageInStreaming 支持 stream_options: { include_usage: true }(默认:true
supportsFinishReason 流式响应是否包含 finish_reason。当为 false 时,pi 会在数据流结束时推断 stoptoolUse。默认值:true
maxTokensField 使用 max_completion_tokensmax_tokens
requiresToolResultName 在工具结果消息中包含 name
requiresAssistantAfterToolResult 在工具结果之后、用户消息之前插入 assistant 消息
requiresThinkingAsText 将 thinking block 转换为纯文本
requiresReasoningContentOnAssistantMessages 启用推理时,在所有重播的助手消息中包含空 reasoning_content
thinkingFormat 使用 reasoning_effortopenrouterdeepseektogetherbasetenzaiqwenchat-templateqwen-chat-template thinking 参数
chatTemplateKwargs thinkingFormat: "chat-template" 使用的 chat_template_kwargs 值;使用 { "$var": "thinking.enabled" }{ "$var": "thinking.effort" } 获取 pi 控制的 thinking 值
chatTemplateArgs thinkingFormat: "baseten" 使用的 chat_template_args 值;使用 { "$var": "thinking.enabled" }{ "$var": "thinking.effort" } 获取 pi 控制的 thinking 值
cacheControlFormat 在系统提示、最后一个工具定义以及最后一个用户、assistant 或工具结果文本内容上使用 Anthropic 风格的 cache_control 标记。目前仅支持 anthropic
sendSessionAffinityHeaders 对于 openai-completions,启用缓存时从会话 ID 发送 session-affinity header。默认值:false
sessionAffinityFormat 对于 openai-completionsopenai-responses,session-affinity header 格式:openai 发送 session_id/x-client-request-id(completions 还会发送 x-session-affinity),openai-nosession 省略包含下划线的 session_id header,openrouter 发送 x-session-id。不影响请求 body 中的 prompt_cache_key 参数。默认:自动检测。
supportsStrictMode Provider 是否接受严格的 JSON Schema function tool 定义。默认值取决于 API;内置 OpenAI 模型携带明确的能力元数据。
supportsOpenAIGrammarTools 兼容 OpenAI 的 API 是否发出自定义 Lark/regex 语法工具。当 false 时,语法约束工具回退到正常功能工具。默认值:false;内置模型目录支持 OpenAI、OpenAI Codex、Azure OpenAI、GitHub Copilot、opencode 和 Cloudflare AI Gateway 上的 GPT-5+ 模型。
deferredToolsMode 使用 Provider 特定的延迟工具序列化。目前仅支持 Kimi 的 OpenAI 兼容 Chat Completions 格式 "kimi"
supportsLongCacheRetention 当缓存保留为 long 时,Provider 是否接受长缓存保留:OpenAI prompt caching 使用 prompt_cache_retention: "24h"cacheControlFormatanthropic 时使用 cache_control.ttl: "1h"。默认值:true
openRouterRouting OpenRouter Provider 的路由首选项。该对象按原样发送到 OpenRouter API requestprovider 字段中。
vercelGatewayRouting 用于选择 Provider 的 Vercel AI 网关路由配置 (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-template,例如 DeepSeek V3.x 模板可使用 chatTemplateKwargs: { "thinking": { "$var": "thinking.enabled" } }。对于通过 chat_template_args 暴露开关值且可选支持顶级 reasoning_effort 的 Provider,请将 thinkingFormat: "baseten"chatTemplateArgs 结合使用。

cacheControlFormat: "anthropic" 适用于通过文本内容和工具定义上的 cache_control 标记暴露 Anthropic 风格 prompt caching 的 OpenAI 兼容 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 网关示例:

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