模型服务部署状态查询修改

This commit is contained in:
limin 2025-01-11 16:04:25 +08:00
parent d31908d6c7
commit 5a6d95d47c
6 changed files with 250 additions and 3 deletions

View File

@ -0,0 +1,60 @@
package cn.iocoder.yudao.module.llm.enums;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
@Getter
@AllArgsConstructor
public enum ModelDeployConstantEnum implements IntArrayValuable {
MODEL_DEPLOY_PENDING(1,"pending"),
MODEL_DEPLOY_RUNNING(2,"running"),
MODEL_DEPLOY_SUCCESS(2,"success"),
MODEL_DEPLOY_FAILED(3,"failed");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ModelDeployConstantEnum::getStatus).toArray();
/**
* 状态值
*/
private final Integer status;
/**
* 状态名
*/
private final String name;
@Override
public int[] array() {
return ARRAYS;
}
public static boolean isEnable(Integer status) {
return ObjUtil.equal(MODEL_DEPLOY_PENDING.status, status);
}
public static boolean isDisable(Integer status) {
return ObjUtil.equal(MODEL_DEPLOY_RUNNING.status, status);
}
public static boolean isDisable1(Integer status) {
return ObjUtil.equal(MODEL_DEPLOY_SUCCESS.status, status);
} public static boolean isDisable2(Integer status) {
return ObjUtil.equal(MODEL_DEPLOY_FAILED.status, status);
}
/**
* 根据 name 返回状态值
*
* @param name 状态名
* @return 状态值如果未找到则返回 null
*/
public static Integer getStatusByName(String name) {
for (ModelDeployConstantEnum status : values()) {
if (ObjUtil.equal(status.getName(), name)) {
return status.getStatus();
}
}
return null; // 如果未找到对应的 name返回 null
}
}

View File

