Spaces:
Running
Running
File size: 6,733 Bytes
ad05511 f3c81c5 ad05511 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
"""
用户输入数据模型定义
使用Pydantic进行数据验证
"""
from pydantic import BaseModel, Field
from typing import Optional, List
from enum import Enum
class RiskLevel(str, Enum):
"""风险等级枚举"""
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
class ModelType(str, Enum):
"""模型类型枚举"""
SARCO_I = "sarcoI"
SARCO_II = "sarcoII"
class UserInput(BaseModel):
"""用户输入数据模型"""
# 基本信息 (注意:本系统适用于18-55岁成年人群)
age_years: float = Field(..., ge=16, le=120, description="年龄(岁) - 推荐18-55岁")
race_ethnicity: int = Field(..., ge=0, le=4, description="种族/民族编码(0-4)")
# 身体指标
body_mass_index: float = Field(..., ge=10, le=80, description="体质量指数BMI")
WWI: float = Field(..., ge=3, le=50, description="腰围重量指数")
# NHANES PAQ 原始问卷数据
# 工作相关活动
PAQ605: int = Field(..., ge=1, le=2, description="工作高强度活动(1=是,2=否)")
PAQ610: Optional[int] = Field(0, ge=0, le=7, description="工作高强度活动天数/周")
PAD615: Optional[float] = Field(0, ge=0, le=1440, description="工作高强度活动分钟数/天")
PAQ620: int = Field(..., ge=1, le=2, description="工作中等强度活动(1=是,2=否)")
PAQ625: Optional[int] = Field(0, ge=0, le=7, description="工作中等强度活动天数/周")
PAD630: Optional[float] = Field(0, ge=0, le=1440, description="工作中等强度活动分钟数/天")
# 交通相关活动
PAQ635: int = Field(..., ge=1, le=2, description="步行/骑车通勤(1=是,2=否)")
PAQ640: Optional[int] = Field(0, ge=0, le=7, description="步行/骑车通勤天数/周")
PAD645: Optional[float] = Field(0, ge=0, le=1440, description="步行/骑车通勤分钟数/天")
# 休闲运动活动
PAQ650: int = Field(..., ge=1, le=2, description="休闲高强度活动(1=是,2=否)")
PAQ655: Optional[int] = Field(0, ge=0, le=7, description="休闲高强度活动天数/周")
PAD660: Optional[float] = Field(0, ge=0, le=1440, description="休闲高强度活动分钟数/天")
PAQ665: int = Field(..., ge=1, le=2, description="休闲中等强度活动(1=是,2=否)")
PAQ670: Optional[int] = Field(0, ge=0, le=7, description="休闲中等强度活动天数/周")
PAD675: Optional[float] = Field(0, ge=0, le=1440, description="休闲中等强度活动分钟数/天")
# 久坐行为
PAD680: float = Field(..., ge=0, le=1440, description="每日久坐时间(分钟)")
# 医疗史 (筛查模型必需)
arthritis: Optional[int] = Field(0, ge=0, le=1, description="关节炎史(0=无,1=有)")
diabetes: Optional[int] = Field(0, ge=0, le=1, description="糖尿病史(0=无,1=有)")
# 计算得出的衍生特征 (前端计算后传入)
Activity_Sedentary_Ratio: Optional[float] = Field(None, ge=0, le=100, description="久坐活动比例")
Total_Moderate_Minutes_week: Optional[float] = Field(None, ge=0, le=10080, description="每周中等强度运动时间(分钟)")
Total_Moderate_Equivalent_Minutes: Optional[float] = Field(None, ge=0, le=10080, description="每周中等强度等效运动时间(分钟)")
Avg_Vigorous_Duration_Per_Bout: Optional[float] = Field(None, ge=0, le=1440, description="平均高强度运动时长每次(分钟)")
Vigorous_MET_Ratio: Optional[float] = Field(None, ge=0, le=10, description="高强度运动比例")
Activity_Diversity_Index: Optional[float] = Field(None, ge=0, le=5, description="活动多样性指数(0-5)")
sedentary_minutes: Optional[float] = Field(None, ge=0, le=1440, description="每日久坐时间(分钟,同PAD680)")
class Config:
json_schema_extra = {
"example": {
"age_years": 45,
"race_ethnicity": 2,
"body_mass_index": 28.5,
"WWI": 11.2,
"PAQ605": 2,
"PAQ620": 1,
"PAQ625": 3,
"PAD630": 60,
"PAQ635": 1,
"PAQ640": 5,
"PAD645": 30,
"PAQ650": 1,
"PAQ655": 2,
"PAD660": 45,
"PAQ665": 1,
"PAQ670": 3,
"PAD675": 60,
"PAD680": 480,
"arthritis": 0,
"diabetes": 0,
"Activity_Sedentary_Ratio": 0.6,
"Total_Moderate_Minutes_week": 150,
"Total_Moderate_Equivalent_Minutes": 150,
"Avg_Vigorous_Duration_Per_Bout": 30,
"Vigorous_MET_Ratio": 0.3,
"Activity_Diversity_Index": 3,
"sedentary_minutes": 480
}
}
class ScreeningRequest(BaseModel):
"""筛查请求模型"""
user_data: UserInput
models: List[ModelType] = [ModelType.SARCO_I, ModelType.SARCO_II]
class AdvisoryRequest(BaseModel):
"""建议请求模型"""
user_data: UserInput
risk_types: List[ModelType] = []
num_recommendations: int = Field(default=3, ge=1, le=5, description="建议数量")
language: str = Field(default="zh", description="语言设置 (zh/en)")
class ScreeningResponse(BaseModel):
"""筛查响应模型"""
# 筛查模型结果 (高召回率)
sarcoI_risk: RiskLevel
sarcoI_probability: float
sarcoI_threshold: float
sarcoII_risk: RiskLevel
sarcoII_probability: float
sarcoII_threshold: float
# 建议模型结果 (高精确率)
sarcoI_advisory_risk: Optional[RiskLevel] = None
sarcoI_advisory_probability: Optional[float] = None
sarcoI_advisory_threshold: Optional[float] = None
sarcoII_advisory_risk: Optional[RiskLevel] = None
sarcoII_advisory_probability: Optional[float] = None
sarcoII_advisory_threshold: Optional[float] = None
# 综合结果
overall_risk: RiskLevel
confidence: float
processing_time: float
class RecommendationItem(BaseModel):
"""单个建议项"""
title: str
description: str
priority: str
target_change: Optional[str] = None
expected_impact: Optional[str] = None
class AdvisoryResponse(BaseModel):
"""建议响应模型"""
sarcoI_recommendations: List[RecommendationItem]
sarcoII_recommendations: List[RecommendationItem]
recommendations: Optional[List[RecommendationItem]] = None # 合并的建议列表,用于前端显示
priority_actions: List[str]
target_metrics: dict
processing_time: float
success: bool
fallback_used: bool = False
class ErrorResponse(BaseModel):
"""错误响应模型"""
error: str
detail: str
timestamp: str |