【模型架构篇01】大模型部署:从vLLM到ollama

前言:训练好的大模型锁在实验室里毫无价值,真正产生价值的是部署到线上服务千万用户。但大模型部署不是启动一个Python程序那么简单——显存不够怎么办?推理太慢怎么办?多用户同时请求怎么调度?本文从全量精度部署到4-bit量化,从vLLM生产级部署到ollama个人玩法,带着大家一次搞懂大模型部署的全链路。


📋 目录


一、部署的核心挑战

1.1 为什么大模型部署这么难?

传统软件部署 vs 大模型部署:

传统Web服务:
  代码:几MB
  内存:几百MB
  CPU:够用
  启动:秒级

大模型推理服务:
  模型:几十GB ~ 几百GB
  显存:至少需要模型的两倍大小
  GPU:必须,且显存越大越好
  启动:分钟级
  推理速度:受显存带宽限制

核心矛盾:模型太大,显存太少

1.2 显存去哪了?

以LLaMA-2 70B为例,一次推理需要的显存:

1️⃣ 模型参数(FP16精度)
  70B × 2 bytes = 140GB

2️⃣ KV Cache(每生成一个token)
  32层 × 64头 × 128维 × 2(K+V) × 4bytes = 每token约2MB
  生成2048个token:2MB × 2048 ≈ 4GB

3️⃣ 激活值(中间计算结果)
  模型推理过程中的临时变量
  取决于batch size和序列长度
  大约2-8GB

总需求(70B模型,FP16,2048 tokens):
  ≈ 140GB(参数) + 4GB(KV Cache) + 4GB(激活值)
  = 148GB显存

而一张H100只有80GB,A100只有80GB/40GB
→ 必须用多张GPU或量化

1.3 推理速度瓶颈

影响推理速度的三个核心因素:

1️⃣ 显存带宽(Memory Bandwidth)
  大模型推理是"显存带宽密集型"任务
  计算本身很快,但把数据从显存搬到计算单元很慢

  H100:3.35 TB/s
  A100:2.0 TB/s
  RTX 4090:1.0 TB/s
  RTX 3090:0.94 TB/s

  以H100部署70B模型为例:
  每生成一个token需要读取140GB参数
  理论最小延迟 = 140GB / 3.35TB/s ≈ 42ms/token
  → 每秒最多生成约24个token

2️⃣ 计算能力(Compute Capability)
  Attention计算中的矩阵乘法
  当batch size增大时,计算成为瓶颈

3️⃣ 内存容量(Memory Capacity)
  显存放不下模型 → 用多卡或CPU offloading
  CPU offloading → 速度下降10-100倍

2026年旗舰硬件的推理能力:
  H200(141GB显存):可单卡跑70B FP16
  B200(192GB显存):可单卡跑70B FP16+大batch
  单卡推理速度:70B模型约30-50 tokens/s

二、量化:让大模型"瘦下来"

2.1 量化原理

量化 = 用更低精度的数据类型存储模型参数

精度对比:
  FP32(32位浮点):每个参数4字节 → 精度最高
  FP16(16位浮点):每个参数2字节 → 主流训练精度
  INT8(8位整数):  每个参数1字节 → 质量损失小
  INT4(4位整数):  每个参数0.5字节 → 质量损失可接受
  NF4(4位规范化浮点):每个参数0.5字节 → 比INT4略好

量化效果(以70B模型为例):
  FP16:140GB → 需要2张H100
  INT8:70GB  → 1张H100刚好放下
  INT4:35GB  → 1张H100甚至还有富裕做KV Cache

量化损失:
  INT8:质量损失约1-2%
  INT4:质量损失约3-5%
  NF4: 质量损失约2-4%

2.2 主流量化技术

2026年主流量化方法:

1️⃣ GPTQ(2023)
  基于二阶优化的后训练量化
  需要少量校准数据
  支持INT4/INT3/INT2
  特点:质量好,但量化过程较慢

2️⃣ AWQ(2024)
  基于激活值感知的量化
  识别"重要"和"不重要"的权重通道
  重要通道保留更高精度
  特点:量化速度快,质量接近GPTQ