@ -8,6 +8,8 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.llm.dal.dataobject.modelservice.ModelServiceDO;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.llm.controller.admin.modelservice.vo.*;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
/**
* 模型服务 Mapper
@ -28,5 +30,6 @@ public interface ModelServiceMapper extends BaseMapperX<ModelServiceDO> {
.eqIfPresent(ModelServiceDO::getStatus, reqVO.getStatus())
.orderByDesc(ModelServiceDO::getId));
}
@Update("update llm_model_service set status = #{status} where id = #{id}")
void updateStatus(@Param(value = "id")Long id,@Param(value = "status") Integer status);
}

View File

@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.llm.handler;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
public class AigcCustomDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
private static final DateTimeFormatter FORMATTER_WITH_SPACE = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private static final DateTimeFormatter FORMATTER_WITH_T = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
@Override
public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
String dateTimeString = jsonParser.getValueAsString();
String dateTimeString1 = dateTimeString.replaceAll("\\..*", "");
try {
return LocalDateTime.parse(dateTimeString1, FORMATTER_WITH_SPACE);
} catch (DateTimeParseException e1) {
try {
return LocalDateTime.parse(dateTimeString1, FORMATTER_WITH_T);
} catch (DateTimeParseException e2) {
throw new RuntimeException("Failed to parse date time string: " + dateTimeString1, e2);
}
}
}
}

View File

@ -159,8 +159,9 @@ public class TrainHttpService {
* 根据表名称查询数据
*/
public String modelTableQuery(Map<String, String> headers, String tableName,String query){
String url = llmBackendProperties.getTableDataQuery();
String res = HttpUtils.getBody(String.format(url,tableName), headers, query);
String url = String.format(llmBackendProperties.getTableDataQuery(),tableName);
url = url+query;
String res = HttpUtils.get(url, headers);
log.info(" model query info :{}", res);
return res;

View File

@ -0,0 +1,63 @@
package cn.iocoder.yudao.module.llm.service.http.vo;
import cn.hutool.core.date.DateTime;
import cn.iocoder.yudao.module.llm.handler.AigcCustomDateTimeDeserializer;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AigcModelDeployVO {
/*
{
"updated_at": "2025-01-09 13:32:10.8013027+00:00",
"model_id": 2,
"created_at": "2025-01-09 13:32:10.8013027+00:00",
"status": "pending",
"inferred_type": "cpu",
"gpu": 0,
"quantization": "float16",
"deployment_name": "test-2",
"deleted_at": "2025-01-09 13:32:18.705719834+00:00",
"id": 4,
"model_path": "/data/base-model/test",
"replicas": 1,
"label": "cpu-aigc-model",
"cpu": 1,
"vllm": 0
}*/
@JsonProperty("updated_at")
// @JsonDeserialize(using = AigcCustomDateTimeDeserializer.class)
private LocalDateTime updatedAt;
@JsonProperty("model_id")
private Integer modeId;
@JsonProperty("created_at")
// @JsonDeserialize(using = AigcCustomDateTimeDeserializer.class)
private LocalDateTime createdAt;
private String status;
@JsonProperty("inferred_type")
private String inferredType;
private Integer gpu;
private String quantization;
@JsonProperty("deployment_name")
private String deploymentName;
@JsonProperty("deleted_at")
// @JsonDeserialize(using = AigcCustomDateTimeDeserializer.class)
private LocalDateTime deletedAt;
private Integer id;
@JsonProperty("model_path")
private String modelPath;
private Integer replicas;
private String label;
private Integer cpu;
private Integer vllm;
}

View File

@ -0,0 +1,89 @@
package cn.iocoder.yudao.module.llm.service.modelservice;
import cn.hutool.json.JSONObject;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.llm.controller.admin.dataset.dto.DataJsonTemplate;
import cn.iocoder.yudao.module.llm.dal.dataobject.modelservice.ModelServiceDO;
import cn.iocoder.yudao.module.llm.dal.mysql.modelservice.ModelServiceMapper;
import cn.iocoder.yudao.module.llm.enums.ModelDeployConstantEnum;
import cn.iocoder.yudao.module.llm.handler.AigcCustomDateTimeDeserializer;
import cn.iocoder.yudao.module.llm.service.http.TrainHttpService;
import cn.iocoder.yudao.module.llm.service.http.vo.AigcModelDeployVO;
import cn.iocoder.yudao.module.llm.service.http.vo.AigcRespVO;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.esotericsoftware.kryo.serializers.TimeSerializers;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
@Component
@Slf4j
public class ModelServiceTaskSyncService {
@Resource
private TrainHttpService trainHttpService;
@Resource
private ModelServiceMapper modelServiceMapper;
@Scheduled(cron ="5 * * * * ?")
public void syncStatusModels() {
log.info("ModelServiceTaskSync 定时任务启动");
LambdaQueryWrapper<ModelServiceDO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(ModelServiceDO::getStatus, 1);
List<ModelServiceDO> modelServiceList = modelServiceMapper.selectList(wrapper);
if (!CollectionUtils.isAnyEmpty(modelServiceList)){
modelServiceList.forEach(modelServiceDO -> {
Long jobid = modelServiceDO.getJobId();
if (jobid == null){
return;
}
// 使用 TypeReference 解析 JSON 字符串为 List<String>
try {
String query = "?filter={\"model_id\":"+modelServiceDO.getJobId()+"}";
String res = trainHttpService.modelTableQuery(new HashMap<>(), "model_deploy",query);
log.info("获取 aigc model_deploy 表数据 info {}",res);
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
SimpleModule module = new SimpleModule();
module.addDeserializer(LocalDateTime.class, new AigcCustomDateTimeDeserializer());
mapper.registerModule(module);
List<AigcModelDeployVO> aigcModelDeployVOS = mapper.readValue(res,new TypeReference<List<AigcModelDeployVO>>() {});
Collections.sort(aigcModelDeployVOS, Comparator.comparing(AigcModelDeployVO::getUpdatedAt).reversed());
// 获取最新的一条记录
if (!aigcModelDeployVOS.isEmpty()) {
AigcModelDeployVO latestRecord = aigcModelDeployVOS.get(0);
modelServiceMapper.updateStatus(modelServiceDO.getId(), ModelDeployConstantEnum.getStatusByName(latestRecord.getStatus()));
log.info("最新的 aigcModelDeployVO: {}", latestRecord);
}
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
});
}
log.info("ModelServiceTaskSync 定时任务结束");
}
}