18  自定义模型

18.1 自定义模型概述

通过 ~/.pi/agent/models.json 文件,可以添加自定义模型提供者和模型。这适用于:

  • 本地模型(Ollama、LM Studio、vLLM)
  • 自定义代理端点
  • 企业内部部署的模型
  • 任何 OpenAI/Anthropic/Google 兼容的 API

18.2 最小示例:Ollama

对于本地模型,每个模型只需要 id 字段:

{
  "providers": {
    "ollama": {
      "baseUrl": "http://localhost:11434/v1",
      "api": "openai-completions",
      "apiKey": "ollama",
      "models": [
        { "id": "llama3.1:8b" },
        { "id": "qwen2.5-coder:7b" }
      ]
    }
  }
}
Note

apiKey 对于 Ollama 是占位符(Ollama 忽略它)。但 Pi 要求有认证配置才会在 /model 中显示模型。对于无认证的本地服务器,保持一个 dummy 值即可。

18.2.1 OpenAI 兼容性调整

某些 OpenAI 兼容服务器不理解 developer 角色(用于推理模型)。对于这些提供者:

{
  "providers": {
    "ollama": {
      "baseUrl": "http://localhost:11434/v1",
      "api": "openai-completions",
      "apiKey": "ollama",
      "compat": {
        "supportsDeveloperRole": false,
        "supportsReasoningEffort": false
      },
      "models": [
        {
          "id": "gpt-oss:20b",
          "reasoning": true
        }
      ]
    }
  }
}

compat 可设在提供者级别(应用于所有模型)或模型级别(覆盖特定模型)。

18.3 完整示例

当需要指定具体参数时:

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

models.json 每次打开 /model 时都会重新加载。你可以在会话中编辑文件,无需重启 Pi。

18.4 Google AI Studio 示例

使用 google-generative-ai API 和 baseUrl 添加 Google AI Studio 模型:

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

google-generative-ai API 类型添加自定义模型时,baseUrl 是必需的。

18.5 支持的 API

API 说明
openai-completions OpenAI Chat Completions(最通用)
openai-responses OpenAI Responses API
anthropic-messages Anthropic Messages API
google-generative-ai Google Generative AI

api 可设在提供者级别(所有模型的默认值)或模型级别(覆盖特定模型)。

18.6 提供者配置

字段 说明
baseUrl API 端点 URL
api API 类型
apiKey 可选 API 密钥配置
oauth 动态 OAuth 提供者类型
headers 自定义请求头
authHeader 设为 true 自动添加 Authorization: Bearer <apiKey>
models 模型配置数组
modelOverrides 对内置或扩展注册模型的逐模型覆盖

18.6.1 值解析(Value Resolution)

apiKeyheaders 字段支持三种值形式:

Shell 命令(以 ! 开头):

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

字面值

{
  "apiKey": "sk-..."
}

转义规则

语法 输出
$$ 字面 $
$! 字面 !(不触发命令执行)
Warning

Shell 命令在请求时解析。Pi 不会为任意命令实现 TTL 或缓存逻辑。如果你的命令很慢或有限流,请用你自己的脚本包装所需的缓存/失败处理策略。

18.6.2 自定义 Headers

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

18.7 模型配置字段

字段 必需 默认值 说明
id 模型标识符(传递给 API)
name id 人类可读的模型标签
api 提供者的 api 覆盖提供者的 API
reasoning false 是否支持扩展思考
thinkingLevelMap 省略 思考级别映射
input ["text"] 输入类型:["text"]["text", "image"]
contextWindow 128000 上下文窗口大小(token 数)
maxTokens 16384 最大输出 token 数
cost 全零 每百万 token 费率
compat 提供者 compat 兼容性覆盖

18.7.1 Cost Tiers(费用分层)

费用分层提供完整的替代费率,当总输入用量超过 inputTokensAbove 时应用于整个请求:

{
  "cost": {
    "input": 5,
    "output": 30,
    "cacheRead": 0.5,
    "cacheWrite": 6.25,
    "tiers": [
      {
        "inputTokensAbove": 272000,
        "input": 10,
        "output": 45,
        "cacheRead": 1,
        "cacheWrite": 12.5
      }
    ]
  }
}

当多个 tier 匹配时,最高阈值的优先。

18.8 Thinking Level Map

使用 thinkingLevelMap 描述模型特定的思考控制。键是 Pi 的思考级别(offminimallowmediumhighxhighmax)。

值的三种状态:

含义
省略 标准级别通过 high 使用提供者默认映射;xhigh 和 max 不支持
string 级别受支持,该值发送给提供者
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
  }
}

18.9 覆盖内置提供者

通过代理路由内置提供者,无需重定义模型:

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

所有内置 Anthropic 模型保持可用。现有的 OAuth 或 API 密钥认证继续工作。

如需合并自定义模型到内置提供者,包含 models 数组:

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

合并语义

  • 内置模型保留
  • 自定义模型按 id 在提供者内 upsert
  • 如果 id 与内置模型匹配,替换该内置模型
  • 如果 id 是新的,添加到内置模型旁边

18.10 Per-model Overrides

使用 modelOverrides 自定义内置模型,而不替换提供者的完整模型列表:

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

modelOverrides 支持的字段:namereasoningthinkingLevelMapinputcost(部分)、contextWindowmaxTokensheaderscompat

18.10.1 扩展 OpenAI 上下文窗口

OpenAI GPT-5.6 Sol/Terra/Luna 默认使用 272K 上下文窗口(保持在短上下文定价层)。要使用 1.05M 上下文窗口:

{
  "providers": {
    "openai": {
      "modelOverrides": {
        "gpt-5.6-sol": {
          "contextWindow": 1050000
        }
      }
    }
  }
}

18.11 Anthropic Messages 兼容性

对于使用 api: "anthropic-messages" 的提供者或代理,使用 compat 控制 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 是否接受 per-tool eager_input_streaming true
supportsLongCacheRetention 是否接受 Anthropic 长缓存保留 true
sendSessionAffinityHeaders 是否发送 x-session-affinity 自动检测
supportsCacheControlOnTools 是否接受工具定义上的 cache_control true
forceAdaptiveThinking 是否发送 adaptive thinking false
allowEmptySignature 是否重放空思考签名 false
supportsStrictTools 是否接受严格 JSON-schema 工具定义 false

18.12 OpenAI 兼容性

对于部分 OpenAI 兼容的提供者,使用 compat 字段:

{
  "providers": {
    "my-openai-compat": {
      "baseUrl": "https://api.example.com/v1",
      "api": "openai-completions",
      "compat": {
        "supportsDeveloperRole": false,
        "supportsReasoningEffort": true,
        "maxTokensField": "max_tokens",
        "requiresToolResultName": true,
        "thinkingFormat": "qwen",
        "cacheControlFormat": "anthropic"
      },
      "models": [...]
    }
  }
}
Tip

大多数 OpenAI 兼容的提供者使用 openai-completions 即可工作。如果遇到问题,检查 compat 配置中的兼容性选项。