TakaiAiServiceImpl.java 68 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492
  1. package com.takai.ai.service.impl;
  2. import com.alibaba.fastjson2.JSON;
  3. import com.alibaba.fastjson2.JSONArray;
  4. import com.alibaba.fastjson2.JSONObject;
  5. import com.takai.ai.domain.TakaiSysOss;
  6. import com.takai.ai.domain.dto.*;
  7. import com.takai.ai.domain.entity.*;
  8. import com.takai.ai.mapper.*;
  9. import com.takai.ai.service.ITakaiAiService;
  10. import com.takai.ai.utils.ApprovalFlowManager;
  11. import com.takai.ai.utils.ApprovalNode;
  12. import com.takai.ai.utils.MinioUtil;
  13. import com.takai.ai.utils.SnowflakeDigitGenerator;
  14. import com.takai.common.annotation.DataSource;
  15. import com.takai.common.config.DeepseekConfig;
  16. import com.takai.common.core.domain.entity.SysDictData;
  17. import com.takai.common.core.redis.RedisCache;
  18. import com.takai.common.enums.DataSourceType;
  19. import com.takai.common.utils.StringUtils;
  20. import com.takai.common.utils.uuid.IdUtils;
  21. import com.takai.framework.web.service.SysPermissionService;
  22. import com.takai.system.domain.DocumentAuditConfig;
  23. import com.takai.system.domain.DocumentAuditInfo;
  24. import com.takai.system.domain.TypeApp;
  25. import com.takai.system.mapper.SysDictDataMapper;
  26. import com.takai.system.mapper.TypeAppMapper;
  27. import com.takai.system.mapper.DocumentAuditConfigMapper;
  28. import com.takai.system.mapper.DocumentAuditInfoMapper;
  29. import lombok.extern.slf4j.Slf4j;
  30. import okhttp3.*;
  31. import okhttp3.sse.EventSource;
  32. import okhttp3.sse.EventSourceListener;
  33. import okhttp3.sse.EventSources;
  34. import org.apache.commons.collections4.MapUtils;
  35. import org.slf4j.Logger;
  36. import org.slf4j.LoggerFactory;
  37. import org.springframework.beans.factory.annotation.Autowired;
  38. import org.springframework.data.redis.core.RedisTemplate;
  39. import org.springframework.stereotype.Service;
  40. import org.springframework.web.multipart.MultipartFile;
  41. import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
  42. import javax.validation.constraints.NotNull;
  43. import java.io.IOException;
  44. import java.time.LocalDate;
  45. import java.time.LocalDateTime;
  46. import java.time.temporal.ChronoUnit;
  47. import java.util.*;
  48. import java.util.concurrent.TimeUnit;
  49. import java.util.function.Function;
  50. import java.util.stream.Collectors;
  51. /**
  52. * 高井 业务层处理
  53. *
  54. * @author takai
  55. */
  56. @Slf4j
  57. @Service
  58. @DataSource(DataSourceType.MASTER)
  59. public class TakaiAiServiceImpl implements ITakaiAiService {
  60. private static final Logger logger = LoggerFactory.getLogger(TakaiAiServiceImpl.class);
  61. @Autowired
  62. private TakaiDialogMapper takaiDialogMapper;
  63. @Autowired
  64. private TakaiApplicationMapper takaiApplicationMapper;
  65. @Autowired
  66. private TakaiQuestionMapper takaiQuestionMapper;
  67. @Autowired
  68. private TakaiKnowledgeMapper takaiKnowledgeMapper;
  69. @Autowired
  70. private TakaiDocumentMapper takaiDocumentMapper;
  71. @Autowired
  72. private TakaiSysOssConfigMapper takaiSysOssConfigMapper;
  73. @Autowired
  74. private TakaiSysOssMapper takaiSysOssMapper;
  75. @Autowired
  76. private MinioUtil minioUtil;
  77. @Autowired
  78. private TakaiDocumentSettingsMapper takaiDocumentSettingsMapper;
  79. @Autowired
  80. private DeepseekConfig deepseekConfig;
  81. @Autowired
  82. private TakaiAppInfoMapper takaiAppInfoMapper;
  83. @Autowired
  84. private TakaiMediaReplacementMapper takaiMediaReplacementMapper;
  85. @Autowired
  86. private RedisCache redisCache;
  87. @Autowired
  88. public RedisTemplate redisTemplate;
  89. @Autowired
  90. private TakaiSliceInfoMapper takaiSliceInfoMapper;
  91. @Autowired
  92. private DocumentAuditConfigMapper documentAuditConfigMapper;
  93. @Autowired
  94. private DocumentAuditInfoMapper documentAuditInfoMapper;
  95. @Autowired
  96. private SysPermissionService permissionService;
  97. @Autowired
  98. private TypeAppMapper appTypeMapper;
  99. @Autowired
  100. private TakaiAppCollectMapper appCollectMapper;
  101. @Autowired
  102. private SysDictDataMapper sysDictDataMapper;
  103. public static final String START_SIGN = "【";
  104. public static final String END_SIGN = "】";
  105. public static final String SYMBOL = "【示意图序号";
  106. public static final String USER_STR = "user";
  107. public static final String TODAY = "今天";
  108. public static final String BEFOR = "天前";
  109. @Override
  110. public void initDeepseekInfo() {
  111. //获取应用列表
  112. // List<TakaiApplication> appList = takaiApplicationMapper.selectApplicationList(null);
  113. setRedisCache(null);
  114. }
  115. private void setRedisCache(String knowledgeId) {
  116. //获取知识库列表
  117. List<TakaiKnowledge> knowledgeList = null;
  118. if (StringUtils.isEmpty(knowledgeId)) {
  119. knowledgeList = takaiKnowledgeMapper.selectKnowledgeList(null);
  120. } else {
  121. knowledgeList = takaiKnowledgeMapper.selectKnowledgeList(TakaiKnowledge.builder().knowledgeId(knowledgeId).build());
  122. }
  123. //获取知识列表
  124. if (!knowledgeList.isEmpty()) {
  125. for (TakaiKnowledge bmKnowledge : knowledgeList) {
  126. TakaiDocument conditon = TakaiDocument.builder().knowledgeId(bmKnowledge.getKnowledgeId()).build();
  127. List<TakaiDocument> documentList = takaiDocumentMapper.selectDocumentList(conditon);
  128. if (!documentList.isEmpty()) {
  129. for (TakaiDocument bmDocument : documentList) {
  130. //获取知识图片列表
  131. TakaiMediaReplacement conditonR = TakaiMediaReplacement.builder().documentId(bmDocument.getDocumentId()).build();
  132. List<TakaiMediaReplacement> imageList = takaiMediaReplacementMapper.selectMediaList(conditonR);
  133. if (!imageList.isEmpty()) {
  134. for (TakaiMediaReplacement image : imageList) {
  135. redisCache.setCacheObject(image.getOriginText(), image.getMediaUrl());
  136. }
  137. }
  138. }
  139. }
  140. }
  141. }
  142. }
  143. @Override
  144. public SseEmitter sseInvoke(TakaiSseInfoParams sseParams) {
  145. TakaiApplication appInfo = takaiApplicationMapper.selectTargetApplication(TakaiApplication.builder().appId(sseParams.getAppId()).build());
  146. if (appInfo != null) {
  147. TakaiKnowledge knowledge = takaiKnowledgeMapper.selectTargetKnowledge(TakaiKnowledge.builder().knowledgeId(appInfo.getKnowledgeIds()).build());
  148. if (knowledge != null) {
  149. SseEmitter sseEmitter = new SseEmitter(0L);
  150. String url = deepseekConfig.getBaseurl() + deepseekConfig.getChat();
  151. TakaiAppInfo info = takaiAppInfoMapper.selectAppInfoByAppId(sseParams.getAppId());
  152. JSONObject json = JSONObject.parseObject(info.getAppInfo());
  153. String query = sseParams.getPrompt().get(sseParams.getPrompt().size() - 1).getContent();
  154. log.info("deepseek聊天请求参数:" + query);
  155. json.put("query", query);
  156. json.put("embeddingId", knowledge.getEmbeddingId());
  157. RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), json.toJSONString());
  158. Request request = buildPostRequest(url, requestBody);
  159. // 使用EventSourceListener处理来自服务器的SSE事件
  160. EventSourceListener listener = new EventSourceListener() {
  161. private String preData = "";
  162. //图片识别
  163. private String symbolData = "";
  164. @Override
  165. public void onOpen(@NotNull EventSource eventSource, @NotNull Response response) {
  166. log.info("deepseek Connection opened. Headers: {}", response.headers());
  167. log.info("deepseek Request URL: {}", response.request().url());
  168. }
  169. @Override
  170. public void onClosed(@NotNull EventSource eventSource) {
  171. log.info("deepseek Connection closed.");
  172. sseEmitter.complete();
  173. }
  174. @Override
  175. public void onEvent(@NotNull EventSource eventSource, String id, String type, @NotNull String data) {
  176. if (!StringUtils.isEmpty(data)) {
  177. String newData = data.substring(preData.length());
  178. logger.info("deepseek聊天返回消息:" + data);
  179. preData = data;
  180. if (newData.indexOf(START_SIGN) > -1 || symbolData.length() > 0) {
  181. symbolData = symbolData + newData;
  182. //接收到了完整的图片标识
  183. int endSignPos = symbolData.indexOf(END_SIGN);
  184. if (endSignPos > -1) {
  185. JSONObject json = new JSONObject();
  186. json.put("id", id);
  187. json.put("event", "add");
  188. //是图片
  189. if (symbolData.indexOf(SYMBOL) > -1) {
  190. //获取完整Key
  191. int startPos = symbolData.indexOf(START_SIGN);
  192. int endPos = symbolData.indexOf(END_SIGN) + 1;
  193. String key = symbolData.substring(startPos, endPos);
  194. String url = redisCache.getCacheObject(key);
  195. if (org.springframework.util.StringUtils.hasText(url)) {
  196. if(url.contains("https://10.1.28.14:9000")){
  197. url = url.replace("https://10.1.28.14:9000", "https://minio.jkec.info:9000");
  198. }
  199. //匹配markdown图片格式
  200. // symbolData = symbolData.replace(key, "![](" + url + ")");
  201. } else {
  202. logger.error("图片标识符"+key+"没有获取到对应的URL{}: " + symbolData);
  203. }
  204. //检查是否当前token包含其他图片的开始符号”【“
  205. int lastPos = symbolData.lastIndexOf(START_SIGN);
  206. if(lastPos > endSignPos){
  207. // 从'【' 开始截取
  208. newData = symbolData.substring(0, lastPos);
  209. symbolData = symbolData.substring(lastPos);
  210. logger.info("截取结果{}: " + symbolData);
  211. } else {
  212. newData = symbolData;
  213. symbolData = "";
  214. }
  215. newData = newData.replace(key, " ![](" + url + ")");
  216. } else {
  217. newData = symbolData;
  218. symbolData = "";
  219. }
  220. json.put("data", newData);
  221. log.info("获取到图片替换结束符号,返回前端信息:" + json);
  222. send(sseEmitter, json);
  223. //如果超过长度200还没收到】符号,直接返回。
  224. } else if (symbolData.length() > 200) {
  225. JSONObject json = new JSONObject();
  226. json.put("id", id);
  227. json.put("event", "add");
  228. json.put("data", symbolData);
  229. }
  230. } else {
  231. JSONObject json = new JSONObject();
  232. json.put("id", id);
  233. json.put("event", type);
  234. json.put("data", newData);
  235. log.info("deepseek返回信息:" + json);
  236. send(sseEmitter, json);
  237. }
  238. }
  239. if (com.takai.common.utils.StringUtils.isNotEmpty(type) && "finish".equals(type)) {
  240. log.info("deepseek聊天结束");
  241. JSONObject json = new JSONObject();
  242. json.put("id", id);
  243. json.put("event", type);
  244. json.put("data", data);
  245. log.info("deepseek返回信息:" + json);
  246. send(sseEmitter, json);
  247. }
  248. }
  249. @Override
  250. public void onFailure(@NotNull EventSource eventSource, Throwable t, Response response) {
  251. if (response != null) {
  252. log.error("deepseek Connection failed. Response code: {}, message: {}, body: {}",
  253. response.code(), response.message(), response.body() != null ? response.body().toString() : "null");
  254. } else {
  255. log.error("deepseek Connection failed with no response", t);
  256. }
  257. sseEmitter.completeWithError(t);
  258. }
  259. private void send(SseEmitter sseEmitter, Object obj) {
  260. try {
  261. sseEmitter.send(obj);
  262. } catch (IOException e) {
  263. log.error("deepseek 推送数据失败", e);
  264. }
  265. }
  266. };
  267. OkHttpClient client = buildOkHttpClient();
  268. EventSource.Factory factory = EventSources.createFactory(client);
  269. final EventSource eventSources = factory.newEventSource(request, listener);
  270. // 客户端主动关闭连接
  271. sseEmitter.onCompletion(() -> {
  272. logger.info("deepseek客户端主动关闭连接 -- SSE 连接关闭");
  273. });
  274. // 超时回调
  275. sseEmitter.onTimeout(() -> {
  276. logger.info("deepseek客户端连接超时 -- SSE 连接关闭");
  277. if(eventSources != null) {
  278. logger.info("deepseek超时回调 -- 成功关闭SSE连接 ");
  279. eventSources.cancel();
  280. }
  281. });
  282. // 错误回调
  283. sseEmitter.onError(e -> {
  284. logger.info("deepseek客户端回调失败 -- SSE 连接关闭");
  285. if(eventSources != null) {
  286. logger.info("deepseek错误回调 -- 成功关闭SSE连接 ");
  287. eventSources.cancel();
  288. }
  289. });
  290. return sseEmitter;
  291. }
  292. }
  293. return null;
  294. }
  295. @Override
  296. public List<String> asyncCompletions(TakaiCompletionsParams params) {
  297. List<String> list = new ArrayList<>();
  298. TakaiApplication vo = takaiApplicationMapper.selectTargetApplication(TakaiApplication.builder().appId(params.getAppId()).build());
  299. if (vo != null) {
  300. TakaiPromptInfo info = new TakaiPromptInfo();
  301. info.setContent(deepseekConfig.getPrompt());
  302. info.setRole("user");
  303. params.getMessages().add(info);
  304. JSONObject jsonObject = new JSONObject();
  305. jsonObject.put("model", vo.getModel());
  306. jsonObject.put("messages", params.getMessages());
  307. jsonObject.put("chat_id", params.getChat_id());
  308. JSONObject result = getasyncCompletions(jsonObject);
  309. if (result != null && result.getInteger("code") == 200) {
  310. JSONArray array = result.getJSONArray("data");
  311. list.addAll(array.toJavaList(String.class));
  312. }
  313. }
  314. return list;
  315. }
  316. private JSONObject getasyncCompletions(JSONObject jsonObject) {
  317. String url = deepseekConfig.getBaseurl() + deepseekConfig.getAsyncCompletions();
  318. RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), jsonObject.toJSONString());
  319. Request request = buildPostRequest(url, requestBody);
  320. OkHttpClient client = buildOkHttpClient();
  321. try {
  322. Response response = client.newCall(request).execute();
  323. if (response.isSuccessful()) {
  324. String body = response.body().string();
  325. if (isJsonObject(body)) {
  326. return JSON.parseObject(body);
  327. }
  328. }
  329. } catch (IOException e) {
  330. log.info("deepseek Request URL: {}", e.getMessage());
  331. }
  332. return null;
  333. }
  334. @Override
  335. public List<TakaiDialogRespDTO> getDialogDetail(String dialogId) {
  336. List<TakaiDialogRespDTO> detail = takaiDialogMapper.selectDialogDetail(dialogId);
  337. if(detail != null && detail.size() != 0){
  338. for(TakaiDialogRespDTO dto : detail){
  339. if(StringUtils.isNotEmpty(dto.getSliceJson())){
  340. dto.setSliceInfo(JSON.parseObject(dto.getSliceJson(), TakaiSliceInfoDTO.class));
  341. }
  342. }
  343. }
  344. return detail;
  345. }
  346. @Override
  347. public void saveDialog(TakaiDialogReqDTO dialogReqDTO) {
  348. String dialogId = null;
  349. TakaiDialogRespDTO dialogVo = null;
  350. if (com.takai.common.utils.StringUtils.isNotEmpty(dialogReqDTO.getId())) {
  351. dialogVo = takaiDialogMapper.selectDialogById(dialogReqDTO.getId());
  352. }
  353. if (dialogVo == null) {
  354. takaiDialogMapper.insertDialog(dialogReqDTO);
  355. dialogId = dialogReqDTO.getId();
  356. } else {
  357. dialogId = dialogReqDTO.getId();
  358. }
  359. for (TakaiDialogDetailReqDTO dto : dialogReqDTO.getMessages()) {
  360. dto.setDialogId(dialogId);
  361. TakaiDialogRespDTO detail = takaiDialogMapper.selectDialogDetailById(dto.getId());
  362. if (detail == null) {
  363. if (dto.getSliceInfo() != null) dto.setSliceJson(JSON.toJSONString(dto.getSliceInfo()));
  364. takaiDialogMapper.insertDialogDetail(dto);
  365. }
  366. }
  367. }
  368. @Override
  369. public List<Object> getDialogList(String appId, String userId) {
  370. List<TakaiDialogRespDTO> dialogRespDTOS = takaiDialogMapper.selectDialogList(appId, userId);
  371. //当前日期
  372. LocalDate today = LocalDate.now();
  373. //根据时间分组降序排序
  374. NavigableMap<LocalDateTime, List<TakaiDialogRespDTO>> groupList = dialogRespDTOS.stream().collect(Collectors.groupingBy(TakaiDialogRespDTO::getCreate_time, TreeMap::new, Collectors.toList())).descendingMap();
  375. List<Object> obj = new ArrayList();
  376. if (!groupList.isEmpty()) {
  377. for (Map.Entry<LocalDateTime, List<TakaiDialogRespDTO>> entry : groupList.entrySet()) {
  378. // 对比两个时间相差多少天
  379. long daysBetween = ChronoUnit.DAYS.between(today, entry.getKey());
  380. Map<String, Object> m = new HashMap();
  381. m.put("key", System.nanoTime());
  382. m.put("type", "group");
  383. if (daysBetween == 0l) {
  384. m.put("label", TODAY);
  385. m.put("children", setValue(entry.getValue(), appId));
  386. obj.add(m);
  387. } else {
  388. m.put("label", -daysBetween + BEFOR);
  389. m.put("children", setValue(entry.getValue(), appId));
  390. obj.add(m);
  391. }
  392. }
  393. }
  394. return obj;
  395. }
  396. @Override
  397. public void DelDialogDetail(String id) {
  398. int result = takaiDialogMapper.delDialog(id);
  399. if (result > 0) {
  400. takaiDialogMapper.delDialogDetail(id);
  401. }
  402. }
  403. @Override
  404. public void updateDialog(TakaiDialogReqDTO dialogReqDTO) {
  405. takaiDialogMapper.updateDialog(dialogReqDTO);
  406. }
  407. @Override
  408. public List<TakaiDialogRespDTO> exportExcel(String dialogId) {
  409. return takaiDialogMapper.selectDialogExport(dialogId);
  410. }
  411. @Override
  412. public int createKnowledge(TakaiKnowledgeParams knowledge) {
  413. SnowflakeDigitGenerator snowflakeDigitGenerator = new SnowflakeDigitGenerator(1, 1);
  414. long knowledgeId = snowflakeDigitGenerator.nextId();
  415. String url = deepseekConfig.getBaseurl() + deepseekConfig.getCreateKnowledge();
  416. JSONObject jsonObject = new JSONObject();
  417. jsonObject.put("knowledge_id", "a" + knowledgeId);
  418. jsonObject.put("embedding_id", knowledge.getEmbeddingId());
  419. RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), jsonObject.toJSONString());
  420. Request request = buildPostRequest(url, requestBody);
  421. OkHttpClient client = buildOkHttpClient();
  422. try {
  423. Response response = client.newCall(request).execute();
  424. if (response.isSuccessful()) {
  425. String body = response.body().string();
  426. JSONObject obj = JSON.parseObject(body);
  427. Integer code = obj.getInteger("code");
  428. if (code == 200) {
  429. TakaiKnowledge params = TakaiKnowledge.builder()
  430. .knowledgeId("a" + knowledgeId)
  431. .name(knowledge.getName())
  432. .embeddingId(knowledge.getEmbeddingId())
  433. .description(knowledge.getDescription())
  434. .build();
  435. return takaiKnowledgeMapper.insertKnowledge(params);
  436. }
  437. } else {
  438. logger.error("创建知识库调用python接口失败,返回状态码:{}", response.code());
  439. }
  440. } catch (IOException e) {
  441. logger.error("创建知识库调用python接口失败", e.getMessage());
  442. }
  443. return 0;
  444. }
  445. @Override
  446. public int updateKnowledge(TakaiKnowledgeParams knowledge, String knowledgeId) {
  447. TakaiKnowledge params = TakaiKnowledge.builder().knowledgeId(knowledgeId)
  448. .name(knowledge.getName())
  449. .description(knowledge.getDescription())
  450. .embeddingId(knowledge.getEmbeddingId())
  451. .build();
  452. return takaiKnowledgeMapper.updateKnowledge(params);
  453. }
  454. @Override
  455. public TakaiKnowledge detailKnowledge(String knowledgeId) {
  456. TakaiKnowledge vo = TakaiKnowledge.builder().knowledgeId(knowledgeId).build();
  457. return takaiKnowledgeMapper.selectTargetKnowledge(vo);
  458. }
  459. @Override
  460. public int delKnowledge(String knowledgeId) {
  461. String url = deepseekConfig.getBaseurl() + deepseekConfig.getDeleteKnowledge() + "/" + knowledgeId;
  462. Request request = buildDeleteRequest(url);
  463. OkHttpClient client = buildOkHttpClient();
  464. Response response = null;
  465. try {
  466. response = client.newCall(request).execute();
  467. if (response.isSuccessful()) {
  468. String body = response.body().string();
  469. JSONObject obj = JSON.parseObject(body);
  470. Integer code = obj.getInteger("code");
  471. if (code == 200) {
  472. // TakaiKnowledge info = takaiKnowledgeMapper.selectTargetKnowledge(TakaiKnowledge.builder().knowledgeId(knowledgeId).build());
  473. List<TakaiMediaReplacement> list = takaiMediaReplacementMapper.selectMediaList(TakaiMediaReplacement.builder().knowledgeId(knowledgeId).build());
  474. List<TakaiDocument> documentList = takaiDocumentMapper.selectDocumentList(TakaiDocument.builder().knowledgeId(knowledgeId).build());
  475. int knowledgeInt = takaiKnowledgeMapper.delKnowledge(knowledgeId);
  476. if (knowledgeInt > 0) {
  477. takaiDocumentMapper.delDocumentByKnowledgeId(knowledgeId);
  478. takaiDocumentSettingsMapper.deleteDocumentSettingsByKnowledgeId(knowledgeId);
  479. if(list != null && list.size() > 0){
  480. try {
  481. for(TakaiDocument document: documentList){
  482. logger.info("删除知识库->删除minio文件");
  483. minioUtil.remove("deepseek-doc", "/"+document.getName());
  484. }
  485. for (int k = 0; k < list.size(); k++ ) {
  486. logger.info("删除知识库->删除minio图片{}", k);
  487. String key = "/pdf/"+knowledgeId+"/"+list.get(k).getDocumentId()+"/【示意图序号_"+list.get(k).getDocumentId()+"_"+k+1+"】.jpg";
  488. logger.info("删除知识库->删除minio图片key{}", key);
  489. minioUtil.remove("deepseek-doc" , key);
  490. }
  491. } catch (Exception e) {
  492. logger.error("删除知识库->删除minion文件失败", e.getMessage());
  493. throw new RuntimeException(e);
  494. }
  495. }
  496. }
  497. return knowledgeInt;
  498. }
  499. }
  500. } catch (IOException e) {
  501. logger.error("删除知识库调用python接口失败", e.getMessage());
  502. }
  503. return 0;
  504. }
  505. @Override
  506. public int uploadDocument(MultipartFile[] files, String knowledgeId) {
  507. List<TakaiSysOss> result = null;
  508. try {
  509. result = minioUtil.uploadMultiple(files);
  510. } catch (Exception e) {
  511. logger.error("上传文件失败", e.getMessage());
  512. }
  513. if (result != null && result.size() > 0) {
  514. List<UploadDocumentParams> params = new ArrayList<>();
  515. for (int i = 0; i<result.size(); i++) {
  516. SnowflakeDigitGenerator documentIdGenerator = new SnowflakeDigitGenerator(i, i);
  517. long documentId = documentIdGenerator.nextId();
  518. UploadDocumentParams param = new UploadDocumentParams();
  519. param.setDocument_id("a" + documentId);
  520. param.setName(result.get(i).getOriginalName());
  521. param.setUrl(result.get(i).getUrl());
  522. params.add(param);
  523. }
  524. TakaiDocumentSettings settings = new TakaiDocumentSettings();
  525. settings.setKnowledgeId(knowledgeId);
  526. JSONObject jsonObject = analysisFile(params, settings, "upload");
  527. if (jsonObject != null && jsonObject.containsKey("code") && jsonObject.getInteger("code") == 200) {
  528. for (UploadDocumentParams vo : params) {
  529. TakaiKnowledge info = takaiKnowledgeMapper.selectTargetKnowledge(TakaiKnowledge.builder().knowledgeId(knowledgeId).build());
  530. if(info != null){
  531. // 更新知识库文件大小,总字符数, 文件总数
  532. JSONObject docInfo = jsonObject.getJSONObject("doc_info");
  533. if(docInfo != null){
  534. List<TakaiDocument> documentList = takaiDocumentMapper.selectDocumentList(TakaiDocument.builder().knowledgeId(knowledgeId).build());
  535. Integer fileLen = docInfo.getInteger("file_size");
  536. Integer wordNum = docInfo.getInteger("total_char_len");
  537. Integer sliceTotal = docInfo.getInteger("slice_num");
  538. TakaiKnowledge paramInfo = TakaiKnowledge.builder().knowledgeId(knowledgeId)
  539. .length(info.getLength() == null ? fileLen : info.getLength() + fileLen ) // 文件大小
  540. .wordNum(info.getWordNum() == null ? wordNum : info.getWordNum() + wordNum) // 总字符数
  541. .documentSize(documentList == null || documentList.size() == 0 ? 1 : documentList.size() + 1) // 文件总数
  542. .build();
  543. takaiKnowledgeMapper.updateKnowledge(paramInfo);
  544. for (TakaiSysOss oss : result) {
  545. // oss保存到数据库
  546. takaiSysOssMapper.insertSysOss(oss);
  547. }
  548. // 保存知识信息
  549. TakaiDocument document = TakaiDocument.builder()
  550. .documentId(vo.getDocument_id())
  551. .knowledgeId(knowledgeId)
  552. .customSeparator(String.format("[\"%s\"", "\\n") + "]")
  553. .sentenceSize("300")
  554. .name(vo.getName())
  555. .url(vo.getUrl())
  556. .sliceTotal(sliceTotal)
  557. .length(fileLen)
  558. .wordNum(wordNum)
  559. .build();
  560. int documentIdInsert = takaiDocumentMapper.insertDocument(document);
  561. if (documentIdInsert > 0) {
  562. // 保存知识设置信息
  563. SnowflakeDigitGenerator snowflakeDigitGenerator = new SnowflakeDigitGenerator(1, 1);
  564. long id = snowflakeDigitGenerator.nextId();
  565. TakaiDocumentSettings dSettings = new TakaiDocumentSettings();
  566. dSettings.setId(String.valueOf(id));
  567. dSettings.setKnowledgeId(knowledgeId);
  568. dSettings.setDocumentId(vo.getDocument_id());
  569. dSettings.setSetSlice("0"); // 默认 按标题段落切片
  570. dSettings.setSetAnalyze("1"); // 默认 图片转换成标识符
  571. dSettings.setSetTable("0"); // 默认 ttable转图片
  572. takaiDocumentSettingsMapper.insertDocumentSettings(dSettings);
  573. }
  574. }
  575. }
  576. }
  577. setRedisCache(knowledgeId);
  578. return 1;
  579. }
  580. }
  581. return 0;
  582. }
  583. @Override
  584. public int updateDocument(TakaiDocumentParams documentParams, String documentId) {
  585. int i = takaiDocumentMapper.updateDocument(TakaiDocument.builder()
  586. .documentId(documentId)
  587. .name(documentParams.getName())
  588. .build());
  589. return i;
  590. }
  591. @Override
  592. public List<TakaiDocument> documentList(TakaiDocumentParams documentParams) {
  593. return takaiDocumentMapper.selectDocumentList(TakaiDocument.builder().knowledgeId(documentParams.getKnowledge_id()).build());
  594. }
  595. @Override
  596. public TakaiDocument documentDetail(String documentId) {
  597. return takaiDocumentMapper.selectTargetDocument(TakaiDocument.builder().documentId(documentId).build());
  598. }
  599. @Override
  600. public int delDocument(String documentId) {
  601. TakaiDocument vo = takaiDocumentMapper.selectTargetDocument(TakaiDocument.builder().documentId(documentId).build());
  602. if(vo != null){
  603. String url = deepseekConfig.getBaseurl() + deepseekConfig.getDeleteDoc() + "/" + documentId + "/" + vo.getKnowledgeId();
  604. Request request = buildDeleteRequest(url);
  605. OkHttpClient client = buildOkHttpClient();
  606. try {
  607. Response response = client.newCall(request).execute();
  608. if (response.isSuccessful()) {
  609. String body = response.body().string();
  610. logger.info("删除知识文件调用python接口返回结果:{}", body);
  611. JSONObject obj = JSON.parseObject(body);
  612. Integer code = obj.getInteger("code");
  613. if (code == 200) {
  614. List<TakaiMediaReplacement> list = takaiMediaReplacementMapper.selectMediaList(TakaiMediaReplacement.builder().documentId(documentId).build());
  615. // 删除图片
  616. takaiMediaReplacementMapper.deleteMedia(documentId);
  617. // 删除document文件
  618. int i = takaiDocumentMapper.delDocument(documentId);
  619. if(i > 0){
  620. TakaiKnowledge info = takaiKnowledgeMapper.selectTargetKnowledge(TakaiKnowledge.builder().knowledgeId(vo.getKnowledgeId()).build());
  621. if(info != null){
  622. // 更新知识库文件大小,总字符数, 文件总数
  623. TakaiKnowledge paramInfo = TakaiKnowledge.builder().knowledgeId(vo.getKnowledgeId())
  624. .length(vo.getLength() == null ? info.getLength() == null ? 0 : info.getLength() : info.getLength() - vo.getLength()) // 文件大小
  625. .wordNum(vo.getWordNum() == null ? info.getWordNum() == null ? 0 : info.getWordNum() : info.getWordNum() - vo.getWordNum()) // 总字符数
  626. .documentSize(info.getDocumentSize() == null ? 0 : info.getDocumentSize() - 1) // 文件总数
  627. .build();
  628. takaiKnowledgeMapper.updateKnowledge(paramInfo);
  629. }
  630. // 删除minio文件
  631. try {
  632. logger.info("删除minio文件");
  633. minioUtil.remove("deepseek-doc", "/"+vo.getName());
  634. if(list != null && list.size() > 0){
  635. for (int k=1; k<=list.size(); k++ ) {
  636. logger.info("删除minio图片{}", k);
  637. minioUtil.remove("deepseek-doc" , "/pdf/"+vo.getKnowledgeId()+"/"+documentId+"/【示意图序号_"+documentId+"_"+k+"】.jpg");
  638. }
  639. }
  640. } catch (Exception e) {
  641. logger.error("删除minion文件失败", e.getMessage());
  642. throw new RuntimeException(e);
  643. }
  644. return i;
  645. }
  646. }
  647. }
  648. } catch (IOException e) {
  649. logger.error("删除知识文件调用python接口失败", e.getMessage());
  650. }
  651. }
  652. return 0;
  653. }
  654. @Override
  655. public void uploadUrl(TakaiDocumentObject object) {
  656. }
  657. @Override
  658. public int createApplication(TakaiApplicationParams params, boolean isAdmin) {
  659. ApprovalNode vo = getFirstApproverNode(); // 获取第一个审批对象
  660. if(vo != null){
  661. SnowflakeDigitGenerator snowflakeDigitGenerator = new SnowflakeDigitGenerator(1, 1);
  662. long appId = snowflakeDigitGenerator.nextId();
  663. TakaiApplication info = TakaiApplication.builder().appId(String.valueOf(appId))
  664. .name(params.getName())
  665. .desc(params.getDesc())
  666. .model(params.getModel())
  667. .knowledgeIds(params.getKnowledge_ids().toString())
  668. .topP(params.getTop_p())
  669. .temperature(params.getTemperature())
  670. .maxToken(params.getMax_token())
  671. .prompt(params.getPrompt())
  672. .knowledgeInfo(params.getKnowledge_info())
  673. .sliceCount(params.getSlice_count())
  674. .typeId(params.getTypeId())
  675. .build();
  676. if(isAdmin){
  677. info.setStatus("3"); // 有直接创建权限无需审核
  678. }else{
  679. info.setStatus("5"); // 未开始审核状态
  680. info.setApprover(String.valueOf(vo.getApprover()));
  681. info.setNodeOrder(String.valueOf(vo.getNodeOrder()));
  682. }
  683. info.setCreateBy(params.getUserId());
  684. int i = takaiApplicationMapper.insertApplication(info);
  685. if (i > 0) {
  686. TypeApp appType = new TypeApp();
  687. appType.setTypeId(params.getTypeId() == null ? null : params.getTypeId());
  688. appType.setAppId(String.valueOf(appId));
  689. appTypeMapper.insertAppType(appType);
  690. logger.info("create application success, id:{}, name:{}", appId, params.getName());
  691. TakaiAppInfo appInfo = new TakaiAppInfo();
  692. appInfo.setAppId(String.valueOf(appId));
  693. appInfo.setAppInfo(String.valueOf(JSONObject.from(info).toJSONString()));
  694. takaiAppInfoMapper.insertAppInfo(appInfo);
  695. List<String> list = params.getQuestionList();
  696. if (!list.isEmpty() && list.size() > 0) {
  697. for (String str : list) {
  698. if (org.apache.commons.lang3.StringUtils.isNotBlank(str)) {
  699. String uuid = IdUtils.simpleUUID();
  700. TakaiQuestion question = TakaiQuestion.builder().id(uuid).question(str).appId(String.valueOf(appId)).build();
  701. takaiQuestionMapper.insertQuestion(question);
  702. }
  703. }
  704. }
  705. return i;
  706. }
  707. }else{
  708. // 没有审批人
  709. return 9;
  710. }
  711. return 0;
  712. }
  713. @Override
  714. public int updateApplication(TakaiApplicationParams params, String appId, boolean isAdmin) {
  715. ApprovalNode vo = getFirstApproverNode(); // 获取第一个审批对象
  716. if(vo != null){
  717. TakaiApplication info = TakaiApplication.builder().appId(appId)
  718. .name(params.getName())
  719. .desc(params.getDesc())
  720. .model(params.getModel())
  721. .knowledgeIds(params.getKnowledge_ids().toString())
  722. .topP(params.getTop_p())
  723. .temperature(params.getTemperature())
  724. .maxToken(params.getMax_token())
  725. .prompt(params.getPrompt())
  726. .knowledgeInfo(params.getKnowledge_info())
  727. .sliceCount(params.getSlice_count())
  728. .typeId(params.getTypeId())
  729. .build();
  730. if(isAdmin){
  731. info.setStatus("3"); // 有直接修改权限无需审核
  732. info.setApprover(null);
  733. info.setNodeOrder(null);
  734. }else{
  735. info.setStatus("5"); // 未开始审核状态
  736. info.setApprover(String.valueOf(vo.getApprover()));
  737. info.setNodeOrder(String.valueOf(vo.getNodeOrder()));
  738. }
  739. info.setUpdateBy(params.getUserId());
  740. int i = takaiApplicationMapper.updateApplication(info);
  741. if (1 > 0) {
  742. TakaiAppInfo appInfo = new TakaiAppInfo();
  743. appInfo.setAppId(appId);
  744. appInfo.setAppInfo(String.valueOf(JSONObject.from(info).toJSONString()));
  745. takaiAppInfoMapper.updateAppInfoByAppId(appInfo);
  746. logger.info("update application success, id:{}, name:{}", appId, params.getName());
  747. //预设问题写入数据库
  748. takaiQuestionMapper.delQuestionByAppId(appId);
  749. List<String> list = params.getQuestionList();
  750. if (!list.isEmpty() && list.size() > 0) {
  751. for (String str : list) {
  752. if (org.apache.commons.lang3.StringUtils.isNotBlank(str)) {
  753. String uuid = IdUtils.simpleUUID();
  754. TakaiQuestion question = TakaiQuestion.builder().id(uuid).question(str).appId(String.valueOf(appId)).build();
  755. takaiQuestionMapper.insertQuestion(question);
  756. }
  757. }
  758. }
  759. }
  760. return i;
  761. } else {
  762. return 9;
  763. }
  764. }
  765. @Override
  766. public List<TakaiApplicationResult> getApplicationList(TakaiApplication params) {
  767. return takaiApplicationMapper.selectApplicationList(params);
  768. }
  769. @Override
  770. public JSONObject selectApplication(String appId) {
  771. JSONObject object = new JSONObject();
  772. TakaiApplication application = TakaiApplication.builder().appId(appId).build();
  773. TakaiApplication takaiApplication = takaiApplicationMapper.selectTargetApplication(application);
  774. List<TakaiQuestionDTO> list = takaiQuestionMapper.getQuestionList(appId);
  775. object.put("detail", takaiApplication);
  776. object.put("questionlist", list);
  777. return object;
  778. }
  779. @Override
  780. public int delApplication(String appId) {
  781. int i = takaiApplicationMapper.delApplication(appId);
  782. if (i > 0) {
  783. takaiAppInfoMapper.delAppInfoByAppId(appId);
  784. takaiQuestionMapper.delQuestionByAppId(appId);
  785. }
  786. return i;
  787. }
  788. @Override
  789. public List<TakaiQuestionDTO> selectQuestionByAppId(String appId) {
  790. List<TakaiQuestionDTO> List = takaiQuestionMapper.getQuestionList(appId);
  791. return List;
  792. }
  793. @Override
  794. public List<TakaiKnowledge> queryKnowledgeList() {
  795. return takaiKnowledgeMapper.selectKnowledgeList(null);
  796. }
  797. @Override
  798. public List<Object> selectDialogListByAppId(String appId, String userId) {
  799. List<TakaiDialogRespDTO> list = takaiDialogMapper.selectDialog(appId, userId);
  800. List<Object> result = setDialogList(list);
  801. return result;
  802. }
  803. @Override
  804. public TakaiDocumentSettings documentSetting(String documentId) {
  805. return takaiDocumentSettingsMapper.selectById(documentId);
  806. }
  807. @Override
  808. public int updateDocumentSetting(TakaiDocumentSettings documentSettings, String documentId) {
  809. TakaiDocumentSettings settings = new TakaiDocumentSettings();
  810. TakaiDocumentSettings settingsVo = takaiDocumentSettingsMapper.selectById(documentId);
  811. settings.setKnowledgeId(settingsVo.getKnowledgeId());
  812. settings.setSetSlice(documentSettings.getSetSlice());
  813. settings.setSliceValue(documentSettings.getSliceValue());
  814. settings.setSetAnalyze(documentSettings.getSetAnalyze());
  815. settings.setSetTable(documentSettings.getSetTable());
  816. TakaiDocument document = takaiDocumentMapper.selectTargetDocument(TakaiDocument.builder().documentId(documentId).build());
  817. List<UploadDocumentParams> listParams = new ArrayList<>();
  818. if (document != null) {
  819. UploadDocumentParams params = new UploadDocumentParams();
  820. params.setDocument_id(documentId);
  821. params.setName(document.getName());
  822. params.setUrl(document.getUrl());
  823. listParams.add(params);
  824. }
  825. JSONObject jsonObject = analysisFile(listParams, settings, "update");
  826. if (jsonObject != null && jsonObject.containsKey("code") && jsonObject.getInteger("code") == 200) {
  827. logger.info("update document setting success, id:{}", documentId);
  828. documentSettings.setDocumentId(documentId);
  829. return takaiDocumentSettingsMapper.updateDocumentSettings(documentSettings);
  830. }
  831. return 0;
  832. }
  833. @Override
  834. public JSONObject getSliceList(TakaiSliceParams params) {
  835. // String url = deepseekConfig.getBaseurl() + deepseekConfig.getSlicePage();
  836. // JSONObject jsonObject = new JSONObject();
  837. // jsonObject.put("document_id", params.getDocument_id());
  838. // jsonObject.put("knowledge_id", params.getKnowledge_id());
  839. // jsonObject.put("text", params.getText());
  840. // jsonObject.put("pageNum", params.getPageNum());
  841. // jsonObject.put("pageSize", params.getPageSize());
  842. //
  843. // RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), jsonObject.toJSONString());
  844. // Request request = buildPostRequest(url, requestBody);
  845. //
  846. // OkHttpClient client = buildOkHttpClient();
  847. // Response response = null;
  848. // try {
  849. // response = client.newCall(request).execute();
  850. // if (response.isSuccessful()) {
  851. // String body = response.body().string();
  852. // JSONObject obj = JSON.parseObject(body);
  853. // Integer code = obj.getInteger("code");
  854. // if (code == 200) {
  855. // return obj;
  856. // }
  857. // } else {
  858. // logger.info("获取切片列表调用python接口失败,返回状态码:{}", response.code());
  859. // }
  860. // } catch (IOException e) {
  861. // logger.error("获取切片列表调用python接口失败", e.getMessage());
  862. // }
  863. return null;
  864. }
  865. @Override
  866. public int deleteSlice(String sliceId, String knowledgeId, String documentId) {
  867. String url = deepseekConfig.getBaseurl() + deepseekConfig.getDeleteSlice() + "/" + sliceId + "/" + knowledgeId + "/" + documentId;
  868. Request request = buildDeleteRequest(url);
  869. OkHttpClient client = buildOkHttpClient();
  870. Response response = null;
  871. try {
  872. response = client.newCall(request).execute();
  873. if (response.isSuccessful()) {
  874. String body = response.body().string();
  875. JSONObject obj = JSON.parseObject(body);
  876. Integer code = obj.getInteger("code");
  877. logger.info("删除切片调用python接口成功,返回结果:{}", body);
  878. if (code == 200) {
  879. return 1;
  880. }
  881. }
  882. } catch (IOException e) {
  883. logger.error("删除切片调用python接口失败", e.getMessage());
  884. }
  885. return 0;
  886. }
  887. @Override
  888. public JSONObject getSliceDetail(String sliceId, String knowledgeId) {
  889. String url = deepseekConfig.getBaseurl() + deepseekConfig.getSliceDetail() + "/" + knowledgeId + "/" + sliceId;
  890. Request request = buildGetRequest(url);
  891. OkHttpClient client = buildOkHttpClient();
  892. try {
  893. Response response = client.newCall(request).execute();
  894. if (response.isSuccessful()) {
  895. String body = response.body().string();
  896. log.info("查询切片详情返回:" + body);
  897. return JSON.parseObject(body);
  898. } else {
  899. logger.info("获取切片详情调用python接口失败,返回状态码:{}", response.code());
  900. }
  901. } catch (IOException e) {
  902. log.error("查询切片详情调用python接口失败", e.getMessage());
  903. }
  904. return null;
  905. }
  906. @Override
  907. public int updateSliceInfo(TakaiSliceUpdateParams params) {
  908. String url = deepseekConfig.getBaseurl() + deepseekConfig.getUpdateSlice();
  909. JSONObject object = new JSONObject();
  910. object.put("knowledge_id", params.getKnowledgeId());
  911. object.put("slice_id", params.getSliceId());
  912. object.put("slice_text", params.getSliceText());
  913. object.put("document_id", params.getDocumentId());
  914. RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), object.toJSONString());
  915. Request request = buildPutRequest(url, requestBody);
  916. OkHttpClient client = buildOkHttpClient();
  917. try {
  918. Response response = client.newCall(request).execute();
  919. if (response.isSuccessful()) {
  920. String body = response.body().string();
  921. JSONObject obj = JSON.parseObject(body);
  922. Integer code = obj.getInteger("code");
  923. if (code == 200) {
  924. return 1;
  925. }
  926. }
  927. } catch (Exception e) {
  928. logger.error("更新切片信息调用python接口失败", e.getMessage());
  929. }
  930. return 0;
  931. }
  932. @Override
  933. public TakaiMediaReplacement getTakaiMediaReplacement() {
  934. TakaiMediaReplacement mrParams = TakaiMediaReplacement.builder()
  935. .documentId("a2912832435041734656")
  936. .originText("【示意图序号_a2912832435041734656_1】")
  937. .mediaType("image").build();
  938. TakaiMediaReplacement mrVo = takaiMediaReplacementMapper.selectTargetMedia(mrParams);
  939. return mrVo;
  940. }
  941. @Override
  942. public int addSlice(TakaiSliceUpdateParams params) {
  943. String url = deepseekConfig.getBaseurl() + deepseekConfig.getAddSlice();
  944. TakaiDocument info = takaiDocumentMapper.selectTargetDocument(TakaiDocument.builder().documentId(params.getDocumentId()).build());
  945. if(info != null){
  946. JSONObject json = new JSONObject();
  947. json.put("knowledge_id", params.getKnowledgeId());
  948. json.put("document_id", params.getDocumentId());
  949. json.put("slice_text", params.getSliceText());
  950. json.put("doc_name", info.getName());
  951. RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), json.toJSONString());
  952. Request request = buildPostRequest(url, requestBody);
  953. OkHttpClient client = buildOkHttpClient();
  954. try {
  955. Response response = client.newCall(request).execute();
  956. if (response.isSuccessful()) {
  957. String body = response.body().string();
  958. JSONObject obj = JSON.parseObject(body);
  959. Integer code = obj.getInteger("code");
  960. if (code == 200) {
  961. return 1;
  962. }
  963. }
  964. }catch (Exception e) {
  965. logger.error("新增切片调用python接口失败", e.getMessage());
  966. }
  967. }
  968. return 0;
  969. }
  970. @Override
  971. public List<TakaiSliceInfo> selectByDocumentId(String documentId) {
  972. return takaiSliceInfoMapper.selectByDocumentId(documentId);
  973. }
  974. @Override
  975. public TakaiSliceInfo selectBySliceId(String sliceId) {
  976. return takaiSliceInfoMapper.selectBySliceId(sliceId);
  977. }
  978. @Override
  979. public List<SliceInfo> slicePageInfoList(List<String> list) {
  980. return takaiSliceInfoMapper.slicePageInfoList(list);
  981. }
  982. @Override
  983. public JSONObject searchSlice(String id) {
  984. String url = deepseekConfig.getBaseurl() + deepseekConfig.getSearchSlice() + "/" + id;
  985. Request request = buildGetRequest(url);
  986. OkHttpClient client = buildOkHttpClient();
  987. try {
  988. Response response = client.newCall(request).execute();
  989. if (response.isSuccessful()) {
  990. String body = response.body().string();
  991. JSONObject obj = JSON.parseObject(body);
  992. Integer code = obj.getInteger("code");
  993. if (code == 200) {
  994. return obj;
  995. }
  996. }
  997. }catch (Exception e) {
  998. logger.error("切片得分调用python接口失败", e.getMessage());
  999. }
  1000. return null;
  1001. }
  1002. @Override
  1003. public List<Object> searchAppTypeGroupList(List<SysDictData> dictDataList, String userId) {
  1004. List<Object> result = new ArrayList();
  1005. if (dictDataList!= null && dictDataList.size() > 0) {
  1006. for (SysDictData dictData : dictDataList){
  1007. Map<String, Object> map = new HashMap();
  1008. TakaiApplication paramsVo = TakaiApplication.builder().approver(userId).flag("0").build();
  1009. if(dictData.getDictCode() == 41){
  1010. Map<String, Object> l = searchAppTypeGroupList(paramsVo, dictData);
  1011. if(!MapUtils.isEmpty(l)){
  1012. result.add(l);
  1013. }
  1014. }else{
  1015. paramsVo.setTypeId(Long.valueOf(dictData.getDictCode()));
  1016. List<TakaiApplicationResult> list = takaiApplicationMapper.selectApplicationList(paramsVo);
  1017. if(list != null && list.size() > 0){
  1018. List<Object> appInfoList = new ArrayList();
  1019. map.put("title", dictData.getDictLabel());
  1020. for (TakaiApplicationResult application : list){
  1021. Map<String, Object> infoMap = new HashMap();
  1022. infoMap.put("title", application.getName());
  1023. infoMap.put("appId", application.getAppId());
  1024. infoMap.put("showMenu", "false");
  1025. infoMap.put("chatMode", "LOCAL");
  1026. appInfoList.add(infoMap);
  1027. }
  1028. map.put("children", appInfoList);
  1029. result.add(map);
  1030. }
  1031. }
  1032. }
  1033. }
  1034. return result;
  1035. }
  1036. private Map<String, Object> searchAppTypeGroupList(TakaiApplication paramsVo, SysDictData dictData) {
  1037. paramsVo.setTypeId(Long.valueOf(42));
  1038. List<TakaiApplicationResult> list1 = takaiApplicationMapper.selectApplicationList(paramsVo);
  1039. paramsVo.setTypeId(Long.valueOf(43));
  1040. List<TakaiApplicationResult> list2 = takaiApplicationMapper.selectApplicationList(paramsVo);
  1041. List<TakaiApplicationResult> list3 = new ArrayList();
  1042. list3.addAll(list1);
  1043. list3.addAll(list2);
  1044. Map<String, Object> map = new HashMap();
  1045. if (list3!= null && list3.size() > 0) {
  1046. List<Object> l = new ArrayList<>();
  1047. map.put("title", dictData.getDictLabel());
  1048. // 分组
  1049. Map<String, List<TakaiApplicationResult>> map1 = list3.stream().collect(Collectors.groupingBy(TakaiApplicationResult::getTypeId));
  1050. for (Map.Entry<String, List<TakaiApplicationResult>> entry : map1.entrySet()) {
  1051. List<TakaiApplicationResult> mp = entry.getValue();
  1052. Map<String, Object> infoProjectMap = new HashMap();
  1053. List<Object> projectInfoList = new ArrayList();
  1054. for (TakaiApplicationResult application : mp){
  1055. SysDictData vo = sysDictDataMapper.selectDictDataById(Long.valueOf(application.getTypeId()));
  1056. infoProjectMap.put("title", vo.getDictLabel());
  1057. Map<String, Object> projectMap = new HashMap();
  1058. projectMap.put("appId", application.getAppId());
  1059. projectMap.put("showMenu", "false");
  1060. projectMap.put("chatMode", "LOCAL");
  1061. projectMap.put("title", application.getName());
  1062. projectInfoList.add(projectMap);
  1063. }
  1064. infoProjectMap.put("children", projectInfoList);
  1065. l.add(infoProjectMap);
  1066. }
  1067. map.put("children", l);
  1068. }
  1069. return map;
  1070. }
  1071. @Override
  1072. public List<TakaiApplication> applicationListByApprover(TakaiApplicationParams takaiApplicationParams) {
  1073. TakaiApplication vo = TakaiApplication.builder().approver(takaiApplicationParams.getApprover())
  1074. .build();
  1075. return takaiApplicationMapper.selectAppListByApprover(vo);
  1076. }
  1077. @Override
  1078. public int startAudit(String appId, String userId) {
  1079. List<DocumentAuditConfig> list = documentAuditConfigMapper.selectDocumentAuditConfigListByBo(null);
  1080. if(list != null && list.size() > 0) {
  1081. ApprovalFlowManager flowManager = new ApprovalFlowManager();
  1082. logger.info("开启审核");
  1083. for (DocumentAuditConfig config : list) {
  1084. // 添加审核节点
  1085. flowManager.addNode(new ApprovalNode(config.getId(), config.getNodeOrder(), Long.valueOf(config.getApprover()), config.getChain()));
  1086. }
  1087. ApprovalNode vo = flowManager.getFirstApprover();
  1088. int i = takaiApplicationMapper.updateApplication(TakaiApplication.builder()
  1089. .appId(appId)
  1090. .approver(String.valueOf(vo.getApprover()))
  1091. .nodeOrder(String.valueOf(vo.getNodeOrder()))
  1092. .status("1") // 待审核
  1093. .build());
  1094. if(i > 0){
  1095. DocumentAuditInfo info = new DocumentAuditInfo();
  1096. info.setAppId(appId);
  1097. info.setApprover(userId);
  1098. info.setStatus("5");
  1099. info.setNodeOrder(Integer.valueOf("0"));
  1100. info.setCreateBy(userId);
  1101. info.setCreateTime(new Date());
  1102. documentAuditInfoMapper.insertDocumentAuditInfo(info); // 审核记录
  1103. }
  1104. return i;
  1105. }else{
  1106. return 9;
  1107. }
  1108. }
  1109. @Override
  1110. public int updateAuditApplication(TakaiApplicationParams appParams, String appId) {
  1111. // 获取审核配置信息 (人员,节点)
  1112. List<DocumentAuditConfig> list = documentAuditConfigMapper.selectDocumentAuditConfigListByBo(null);
  1113. if(list != null && list.size() > 0){
  1114. if(("Y").equals(appParams.getStatus())){
  1115. ApprovalFlowManager flowManager = new ApprovalFlowManager();
  1116. logger.info("审核通过,开始审批流程");
  1117. for (DocumentAuditConfig config: list){
  1118. // 添加审核节点
  1119. flowManager.addNode(new ApprovalNode(config.getId(), config.getNodeOrder(), Long.valueOf(config.getApprover()), config.getChain()));
  1120. }
  1121. // 根据审核节点获取下一个审核节点
  1122. ApprovalNode nextNode = flowManager.getNextApproverByOrder(Integer.valueOf(appParams.getNodeOrder()));
  1123. if (nextNode == null) {
  1124. // 审核通过,更新文档状态
  1125. logger.info("审核通过,到最后节点");
  1126. return saveAuditInfo(appParams, "3", appId);
  1127. }else{
  1128. // 审核通过,下一个节点
  1129. int successI = takaiApplicationMapper.updateApplication(TakaiApplication.builder()
  1130. .appId(appId)
  1131. .status("2")
  1132. .approver(String.valueOf(nextNode.getApprover()))
  1133. .nodeOrder(String.valueOf(nextNode.getNodeOrder()))
  1134. .comment(appParams.getComment())
  1135. .build());
  1136. if(successI > 0){
  1137. DocumentAuditInfo info = new DocumentAuditInfo();
  1138. info.setAppId(appId);
  1139. info.setApprover(appParams.getApprover());
  1140. info.setComment(appParams.getComment());
  1141. info.setStatus("2");
  1142. info.setNodeOrder(Integer.valueOf(appParams.getNodeOrder()));
  1143. info.setCreateBy(appParams.getApprover());
  1144. info.setCreateTime(new Date());
  1145. documentAuditInfoMapper.insertDocumentAuditInfo(info); // 审核记录
  1146. }
  1147. return successI;
  1148. }
  1149. }else{
  1150. // 审核拒绝,更新文档状态
  1151. logger.info("审核拒绝,更新状态");
  1152. return saveAuditInfo(appParams, "5", appId);
  1153. }
  1154. }
  1155. return 0;
  1156. }
  1157. private int saveAuditInfo(TakaiApplicationParams appParams, String status, String appId){
  1158. int successI = takaiApplicationMapper.updateApplication(TakaiApplication.builder()
  1159. .appId(appId)
  1160. .status(status)
  1161. .approver(appParams.getApprover())
  1162. .nodeOrder(appParams.getNodeOrder())
  1163. .comment(appParams.getComment())
  1164. .build());
  1165. if(successI > 0){
  1166. DocumentAuditInfo info = new DocumentAuditInfo();
  1167. info.setAppId(appId);
  1168. info.setApprover(appParams.getApprover());
  1169. info.setComment(appParams.getComment());
  1170. if("5".equals(status)){
  1171. info.setStatus("4");
  1172. }else{
  1173. info.setStatus(status);
  1174. }
  1175. info.setNodeOrder(Integer.valueOf(appParams.getNodeOrder()));
  1176. info.setCreateBy(appParams.getApprover());
  1177. info.setCreateTime(new Date());
  1178. documentAuditInfoMapper.insertDocumentAuditInfo(info); // 审核记录
  1179. }
  1180. return successI;
  1181. }
  1182. @Override
  1183. public List<TakaiApplicationResult> selectAppByUserId(String userId) {
  1184. return takaiApplicationMapper.selectAppByUserId(userId);
  1185. }
  1186. @Override
  1187. public List<String> selectAppCollectList(String userId) {
  1188. return appCollectMapper.selectAppCollectList(userId);
  1189. }
  1190. @Override
  1191. public int insertAppCollect(AppCollect appCollect) {
  1192. AppCollect collect = appCollectMapper.selectAppCollectDetail(appCollect.getAppId(), appCollect.getUserId());
  1193. if (collect == null) {
  1194. return appCollectMapper.insertAppCollect(appCollect);
  1195. }
  1196. return 0;
  1197. }
  1198. @Override
  1199. public int deleteAppCollect(String userId, String appId) {
  1200. return appCollectMapper.delAppCollect(userId, appId);
  1201. }
  1202. @Override
  1203. public List<TakaiApplicationResult> selectRoleApp() {
  1204. return takaiApplicationMapper.selectRoleApp();
  1205. }
  1206. @Override
  1207. public List<TakaiApplicationResult> getChatAppList(List<TakaiApplicationResult> params, String userId) {
  1208. List<TakaiApplicationResult> list = new ArrayList();
  1209. for (TakaiApplicationResult app : params) {
  1210. AppCollect appCollect = appCollectMapper.selectAppCollectDetail(app.getAppId(), userId);
  1211. SysDictData dictData = null;
  1212. if(app.getTypeId() != null && !"".equals(app.getTypeId())){
  1213. dictData = sysDictDataMapper.selectDictDataById(Long.valueOf(app.getTypeId()));
  1214. }
  1215. TakaiApplicationResult appResult = new TakaiApplicationResult();
  1216. appResult.setAppId(app.getAppId());
  1217. appResult.setName(app.getName());
  1218. appResult.setDesc(app.getDesc());
  1219. appResult.setTypeId(app.getTypeId());
  1220. appResult.setCreateTime(app.getCreateTime());
  1221. appResult.setChatMode("LOCAL");
  1222. appResult.setIsCollect(appCollect != null ? true : false);
  1223. appResult.setTypeName(dictData != null ? dictData.getDictLabel() : "");
  1224. list.add(appResult);
  1225. }
  1226. return list;
  1227. }
  1228. private ApprovalNode getFirstApproverNode() {
  1229. List<DocumentAuditConfig> list = documentAuditConfigMapper.selectDocumentAuditConfigListByBo(null);
  1230. if(list != null && list.size() > 0) {
  1231. ApprovalFlowManager flowManager = new ApprovalFlowManager();
  1232. logger.info("开启审核");
  1233. for (DocumentAuditConfig config : list) {
  1234. // 添加审核节点
  1235. flowManager.addNode(new ApprovalNode(config.getId(), config.getNodeOrder(), Long.valueOf(config.getApprover()), config.getChain()));
  1236. }
  1237. return flowManager.getFirstApprover();
  1238. }
  1239. return null;
  1240. }
  1241. private JSONObject analysisFile(List<UploadDocumentParams> result, TakaiDocumentSettings settings, String flag) {
  1242. String url = deepseekConfig.getBaseurl() + deepseekConfig.getUploadKnowledge();
  1243. JSONObject json = new JSONObject();
  1244. json.put("knowledge_id", settings.getKnowledgeId());
  1245. json.put("docs", result);
  1246. if ("upload".equals(flag)) {
  1247. json.put("set_slice", "0");
  1248. json.put("slice_value", null);
  1249. json.put("set_analyze", "1");
  1250. json.put("set_table", "0");
  1251. json.put("flag", "upload");
  1252. } else {
  1253. json.put("set_slice", settings.getSetSlice());
  1254. json.put("slice_value", settings.getSliceValue());
  1255. json.put("set_analyze", settings.getSetAnalyze());
  1256. json.put("set_table", settings.getSetTable());
  1257. json.put("flag", "update");
  1258. }
  1259. RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), json.toJSONString());
  1260. Request request = buildPostRequest(url, requestBody);
  1261. OkHttpClient client = buildOkHttpClient();
  1262. Response response = null;
  1263. try {
  1264. response = client.newCall(request).execute();
  1265. if (response.isSuccessful()) {
  1266. String body = response.body().string();
  1267. JSONObject obj = JSON.parseObject(body);
  1268. Integer code = obj.getInteger("code");
  1269. if (code == 200) {
  1270. logger.info("上传文档调用python接口成功,返回内容:{}", body);
  1271. return obj;
  1272. }
  1273. return obj;
  1274. } else {
  1275. logger.error("上传文档调用python接口失败返回code:{}", response.code());
  1276. return null;
  1277. }
  1278. } catch (IOException e) {
  1279. logger.error("上传文档调用python接口失败", e.getMessage());
  1280. return null;
  1281. }
  1282. }
  1283. private List<Object> setDialogList(List<TakaiDialogRespDTO> list) {
  1284. //根据时间分组降序排序
  1285. NavigableMap<LocalDateTime, List<TakaiDialogRespDTO>> groupList = list.stream().collect(Collectors.groupingBy(TakaiDialogRespDTO::getCreate_time, TreeMap::new, Collectors.toList())).descendingMap();
  1286. List<Object> obj = new ArrayList();
  1287. if (!groupList.isEmpty()) {
  1288. for (Map.Entry<LocalDateTime, List<TakaiDialogRespDTO>> entry : groupList.entrySet()) {
  1289. List<TakaiDialogRespDTO> aList = entry.getValue();
  1290. List<TakaiDialogRespDTO> detailList = takaiDialogMapper.selectDialogExport(aList.get(0).getId());
  1291. Map<String, Object> map = new HashMap();
  1292. map.put("dialog_name", aList.get(0).getDialog_name());
  1293. map.put("length", detailList.size());
  1294. map.put("create_time", aList.get(0).getCreate_time());
  1295. map.put("did", aList.get(0).getDid());
  1296. map.put("id", aList.get(0).getId());
  1297. obj.add(map);
  1298. }
  1299. }
  1300. return obj;
  1301. }
  1302. private List<Map<String, Object>> setValue(List<TakaiDialogRespDTO> list, String appId) {
  1303. List<Map<String, Object>> l = new ArrayList();
  1304. for (TakaiDialogRespDTO vo : list) {
  1305. Map<String, Object> map = new HashMap();
  1306. map.put("key", vo.getId());
  1307. map.put("label", vo.getDialog_name());
  1308. map.put("appId", appId);
  1309. map.put("showMenu", "false");
  1310. map.put("chatMode", "LOCAL");
  1311. l.add(map);
  1312. }
  1313. return l;
  1314. }
  1315. private OkHttpClient buildOkHttpClient() {
  1316. return new OkHttpClient.Builder()
  1317. .connectTimeout(10, TimeUnit.SECONDS)
  1318. .writeTimeout(50, TimeUnit.SECONDS)
  1319. .readTimeout(10, TimeUnit.MINUTES)
  1320. .build();
  1321. }
  1322. private Request buildGetRequest(String url) {
  1323. return new Request.Builder()
  1324. .addHeader("User-Agent", "insomnia/10.3.1")
  1325. .url(url).get().build();
  1326. }
  1327. private Request buildPostRequest(String url, RequestBody requestBody) {
  1328. return new Request.Builder()
  1329. .addHeader("User-Agent", "insomnia/10.3.1")
  1330. .addHeader("Content-Type", "application/json")
  1331. .url(url).post(requestBody).build();
  1332. }
  1333. private Request buildPutRequest(String url, RequestBody requestBody) {
  1334. return new Request.Builder()
  1335. .addHeader("User-Agent", "insomnia/10.3.1")
  1336. .url(url).put(requestBody).build();
  1337. }
  1338. private Request buildDeleteRequest(String url) {
  1339. return new Request.Builder()
  1340. .addHeader("Content-Type", "multipart/form-data")
  1341. .addHeader("User-Agent", "insomnia/10.3.1")
  1342. .url(url).delete().build();
  1343. }
  1344. private Request buildUploadPostRequest(String url, RequestBody requestBody) {
  1345. return new Request.Builder()
  1346. .addHeader("User-Agent", "insomnia/10.3.1")
  1347. .addHeader("Content-Type", "application/json")
  1348. .url(url).post(requestBody).build();
  1349. }
  1350. private boolean isJsonObject(String data) {
  1351. try {
  1352. JSON.parseObject(data);
  1353. return true;
  1354. } catch (Exception e) {
  1355. return false;
  1356. }
  1357. }
  1358. }