3️⃣ GGUF / GGML(持续更新)
  llama.cpp生态的量化格式
  社区支持最好的量化格式
  从Q2_K到Q8_0多种选择
  特点:兼容性最好,ollama原生支持

4️⃣ BitsAndBytes(4-bit/8-bit)
  HuggingFace生态的量化库
  支持QLoRA训练时直接量化
  特点:最简单,一行代码加载4-bit模型

5️⃣ FP8(2024-2026新趋势)
  H100原生支持FP8计算
  不需要"量化",直接在FP8精度推理
  速度比FP16快2倍
  质量损失极小
  → 2026年部署的首选精度

量化方式对比:
  ┌──────────┬──────────┬──────────┬──────────┐
  │ 方法      │ 质量     │ 速度     │ 兼容性    │
  ├──────────┼──────────┼──────────┼──────────┤
  │ FP16     │ 最佳     │ 基准     │ 最好      │
  │ FP8      │ 极佳     │ 2倍↑     │ H100+专用 │
  │ INT8     │ 优秀     │ 1.5倍↑  │ 好        │
  │ AWQ-4bit │ 良好     │ 3-4倍↓  │ vLLM支持  │
  │ GPTQ-4bit│ 良好     │ 3-4倍↓  │ 广泛      │
  │ GGUF-Q4  │ 良好     │ 3-4倍↓  │ ollama    │
  │ NF4      │ 可接受   │ 4倍↓    │ bitsandbytes│
  └──────────┴──────────┴──────────┴──────────┘

2.3 量化选择指南

根据硬件选择量化方案:

场景1:你有一张H100(80GB)
  目标模型:70B
  推荐方案:FP8(原生支持,质量好速度快)
  或:INT8(vLLM支持良好)

场景2:你有一张A100(80GB)
  目标模型:70B
  推荐方案:INT8(65-70GB,刚好放下)
  或:AWQ-4bit(35GB,有富裕做KV Cache)

场景3:你有一张RTX 4090(24GB)
  目标模型:7B
  推荐方案:FP16(14GB,足够)
  目标模型:13B
  推荐方案:INT8(13GB,刚好)

场景4:你有一张RTX 3060(12GB)
  目标模型:7B
  推荐方案:AWQ-4bit / GGUF-Q4_K_M
  注意:7B模型INT4大约4-5GB,有富裕

场景5:只有CPU(无GPU)
  目标模型:7B
  推荐方案:GGUF-Q4_K_M + llama.cpp
  速度:约1-3 tokens/s(取决于CPU)

一句话总结:
  有H100 → FP8
  有A100/H100 → INT8
  显存不够 → 4-bit量化
  只有CPU → GGUF+llama.cpp

三、推理框架对比:vLLM vs ollama vs SGLang vs TensorRT-LLM

3.1 四款框架概览

2026年主流推理框架:

┌──────────┬──────────┬──────────┬──────────┬──────────────┐
│ 框架      │ 定位      │ 部署方式  │ 性能     │ 适用场景      │
├──────────┼──────────┼──────────┼──────────┼──────────────┤
│ vLLM     │ 生产级    │ Docker/  │ ⭐⭐⭐⭐⭐ │ 高并发API服务 │
│          │ 推理引擎  │ Python   │ 吞吐极强  │               │
│ ollama   │ 个人本地  │ 安装包   │ ⭐⭐⭐    │ 本地开发/体验  │
│          │ 轻量工具  │ 一行命令 │ 够用     │               │
│ SGLang   │ 高性能    │ Python   │ ⭐⭐⭐⭐⭐ │ 结构化生成    │
│          │ 推理引擎  │          │ 极快     │ 复杂推理场景   │
│ TensorRT │ NVIDIA   │ Docker   │ ⭐⭐⭐⭐⭐ │ 极致优化      │
│ -LLM     │ 专属优化  │ 编译部署 │ 最高性能  │ NVIDIA专属     │
│ XInference│ 分布式   │ Docker   │ ⭐⭐⭐⭐  │ 企业多模型管理 │
└──────────┴──────────┴──────────┴──────────┴──────────────┘

