团队里同时在用GPT-4o、Claude、Qwen三个模型,每个模型的API格式都不一样,代码里一堆if-else判断用哪个SDK。后来发现一个更好的方案:所有模型都通过OpenAI兼容API格式暴露,代码只维护一套,换模型只改一个参数。这篇文章分享这个方案的实现思路和实际经验。
为什么是OpenAI格式
大模型领域的API格式目前是"OpenAI一家独大"的局面。虽然各家的API细节不同,但核心接口(chat completions)的结构惊人地一致:system/user/assistant角色、messages数组、model参数、stream开关。这意味着只要一个服务把内部格式转换成OpenAI格式,所有OpenAI SDK的代码都能直接用。
统一API格式的好处:
- 代码维护成本低:一套SDK代码,不用适配每个模型的API差异;
- 切换模型方便:改一个model参数就能换模型,不需要改业务逻辑;
- A/B测试简单:同一个接口不同model参数就能对比不同模型的效果;
- 供应商锁定风险低:随时可以从OpenAI切换到其他模型提供商;
开源方案对比
LiteLLM是最成熟的方案,支持100+模型提供商,一个Python包搞定所有适配。它的核心功能是把各种模型的API格式统一转换成OpenAI格式,你只需要配置API Key和模型映射关系;
Ollama内置了OpenAI兼容API,专门针对本地部署的模型。访问/v1/chat/completions就能用OpenAI SDK调用本地模型;
vLLM的OpenAI兼容服务适合高并发场景。它在底层做了PagedAttention等优化,推理性能比Ollama高一个量级,但部署也更复杂;
One API是国内开发者做的,支持Azure、国内各家大模型(文心一言、通义千问、智谱等),有Web管理界面,适合团队使用;
切换后端只需改两行
from openai import OpenAI
# 切换OpenAI
client = OpenAI(api_key="sk-xxx")
# 切换Ollama —— 改两行
client = OpenAI(
base_url="http://localhost:11434/v1",
api_key="ollama"
)
# 切换vLLM
client = OpenAI(
base_url="http://localhost:8000/v1",
api_key="dummy"
)
# 切换LiteLLM网关
client = OpenAI(
base_url="http://localhost:4000/v1",
api_key="anything"
)
# 调用代码完全一样,不需要改任何东西
response = client.chat.completions.create(
model="qwen2.5-7b",
messages=[{"role": "user", "content": "你好"}]
)
这套代码在OpenAI、Ollama、vLLM、LiteLLM上都能跑,只需要改base_url和api_key。这就是OpenAI兼容API的核心价值——业务代码和模型提供商解耦。
用LiteLLM搭建统一网关
安装和配置
pip install litellm
配置文件config.yaml:
model_list:
- model_name: gpt-4o
litellm_params:
model: openai/gpt-4o
api_key: ${OPENAI_API_KEY}
- model_name: claude
litellm_params:
model: anthropic/claude-sonnet-4-20250514
api_key: ${ANTHROPIC_API_KEY}
- model_name: qwen
litellm_params:
model: openai/qwen-turbo
api_base: https://dashscope.aliyuncs.com/compatible-mode/v1
api_key: ${DASHSCOPE_API_KEY}
启动服务
litellm --config config.yaml --port 4000
负载均衡和故障转移
LiteLLM支持多API Key轮询和故障转移——配置两个Key后自动轮询,一个Key触发rate limit自动切换到另一个:
model_list:
- model_name: gpt-4o
litellm_params:
model: openai/gpt-4o
api_key: ${OPENAI_KEY_1}
- model_name: gpt-4o
litellm_params:
model: openai/gpt-4o
api_key: ${OPENAI_KEY_2}
流式输出兼容性
流式输出是各家API差异最大的地方。好消息是OpenAI兼容格式的SSE(Server-Sent Events)基本一致:
stream = client.chat.completions.create(
model="qwen2.5-7b",
messages=[{"role": "user", "content": "写一首诗"}],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="")
这段代码在所有OpenAI兼容的后端上都能正常流式输出。唯一的差异是各家模型的生成速度不同——本地7B模型可能比GPT-4o慢,但数据格式完全兼容。
注意事项和踩坑
模型参数不完全兼容。比如Claude不支持response_format参数,Gemini的stop_sequences和OpenAI的stop参数格式不同。LiteLLM做了大部分适配,但偶尔还是会遇到不支持的参数,需要在请求里过滤掉;
Token计数方式不同。OpenAI用tiktoken计数,其他模型各有各的分词器。统一网关的成本追踪可能和实际计费有出入,重要场景以模型提供商的实际计费为准;
Function Calling格式差异。虽然都是function calling,但各家对tool schema的支持程度不同。有些模型不支持嵌套的JSON Schema,有些对enum字段的处理有差异。在统一网关里做tool schema的兼容性检查很重要;
错误码不统一。OpenAI返回429表示rate limit,但有些模型返回503或自定义错误码。统一网关需要做错误码映射,让业务代码能统一处理;
写在最后
OpenAI兼容API已经是事实上的行业标准。与其为每个模型写适配代码,不如在API层做一次格式统一。LiteLLM、Ollama、vLLM这些开源方案让这件事变得非常简单。如果你的团队同时使用多个模型,强烈建议搭一个统一API网关。