AI应用开发进阶(五):AI应用性能调优让响应速度提升10倍
一、开场:慢是AI应用的最大敌人
大家好,我是老金。
AI应用最大的敌人是什么?
慢。
用户等3秒就流失,你的AI应用还在转圈圈?
今天聊聊性能调优。
二、性能瓶颈分析
2.1 延迟来源
┌─────────────────────────────────────────────────────────┐
│ AI应用延迟来源 │
├─────────────────────────────────────────────────────────┤
│ │
│ 总延迟 = 网络延迟 + 预处理 + LLM推理 + 后处理 │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 网络延迟(10-100ms) │ │
│ │ • DNS解析 │ │
│ │ • TCP握手 │ │
│ │ • TLS握手 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 预处理(50-200ms) │ │
│ │ • Prompt构建 │ │
│ │ • 上下文检索 │ │
│ │ • 数据格式化 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ LLM推理(500ms-10s)⭐ 主要瓶颈 │ │
│ │ • 模型加载 │ │
│ │ • Token生成 │ │
│ │ • 解码过程 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 后处理(10-50ms) │ │
│ │ • 结果解析 │ │
│ │ • 格式化输出 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
2.2 性能指标
# 关键性能指标
PERFORMANCE_METRICS = {
"TTFT": {
"description": "Time To First Token",
"target": "< 500ms",
"说明": "首Token延迟,影响用户感知"
},
"TPOT": {
"description": "Time Per Output Token",
"target": "< 50ms",
"说明": "每Token生成时间"
},
"Latency": {
"description": "端到端延迟",
"target": " 100 req/s",
"说明": "每秒处理请求数"
}
}
三、推理优化
3.1 模型优化
# 1. 使用更小的模型(模型蒸馏)
# 大模型生成数据,小模型学习
# 2. 量化推理
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(
load_in_4bit=True, # 4-bit量化
bnb_4bit_compute_dtype=torch.float16
)
model = AutoModelForCausalLM.from_pretrained(
"model_name",
quantization_config=quantization_config
)
# 3. 使用高效推理引擎
# vLLM(推荐)
from vllm import LLM
llm = LLM(
model="model_name",
tensor_parallel_size=2, # 张量并行
gpu_memory_utilization=0.95
)
# TensorRT-LLM(NVIDIA GPU最优)
# 需要编译模型,推理速度提升2-3倍
3.2 批处理优化
# 动态批处理
from vllm import LLM, SamplingParams
llm = LLM(model="model_name")
# vLLM自动批处理
# 多个请求自动合并处理
# 手动批处理(控制粒度)
def batch_inference(prompts: List[str], batch_size: int = 8):
"""批量推理"""
results = []
for i in range(0, len(prompts), batch_size):
batch = prompts[i:i+batch_size]
outputs = llm.generate(
batch,
SamplingParams(temperature=0.7)
)
results.extend([o.outputs[0].text for o in outputs])
return results
# 连续批处理(Continuous Batching)
# vLLM默认支持,自动合并新请求到正在进行的batch
3.3 投机解码
# 投机解码:用小模型预测,大模型验证
# 可以加速2-3倍
from vllm import LLM
# 配置投机解码
llm = LLM(
model="large_model",
speculative_model="small_model", # 小模型做draft
num_speculative_tokens=5 # 每次预测5个token
)
# 原理:
# 1. 小模型快速生成5个token
# 2. 大模型并行验证
# 3. 接受正确的,拒绝的重新生成
四、系统优化
4.1 异步架构
# FastAPI异步服务
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import asyncio
app = FastAPI()
# 异步生成
async def generate_stream(prompt: str):
"""流式生成"""
# 模拟流式输出
for chunk in llm.generate_stream(prompt):
yield f"data: {chunk}nn"
yield "data: [DONE]nn"
@app.post("/chat/stream")
async def chat_stream(request: ChatRequest):
"""流式接口"""
return StreamingResponse(
generate_stream(request.message),
media_type="text/event-stream"
)
# 异步任务队列
from celery import Celery
celery_app = Celery('ai_tasks')
@celery_app.task
def async_generate(prompt: str):
"""异步生成任务"""
result = llm.generate(prompt)
# 保存到数据库/发送通知
return result
# 调用
async_generate.delay("长任务提示词")
4.2 缓存策略
# 多级缓存
import redis
import hashlib
from functools import lru_cache
class MultiLevelCache:
"""多级缓存"""
def __init__(self):
self.l1_cache = {} # 内存缓存
self.l2_cache = redis.Redis() # Redis缓存
def _get_key(self, prompt: str) -> str:
"""生成缓存key"""
return hashlib.md5(prompt.encode()).hexdigest()
def get(self, prompt: str) -> Optional[str]:
"""获取缓存"""
key = self._get_key(prompt)
# L1缓存
if key in self.l1_cache:
return self.l1_cache[key]
# L2缓存
cached = self.l2_cache.get(key)
if cached:
# 回填L1
self.l1_cache[key] = cached
return cached
return None
def set(self, prompt: str, response: str, ttl: int = 3600):
"""设置缓存"""
key = self._get_key(prompt)
# L1(短期)
self.l1_cache[key] = response
# L2(长期)
self.l2_cache.setex(key, ttl, response)
# 使用
cache = MultiLevelCache()
async def cached_chat(prompt: str) -> str:
# 检查缓存
cached = cache.get(prompt)
if cached:
return cached
# 生成
response = await generate(prompt)
# 缓存
cache.set(prompt, response)
return response
4.3 连接池
# 数据库连接池
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
engine = create_engine(
"postgresql://user:pass@localhost/db",
pool_size=20, # 连接池大小
max_overflow=10,
pool_pre_ping=True # 自动检测连接
)
# HTTP连接池
import httpx
async_client = httpx.AsyncClient(
limits=httpx.Limits(
max_connections=100,
max_keepalive_connections=20
),
timeout=httpx.Timeout(30.0)
)
# LLM客户端连接池
from openai import AsyncOpenAI
client = AsyncOpenAI(
max_retries=3,
timeout=30.0
)
五、Prompt优化
5.1 减少Token数
# 优化前
LONG_PROMPT = """
你是一个专业的Python开发工程师,拥有10年开发经验。
你熟悉各种Python框架,包括Django、Flask、FastAPI等。
你擅长编写高质量的Python代码,注重代码的可读性和可维护性。
你的回答应该简洁明了,直接给出代码示例。
请回答以下问题:
"""
# 优化后
SHORT_PROMPT = "Python专家,简洁回答,带代码示例。"
# 节省:约100 tokens = 50ms延迟
5.2 结构化Prompt
# 使用JSON格式,减少解析时间
STRUCTURED_PROMPT = """
分析以下代码,返回JSON格式:
代码:
{code}
返回格式:
{{
"issues": [
{{
"line": 行号,
"severity": "high/medium/low",
"description": "问题描述"
}}
],
"suggestions": ["建议1", "建议2"]
}}
"""
# 比自然语言输出更快解析
六、监控与调优
6.1 性能监控
# 使用Prometheus监控
from prometheus_client import Counter, Histogram, Gauge
import time
# 定义指标
REQUEST_COUNT = Counter('ai_requests_total', 'Total requests')
REQUEST_LATENCY = Histogram('ai_request_latency_seconds', 'Request latency')
QUEUE_SIZE = Gauge('ai_queue_size', 'Current queue size')
# 装饰器监控
def monitor_performance(func):
@wraps(func)
async def wrapper(*args, **kwargs):
start = time.time()
REQUEST_COUNT.inc()
try:
result = await func(*args, **kwargs)
return result
finally:
latency = time.time() - start
REQUEST_LATENCY.observe(latency)
return wrapper
@monitor_performance
async def generate_response(prompt: str):
return await llm.generate(prompt)
6.2 性能分析
# 使用cProfile分析
import cProfile
import pstats
def profile_function():
profiler = cProfile.Profile()
profiler.enable()
# 你的代码
result = slow_function()
profiler.disable()
# 输出统计
stats = pstats.Stats(profiler)
stats.sort_stats('cumulative')
stats.print_stats(20) # Top 20
return result
# 使用line_profiler逐行分析
# @profile
def function_to_profile():
pass
七、部署优化
7.1 容器优化
# 优化后的Dockerfile
FROM nvidia/cuda:12.1-devel-ubuntu22.04
# 减少层数
RUN apt-get update && apt-get install -y
python3-pip
&& rm -rf /var/lib/apt/lists/*
# 先复制requirements,利用缓存
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 再复制代码
COPY . .
# 使用非root用户
RUN useradd -m appuser
USER appuser
CMD ["python", "app.py"]
7.2 Kubernetes优化
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ai-service
spec:
replicas: 3
template:
spec:
containers:
- name: ai
image: ai-service:latest
resources:
requests:
memory: "8Gi"
cpu: "4"
nvidia.com/gpu: 1
limits:
memory: "16Gi"
cpu: "8"
nvidia.com/gpu: 1
# 健康检查
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 60
readinessProbe:
httpGet:
path: /ready
port: 8000
initialDelaySeconds: 30
# GPU亲和性
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: nvidia.com/gpu.product
operator: In
values:
- NVIDIA-A100
八、总结
优化效果
| 优化项 | 效果 |
|---|---|
| 流式输出 | 首Token延迟降低90% |
| 量化推理 | 速度提升2-3倍 |
| 缓存命中 | 减少50% API调用 |
| 批处理 | 吞吐量提升3-5倍 |
| 投机解码 | 速度提升2-3倍 |
优化路径
阶段1:快速优化(1天)
- 启用流式输出
- 添加缓存
- 优化Prompt
阶段2:系统优化(1周)
- 异步架构
- 批处理
- 连接池
阶段3:深度优化(2周)
- 模型量化
- 投机解码
- 负载均衡
相关阅读
正文完