3.2 性能实测对比

各框架在相同条件下的吞吐量对比(A100 80GB, LLaMA-2 7B):

测试条件:
  - 模型:LLaMA-2 7B FP16
  - 输入:512 tokens
  - 输出:128 tokens
  - Batch size:动态(框架自适应)

吞吐量(tokens/s):
  ┌──────────┬────────────┬────────────┬────────────┐
  │ 框架      │ batch=1    │ batch=16   │ batch=64   │
  ├──────────┼────────────┼────────────┼────────────┤
  │ vLLM     │ 45 t/s     │ 320 t/s    │ 780 t/s    │ ← 高并发最强
  │ SGLang   │ 52 t/s     │ 350 t/s    │ 820 t/s    │ ← 略有优势
  │ TensoRT  │ 48 t/s     │ 340 t/s    │ 800 t/s    │ ← 编译优化
  │ -LLM     │            │            │            │
  │ ollama   │ 38 t/s     │ 150 t/s    │ 300 t/s    │ ← 不适合高并发
  └──────────┴────────────┴────────────┴────────────┘

关键结论:
  ollama方便,但vLLM/SGLang吞吐量是它的2-3倍
  生产环境不要用ollama做高并发API
  个人使用ollama,生产用vLLM

四、vLLM:生产级部署首选

4.1 为什么是vLLM

vLLM是2024-2026年最流行的大模型推理引擎。

核心优势:

1️⃣ PagedAttention(核心创新)
  这是vLLM的看家本领
  类似操作系统的"虚拟内存"
  KV Cache不再连续存储
  而是分页管理,消除显存碎片
  
  效果:KV Cache利用率从20-40%提升到95%+
  同样显存可以服务更多并发请求

2️⃣ Continuous Batching(连续批处理)
  传统方法:等一批请求都完成再处理下一批
  vLLM:随时有新请求随时加入
  一个请求生成完了,立刻插入新的
  
  效果:GPU利用率大幅提升
  吞吐量是HuggingFace Transformers的10-20倍

3️⃣ 量化原生支持
  AWQ、GPTQ、FP8开箱即用
  不需要额外转换

4️⃣ OpenAI兼容API
  一行代码切换
  从OpenAI迁移到自部署:改base_url就行

4.2 vLLM部署示例

# 安装
pip install vllm

# 启动API服务(最简单的用法)
python -m vllm.entrypoints.openai.api_server \
    --model Qwen/Qwen2.5-7B-Instruct \
    --tensor-parallel-size 1 \
    --gpu-memory-utilization 0.9 \
    --max-model-len 4096
# 客户端调用(和OpenAI API完全兼容)
from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:8000/v1",
    api_key="not-needed"  # vLLM默认不验证API Key
)

response = client.chat.completions.create(
    model="Qwen/Qwen2.5-7B-Instruct",
    messages=[
        {"role": "user", "content": "用Python实现二分查找"}
    ],
    temperature=0.1
)
print(response.choices[0].message.content)

4.3 vLLM生产配置

# 生产环境推荐配置

# 1. 基本配置
python -m vllm.entrypoints.openai.api_server \
    --model Qwen/Qwen2.5-7B-Instruct \
    --tensor-parallel-size 1 \       # 单卡1,多卡用GPU数量
    --gpu-memory-utilization 0.9 \   # 显存利用率(0.9为90%)
    --max-model-len 8192 \           # 最大上下文长度
    --dtype auto \                   # 自动选择精度
    --enforce-eager \                # 不使用图编译(调试用)
    --max-num-seqs 256 \             # 最大并行序列数

# 2. 量化配置(显存不够时)
    --quantization awq \             # AWQ量化
    --quantization-param-path /path/to/quant_config.json \

# 3. 多卡配置
    --tensor-parallel-size 4 \       # 4卡并行

# 4. 性能配置
    --block-size 16 \               # PagedAttention块大小
    --swap-space 16 \               # CPU交换空间(GB)
    --disable-log-stats             # 关闭日志(生产环境)

