模型服务
→ 返回工程实践
将训练好的模型部署为可调用的 API 服务,是 MLOps 的核心环节。服务化需要考虑延迟、吞吐、成本、可用性和版本管理的综合权衡。
服务架构模式
同步推理(Request-Response)
客户端 → HTTP POST /predict → 模型服务 → 返回结果
- 适合:实时查询、低延迟需求(<500ms)
- 问题:高并发时容易成为瓶颈
异步推理(队列模式)
客户端 → 发布到消息队列 → Worker 消费 → 结果写回 → 客户端轮询/回调
- 适合:批量处理、允许延迟的场景
- 优势:解耦生产者/消费者,Worker 可弹性扩缩
批推理(Batch Inference)
调度器 → 触发批任务 → 模型读取数据集 → 批量预测 → 结果写入存储
- 适合:离线分析、定期评分
- 工具:Spark、Ray、SageMaker Batch Transform
主流推理框架
| 框架 | 特点 | 适用场景 |
|---|
| vLLM | PagedAttention,高吞吐,LLM 专用 | 开源 LLM 生产部署 |
| TGI(Text Generation Inference) | HuggingFace 出品,支持流式 | HF 模型快速部署 |
| Triton Inference Server | NVIDIA,多框架,GPU 优化 | 企业级,多模型管理 |
| TorchServe | PyTorch 官方,灵活 | PyTorch 模型 |
| ONNX Runtime | 跨框架,CPU 友好 | 边缘/CPU 部署 |
| Ollama | 本地运行 LLM,开箱即用 | 开发调试 |
vLLM 部署示例
# 启动 vLLM 服务
# python -m vllm.entrypoints.openai.api_server \
# --model meta-llama/Llama-3-8B-Instruct \
# --tensor-parallel-size 2 \
# --max-model-len 8192 \
# --gpu-memory-utilization 0.9
# 调用(兼容 OpenAI SDK)
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="ignored")
response = client.chat.completions.create(
model="meta-llama/Llama-3-8B-Instruct",
messages=[{"role": "user", "content": "你好"}],
stream=True,
)
for chunk in response:
print(chunk.choices[0].delta.content or "", end="")
性能优化技术
| 技术 | 原理 | 收益 |
|---|
| 连续批处理(Continuous Batching) | 动态将多个请求合并推理 | 吞吐提升 3-10x |
| KV Cache | 缓存注意力的 K/V 矩阵,避免重算 | 减少重复计算 |
| PagedAttention | 非连续内存管理 KV Cache,减少碎片 | 显存利用率 +40% |
| 投机采样(Speculative Decoding) | 小模型起草 + 大模型验证 | 延迟降低 2-3x |
| 量化推理 | INT4/INT8 权重 | 显存减半,速度提升 |
| 张量并行 | 大模型切分到多 GPU | 支持超过单卡显存的模型 |
接口设计
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class PredictRequest(BaseModel):
text: str
model_version: str = "v1"
temperature: float = 0.7
class PredictResponse(BaseModel):
prediction: str
confidence: float
latency_ms: float
model_version: str
@app.post("/predict", response_model=PredictResponse)
async def predict(req: PredictRequest):
start = time.time()
result = model.inference(req.text, temperature=req.temperature)
return PredictResponse(
prediction=result.text,
confidence=result.score,
latency_ms=(time.time() - start) * 1000,
model_version=req.model_version,
)
@app.get("/health")
async def health():
return {"status": "ok", "model_loaded": model is not None}
容器化与 K8s 部署
# k8s Deployment 示例
apiVersion: apps/v1
kind: Deployment
metadata:
name: model-serving
spec:
replicas: 3
template:
spec:
containers:
- name: inference
image: myrepo/model-server:v1.2
resources:
limits:
nvidia.com/gpu: 1
memory: "16Gi"
requests:
cpu: "4"
memory: "8Gi"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 60
readinessProbe:
httpGet:
path: /health
port: 8080
SLA 与监控关键指标
| 指标 | 目标值(参考) | 说明 |
|---|
| P50 延迟 | < 200ms | 中位响应时间 |
| P99 延迟 | < 1s | 99% 请求响应时间 |
| 首 Token 延迟(TTFT) | < 500ms | LLM 流式关键指标 |
| 吞吐(RPS/TPS) | 按业务定 | 每秒请求/token 数 |
| 错误率 | < 0.1% | 5xx 比例 |
| GPU 利用率 | > 70% | 低于此值说明资源浪费 |
相关文档