FastAPI返回ML模型预测结果时报Internal Server Error
FastAPI机器学习推理接口500错误排查
故障原因
- 本地
print()调试可以正常输出结果、接口返回普通字符串时响应正常,说明请求参数校验、模型加载、推理逻辑本身没有问题。 - 触发
Internal Server Error的核心原因是:scikit-learn模型的predict()方法返回值是numpy数据类型(numpy数组/numpy.int64/numpy.float64等),FastAPI默认使用的JSON序列化器无法识别这类非Python原生的数据类型,序列化响应阶段直接抛出异常,最终返回500错误。如果查看FastAPI运行的终端日志,会看到类似TypeError: Object of type int64 is not JSON serializable的明确报错。 - 本地调试时
print()只需要调用对象的字符串表示方法,不需要做JSON格式转换,因此不会触发该问题。
修复方法
- 把模型推理返回的numpy类型转为Python原生类型再返回,修改接口的返回逻辑即可:
# 原错误写法:直接返回numpy类型的预测结果 # return { # "Predicted transaction(1 - fraud, 0 - not fraud)": new_prediction # } # 修复后写法:转成Python原生int/列表 new_prediction = rf_model.predict(new) return { # 单样本预测取第一个值转原生int,也可以用new_prediction.tolist()直接转成Python列表 "Predicted transaction(1 - fraud, 0 - not fraud)": int(new_prediction[0]) }
- 性能优化:把模型加载代码
rf_model = joblib.load('./rf_model.pkl')移到接口函数的外部,在服务启动时只加载一次模型即可。放在接口内部会导致每次请求进来都重复读取磁盘加载模型,接口响应速度会非常慢。
相关代码参考
业务接口原实现
class FraudDetection333(BaseModel): """ Input features validation for the ML model """ user_id: int signup_day: int signup_month: int signup_year: int purchase_day: int purchase_month: int purchase_year: int purchase_value: float source: str browser: str sex: str age: int @api.post("/predictions_test",tags=['DecisionTreeClassifier']) def predictions_test(fraud:FraudDetection333): """ :param:input data from the post request :return predicted type """ features = [[ fraud.user_id, fraud.signup_day, fraud.signup_month, fraud.signup_year, fraud.purchase_day, fraud.purchase_month, fraud.purchase_year, fraud.purchase_value, fraud.source, fraud.browser, fraud.sex, fraud.age ]] rf_model = joblib.load('./rf_model.pkl') new = (pd.DataFrame(features, index = ['0'], columns = ['user_id','signup_day', 'signup_month', 'signup_year', 'purchase_day', 'purchase_month', 'purchase_year','purchase_value', 'source','browser','sex','age'])) new_prediction = rf_model.predict(new) return { "Predicted transaction(1 - fraud, 0 - not fraud)": new_prediction }
本地正常运行的调试代码
featuress={ "user_id": 22058, "signup_day": 24, "signup_month": 2, "signup_year": 2015, "purchase_day": 18, "purchase_month": 4, "purchase_year": 2015, "purchase_value": 34, "source": "SEO", "browser": "Chrome", "sex": "M", "age": 39 } rf_model = joblib.load('./rf_model.pkl') new = (pd.DataFrame(featuress, index = ['0'], columns = ['user_id','signup_day', 'signup_month', 'signup_year', 'purchase_day', 'purchase_month', 'purchase_year','purchase_value', 'source','browser','sex','age'])) new_prediction = rf_model.predict(new) print(new) print(new_prediction)
内容的提问来源于stack exchange,提问作者Anastasia_data
相关产品推荐
相关产品推荐