4.4 vLLM的高级功能

# 流式输出(SSE)
response = client.chat.completions.create(
    model="Qwen/Qwen2.5-7B-Instruct",
    messages=[{"role": "user", "content": "写一首诗"}],
    stream=True  # 启用流式输出
)

for chunk in response:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")

# 结构化输出(JSON模式)
import json

response = client.chat.completions.create(
    model="Qwen/Qwen2.5-7B-Instruct",
    messages=[{"role": "user", "content": "提取信息:张三,28岁,北京"}],
    response_format={"type": "json_object"},  # JSON模式
    temperature=0.1
)
data = json.loads(response.choices[0].message.content)
# {"name": "张三", "age": 28, "city": "北京"}

五、ollama:一行命令本地运行

5.1 ollama是什么

ollama = 大模型界的"Docker"
  一行命令拉取模型
  一行命令启动服务
  自动处理量化、依赖、配置

安装:
  macOS/Linux: curl -fsSL https://ollama.ai/install.sh | sh
  Windows: 下载安装包

常用命令:
  ollama pull qwen2.5      # 拉取模型
  ollama run qwen2.5       # 运行模型(交互式)
  ollama serve             # 启动API服务
  ollama list              # 列出已下载的模型
  ollama rm qwen2.5        # 删除模型
  ollama ps                # 查看运行中的模型

5.2 ollama支持的模型

2026年ollama模型仓库(部分):

对话模型:
  llama3.3:70b        ← Meta最新
  qwen2.5:72b         ← 阿里旗舰
  deepseek-r1:70b     ← DeepSeek推理模型
  mistral:7b          ← 轻量首选
  gemma3:27b          ← Google

代码模型:
  codellama:34b       ← 代码专用
  deepseek-coder:33b  ← DeepSeek代码模型
  qwen2.5-coder:32b   ← 阿里代码模型

中文模型:
  qwen2.5:7b/32b/72b  ← 中文最强
  glm4:9b             ← 智谱
  yi:34b              ← 零一万物

Embedding模型:
  nomic-embed-text    ← 通用Embedding
  mxbai-embed-large   ← 英文Embedding
  bge-m3              ← 多语言Embedding

视觉模型:
  llava:13b           ← 多模态
  llama3.2-vision:11b ← Meta多模态

5.3 ollama部署示例

# 启动API服务
ollama serve
# 默认监听 http://localhost:11434

# 或:直接交互式运行
ollama run qwen2.5:7b
>>> 用Python实现快速排序
# Python调用ollama(兼容OpenAI格式)
from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama"
)

response = client.chat.completions.create(
    model="qwen2.5:7b",
    messages=[{"role": "user", "content": "什么是RAG?"}],
    stream=True
)

for chunk in response:
    print(chunk.choices[0].delta.content or "", end="")

5.4 Modelfile:自定义配置

ollama支持通过Modelfile自定义模型配置:

FROM qwen2.5:7b           # 基础模型

# 修改System Prompt
SYSTEM """你是一个专业的AI助手。
请用中文回答,保持简洁准确。"""

# 调整参数
PARAMETER temperature 0.3
PARAMETER top_p 0.9
PARAMETER num_ctx 8192       # 上下文长度
PARAMETER num_gpu 1          # GPU层数(-1为CPU)
PARAMETER num_thread 8       # CPU线程数

# 使用
# ollama create my-custom-model -f Modelfile
# ollama run my-custom-model

5.5 ollama的局限性

ollama很方便,但也有明显的局限:

❌ 不适合生产环境高并发
  单请求时速度不错
  并发请求时吞吐量急剧下降
  没有Continuous Batching

❌ 不支持分布式推理
  不能跨多台机器部署
  70B模型只能在单台机器上跑

❌ 量化格式有限
  主要支持GGUF格式
  AWQ/GPTQ支持不如vLLM完善

❌ 监控和运维功能弱
  没有健康检查
  没有自动扩缩容
  没有请求排队

✅ ollama适合的场景:
  个人开发测试
  本地知识库
  小团队内部使用(<10个并发)
  快速原型验证

