kx_guo e8c122e542 完善风险评分、LLM兜底与会话历史加载
- 接入数据库驱动的七维风险评分第一阶段逻辑\n- 增加主模型失败后的 DeepSeek 语义、流式和预防建议兜底\n- 将 AI 预防建议改为基于评分、历史异常和标准规则动态生成\n- 增加无历史案例时的标准库兜底校验和通用规则匹配\n- 修复未知供应商识别及测试占位名称过滤\n- 增加后端滚动日志文件配置和 LLM 请求日志\n- 历史会话直接读取已保存结果,避免重新调用模型和重算风险\n- 补充评分、供应商识别和 LLM 协议测试
2026-09-04 18:02:39 +08:00

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
],
)