全部笔记All notes

大模型应用生产环境最佳实践

阅读 7m 33s7m 33s read

生产环境最佳实践

大模型 API 在生产环境中的限流、监控、安全和运维策略。


生产环境的挑战

将大模型 API 应用于生产环境,面临诸多挑战:

  • 成本控制:API 调用费用可能快速增长
  • 稳定性:外部 API 可能不可用或响应慢
  • 安全性:防止 API Key 泄露、恶意调用
  • 可观测性:需要监控调用量、延迟、错误率

本文档提供经过验证的最佳实践,帮助你构建稳定可靠的生产系统。

生产环境 vs 开发环境的关键差异:

方面开发环境生产环境
错误处理简单打印完整的重试、降级、告警
监控可选必须
安全基本多层防护
成本不敏感严格控制
可用性可接受中断99.9%+
日志简单结构化、可追溯

生产架构

一个健壮的生产架构应该包含多个层次的保护和优化:

flowchart TD
    A[客户端] --> B[API 网关]
    B --> C[限流器]
    C --> D[负载均衡]
    D --> E[LLM 代理服务]
    
    E --> F[OpenAI]
    E --> G[Claude]
    E --> H[Gemini]
    
    E --> I[(缓存)]
    E --> J[(日志)]
    E --> K[监控]

各组件职责:

组件职责推荐工具
API 网关认证、路由、协议转换Kong, AWS API Gateway
限流器保护后端、防止滥用Redis, 令牌桶
负载均衡分发请求、健康检查Nginx, HAProxy
LLM 代理统一接口、模型路由LiteLLM, One API
缓存减少重复调用Redis, Memcached
日志审计、排错ELK, Loki
监控告警、可视化Prometheus, Grafana

限流策略

限流是保护系统的第一道防线。没有限流,恶意用户或程序 bug 可能导致巨额账单。

为什么限流如此重要?

  1. 成本保护:防止意外的大量调用导致账单爆炸
  2. 公平性:防止单个用户占用过多资源
  3. 稳定性:防止系统过载
  4. 安全性:减缓恶意攻击的影响

多级限流

建议实施多级限流,从细到粗:

  • 用户级:限制单个用户的调用频率
  • API Key 级:限制单个 Key 的总调用量
  • 全局级:限制系统总体调用量
flowchart LR
    A[请求] --> B{用户限流}
    B -->|通过| C{API 限流}
    C -->|通过| D{全局限流}
    D -->|通过| E[处理]
    
    B -->|拒绝| F[429]
    C -->|拒绝| F
    D -->|拒绝| F

限流维度

维度说明示例适用场景
用户级每用户限制100 次/分钟防止单用户滥用
API Key 级每 Key 限制1000 次/分钟多租户隔离
全局级总体限制10000 次/分钟保护系统整体
Token 级按 Token 计费100K tokens/小时成本控制

令牌桶算法

令牌桶是最常用的限流算法,它允许一定程度的突发流量,同时保证长期平均速率。

工作原理:

  1. 桶以固定速率补充令牌
  2. 每个请求消耗一个令牌
  3. 桶满时令牌不再增加
  4. 桶空时请求被拒绝
class TokenBucket:
    def __init__(self, rate, capacity):
        self.rate = rate        # 每秒补充
        self.capacity = capacity
        self.tokens = capacity
        self.last = time.time()
    
    def acquire(self):
        now = time.time()
        self.tokens = min(
            self.capacity,
            self.tokens + (now - self.last) * self.rate
        )
        self.last = now
        
        if self.tokens >= 1:
            self.tokens -= 1
            return True
        return False

限流响应处理:

当请求被限流时,应该返回清晰的错误信息和重试建议:

# 返回 429 状态码和重试时间
return JSONResponse(
    status_code=429,
    content={
        "error": "rate_limit_exceeded",
        "message": "请求过于频繁,请稍后重试",
        "retry_after": 60  # 建议等待秒数
    },
    headers={"Retry-After": "60"}
)