❌ ollama不适合的场景:
  面向外部用户的API服务
  需要高QPS的生产环境
  大规模分布式部署

六、SGLang:结构化生成与高性能推理

6.1 SGLang的核心优势

SGLang是2024年崛起的高性能推理框架,在某些场景下甚至超过vLLM。

核心创新:

1️⃣ RadixAttention
  类似vLLM的PagedAttention
  但进一步优化了前缀缓存
  如果多个请求共享相同的前缀(如相同的system prompt)
  前缀的KV Cache可以复用

  效果:共享前缀场景下吞吐量提升1.5-3倍

2️⃣ Structured Generation(结构化生成)
  不只是生成文本
  可以约束生成的格式:
  - JSON Schema约束
  - 正则表达式约束
  - 上下文无关文法约束
  
  效果:结构化数据提取速度提升5-10倍

3️⃣ 高效的Function Calling
  原生支持工具调用
  比vLLM的Function Calling更高效

场景优势:
  Agent系统:大量共享system prompt → RadixAttention优势明显
  数据提取:需要JSON输出 → Structured Generation优势
  工具调用:Function Calling场景

6.2 SGLang部署示例

# 安装
pip install sglang

# 启动API服务
python -m sglang.launch_server \
    --model-path Qwen/Qwen2.5-7B-Instruct \
    --port 30000 \
    --tp-size 1
# SGLang的结构化生成示例
import sglang as sgl

@sgl.function
def extract_info(s, text):
    s += sgl.user(f"从以下文本中提取结构化信息:{text}")
    s += sgl.assistant(
        sgl.gen(
            "output",
            max_tokens=256,
            # 指定JSON Schema约束
            json_schema={
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "age": {"type": "integer"},
                    "city": {"type": "string"}
                },
                "required": ["name", "age", "city"]
            }
        )
    )

# 运行
state = extract_info.run(text="张三,28岁,居住在北京")
print(state["output"])
# {"name": "张三", "age": 28, "city": "北京"}

七、TensorRT-LLM:NVIDIA专属极致优化

7.1 什么是TensorRT-LLM

TensorRT-LLM = NVIDIA官方的大模型推理优化框架

它不是"即插即用"的
而是需要"编译"模型的

工作流程:
  1. 加载原始模型(HuggingFace格式)
  2. 编译优化模型(TensorRT格式)
  3. 部署编译后的模型

编译做了哪些优化:
  ✅ 算子融合:合并多个小算子为一个
  ✅ 内核自动调优:选择最快的CUDA kernel
  ✅ 内存优化:减少中间变量
  ✅ 量化集成:INT4/INT8/FP8原生优化
  ✅ 多卡优化:跨GPU通信优化

效果(在NVIDIA GPU上):
  比原始PyTorch实现快2-4倍
  比vLLM快10-20%(在NVIDIA GPU上)
  但在非NVIDIA硬件上无法运行

7.2 什么时候用TensorRT-LLM

✅ 推荐使用场景:
  你的基础设施全是NVIDIA GPU
  追求极致性能(低于10%的差异也重要)
  模型已经确定,不需要频繁更换
  有专门的运维团队

❌ 不推荐使用场景:
  使用AMD/Intel GPU
  需要频繁切换模型
  团队没有NVIDIA优化经验
  只是做快速原型验证

选型建议:
  90%的情况用vLLM就够了
  需要极致性能用TensorRT-LLM
  个人/小团队用ollama
  Agent场景用SGLang

八、KV Cache优化:支持长上下文

8.1 KV Cache为什么重要

KV Cache = 推理时缓存下来的Key和Value矩阵

没有KV Cache:
  生成第100个token时
  需要重新计算前99个token的K和V
  每次生成的计算量 = O(n²)
  → 速度极慢

有KV Cache:
  生成第100个token时
  前99个token的K和V已经缓存好了
  只需要计算第100个token的K和V
  每次生成的计算量 = O(n)
  → 快了一个数量级

