# 自定义模型

> 通过 ~/.pi/agent/models.json 添加自定义提供商与模型，配置兼容性与逐模型覆盖。

---

LLMS 索引： [llms.txt](/llms.txt)

---

通过 `~/.pi/agent/models.json` 添加自定义提供商与模型（Ollama、vLLM、LM Studio、代理）。

## 目录 {#table-of-contents}

- [最小示例](#minimal-example)
- [完整示例](#full-example)
- [支持的 API](#supported-apis)
- [提供商配置](#provider-configuration)
- [模型配置](#model-configuration)
- [覆盖内置提供商](#overriding-built-in-providers)
- [按模型覆盖](#per-model-overrides)
- [Anthropic Messages 兼容性](#anthropic-messages-compatibility)
- [OpenAI 兼容性](#openai-compatibility)

## 最小示例 {#minimal-example}

对于本地模型（Ollama、LM Studio、vLLM），每个模型只需提供 `id`：

```json
{
  "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` 中，因此不带密钥的本地服务器应保留一个虚拟值，用 `/login` 为该提供商保存一个密钥，或在选择模型时传入 `--api-key`。

一些 OpenAI 兼容服务器无法理解推理模型所用的 `developer` 角色。对于这类提供商，将 `compat.supportsDeveloperRole` 设为 `false`，pi 便会改用 `system` 消息来发送系统提示词。如果服务器同样不支持 `reasoning_effort`，请将 `compat.supportsReasoningEffort` 也设为 `false`。

`compat` 可以设在提供商级别，作用于所有模型；也可以设在模型级别，为特定模型做覆盖。这常见于 Ollama、vLLM、SGLang 以及类似的 OpenAI 兼容服务器。

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

## 完整示例 {#full-example}

在需要具体数值时覆盖默认值：

```json
{
  "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-ai-studio-example}

配合 `baseUrl` 使用 `google-generative-ai`，即可添加来自 Google AI Studio 的模型，包括自定义的 Gemma 4 条目：

```json
{
  "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 {#supported-apis}

| API | 说明 |
|-----|-------------|
| `openai-completions` | OpenAI Chat Completions（兼容性最好） |
| `openai-responses` | OpenAI Responses API |
| `anthropic-messages` | Anthropic Messages API |
| `google-generative-ai` | Google Generative AI |

在提供商级别设置 `api`（作为所有模型的默认值），或在模型级别设置（按模型覆盖）。

## 提供商配置 {#provider-configuration}

| 字段 | 说明 |
|-------|-------------|
| `baseUrl` | API 端点 URL |
| `api` | API 类型（见上文） |
| `apiKey` | 可选的 API 密钥配置（取值解析见下文）。当认证由 `/login`/`auth.json` 或 CLI 的 `--api-key` 提供时，可将其省略。 |
| `oauth` | 动态 OAuth 提供商类型。目前支持 `"radius"`；需要网关的 `baseUrl`。 |
| `headers` | 自定义请求头（取值解析见下文） |
| `authHeader` | 设为 `true` 时自动添加 `Authorization: Bearer <apiKey>` |
| `models` | 模型配置数组 |
| `modelOverrides` | 针对该提供商的内置模型或扩展注册模型进行逐模型覆盖 |

对于带 `models` 的提供商，非内置的提供商配置需要在提供商级别或模型级别提供 `baseUrl` 和 `api` 值。加载该文件本身并不要求 `apiKey`：当认证通过 `/login`/`auth.json`、CLI `--api-key` 或提供商 `apiKey` 配置好之后，模型即可使用。如果未配置任何认证，模型仍会加载，但在 `/model` 和 `--list-models` 中不可用。

### 取值解析 {#value-resolution}

`apiKey` 与 `headers` 字段支持命令执行、环境变量插值和字面量：

- **Shell 命令：** 值以 `"!command"` 开头时，整个值会作为命令执行，并使用其 stdout
  ```json
  "apiKey": "!security find-generic-password -ws 'anthropic'"
  "apiKey": "!op read 'op://vault/item/credential'"
  ```
- **环境变量插值：** `"$ENV_VAR"` 或 `"${ENV_VAR}"` 使用指定变量的值。插值也可以在更长的字面量内部使用。
  ```json
  "apiKey": "$MY_API_KEY"
  "apiKey": "${KEY_PREFIX}_${KEY_SUFFIX}"
  ```
  `$FOO_BAR` 指向变量 `FOO_BAR`；如果 `BAR` 是字面文本，应使用 `${FOO}_BAR`。环境变量缺失时，该值视为未解析。
- **转义：** `"$$"` 输出字面量 `"$"`；`"$!"` 输出字面量 `"!"`，且不会触发命令执行。
  ```json
  "apiKey": "$$literal-dollar-prefix"
  "apiKey": "$!literal-bang-prefix"
  ```
- **字面量：** 直接使用原值。`MY_API_KEY` 这类纯大写字符串就是字面量；要引用环境变量请写 `$MY_API_KEY`。
  ```json
  "apiKey": "sk-..."
  ```

对于 `models.json`，shell 命令在请求时解析。pi 有意不为任意命令应用内置的 TTL、过期复用或恢复逻辑——不同的命令需要不同的缓存与失败策略，pi 无法推断出正确的做法。

如果你的命令较慢、开销大、受速率限制，或希望在偶发失败时沿用先前的值，请把它包装进你自己的脚本或命令中，实现你想要的缓存或 TTL 行为。

`/model` 的可用性检查只依据已配置的认证信息，不会执行 shell 命令。

### 自定义请求头 {#custom-headers}

```json
{
  "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": [...]
    }
  }
}
```
## 模型配置 {#model-configuration}

| 字段 | 必填 | 默认值 | 说明 |
|-------|----------|---------|-------------|
| `id` | 是 | — | 模型标识符（传给 API） |
| `name` | 否 | `id` | 人类可读的模型标签。用于模型匹配（`--model` 的模式），并作为次要模型详情文本显示。 |
| `api` | 否 | 提供商的 `api` | 为该模型覆盖提供商的 API |
| `reasoning` | 否 | `false` | 支持扩展思考 |
| `thinkingLevelMap` | 否 | 省略 | 将 pi 的思考级别映射为提供商取值，并标记不支持的级别（见下文） |
| `input` | 否 | `["text"]` | 输入类型：`["text"]` 或 `["text", "image"]` |
| `contextWindow` | 否 | `128000` | 上下文窗口大小（token 数） |
| `maxTokens` | 否 | `16384` | 最大输出 token 数 |
| `samplingParams` | 否 | 省略 | 逐字合并进每个请求体的采样参数（见下文） |
| `cost` | 否 | 全为零 | 每百万 token 费率，可选按请求整体生效的输入定价分层 |
| `compat` | 否 | 提供商的 `compat` | 提供商兼容性覆盖。两者都设置时会与提供商级别的 `compat` 合并。 |

费用分层提供一套完整的替代费率；当总输入用量（`input + cacheRead + cacheWrite`）超过 `inputTokensAbove` 时，对整个请求生效。多个分层同时命中时，以阈值最高的为准。

```json
{
  "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。

### 采样参数 {#sampling-parameters}

`samplingParams` 是一个自由格式的对象，会逐字合并进该模型的每个请求体，并且合并在 pi 自身设置的字段之后，因此它的键优先。可用它发送 pi 未建模的采样参数——包括服务器特有的参数，比如 llama.cpp 的 `min_p` 或 vLLM 的 `top_k`：

```json
{
  "id": "deepseek-v4-flash",
  "samplingParams": {
    "temperature": 1.0,
    "top_p": 0.95,
    "top_k": 0,
    "min_p": 0.0
  }
}
```

只有 OpenAI 兼容 API 会应用它（`openai-completions`、`openai-responses`、`azure-openai-responses`）；其他 API 会忽略它。其中的键会覆盖 pi 的具名请求字段（例如这里的 `temperature` 键优先于请求级别的 temperature），因此建议将它作为模型采样参数的唯一事实来源。在 `modelOverrides` 中，`samplingParams` 会按键与基础模型的值合并。

固定的思考 token 上限也可以放在这里，但它不会跟随 `thinkingBudgets` 变化，也不会为回答预留空间。这类需求请优先使用 `compat.thinkingTokenBudgetField`（或其别名 `supportsThinkingTokenBudget`）。

### 思考级别映射 {#thinking-level-map}

在模型上使用 `thinkingLevelMap` 来描述该模型特有的思考控制。键是 pi 的思考级别：`off`、`minimal`、`low`、`medium`、`high`、`xhigh`、`max`。映射可以留有空档，例如某模型可以提供 `high` 和 `max`，而不提供 `xhigh`。

取值有三态：

| 取值 | 含义 |
|-------|---------|
| 省略 | `high` 及以下的标准级别使用提供商的默认映射；扩展的 `xhigh` 和 `max` 级别视为不支持 |
| string | 该级别受支持，此值会发送给提供商 |
| `null` | 该级别不受支持，会被隐藏/跳过/钳制掉 |

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

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

思考无法被禁用的模型示例：

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

迁移：旧配置中使用的 `compat.reasoningEffortMap` 应迁移到模型级别的 `thinkingLevelMap`。对不应出现在 UI 中的级别使用 `null`。

## 覆盖内置提供商 {#overriding-built-in-providers}

将内置提供商的请求路由到代理，而无需重新定义模型：

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

所有内置 Anthropic 模型仍然可用。已有的 OAuth 或 API 密钥认证继续有效。

要将自定义模型合并进内置提供商，请加上 `models` 数组：

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

合并语义：
- 保留内置模型。
- 自定义模型按 `id` 在该提供商内执行 upsert。
- 如果自定义模型的 `id` 与某个内置模型相同，该自定义模型会替换对应的内置模型。
- 如果自定义模型的 `id` 是新的，会与内置模型并列添加。

## 按模型覆盖 {#per-model-overrides}

使用 `modelOverrides` 定制内置模型以及匹配的扩展注册模型，而无需替换该提供商的完整模型列表。

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

`modelOverrides` 支持按模型设置以下字段：`name`、`reasoning`、`thinkingLevelMap`、`input`、`cost`（部分）、`contextWindow`、`maxTokens`、`samplingParams`（按键合并）、`headers`、`compat`。

OpenAI 直连的 GPT-5.6 Sol、Terra 和 Luna 默认使用 `272000` 上下文窗口，以便请求保持在 OpenAI 的短上下文定价档内。要启用 OpenAI 的 1.05M 上下文窗口，请为你使用的每个模型调大该值：

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

该覆盖会保留内置的定价元数据。总输入 token 超过 272K 的请求，将按 GPT-5.6 的长上下文费率对整个请求计费。需要时可对 `gpt-5.6-terra` 或 `gpt-5.6-luna` 应用相同的覆盖。

行为说明：
- `modelOverrides` 应用于内置提供商模型以及匹配的扩展注册提供商模型。
- 未知的模型 ID 会被忽略。
- 可以将提供商级别的 `baseUrl`/`headers` 与 `modelOverrides` 组合使用。
- 覆盖 `name` 只影响模型匹配和次要详情文本；页脚和主模型列表仍显示模型 `id`。
- 如果提供商还定义了 `models`，自定义模型会在内置覆盖之后合并。`id` 相同的自定义模型会替换已被覆盖的内置模型条目。

## Anthropic Messages 兼容性 {#anthropic-messages-compatibility}

对于使用 `api: "anthropic-messages"` 的提供商或代理，可用 `compat` 控制 Anthropic 特有的请求兼容性。

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

某些 Anthropic 模型需要自适应思考（`thinking.type: "adaptive"` 加 `output_config.effort`），而不是传统的基于预算的思考负载。内置模型会自动设置。对于路由到这些模型的自定义提供商或别名，请将 `forceAdaptiveThinking` 设为 `true`。

支持逐轮 effort 的 Claude 模型使用 `supportsMidConvoEffort`。启用后，pi 会持久化每个响应中提供商返回的 effort，在后续请求中重建仅含 effort 的系统消息，并发送带 `prefix_mismatch_behavior: "drop_block"` 的思考绑定控制，以避免过期的已签名思考前缀导致持续的 400 响应。请只对忠实实现 Anthropic Messages 传输且确切受支持的 Claude 模型启用它；不要为仅模仿 Messages 结构的 API 启用。

某些 Anthropic 兼容提供商会输出签名为空的思考块，并且期望在回放时原样传回。只应对这类提供商将 `allowEmptySignature` 设为 `true`；真正的 Anthropic 会拒绝空的思考签名。

内置 Anthropic 模型在模型元数据中启用了 `supportsStrictTools`。自定义的 Anthropic 兼容模型，在其端点接受严格 JSON schema 工具定义时，必须将它设为 `true`。

```json
{
  "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`。默认：`true`。设为 `false` 可省略该字段，并在带工具的请求中使用旧版细粒度工具流式 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`。 |
| `supportsMidConvoEffort` | 确切的 Claude 模型传输是否支持逐轮 effort 系统消息与思考绑定控制。启用后，pi 会持久化原生 effort 级别并始终发送 `drop_block`。默认：`false`。 |
| `allowEmptySignature` | 回放时是否将空思考签名保持为 `signature: ""`，而不是把思考转换为文本。默认：`false`。 |
| `supportsStrictTools` | 提供商是否接受严格 JSON schema 工具定义。默认：`false`；内置 Anthropic 模型在生成的元数据中启用了它。 |

## OpenAI 兼容性 {#openai-compatibility}

对于只部分兼容 OpenAI 的提供商，使用 `compat` 字段。

- 提供商级别的 `compat` 为该提供商下的所有模型提供默认值。
- 模型级别的 `compat` 为该模型覆盖提供商级别的值。

```json
{
  "providers": {
    "local-llm": {
      "baseUrl": "http://localhost:8080/v1",
      "api": "openai-completions",
      "compat": {
        "supportsUsageInStreaming": false,
        "maxTokensField": "max_tokens"
      },
      "models": [...]
    }
  }
}
```

| 字段 | 说明 |
|-------|-------------|
| `supportsStore` | 提供商支持 `store` 字段 |
| `supportsDeveloperRole` | 使用 `developer` 还是 `system` 角色 |
| `supportsReasoningEffort` | 是否支持 `reasoning_effort` 参数 |
| `supportsUsageInStreaming` | 是否支持 `stream_options: { include_usage: true }`（默认：`true`） |
| `supportsFinishReason` | 流式响应是否包含 `finish_reason`。为 `false` 时，pi 会在流结束时推断 `stop` 或 `toolUse`。默认：`true`。 |
| `maxTokensField` | 使用 `max_completion_tokens` 还是 `max_tokens` |
| `requiresToolResultName` | 在工具结果消息中包含 `name` |
| `requiresAssistantAfterToolResult` | 在工具结果之后的用户消息前插入一条 assistant 消息 |
| `requiresThinkingAsText` | 将思考块转换为纯文本 |
| `requiresReasoningContentOnAssistantMessages` | 启用推理时，在所有回放的 assistant 消息上包含空的 `reasoning_content` |
| `thinkingFormat` | 使用 `reasoning_effort`、`openrouter`、`deepseek`、`together`、`baseten`、`zai`、`qwen`、`chat-template` 或 `qwen-chat-template` 思考参数 |
| `chatTemplateKwargs` | `thinkingFormat: "chat-template"` 时的 `chat_template_kwargs` 取值；使用 `{ "$var": "thinking.enabled" }`、`{ "$var": "thinking.effort" }` 或 `{ "$var": "thinking.budget" }` 表示由 pi 控制的思考取值 |
| `chatTemplateArgs` | `thinkingFormat: "baseten"` 时的 `chat_template_args` 取值；使用 `{ "$var": "thinking.enabled" }`、`{ "$var": "thinking.effort" }` 或 `{ "$var": "thinking.budget" }` 表示由 pi 控制的思考取值 |
| `thinkingTokenBudgetField` | 用于根据 `thinkingBudgets` 限制推理 token 的顶层请求字段，并会钳制以确保至少为回答保留 1024 个 token。`"thinking_token_budget"`（vLLM）、`"thinking_budget"`（Qwen/DashScope/SGLang）、`"thinking_budget_tokens"`（llama.cpp）。默认关闭；不会在生成的模型目录上设置。 |
| `supportsThinkingTokenBudget` | `thinkingTokenBudgetField: "thinking_token_budget"`（vLLM）的别名。建议优先使用 `thinkingTokenBudgetField`。默认：`false`。 |
| `cacheControlFormat` | 在系统提示词、最后一个工具定义以及最后一条 user、assistant 或工具结果文本内容上使用 Anthropic 风格的 `cache_control` 标记。目前仅支持 `anthropic`。 |
| `sendSessionAffinityHeaders` | 对 `openai-completions`，启用缓存时根据会话 id 发送会话亲和头。默认：`false`。 |
| `sessionAffinityFormat` | 对 `openai-completions` 和 `openai-responses` 的会话亲和头格式：`openai` 发送 `session_id`/`x-client-request-id`（completions 还会发送 `x-session-affinity`）；`openai-nosession` 省略包含下划线的 `session_id` 头；`openrouter` 发送 `x-session-id`。不影响 `prompt_cache_key` 请求体参数。默认：自动检测。 |
| `supportsStrictMode` | 提供商是否接受严格 JSON schema 的函数工具定义。默认值取决于 API；内置 OpenAI 模型带有显式的能力元数据。 |
| `supportsOpenAIGrammarTools` | OpenAI 兼容 API 是否输出自定义 Lark/正则文法工具。为 `false` 时，文法约束的工具会退回为普通函数工具。默认：`false`；内置模型目录为 OpenAI、OpenAI Codex、Azure OpenAI、GitHub Copilot、opencode 和 Cloudflare AI Gateway 上的 GPT-5+ 模型启用了它。 |
| `deferredToolsMode` | 使用提供商特有的延迟工具序列化。目前仅支持 `"kimi"`，用于 Kimi 的 OpenAI 兼容 Chat Completions 格式。 |
| `supportsLongCacheRetention` | 当缓存保留策略为 `long` 时，提供商是否接受长缓存保留：GPT-5.6+ Responses 模型使用 `prompt_cache_options.ttl: "30m"`，较早的 OpenAI 模型使用 `prompt_cache_retention: "24h"`，`cacheControlFormat` 为 `anthropic` 时使用 `cache_control.ttl: "1h"`。默认：`true`。 |
| `openRouterRouting` | OpenRouter 提供商路由偏好。该对象会原样放入 [OpenRouter API 请求](https://openrouter.ai/docs/guides/routing/provider-selection)的 `provider` 字段中发送。 |
| `vercelGatewayRouting` | Vercel AI Gateway 用于提供商选择的路由配置（`only`、`order`） |

`openrouter` 使用 `reasoning: { effort }`。`together` 使用 `reasoning: { enabled }`，并在启用 `supportsReasoningEffort` 时同时发送 `reasoning_effort`。`qwen` 使用顶层的 `enable_thinking`。对于需要 `chat_template_kwargs.enable_thinking` 和 `preserve_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` 的提供商，将 `thinkingFormat: "baseten"` 与 `chatTemplateArgs` 搭配使用。

`thinkingTokenBudgetField` 与 `thinkingFormat` 相互独立。不要在生成的 Qwen 模型目录上启用它：这些模型已经发送 `reasoning_effort`，而 DashScope 会拒绝 `thinking_budget` 与 `reasoning_effort` 同时出现。

`cacheControlFormat: "anthropic"` 适用于通过文本内容和工具定义上的 `cache_control` 标记暴露 Anthropic 风格提示词缓存的 OpenAI 兼容提供商。

示例：

```json
{
  "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 示例：

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

---

反链：

- [扩展](/book/pi/extensions/)
- [提供商](/book/pi/providers/)
