模型部署实战教程
一篇面向 AI 应用开发者的模型部署完整指南——从本地跑通到线上服务,手把手覆盖每一步。
一、为什么需要这篇教程
你大概率已经用过 OpenAI、Claude 或者通义千问的 API——传一个请求,拿回一段文本,非常方便。但当你开始认真做产品,几个现实问题会接踵而来:
- 成本:GPT-4 级别的 API 按 token 计费,日调用量上万次之后账单会变得很刺眼
- 隐私:客户数据不能发到第三方服务器,合规要求你必须自建
- 延迟:跨境调用 OpenAI API 动辄 2–5 秒,国内用户体验很差
- 可控性:闭源 API 随时可能涨价、限流、甚至下线模型
这时候,部署一个自己的开源模型就成了刚需。
1.1 教程定位与读者画像
这篇教程和《2.4 模型部署与推理》的区别在于:那篇是"地图",告诉你有哪些技术和方案;这篇是"导航",手把手带你跑通每一步。
你会在这篇教程里看到具体的命令、完整的代码、真实的截图,而不只是概念介绍。
适合你的前提:
- 有 Python 基础(能写 FastAPI 接口)
- 用过至少一个 LLM API(OpenAI / Claude / 通义千问 都算)
- 想部署开源模型(Qwen、LLaMA、DeepSeek 等),但还没跑通过
- Mac / Linux / Windows 任一系统都可以
不适合的情况:
- 你只是想调 API,不需要自己部署 → 直接用闭源 API 就好
- 你需要训练或微调模型 → 请看《2.3 模型微调》
1.2 本地 vs 线上:两条路线概览
本教程围绕两条主线展开,你可以根据自己的场景选择阅读路径:
路线一:本地部署
在你自己的电脑或公司内网服务器上运行模型。
- 适用场景:个人实验、本地开发调试、数据隐私要求高、内网环境
- 硬件要求:Mac(Apple Silicon)、Windows / Linux(NVIDIA 显卡最佳,CPU 也能跑)
- 代表方案:Ollama、LM Studio、llama.cpp、vLLM、Xinference
路线二:线上部署
把模型部署到云端,通过公网 API 对外提供服务。
- 适用场景:产品上线、多用户并发、没有本地 GPU、需要弹性扩缩容
- 两种子路线:
- Serverless 平台(零运维):硅基流动、Replicate、Modal
- GPU 云服务器自建(完全可控):AutoDL + vLLM、阿里云 PAI
两条路线并不互斥——最常见的工作流是:本地用 Ollama 开发调试,确认效果后切到云端 vLLM 上线。本教程第六章的实战项目就是这个流程。
开发流程推荐路径
═══════════════════════════════════════════════════════
本地 Ollama ──▶ 确认效果 ──▶ 云端 vLLM 上线
(快速迭代、零成本) (Prompt/参数调优) (高并发、稳定服务)
═══════════════════════════════════════════════════════1.3 前置准备(硬件检查、环境依赖)
在动手之前,花 2 分钟检查一下你的环境。
硬件自检:
| 你的设备 | 能跑什么 | 推荐方案 |
|---|---|---|
| Mac M1/M2/M3/M4(16 GB+) | 7B 模型流畅,14B 可用 | Ollama / LM Studio |
| Windows / Linux + RTX 3060(12 GB) | 7B 模型流畅 | Ollama / vLLM |
| Windows / Linux + RTX 4090(24 GB) | 14B 流畅,70B 量化后可用 | vLLM / Ollama |
| 纯 CPU(无独显) | 7B 量化模型(较慢但能用) | llama.cpp / Ollama |
| 云服务器 A100(80 GB) | 70B+ 模型 | vLLM |
💡 经验法则:模型参数量(十亿)× 0.5 ≈ 4-bit 量化后所需显存(GB)。比如 7B 模型约需 3.5 GB 显存,14B 约需 7 GB。
软件依赖:
# 确认 Python 版本(推荐 3.10+)
python3 --version
# 确认 pip 可用
pip3 --version
# 如果有 NVIDIA 显卡,确认 CUDA 环境
nvidia-smi # 应显示驱动版本和 GPU 信息如果你用 Mac,不需要额外安装 CUDA——Ollama 和 llama.cpp 会自动使用 Metal 加速。
准备就绪,接下来我们从最简单的本地方案开始。
二、本地部署方案
本地部署的核心价值:零成本、零延迟、完全隐私。从个人实验到团队内网服务,这一章覆盖 6 个主流方案,由简到繁。
2.1 Ollama:最推荐的入门方案
Ollama 的设计哲学和 Docker 很像——一个命令下载模型,一个命令运行模型,自动提供 API 服务。如果你只看一个方案,看这个就够了。
安装:
# macOS / Linux:一行命令安装
curl -fsSL https://ollama.com/install.sh | sh
# Windows:从 https://ollama.com 下载安装包
# 验证安装
ollama --version运行模型:
# 下载并运行(首次会自动下载模型,后续直接启动)
ollama run qwen2.5:7b # Qwen 2.5 7B(推荐,中文能力强)
ollama run llama3.1:8b # LLaMA 3.1 8B
ollama run deepseek-r1:8b # DeepSeek-R1 蒸馏版(推理能力强)
ollama run gemma2:9b # Google Gemma 2 9B
# 查看已下载的模型
ollama list
# 删除不需要的模型
ollama rm llama3.1:8b运行后会进入交互式对话,直接在终端里和模型聊天。按 Ctrl+D 退出。
API 服务:
Ollama 启动后自动在 localhost:11434 提供 OpenAI 兼容的 API,无需额外配置:
# 确认服务正在运行
curl http://localhost:11434/api/tags
# 用 curl 测试对话接口
curl http://localhost:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen2.5:7b",
"messages": [{"role": "user", "content": "用一句话解释什么是 Docker"}]
}'# Python 调用(使用 openai 库,和调 OpenAI API 完全一样)
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:11434/v1",
api_key="ollama" # Ollama 不验证 key,随便填
)
response = client.chat.completions.create(
model="qwen2.5:7b",
messages=[{"role": "user", "content": "用 Python 实现快速排序"}]
)
print(response.choices[0].message.content)💡 因为 Ollama 兼容 OpenAI API 格式,你的应用代码几乎零改动就能在闭源 API 和本地模型之间切换——只需要改
base_url。
Modelfile:自定义模型:
Modelfile 类似 Dockerfile,用来创建预配置的模型:
# 文件名:Modelfile-reviewer
FROM qwen2.5:7b
SYSTEM "你是一个资深的 Python 代码审查专家。你只关注:1. 安全漏洞 2. 性能问题 3. 代码可维护性。对每个问题给出修复建议和代码示例。"
PARAMETER temperature 0.3
PARAMETER num_ctx 8192# 创建自定义模型
ollama create code-reviewer -f Modelfile-reviewer
# 运行自定义模型
ollama run code-reviewer这在 RAG 应用、Agent 开发中非常实用——你可以为不同任务创建不同的预配置模型,而不需要每次都塞一大段 System Prompt。
2.2 LM Studio:图形界面方案
如果你不想碰命令行,或者需要给非技术同事演示,LM Studio 是最好的选择。它提供了一个类似 ChatGPT 的桌面客户端,内置模型搜索、下载、对话、API 服务全部功能。
安装:从 lmstudio.ai 下载对应系统的安装包(支持 macOS / Windows / Linux),双击安装即可。
核心功能:
- 模型发现与下载:内置 Hugging Face 搜索,支持按模型大小、量化级别筛选。推荐搜索
GGUF格式的模型(如Qwen2.5-7B-Instruct-GGUF),下载速度比命令行快 - 聊天界面:和 ChatGPT 体验一致,支持多轮对话、System Prompt 配置、参数调节(温度、Top-P 等)
- 本地 API 服务器:一键开启 OpenAI 兼容的本地 API,默认端口
1234
启动 API 服务:
在 LM Studio 左侧栏点击「Local Server」→ 选择已下载的模型 → 点击「Start Server」。
# Python 调用 LM Studio 的 API
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:1234/v1",
api_key="lm-studio"
)
response = client.chat.completions.create(
model="qwen2.5-7b-instruct", # 模型名在 LM Studio 界面可以看到
messages=[{"role": "user", "content": "解释一下什么是向量数据库"}]
)
print(response.choices[0].message.content)LM Studio vs Ollama:
- LM Studio 胜在可视化体验——模型搜索、参数调节、对话测试都在 GUI 里完成
- Ollama 胜在自动化和集成——命令行操作更适合脚本化、CI/CD、Docker 容器
- 两者都提供 OpenAI 兼容 API,客户端代码可以无缝切换
2.3 llama.cpp + llama-cpp-python:CPU / Apple Silicon 极致方案
llama.cpp 是所有本地推理方案的"底层引擎"——Ollama 和 LM Studio 底层都在用它。直接使用 llama.cpp 的好处是:最大程度的控制权和最广泛的硬件支持。
它是唯一能让大模型在纯 CPU 环境下流畅运行的方案,同时也支持 CUDA(N 卡)、Metal(Mac)、Vulkan 等 GPU 加速后端。
安装方式一:用 Python 绑定(推荐)
如果你主要用 Python 开发,llama-cpp-python 是最方便的选择:
# 基础安装(CPU 推理)
pip install llama-cpp-python
# Mac 用户(启用 Metal GPU 加速)
CMAKE_ARGS="-DGGML_METAL=on" pip install llama-cpp-python
# NVIDIA 显卡用户(启用 CUDA 加速)
CMAKE_ARGS="-DGGML_CUDA=on" pip install llama-cpp-python下载 GGUF 模型:
llama.cpp 使用 GGUF 格式的模型文件。去 Hugging Face 搜索带 GGUF 标签的模型:
# 推荐用 huggingface-cli 下载
pip install huggingface_hub
huggingface-cli download Qwen/Qwen2.5-7B-Instruct-GGUF \
qwen2.5-7b-instruct-q4_k_m.gguf \
--local-dir ./models💡 量化等级选择:
Q4_K_M是最常用的平衡点——模型大小约为原始的 30%,质量损失几乎感知不到。Q8_0质量更高但更大,Q2_K最小但质量明显下降。
Python 调用:
from llama_cpp import Llama
# 加载模型
llm = Llama(
model_path="./models/qwen2.5-7b-instruct-q4_k_m.gguf",
n_ctx=8192, # 上下文长度
n_gpu_layers=-1, # -1 表示全部层都加载到 GPU(Mac Metal / CUDA)
verbose=False
)
# 对话
response = llm.create_chat_completion(
messages=[
{"role": "system", "content": "你是一个有帮助的助手。"},
{"role": "user", "content": "解释一下 GGUF 格式是什么"}
],
temperature=0.7,
max_tokens=512
)
print(response["choices"][0]["message"]["content"])也可以启动 OpenAI 兼容的 API 服务:
python -m llama_cpp.server \
--model ./models/qwen2.5-7b-instruct-q4_k_m.gguf \
--n_gpu_layers -1 \
--host 0.0.0.0 \
--port 8000启动后就可以用 openai 库调用 http://localhost:8000/v1,和 Ollama、LM Studio 的客户端代码完全通用。
什么时候选 llama.cpp 而不是 Ollama:
- 需要精确控制 GPU 层数分配(部分 GPU + 部分 CPU 的混合推理)
- 需要使用最新的 GGUF 模型(Ollama 的模型库更新有延迟)
- 需要嵌入到 C/C++ 项目中
- 需要在树莓派、嵌入式设备等极端环境运行
2.4 vLLM 本地部署:有 N 卡就上生产级
如果你的电脑或工作站有 NVIDIA 显卡(最好 12 GB 以上显存),vLLM 能给你本地最强的推理性能。它的核心技术 PagedAttention 让显存利用率远超其他方案,同样的硬件能跑更大的模型、服务更多的并发。
⚠️ vLLM 目前只支持 NVIDIA GPU(CUDA),Mac 和 AMD 显卡用户请用 Ollama 或 llama.cpp。
安装:
# 推荐在虚拟环境中安装
python -m venv vllm-env
source vllm-env/bin/activate
# 安装 vLLM(会自动安装 PyTorch + CUDA 依赖)
pip install vllm启动推理服务:
# 启动 OpenAI 兼容的 API 服务(模型会自动从 Hugging Face 下载)
vllm serve qwen/Qwen2.5-7B-Instruct \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 8192
# 如果有多张显卡,可以用张量并行
vllm serve qwen/Qwen2.5-7B-Instruct \
--tensor-parallel-size 2 \
--host 0.0.0.0 \
--port 8000客户端调用:
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="unused")
# 普通调用
response = client.chat.completions.create(
model="qwen/Qwen2.5-7B-Instruct",
messages=[{"role": "user", "content": "解释 PagedAttention 的原理"}]
)
print(response.choices[0].message.content)
# 流式调用
stream = client.chat.completions.create(
model="qwen/Qwen2.5-7B-Instruct",
messages=[{"role": "user", "content": "写一个 FastAPI 的 hello world"}],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)加载量化模型(节省显存):
# 加载 AWQ 量化模型(显存占用减半)
vllm serve Qwen/Qwen2.5-7B-Instruct-AWQ \
--quantization awq \
--max-model-len 8192
# 加载 GPTQ 量化模型
vllm serve Qwen/Qwen2.5-7B-Instruct-GPTQ-Int4 \
--quantization gptq \
--max-model-len 8192vLLM vs Ollama 本地对比:
| 维度 | vLLM | Ollama |
|---|---|---|
| 推理速度 | 更快(PagedAttention) | 够用 |
| 并发能力 | 强(Continuous Batching) | 默认单并发 |
| 显卡要求 | 必须 NVIDIA | 支持任意硬件 |
| 安装复杂度 | 较高(CUDA 依赖) | 极低 |
| 适用场景 | 本地高性能服务 | 个人实验、快速开发 |
2.5 Xinference:多模型统一管理平台
Xinference(Xorbits Inference)的独特价值在于:一个平台同时管理 LLM、Embedding 模型、Rerank 模型、图像模型。如果你在做 RAG 应用,需要同时跑对话模型 + 向量模型 + 重排模型,Xinference 比分别用三个工具方便得多。
安装与启动:
pip install "xinference[all]"
# 启动 Xinference 服务(默认端口 9997)
xinference-local --host 0.0.0.0 --port 9997启动后打开 http://localhost:9997,会看到一个 Web 管理界面——可以在浏览器里搜索、下载、启动模型。
通过 Web UI 部署模型:
- 打开
http://localhost:9997→ 点击「Launch Model」 - 选择模型类型(LLM / Embedding / Rerank)
- 选择具体模型(如
qwen2.5-instruct)和量化级别 - 点击部署,等待模型下载和加载
通过命令行部署:
# 部署 LLM
xinference launch \
--model-name qwen2.5-instruct \
--size-in-billions 7 \
--model-format ggufv2 \
--quantization q4_k_m
# 部署 Embedding 模型(RAG 用)
xinference launch \
--model-name bge-m3 \
--model-type embedding
# 部署 Rerank 模型(RAG 用)
xinference launch \
--model-name bge-reranker-v2-m3 \
--model-type rerankAPI 调用(兼容 OpenAI 格式):
from openai import OpenAI
client = OpenAI(base_url="http://localhost:9997/v1", api_key="xinference")
# 调用 LLM
response = client.chat.completions.create(
model="qwen2.5-instruct",
messages=[{"role": "user", "content": "什么是 RAG?"}]
)
# 调用 Embedding
embedding = client.embeddings.create(
model="bge-m3",
input="这是一段需要向量化的文本"
)适用场景:本地 RAG 全流程开发(LLM + Embedding + Rerank 一站式)、需要同时管理多个不同类型模型的团队。
2.6 LocalAI:OpenAI API 的本地替代
LocalAI 的目标很明确:做一个 OpenAI API 的完整本地替代品。它不仅支持对话补全,还支持 Embedding、TTS(语音合成)、STT(语音识别)、图像生成等 OpenAI API 的全部端点。
Docker 一键启动(推荐):
# 基础版(CPU)
docker run -p 8080:8080 --name local-ai \
-v ./models:/models \
localai/localai:latest
# GPU 版(NVIDIA)
docker run -p 8080:8080 --gpus all --name local-ai \
-v ./models:/models \
localai/localai:latest-gpu-nvidia-cuda-12启动后打开 http://localhost:8080,会看到一个模型管理界面。可以从内置的模型库一键安装模型,也可以手动放入 GGUF 文件。
API 调用(完全兼容 OpenAI 格式):
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8080/v1", api_key="local-ai")
# 对话
response = client.chat.completions.create(
model="qwen2.5-7b-instruct",
messages=[{"role": "user", "content": "你好"}]
)
# Embedding(如果安装了 Embedding 模型)
embedding = client.embeddings.create(
model="text-embedding-ada-002", # LocalAI 可以用兼容的模型名
input="需要向量化的文本"
)什么时候选 LocalAI:
- 你的项目大量使用 OpenAI SDK,想要一个 drop-in 的本地替代(连模型名都可以保持一致)
- 需要一个 Docker 容器内集成多种 AI 能力(对话 + Embedding + TTS)
- 偏好容器化部署,不想在宿主机安装依赖
2.7 本地方案横向对比与选型建议
六个方案各有侧重,一张表帮你快速决策:
| 方案 | 上手难度 | 硬件要求 | 推理性能 | 多模型管理 | API 兼容 | 最佳场景 |
|---|---|---|---|---|---|---|
| Ollama | ⭐ 极低 | 任意 | ★★★ | 基础 | OpenAI | 个人开发、快速实验 |
| LM Studio | ⭐ 极低 | 任意 | ★★★ | GUI 管理 | OpenAI | 非技术人员、演示 |
| llama.cpp | ⭐⭐⭐ 中 | 任意(CPU 友好) | ★★★★ | 无 | OpenAI | 极致控制、嵌入式 |
| vLLM | ⭐⭐⭐ 中 | NVIDIA GPU | ★★★★★ | 无 | OpenAI | 高并发本地服务 |
| Xinference | ⭐⭐ 低 | 任意 | ★★★ | 强(多类型) | OpenAI | RAG 全流程、多模型 |
| LocalAI | ⭐⭐ 低 | 任意 | ★★★ | Docker 内置 | OpenAI(全端点) | OpenAI 完整替代 |
快速选型指南:
你的场景是什么?
│
├── 个人实验 / 学习 ──────────────▶ Ollama(最省心)
│
├── 给非技术人员演示 ────────────▶ LM Studio(有 GUI)
│
├── Mac 开发 / CPU 服务器 ──────▶ Ollama 或 llama.cpp
│
├── 有 N 卡,要高并发 ──────────▶ vLLM
│
├── RAG 应用(LLM + Embedding)──▶ Xinference
│
└── Docker 部署,要完整 API ────▶ LocalAI💡 务实建议:如果你不确定选哪个,从 Ollama 开始。它能覆盖 80% 的本地使用场景,等你遇到了它解决不了的问题(比如需要更高并发、需要多模型管理),再切换到对应的方案。
2.8 本地模型接入应用(Python / JS 客户端调用示例)
因为上面所有方案都兼容 OpenAI API 格式,你可以写一个通用的客户端封装,通过配置切换不同的后端:
Python 通用封装:
from openai import OpenAI
# 只需要改这两行,就能切换不同的本地后端
CONFIGS = {
"ollama": {"base_url": "http://localhost:11434/v1", "model": "qwen2.5:7b"},
"lm_studio": {"base_url": "http://localhost:1234/v1", "model": "qwen2.5-7b-instruct"},
"vllm": {"base_url": "http://localhost:8000/v1", "model": "qwen/Qwen2.5-7B-Instruct"},
"xinference": {"base_url": "http://localhost:9997/v1", "model": "qwen2.5-instruct"},
"localai": {"base_url": "http://localhost:8080/v1", "model": "qwen2.5-7b-instruct"},
}
def get_client(backend: str = "ollama"):
config = CONFIGS[backend]
client = OpenAI(base_url=config["base_url"], api_key="local")
return client, config["model"]
# 使用
client, model = get_client("ollama") # 切换后端只需改这里
response = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": "你好"}]
)
print(response.choices[0].message.content)JavaScript(前端 fetch 调用):
// 前端直接调用本地 API(开发环境)
async function chat(message, baseUrl = "http://localhost:11434") {
const response = await fetch(`${baseUrl}/v1/chat/completions`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
model: "qwen2.5:7b",
messages: [{ role: "user", content: message }],
stream: true,
}),
});
// 处理流式输出
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split("\n").filter((line) => line.startsWith("data: "));
for (const line of lines) {
const data = line.slice(6); // 去掉 "data: " 前缀
if (data === "[DONE]") return;
const parsed = JSON.parse(data);
const content = parsed.choices[0]?.delta?.content;
if (content) process.stdout.write(content); // 或更新 DOM
}
}
}💡 这就是 OpenAI 兼容 API 的最大好处:你的应用代码和底层推理引擎完全解耦。开发时用 Ollama,上线时切 vLLM,甚至回退到 OpenAI API——只需要改一个 URL。
三、线上部署方案(一):Serverless 推理平台
线上部署的第一条路线:把推理交给平台,你只管调 API。不需要选机器、装驱动、管容器,按调用量付费,适合快速上线和流量不稳定的场景。
3.1 什么时候选 Serverless
Serverless 推理平台的本质是:别人帮你把 vLLM / TGI 搭好了,你直接用。
适合选 Serverless 的情况:
- 快速验证:产品还在 MVP 阶段,不确定有没有人用,不值得花时间搭基础设施
- 流量波动大:白天高峰、晚上没人,Serverless 自动扩缩容,不用为闲置 GPU 付费
- 没有运维能力:团队没有 GPU 服务器管理经验,不想踩 CUDA 驱动的坑
- 合规要求:国内业务选国内平台(硅基流动、火山引擎),避免数据出境问题
不适合的情况:
- 持续高并发:如果 GPU 需要 7×24 跑满,自建比 Serverless 便宜得多
- 极致延迟要求:Serverless 平台可能有冷启动延迟(首次请求慢 5–30 秒)
- 自定义模型:大多数平台只支持热门开源模型,微调过的私有模型需要自建
成本粗算
═══════════════════════════════════════════════════
场景:7B 模型,日均 1 万次请求,每次 ~500 token
Serverless(硅基流动):约 ¥50–100/天
自建(AutoDL A10):约 ¥30–50/天(含闲置时间)
自建(自有 4090):约 ¥5/天(电费)
结论:日请求 < 5000 次时 Serverless 更划算
日请求 > 10000 次时自建开始有优势
═══════════════════════════════════════════════════3.2 硅基流动:国内首选(注册→部署→调用全流程)
硅基流动(SiliconFlow)是目前国内最受开发者欢迎的 Serverless 推理平台,模型丰富、价格低、兼容 OpenAI API 格式。新用户还有免费额度可以体验。
Step 1:注册与获取 API Key
- 打开 siliconflow.cn,注册账号
- 进入控制台 → 「API 密钥」→ 创建新密钥
- 复制 API Key,保存好(只显示一次)
Step 2:查看可用模型
硅基流动支持主流开源模型,常用的包括:
| 模型 | 模型 ID | 适用场景 |
|---|---|---|
| Qwen2.5-7B | Qwen/Qwen2.5-7B-Instruct | 通用对话、中文任务 |
| Qwen2.5-72B | Qwen/Qwen2.5-72B-Instruct | 复杂推理、高质量生成 |
| DeepSeek-R1 | deepseek-ai/DeepSeek-R1 | 强推理、数学、代码 |
| GLM-4-9B | THUDM/glm-4-9b-chat | 通用对话 |
💡 平台会持续更新模型列表,最新支持的模型以官网为准。部分小模型(如 Qwen2.5-7B)有永久免费额度。
Step 3:Python 调用
from openai import OpenAI
client = OpenAI(
base_url="https://api.siliconflow.cn/v1",
api_key="sk-xxxxxxxxxxxxx" # 替换为你的 API Key
)
# 普通调用
response = client.chat.completions.create(
model="Qwen/Qwen2.5-7B-Instruct",
messages=[
{"role": "system", "content": "你是一个专业的技术文档写手。"},
{"role": "user", "content": "用 200 字解释什么是 RAG"}
],
temperature=0.7,
max_tokens=1024
)
print(response.choices[0].message.content)
# 流式调用
stream = client.chat.completions.create(
model="Qwen/Qwen2.5-7B-Instruct",
messages=[{"role": "user", "content": "写一个 Python 装饰器教程"}],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)Step 4:调用 Embedding 模型(RAG 场景)
# 硅基流动也支持 Embedding 模型
embedding = client.embeddings.create(
model="BAAI/bge-m3",
input="这段文本需要转成向量"
)
print(f"向量维度:{len(embedding.data[0].embedding)}")计费说明:按 token 计费,不同模型价格不同。7B 模型约 ¥0.5/百万 token,72B 模型约 ¥4/百万 token。新用户有免费额度,小模型部分请求永久免费。
💡 从本地切到硅基流动只需要改两行:把
base_url从http://localhost:11434/v1改成https://api.siliconflow.cn/v1,把api_key填上真实的 Key。其他代码完全不用动。
3.3 Replicate / Modal:海外方案
如果你的用户主要在海外,或者需要用一些国内平台还没上架的模型,两个海外平台值得了解。
Replicate
Replicate 的特色是"一行代码跑模型",模型生态非常丰富(不只是 LLM,还有图像、音频、视频模型)。
import replicate
# 安装:pip install replicate
# 设置环境变量:export REPLICATE_API_TOKEN=r8_xxxxx
output = replicate.run(
"meta/llama-2-70b-chat",
input={
"prompt": "Explain quantum computing in simple terms",
"max_tokens": 500,
"temperature": 0.7
}
)
# output 是一个生成器,逐 token 返回
for token in output:
print(token, end="", flush=True)- 按秒计费,冷启动优化较好(通常 2–5 秒)
- 支持自定义 Docker 镜像部署私有模型
- 官网:replicate.com
Modal
Modal 更偏向"Serverless GPU 计算平台"——你可以把任意 Python 函数部署成 GPU 服务,不限于 LLM 推理。
import modal
# 定义一个 GPU 函数
app = modal.App("my-llm-service")
@app.function(gpu="A10G", image=modal.Image.debian_slim().pip_install("vllm"))
def generate(prompt: str):
from vllm import LLM, SamplingParams
llm = LLM(model="Qwen/Qwen2.5-7B-Instruct")
outputs = llm.generate([prompt], SamplingParams(temperature=0.7, max_tokens=512))
return outputs[0].outputs[0].text
# 本地调用远程 GPU 函数
with app.run():
result = generate.remote("What is RAG?")
print(result)- 按 GPU 秒计费,支持 A10G / A100 / H100
- 可以将 vLLM 直接部署为 Serverless 端点
- 冷启动可配置预热策略(keep-warm)
- 官网:modal.com
海外平台 vs 国内平台:
| 维度 | 硅基流动 | Replicate | Modal |
|---|---|---|---|
| 国内访问速度 | 快 | 慢(需代理) | 慢(需代理) |
| 中文模型支持 | 丰富 | 较少 | 自己部署 |
| 计费方式 | 按 token | 按秒 | 按 GPU 秒 |
| 灵活性 | 只能用平台模型 | 可自定义 | 完全自定义 |
| 适用场景 | 国内业务 | 海外业务、多模态 | 自定义推理逻辑 |
3.4 Hugging Face Inference Endpoints
Hugging Face 的 Inference Endpoints 是一个"独占实例"方案——你选一个模型,HF 帮你在云端启一台 GPU 机器跑起来,按小时计费。
和前面的 Serverless 平台不同,它不是按请求计费,而是按运行时间计费。适合需要稳定在线服务、但不想自己管服务器的场景。
创建步骤:
- 打开 huggingface.co/inference-endpoints
- 点击「Create Endpoint」
- 选择模型(可以是 HF Hub 上任意公开模型,也可以是你的私有模型)
- 选择 GPU 类型和区域(如 AWS us-east-1 / A10G)
- 点击创建,等待部署(通常 2–5 分钟)
API 调用:
from openai import OpenAI
# Endpoint URL 在 HF 控制台可以看到
client = OpenAI(
base_url="https://xxxxx.endpoints.huggingface.cloud/v1",
api_key="hf_xxxxxxxxxxxxx" # Hugging Face Token
)
response = client.chat.completions.create(
model="tgi", # HF Endpoints 默认模型名
messages=[{"role": "user", "content": "What is transfer learning?"}],
max_tokens=512
)
print(response.choices[0].message.content)优缺点:
- ✅ 支持 HF Hub 上任意模型(包括你微调后上传的私有模型)
- ✅ 底层用 TGI,性能有保障
- ✅ 支持自动扩缩容(Scale-to-zero:没请求时自动关机,省钱)
- ❌ 价格较贵(A10G 约 $1.3/小时,A100 约 $6.5/小时)
- ❌ 服务器在海外,国内访问延迟高
适用场景:你有微调过的私有模型上传在 HF Hub,需要快速部署一个稳定的推理端点,且用户主要在海外。
四、线上部署方案(二):GPU 云服务器自建
线上部署的第二条路线:租一台有 GPU 的云服务器,自己搭推理服务。完全可控,适合有稳定流量且需要定制化的场景。
4.1 什么时候选自建
自建意味着你要自己处理环境安装、服务启动、监控告警、扩缩容等运维工作。这些事并不轻松,所以先确认你是否真的需要自建:
值得自建的情况:
- 持续高并发:GPU 需要 7×24 跑满,此时自建比 Serverless 平台便宜 50%+
- 私有模型:微调过的模型不想上传到第三方平台,需要完全掌控
- 定制化需求:需要特殊的推理参数、自定义的前后处理逻辑、LoRA 动态加载等
- 内网部署:企业安全要求服务不能暴露在公网,需要部署在公司内网或 VPC
不值得自建的情况:
- 日请求量 < 5000 次 → Serverless 更省钱省心
- 团队没人懂 Linux / Docker / CUDA → 运维成本远超你的预期
- 产品还在验证阶段 → 先用 API 跑通,确认有需求再自建
💡 经验之谈:很多团队在产品上线前就花了两周搭 GPU 服务,结果上线后发现没人用。先用闭源 API / Serverless 验证需求,再自建,能避免大量资源浪费。
4.2 GPU 云平台选型(AutoDL / 阿里云 / RunPod)
主流 GPU 云平台对比:
| 平台 | 定位 | GPU 选择 | 价格参考 | 优势 | 劣势 |
|---|---|---|---|---|---|
| AutoDL | 国内个人/中小团队 | RTX 4090 / A100 / A800 | 4090: ~¥2/时, A100: ~¥6/时 | 性价比极高、镜像丰富、社区活跃 | 企业级功能偏弱 |
| 阿里云 PAI | 国内企业级 | A10 / A100 / GU系列 | A10: ~¥15/时 | 完整 MLOps 工具链、SLA 保障 | 贵、配置复杂 |
| RunPod | 海外开发者 | A100 / H100 | A100: ~$1.5/时 | H100 货源充足、按秒计费 | 国内访问需代理 |
| Lambda Cloud | 海外团队 | A100 / H100 | H100: ~$2.5/时 | 开发者友好、预装 ML 环境 | 库存紧张 |
推荐策略:
- 个人开发者 / 学习:AutoDL(国内性价比最高,最低几毛钱一小时)
- 国内企业生产:阿里云 PAI / 腾讯云 TI(有 SLA,合规可控)
- 海外业务:RunPod / Lambda(H100 资源好找)
以下实操以 AutoDL 为例,因为它最适合从零开始学习部署。
4.3 vLLM 部署全流程(AutoDL 实操)
以下是在 AutoDL 上从零部署 vLLM 推理服务的完整步骤。
Step 1:创建 GPU 实例
- 注册并登录 autodl.com
- 点击「容器实例」→「创建实例」
- 选择配置:
- GPU:RTX 4090(24 GB)够跑 7B 模型,A100(80 GB)可跑 70B
- 镜像:选择
PyTorch 2.1+CUDA 12.1+Python 3.10的官方镜像 - 系统盘:30 GB(默认够用)
- 数据盘:50 GB+(存模型用,7B 模型约占 15 GB)
- 点击创建,等待实例启动(通常 1–3 分钟)
Step 2:SSH 登录与环境配置
# 在 AutoDL 控制台复制 SSH 登录命令
ssh -p <port> root@<host>
# 确认 GPU 可用
nvidia-smi
# 创建虚拟环境并安装 vLLM
python -m venv /root/vllm-env
source /root/vllm-env/bin/activate
pip install vllmStep 3:下载模型
AutoDL 有 Hugging Face 镜像加速,下载速度很快:
# 方法一:vLLM 启动时自动下载(推荐)
# 设置 HF 镜像(AutoDL 通常已配置)
export HF_ENDPOINT=https://hf-mirror.com
# 方法二:手动提前下载
pip install huggingface_hub
huggingface-cli download Qwen/Qwen2.5-7B-Instruct \
--local-dir /root/models/Qwen2.5-7B-InstructStep 4:启动 vLLM 服务
# 基础启动
vllm serve Qwen/Qwen2.5-7B-Instruct \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 8192 \
--gpu-memory-utilization 0.9
# 如果用了本地下载的模型
vllm serve /root/models/Qwen2.5-7B-Instruct \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 8192
# 后台运行(推荐,断开 SSH 后服务不中断)
nohup vllm serve Qwen/Qwen2.5-7B-Instruct \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 8192 \
--gpu-memory-utilization 0.9 \
> /root/vllm.log 2>&1 &
# 查看日志
tail -f /root/vllm.logStep 5:验证服务
# 在服务器上测试
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-7B-Instruct",
"messages": [{"role": "user", "content": "你好,自我介绍一下"}],
"max_tokens": 100
}'Step 6:开放外网访问
AutoDL 支持自定义服务端口映射:
- 在 AutoDL 控制台 → 实例详情 → 「自定义服务」
- 开放 8000 端口,获得一个公网 URL(如
https://u-xxxxx-8000.westc.gpuhub.com) - 在本地用这个 URL 调用:
from openai import OpenAI
client = OpenAI(
base_url="https://u-xxxxx-8000.westc.gpuhub.com/v1", # AutoDL 公网 URL
api_key="unused"
)
response = client.chat.completions.create(
model="Qwen/Qwen2.5-7B-Instruct",
messages=[{"role": "user", "content": "AutoDL 部署成功了吗?"}]
)
print(response.choices[0].message.content)⚠️ AutoDL 的自定义服务 URL 是临时的,每次重启实例可能会变。生产环境建议用固定 IP + 域名。
4.4 TGI Docker 部署(备选方案)
如果你更熟悉 Docker 部署,或者对 Hugging Face 生态有偏好,TGI(Text Generation Inference)是一个稳定的选择。它是 Hugging Face 官方维护的推理服务,很多云厂商的推理服务底层就是 TGI。
Docker 一键启动:
# 拉取并启动 TGI 容器(NVIDIA GPU)
docker run --gpus all -d \
--name tgi \
-p 8000:80 \
-v /root/models:/data \
-e HF_TOKEN=hf_xxxxx \
ghcr.io/huggingface/text-generation-inference:latest \
--model-id Qwen/Qwen2.5-7B-Instruct \
--max-input-tokens 4096 \
--max-total-tokens 8192
# 查看启动日志(等待模型加载完成)
docker logs -f tgiAPI 调用(兼容 OpenAI 格式):
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="unused")
response = client.chat.completions.create(
model="Qwen/Qwen2.5-7B-Instruct",
messages=[{"role": "user", "content": "TGI 和 vLLM 有什么区别?"}],
max_tokens=512
)
print(response.choices[0].message.content)TGI vs vLLM 怎么选:
| 维度 | TGI | vLLM |
|---|---|---|
| 部署方式 | Docker 一键启动 | pip install + 命令行 |
| 极端吞吐 | 略低 | 更高(PagedAttention) |
| HF 生态集成 | 原生支持 | 需手动配置 |
| 社区活跃度 | 中等 | 非常活跃 |
| 推荐场景 | Docker 运维、HF 生态 | 追求极致性能 |
简单总结:追求性能选 vLLM,追求简单选 TGI。
4.5 生产化配套(Nginx 反代、HTTPS、监控)
vLLM / TGI 跑起来只是第一步。要给真实用户提供稳定服务,还需要几个工程化配套。
Nginx 反向代理:
vLLM 直接暴露在公网不安全也不专业。用 Nginx 反代可以实现:域名绑定、SSL 证书、请求限流、负载均衡。
# /etc/nginx/sites-available/llm-api
server {
listen 80;
server_name api.yourdomain.com;
# 限制请求体大小(防止超大 prompt 打崩服务)
client_max_body_size 10m;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# 流式输出必须关闭缓冲
proxy_buffering off;
proxy_cache off;
# 长连接超时(大模型生成可能需要较长时间)
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
}# 启用配置并重载 Nginx
sudo ln -s /etc/nginx/sites-available/llm-api /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginxHTTPS 证书(Let's Encrypt 免费证书):
# 安装 Certbot
sudo apt install certbot python3-certbot-nginx
# 自动配置 HTTPS
sudo certbot --nginx -d api.yourdomain.com
# 证书会自动续期,无需手动管理健康检查脚本:
#!/bin/bash
# healthcheck.sh - 定时检查 vLLM 服务状态
ENDPOINT="http://localhost:8000/health"
ALERT_WEBHOOK="https://your-webhook-url" # 企业微信/钉钉/Slack webhook
if ! curl -sf "$ENDPOINT" > /dev/null 2>&1; then
echo "[$(date)] vLLM 服务异常,尝试重启..."
# 重启 vLLM
pkill -f "vllm serve"
sleep 5
nohup vllm serve Qwen/Qwen2.5-7B-Instruct \
--host 0.0.0.0 --port 8000 \
--max-model-len 8192 \
> /root/vllm.log 2>&1 &
# 发送告警
curl -s "$ALERT_WEBHOOK" \
-H "Content-Type: application/json" \
-d '{"content": "⚠️ vLLM 服务异常已自动重启"}'
fi# 添加到 crontab,每分钟检查一次
echo "* * * * * /root/healthcheck.sh" | crontab -基础监控指标:
vLLM 内置了 Prometheus 指标端点(/metrics),可以对接 Grafana 监控面板:
vllm:num_requests_running— 当前正在处理的请求数vllm:num_requests_waiting— 等待队列长度vllm:gpu_cache_usage_perc— GPU KV Cache 使用率vllm:avg_generation_throughput_toks_per_s— 平均生成吞吐(tokens/秒)
💡 对于中小规模部署,健康检查脚本 + 日志监控就够了。上了多台 GPU 服务器之后,再考虑 Prometheus + Grafana 的完整监控方案。
五、推理性能优化
模型能跑只是及格线。要在有限的硬件上服务更多用户、降低每次请求的成本,需要掌握几个关键的优化技术。这一章不深入数学原理,只讲你需要做什么决策、怎么配置。
5.1 量化方案选型指南(GGUF / GPTQ / AWQ)
量化的本质:把模型权重从高精度(FP16,每个参数占 2 字节)压缩到低精度(INT4,每个参数占 0.5 字节),用微小的质量损失换取显存减半、速度翻倍。
三大量化格式对比:
| 格式 | 量化方式 | 适用后端 | 精度保持 | 推理速度 | 适用场景 |
|---|---|---|---|---|---|
| GGUF | 离线量化,多种量化级别 | llama.cpp / Ollama / LM Studio | ★★★ | ★★★★ | CPU / Mac / 边缘设备 |
| GPTQ | 离线量化,基于校准数据 | vLLM / TGI / Transformers | ★★★★ | ★★★★ | GPU 推理(生产环境) |
| AWQ | 激活感知量化 | vLLM / TGI | ★★★★★ | ★★★★★ | GPU 推理(推荐首选) |
GGUF 量化级别详解:
GGUF 格式有多种量化级别,名字看起来很晦涩,其实逻辑很简单:
| 量化级别 | 大小(7B 模型) | 质量 | 推荐度 |
|---|---|---|---|
Q2_K | ~2.7 GB | 明显下降 | 仅内存极有限时 |
Q3_K_M | ~3.3 GB | 可接受 | 内存紧张的折中 |
Q4_K_M | ~4.1 GB | 几乎无损 | ⭐ 最推荐 |
Q5_K_M | ~4.8 GB | 非常接近原始 | 追求质量 |
Q6_K | ~5.5 GB | 接近 FP16 | 内存充裕时 |
Q8_0 | ~7.2 GB | 几乎等于 FP16 | 不差内存的首选 |
💡 记住一个就行:
Q4_K_M。它是社区公认的最佳性价比量化级别——模型大小缩小到原始的 ~30%,质量损失在大多数任务上感知不到。
选型决策:
你用什么硬件?
│
├── Mac / CPU / 边缘设备 ──▶ GGUF(Q4_K_M)
│
├── NVIDIA GPU(vLLM 部署)
│ ├── 追求质量 ──────────▶ AWQ(推荐)
│ └── 模型只有 GPTQ 版本 ▶ GPTQ
│
└── 不确定 ────────────────▶ GGUF(通用性最好)5.2 vLLM 调优参数详解
vLLM 启动时有很多参数可以调,但大多数情况下默认值就够了。这里只列出你最可能需要调整的参数:
显存与模型相关:
vllm serve Qwen/Qwen2.5-7B-Instruct \
--max-model-len 8192 \ # 最大上下文长度(越长越耗显存)
--gpu-memory-utilization 0.9 \ # GPU 显存使用比例(默认 0.9)
--enforce-eager \ # 禁用 CUDA Graph(调试用,牺牲速度换稳定性)
--dtype auto # 数据类型,auto 会自动选择| 参数 | 默认值 | 调优建议 |
|---|---|---|
--max-model-len | 模型最大长度 | 设为你实际需要的长度。8192 够大多数场景。设太大会浪费显存 |
--gpu-memory-utilization | 0.9 | 显存紧张时调到 0.95,但可能导致 OOM。留 10% 余量更稳 |
--dtype | auto | 一般不用改。A100 用 bfloat16,其他卡用 float16 |
并发与吞吐相关:
vllm serve Qwen/Qwen2.5-7B-Instruct \
--max-num-seqs 256 \ # 最大并发序列数
--max-num-batched-tokens 8192 \ # 每个批次最大 token 数
--swap-space 4 # CPU 交换空间(GB),显存不够时用| 参数 | 默认值 | 调优建议 |
|---|---|---|
--max-num-seqs | 256 | 并发数上限。显存紧张时调小(如 64),能提高稳定性 |
--swap-space | 4 | 当并发请求的 KV Cache 超出显存时,交换到 CPU 内存。设为 0 可禁用 |
多卡与量化:
# 双卡张量并行
vllm serve Qwen/Qwen2.5-72B-Instruct \
--tensor-parallel-size 2
# 加载 AWQ 量化模型
vllm serve Qwen/Qwen2.5-7B-Instruct-AWQ \
--quantization awq
# 启用 KV Cache 量化(实验性功能,减少显存占用)
vllm serve Qwen/Qwen2.5-7B-Instruct \
--kv-cache-dtype fp8一个实用的生产配置模板:
# 适用于单卡 RTX 4090(24 GB)跑 7B 模型的推荐配置
vllm serve Qwen/Qwen2.5-7B-Instruct \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 8192 \
--gpu-memory-utilization 0.9 \
--max-num-seqs 64 \
--swap-space 4 \
--disable-log-requests # 生产环境关闭请求日志,减少 I/O 开销5.3 成本与性能的平衡策略
部署优化不是"越快越好",而是在预算、质量、速度三者之间找到适合你的平衡点。
策略一:模型大小选择
不要盲目追求大模型。在很多任务上,7B 模型 + 好的 Prompt 可以达到 70B 模型 80%+ 的效果,但成本只有 1/10。
| 模型规模 | 典型显存(FP16) | 典型显存(4-bit) | 适用场景 |
|---|---|---|---|
| 1.5B–3B | 3–6 GB | 1–2 GB | 简单分类、提取、格式化 |
| 7B–9B | 14–18 GB | 4–5 GB | 通用对话、代码辅助、客服 |
| 14B–32B | 28–64 GB | 8–18 GB | 复杂推理、专业领域 |
| 70B+ | 140+ GB | 35+ GB | 最高质量要求、多卡部署 |
💡 务实建议:先用 7B 量化模型跑通,测试质量是否满足需求。不够再升级到 14B 或 70B,而不是一上来就部署最大的。
策略二:请求路由(大小模型搭配)
对不同复杂度的请求用不同模型处理:
用户请求 ──▶ 路由判断
│
├── 简单问题(FAQ、格式化)──▶ 7B 模型(便宜、快)
│
└── 复杂问题(推理、创作)──▶ 70B 模型或闭源 API这种模式可以让 80% 的请求由低成本模型处理,只在真正需要时调用大模型,综合成本降低 60%+。
策略三:缓存常见响应
如果你的应用有很多重复或相似的查询(比如客服场景),可以缓存模型的响应:
- 精确匹配缓存:相同输入直接返回缓存结果
- 语义缓存:用 Embedding 计算相似度,相似问题返回缓存结果(GPTCache 等方案)
缓存命中率达到 30% 就能显著降低 GPU 成本。
策略四:按需启停
如果流量有明显的高低峰:
- AutoDL:使用"无卡模式"——低峰期释放 GPU 只保留数据盘,高峰期恢复(每小时只收几毛钱存储费)
- 云服务器:结合 Serverless 平台,低峰期用 Serverless(按量付费),高峰期用自建服务器
- HF Endpoints:启用 Scale-to-zero,没有请求时自动关机
综合成本参考(7B 模型,日均 1 万次请求):
方案对比(月成本估算)
═══════════════════════════════════════════
闭源 API(GPT-4o-mini) : ¥300–600/月
硅基流动 Serverless : ¥150–300/月
AutoDL 4090 按需 : ¥500–1000/月(不间断)
AutoDL 4090 按需 + 无卡模式 : ¥200–400/月(白天开机)
自有 4090 : ¥100–150/月(电费)
═══════════════════════════════════════════六、端到端实战项目
前面五章讲的都是单个技术点。这一章把它们串起来——从本地开发到线上部署,完成一个可以真正给人用的对话 API 服务。
6.1 项目目标与架构设计
我们要做什么:
搭建一个基于 Qwen2.5-7B 的智能对话 API,支持:
- 多轮对话(带上下文记忆)
- 流式输出(逐 token 返回)
- System Prompt 自定义
- 本地和线上两套部署方案
技术栈:
- 模型:Qwen2.5-7B-Instruct
- 本地推理:Ollama
- 线上推理:vLLM(AutoDL)
- API 层:FastAPI
- 前端:原生 HTML + JavaScript(演示用)
架构图:
开发环境(本地) 生产环境(云端)
════════════════ ════════════════
┌──────────┐ ┌──────────┐
│ 前端页面 │◀── HTTP/SSE ──▶ │ 前端页面 │
└────┬─────┘ └────┬─────┘
│ │
▼ ▼
┌──────────┐ ┌──────────┐
│ FastAPI │ │ Nginx │
│ (API 层) │ │ (反向代理)│
└────┬─────┘ └────┬─────┘
│ │
▼ ▼
┌──────────┐ ┌──────────┐
│ Ollama │ │ vLLM │
│(localhost)│ │ (GPU 服务)│
└──────────┘ └──────────┘关键设计决策:
FastAPI 作为中间层的价值在于:业务逻辑和推理引擎解耦。切换后端(Ollama → vLLM → 闭源 API)只需改一行配置,前端代码和 API 接口完全不变。
6.2 本地开发阶段(Ollama + FastAPI)
Step 1:确保 Ollama 运行
# 下载模型(如果还没下载)
ollama pull qwen2.5:7b
# 确认服务在跑
curl http://localhost:11434/api/tagsStep 2:创建项目结构
mkdir llm-chat-api && cd llm-chat-api
python -m venv .venv
source .venv/bin/activate
pip install fastapi uvicorn openai python-dotenvllm-chat-api/
├── .env # 环境配置
├── main.py # FastAPI 主文件
└── static/
└── index.html # 前端页面(6.4 编写)Step 3:编写环境配置
# .env
LLM_BASE_URL=http://localhost:11434/v1
LLM_API_KEY=ollama
LLM_MODEL=qwen2.5:7bStep 4:编写 FastAPI 服务
# main.py
import os
from dotenv import load_dotenv
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import StreamingResponse
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel
from openai import OpenAI
load_dotenv()
app = FastAPI(title="LLM Chat API")
# 允许前端跨域访问
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
# 初始化 LLM 客户端(通过 .env 切换后端)
client = OpenAI(
base_url=os.getenv("LLM_BASE_URL"),
api_key=os.getenv("LLM_API_KEY"),
)
MODEL = os.getenv("LLM_MODEL")
class ChatRequest(BaseModel):
messages: list[dict]
system_prompt: str = "你是一个有帮助的 AI 助手。"
stream: bool = True
temperature: float = 0.7
max_tokens: int = 1024
@app.post("/api/chat")
async def chat(request: ChatRequest):
# 构建消息列表(加入 system prompt)
messages = [{"role": "system", "content": request.system_prompt}]
messages.extend(request.messages)
if request.stream:
# 流式输出
def generate():
stream = client.chat.completions.create(
model=MODEL,
messages=messages,
temperature=request.temperature,
max_tokens=request.max_tokens,
stream=True,
)
for chunk in stream:
content = chunk.choices[0].delta.content
if content:
yield f"data: {content}\n\n"
yield "data: [DONE]\n\n"
return StreamingResponse(generate(), media_type="text/event-stream")
else:
# 非流式输出
response = client.chat.completions.create(
model=MODEL,
messages=messages,
temperature=request.temperature,
max_tokens=request.max_tokens,
)
return {"content": response.choices[0].message.content}
# 挂载静态文件(前端页面)
app.mount("/", StaticFiles(directory="static", html=True), name="static")Step 5:启动并测试
# 启动 FastAPI
uvicorn main:app --reload --host 0.0.0.0 --port 3000
# 测试非流式调用
curl -X POST http://localhost:3000/api/chat \
-H "Content-Type: application/json" \
-d '{
"messages": [{"role": "user", "content": "用一句话介绍你自己"}],
"stream": false
}'
# 测试流式调用
curl -X POST http://localhost:3000/api/chat \
-H "Content-Type: application/json" \
-d '{
"messages": [{"role": "user", "content": "写一首关于编程的诗"}],
"stream": true
}'💡 切换到线上 vLLM 只需要改
.env文件中的LLM_BASE_URL和LLM_MODEL,代码完全不用动。
6.3 线上部署阶段(AutoDL + vLLM)
本地开发验证通过后,切到线上只需两步:启动 vLLM + 修改 .env 配置。
Step 1:在 AutoDL 启动 vLLM
按照 4.3 节的流程,在 AutoDL 上启动 vLLM 服务:
# SSH 登录 AutoDL 实例后
source /root/vllm-env/bin/activate
nohup vllm serve Qwen/Qwen2.5-7B-Instruct \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 8192 \
--gpu-memory-utilization 0.9 \
> /root/vllm.log 2>&1 &
# 确认启动成功
curl http://localhost:8000/v1/models开放 8000 端口,获取公网 URL(如 https://u-xxxxx-8000.westc.gpuhub.com)。
Step 2:修改 .env 配置
# .env(线上版本)
LLM_BASE_URL=https://u-xxxxx-8000.westc.gpuhub.com/v1
LLM_API_KEY=unused
LLM_MODEL=Qwen/Qwen2.5-7B-InstructStep 3:部署 FastAPI 服务
FastAPI 服务可以部署在任意有公网 IP 的服务器上(不需要 GPU):
# 在云服务器上(普通 CPU 机器即可)
git clone your-repo llm-chat-api
cd llm-chat-api
pip install -r requirements.txt
# 生产启动(使用 gunicorn + uvicorn workers)
pip install gunicorn
gunicorn main:app \
-w 4 \
-k uvicorn.workers.UvicornWorker \
--bind 0.0.0.0:3000完整的请求链路:
用户浏览器
│
▼
FastAPI 服务器(CPU 云服务器,¥50/月)
│
▼ (HTTP 请求)
vLLM 服务(AutoDL GPU 服务器,按需启停)
│
▼ (GPU 推理)
Qwen2.5-7B 模型💡 这个架构的好处:FastAPI 服务器很便宜(不需要 GPU),GPU 服务器按需启停。如果临时不用 vLLM,把
.env切回硅基流动或 OpenAI API,服务不中断。
6.4 前端接入(流式输出聊天界面)
最后一步:做一个简单的聊天页面,接入我们的 FastAPI 服务。以下是一个完整的单文件 HTML,支持流式打字效果。
创建 static/index.html:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LLM Chat</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
background: #1a1a2e; color: #eee;
display: flex; justify-content: center;
min-height: 100vh; padding: 20px;
}
.container { max-width: 800px; width: 100%; display: flex; flex-direction: column; }
h1 { text-align: center; margin-bottom: 20px; color: #8b5cf6; }
#chat-box {
flex: 1; overflow-y: auto; padding: 20px;
background: #16213e; border-radius: 12px;
margin-bottom: 16px; min-height: 400px;
}
.message { margin-bottom: 16px; line-height: 1.6; }
.user { color: #60a5fa; }
.user::before { content: "🧑 "; }
.assistant { color: #d1d5db; }
.assistant::before { content: "🤖 "; }
.input-area { display: flex; gap: 8px; }
input {
flex: 1; padding: 12px 16px; border: none;
border-radius: 8px; background: #16213e;
color: #eee; font-size: 16px; outline: none;
}
input:focus { box-shadow: 0 0 0 2px #8b5cf6; }
button {
padding: 12px 24px; border: none; border-radius: 8px;
background: #8b5cf6; color: white; font-size: 16px;
cursor: pointer; transition: background 0.2s;
}
button:hover { background: #7c3aed; }
button:disabled { background: #4a4a6a; cursor: not-allowed; }
</style>
</head>
<body>
<div class="container">
<h1>💬 LLM Chat</h1>
<div id="chat-box"></div>
<div class="input-area">
<input id="input" placeholder="输入消息..."
onkeydown="if(event.key==='Enter') sendMessage()" />
<button id="send-btn" onclick="sendMessage()">发送</button>
</div>
</div>
<script>
const chatBox = document.getElementById('chat-box');
const input = document.getElementById('input');
const sendBtn = document.getElementById('send-btn');
const messages = []; // 对话历史
async function sendMessage() {
const text = input.value.trim();
if (!text) return;
// 显示用户消息
messages.push({ role: 'user', content: text });
appendMessage('user', text);
input.value = '';
sendBtn.disabled = true;
// 创建 AI 回复容器
const aiDiv = appendMessage('assistant', '');
try {
const response = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ messages, stream: true }),
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
let fullContent = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n')
.filter(line => line.startsWith('data: '));
for (const line of lines) {
const data = line.slice(6);
if (data === '[DONE]') break;
fullContent += data;
aiDiv.textContent = '🤖 ' + fullContent;
}
}
messages.push({ role: 'assistant', content: fullContent });
} catch (error) {
aiDiv.textContent = '🤖 出错了:' + error.message;
}
sendBtn.disabled = false;
chatBox.scrollTop = chatBox.scrollHeight;
}
function appendMessage(role, content) {
const div = document.createElement('div');
div.className = `message ${role}`;
div.textContent = (role === 'user' ? '🧑 ' : '🤖 ') + content;
chatBox.appendChild(div);
chatBox.scrollTop = chatBox.scrollHeight;
return div;
}
</script>
</body>
</html>启动并验证:
# 确保 Ollama 在跑,然后启动 FastAPI
uvicorn main:app --reload --host 0.0.0.0 --port 3000
# 打开浏览器访问 http://localhost:3000你应该看到一个暗色主题的聊天界面,输入消息后模型会逐字流式返回。
至此,整个项目完成:
✅ 本地 Ollama 跑通模型推理
✅ FastAPI 封装 API(支持流式输出)
✅ 环境变量切换后端(Ollama → vLLM → 闭源 API)
✅ AutoDL + vLLM 线上部署
✅ 前端聊天页面接入(流式打字效果)七、选型决策与常见问题
如果你跳过前面直接翻到这里——没问题,这一章就是为快速决策设计的。
7.1 场景-方案速查表
按你的身份选:
| 你是谁 | 推荐方案 | 理由 |
|---|---|---|
| 学生 / 个人开发者 | Ollama 本地 | 零成本,Mac / Windows 通吃 |
| 独立开发者做产品 | 硅基流动 Serverless | 零运维,按量付费,有免费额度 |
| 创业团队(< 10 人) | 硅基流动 + AutoDL vLLM 备用 | 低峰用 Serverless,高峰自建 |
| 企业(数据安全要求高) | 内网 vLLM / Xinference | 数据不出网,完全可控 |
| 海外业务团队 | Replicate / Modal | 海外节点延迟低 |
按你的硬件选:
| 你有什么 | 推荐方案 |
|---|---|
| Mac M 系列(16 GB+) | Ollama(开发)→ 硅基流动(上线) |
| Windows / Linux + RTX 4090 | Ollama(开发)→ vLLM 本地(内网服务) |
| 没有 GPU | Ollama CPU 模式(开发)→ Serverless(上线) |
| 多张 A100 服务器 | vLLM + 张量并行 |
按你的预算选:
| 月预算 | 推荐方案 |
|---|---|
| ¥0 | Ollama 本地 + 硅基流动免费额度 |
| ¥100–500 | 硅基流动 Serverless |
| ¥500–2000 | AutoDL 4090 按需启停 + vLLM |
| ¥2000+ | 阿里云 PAI / 自建多卡集群 |
一句话总结:
🎯 不确定选什么?从 Ollama 本地 + 硅基流动 API 开始。这个组合覆盖了从开发到上线的全流程,零成本起步,遇到瓶颈再升级。
7.2 常见问题排错
Q1:Ollama 启动后模型下载很慢怎么办?
# 设置 Hugging Face 镜像加速(国内用户)
export OLLAMA_HOST=0.0.0.0
# Ollama 有自己的 CDN,通常不需要配置镜像
# 如果确实很慢,尝试用代理或在 LM Studio 中下载 GGUF 后导入Q2:vLLM 启动报 CUDA out of memory?
三个排查方向:
- 减小
--max-model-len(如从 32768 降到 8192) - 用量化模型(AWQ / GPTQ),显存占用减半
- 降低
--gpu-memory-utilization(如从 0.9 降到 0.85),让系统有更多余量
Q3:模型输出质量很差 / 答非所问?
通常不是部署问题,而是模型或 Prompt 的问题:
- 确认用的是
Instruct版本(如Qwen2.5-7B-Instruct),而不是 Base 版本 - 检查 System Prompt 是否合理
- 7B 模型在复杂推理任务上确实能力有限,考虑换更大的模型
Q4:vLLM 安装失败 / 编译报错?
# 确认 CUDA 版本兼容
nvidia-smi # 查看驱动支持的最高 CUDA 版本
nvcc --version # 查看已安装的 CUDA 工具链版本
# vLLM 要求 CUDA 12.1+,如果版本太低需要升级
# 最简单的方案:用 AutoDL 的预配置镜像,自带 CUDA 12.1Q5:流式输出无效,前端一次性收到全部内容?
检查 Nginx 配置是否关闭了缓冲:
proxy_buffering off;
proxy_cache off;如果没有 Nginx,检查 FastAPI 的 StreamingResponse 是否正确设置了 media_type="text/event-stream"。
Q6:Ollama 和 vLLM 的模型名不一样,切换后报错?
Ollama 用简短名(qwen2.5:7b),vLLM 用 HF 全名(Qwen/Qwen2.5-7B-Instruct)。解决方案:把模型名放在 .env 里,通过环境变量读取,切换后端时一起改。
Q7:AutoDL 实例重启后 vLLM 服务没了?
vLLM 进程不会自动随系统启动。解决方案:
# 方法一:写一个启动脚本,放到 /root/start.sh
# 方法二:用 supervisor 管理进程
pip install supervisor
# 配置 supervisord 自动拉起 vLLMQ8:本地 Ollama 跑 7B 模型很慢(< 5 tokens/s)?
- Mac 用户:确认 Ollama 在用 Metal GPU 加速(Activity Monitor 看 GPU 使用率)
- Windows / Linux:确认 Ollama 检测到了 GPU(
ollama run qwen2.5:7b启动时会打印使用的设备) - 如果是纯 CPU:7B Q4 模型在现代 CPU 上大约 5–15 tokens/s,这是正常速度
7.3 下一步学习路径
模型部署只是 AI 应用开发的一环。跑通部署后,以下方向值得继续深入:
如果你想提升模型质量:
- 学习 Prompt Engineering(→ 参考《3.1 Prompt 设计原则》)——好的 Prompt 比换大模型更有效
- 学习 RAG(→ 参考《4.1 RAG 核心架构》)——让模型基于你的私有数据回答问题
- 学习 模型微调(→ 参考《2.3 模型微调》)——让模型掌握你的领域知识和行为模式
如果你想构建更复杂的应用:
- 学习 Agent 开发(→ 参考《5.1 Agent 基础概念》)——让 LLM 使用工具、自主规划
- 学习 Function Calling(→ 参考《5.3 工具使用》)——让模型调用你的 API
- 学习 多模态模型(→ 参考《6.1 视觉模型》)——处理图像、音频输入
如果你想优化生产系统:
- 深入 vLLM 的高级特性:LoRA 动态加载、推测解码、前缀缓存
- 学习 Kubernetes + GPU 调度,实现多模型、多副本的弹性部署
- 研究 LLM 评测方法,建立质量评估体系
推荐的学习顺序:
你现在在这里
│
▼
模型部署(本教程)✅
│
├──▶ Prompt Engineering(立竿见影提升效果)
│
├──▶ RAG(让模型用上你的数据)
│
├──▶ Agent(让模型自主完成任务)
│
└──▶ 模型微调(终极手段,需要数据和算力)📝 本教程完。从 Ollama 一行命令到 vLLM 生产部署,从本地实验到云端上线——你已经掌握了模型部署的完整武器库。现在,去部署你的第一个模型吧。