houzhongjian
2024-12-05 a709abfd8ffec1524cefff30c3581f4425695433
提交 | 用户 | 时间
449017 1 package com.iailab.module.model.mpk.controller.admin;
D 2
a8c6a6 3 import cn.hutool.cache.CacheUtil;
D 4 import cn.hutool.cache.impl.FIFOCache;
449017 5 import com.alibaba.fastjson.JSON;
D 6 import com.alibaba.fastjson.JSONArray;
3e18d4 7 import com.iail.utils.RSAUtils;
449017 8 import com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants;
D 9 import com.iailab.framework.common.pojo.CommonResult;
558ffc 10 import com.iailab.framework.tenant.core.context.TenantContextHolder;
1fea3e 11 import com.iailab.module.model.mpk.common.MdkConstant;
912a1e 12 import com.iailab.module.model.mpk.common.utils.DllUtils;
449017 13 import com.iailab.module.model.mpk.common.utils.Readtxt;
D 14 import com.iailab.module.model.mpk.dto.MdkDTO;
3e18d4 15 import com.iailab.module.model.mpk.dto.MdkRunDTO;
a8c6a6 16 import com.iailab.module.model.mpk.dto.MethodSettingDTO;
449017 17 import io.swagger.v3.oas.annotations.Operation;
912a1e 18 import lombok.extern.slf4j.Slf4j;
1fea3e 19 import org.springframework.beans.factory.annotation.Value;
449017 20 import org.springframework.util.CollectionUtils;
D 21 import org.springframework.web.bind.annotation.*;
22 import org.springframework.web.multipart.MultipartFile;
23
1fea3e 24 import java.io.File;
3e18d4 25 import java.lang.reflect.Method;
1fea3e 26 import java.net.URLClassLoader;
D 27 import java.util.ArrayList;
28 import java.util.HashMap;
29 import java.util.List;
a8c6a6 30 import java.util.UUID;
449017 31
D 32 import static com.iailab.framework.common.pojo.CommonResult.error;
33 import static com.iailab.framework.common.pojo.CommonResult.success;
34
35 /**
36  * @author PanZhibao
37  * @Description
38  * @createTime 2024年08月08日
39  */
40 @RestController
912a1e 41 @Slf4j
449017 42 @RequestMapping("/model/mpk/api")
D 43 public class MdkController {
1fea3e 44     @Value("${mpk.bak-file-path}")
D 45     private String mpkBakFilePath;
46
a8c6a6 47     // 先进先出缓存
D 48     private static FIFOCache<String, String> cache = CacheUtil.newFIFOCache(100);
1fea3e 49
3e18d4 50     /**
D 51      * @description: 模型测试运行
52      * @author: dzd
53      * @date: 2024/10/14 15:26
54      **/
55     @PostMapping("test")
56     public CommonResult<String> test(@RequestBody MdkDTO dto) {
558ffc 57         Long tenantId = TenantContextHolder.getTenantId();
D 58         // 备份文件 租户隔离
59         String mpkTenantBakFilePath = mpkBakFilePath + File.separator + tenantId;
60
912a1e 61         Class<?> clazz;
D 62         URLClassLoader classLoader;
1fea3e 63         try {
558ffc 64             File jarFile = new File(mpkTenantBakFilePath + File.separator + MdkConstant.JAR + File.separator + dto.getPyName() + ".jar");
1fea3e 65             if (!jarFile.exists()) {
D 66                 throw new RuntimeException("jar包不存在,请先生成代码。jarPath:" + jarFile.getAbsolutePath());
67             }
558ffc 68             File dllFile = new File(mpkTenantBakFilePath + File.separator + MdkConstant.DLL + File.separator + dto.getPyName() + ".dll");
1fea3e 69             if (!dllFile.exists()) {
912a1e 70                 throw new RuntimeException("dll文件不存在,请先生成代码。dllPath:" + dllFile.getAbsolutePath());
1fea3e 71             }
D 72             // 加载jar包
912a1e 73             classLoader = DllUtils.loadJar(jarFile.getAbsolutePath());
D 74             // 实现类
75             clazz = classLoader.loadClass(dto.getClassName());
76             // 加载dll到实现类
77             DllUtils.loadDll(clazz,dllFile.getAbsolutePath());
1fea3e 78         } catch (Exception e) {
912a1e 79             e.printStackTrace();
1fea3e 80             throw new RuntimeException("加载运行环境失败。");
D 81         }
82
449017 83         System.out.println("runTime=" + System.currentTimeMillis());
D 84         try {
a8c6a6 85             List<String> uuids = dto.getUuids();
449017 86
a8c6a6 87             int paramLength = dto.getHasModel() ? uuids.size() + 2 : uuids.size() + 1;
449017 88             Object[] paramsValueArray = new Object[paramLength];
D 89             Class<?>[] paramsArray = new Class[paramLength];
90
91             try {
a8c6a6 92                 for (int i = 0; i < uuids.size(); i++) {
D 93                     String uuid = uuids.get(i);
94                     if (!cache.containsKey(uuid)) {
95                         return error(GlobalErrorCodeConstants.BAD_REQUEST.getCode(),"请重新导入模型参数");
96                     }
97                     JSONArray jsonArray = JSON.parseArray(cache.get(uuid));
449017 98                     double[][] data = new double[jsonArray.size()][jsonArray.getJSONArray(0).size()];
D 99                     for (int j = 0; j < jsonArray.size(); j++) {
100                         for (int k = 0; k < jsonArray.getJSONArray(j).size(); k++) {
101                             data[j][k] = jsonArray.getJSONArray(j).getDoubleValue(k);
102                         }
103                     }
104                     paramsValueArray[i] = data;
105                     paramsArray[i] = double[][].class;
106                 }
107             } catch (Exception e) {
108                 e.printStackTrace();
a8c6a6 109                 return error(GlobalErrorCodeConstants.BAD_REQUEST.getCode(),"模型参数错误,请检查!");
449017 110             }
D 111
a8c6a6 112             try {
4f4b05 113                 if (dto.getModelSettings().stream().noneMatch(e -> e.getSettingKey().equals(MdkConstant.PY_FILE_KEY))) {
D 114                     return error(GlobalErrorCodeConstants.BAD_REQUEST.getCode(),"模型设置参数缺少必要信息【" + MdkConstant.PY_FILE_KEY +  "】,请重新上传模型!");
115                 }
116
a8c6a6 117                 if (dto.getHasModel()) {
D 118                     paramsValueArray[uuids.size()] = dto.getModel();
119                     paramsValueArray[uuids.size() + 1] = handleModelSettings(dto.getModelSettings());
120                     paramsArray[uuids.size()] = HashMap.class;
121                     paramsArray[uuids.size() + 1] = HashMap.class;
122                 }else {
123                     paramsValueArray[uuids.size()] = handleModelSettings(dto.getModelSettings());
124                     paramsArray[uuids.size()] = HashMap.class;
125                 }
126             } catch (Exception e) {
127                 e.printStackTrace();
128                 return error(GlobalErrorCodeConstants.BAD_REQUEST.getCode(),"模型设置错误,请检查!");
449017 129             }
D 130
912a1e 131             HashMap result = (HashMap) clazz.getDeclaredMethod(dto.getMethodName(), paramsArray).invoke(clazz.newInstance(), paramsValueArray);
449017 132             return success(JSON.toJSONString(result));
D 133         } catch (Exception ex) {
134             ex.printStackTrace();
135             return error(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"运行异常");
136         } finally {
912a1e 137             if (classLoader != null) {
c12dae 138                 DllUtils.unloadDll(classLoader);
D 139                 DllUtils.unloadJar(classLoader);
912a1e 140             }
449017 141             System.gc();
D 142         }
a8c6a6 143     }
D 144
145     private HashMap<String, Object> handleModelSettings(List<MethodSettingDTO> modelSettings) {
146         HashMap<String, Object> resultMap = null;
147         try {
148             resultMap = new HashMap<>(modelSettings.size());
149             for (MethodSettingDTO modelSetting : modelSettings) {
150                 switch (modelSetting.getValueType()) {
151                     case "int":
152                         resultMap.put(modelSetting.getSettingKey(), Integer.valueOf(modelSetting.getSettingValue()));
153                         break;
154                     case "string":
155                         resultMap.put(modelSetting.getSettingKey(), modelSetting.getSettingValue());
156                         break;
157                     case "decimal":
158                         resultMap.put(modelSetting.getSettingKey(), Double.valueOf(modelSetting.getSettingValue()));
159                         break;
160                     case "decimalArray":
161                         JSONArray jsonArray = JSON.parseArray(modelSetting.getSettingValue());
162                         double[] doubles = new double[jsonArray.size()];
163                         for (int i = 0; i < jsonArray.size(); i++) {
164                             doubles[i] = Double.valueOf(String.valueOf(jsonArray.get(i)));
165                         }
166                         resultMap.put(modelSetting.getSettingKey(), doubles);
167                         break;
168                 }
169             }
170         } catch (NumberFormatException e) {
171             throw new RuntimeException("模型参数有误,请检查!!!");
172         }
173         return resultMap;
449017 174     }
D 175
3e18d4 176     /**
D 177      * @description: 模型运行
178      * @author: dzd
179      * @date: 2024/10/14 15:26
180      **/
181     @PostMapping("run")
182     public CommonResult<String> run(@RequestBody MdkRunDTO dto) {
183         if (RSAUtils.checkLisenceBean().getCode() != 1) {
184             log.error("Lisence 不可用!");
185             return CommonResult.error(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"Lisence 不可用!");
186         } else {
187             try {
188                 URLClassLoader classLoader = DllUtils.getClassLoader(dto.getProjectId());
189                 if (null == classLoader) {
190                     return CommonResult.error(GlobalErrorCodeConstants.ERROR_CONFIGURATION.getCode(),"请先发布项目!");
191                 }
192
193                 Class<?> clazz = classLoader.loadClass(dto.getClassName());
194                 Method method = clazz.getMethod(dto.getMethodName(), dto.getParamsClassArray());
195                 HashMap invoke = (HashMap) method.invoke(clazz.newInstance(), dto.getParamsValueArray());
196
197                 // todo 将结果存入数据库
198
199             } catch (Exception e) {
200                 log.error("模型运行失败",e);
201                 return CommonResult.error(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"模型运行失败!");
202             }
203         }
204         return CommonResult.success();
205     }
206
449017 207     @PostMapping("/import")
D 208     @Operation(summary = "导入参数")
a8c6a6 209     public CommonResult<List<HashMap<String,Object>>> importExcel(@RequestParam("file") MultipartFile file) throws Exception {
449017 210         List<double[][]> datas = Readtxt.readMethodExcel(file);
a8c6a6 211         List<HashMap<String,Object>> result = new ArrayList<>();
449017 212         if (!CollectionUtils.isEmpty(datas)) {
D 213             for (double[][] data : datas) {
214                 if (data.length > 0) {
a8c6a6 215                     HashMap<String,Object> map = new HashMap<>();
D 216                     String uuid = UUID.randomUUID().toString();
217                     map.put("uuid",uuid);
218                     map.put("data",JSON.toJSONString(data));
219                     cache.put(uuid,JSON.toJSONString(data));
220                     result.add(map);
449017 221                 }
D 222             }
223         }
224         return success(result);
1fea3e 225     }
449017 226 }