4. Flask REST API 服务搭建
将训练好的 XGBoost 模型封装为可对外提供实时预测的 REST API,是模型上线的关键一步。Flask 作为轻量级 Python Web 框架,非常适合快速搭建评分服务。本节将系统讲解 Flask 基础、模型加载、预测接口设计以及请求/响应格式规范。
核心目标:构建一个稳定、可复用的 XGBoost 评分服务端点,接收特征数据并返回预测结果。
4.1 Flask 框架基础
Flask 是一个基于 Werkzeug 和 Jinja2 的微框架,核心概念包括路由、视图函数和请求/响应对象。在评分服务中,我们主要使用其 RESTful 能力。
| 组件 | 说明 | 评分服务中的角色 |
|---|---|---|
| Flask 应用实例 | app = Flask(__name__) | 服务入口,管理路由与配置 |
| 路由装饰器 | @app.route('/predict', methods=['POST']) | 定义预测端点 |
| 请求对象 | request.get_json() | 解析客户端传入的特征数据 |
| 响应对象 | jsonify() | 返回标准 JSON 格式预测结果 |
最佳实践:使用
app.run(host='0.0.0.0', port=5000, threaded=True) 启动服务,支持多线程并发请求。
4.2 模型加载策略
模型加载是评分服务的性能瓶颈之一。正确的做法是在服务启动时全局加载一次,避免每次请求都重新加载模型文件。
import xgboost as xgb
from flask import Flask, request, jsonify
app = Flask(__name__)
# 全局加载模型(服务启动时执行一次)
model_path = './models/xgb_model.json'
try:
booster = xgb.Booster()
booster.load_model(model_path)
print(f"[INFO] 模型加载成功: {model_path}")
except Exception as e:
print(f"[ERROR] 模型加载失败: {e}")
booster = None
注意:模型文件路径建议使用绝对路径或环境变量配置,避免相对路径在不同工作目录下引发 FileNotFoundError。
4.3 预测接口设计
预测接口是服务的核心,需要处理请求解析、特征校验、模型预测和异常捕获四个环节。
@app.route('/predict', methods=['POST'])
def predict():
# 1. 检查模型是否可用
if booster is None:
return jsonify({'error': '模型未加载,服务不可用'}), 500
# 2. 解析请求 JSON
data = request.get_json()
if not data or 'features' not in data:
return jsonify({'error': '请求格式错误,缺少 features 字段'}), 400
# 3. 特征校验与转换
try:
features = data['features']
# 假设 features 为二维列表 [[f1, f2, ...]]
dmatrix = xgb.DMatrix(features)
except Exception as e:
return jsonify({'error': f'特征数据格式错误: {str(e)}'}), 400
# 4. 模型预测
try:
preds = booster.predict(dmatrix)
# 将 numpy 数组转为列表,便于 JSON 序列化
result = preds.tolist()
return jsonify({'prediction': result, 'status': 'success'}), 200
except Exception as e:
return jsonify({'error': f'预测过程异常: {str(e)}'}), 500
4.4 请求与响应格式规范
统一的请求/响应格式有助于客户端集成和服务维护。推荐遵循以下规范:
请求格式
{
"features": [
[5.1, 3.5, 1.4, 0.2], // 第一条样本
[6.2, 2.9, 4.3, 1.3] // 第二条样本
],
"options": {
"output_margin": false, // 可选:是否输出原始 margin
"ntree_limit": 0 // 可选:限制使用的树数量
}
}
成功响应格式
{
"status": "success",
"prediction": [0.982, 0.015], // 预测结果列表
"model_version": "v1.0.0",
"timestamp": "2025-03-21T10:30:00Z"
}
错误响应格式
{
"status": "error",
"error": "特征数据格式错误: list index out of range",
"error_code": "INVALID_FEATURES"
}
| HTTP 状态码 | 场景 | 响应体关键字段 |
|---|---|---|
| 200 | 预测成功 | status: "success", prediction |
| 400 | 请求格式错误、特征缺失或类型错误 | status: "error", error, error_code |
| 500 | 模型未加载、预测过程异常 | status: "error", error |
生产建议:添加
model_version 和 timestamp 字段便于问题追踪;使用 error_code 枚举值(如 INVALID_FEATURES、MODEL_NOT_LOADED)方便客户端程序化处理。
4.5 完整服务启动脚本
if __name__ == '__main__':
# 生产环境建议使用 Gunicorn 等 WSGI 服务器
# 开发调试可直接运行
app.run(host='0.0.0.0', port=5000, debug=False, threaded=True)
安全提醒:生产环境务必关闭
debug=True,避免泄露敏感信息。使用 threaded=True 提升并发能力,但需注意模型预测的线程安全性(XGBoost 的 predict 方法是线程安全的)。
通过以上步骤,我们完成了一个具备完整错误处理、统一格式规范的 XGBoost 评分 REST API 服务。下一环节将介绍如何对服务进行单元测试与集成测试,确保上线质量。