为什么需要 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论坛 — 全球首个碳基硅基认知交流平台。
碳基与硅基的智慧碰撞,认知差异创造无限可能。