监控指标

“没有度量就没有管理”。生产环境必须建立完善的监控体系。

核心指标

关注以下四个黄金指标(Google SRE 推荐):

  • 延迟:请求响应时间,关注 P99
  • 吞吐:每秒处理请求数
  • 错误率:失败请求占比
  • 成本:Token 消耗和费用
flowchart LR
    A[监控] --> B[延迟 Latency]
    A --> C[吞吐 Throughput]
    A --> D[错误率 Error Rate]
    A --> E[成本 Cost]
指标计算方式告警阈值说明
P99 延迟99% 请求延迟> 10s用户体验底线
错误率失败数/总数> 5%系统健康度
Token 消耗日累计超预算成本控制
可用性成功数/总数< 99.9%SLA 保障
TTFT首 Token 时间> 3s流式体验

延迟分解:

理解延迟的组成有助于优化:

总延迟 = 网络延迟 + 排队延迟 + 处理延迟
       = (客户端→API) + (API 队列等待) + (模型推理)

日志格式

结构化日志便于查询和分析:

{
  "timestamp": "2025-01-01T00:00:00Z",
  "request_id": "req_xxx",
  "model": "gpt-4o",
  "input_tokens": 100,
  "output_tokens": 50,
  "latency_ms": 1500,
  "status": "success",
  "user_id": "user_xxx",
  "cost_usd": 0.0015,
  "error_code": null,
  "trace_id": "trace_xxx"
}

日志最佳实践:

实践说明
结构化使用 JSON 格式,便于解析
唯一 ID每个请求有唯一标识,便于追踪
脱敏不记录用户输入的敏感内容
采样高流量时可采样记录
保留期根据合规要求设置保留时间

安全策略

安全是生产环境的重中之重。API Key 泄露可能导致巨额损失。

安全层级

建立多层安全防护:

  • 认证:验证调用者身份
  • 授权:检查调用权限
  • 输入过滤:防止恶意输入
  • 输出审核:过滤敏感内容
  • 数据脱敏:保护用户隐私
flowchart TD
    A[安全] --> B[认证]
    A --> C[授权]
    A --> D[输入过滤]
    A --> E[输出审核]
    A --> F[数据脱敏]

API Key 管理

实践说明
环境变量不硬编码 Key
定期轮换每 90 天更换
最小权限按需分配
监控异常检测泄露

输入过滤

def sanitize_input(text):
    # 长度限制
    if len(text) > 10000:
        raise ValueError("输入过长")
    
    # 敏感词过滤
    for word in BLOCKED_WORDS:
        if word in text:
            raise ValueError("包含敏感内容")
    
    return text

高可用设计

单一模型厂商不可避免会出现故障。高可用设计的核心是”不把鸡蛋放在一个篮子里”。

多模型容灾

配置多个模型作为备选,当主模型故障时自动切换。切换应该对用户透明,不影响体验。

建议按照能力相近、成本可接受的原则选择备用模型。

flowchart TD
    A[请求] --> B[主模型 GPT-4o]
    B -->|失败| C[备用 Claude]
    C -->|失败| D[兜底 Gemini]
    
    B -->|成功| E[返回]
    C -->|成功| E
    D -->|成功| E
    D -->|失败| F[降级响应]

健康检查

async def health_check():
    checks = {
        "openai": check_openai(),
        "claude": check_claude(),
        "gemini": check_gemini()
    }
    return await asyncio.gather(*checks.values())

缓存策略

合理使用缓存可以显著降低成本和延迟。但要注意:大模型输出通常有随机性,不是所有场景都适合缓存。

缓存层级

建议使用两级缓存:

  • 本地缓存:进程内缓存,速度最快
  • 分布式缓存:Redis 等,多实例共享
flowchart LR
    A[请求] --> B{本地缓存}
    B -->|命中| C[返回]
    B -->|未命中| D{Redis 缓存}
    D -->|命中| C
    D -->|未命中| E[调用 API]
    E --> F[写入缓存]
    F --> C

