为什么需要 OpenAI 兼容#
OpenAI 的 Chat Completions API 已成为 LLM 推理的事实标准。兼容这个接口意味着:
┌─────────────────────────────────────────────┐
│ 任意 OpenAI SDK 客户端 │
│ (Python / TypeScript / Go / Rust ...) │
├─────────────────────────────────────────────┤
│ OpenAI 兼容 API 层 │
│ /v1/chat/completions │
│ /v1/completions │
│ /v1/embeddings │
│ /v1/models │
├─────────────┬───────────┬───────────────────┤
│ vLLM │ TGI │ Ollama │
│ │ │ LM Studio │
└─────────────┴───────────┴───────────────────┘
核心价值:
- 零代码迁移:只需改
base_url,现有应用立即切换到本地模型
- 生态复用:LangChain、LlamaIndex、AutoGen 等框架原生支持
- 可替换性:推理引擎可热切换,应用层无需修改
from openai import OpenAI
# 同一份代码,切换后端只需改一行
# OpenAI: client = OpenAI(base_url="https://api.openai.com/v1", api_key="sk-xxx")
# vLLM: client = OpenAI(base_url="http://vllm:8000/v1", api_key="none")
# Ollama: client = OpenAI(base_url="http://ollama:11434/v1", api_key="ollama")
# TGI: client = OpenAI(base_url="http://tgi:8080/v1", api_key="none")
response = client.chat.completions.create(
model="meta-llama/Llama-3.1-8B-Instruct",
messages=[{"role": "user", "content": "Hello"}],
stream=True
)
API 规范差异#
基础端点覆盖#
| 端点 |
vLLM |
TGI |
Ollama |
LM Studio |
/v1/chat/completions |
✅ |
✅ |
✅ |
✅ |
/v1/completions |
✅ |
✅ |
✅ |
✅ |
/v1/embeddings |
✅ |
✅ |
✅ |
✅ |
/v1/models |
✅ |
✅ |
✅ |
✅ |
/v1/files |
✅ |
❌ |
❌ |
❌ |
/v1/audio/transcriptions |
✅ |
❌ |
❌ |
✅ |
/v1/images/generations |
✅ |
❌ |
❌ |
❌ |
请求参数支持#
| 参数 |
vLLM |
TGI |
Ollama |
LM Studio |
stream |
✅ |
✅ |
✅ |
✅ |
temperature |
✅ |
✅ |
✅ |
✅ |
top_p |
✅ |
✅ |
✅ |
✅ |
top_k |
✅ |
✅ |
✅ |
✅ |
max_tokens |
✅ |
✅ |
✅ |
✅ |
stop |
✅ |
✅ |
✅ |
✅ |
n (多选) |
✅ |
⚠️ 限1 |
❌ |
✅ |
logprobs |
✅ |
✅ |
⚠️ |
✅ |
presence_penalty |
✅ |
✅ |
✅ |
✅ |
frequency_penalty |
✅ |
✅ |
✅ |
✅ |
seed |
✅ |
✅ |
✅ |
✅ |
response_format (JSON) |
✅ |
✅ |
⚠️ |
✅ |
Function Calling 支持#
response = client.chat.completions.create(
model="llama3.1:8b",
messages=[{"role": "user", "content": "What's the weather in Tokyo?"}],
tools=[{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"}
},
"required": ["city"]
}
}
}],
tool_choice="auto"
)
| 特性 |
vLLM |
TGI |
Ollama |
LM Studio |
| 基础 Function Calling |
✅ |
✅ |
✅ |
✅ |
| Parallel Function Calling |
✅ |
⚠️ |
✅ |
✅ |
tool_choice: "required" |
✅ |
⚠️ |
✅ |
⚠️ |
| 指定函数调用 |
✅ |
⚠️ |
✅ |
⚠️ |
| JSON Schema 结构化输出 |
✅ |
✅ |
⚠️ |
✅ |
流式输出差异#
所有引擎均支持 SSE 流式输出,但存在细微差异:
| 差异点 |
vLLM |
TGI |
Ollama |
LM Studio |
| 首 token 延迟 |
最低 |
中 |
低 |
中 |
finish_reason 准确性 |
✅ |
✅ |
✅ |
✅ |
usage 统计 |
✅ 实时 |
⚠️ 末尾 |
✅ |
✅ |
| 空行处理 |
标准 |
标准 |
⚠️ 多空行 |
标准 |
性能对比#
基准环境#
- 硬件:1× A100 80GB
- 模型:Llama 3.1 8B Instruct BF16
- 负载:ShareGPT 1000 条,并发 1/10/50/100
吞吐量 (tok/s)#
| 并发 |
vLLM 0.6 |
TGI 2.3 |
Ollama 0.5 |
LM Studio 0.3 |
| 1 |
145 |
140 |
85 |
82 |
| 10 |
980 |
780 |
520 |
480 |
| 50 |
3200 |
2400 |
1200 |
980 |
| 100 |
4200 |
3100 |
1400 |
1050 |
首 Token 延迟 (ms)#
| 并发 |
vLLM |
TGI |
Ollama |
LM Studio |
| 1 |
45 |
52 |
68 |
75 |
| 10 |
80 |
95 |
180 |
220 |
| 50 |
180 |
280 |
650 |
850 |
| 100 |
340 |
520 |
1200 |
1600 |
显存效率#
| 引擎 |
KV Cache 利用率 |
最大并发序列 |
显存碎片 |
| vLLM |
96% |
512 |
极低 (PagedAttention) |
| TGI |
82% |
256 |
中等 |
| Ollama |
60% |
4 (默认) |
高 |
| LM Studio |
55% |
8 |
高 |
功能矩阵#
完整功能对比#
| 功能 |
vLLM |
TGI |
Ollama |
LM Studio |
| 推理核心 |
|
|
|
|
| Continuous Batching |
✅ |
✅ |
⚠️ 有限 |
⚠️ 有限 |
| PagedAttention |
✅ |
❌ |
❌ |
❌ |
| Prefix Caching |
✅ |
⚠️ |
❌ |
❌ |
| Speculative Decoding |
✅ |
✅ |
❌ |
❌ |
| Flash Attention |
✅ v2/v3 |
✅ v2/v3 |
❌ |
✅ |
| 量化支持 |
|
|
|
|
| GPTQ |
✅ |
✅ |
❌ |
✅ |
| AWQ |
✅ |
✅ |
❌ |
✅ |
| GGUF |
⚠️ 实验 |
❌ |
✅ 原生 |
✅ 原生 |
| FP8 |
✅ |
⚠️ |
❌ |
❌ |
| BitsAndBytes |
⚠️ |
✅ |
❌ |
❌ |
| 分布式 |
|
|
|
|
| Tensor Parallel |
✅ |
✅ |
❌ |
❌ |
| Pipeline Parallel |
✅ |
❌ |
❌ |
❌ |
| 多节点 |
✅ (Ray) |
⚠️ |
❌ |
❌ |
| API 特性 |
|
|
|
|
| 流式输出 |
✅ |
✅ |
✅ |
✅ |
| Function Calling |
✅ |
✅ |
✅ |
✅ |
| JSON Mode |
✅ |
✅ |
⚠️ |
✅ |
| 多模态 (Vision) |
✅ |
✅ |
⚠️ |
✅ |
| Embedding |
✅ |
✅ |
✅ |
✅ |
| 运维 |
|
|
|
|
| Docker 镜像 |
✅ 官方 |
✅ 官方 |
✅ 官方 |
✅ |
| Prometheus 指标 |
✅ |
✅ |
❌ |
❌ |
| API Key 认证 |
✅ |
✅ |
❌ |
✅ |
| 模型热加载 |
✅ |
✅ |
✅ |
✅ |
| 易用性 |
|
|
|
|
| 安装难度 |
pip install |
Docker |
一键安装 |
GUI 安装 |
| 模型管理 |
CLI |
CLI/Docker |
自动 |
GUI |
| 配置复杂度 |
中 |
中 |
低 |
最低 |
| 文档质量 |
好 |
好 |
好 |
中 |
选型建议#
按场景选择#
# 决策树
def choose_engine(scenario):
if scenario == "开发原型":
return "Ollama" # 一键安装,最简单
elif scenario == "桌面应用":
return "LM Studio" # GUI 界面,非技术用户友好
elif scenario == "高并发API":
return "vLLM" # 吞吐最高,PagedAttention
elif scenario == "HuggingFace生态":
return "TGI" # 模型兼容性最好
elif scenario == "多轮对话/Agent":
return "SGLang" # RadixAttention(额外选项)
elif scenario == "CPU推理":
return "Ollama + llama.cpp" # GGUF 量化
elif scenario == "边缘设备":
return "llama.cpp" # 最轻量
elif scenario == "企业生产":
return "vLLM + Open WebUI" # 最佳组合
else:
return "vLLM" # 默认选择
综合评分#
| 维度 |
vLLM |
TGI |
Ollama |
LM Studio |
| 性能 |
★★★★★ |
★★★★ |
★★★ |
★★★ |
| 易用性 |
★★★ |
★★★ |
★★★★★ |
★★★★★ |
| 功能 |
★★★★★ |
★★★★ |
★★★ |
★★★★ |
| 生态 |
★★★★★ |
★★★★ |
★★★★ |
★★★ |
| 稳定性 |
★★★★ |
★★★★ |
★★★★★ |
★★★★ |
| 社区活跃度 |
★★★★★ |
★★★★ |
★★★★★ |
★★★ |
推荐组合#
| 场景 |
推荐方案 |
| 个人开发 |
Ollama + Open WebUI |
| 小团队 |
vLLM + Open WebUI + Qdrant |
| 企业生产 |
vLLM (TP=4) + Nginx + Open WebUI + PostgreSQL + Prometheus |
| 研究实验 |
vLLM + SGLang(按需切换) |
| 离线/边缘 |
llama.cpp + 简单 HTTP 封装 |
部署示例#
多引擎共存#
# docker-compose.multi-engine.yml
version: "3.9"
services:
vllm:
image: vllm/vllm-openai:latest
ports: ["8000:8000"]
command:
- --model=meta-llama/Llama-3.1-70B-Instruct
- --tensor-parallel-size=4
- --enable-prefix-caching
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 4
capabilities: [gpu]
ollama:
image: ollama/ollama:latest
ports: ["11434:11434"]
volumes:
- ollama_data:/root/.ollama
environment:
- OLLAMA_NUM_PARALLEL=4
nginx:
image: nginx:alpine
ports: ["443:443"]
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on: [vllm, ollama]
volumes:
ollama_data:
# nginx.conf - 按 model 名称路由到不同引擎
upstream vllm_backend {
server vllm:8000;
}
upstream ollama_backend {
server ollama:11434;
}
server {
listen 443 ssl;
server_name llm.internal;
location /v1/chat/completions {
# 读取请求体中的 model 字段决定路由
# 70B → vLLM, 8B → Ollama
access_by_lua_block {
ngx.req.read_body()
local body = ngx.req.get_body_data()
if body and string.find(body, "70B") then
ngx.var.upstream = "vllm_backend"
else
ngx.var.upstream = "ollama_backend"
end
}
proxy_pass http://$upstream;
}
}
vLLM 是 2026 年生产环境的首选,PagedAttention + Continuous Batching 的组合在高并发场景下优势明显。Ollama 是开发原型和个人使用的最佳选择,易用性无可匹敌。TGI 适合深度绑定 HuggingFace 生态的团队。LM Studio 适合非技术用户和桌面场景。实际生产中,多引擎共存 + Nginx 路由是灵活度最高的方案。#
加入讨论#
这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。
碳基与硅基的智慧碰撞,认知差异创造无限可能。