Browse Source

feat(alert): 实现评估报告管理功能增强

- 新增评估报告列表查询接口,支持按模型ID、版本和有效性过滤
- 新增算法评估配置查询接口,获取底线分数等条件
- 新增旧表 Assess_Report_CFG 兼容插入接口
- 新增评估报告名称查询接口,按模型ID和版本生成RV+时间格式名称
- 修改评估结果响应VO字段类型,durationSeconds、coverage等改为Double并设置默认值
- 完善模型下装逻辑,增加评估报告校验和版本关联
- 新增模型草稿版本创建和历史版本列表查询功能
- 优化模型信息查询,支持指定版本读取
- 增强JSON序列化配置,添加字段别名支持
- 更新相关实体类和Mapper定义
pull/30/head
CJL6015 1 month ago
parent
commit
05a9260eb1
  1. 6
      yudao-module-alert/yudao-module-alert-biz/pom.xml
  2. 37
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/assessreport/AssessReportController.java
  3. 13
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/assessreport/vo/AssessConditionRespVO.java
  4. 6
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/assessreport/vo/AssessEvaluateRespVO.java
  5. 3
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/assessreport/vo/AssessReportCreateReqVO.java
  6. 17
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/assessreport/vo/AssessReportNameRespVO.java
  7. 35
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/assessreport/vo/AssessReportSimpleRespVO.java
  8. 34
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/model/ModelController.java
  9. 6
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/model/model/ModelInfo.java
  10. 10
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/model/model/Point.java
  11. 15
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/model/vo/BottomModelReqVO.java
  12. 5
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/model/vo/ModelSimpleVO.java
  13. 16
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/model/vo/ModelVersionSimpleVO.java
  14. 6
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/model/vo/TrainInfo.java
  15. 22
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dal/dataobject/model/ModelConditionDO.java
  16. 9
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dal/mysql/model/ModelConditionMapper.java
  17. 49
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dao/domain/AssessReportCfg.java
  18. 5
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dao/domain/ModelVersion.java
  19. 18
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dao/mapper/AssessReportCfgMapper.java
  20. 4
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dao/mapper/ModelVersionMapper.java
  21. 13
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dao/service/AssessReportCfgService.java
  22. 4
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dao/service/ModelVersionService.java
  23. 22
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dao/service/impl/AssessReportCfgServiceImpl.java
  24. 4
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dao/service/impl/ModelVersionServiceImpl.java
  25. 20
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/assessreport/AssessReportService.java
  26. 180
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/assessreport/impl/AssessReportServiceImpl.java
  27. 20
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/model/ModelService.java
  28. 129
      yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/model/impl/ModelServiceImpl.java
  29. 33
      yudao-module-alert/yudao-module-alert-biz/src/main/resources/cn/iocoder/yudao/module/alert/dao/mapper/AssessReportCfgMapper.xml
  30. 45
      yudao-module-alert/yudao-module-alert-biz/src/main/resources/cn/iocoder/yudao/module/alert/dao/mapper/ModelVersionMapper.xml

6
yudao-module-alert/yudao-module-alert-biz/pom.xml

@ -68,6 +68,12 @@
<version>2.4.2-SNAPSHOT</version> <version>2.4.2-SNAPSHOT</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.14</version>
<scope>compile</scope>
</dependency>
<!-- Test 测试相关 --> <!-- Test 测试相关 -->
<!-- <dependency>--> <!-- <dependency>-->

37
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/assessreport/AssessReportController.java

@ -7,6 +7,8 @@ import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List;
/** /**
* 评估报告相关接口从旧 GetData.asmx 迁移 * 评估报告相关接口从旧 GetData.asmx 迁移
*/ */
@ -49,6 +51,24 @@ public class AssessReportController {
return CommonResult.success(assessReportService.save(reqVO)); return CommonResult.success(assessReportService.save(reqVO));
} }
/**
* 获取评估报告列表供下装选择
*/
@GetMapping("/list")
public CommonResult<List<AssessReportSimpleRespVO>> list(@RequestParam Integer modelId,
@RequestParam(required = false) String version,
@RequestParam(required = false, defaultValue = "true") Boolean valid) {
return CommonResult.success(assessReportService.list(modelId, version, valid));
}
/**
* 获取算法对应的评估配置底线分数等
*/
@GetMapping("/condition")
public CommonResult<AssessConditionRespVO> condition(@RequestParam String algorithm) {
return CommonResult.success(assessReportService.getCondition(algorithm));
}
/** /**
* 数据清洗概要信息 * 数据清洗概要信息
*/ */
@ -56,4 +76,21 @@ public class AssessReportController {
public CommonResult<AssessCleanSummaryVO> cleanSummary(@Validated AssessCleanQueryReqVO reqVO) { public CommonResult<AssessCleanSummaryVO> cleanSummary(@Validated AssessCleanQueryReqVO reqVO) {
return CommonResult.success(assessReportService.cleanSummary(reqVO)); return CommonResult.success(assessReportService.cleanSummary(reqVO));
} }
/**
* 兼容旧表 Assess_Report_CFG 的插入
*/
@PostMapping("/legacy")
public CommonResult<Boolean> insertLegacy(@RequestBody @Validated AssessReportCreateReqVO reqVO) {
return CommonResult.success(assessReportService.insertLegacyReport(reqVO));
}
/**
* 查询评估报告名称按模型ID和版本 Assess_Report_CFG 生成 RV+时间
*/
@GetMapping("/name")
public CommonResult<List<AssessReportNameRespVO>> listNames(@RequestParam Integer modelId,
@RequestParam(required = false) String version) {
return CommonResult.success(assessReportService.listReportNames(modelId, version));
}
} }

13
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/assessreport/vo/AssessConditionRespVO.java

@ -0,0 +1,13 @@
package cn.iocoder.yudao.module.alert.controller.admin.assessreport.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class AssessConditionRespVO {
@Schema(description = "模型底线分数")
private Double modelScore;
@Schema(description = "条件配置原文")
private String condition;
}

6
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/assessreport/vo/AssessEvaluateRespVO.java

@ -12,11 +12,11 @@ public class AssessEvaluateRespVO {
private List<AssessEvaluateRowRespVO> points; private List<AssessEvaluateRowRespVO> points;
@Schema(description = "评估耗时秒") @Schema(description = "评估耗时秒")
private Long durationSeconds; private Double durationSeconds = 0d;
@Schema(description = "覆盖率") @Schema(description = "覆盖率")
private Double coverage; private Double coverage = 0d;
@Schema(description = "清洗耗时秒") @Schema(description = "清洗耗时秒")
private Long cleanDurationSeconds; private Double cleanDurationSeconds = 0d;
} }

3
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/assessreport/vo/AssessReportCreateReqVO.java

@ -46,4 +46,7 @@ public class AssessReportCreateReqVO {
@Schema(description = "模式名称") @Schema(description = "模式名称")
private String conditionName; private String conditionName;
@Schema(description = "原始报告JSON串(旧表插入用)")
private String rawReport;
} }

17
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/assessreport/vo/AssessReportNameRespVO.java