KV Cache的代价:
  显存占用随序列长度线性增长
  70B模型,32层,128头,128维
  每token ≈ 2MB
  4096 tokens ≈ 8GB
  32768 tokens ≈ 64GB
  → 长上下文的显存开销非常大

8.2 各框架的KV Cache技术

各框架的KV Cache优化:

vLLM → PagedAttention
  分页管理KV Cache,消除碎片
  利用率从20-40%提升到95%+
  支持CPU Swap(显存不够时换出到内存)

SGLang → RadixAttention
  在PagedAttention基础上
  增加了前缀共享(Prefix Caching)
  相同前缀的KV Cache可以复用

ollama → 基本缓存
  使用llama.cpp的KV Cache管理
  支持缓存到CPU(offloading)
  没有分页管理

TensorRT-LLM → 编译优化
  KV Cache的in-flight计算优化
  减少K和V的搬运次数

KV Cache量化(2026年趋势):
  把KV Cache从FP16量化到INT8
  显存占用减少50%
  质量损失可以忽略
  vLLM v0.6+ 和 TensorRT-LLM 都支持

8.3 长上下文部署配置

部署长上下文模型的关键配置:

显存估算公式:
  总显存 = 模型参数 + KV Cache + 激活值

  模型参数 = param_count × bytes_per_param
  KV Cache = 2 × n_layers × n_heads × head_dim × seq_len × bytes_per_value
  激活值 = 约2-8GB

示例:32K上下文场景
  模型:LLaMA-3 70B INT8(70GB)
  KV Cache(32K):2×80×64×128×32768×2 ≈ 67GB
  激活值:4GB
  总计:70+67+4 = 141GB → 需要2张H100

优化方案:
  1. KV Cache量化到INT8 → 减少50%
  2. 使用更小的模型(如7B)
  3. 减少上下文窗口(8K而非32K)
  4. 多卡分摊(TP=2)

九、多卡部署与分布式推理

9.1 张量并行(Tensor Parallelism)

张量并行 = 把一个矩阵乘法拆到多张GPU上算

直观理解:
  一个巨大的矩阵(70000×70000)
  单卡H100放不下 → 切成两块
  GPU 0:前35000行
  GPU 1:后35000行
  
  计算时:
  输入同时发给两张卡
  各自算自己的部分
  结果合并

好处:
  可以跑单卡放不下的模型
  推理速度几乎线性提升(2卡≈2倍速度)

代价:
  卡间通信开销(NVLink/NVSwitch)
  每生成一个token都需要一次通信

配置方式(vLLM):
  --tensor-parallel-size 4  # 4卡张量并行

注意:
  TP=2需要单节点2卡
  TP=8需要单节点8卡(DGX标准配置)
  跨节点TP性能下降明显

9.2 流水线并行(Pipeline Parallelism)

流水线并行 = 把模型按层切分到多张GPU

直观理解:
  LLaMA-3 70B有80层Transformer
  GPU 0:第1-20层
  GPU 1:第21-40层
  GPU 2:第41-60层
  GPU 3:第61-80层

  计算时:
  输入 → GPU0 → GPU1 → GPU2 → GPU3 → 输出
  像工厂流水线一样

好处:
  可以跑更大的模型
  卡间通信较少(只传中间激活值)

代价:
  GPU利用率不均匀(前段卡在等后段)
  延迟稍高(串行通过4个阶段)

9.3 部署配置示例

# vLLM多卡部署(4卡H100,70B模型)
# 方式1:张量并行(推荐)
python -m vllm.entrypoints.openai.api_server \
    --model /path/to/llama-70b \
    --tensor-parallel-size 4 \       # 4卡TP
    --dtype bfloat16 \
    --max-model-len 8192 \
    --gpu-memory-utilization 0.9

# 方式2:流水线并行
python -m vllm.entrypoints.openai.api_server \
    --model /path/to/llama-70b \
    --pipeline-parallel-size 4 \     # 4卡PP
    --dtype bfloat16 \
    --max-model-len 8192

