AI产品灰度发布实战:从“全量硬推”到“5%灰度”
模型迭代了,不敢全量推。万一新模型效果回退,所有用户都会受影响。灰度发布不是大厂专利,个人项目也能做。
背景
灵析的LSTM模型从V1.0迭代到V2.0,离线测试RMSE下降了31%,但离线测试≠线上效果。如果直接全量替换,万一线上数据分布和测试集不一样,所有用户都会看到偏差的分析结果。
坑1:灰度发布不知道怎么配
问题: 新模型不敢全量推,但没有灰度机制,只能二选一——要么全量,要么不回。
解决方案:环境变量控制流量比例
import os
import random
NEW_MODEL_RATIO = int(os.getenv("NEW_MODEL_RATIO", 5)) # 默认5%流量走新模型
def get_prediction(data):
# 根据用户ID或随机数决定走哪套模型
use_new_model = random.randint(1, 100) <= NEW_MODEL_RATIO
if use_new_model:
result = new_model.predict(data)
model_version = "v2.0"
else:
result = old_model.predict(data)
model_version = "v1.0"
return {
"result": result,
"model_version": model_version,
"is_gray": use_new_model
}
启动时配置:
# 5%流量走新模型
docker run -e NEW_MODEL_RATIO=5 lingxi-backend
# 灰度验证通过后,逐步放量
docker run -e NEW_MODEL_RATIO=20 lingxi-backend
docker run -e NEW_MODEL_RATIO=50 lingxi-backend
docker run -e NEW_MODEL_RATIO=100 lingxi-backend
坑2:合规拦截计数重复
表象: 用户问了一次问题,系统显示拦截了2次。
根本原因: 前端按钮没有防抖,用户快速点击两次,后端收到两个请求,各拦截一次,计数重复。
解决方案:
// 前端:发送后禁用按钮
function sendQuestion() {
const btn = document.getElementById('send-btn');
btn.disabled = true;
btn.textContent = '发送中...';
api.chat(question)
.then(response => {
// 处理响应
})
.finally(() => {
btn.disabled = false;
btn.textContent = '发送';
});
}
# 后端:分布式防抖(基于用户+问题去重)
from functools import lru_cache
import hashlib
def deduplicate(user_id, question):
key = hashlib.md5(f"{user_id}:{question}".encode()).hexdigest()
if key in recent_requests:
return False # 重复请求
recent_requests.add(key)
return True
坑3:模型回滚接口——解决“怎么回滚”,只有函数没有接口
问题: “模型出问题了怎么回滚”,“执行脚本切换”,“有HTTP接口”
解决方案:加管理接口
from fastapi import APIRouter
admin_router = APIRouter(prefix="/api/admin")
@admin_router.post("/model/rollback")
def rollback_model(target_version: str):
"""一键回滚到指定版本"""
if target_version not in available_versions:
return {"error": f"版本 {target_version} 不存在"}
# 切换模型
current_version = switch_model(target_version)
return {
"status": "success",
"current_version": current_version,
"rollback_at": datetime.now().isoformat()
}
@admin_router.get("/model/versions")
def list_versions():
"""查看所有可用版本"""
return {
"available": available_versions,
"current": current_model_version,
"metrics": get_model_metrics(current_model_version)
}
使用方式:
# 查看当前版本
curl /api/admin/model/versions
# 一键回滚
curl -X POST /api/admin/model/rollback?target_version=v1.0

浙公网安备 33010602011771号