174 lines
5.5 KiB
Python
174 lines
5.5 KiB
Python
"""Risk prediction request and response contracts."""
|
|
|
|
from typing import Literal
|
|
|
|
from pydantic import Field
|
|
|
|
from app.domain.risk_engine import RiskLevel
|
|
from app.schemas.common import ApiSchema
|
|
|
|
|
|
class RiskIndicator(ApiSchema):
|
|
name: str = Field(min_length=1, max_length=64)
|
|
value: float = Field(ge=0, le=100)
|
|
weight: float = Field(default=1, gt=0, le=100)
|
|
|
|
|
|
class RiskAssessmentRequest(ApiSchema):
|
|
subject_id: str = Field(min_length=1, max_length=128)
|
|
indicators: list[RiskIndicator] = Field(default_factory=list, max_length=50)
|
|
product_category: str | None = Field(default=None, max_length=100)
|
|
material_type: str | None = Field(default=None, max_length=200)
|
|
supplier: str | None = Field(default=None, max_length=300)
|
|
factory: str | None = Field(default=None, max_length=300)
|
|
stage_new: str | None = Field(default=None, max_length=100)
|
|
defect_level: str | None = Field(default=None, max_length=10)
|
|
|
|
|
|
class RiskFactorResult(ApiSchema):
|
|
name: str
|
|
value: float
|
|
weight: float
|
|
contribution: float
|
|
|
|
|
|
class CategoryWarning(ApiSchema):
|
|
category: str
|
|
anomaly_count: int
|
|
risk_level: str
|
|
similar_category: str | None = None
|
|
similar_count: int | None = None
|
|
suggestion: str | None = None
|
|
|
|
|
|
class SupplierFrequency(ApiSchema):
|
|
supplier_name: str | None = None
|
|
cooperation_count: int | None = None
|
|
anomaly_count: int | None = None
|
|
alpha: float | None = None
|
|
tier: str | None = None
|
|
suggestion: str | None = None
|
|
frequency_basis: str = "暂无匹配采购订单"
|
|
note: str | None = None
|
|
data_available: bool = False
|
|
|
|
|
|
class StandardJudgment(ApiSchema):
|
|
category: str
|
|
risk_point: str
|
|
rule: str
|
|
source: str | None = None
|
|
status: str = "待检测"
|
|
|
|
|
|
class RiskDimensionScore(ApiSchema):
|
|
dimension: str
|
|
score: float
|
|
weight: float
|
|
status: str = "database"
|
|
reason: str | None = None
|
|
sample_size: int | None = None
|
|
raw_value: float | int | None = None
|
|
|
|
|
|
class SimilarCase(ApiSchema):
|
|
case_id: int | None = None
|
|
date: str | None = None
|
|
product: str | None = None
|
|
category: str | None = None
|
|
material: str | None = None
|
|
anomaly_type: str | None = None
|
|
description: str | None = None
|
|
root_cause: str | None = None
|
|
defect_level: str | None = None
|
|
result: str | None = None
|
|
problem: str | None = None
|
|
solution: str | None = None
|
|
similarity: float | None = None
|
|
|
|
|
|
class AiSolutionRisk(ApiSchema):
|
|
level: str
|
|
title: str
|
|
detail: str
|
|
|
|
|
|
class AiSolutionReport(ApiSchema):
|
|
title: str = "AI 案例推理生成"
|
|
confidence: str | None = None
|
|
analysis_base: str | None = None
|
|
standard_fallback_enabled: bool = False
|
|
standards: list[StandardJudgment] = Field(default_factory=list)
|
|
similar_cases: list[SimilarCase] = Field(default_factory=list)
|
|
risks: list[AiSolutionRisk] = Field(default_factory=list)
|
|
suggestions: list[str] = Field(default_factory=list)
|
|
warning: str | None = None
|
|
|
|
|
|
class ReportCard(ApiSchema):
|
|
"""A response card explicitly appended to the risk report.
|
|
|
|
The card is intentionally a superset of the five assistant card types so
|
|
that the report page and both export formats can consume the exact same
|
|
payload without type-specific ad-hoc transformations.
|
|
"""
|
|
|
|
type: Literal["supplier", "material", "standard", "compliance", "solution"]
|
|
title: str = "风险分析卡片"
|
|
name: str | None = None
|
|
party_type: str | None = None
|
|
material: str | None = None
|
|
category: str | None = None
|
|
question: str | None = None
|
|
anomaly_count: int | None = None
|
|
cooperation_count: int | None = None
|
|
frequency_coefficient: float | None = None
|
|
supplier_base_score: float | None = None
|
|
supplier_score: float | None = None
|
|
tier: str | None = None
|
|
matched_count: int | None = None
|
|
detected_values: list[dict[str, str]] = Field(default_factory=list)
|
|
top_problems: list[dict[str, int | str]] = Field(default_factory=list)
|
|
frequent_problems: list[dict[str, int | str]] = Field(default_factory=list)
|
|
standards: list[StandardJudgment] = Field(default_factory=list)
|
|
similar_cases: list[SimilarCase] = Field(default_factory=list)
|
|
confidence: str | None = None
|
|
analysis_base: str | None = None
|
|
standard_fallback_enabled: bool = False
|
|
risks: list[AiSolutionRisk] = Field(default_factory=list)
|
|
suggestions: list[str] = Field(default_factory=list)
|
|
note: str | None = None
|
|
warning: str | None = None
|
|
frequency_basis: str | None = None
|
|
data_available: bool | None = None
|
|
|
|
|
|
class RiskAssessmentResult(ApiSchema):
|
|
subject_id: str
|
|
score: float
|
|
level: RiskLevel
|
|
model_version: str
|
|
factors: list[RiskFactorResult]
|
|
risk_badge: str | None = None
|
|
alert_text: str | None = None
|
|
category_warning: CategoryWarning | None = None
|
|
supplier_freq: SupplierFrequency | None = None
|
|
standard_judgment: list[StandardJudgment] = Field(default_factory=list)
|
|
dimension_scores: list[RiskDimensionScore] = Field(default_factory=list)
|
|
similar_cases: list[SimilarCase] = Field(default_factory=list)
|
|
ai_suggestions: list[str] = Field(default_factory=list)
|
|
ai_solution_cards: list[AiSolutionReport] = Field(default_factory=list)
|
|
report_cards: list[ReportCard] = Field(default_factory=list)
|
|
|
|
|
|
class ModelInfo(ApiSchema):
|
|
model_version: str
|
|
score_range: str = "0-100"
|
|
levels: tuple[RiskLevel, ...] = (
|
|
RiskLevel.LOW,
|
|
RiskLevel.MODERATELY_LOW,
|
|
RiskLevel.MEDIUM,
|
|
RiskLevel.HIGH,
|
|
RiskLevel.VERY_HIGH,
|
|
)
|