- 接入数据库驱动的七维风险评分第一阶段逻辑\n- 增加主模型失败后的 DeepSeek 语义、流式和预防建议兜底\n- 将 AI 预防建议改为基于评分、历史异常和标准规则动态生成\n- 增加无历史案例时的标准库兜底校验和通用规则匹配\n- 修复未知供应商识别及测试占位名称过滤\n- 增加后端滚动日志文件配置和 LLM 请求日志\n- 历史会话直接读取已保存结果,避免重新调用模型和重算风险\n- 补充评分、供应商识别和 LLM 协议测试
100 lines
3.4 KiB
Python
100 lines
3.4 KiB
Python
"""Risk prediction use-case orchestration."""
|
|
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.core.exceptions import AppException
|
|
from app.domain.risk_engine import BaselineRiskEngine, IndicatorValue
|
|
from app.schemas.risk_prediction import (
|
|
ModelInfo,
|
|
RiskAssessmentRequest,
|
|
RiskAssessmentResult,
|
|
RiskDimensionScore,
|
|
RiskFactorResult,
|
|
)
|
|
from app.services.database_risk_scoring import DatabaseRiskScoringService
|
|
|
|
|
|
class RiskPredictionService:
|
|
_engine = BaselineRiskEngine()
|
|
|
|
@classmethod
|
|
def model_info(cls) -> ModelInfo:
|
|
return ModelInfo(model_version="database-seven-dimension-v1")
|
|
|
|
@classmethod
|
|
async def preview(
|
|
cls,
|
|
request: RiskAssessmentRequest,
|
|
session: AsyncSession | None = None,
|
|
) -> RiskAssessmentResult:
|
|
if session and any(
|
|
value is not None
|
|
for value in (
|
|
request.product_category,
|
|
request.material_type,
|
|
request.supplier,
|
|
request.factory,
|
|
request.stage_new,
|
|
request.defect_level,
|
|
)
|
|
):
|
|
database_score = await DatabaseRiskScoringService(session).score(
|
|
category=request.product_category,
|
|
material=request.material_type,
|
|
supplier=request.supplier,
|
|
factory=request.factory,
|
|
stage=request.stage_new,
|
|
defect_level=request.defect_level,
|
|
)
|
|
dimensions = [
|
|
RiskDimensionScore(
|
|
dimension=item.name,
|
|
score=item.score,
|
|
weight=item.weight,
|
|
status=item.status,
|
|
reason=item.reason,
|
|
sample_size=item.sample_size,
|
|
raw_value=item.raw_value,
|
|
)
|
|
for item in database_score.dimensions
|
|
]
|
|
return RiskAssessmentResult(
|
|
subject_id=request.subject_id,
|
|
score=database_score.score,
|
|
level=database_score.level,
|
|
model_version="database-seven-dimension-v1",
|
|
factors=[
|
|
RiskFactorResult(
|
|
name=item.name,
|
|
value=round(100 - item.score, 2),
|
|
weight=item.weight,
|
|
contribution=round(item.score * item.weight / 100, 2),
|
|
)
|
|
for item in database_score.dimensions
|
|
],
|
|
dimension_scores=dimensions,
|
|
)
|
|
if not request.indicators:
|
|
raise AppException("请填写产品评估参数", code=422, status_code=422)
|
|
score = cls._engine.predict(
|
|
[
|
|
IndicatorValue(name=item.name, value=item.value, weight=item.weight)
|
|
for item in request.indicators
|
|
]
|
|
)
|
|
return RiskAssessmentResult(
|
|
subject_id=request.subject_id,
|
|
score=score.score,
|
|
level=score.level,
|
|
model_version=cls._engine.model_version,
|
|
factors=[
|
|
RiskFactorResult(
|
|
name=item.name,
|
|
value=item.value,
|
|
weight=item.weight,
|
|
contribution=item.contribution,
|
|
)
|
|
for item in score.factors
|
|
],
|
|
)
|