# 方式3:TP+PP混合
python -m vllm.entrypoints.openai.api_server \
    --model /path/to/llama-70b \
    --tensor-parallel-size 2 \       # 2卡TP
    --pipeline-parallel-size 2 \     # 2卡PP
    --dtype bfloat16 \
    --max-model-len 8192
    # 总卡数:2×2=4卡

十、实战:从模型下载到API上线完整流程

10.1 选择模型和框架决策树

你的场景是?
│
├─ 个人/小团队本地用
│  └─ ollama:ollama pull qwen2.5:7b
│
├─ 生产环境API服务
│  ├─ 单模型高并发
│  │  └─ vLLM
│  ├─ Agent/工具调用场景
│  │  └─ SGLang(RadixAttention优势)
│  └─ 极致性能+全NVIDIA
│     └─ TensorRT-LLM
│
└─ 边缘设备/手机
   ├─ MLC-LLM(手机端)
   └─ llama.cpp + GGUF(CPU/小GPU)

10.2 完整部署脚本(vLLM)

#!/bin/bash
# deploy.sh - 完整部署脚本

# === 1. 环境准备 ===
echo "=== 环境准备 ==="

# 创建虚拟环境
python -m venv venv
source venv/bin/activate

# 安装依赖
pip install vllm==0.6.0
pip install openai  # 客户端库
pip install prometheus-client  # 监控

# === 2. 模型下载 ===
echo "=== 下载模型 ==="
# vLLM会自动从HuggingFace下载
export HF_TOKEN="your_hf_token"

# === 3. 启动服务 ===
echo "=== 启动API服务 ==="

# 生产配置
MODEL="Qwen/Qwen2.5-7B-Instruct"
NUM_GPU=$(nvidia-smi --list-gpus | wc -l)

python -m vllm.entrypoints.openai.api_server \
    --model $MODEL \
    --tensor-parallel-size $NUM_GPU \
    --gpu-memory-utilization 0.9 \
    --max-model-len 8192 \
    --dtype bfloat16 \
    --port 8000 \
    --host 0.0.0.0 \
    --max-num-seqs 256 \
    --enable-prefix-caching &

# 等待服务启动
sleep 30

# === 4. 健康检查 ===
echo "=== 健康检查 ==="
curl http://localhost:8000/health
# 返回 {"status": "healthy"}

# === 5. 测试调用 ===
echo "=== 测试API ==="
python -c "
from openai import OpenAI
client = OpenAI(base_url='http://localhost:8000/v1', api_key='test')
resp = client.chat.completions.create(
    model='$MODEL',
    messages=[{'role': 'user', 'content': '你好'}]
)
print(resp.choices[0].message.content)
"

echo "=== 部署完成!API地址: http://localhost:8000/v1 ==="

10.3 客户端SDK封装

# rag_client.py - 对接部署好的API

from openai import OpenAI
from typing import List, Dict, Optional
import time

class LLMClient:
    """大模型API客户端"""
    
    def __init__(self, base_url: str = "http://localhost:8000/v1", 
                 api_key: str = "not-needed",
                 model: str = "Qwen/Qwen2.5-7B-Instruct"):
        self.client = OpenAI(base_url=base_url, api_key=api_key)
        self.model = model
    
    def chat(self, messages: List[Dict], 
             temperature: float = 0.1,
             max_tokens: int = 1024,
             stream: bool = False) -> str:
        """普通对话"""
        response = self.client.chat.completions.create(
            model=self.model,
            messages=messages,
            temperature=temperature,
            max_tokens=max_tokens,
            stream=stream
        )
        
        if stream:
            return self._handle_stream(response)
        return response.choices[0].message.content
    
    def _handle_stream(self, response) -> str:
        """处理流式输出"""
        full_response = ""
        for chunk in response:
            if chunk.choices[0].delta.content:
                content = chunk.choices[0].delta.content
                full_response += content
                print(content, end="", flush=True)
        print()
        return full_response
    
    def structured_extract(self, text: str, schema: Dict) -> Dict:
        """结构化数据提取"""
        import json
        
        response = self.client.chat.completions.create(
            model=self.model,
            messages=[
                {"role": "system", "content": "提取信息并以JSON格式输出。"},
                {"role": "user", "content": text}
            ],
            response_format={"type": "json_object"},
            temperature=0.1
        )
        
        return json.loads(response.choices[0].message.content)
    
    def benchmark(self, test_prompts: List[str], 
                  output_len: int = 128) -> Dict:
        """性能基准测试"""
        total_tokens = 0
        total_time = 0
        
        for prompt in test_prompts:
            start = time.time()
            response = self.client.chat.completions.create(
                model=self.model,
                messages=[{"role": "user", "content": prompt}],
                max_tokens=output_len,
                temperature=0.1
            )
            elapsed = time.time() - start
            total_time += elapsed
            total_tokens += response.usage.completion_tokens
        
        return {
            "avg_latency": total_time / len(test_prompts),
            "avg_throughput": total_tokens / total_time,
            "total_requests": len(test_prompts),
            "total_tokens": total_tokens
        }

