feat(llm): 更新基座模型状态并优化相关功能

- 在 BaseModelController 中添加刷新基座模型状态的接口
- 在 BaseModelService 中新增相关方法以支持模型状态更新
- 在 BaseModelTaskService 中实现定时任务以同步远程模型状态
- 更新 BaseModelDO 和相关 VO 类以适应新的模型状态逻辑- 在 LLMBackendProperties 中添加 baseModelStatus 属性以配置模型状态接口 URL
This commit is contained in:
sunxiqing 2025-03-05 16:41:23 +08:00
parent 9523d0c077
commit ebe7fced35
11 changed files with 236 additions and 31 deletions

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.llm.controller.admin.basemodel;
import cn.iocoder.yudao.module.llm.service.basemodel.BaseModelTaskService;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@ -38,6 +39,8 @@ public class BaseModelController {
@Resource
private BaseModelService baseModelService;
@Resource
private BaseModelTaskService baseModelTaskService;
@PostMapping("/create")
@Operation(summary = "创建基座模型")
@ -58,7 +61,7 @@ public class BaseModelController {
@Operation(summary = "启动")
// @PreAuthorize("@ss.hasPermission('llm:base-model:update')")
public CommonResult<Boolean> active(@Valid @RequestBody BaseModelSaveReqVO updateReqVO) {
updateReqVO.setIsActive(true);
updateReqVO.setIsActive(1);
baseModelService.updateBaseModel(updateReqVO);
return success(true);
}
@ -71,6 +74,14 @@ public class BaseModelController {
return success(true);
}
@GetMapping("/getCount")
@Operation(summary = "刷新基座模型状态")
public CommonResult<PageResult<BaseModelRespVO>> getCount(@Valid BaseModelPageReqVO pageReqVO) {
baseModelTaskService.updateTheBaseModelState();
PageResult<BaseModelDO> pageResult = baseModelService.getBaseModelPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, BaseModelRespVO.class));
}
@DeleteMapping("/delete")
@Operation(summary = "删除基座模型")
@Parameter(name = "id", description = "编号", required = true)

View File