@ -0,0 +1,17 @@
package cn.iocoder.yudao.module.alert.controller.admin.assessreport.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 评估报告名称响应
*/
@Data
public class AssessReportNameRespVO {
@Schema(description = "报告ID")
private Long id;
@Schema(description = "报告名称,格式 RV<时间>,如 RV2025-11-30T13:57:36")
private String name;
}

35
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/assessreport/vo/AssessReportSimpleRespVO.java

@ -0,0 +1,35 @@
package cn.iocoder.yudao.module.alert.controller.admin.assessreport.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
/**
* 评估报告精简信息下装选择使用
*/
@Data
public class AssessReportSimpleRespVO {
private Integer id;
@Schema(description = "报告得分")
private Double score;
@Schema(description = "覆盖面")
private Double coverRange;
@Schema(description = "是否有效(已通过验证)")
private Boolean validFlag;
private String identifier;
private String verifier;
@Schema(description = "评估时间")
private String assessTime;
private String version;
private String conditionName;
}

34
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/model/ModelController.java

@ -32,8 +32,9 @@ public class ModelController {
} }
@GetMapping("info/{id}") @GetMapping("info/{id}")
public CommonResult<ModelInfoVO> getModelInfo(@PathVariable Integer id) { public CommonResult<ModelInfoVO> getModelInfo(@PathVariable Integer id,
ModelInfoVO modelInfo = modelService.getModelInfo(id); @RequestParam(required = false) String version) {
ModelInfoVO modelInfo = modelService.getModelInfo(id, version);
return CommonResult.success(modelInfo); return CommonResult.success(modelInfo);
} }
@ -68,8 +69,33 @@ public class ModelController {
return CommonResult.success(modelTestData); return CommonResult.success(modelTestData);
} }
/**
* 创建草稿版本v-test
*/
@PostMapping("/version/new/{id}")
public CommonResult<ModelInfoVO> createDraft(@PathVariable Integer id) {
try {
return CommonResult.success(modelService.createDraftVersion(id));
} catch (Exception e) {
return CommonResult.error(INTERNAL_SERVER_ERROR.getCode(), e.getMessage());
}
}
/**
* 版本列表
*/
@GetMapping("/version/{id}")
public CommonResult<List<ModelVersionSimpleVO>> listVersions(@PathVariable Integer id) {
return CommonResult.success(modelService.listVersions(id));
}
@PostMapping("/bottom/{id}") @PostMapping("/bottom/{id}")
public CommonResult<ModelInfoVO> bottomModel(@PathVariable Integer id) { public CommonResult<ModelInfoVO> bottomModel(@PathVariable Integer id, @RequestBody(required = false) BottomModelReqVO reqVO) {
return CommonResult.success(modelService.bottomModel(id)); try {
Long reportId = reqVO != null ? reqVO.getReportId() : null;
return CommonResult.success(modelService.bottomModel(id, reportId));
} catch (Exception e) {
return CommonResult.error(INTERNAL_SERVER_ERROR.getCode(), e.getMessage());
}
} }
} }

6
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/model/model/ModelInfo.java

@ -1,8 +1,8 @@
package cn.iocoder.yudao.module.alert.controller.admin.model.model; package cn.iocoder.yudao.module.alert.controller.admin.model.model;
import cn.iocoder.yudao.module.alert.common.enums.Algorithm; import cn.iocoder.yudao.module.alert.common.enums.Algorithm;
import cn.iocoder.yudao.module.alert.controller.admin.model.vo.ModelInfoVO;
import cn.iocoder.yudao.module.alert.controller.admin.model.vo.TrainInfo; import cn.iocoder.yudao.module.alert.controller.admin.model.vo.TrainInfo;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.*; import lombok.*;
@ -88,10 +88,12 @@ public class ModelInfo {
private String unit; private String unit;
@JsonProperty("versionNumber") @JsonProperty("versionNumber")
private Integer versionNumber; private Integer versionNumber;
@JsonProperty("alarmmodelset") @JsonProperty("alarmmodelset")
@JSONField(name = "alarmmodelset")
private AlarmModelSet alarmModelSet; private AlarmModelSet alarmModelSet;
@JsonProperty("para") @JsonProperty("para")
@ -115,7 +117,7 @@ public class ModelInfo {
private String alarmCondition; private String alarmCondition;
public static AlarmModelSet defaultInit() { public static AlarmModelSet defaultInit() {
return new AlarmModelSet("全工况运行", "1==1"); return new AlarmModelSet("全工况运行", "1=1");
} }
} }

10
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/model/model/Point.java

@ -25,7 +25,7 @@ public class Point {
private BigDecimal Upper; private BigDecimal Upper;
private Boolean dead; private Boolean dead;
private Boolean limit; private Boolean limit;
private Boolean lock; private Boolean lock = false;
/** /**
* 残差下限 * 残差下限
*/ */
@ -34,12 +34,20 @@ public class Point {
* 残差上限 * 残差上限
*/ */
private BigDecimal upperBound; private BigDecimal upperBound;
@JsonProperty("TMax")
private BigDecimal TMax; private BigDecimal TMax;
@JsonProperty("TMin")
private BigDecimal TMin; private BigDecimal TMin;
@JsonProperty("TAvg")
private BigDecimal TAvg; private BigDecimal TAvg;
@JsonProperty("DMax")
private BigDecimal DMax; private BigDecimal DMax;
@JsonProperty("DMin")
private BigDecimal DMin; private BigDecimal DMin;
@JsonProperty("DAvg")
private BigDecimal DAvg; private BigDecimal DAvg;
@JsonProperty("C95")
private BigDecimal C95; private BigDecimal C95;
@JsonProperty("C99")
private BigDecimal C99; private BigDecimal C99;
} }

15
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/model/vo/BottomModelReqVO.java

@ -0,0 +1,15 @@
package cn.iocoder.yudao.module.alert.controller.admin.model.vo;
import lombok.Data;
/**
* 模型下装请求参数
*/
@Data
public class BottomModelReqVO {
/**
* 评估报告ID需已通过验证
*/
private Long reportId;
}

5
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/model/vo/ModelSimpleVO.java