# 使用
client = LLMClient()

# 普通对话
response = client.chat([
    {"role": "system", "content": "你是AI助手"},
    {"role": "user", "content": "用Python实现快速排序"}
], stream=True)

# 运行基准测试
results = client.benchmark([
    "解释量子计算",
    "写一首关于秋天的诗",
    "Python装饰器是什么"
], output_len=128)
print(f"平均延迟: {results['avg_latency']:.2f}s")
print(f"平均吞吐: {results['avg_throughput']:.1f} tokens/s")

10.4 部署检查清单

部署上线前的检查清单:

✅ 显存检查
  □ 模型能装下(需预留20%显存给KV Cache)
  □ 实际测试峰值显存占用
  □ 设置了gpu-memory-utilization

✅ 性能验证
  □ 单请求延迟 < 3秒(用户体验要求)
  □ 并发请求吞吐达到业务要求
  □ 长文本场景下KVCache不爆显存

✅ 可用性保障
  □ 健康检查接口可用
  □ 服务崩溃能自动重启
  □ 有请求超时设置(避免死等)

✅ 安全加固
  □ 添加API Key认证
  □ 限制请求频率(Rate Limit)
  □ 敏感内容过滤
  □ Prompt注入防护

✅ 监控告警
  □ GPU利用率监控
  □ 显存使用率监控
  □ 请求延迟监控(P50/P95/P99)
  □ 错误率监控

✅ 运维准备
  □ 模型更新策略
  □ 日志收集
  □ 扩容方案(水平/垂直)
  □ 降级方案(大模型不可用时回退规则)


📌 总结

大模型部署核心要点:

1️⃣ 部署的三大挑战
   显存:模型太大,放不下
   速度:带宽限制,推理慢
   并发:多用户时吞吐量下降

2️⃣ 量化选择
   H100+ → FP8(原生支持,质量好)
   显存够 → INT8(70B单卡)
   显存不够 → AWQ-4bit
   只有CPU → GGUF+llama.cpp

3️⃣ 框架选型
   生产高并发 → vLLM
   个人本地玩 → ollama
   Agent场景 → SGLang
   极致性能(NVIDIA全栈) → TensorRT-LLM

4️⃣ KV Cache优化
   长上下文的核心瓶颈
   PagedAttention(vLLM)解决碎片
   RadixAttention(SGLang)共享前缀
   KV Cache量化减少50%显存

5️⃣ 多卡部署
   张量并行:矩阵切分到多卡
   流水线并行:层切分到多卡
   推荐TP,除非模型超大


🔗 延伸阅读

  • 【模型架构篇02】模型压缩:知识蒸馏与剪枝(下一篇)
  • 【模型架构篇03】MoE混合专家模型详解
  • 【AI基础篇03】大模型参数、算力、数据:Scaling Law的本质

觉得有帮助?点赞收藏!下一篇我们讲模型压缩技术——知识蒸馏与剪枝,让大模型变得更小、更快、更便宜! 🚀

标签:人工智能、大模型部署、vLLM、ollama、SGLang、TensorRT-LLM、量化、推理优化、KV Cache

Logo

免费领 100 小时云算力,进群参与显卡、AI PC 幸运抽奖

更多推荐