OpenAI 兼容 SDK(OpenAI-Compatible SDK)
1. 定义
OpenAI 兼容 SDK 有两层意思,容易混:
- OpenAI 官方 SDK(
openai这个 Python / JS 库):原本只连 OpenAI 自家服务,但因为设计成”可换底座”,现在被当成通用的 LLM 客户端用。 - OpenAI 兼容端点 / 服务:任何第三方(Ollama、vLLM、LM Studio、OpenRouter、LiteLLM 等)只要把自己的 HTTP 接口做成跟 OpenAI 一样的请求/响应格式,就叫”OpenAI 兼容”。
一句话总结:只要把
base_url指过去、按 OpenAI 的字段填请求,就能用同一套代码调用无数家模型——这是 LLM 生态里事实上的”USB 接口”。
类比:OpenAI 的 API 像是 USB 接口标准,官方 SDK 是一根原装线;“兼容”就是别的厂家也照这个口做了插座,于是原装线插谁家都能用。
2. 它解决什么问题
| 痛点 | 没有兼容层时 | OpenAI 兼容后 |
|---|---|---|
| 换模型供应商 | 重写一整套请求/解析代码 | 改 base_url + api_key 即可 |
| 本地跑模型 | 各推理框架各写各的客户端 | Ollama/vLLM 直接复用官方 SDK |
| 聚合多家模型 | 每个厂商装一个 SDK | LiteLLM 一个端点代理全部 |
| 防厂商锁定 | 深度绑定某家 API 字段 | 业务代码与具体厂商解耦 |
核心收益:业务逻辑只认 OpenAI 的接口形状,底座可随时替换。
3. 工作原理
兼容的本质是”接口对齐”——服务端复刻 OpenAI 的 REST 端点和 JSON 字段,客户端(官方 SDK)通过 base_url 重定向即可,代码路径完全不变。
你的代码
│ from openai import OpenAI
│ client = OpenAI(base_url=..., api_key=...)
▼
┌─────────────────────────────┐
│ OpenAI 官方 SDK(客户端) │ <- 同一份代码,只换底座
└──────────────┬──────────────┘
│ POST /v1/chat/completions
│ {model, messages, temperature, ...}
▼
base_url 指向哪里?
┌──────┬───────┬──────┬──────────┬──────────┐
▼ ▼ ▼ ▼ ▼ ▼
api.openai Ollama vLLM LM Studio OpenRouter LiteLLM
.com :11434 :8000 :1234 :443 :4000
(官方) (本地) (本地) (本地GUI) (聚合) (代理全部)
关键点:
- 端点对齐:
/v1/chat/completions、/v1/embeddings、/v1/models、/v1/audio/transcriptions等路径一致。 - 字段对齐:请求体用
model/messages/temperature/tools;响应体用choices[].message/usage。 - 流式对齐:SSE 格式
data: {json}与 OpenAI 一致,官方 SDK 的stream=True直接可用。 - 新接口:OpenAI 后来的 Responses API(
/v1/responses)也在成为事实标准,兼容服务逐步跟进。
4. 基本用法
Python:同一份代码,换底座
# 官方 OpenAI
from openai import OpenAI
client = OpenAI(api_key="sk-...") # 默认 base_url=https://api.openai.com/v1
# 本地 Ollama
client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama") # key 随便填
# vLLM 部署的模型
client = OpenAI(base_url="http://localhost:8000/v1", api_key="EMPTY")
# 调用方式完全不变
resp = client.chat.completions.create(
model="gpt-4o-mini", # 换成 ollama 的 "llama3" 或 vllm 的 "my-model"
messages=[{"role": "user", "content": "你好"}],
temperature=0.7,
stream=False,
)
print(resp.choices[0].message.content)JS / TS(同样只换 baseURL)
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "http://localhost:11434/v1", // 指到兼容服务
apiKey: "ollama",
});
const stream = await client.chat.completions.create({
model: "llama3",
messages: [{ role: "user", content: "讲个笑话" }],
stream: true, // 流式;兼容服务若支持则原样工作
});带 function calling(工具调用)
resp = client.chat.completions.create(
model="llama3",
messages=[{"role": "user", "content": "北京现在几点?"}],
tools=[{ # 字段与 OpenAI 官方一致
"type": "function",
"function": {
"name": "get_time",
"parameters": {"type": "object",
"properties": {"city": {"type": "string"}}},
},
}],
)
# 兼容服务若支持 tool calling,返回 choices[].message.tool_calls这正好衔接
tool_calling.md与hermes.md:Hermes 这类擅长 function-calling 的开源模型,常通过 Ollama/vLLM 这类兼容端点对外提供能力。
5. 对比辨析表
常见兼容服务端
| 服务 | 形态 | 兼容范围 | 典型 base_url | 备注 |
|---|---|---|---|---|
| OpenAI 官方 | 云端 | 全量(含 Responses、微调、图像) | https://api.openai.com/v1 | 标准本体 |
| Ollama | 本地 | chat / embeddings / tools | http://localhost:11434/v1 | 个人本地首选 |
| vLLM | 本地/集群 | chat / completions / embeddings | http://localhost:8000/v1 | 高吞吐推理 |
| LM Studio | 本地 GUI | chat / embeddings | http://localhost:1234/v1 | 图形界面友好 |
| OpenRouter | 云端聚合 | chat(多模型) | https://openrouter.ai/api/v1 | 一个 key 调几百个模型 |
| LiteLLM | 代理/网关 | 几乎全厂商 chat/embeddings | http://localhost:4000 | 把 Anthropic/Google 等也转成 OpenAI 形状 |
”OpenAI 兼容” vs “直接用各家原生 SDK”
| 维度 | OpenAI 兼容(统一客户端) | 各家原生 SDK(anthropic / google-genai) |
|---|---|---|
| 换模型成本 | 极低(改 base_url) | 高(改 import + 请求结构) |
| 功能完整性 | 受兼容层覆盖度限制 | 100% 支持自家独有特性 |
| 独有能力 | 可能拿不到(如 Claude 的 extended thinking 早期) | 完整 |
| 多模型统一 | 天然统一 | 需自己写适配层 |
| 适用场景 | 快速试模型、自托管、网关聚合 | 深度依赖某家独有功能 |
结论:兼容层是”最大公约数”,拿了方便、损了独特性。需要某家独门绝技时,原生 SDK 仍不可替代。
6. 典型工作流
新项目:先用 OpenAI 兼容快速验证
1. 业务代码只依赖 openai SDK,base_url 先指向 OpenAI 官方
2. 本地用 Ollama 跑小模型做单测(零 API 费用)
3. 上线前评估成本 → 把 base_url 切到 OpenRouter / 自托管 vLLM
4. 业务代码一行不改
接手已有项目:识别兼容层
1. 搜代码里 OpenAI(...) 的 base_url 参数 → 确定实际打到哪
2. 确认兼容端点覆盖了哪些接口(chat?embeddings?tools?)
3. 缺的能力(如图像、微调)要么补端点,要么为那部分单独接原生 SDK
自建网关:用 LiteLLM 统一多供应商
多家模型(OpenAI / Anthropic / Gemini)
│ LiteLLM 代理
▼
一个 OpenAI 兼容端点 :4000
│
业务代码(只认 openai SDK)
7. 常见误区
❌ “OpenAI 兼容 = 完全等价于 OpenAI” 正确:只对齐了接口形状,模型能力、上下文长度、tool calling 支持度、价格都不同。换底座后务必重新测行为,不能假设和官方完全一致。
❌ “api_key 必须填真的 OpenAI key”
正确:本地服务(Ollama/vLLM)不需要真 key,随便填占位串(如 "ollama"、"EMPTY")即可,重点是 base_url。
❌ “用了兼容 SDK 就自动支持所有模型的最新特性” 正确:兼容层是子集。Responses API、某些推理参数、厂商独有功能可能不被兼容服务实现;需要时就得退化到原生 SDK。
❌ “base_url 大小写 / 末尾 /v1 不重要”
正确:base_url 必须包含且只到 /v1(或该服务规定的前缀),多写少写都会导致 404。每个服务约定不同,以官方文档为准。
❌ “兼容层会帮我做鉴权和限速” 正确:兼容层只管”转发和格式转换”。生产环境仍需自己加 key 管理、并发限制、fallback——尤其用 LiteLLM 当网关时。
8. 延伸阅读 / 关联概念
tool_calling.md— 工具调用字段如何在兼容层里保持统一hermes.md— 擅长 function calling 的开源模型,常经 Ollama/vLLM 兼容端点提供mcp.md— MCP 是工具接入协议,与”模型 API 兼容”是不同层面(一个管接工具,一个管调模型)agent_harness.md— Agent 运行时如何借统一客户端在多家模型间切换openclaw.md— 开源 Agent 框架,底层也常通过兼容客户端调模型../networking/http_methods_fetch.md—create()剥开就是POST /v1/chat/completions;怎么用 Fetch/curl 真正发出这些请求api_relay.md— 中转站/代理网关:把”兼容端点”做成服务端 + 格式翻译 + 计费,本文的服务端对应物
官方参考:
- OpenAI API 文档(接口形状的定义源):https://platform.openai.com/docs/api-reference
- Ollama / vLLM / LiteLLM 各自的 “OpenAI-compatible endpoint” 章节