机器学习模型处理输入数据并生成预测后,请求-响应周期的最后一步是将这些结果发送回客户端。您如何构建此响应对于易用性以及与后续应用的集成很重要。仅仅返回原始数字或字符串通常是不够的。客户端通常会从一个定义良好的JSON对象中受益,该对象包含预测结果以及其他可能的相关信息,如置信度分数或概率。FastAPI 结合 Pydantic,使得使用响应模型来定义和执行这些响应结构变得直接简单。构建预测响应让我们从一个基本情况开始:一个预测单个类别标签的分类模型。虽然您可以只返回标签作为字符串,但更好的做法是将其封装在一个 JSON 对象中。这能提供上下文,并使 API 响应更具自我描述性。我们可以定义一个 Pydantic 模型来表示这种结构:from pydantic import BaseModel, Field class PredictionResponse(BaseModel): predicted_class: str = Field(..., description="预测的类别标签。") # 之后您可能还会添加其他字段,例如请求 ID 或模型版本在您的端点中,您将在路径操作装饰器的 response_model 参数中使用此模型。FastAPI 会自动处理将返回值(例如字典或另一个 Pydantic 模型实例)序列化为符合 PredictionResponse 格式的 JSON。# 假设 'model' 是您已加载的机器学习模型对象 # 假设 'InputFeatures' 是您的 Pydantic 输入模型 @app.post("/predict", response_model=PredictionResponse) async def make_prediction(features: InputFeatures): # 1. 如有必要,对特征进行预处理 processed_data = preprocess(features.dict()) # 预处理示例 # 2. 从模型获取预测结果 # 假设 model.predict() 直接返回类别标签 prediction_label = model.predict(processed_data) # 3. 返回符合响应模型的结果 return PredictionResponse(predicted_class=prediction_label) 这种方式确保响应格式一致,并自动将其包含在 FastAPI 生成的 API 文档中。包含概率或置信度分数对于许多分类任务,了解模型对其预测结果的置信度与预测结果本身同样重要。大多数分类模型可以输出每个可能类别的概率。例如,scikit-learn 分类器通常有一个 predict_proba() 方法,该方法返回一个包含每个类别概率的数组。返回这些概率能为客户端提供有用的背景信息。他们可以使用此信息来设置决策阈值,或识别需要人工审查的不确定预测。为了包含概率,我们扩展了 Pydantic 响应模型:from pydantic import BaseModel, Field from typing import List, Dict class ProbabilityResponse(BaseModel): predicted_class: str = Field(..., description="预测的类别标签。") probabilities: Dict[str, float] = Field(..., description="一个字典,将类别标签映射到其预测概率。") # 示例: {"cat": 0.95, "dog": 0.04, "other": 0.01} @app.post("/predict_proba", response_model=ProbabilityResponse) async def make_prediction_with_proba(features: InputFeatures): processed_data = preprocess(features.dict()) # 假设 model.predict() 提供标签 prediction_label = model.predict(processed_data) # 假设 model.predict_proba() 提供每个类别的概率 # 并且 model.classes_ 提供类别的顺序 proba_values = model.predict_proba(processed_data)[0] # 获取第一个(也是唯一一个)输入样本的概率 class_labels = model.classes_ probabilities_dict = {label: proba for label, proba in zip(class_labels, proba_values)} # 排序概率以便于阅读(可选) sorted_probabilities = dict(sorted(probabilities_dict.items(), key=lambda item: item[1], reverse=True)) return ProbabilityResponse( predicted_class=prediction_label, probabilities=sorted_probabilities ) 在此示例中,ProbabilityResponse 定义了一个结构,其中包含最可能的类别(predicted_class)以及一个字典(probabilities),该字典包含与每个可能类别相关的概率。端点从模型中获取预测结果和概率,并根据此结构进行打包。这些概率的可视化表示有时有助于理解模型的置信度分布。{"layout": {"title": "类别概率示例", "xaxis": {"title": "概率", "range": [0, 1]}, "yaxis": {"title": "类别", "categoryorder": "total descending"}, "margin": {"l": 50, "r": 20, "t": 40, "b": 40}, "height": 250, "width": 400}, "data": [{"type": "bar", "y": ["类别 A", "类别 B", "类别 C", "类别 D"], "x": [0.75, 0.15, 0.08, 0.02], "orientation": "h", "marker": {"color": ["#4263eb", "#adb5bd", "#adb5bd", "#adb5bd"]}}]}单个输入实例在不同类别上的预测概率分布示例。类别 A 具有最高概率。适应不同模型输出您的响应模型结构应自然地反映您的特定机器学习模型的输出:回归模型: 您可能返回单个 predicted_value(浮点数)而不是 predicted_class 和 probabilities,并且可能包含一个 confidence_interval(例如,一个包含 lower_bound 和 upper_bound 的字典)。多输出模型: 响应模型可能包含多个预测字段或预测/概率列表。对象检测/图像分割: 响应可能涉及边界框列表(包含坐标和类别标签)或图像掩码。核心思路保持不变:定义一个 Pydantic 模型,精确描述预期的输出格式,并在端点装饰器的 response_model 参数中使用它。这为您的 API 使用者提供了清晰的约定,并使用了 FastAPI 的验证和文档功能。请记住,在返回浮点数(如概率)时,要考虑数值精度。您可能希望在返回响应之前,在端点逻辑中将它们四舍五入到合理的 H 位小数。此外,确保您的端点在预测过程中优雅地处理潜在错误,或许返回特定的 HTTP 错误代码和消息,而不是标准的预测响应。