@ -28,7 +28,7 @@ public class BaseModelPageReqVO extends PageParam {
private String modelType;
@Schema(description = "是否启动")
private Boolean isActive;
private Integer isActive;
@Schema(description = "是否微调")
private Boolean isFinetuned;

View File

@ -34,7 +34,7 @@ public class BaseModelRespVO {
@Schema(description = "是否启动", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("是否启动")
private Boolean isActive;
private Integer isActive;
@Schema(description = "是否微调", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("是否微调")

View File

@ -30,7 +30,7 @@ public class BaseModelSaveReqVO {
@Schema(description = "是否启动", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "是否启动不能为空")
private Boolean isActive;
private Integer isActive;
@Schema(description = "是否微调", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "是否微调不能为空")
@ -58,4 +58,6 @@ public class BaseModelSaveReqVO {
private Long gpuId;
private String gpuName;
private String aigcModelName;
}

View File

@ -45,8 +45,9 @@ public class BaseModelDO extends BaseDO {
private String modelType;
/**
* 是否启动
* 字典base_model_status
*/
private Boolean isActive;
private Integer isActive;
/**
* 是否微调
*/

View File

@ -112,6 +112,8 @@ public class LLMBackendProperties {
private String autoEvaluation;
private String textToImage;
private String baseModelStatus;
/**
* 知识库向量嵌入
*/

View File

@ -70,4 +70,10 @@ public interface BaseModelService {
* @param updateReqVO 更新信息
*/
void unActive (@Valid BaseModelSaveReqVO updateReqVO);
void updetatebyId(BaseModelDO localModel);
List<BaseModelDO> getAllModels();
void updetatebyIds(List<BaseModelDO> differentModels);
}

View File

@ -153,10 +153,26 @@ public class BaseModelServiceImpl implements BaseModelService {
// 校验使用
validateModelUse(updateReqVO.getId());
updateReqVO.setIsActive(false);
updateReqVO.setIsActive(0);
updateBaseModel(updateReqVO);
}
@Override
public void updetatebyId(BaseModelDO localModel) {
baseModelMapper.updateById(localModel);
}
@Override
public List<BaseModelDO> getAllModels() {
List<BaseModelDO> baseModelDOS = baseModelMapper.selectList();
return baseModelDOS;
}
@Override
public void updetatebyIds(List<BaseModelDO> differentModels) {
baseModelMapper.updateBatch(differentModels);
}
/**
* 校验模型使用情况
*

View File

@ -1,11 +1,15 @@
package cn.iocoder.yudao.module.llm.service.basemodel;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
import cn.iocoder.yudao.module.llm.controller.admin.basemodel.vo.BaseModelSaveReqVO;
import cn.iocoder.yudao.module.llm.dal.dataobject.basemodel.BaseModelDO;
import cn.iocoder.yudao.module.llm.dal.dataobject.servername.ServerNameDO;
import cn.iocoder.yudao.module.llm.dal.mysql.servername.ServerNameMapper;
import cn.iocoder.yudao.module.llm.framework.backend.config.LLMBackendProperties;
import cn.iocoder.yudao.module.llm.handler.AigcCustomDateTimeDeserializer;
import cn.iocoder.yudao.module.llm.service.basemodel.vo.ModelListRes;
import cn.iocoder.yudao.module.llm.service.basemodel.vo.PedestalModelVo;
import cn.iocoder.yudao.module.llm.service.http.FineTuningTaskHttpService;
import cn.iocoder.yudao.module.llm.service.http.TrainHttpService;
import cn.iocoder.yudao.module.llm.service.http.vo.AigcModelDeploySaveReq;
@ -34,22 +38,20 @@ import java.util.stream.Collectors;
@Slf4j
public class BaseModelTaskService {
private static final String DEFAULT_MODEL_URL_SUFFIX = "/v1/chat/completions";
@Resource
TrainHttpService trainHttpService;
@Resource
BaseModelService baseModelService;
@Resource
ServerNameMapper serverNameMapper;
@Resource
private FineTuningTaskHttpService fineTuningTaskHttpService;
private static final String DEFAULT_MODEL_URL_SUFFIX = "/v1/chat/completions";
@Resource
private LLMBackendProperties llmBackendProperties;
// 减少维护 先注释掉
@Scheduled(cron ="0 0/1 * * * ?")
@Scheduled(cron = "0 0/1 * * * ?")
public void synchronous() throws JsonProcessingException {
try {
log.info("开始同步基础模型信息...");
@ -87,7 +89,8 @@ public class BaseModelTaskService {
SimpleModule module = new SimpleModule();
module.addDeserializer(LocalDateTime.class, new AigcCustomDateTimeDeserializer());
mapper.registerModule(module);
List<AigcModelDeployVO> aigcModelDeploys = mapper.readValue(res, new TypeReference<List<AigcModelDeployVO>>() {});
List<AigcModelDeployVO> aigcModelDeploys = mapper.readValue(res, new TypeReference<List<AigcModelDeployVO>>() {
});
log.debug("模型部署信息解析完成。记录数量: {}", aigcModelDeploys.size());
if (!aigcModelDeploys.isEmpty()) {
@ -135,11 +138,11 @@ public class BaseModelTaskService {
}
// @Scheduled(cron ="0 0/1 * * * ?")
// @Scheduled(cron ="0 0/1 * * * ?")
public void updateBaseModel() {
Log.info("定时任务启动");
String resStr = trainHttpService.modelsList("");
Log.info("获取aicg模型列表返回数据内容{}",resStr);
Log.info("获取aicg模型列表返回数据内容{}", resStr);
JSONObject jsonObject = JSONObject.parseObject(resStr);
JSONObject data = jsonObject.getJSONObject("data");
JSONArray list = data.getJSONArray("list");
@ -148,43 +151,112 @@ public class BaseModelTaskService {
for (ModelListRes modelListRe : modelListRes) {
Long id = modelListRe.getId();
BaseModelDO byAigcId = baseModelService.getByAigcId(id);
if(byAigcId == null){
if (byAigcId == null) {
BaseModelSaveReqVO baseModelSaveReqVO = new BaseModelSaveReqVO();
baseModelSaveReqVO.setAigcId(id);
baseModelSaveReqVO.setModelName(modelListRe.getModelName());
baseModelSaveReqVO.setModelType(modelListRe.getModelType());
baseModelSaveReqVO.setMaxContextLength(modelListRe.getMaxTokens());
baseModelSaveReqVO.setIsActive(modelListRe.getEnabled());
baseModelSaveReqVO.setIsActive(1);
baseModelSaveReqVO.setIsFinetuned(modelListRe.getIsFineTuning());
baseModelSaveReqVO.setNotes(modelListRe.getRemark());
baseModelSaveReqVO.setParameterCount(1);
baseModelService.createBaseModel(baseModelSaveReqVO);
}else{
BaseModelSaveReqVO baseModelSaveReqVO = new BaseModelSaveReqVO();
baseModelSaveReqVO.setId(byAigcId.getId());
baseModelSaveReqVO.setParameterCount(1);
baseModelSaveReqVO.setModelName(modelListRe.getModelName());
baseModelSaveReqVO.setModelType(modelListRe.getModelType());
baseModelSaveReqVO.setMaxContextLength(modelListRe.getMaxTokens());
baseModelSaveReqVO.setIsActive(modelListRe.getEnabled());
baseModelSaveReqVO.setIsFinetuned(modelListRe.getIsFineTuning());
baseModelSaveReqVO.setNotes(modelListRe.getRemark());
baseModelService.updateBaseModel(baseModelSaveReqVO);
} else {
BaseModelSaveReqVO baseModelSaveReqVO = new BaseModelSaveReqVO();
baseModelSaveReqVO.setId(byAigcId.getId());
baseModelSaveReqVO.setParameterCount(1);
baseModelSaveReqVO.setModelName(modelListRe.getModelName());
baseModelSaveReqVO.setModelType(modelListRe.getModelType());
baseModelSaveReqVO.setMaxContextLength(modelListRe.getMaxTokens());
baseModelSaveReqVO.setIsActive(1);
baseModelSaveReqVO.setIsFinetuned(modelListRe.getIsFineTuning());
baseModelSaveReqVO.setNotes(modelListRe.getRemark());
baseModelService.updateBaseModel(baseModelSaveReqVO);
}
}
List<BaseModelDO> baseModelList = baseModelService.getBaseModelList();
List<Long> ids = modelListRes.stream().map(ModelListRes::getId).collect(Collectors.toList());
List<Long> ids = modelListRes.stream().map(ModelListRes::getId).collect(Collectors.toList());
for (BaseModelDO baseModelDO : baseModelList) {
if(baseModelDO.getAigcId() == null){
if (baseModelDO.getAigcId() == null) {
continue;
}
if(!ids.contains(baseModelDO.getAigcId())){
if (!ids.contains(baseModelDO.getAigcId())) {
baseModelService.deleteBaseModel(baseModelDO.getId());
}
}
}
@Scheduled(cron = "0 0/5 * * * ?")
public void updateTheBaseModelState() {
try {
// 获取所有基础模型列表
List<BaseModelDO> baseModelList = baseModelService.getAllModels();
log.info("获取到 {} 个基础模型", baseModelList.size());
// 调用接口获取远程模型状态
String resStr = HttpUtils.post(llmBackendProperties.getBaseModelStatus(), null, "");
log.info("获取aicg模型列表返回数据内容: {}", resStr);
JSONArray objects = JSONArray.parseArray(resStr);
String s = JSON.toJSONString(objects);
List<PedestalModelVo> modelListRes = JSONObject.parseArray(s, PedestalModelVo.class);
List<String> remoteModelNames = modelListRes.stream()
.map(PedestalModelVo::getDeploymentName)
.collect(Collectors.toList());
List<BaseModelDO> differentModels = baseModelList.stream()
.filter(baseModel -> !remoteModelNames.contains(baseModel.getModelName())&& baseModel.getIsActive()==1)
.collect(Collectors.toList());
for (BaseModelDO baseModel : differentModels){
baseModel.setIsActive(2);
}
baseModelService.updetatebyIds(differentModels);
for (PedestalModelVo pedestalModelVo : modelListRes) {
// JSONObject jsonObject = (JSONObject) object;
// String string = JSON.toJSONString(jsonObject);
// PedestalModelVo pedestalModelVo = JSON.parseObject(string, PedestalModelVo.class);
// 查找本地模型
List<BaseModelDO> localModels = baseModelList.stream()
.filter(baseModel -> pedestalModelVo.getDeploymentName().equals(baseModel.getModelName()))
.collect(Collectors.toList());
if (localModels != null && localModels.size() > 0) {
BaseModelDO localModel = localModels.get(0);
// 如果状态不是 "running"更新本地状态
if (!"running".equals(pedestalModelVo.getStatus())) {
log.info("更新模型状态,模型名称: {}, 状态: {}", pedestalModelVo.getDeploymentName(), pedestalModelVo.getStatus());
localModel.setIsActive(2);
baseModelService.updetatebyId(localModel);
} else {
String string1 = pedestalModelVo.getHost() + "/v1/chat/completions";
if (!string1.equals(localModel.getChatUrl())) {
localModel.setIsActive(1);
localModel.setChatUrl(string1);
baseModelService.updetatebyId(localModel);
}
log.debug("模型 {} 状态为 running无需更新", pedestalModelVo.getDeploymentName());
}
} else {
//新增基座模型
if ("running".equals(pedestalModelVo.getStatus())){
BaseModelSaveReqVO baseModelSaveReqVO = new BaseModelSaveReqVO();
baseModelSaveReqVO.setModelName(pedestalModelVo.getDeploymentName());
baseModelSaveReqVO.setIsActive(1);
baseModelSaveReqVO.setAigcModelName(pedestalModelVo.getDeploymentName());
baseModelSaveReqVO.setChatUrl(pedestalModelVo.getHost() + "/v1/chat/completions");
baseModelService.createBaseModel(baseModelSaveReqVO);
}
}
}
} catch (Exception e) {
log.error("更新基础模型状态时发生异常: {}", e.getMessage(), e);
}
}
}

View File

@ -0,0 +1,93 @@
package cn.iocoder.yudao.module.llm.service.basemodel.vo;
import lombok.Data;
@Data
public class PedestalModelVo {
/**
* 创建时间
*/
public String createdAt;
/**
* 更新时间
*/
public String updatedAt;
/**
* 模型ID
*/
public int modelId;
/**
* 模型状态
*/
public String status;
/**
* 推理类型
*/
public String inferredType;
/**
* GPU数量
*/
public int gpu;
/**
* 量化类型
*/
public String quantization;
/**
* 部署名称
*/
public String deploymentName;
/**
* 端口号
*/
public String port;
/**
* ID
*/
public int id;
/**
* 删除时间
*/
public String deletedAt;
/**
* 模型路径
*/
public String modelPath;
/**
* 副本数量
*/
public int replicas;
/**
* 标签
*/
public String label;
/**
* CPU数量
*/
public int cpu;
/**
* VLLM数量
*/
public int vllm;
/**
* 主机地址
*/
public String host;
}

View File

@ -328,6 +328,8 @@ llm:
check_file_list: /llm/finetuning/checkpoints?model_name=
# 模型调优停止 POST
stop_finetuning: /llm/finetuning/stop
# 基座模型状态 POST
base_model_status: http://36.103.199.248:5123/llm/deploy/list
#################### 30000: 大模型对话相关API。 ###################
#### 大模型对话