# 从 OpenRouter 迁移 (/docs/cookbook/migration/from-openrouter)



保留 OpenAI SDK，替换连接配置与模型 ID；切流量前逐项处理 OpenRouter 专有选项。

```diff
 client = OpenAI(
-    base_url="https://openrouter.ai/api/v1",
-    api_key=os.environ["OPENROUTER_API_KEY"],
+    base_url="https://api.deepraxis.ai/openai/v1",
+    api_key=os.environ["PRAXIS_API_KEY"],
 )
-model = "openai/gpt-4o"
+model = "deepseek-flash"
```

## 1. 准备 [#1-准备]

需要 Python 3.10+、[uv](https://docs.astral.sh/uv/getting-started/installation/) 和一个 Praxis Key。在[控制台 → API Keys](https://console.deepraxis.ai/keys)创建 Key，将它安全注入当前终端的 `PRAXIS_API_KEY` 环境变量；不要把 Key 写进代码或日志。保留原服务的配置与 Key，供回滚使用。以下命令在 macOS / Linux 的 Bash 中执行。

```bash
test -n "${PRAXIS_API_KEY:-}"
```

期望：退出码 0；退出码 1 表示变量未设置，先设置再继续。

## 2. 替换模型 ID [#2-替换模型-id]

| OpenRouter 选择     | Praxis 选择                           |
| ----------------- | ----------------------------------- |
| `openai/gpt-4o`   | 先用 `deepseek-flash` 跑通；这是另一个模型，不是别名 |
| `vendor/model`    | 从 Praxis 目录复制完整 ID，不能假设去掉前缀就可用      |
| 带 `:nitro` 后缀的 ID | 选不带后缀的目录 ID；不支持该后缀                  |
| `openrouter/auto` | 明确选择一个模型，或配置 `models` 回退列表          |

期望：`client.models.list()` 包含选定 ID。回退列表中的每个 ID 都必须是有效的 Praxis ID，并支持你调用的操作。

## 行为差异 [#行为差异]

| OpenRouter 选项                                      | 迁移处理                                                                  |
| -------------------------------------------------- | --------------------------------------------------------------------- |
| `provider.order`、`provider.only`、`provider.ignore` | 仅自带上游 Key（BYOK）可用；使用平台凭据时移除，否则返回 `400 provider_selection_not_allowed` |
| `provider.allow_fallbacks`、`provider.sort`         | 无效果；移除并重新评估选路假设                                                       |
| `provider.data_collection`、`provider.zdr`          | 无效果；请求被接受不代表这些策略已执行                                                   |
| `models`                                           | 支持模型回退列表；替换每个 ID 并检查响应中的 `model`                                      |
| `provider.require_parameters: true`                | 对工具参数与已声明的采样参数进行支持检查；要求未声明支持的参数时返回 400；不支持的采样参数默认忽略                   |

参数检查范围是工具参数与已声明的采样参数，不是供应商任意功能。准确范围见 [Chat Completions 字段支持](/docs/api/compatible/openai/createChatCompletion)。如果应用依赖被忽略选项所控制的数据策略，应继续使用原服务，直到单独确认所需策略。

Chat 的 `usage.cost` 是实付金额；Responses 和 Messages 目前不返回该字段。收到 `X-Praxis-Generation-Id` 时，可按 [生成记录 API](/docs/api/native/model/getGeneration) 用 `GET /model/v1/generation?id=生成ID` 查费用（记录可能延迟几秒）。若响应没有该头，去[控制台 → 用量与费用](https://console.deepraxis.ai/usage)查本次调用；不要把响应正文的 `id` 或 `X-Request-Id` 当成生成 ID，也不要将缺失费用当成零。

## 不支持的操作与替代 [#不支持的操作与替代]

`vendor/model`、`:nitro`、`openrouter/auto` 都不是受支持的模型选择方式，也不会自动映射。缺失的 OpenAI 端点见[不支持清单与替代](/docs/cookbook/migration/from-openai#不支持的端点与替代)。具体操作与字段以 [API 参考](/docs/api/compatible/openai) 为准，不要假设 OpenRouter 扩展也适用于 Responses。

## 3. 验证一次请求 [#3-验证一次请求]

先跑通不带供应商偏好的最小 Chat 请求：

```bash
unset HTTP_PROXY HTTPS_PROXY ALL_PROXY http_proxy https_proxy all_proxy
uv run -q --no-project --with openai --with anthropic python - <<'PY'
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.deepraxis.ai/openai/v1",
    api_key=os.environ["PRAXIS_API_KEY"],
    timeout=90.0,
    max_retries=0,
)
models = client.models.list()
assert "deepseek-flash" in {m.id for m in models.data}
raw = client.chat.completions.with_raw_response.create(
    model="deepseek-flash",
    messages=[{"role": "user", "content": "Reply OK."}],
    max_tokens=1024,
)
reply = raw.parse()
text = reply.choices[0].message.content
print("HTTP", raw.status_code)
print("X-Request-Id:", raw.headers.get("x-request-id"))
print("X-Praxis-Generation-Id:", raw.headers.get("x-praxis-generation-id"))
print(text)
assert raw.status_code == 200 and text and text.strip()
assert raw.headers.get("x-request-id")
PY
```

期望：退出码 0，输出 `HTTP 200`、非空正文（通常为 `OK.`）和 `X-Request-Id`。断言同时检查模型存在与真实回复；不是只检查能否连接。保留请求 ID 便于排查，不要记录 Key。示例会产生少量调用费用。

然后逐个加回应用需要的选项。期望：每次请求成功且返回预期模型；被忽略的字段不能作为策略生效的证据。

## 失败分支 [#失败分支]

| 实测报错                                 | 处理                          |
| ------------------------------------ | --------------------------- |
| `400 provider_selection_not_allowed` | 平台凭据移除供应商选择；或先配置 BYOK 再选择上游 |
| `404`，包含 `does not exist`            | 将带厂商前缀、后缀或自动选择器的 ID 换成目录 ID |
| `404 model_protocol_not_offered`     | 选择提供该操作的模型                  |

## 4. 回滚 [#4-回滚]

恢复 `https://openrouter.ai/api/v1`、原 `OPENROUTER_API_KEY`、原模型 ID 和保存的 OpenRouter 选项。重启客户端后跑原冒烟请求。不要把 Praxis Key 发给 OpenRouter。

期望：原请求返回可用正文与预期模型。Praxis 上已产生的调用费用仍保留。

[API 参考 →](/docs/api/compatible/openai) · [Cookbook：OpenAI SDK →](/docs/cookbook/sdk/openai-sdk)