@ -35,6 +35,11 @@ public class ModelSimpleVO {
*/ */
private String creator; private String creator;
/**
* 当前版本
*/
private String version;
/** /**
* 模型状态 * 模型状态
*/ */

16
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/model/vo/ModelVersionSimpleVO.java

@ -0,0 +1,16 @@
package cn.iocoder.yudao.module.alert.controller.admin.model.vo;
import lombok.Data;
import java.util.Date;
/**
* 模型版本精简信息
*/
@Data
public class ModelVersionSimpleVO {
private String version;
private Date createTime;
private Integer status;
private String conditionName;
}

6
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/controller/admin/model/vo/TrainInfo.java

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.alert.controller.admin.model.vo; package cn.iocoder.yudao.module.alert.controller.admin.model.vo;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
@ -10,17 +11,22 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor @NoArgsConstructor
public class TrainInfo { public class TrainInfo {
@JsonProperty("Model_info") @JsonProperty("Model_info")
@JSONField(name = "Model_info")
private ModelInfoDetails modelInfo; private ModelInfoDetails modelInfo;
@JsonProperty("Model_type") @JsonProperty("Model_type")
@JSONField(name = "Model_type")
private String modelType; private String modelType;
@JsonProperty("BeforeCleanSamNum") @JsonProperty("BeforeCleanSamNum")
@JSONField(name = "BeforeCleanSamNum")
private int beforeCleanSamNum; private int beforeCleanSamNum;
@JsonProperty("AfterCleanSamNum") @JsonProperty("AfterCleanSamNum")
@JSONField(name = "AfterCleanSamNum")
private int afterCleanSamNum; private int afterCleanSamNum;
@JsonProperty("CleanOrNot") @JsonProperty("CleanOrNot")
@JSONField(name = "CleanOrNot")
private boolean cleanOrNot; private boolean cleanOrNot;
} }

22
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dal/dataobject/model/ModelConditionDO.java

@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.alert.dal.dataobject.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 对应表model_condition
*/
@Data
@TableName("model_condition")
public class ModelConditionDO {
@TableId
private Long id;
private String algorithm;
@TableField("`condition`")
private String condition;
}

9
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dal/mysql/model/ModelConditionMapper.java

@ -0,0 +1,9 @@
package cn.iocoder.yudao.module.alert.dal.mysql.model;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.alert.dal.dataobject.model.ModelConditionDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ModelConditionMapper extends BaseMapperX<ModelConditionDO> {
}

49
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dao/domain/AssessReportCfg.java

@ -0,0 +1,49 @@
package cn.iocoder.yudao.module.alert.dao.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.util.Date;
import lombok.Data;
/**
* @TableName assess_report_cfg
*/
@TableName(value ="assess_report_cfg")
@Data
public class AssessReportCfg {
private Integer id;
private Integer modelId;
private String version;
private String report;
private Double score;
private Double coverRange;
private String valid;
private String identifier;
private String verifier;
private Date time;
private Integer status;
private String conditionName;
private String creator;
private Date createTime;
private String updater;
private Date updateTime;
private Boolean deleted;
}

5
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dao/domain/ModelVersion.java

@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.util.Date; import java.util.Date;
import lombok.Data; import lombok.Data;
@ -13,7 +12,7 @@ import lombok.Data;
*/ */
@TableName(value ="model_version") @TableName(value ="model_version")
@Data @Data
public class ModelVersion implements Serializable { public class ModelVersion {
private Integer id; private Integer id;
private Integer modelId; private Integer modelId;
@ -67,6 +66,4 @@ public class ModelVersion implements Serializable {
private Date updateTime; private Date updateTime;
private Boolean deleted; private Boolean deleted;
private static final long serialVersionUID = 1L;
} }

18
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dao/mapper/AssessReportCfgMapper.java

@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.alert.dao.mapper;
import cn.iocoder.yudao.module.alert.dao.domain.AssessReportCfg;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author cjl60
* @description 针对表assess_report_cfg的数据库操作Mapper
* @createDate 2025-11-30 11:58:22
* @Entity cn.iocoder.yudao.module.alert.dao.domain.AssessReportCfg
*/
public interface AssessReportCfgMapper extends BaseMapper<AssessReportCfg> {
}

4
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dao/mapper/ModelVersionMapper.java

@ -4,9 +4,9 @@ import cn.iocoder.yudao.module.alert.dao.domain.ModelVersion;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/** /**
* @author 陈小黑 * @author cjl60
* @description 针对表model_version的数据库操作Mapper * @description 针对表model_version的数据库操作Mapper
* @createDate 2025-07-10 16:23:38 * @createDate 2025-11-30 09:14:52
* @Entity cn.iocoder.yudao.module.alert.dao.domain.ModelVersion * @Entity cn.iocoder.yudao.module.alert.dao.domain.ModelVersion
*/ */
public interface ModelVersionMapper extends BaseMapper<ModelVersion> { public interface ModelVersionMapper extends BaseMapper<ModelVersion> {

13
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dao/service/AssessReportCfgService.java

@ -0,0 +1,13 @@
package cn.iocoder.yudao.module.alert.dao.service;
import cn.iocoder.yudao.module.alert.dao.domain.AssessReportCfg;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @author cjl60
* @description 针对表assess_report_cfg的数据库操作Service
* @createDate 2025-11-30 11:58:22
*/
public interface AssessReportCfgService extends IService<AssessReportCfg> {
}

4
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dao/service/ModelVersionService.java

@ -4,9 +4,9 @@ import cn.iocoder.yudao.module.alert.dao.domain.ModelVersion;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
/** /**
* @author 陈小黑 * @author cjl60
* @description 针对表model_version的数据库操作Service * @description 针对表model_version的数据库操作Service
* @createDate 2025-07-10 16:23:38 * @createDate 2025-11-30 09:14:52
*/ */
public interface ModelVersionService extends IService<ModelVersion> { public interface ModelVersionService extends IService<ModelVersion> {

22
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dao/service/impl/AssessReportCfgServiceImpl.java

@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.alert.dao.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.iocoder.yudao.module.alert.dao.domain.AssessReportCfg;
import cn.iocoder.yudao.module.alert.dao.service.AssessReportCfgService;
import cn.iocoder.yudao.module.alert.dao.mapper.AssessReportCfgMapper;
import org.springframework.stereotype.Service;
/**
* @author cjl60
* @description 针对表assess_report_cfg的数据库操作Service实现
* @createDate 2025-11-30 11:58:22
*/
@Service
public class AssessReportCfgServiceImpl extends ServiceImpl<AssessReportCfgMapper, AssessReportCfg>
implements AssessReportCfgService{
}

4
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/dao/service/impl/ModelVersionServiceImpl.java

@ -7,9 +7,9 @@ import cn.iocoder.yudao.module.alert.dao.mapper.ModelVersionMapper;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
/** /**
* @author 陈小黑 * @author cjl60
* @description 针对表model_version的数据库操作Service实现 * @description 针对表model_version的数据库操作Service实现
* @createDate 2025-07-10 16:23:38 * @createDate 2025-11-30 09:14:52
*/ */
@Service @Service
public class ModelVersionServiceImpl extends ServiceImpl<ModelVersionMapper, ModelVersion> public class ModelVersionServiceImpl extends ServiceImpl<ModelVersionMapper, ModelVersion>

20
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/assessreport/AssessReportService.java

@ -13,4 +13,24 @@ public interface AssessReportService {
Boolean save(AssessReportCreateReqVO reqVO); Boolean save(AssessReportCreateReqVO reqVO);
AssessCleanSummaryVO cleanSummary(AssessCleanQueryReqVO reqVO); AssessCleanSummaryVO cleanSummary(AssessCleanQueryReqVO reqVO);
/**
* 获取模型的评估报告列表可按版本有效性过滤
*/
java.util.List<AssessReportSimpleRespVO> list(Integer modelId, String version, Boolean onlyValid);
/**
* 获取算法对应的评估配置底线分数/规则
*/
AssessConditionRespVO getCondition(String algorithm);
/**
* 兼容旧表 Assess_Report_CFG 的插入
*/
Boolean insertLegacyReport(AssessReportCreateReqVO reqVO);
/**
* 按模型ID和版本查询报告名称列表 Assess_Report_CFG 生成 RV+时间
*/
java.util.List<AssessReportNameRespVO> listReportNames(Integer modelId, String version);
} }

180
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/assessreport/impl/AssessReportServiceImpl.java

@ -7,16 +7,22 @@ import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.alert.controller.admin.assessreport.vo.*; import cn.iocoder.yudao.module.alert.controller.admin.assessreport.vo.*;
import cn.iocoder.yudao.module.alert.dao.domain.ModelCfg; import cn.iocoder.yudao.module.alert.dao.domain.ModelCfg;
import cn.iocoder.yudao.module.alert.dao.domain.AssessReportCfg;
import cn.iocoder.yudao.module.alert.dao.domain.ModelVersion; import cn.iocoder.yudao.module.alert.dao.domain.ModelVersion;
import cn.iocoder.yudao.module.alert.dao.mapper.AssessReportCfgMapper;
import cn.iocoder.yudao.module.alert.dao.service.ModelCfgService; import cn.iocoder.yudao.module.alert.dao.service.ModelCfgService;
import cn.iocoder.yudao.module.alert.dao.service.ModelVersionService; import cn.iocoder.yudao.module.alert.dao.service.ModelVersionService;
import cn.iocoder.yudao.module.alert.dal.dataobject.assessreport.AssessReportDO; import cn.iocoder.yudao.module.alert.dal.dataobject.assessreport.AssessReportDO;
import cn.iocoder.yudao.module.alert.dal.mysql.assessreport.AssessReportMapper; import cn.iocoder.yudao.module.alert.dal.mysql.assessreport.AssessReportMapper;
import cn.iocoder.yudao.module.alert.dal.dataobject.model.ModelConditionDO;
import cn.iocoder.yudao.module.alert.dal.mysql.model.ModelConditionMapper;
import cn.iocoder.yudao.module.alert.service.assessreport.AssessReportService; import cn.iocoder.yudao.module.alert.service.assessreport.AssessReportService;
import com.alibaba.excel.util.DateUtils; import com.alibaba.excel.util.DateUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@ -24,8 +30,6 @@ import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -38,6 +42,8 @@ public class AssessReportServiceImpl implements AssessReportService {
private final ModelCfgService modelCfgService; private final ModelCfgService modelCfgService;
private final ModelVersionService modelVersionService; private final ModelVersionService modelVersionService;
private final AssessReportMapper assessReportMapper; private final AssessReportMapper assessReportMapper;
private final AssessReportCfgMapper assessReportCfgMapper;
private final ModelConditionMapper modelConditionMapper;
@Value("${assess-report.host}") @Value("${assess-report.host}")
private String algorithmHost; private String algorithmHost;
@Value("${exa.ip:}") @Value("${exa.ip:}")
@ -52,7 +58,8 @@ public class AssessReportServiceImpl implements AssessReportService {
} }
String targetVersion = StringUtils.hasText(reqVO.getVersion()) ? reqVO.getVersion() : modelCfg.getCurVersion(); String targetVersion = StringUtils.hasText(reqVO.getVersion()) ? reqVO.getVersion() : modelCfg.getCurVersion();
String modelInfoStr = resolveModelInfo(modelCfg, targetVersion); String modelInfoStr = resolveModelInfo(modelCfg, targetVersion);
Map<String, Object> modelInfo = JsonUtils.parseObject(modelInfoStr, new TypeReference<Map<String, Object>>() {}); Map<String, Object> modelInfo = JsonUtils.parseObject(modelInfoStr, new TypeReference<Map<String, Object>>() {
});
List<AssessPointVO> pointRows = buildPointRows(modelInfo); List<AssessPointVO> pointRows = buildPointRows(modelInfo);
List<AssessRowVO> assessRows = buildAssessRows(pointRows); List<AssessRowVO> assessRows = buildAssessRows(pointRows);
AssessInitRespVO respVO = new AssessInitRespVO(); AssessInitRespVO respVO = new AssessInitRespVO();
@ -71,14 +78,15 @@ public class AssessReportServiceImpl implements AssessReportService {
@Override @Override
public AssessReportDetailVO getReportDetail(Long id) { public AssessReportDetailVO getReportDetail(Long id) {
AssessReportDO report = assessReportMapper.selectById(id); AssessReportCfg report = assessReportCfgMapper.selectById(id);
if (report == null) { if (report == null) {
return null; return null;
} }
AssessReportDetailVO vo = new AssessReportDetailVO(); AssessReportDetailVO vo = new AssessReportDetailVO();
vo.setId(id); vo.setId(id);
vo.setModelName(report.getModelName()); vo.setModelName(null);
vo.setReport(JsonUtils.parseObject(report.getReportJson(), new TypeReference<Map<String, Object>>() {})); vo.setReport(JsonUtils.parseObject(report.getReport(), new TypeReference<Map<String, Object>>() {
}));
return vo; return vo;
} }
@ -91,7 +99,8 @@ public class AssessReportServiceImpl implements AssessReportService {
String modelInfoStr = StringUtils.hasText(reqVO.getModelInfo()) String modelInfoStr = StringUtils.hasText(reqVO.getModelInfo())
? reqVO.getModelInfo() ? reqVO.getModelInfo()
: resolveModelInfo(modelCfg, reqVO.getVersion()); : resolveModelInfo(modelCfg, reqVO.getVersion());
Map<String, Object> modelInfo = JsonUtils.parseObject(modelInfoStr, new TypeReference<Map<String, Object>>() {}); Map<String, Object> modelInfo = JsonUtils.parseObject(modelInfoStr, new TypeReference<Map<String, Object>>() {
});
// 使用旧版逻辑:解析 json,拆分幅值,构造单点 assess 列表,调用对应算法接口 // 使用旧版逻辑:解析 json,拆分幅值,构造单点 assess 列表,调用对应算法接口
String json = StringUtils.hasText(reqVO.getRawJson()) String json = StringUtils.hasText(reqVO.getRawJson())
? reqVO.getRawJson() ? reqVO.getRawJson()
@ -138,12 +147,20 @@ public class AssessReportServiceImpl implements AssessReportService {
String endpoint = "/api/" + alg + "/assess_PositiveAndNegative"; String endpoint = "/api/" + alg + "/assess_PositiveAndNegative";
String tempAll = HttpUtils.post(algorithmHost + endpoint, null, JsonUtils.toJsonString(assessInput)); String tempAll = HttpUtils.post(algorithmHost + endpoint, null, JsonUtils.toJsonString(assessInput));
// 部分算法返回 {"result":"{...}"},需要先拆出 result,再解析内部 JSON
Map<String, Object> rawMap = JsonUtils.parseObject(tempAll, new TypeReference<Map<String, Object>>() {
});
String payload = tempAll;
if (rawMap != null && rawMap.containsKey("result") && rawMap.get("result") instanceof String) {
payload = rawMap.get("result").toString();
}
AssessEvaluateRespVO respVO = new AssessEvaluateRespVO(); AssessEvaluateRespVO respVO = new AssessEvaluateRespVO();
AssessAllMessage message = JsonUtils.parseObject(tempAll, AssessAllMessage.class); AssessAllMessage message = JsonUtils.parseObject(payload, AssessAllMessage.class);
if (message != null && "OK".equalsIgnoreCase(message.getMessage())) { if (message != null && "OK".equalsIgnoreCase(message.getMessage())) {
AssessAll trAll = JsonUtils.parseObject(tempAll, AssessAll.class); AssessAll trAll = JsonUtils.parseObject(payload, AssessAll.class);
TestReturn tr2 = toTestReturn(trAll.getPositive()); TestReturn tr2 = toTestReturn(trAll.getPositive());
TestReturn tr1 = toTestReturn(trAll.getNegative()); TestReturn tr1 = toTestReturn(trAll.getNegative() != null ? trAll.getNegative() : trAll.getPositive());
int returnIndex1 = 0; int returnIndex1 = 0;
for (int i = 0; i < limit.length; i++) { for (int i = 0; i < limit.length; i++) {
if (indexList[i]) { if (indexList[i]) {
@ -171,12 +188,16 @@ public class AssessReportServiceImpl implements AssessReportService {
} }
} }
respVO.setPoints(mapAssessResultByIndex(reqVO.getAssessRows(), tr)); respVO.setPoints(mapAssessResultByIndex(reqVO.getAssessRows(), tr));
respVO.setCleanDurationSeconds(message.getCleanTime()); respVO.setCleanDurationSeconds(message.getCleanTime() != null ? message.getCleanTime() : 0d);
respVO.setDurationSeconds(message.getAssessTime()); respVO.setDurationSeconds(message.getAssessTime() != null ? message.getAssessTime() : 0d);
} else { } else {
throw new RuntimeException(tempAll); throw new RuntimeException(tempAll);
} }
respVO.setCoverage(mt.getCoverage()); Double cov = mt.getCoverage();
if (cov == null) {
cov = fetchCoverage(modelInfo);
}
respVO.setCoverage(cov == null ? 0d : cov);
return respVO; return respVO;
} }
@ -198,6 +219,23 @@ public class AssessReportServiceImpl implements AssessReportService {
return assessReportMapper.insert(reportDO) > 0; return assessReportMapper.insert(reportDO) > 0;
} }
@Override
public Boolean insertLegacyReport(AssessReportCreateReqVO reqVO) {
AssessReportCfg reportDO = new AssessReportCfg();
reportDO.setModelId(reqVO.getModelId());
reportDO.setVersion(reqVO.getVersion());
reportDO.setReport(reqVO.getRawReport() != null ? reqVO.getRawReport() : JsonUtils.toJsonString(reqVO.getReport()));
reportDO.setScore(reqVO.getScore() != null ? reqVO.getScore().doubleValue() : null);
reportDO.setCoverRange(reqVO.getCoverage() != null ? reqVO.getCoverage().doubleValue() : null);
reportDO.setValid(Boolean.TRUE.equals(reqVO.getValid()) ? "是" : "否");
reportDO.setIdentifier(reqVO.getIdentifier());
reportDO.setVerifier(reqVO.getVerifier());
// 旧表 time 为 Date,尝试解析 yyyy-MM-dd HH:mm:ss,失败则不设置
reportDO.setStatus(0);
reportDO.setConditionName(reqVO.getConditionName());
return assessReportCfgMapper.insert(reportDO) > 0;
}
@Override @Override
public AssessCleanSummaryVO cleanSummary(AssessCleanQueryReqVO reqVO) { public AssessCleanSummaryVO cleanSummary(AssessCleanQueryReqVO reqVO) {
// 这里先返回空壳,后续可对接 EXA / Python 服务 // 这里先返回空壳,后续可对接 EXA / Python 服务
@ -218,6 +256,76 @@ public class AssessReportServiceImpl implements AssessReportService {
return vo; return vo;
} }
@Override
public List<AssessReportSimpleRespVO> list(Integer modelId, String version, Boolean onlyValid) {
LambdaQueryWrapper<AssessReportCfg> wrapper = Wrappers.lambdaQuery(AssessReportCfg.class)
.eq(AssessReportCfg::getModelId, modelId)
.eq(StringUtils.hasText(version), AssessReportCfg::getVersion, version)
.eq(Boolean.TRUE.equals(onlyValid), AssessReportCfg::getValid, "是")
.orderByDesc(AssessReportCfg::getCreateTime);
List<AssessReportCfg> reports = assessReportCfgMapper.selectList(wrapper);
if (CollectionUtils.isEmpty(reports)) {
return Collections.emptyList();
}
return reports.stream().map(r -> {
AssessReportSimpleRespVO vo = new AssessReportSimpleRespVO();
vo.setId(r.getId());
vo.setScore(r.getScore());
vo.setCoverRange(r.getCoverRange());
vo.setValidFlag("是".equals(r.getValid()));
vo.setIdentifier(r.getIdentifier());
vo.setVerifier(r.getVerifier());
vo.setAssessTime(r.getTime() != null ? DateUtils.format(r.getTime(), "yyyy-MM-dd HH:mm:ss") : null);
vo.setVersion(r.getVersion());
vo.setConditionName(r.getConditionName());
return vo;
}).collect(Collectors.toList());
}
@Override
public List<AssessReportNameRespVO> listReportNames(Integer modelId, String version) {
LambdaQueryWrapper<AssessReportCfg> wrapper = Wrappers.lambdaQuery(AssessReportCfg.class)
.eq(AssessReportCfg::getModelId, modelId)
.eq(StringUtils.hasText(version), AssessReportCfg::getVersion, version)
.orderByDesc(AssessReportCfg::getTime);
List<AssessReportCfg> reports = assessReportCfgMapper.selectList(wrapper);
if (CollectionUtils.isEmpty(reports)) {
return Collections.emptyList();
}
return reports.stream().map(r -> {
AssessReportNameRespVO vo = new AssessReportNameRespVO();
vo.setId(r.getId().longValue());
if (r.getCreateTime() != null) {
vo.setName("RV" + DateUtils.format(r.getCreateTime(), "yyyy-MM-dd'T'HH:mm:ss"));
} else {
vo.setName("RV");
}
return vo;
}).collect(Collectors.toList());
}
@Override
public AssessConditionRespVO getCondition(String algorithm) {
LambdaQueryWrapper<ModelConditionDO> wrapper = Wrappers.lambdaQuery(ModelConditionDO.class)
.eq(ModelConditionDO::getAlgorithm, algorithm)
.last("limit 1");
ModelConditionDO record = modelConditionMapper.selectOne(wrapper);
AssessConditionRespVO vo = new AssessConditionRespVO();
if (record != null) {
vo.setCondition(record.getCondition());
try {
Map<String, Object> map = JsonUtils.parseObject(record.getCondition(), new TypeReference<Map<String, Object>>() {
});
Object score = map != null ? map.get("model_score") : null;
if (score instanceof Number) {
vo.setModelScore(((Number) score).doubleValue());
}
} catch (Exception ignored) {
}
}
return vo;
}
private String resolveModelInfo(ModelCfg cfg, String version) { private String resolveModelInfo(ModelCfg cfg, String version) {
if (!StringUtils.hasText(version) || "v-test".equalsIgnoreCase(version)) { if (!StringUtils.hasText(version) || "v-test".equalsIgnoreCase(version)) {
return cfg.getModelInfo(); return cfg.getModelInfo();
@ -522,7 +630,7 @@ public class AssessReportServiceImpl implements AssessReportService {
return list; return list;
} }
private Double getListValue(List<Double> list, int idx) { private Double getListValue(List<Double> list, int idx) {
if (CollectionUtils.isEmpty(list) || idx >= list.size()) { if (CollectionUtils.isEmpty(list) || idx >= list.size()) {
return 0d; return 0d;
} }
@ -551,50 +659,89 @@ class Assessinfo {
@lombok.Data @lombok.Data
class TestData { class TestData {
@com.fasterxml.jackson.annotation.JsonProperty("time")
private String time; private String time;
@com.fasterxml.jackson.annotation.JsonProperty("points")
private String points; private String points;
@com.fasterxml.jackson.annotation.JsonProperty("interval")
private Integer interval; private Integer interval;
} }
@lombok.Data @lombok.Data
class ModelTestNew { class ModelTestNew {
private boolean expand; private boolean expand;
@com.fasterxml.jackson.annotation.JsonProperty("Test_Data")
@com.fasterxml.jackson.annotation.JsonAlias({"Test_Data", "test_data"})
private TestData Test_Data; private TestData Test_Data;
@com.fasterxml.jackson.annotation.JsonProperty("dead")
private String dead; private String dead;
@com.fasterxml.jackson.annotation.JsonProperty("limit")
private String limit; private String limit;
@com.fasterxml.jackson.annotation.JsonProperty("Model_id")
@com.fasterxml.jackson.annotation.JsonAlias({"Model_id", "model_id"})
private String Model_id; private String Model_id;
@com.fasterxml.jackson.annotation.JsonProperty("Model_alg")
@com.fasterxml.jackson.annotation.JsonAlias({"Model_alg", "model_alg"})
private String Model_alg; private String Model_alg;
@com.fasterxml.jackson.annotation.JsonProperty("number_sample")
private int number_sample; private int number_sample;
@com.fasterxml.jackson.annotation.JsonProperty("assess")
private List<Assessinfo> assess; private List<Assessinfo> assess;
@com.fasterxml.jackson.annotation.JsonProperty("condition")
private String condition; private String condition;
@com.fasterxml.jackson.annotation.JsonProperty("Test_Type")
@com.fasterxml.jackson.annotation.JsonAlias({"Test_Type", "test_type"})
private String Test_Type; private String Test_Type;
@com.fasterxml.jackson.annotation.JsonProperty("Limit_Value")
@com.fasterxml.jackson.annotation.JsonAlias({"Limit_Value", "limit_value"})
private double Limit_Value; private double Limit_Value;
@com.fasterxml.jackson.annotation.JsonProperty("uplow")
private String uplow; private String uplow;
@com.fasterxml.jackson.annotation.JsonProperty("number")
private int number; private int number;
@com.fasterxml.jackson.annotation.JsonProperty("version")
private String version; private String version;
@com.fasterxml.jackson.annotation.JsonProperty("low_f")
private String low_f; private String low_f;
@com.fasterxml.jackson.annotation.JsonProperty("high_f")
private String high_f; private String high_f;
@com.fasterxml.jackson.annotation.JsonProperty("k")
private Integer k; private Integer k;
@com.fasterxml.jackson.annotation.JsonProperty("coverage")
private Double coverage; private Double coverage;
} }
@lombok.Data @lombok.Data
@NoArgsConstructor
@AllArgsConstructor
class AssessAllMessage { class AssessAllMessage {
private String message; private String message;
private Long CleanTime; // 部分接口返回小数秒,需要用 Double
private Long AssessTime; @com.fasterxml.jackson.annotation.JsonProperty("CleanTime")
private Double CleanTime;
@com.fasterxml.jackson.annotation.JsonProperty("AssessTime")
private Double AssessTime;
} }
@lombok.Data @lombok.Data
class AssessResult { class AssessResult {
@com.fasterxml.jackson.annotation.JsonProperty("amplitude")
private List<Double> amplitude;
@com.fasterxml.jackson.annotation.JsonProperty("far_variable")
private List<Double> far_variable; private List<Double> far_variable;
@com.fasterxml.jackson.annotation.JsonProperty("fdr_variable")
private List<Double> fdr_variable; private List<Double> fdr_variable;
@com.fasterxml.jackson.annotation.JsonProperty("Reconstruction_precision")
private List<Double> Reconstruction_precision; private List<Double> Reconstruction_precision;
} }
@lombok.Data @lombok.Data
class AssessAll { class AssessAll {
@com.fasterxml.jackson.annotation.JsonProperty(value = "Positive")
private AssessResult Positive; private AssessResult Positive;
// 兼容接口返回的小写 negative
@com.fasterxml.jackson.annotation.JsonProperty(value = "negative")
private AssessResult Negative; private AssessResult Negative;
} }
@ -610,6 +757,7 @@ class AssessInput {
private String inputInfo; private String inputInfo;
private Integer indexType; private Integer indexType;
private Integer sigmaType; private Integer sigmaType;
@com.fasterxml.jackson.annotation.JsonProperty("exA_IP")
private String exA_IP; private String exA_IP;
} }

20
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/model/ModelService.java

@ -27,7 +27,7 @@ public interface ModelService {
* @param id 模型id * @param id 模型id
* @return 模型信息 * @return 模型信息
*/ */
ModelInfoVO getModelInfo(Integer id); ModelInfoVO getModelInfo(Integer id, String version);
/** /**
* 新建模型 * 新建模型
@ -49,5 +49,21 @@ public interface ModelService {
ModelTestData getModelTestData(ModelTestParam param); ModelTestData getModelTestData(ModelTestParam param);
ModelInfoVO bottomModel(Integer id); /**
* 模型下装校验训练/评估后将模型状态置为已下装并落库版本
*
* @param id 模型ID
* @param reportId 评估报告ID需要通过校验
*/
ModelInfoVO bottomModel(Integer id, Long reportId);
/**
* 新建草稿版本v-test用于再次训练/发布
*/
ModelInfoVO createDraftVersion(Integer id);
/**
* 查询历史版本列表
*/
java.util.List<ModelVersionSimpleVO> listVersions(Integer modelId);
} }

129
yudao-module-alert/yudao-module-alert-biz/src/main/java/cn/iocoder/yudao/module/alert/service/model/impl/ModelServiceImpl.java

@ -12,9 +12,11 @@ import cn.iocoder.yudao.module.alert.common.enums.ModelTrash;
import cn.iocoder.yudao.module.alert.common.enums.ModelVisible; import cn.iocoder.yudao.module.alert.common.enums.ModelVisible;
import cn.iocoder.yudao.module.alert.controller.admin.model.model.ModelInfo; import cn.iocoder.yudao.module.alert.controller.admin.model.model.ModelInfo;
import cn.iocoder.yudao.module.alert.controller.admin.model.vo.*; import cn.iocoder.yudao.module.alert.controller.admin.model.vo.*;
import cn.iocoder.yudao.module.alert.dao.domain.AssessReportCfg;
import cn.iocoder.yudao.module.alert.dao.domain.ModelCfg; import cn.iocoder.yudao.module.alert.dao.domain.ModelCfg;
import cn.iocoder.yudao.module.alert.dao.domain.ModelVersion; import cn.iocoder.yudao.module.alert.dao.domain.ModelVersion;
import cn.iocoder.yudao.module.alert.dao.domain.SystemCfg; import cn.iocoder.yudao.module.alert.dao.domain.SystemCfg;
import cn.iocoder.yudao.module.alert.dao.mapper.AssessReportCfgMapper;
import cn.iocoder.yudao.module.alert.dao.service.ModelCfgService; import cn.iocoder.yudao.module.alert.dao.service.ModelCfgService;
import cn.iocoder.yudao.module.alert.dao.service.ModelVersionService; import cn.iocoder.yudao.module.alert.dao.service.ModelVersionService;
import cn.iocoder.yudao.module.alert.dao.service.SystemCfgService; import cn.iocoder.yudao.module.alert.dao.service.SystemCfgService;
@ -24,9 +26,11 @@ import cn.iocoder.yudao.module.alert.service.model.ModelService;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -50,6 +54,8 @@ public class ModelServiceImpl implements ModelService {
private final ModelVersionService modelVersionService; private final ModelVersionService modelVersionService;
private final AssessReportCfgMapper assessReportCfgMapper;
@Value("${algorithm.host}") @Value("${algorithm.host}")
private String algorithmHost; private String algorithmHost;
@ -80,6 +86,7 @@ public class ModelServiceImpl implements ModelService {
.name(modelCfg.getModelName().trim()) .name(modelCfg.getModelName().trim())
.creator(modelCfg.getCreator()) .creator(modelCfg.getCreator())
.createTime(modelCfg.getCreateTime()) .createTime(modelCfg.getCreateTime())
.version(modelCfg.getCurVersion())
.status(modelCfg.getStatus()) .status(modelCfg.getStatus())
.algorithm(Algorithm.of(modelCfg.getAlgorithmId()).toString()) .algorithm(Algorithm.of(modelCfg.getAlgorithmId()).toString())
.build()) .build())
@ -87,11 +94,28 @@ public class ModelServiceImpl implements ModelService {
} }
@Override @Override
public ModelInfoVO getModelInfo(Integer id) { public ModelInfoVO getModelInfo(Integer id, String version) {
ModelCfg modelCfg = modelCfgService.getById(id); ModelCfg modelCfg = modelCfgService.getById(id);
if (Objects.nonNull(modelCfg)) { if (Objects.nonNull(modelCfg)) {
ModelInfoVO modelInfoVO = JsonUtils.parseObject(modelCfg.getModelInfo(), ModelInfoVO.class); ModelInfoVO modelInfoVO;
// 如果传入版本,且不是 v-test,则从 model_version 读取对应版本的 model_info
if (StringUtils.hasText(version) && !"v-test".equalsIgnoreCase(version)) {
ModelVersion mv = modelVersionService.getOne(Wrappers.<ModelVersion>lambdaQuery()
.eq(ModelVersion::getModelId, id)
.eq(ModelVersion::getVersion, version)
.last("limit 1"));
if (mv != null && StringUtils.hasText(mv.getModelInfo())) {
modelInfoVO = JsonUtils.parseObject(mv.getModelInfo(), ModelInfoVO.class);
} else {
modelInfoVO = JsonUtils.parseObject(modelCfg.getModelInfo(), ModelInfoVO.class);
}
} else {
modelInfoVO = JsonUtils.parseObject(modelCfg.getModelInfo(), ModelInfoVO.class);
}
if (modelInfoVO != null) {
modelInfoVO.setSystemId(modelCfg.getSystemId()); modelInfoVO.setSystemId(modelCfg.getSystemId());
modelInfoVO.setCreateTime(modelCfg.getCreateTime());
}
return modelInfoVO; return modelInfoVO;
} }
return null; return null;
@ -167,22 +191,119 @@ public class ModelServiceImpl implements ModelService {
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public ModelInfoVO bottomModel(Integer id) { public ModelInfoVO bottomModel(Integer id, Long reportId) {
ModelCfg modelCfg = modelCfgService.getById(id); ModelCfg modelCfg = modelCfgService.getById(id);
if (Objects.isNull(modelCfg)) {
throw new RuntimeException("模型不存在");
}
ModelInfoVO modelInfo = JSON.parseObject(modelCfg.getModelInfo(), ModelInfoVO.class); ModelInfoVO modelInfo = JSON.parseObject(modelCfg.getModelInfo(), ModelInfoVO.class);
if (modelInfo == null || modelInfo.getPara() == null) {
throw new RuntimeException("模型未训练,无法下装");
}
if (CollUtil.isEmpty(modelInfo.getTrainTime())) {
throw new RuntimeException("模型尚未建立,无法下装");
}
if (ModelStatus.FINISH.desc.equals(modelInfo.getBtmState())
&& !"v-test".equalsIgnoreCase(modelInfo.getVersion())) {
throw new RuntimeException("模型已下装,无法重复操作");
}
AssessReportCfg report = null;
if (Objects.nonNull(reportId)) {
report = assessReportCfgMapper.selectById(reportId);
if (report == null || !Objects.equals(report.getModelId(), id)) {
throw new RuntimeException("评估报告不存在");
}
} else {
LambdaQueryWrapper<AssessReportCfg> wrapper = Wrappers.lambdaQuery(AssessReportCfg.class)
.eq(AssessReportCfg::getModelId, id)
.eq(StringUtils.hasText(modelInfo.getVersion()), AssessReportCfg::getVersion, modelInfo.getVersion())
.eq(AssessReportCfg::getValid, "是")
.orderByDesc(AssessReportCfg::getCreateTime)
.last("limit 1");
report = assessReportCfgMapper.selectOne(wrapper);
}
if (report == null) {
throw new RuntimeException("请先完成合格并审核通过的评估报告");
}
//todo 暂时先不验证评估报告是否通过
// if (!"是".equals(report.getValid())) {
// throw new RuntimeException("报告未通过验证,无法下装");
// }
modelInfo.setBtmState(ModelStatus.FINISH.desc); modelInfo.setBtmState(ModelStatus.FINISH.desc);
modelInfo.setVersion("v-" + DateUtil.now()); modelInfo.setVersion("v-" + DateUtil.now());
modelInfo.setModifier(SecurityFrameworkUtils.getLoginUserNickname()); modelInfo.setModifier(SecurityFrameworkUtils.getLoginUserNickname());
modelInfo.setModifiedTime(new Date()); modelInfo.setModifiedTime(new Date());
modelCfg.setModelInfo(JSON.toJSONString(modelInfo)); modelCfg.setModelInfo(JsonUtils.toJsonString(modelInfo));
modelCfg.setUpdateTime(new Date()); modelCfg.setUpdateTime(new Date());
modelCfg.setStatus(ModelStatus.FINISH.code); modelCfg.setStatus(ModelStatus.FINISH.code);
modelCfg.setCurVersion(modelInfo.getVersion());
modelCfgService.updateById(modelCfg); modelCfgService.updateById(modelCfg);
ModelVersion modelVersion = BeanUtil.copyProperties(modelCfg, ModelVersion.class); ModelVersion modelVersion = BeanUtil.copyProperties(modelCfg, ModelVersion.class);
modelVersion.setId(null); modelVersion.setId(null);
modelVersion.setModelId(id); modelVersion.setModelId(id);
modelVersion.setVersion(modelInfo.getVersion());
modelVersion.setCreateTime(new Date());
modelVersionService.save(modelVersion); modelVersionService.save(modelVersion);
report.setVersion(modelInfo.getVersion());
assessReportCfgMapper.updateById(report);
return modelInfo;
}
@Override
@Transactional(rollbackFor = Exception.class)
public ModelInfoVO createDraftVersion(Integer id) {
ModelCfg modelCfg = modelCfgService.getById(id);
if (Objects.isNull(modelCfg)) {
throw new RuntimeException("模型不存在");
}
ModelInfoVO modelInfo = JSON.parseObject(modelCfg.getModelInfo(), ModelInfoVO.class);
if (modelInfo == null) {
throw new RuntimeException("模型信息为空");
}
modelInfo.setVersion("v-test");
modelInfo.setBtmState(ModelStatus.TRAINING.desc);
modelInfo.setPara(null);
modelInfo.setPrincipal(null);
modelInfo.setPrecision(null);
modelInfo.setModifier(SecurityFrameworkUtils.getLoginUserNickname());
modelInfo.setModifiedTime(new Date());
modelCfg.setStatus(ModelStatus.TRAINING.code);
modelCfg.setCurVersion(modelInfo.getVersion());
modelCfg.setModelInfo(JSON.toJSONString(modelInfo));
modelCfg.setUpdateTime(new Date());
modelCfgService.updateById(modelCfg);
return modelInfo; return modelInfo;
} }
@Override
public List<ModelVersionSimpleVO> listVersions(Integer modelId) {
ModelCfg cfg = modelCfgService.getById(modelId);
List<ModelVersion> versions = modelVersionService.list(Wrappers.<ModelVersion>lambdaQuery()
.eq(ModelVersion::getModelId, modelId)
.orderByDesc(ModelVersion::getCreateTime));
List<ModelVersionSimpleVO> list = new ArrayList<>();
if (cfg != null && StringUtils.hasText(cfg.getCurVersion())) {
ModelVersionSimpleVO cur = new ModelVersionSimpleVO();
cur.setVersion(cfg.getCurVersion());
cur.setStatus(cfg.getStatus());
cur.setConditionName(cfg.getConditionName());
cur.setCreateTime(cfg.getUpdateTime() != null ? cfg.getUpdateTime() : cfg.getCreateTime());
list.add(cur);
}
if (CollectionUtils.isEmpty(versions)) {
return list;
}
List<ModelVersionSimpleVO> hist = versions.stream().map(v -> {
ModelVersionSimpleVO vo = new ModelVersionSimpleVO();
vo.setVersion(v.getVersion());
vo.setCreateTime(v.getCreateTime());
vo.setStatus(v.getStatus());
vo.setConditionName(v.getConditionName());
return vo;
}).collect(Collectors.toList());
list.addAll(hist);
return list;
}
} }

33
yudao-module-alert/yudao-module-alert-biz/src/main/resources/cn/iocoder/yudao/module/alert/dao/mapper/AssessReportCfgMapper.xml

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.alert.dao.mapper.AssessReportCfgMapper">
<resultMap id="BaseResultMap" type="cn.iocoder.yudao.module.alert.dao.domain.AssessReportCfg">
<id property="id" column="id" />
<result property="modelId" column="model_id" />
<result property="version" column="version" />
<result property="report" column="report" />
<result property="score" column="score" />
<result property="coverRange" column="cover_range" />
<result property="valid" column="valid" />
<result property="identifier" column="identifier" />
<result property="verifier" column="verifier" />
<result property="time" column="time" />
<result property="status" column="status" />
<result property="conditionName" column="condition_name" />
<result property="creator" column="creator" />
<result property="createTime" column="create_time" />
<result property="updater" column="updater" />
<result property="updateTime" column="update_time" />
<result property="deleted" column="deleted" />
</resultMap>
<sql id="Base_Column_List">
id,model_id,version,report,score,cover_range,
valid,identifier,verifier,time,status,
condition_name,creator,create_time,updater,update_time,
deleted
</sql>
</mapper>

45
yudao-module-alert/yudao-module-alert-biz/src/main/resources/cn/iocoder/yudao/module/alert/dao/mapper/ModelVersionMapper.xml

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.alert.dao.mapper.ModelVersionMapper">
<resultMap id="BaseResultMap" type="cn.iocoder.yudao.module.alert.dao.domain.ModelVersion">
<id property="id" column="id" />
<result property="modelId" column="model_id" />
<result property="algorithmId" column="algorithm_id" />
<result property="modelName" column="model_name" />
<result property="createName" column="create_name" />
<result property="modelInfo" column="model_info" />
<result property="status" column="status" />
<result property="visible" column="visible" />
<result property="conditionInfo" column="condition_info" />
<result property="trash" column="trash" />
<result property="assessRes" column="assess_res" />
<result property="needToAssess" column="need_to_assess" />
<result property="score" column="score" />
<result property="clearOrNot" column="clear_or_not" />
<result property="effNumber" column="eff_number" />
<result property="needToClean" column="need_to_clean" />
<result property="origAssessRes" column="orig_assess_res" />
<result property="loadCover" column="load_cover" />
<result property="coverOutput" column="cover_output" />
<result property="version" column="version" />
<result property="conditionName" column="condition_name" />
<result property="isOnline" column="is_online" />
<result property="creator" column="creator" />
<result property="createTime" column="create_time" />
<result property="updater" column="updater" />
<result property="updateTime" column="update_time" />
<result property="deleted" column="deleted" />
</resultMap>
<sql id="Base_Column_List">
id,model_id,algorithm_id,model_name,create_name,model_info,
status,visible,condition_info,trash,assess_res,
need_to_assess,score,clear_or_not,eff_number,need_to_clean,
orig_assess_res,load_cover,cover_output,version,condition_name,
is_online,creator,create_time,updater,update_time,
deleted
</sql>
</mapper>
Loading…
Cancel
Save