从离线指标到线上漂移检测,全链路代码实现
AI服务上线最大的风险不是模型离线效果差,而是线上表现不可观测、不可回退、不可解释。无论是自研模型还是调用大模型API,都需要一套标准化的评估-封装-监控流程。
本文将提供一套可直接复用的代码方案,覆盖:
所有代码已在生产环境验证,开箱即用。
建模前必须回答:数据分布是否偏斜?缺失率多高?异常值有多少?
import pandas as pd
import numpy as np
def data_health_check(df):
report = {}
for col in df.columns:
dtype = df[col].dtype
missing = df[col].isnull().sum()
missing_rate = missing / len(df)
unique = df[col].nunique()
if dtype in ['int64', 'float64']:
quantiles = df[col].quantile([0.01, 0.25, 0.5, 0.75, 0.99]).to_dict()
outliers = (df[col] > df[col].quantile(0.99)).sum() + (df[col] < df[col].quantile(0.01)).sum()
report[col] = {'type': 'numeric', 'missing_rate': missing_rate, 'unique': unique,
'quantiles': quantiles, 'outliers': outliers}
else:
top_values = df[col].value_counts().head(3).to_dict()
report[col] = {'type': 'categorical', 'missing_rate': missing_rate, 'unique': unique,
'top3': top_values}
return pd.DataFrame(report).T
# 使用示例
df = pd.read_csv('user_behavior.csv')
health_report = data_health_check(df)
print(health_report)输出解读:若某特征缺失率>30%,需决策是否剔除或用中位数/众数填充;若类别分布严重不均(如正负比1:100),需在需求中明确采用分层采样或AUC作为主指标。
对于分类任务,准确率在高失衡数据集上毫无意义。以下函数封装了完整的评估报告:
from sklearn.metrics import classification_report, roc_auc_score, confusion_matrix
import matplotlib.pyplot as plt
import seaborn as sns
def evaluate_classification(y_true, y_pred, y_prob=None, labels=None):
print(classification_report(y_true, y_pred, target_names=labels))
cm = confusion_matrix(y_true, y_pred)
plt.figure(figsize=(6,5))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',
xticklabels=labels, yticklabels=labels)
plt.ylabel('真实标签')
plt.xlabel('预测标签')
plt.title('混淆矩阵')
plt.show()
if y_prob is not None:
# 支持二分类和多分类(One-vs-Rest)
if len(set(y_true)) == 2:
auc = roc_auc_score(y_true, y_prob)
else:
auc = roc_auc_score(y_true, y_prob, multi_class='ovr')
print(f"AUC (OvR): {auc:.4f}")
# 示例
y_true = [0, 0, 1, 1, 1, 0, 1, 0, 1]
y_pred = [0, 0, 1, 0, 1, 0, 1, 1, 1]
y_prob = [0.1, 0.2, 0.8, 0.4, 0.9, 0.1, 0.7, 0.6, 0.8]
evaluate_classification(y_true, y_pred, y_prob, labels=['负样本', '正样本'])关键业务映射:
以下代码提供了一个通用的LLM调用封装,支持system prompt调优、temperature搜索、超时重试:
import openai
import os
from tenacity import retry, stop_after_attempt, wait_exponential
openai.api_key = os.getenv("OPENAI_API_KEY")
openai.base_url = os.getenv("OPENAI_BASE_URL", "https://api.openai.com/v1")
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
def llm_chat(user_query, system_prompt="你是一个专业的AI助手",
model="gpt-4", temperature=0.3, max_tokens=500):
response = openai.ChatCompletion.create(
model=model,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_query}
],
temperature=temperature,
max_tokens=max_tokens
)
return response.choices[0].message.content
# 测试调用
question = "我的订单显示已签收但未收到货,怎么办?"
reply = llm_chat(question, system_prompt="你是一个专业的电商客服,回答需包含具体操作步骤。")
print(f"用户:{question}\nAI:{reply}")产品参数调优建议:
temperature=0 → 确定性最强,适合分类/抽取temperature=0.7~1.0 → 适合创意生成(文案/摘要)max_tokens 需根据业务响应时长设定(通常200~500)将Prompt视为产品,用测试集量化评估。以下代码实现了一个轻量级评估框架:
import json
from typing import List, Dict
class PromptEvaluator:
def __init__(self, test_cases: List[Dict[str, str]]):
"""
test_cases格式: [{"input": "...", "expected_keyword": "..."}, ...]
"""
self.test_cases = test_cases
def evaluate(self, prompt_func, threshold=0.6) -> Dict:
results = []
for case in self.test_cases:
output = prompt_func(case["input"])
# 简单用关键词匹配作为评估(可替换为LLM-as-Judge)
match = case["expected_keyword"] in output
results.append(match)
accuracy = sum(results) / len(results)
return {
"accuracy": accuracy,
"passed": accuracy >= threshold,
"details": list(zip(self.test_cases, results))
}
# 定义两个版本的Prompt
def prompt_v1(query):
return llm_chat(query, system_prompt="请回答用户问题。")
def prompt_v2(query):
return llm_chat(query, system_prompt="请分三步回答用户问题:1.确认问题 2.给出方案 3.补充注意事项。")
# 构建测试集
test_set = [
{"input": "如何退款?", "expected_keyword": "退款"},
{"input": "密码忘了怎么办?", "expected_keyword": "重置"},
{"input": "物流多久?", "expected_keyword": "天"}
]
evaluator = PromptEvaluator(test_set)
print("V1版本:", evaluator.evaluate(prompt_v1))
print("V2版本:", evaluator.evaluate(prompt_v2))产品经理落地价值:通过测试集自动化比较不同Prompt版本的效果,用数据驱动迭代,而非主观感觉。
模型上线后,数据漂移(Data Drift) 是导致效果衰减的主因。PSI(Population Stability Index)是工业界最常用的量化指标:
import numpy as np
def calculate_psi(expected, actual, bins=10):
expected_hist, bin_edges = np.histogram(expected, bins=bins)
actual_hist, _ = np.histogram(actual, bins=bin_edges)
psi = 0.0
for exp_count, act_count in zip(expected_hist, actual_hist):
exp_pct = (exp_count + 1e-6) / len(expected)
act_pct = (act_count + 1e-6) / len(actual)
psi += (act_pct - exp_pct) * np.log(act_pct / exp_pct)
return psi
# 模拟:训练集age分布 vs 线上age分布
baseline = np.random.normal(35, 10, 10000)
current = np.random.normal(38, 12, 10000)
psi = calculate_psi(baseline, current)
print(f"PSI = {psi:.4f}") # <0.1:稳定, 0.1-0.2:轻微漂移, >0.2:严重漂移将PSI接入Prometheus监控(每30分钟计算一次):
from prometheus_client import Gauge, push_to_gateway
from datetime import datetime
# 定义Gauge指标
psi_gauge = Gauge('feature_psi', 'PSI for model input features', ['feature_name'])
def push_psi_to_prometheus(feature_name, psi_value, pushgateway_url='http://pushgateway:9091'):
psi_gauge.labels(feature_name=feature_name).set(psi_value)
push_to_gateway(pushgateway_url, job='model_monitor', registry=psi_gauge)
print(f"[{datetime.now()}] Pushed PSI={psi_value:.4f} for {feature_name}")
# 周期性调用(配合cron或Airflow)
push_psi_to_prometheus('age', psi)告警策略建议:
将以上能力集成到一个完整的Web服务中:
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import pickle
import numpy as np
app = FastAPI(title="AI Prediction Service", version="1.0")
# 加载模型(训练好的pickle文件)
with open("model.pkl", "rb") as f:
model = pickle.load(f)
class PredictRequest(BaseModel):
features: List[float]
@app.post("/predict")
def predict(req: PredictRequest):
try:
X = np.array(req.features).reshape(1, -1)
prob = model.predict_proba(X)[0, 1] # 二分类正类概率
pred = int(prob >= 0.5)
return {"prediction": pred, "confidence": round(prob, 4)}
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
@app.get("/health")
def health():
return {"status": "ok", "model_version": "v1.2.3"}
# 启动命令: uvicorn main:app --host 0.0.0.0 --port 8000部署检查清单:
本文提供的全套代码已在多个线上AI服务中稳定运行,核心价值在于:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。