缓存 Key 设计

def cache_key(model, messages, params):
    content = json.dumps({
        "model": model,
        "messages": messages,
        "temperature": params.get("temperature", 1)
    }, sort_keys=True)
    return hashlib.md5(content.encode()).hexdigest()

缓存策略选择

不同场景使用不同的缓存策略:

场景TTL说明
确定性回答24htemperature=0
通用问答1h常见问题
实时信息不缓存天气、新闻

成本控制

成本失控是生产环境最常见的问题之一。建议建立预算管理机制,在成本超出预期前及时告警。

预算管理

flowchart TD
    A[请求] --> B{检查预算}
    B -->|充足| C[处理]
    B -->|不足| D[拒绝/降级]
    
    C --> E[扣减预算]
    E --> F[告警检查]
    F -->|超 80%| G[发送告警]

成本分摊

维度说明
按用户用户级计费
按项目项目成本中心
按功能功能模块分摊

运维清单

生产环境运维需要系统化的检查清单,避免遗漏关键步骤。

上线前

上线前务必完成以下检查:

  • API Key 配置正确
  • 限流策略配置
  • 监控告警配置
  • 日志采集配置
  • 容灾方案测试

日常运维

日常运维关注系统健康状态:

  • 监控指标巡检
  • 成本账单审核
  • 错误日志分析
  • 性能优化评估

故障处理

故障发生时,按照标准流程处理:

flowchart LR
    A[告警] --> B[定位]
    B --> C[止血]
    C --> D[修复]
    D --> E[复盘]

灰度发布

新模型或新 Prompt 上线前,建议先进行灰度发布,逐步放量。

灰度策略

flowchart TD
    A[新版本] --> B{灰度比例}
    B -->|5%| C[小流量验证]
    C -->|指标正常| D[扩大到 20%]
    D -->|指标正常| E[扩大到 50%]
    E -->|指标正常| F[全量发布]
    
    C -->|异常| G[回滚]
    D -->|异常| G
    E -->|异常| G

实现方式

import random

def select_model(user_id, gray_ratio=0.1):
    """灰度选择模型"""
    # 基于用户 ID 哈希,保证同一用户始终使用同一版本
    hash_value = hash(user_id) % 100
    
    if hash_value < gray_ratio * 100:
        return "gpt-4o-new"  # 新版本
    return "gpt-4o"  # 稳定版本

A/B 测试

对比不同模型或 Prompt 的效果,用数据驱动决策。

测试指标

指标说明计算方式
响应质量用户满意度评分/点赞率
响应速度延迟P50/P99
成本效率单次成本Token × 单价
完成率任务成功率成功数/总数

实验框架

class ABTest:
    def __init__(self, variants):
        self.variants = variants  # {"A": config_a, "B": config_b}
        self.results = {"A": [], "B": []}
    
    def assign(self, user_id):
        """分配实验组"""
        return "A" if hash(user_id) % 2 == 0 else "B"
    
    def record(self, variant, metrics):
        """记录结果"""
        self.results[variant].append(metrics)
    
    def analyze(self):
        """分析结果"""
        for v, data in self.results.items():
            avg_latency = sum(d["latency"] for d in data) / len(data)
            avg_score = sum(d["score"] for d in data) / len(data)
            print(f"{v}: latency={avg_latency:.2f}s, score={avg_score:.2f}")

容量规划

根据业务增长预估资源需求,避免突发流量导致服务不可用。

容量计算

日请求量 = DAU × 人均请求数
峰值 QPS = 日请求量 / 86400 × 峰值系数(通常 3-5)
Token 预算 = 日请求量 × 平均 Token × 单价

扩容策略

指标阈值动作
CPU > 70%持续 5 分钟扩容
延迟 P99 > 10s持续 3 分钟扩容
错误率 > 5%持续 1 分钟告警 + 排查

相关文档