第 01 模块 · 3 节

Custom Provider 配置

《Pi 生产级工程》01 多模型与提供方 · 本节时长 30 分钟

为什么要自定义 provider

内置提供方不够用?那就自己配。pi 支持通过 ~/.pi/agent/models.json 加自定义提供方和模型:Ollama、vLLM、LM Studio、各种代理,只要它讲 pi 认识的 API(OpenAI Completions、OpenAI Responses、Anthropic Messages、Google Generative AI)。

一句话:凡是能 curl 通的模型服务,都能接进 pi。

贯穿项目md-tools 分发,自定义 provider 最大的价值是**用本地模型做免费分发测试**。你不想每次跑测试都烧 API 额度?那就给 md-tools 的开发环境配一个 Ollama 本地模型。这样改一行脚本、跑一次验证,零成本。**本节学会 models.json,你就能给 md-tools 搭一个本地测试床。**

最小示例:加一个 Ollama

本地模型(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" 是个占位符——Ollama 其实忽略 Key。但 pi 会认为「模型需要认证」才让它在 /model 里出现,所以无 Key 的本地服务要么留个占位值,要么用 /login 存个假 Key,要么在选模型时 --api-key


完整的 provider 配置字段

需要更细控制时,覆盖这些字段:

字段 作用
baseUrl API 端点 URL
api API 类型(见下)
apiKey 可选,Key 配置;省略则走 /login/auth.json 或 CLI
headers 自定义请求头
authHeader true 则自动加 Authorization: Bearer
models 模型配置数组
modelOverrides 对内置模型的逐模型覆盖

支持的 API 类型:openai-completions(兼容性最好)、openai-responsesanthropic-messagesgoogle-generative-ai

完整的模型级字段也值得记住:

{
  "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 都会重载——会话中改了不用重启


兼容性小坑:supportsDeveloperRole

有些 OpenAI 兼容服务不认识 reasoning 模型用的 developer 角色。对这类服务,设置 compat.supportsDeveloperRole: false,pi 就会把系统提示词当 system 消息发;如果服务也不支持 reasoning_effort,再加 supportsReasoningEffort: false

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

这在你接 Ollama / vLLM / SGLang 这类本地服务时很常见。


覆盖内置 provider

不重新定义模型,也能把一个内置 provider 路由到代理:

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

只给 baseUrl / headers 时,该 provider 现有的模型全部保留,只是换了新端点。合并语义:

  • 内置模型保留
  • 自定义模型按 id 合并进 provider
  • 若自定义 id 与内置重复,自定义替换内置

扩展也能注册 provider

除了 models.json,扩展里也能用 pi.registerProvider() 注册 provider——这适合需要自定义鉴权、OAuth 或非标准流式的场景:

export default function (pi: ExtensionAPI) {
  pi.registerProvider("my-provider", {
    name: "My Provider",
    baseUrl: "https://api.example.com",
    apiKey: "$MY_API_KEY",
    api: "openai-completions",
    models: [
      {
        id: "my-model",
        name: "My Model",
        reasoning: false,
        input: ["text", "image"],
        cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
        contextWindow: 128000,
        maxTokens: 4096,
      },
    ],
  });
}

这类 registerProvider 本身就能封装进 Pi Package——这正好引向下一个模块。


落地练习:配一个 Ollama 本地 provider

动手把本地模型接进 pi:

  1. 确认你装了 Ollama(或任一本地服务),并 ollama pull llama3.1:8b 拉了模型
  2. ~/.pi/agent/models.json 写入上面的「最小示例」配置
  3. pi,打开 /model,确认 llama3.1:8b 可选,并试一次对话

怎么判断做对了?——/model 里能看到 llama3.1:8b,且能正常对话;如果模型加载了却不出现,多半是缺认证占位,补上 apiKey 或存一个假 Key。

卡住了怎么办? 服务没起来?先 curl http://localhost:11434/v1/models 确认它通。选了模型仍报错?多半是 developer 角色问题,把 supportsDeveloperRole: false 加上。


常见坑:配了模型却不出现

最常见的挫败感是「我明明写了 models.json,模型就是不出现在 /model」。

原因几乎总是认证:pi 只有在判定「认证已配置」时,才会让模型在 /model--list-models 里出现。本地无 Key 服务,你得像上面那样留占位 apiKey,或给该 provider 用 /login 存一把 Key。不是配置没生效,是 pi 认为你没认证好。


小结

  1. models.json 用来加自定义 provider(Ollama、vLLM、代理等)
  2. 本地模型最小只需 id,但需认证占位才在 /model 出现
  3. 常用兼容开关:supportsDeveloperRole / supportsReasoningEffort
  4. 只给 baseUrl/headers 可把内置 provider 路由到代理,模型保留
  5. 扩展里也能用 pi.registerProvider() 注册

下一节,用 pi-switch 把 Provider 管理起来。