GenerateInstructionService.java 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. package cn.cslg.pas.service.dify;
  2. import cn.cslg.pas.common.model.dify.*;
  3. import cn.cslg.pas.common.model.dify.confessionSession.AddConfessionSessionDTO;
  4. import cn.cslg.pas.common.utils.ClaimUtils.ClaimSplitUtils;
  5. import cn.cslg.pas.common.utils.DateUtils;
  6. import cn.cslg.pas.common.utils.FileUtils;
  7. import cn.cslg.pas.common.utils.StringUtils;
  8. import cn.cslg.pas.common.vo.PatentRightParams;
  9. import cn.cslg.pas.common.vo.RePatentClaim;
  10. import cn.cslg.pas.domain.business.ReportProject;
  11. import cn.cslg.pas.domain.business.ReportTemple;
  12. import cn.cslg.pas.domain.dify.AssoConfessionSessionFile;
  13. import cn.cslg.pas.domain.dify.ConfessionSession;
  14. import cn.cslg.pas.exception.ExceptionEnum;
  15. import cn.cslg.pas.exception.XiaoShiException;
  16. import cn.cslg.pas.service.business.ReportTempleService;
  17. import cn.cslg.pas.service.common.DifyService;
  18. import cn.cslg.pas.service.common.FileManagerService;
  19. import cn.hutool.core.util.IdUtil;
  20. import com.alibaba.fastjson.JSONArray;
  21. import com.alibaba.fastjson.JSONObject;
  22. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  23. import com.deepoove.poi.XWPFTemplate;
  24. import com.deepoove.poi.config.Configure;
  25. import com.google.gson.Gson;
  26. import okhttp3.MediaType;
  27. import okhttp3.OkHttpClient;
  28. import okhttp3.Request;
  29. import okhttp3.RequestBody;
  30. import org.springframework.beans.factory.annotation.Autowired;
  31. import org.springframework.beans.factory.annotation.Value;
  32. import org.springframework.stereotype.Service;
  33. import reactor.core.publisher.Flux;
  34. import reactor.core.publisher.FluxSink;
  35. import java.io.File;
  36. import java.io.IOException;
  37. import java.util.*;
  38. import java.util.concurrent.TimeUnit;
  39. import java.util.regex.Matcher;
  40. import java.util.regex.Pattern;
  41. import java.util.stream.Collectors;
  42. @Service
  43. public class GenerateInstructionService {
  44. @Autowired
  45. private ReportTempleService templeService;
  46. @Autowired
  47. private FileUtils fileUtils;
  48. @Autowired
  49. private AssoConfessionSessionFileService assoConfessionSessionFileService;
  50. @Autowired
  51. private DifyService difyService;
  52. @Autowired
  53. private FileManagerService fileManagerService;
  54. @Autowired
  55. private ConfessionSessionService confessionSessionService;
  56. private final static String ALL_START = "all_start";
  57. private final static String ALL_END = "all_end";
  58. private final static String START = "start";
  59. private final static String END = "end";
  60. private final static String MESSAGE = "message";
  61. private final static String FIELD_TITLE = "title";
  62. private final static String FIELD_TECHNICAL = "technical";
  63. private final static String FIELD_IMPLEMENTATION = "implementation";
  64. private final static String FIELD_BACKGROUND = "background";
  65. private final static String FIELD_CONTENT = "content";
  66. private final static String ERROR = "error";
  67. private Integer SESSION_ID;
  68. @Value("${DIFY.gInstructionKey}")
  69. private String gInstructionKey;
  70. public String getClaimContent(String claim) {
  71. // 正则表达式模式(注意 Java 中需要双反斜杠转义)
  72. String regex = "其特征在于[,。;!?、]+(.+)";
  73. Pattern pattern = Pattern.compile(regex);
  74. Matcher matcher = pattern.matcher(claim);
  75. if (matcher.find()) {
  76. // 提取第一个捕获组的内容(即括号内的部分)
  77. return matcher.group(1).trim();
  78. }
  79. return "其中," + claim; // 未找到匹配时返回空字符串
  80. }
  81. public String getMainClaimContent(String claim) {
  82. // 正则表达式模式(注意 Java 中需要双反斜杠转义)
  83. // String regex1 = "^[0-9]+\\.";
  84. // String regex2 = "^\\[[0-9]+]";
  85. // String regex3 = "^[0-9]+、";
  86. // String outPut1 = claim.replaceAll(regex1, "");
  87. // String outPut2 = outPut1.replaceAll(regex2, "");
  88. // String outPut3 =outPut2.replaceAll(regex3,"");
  89. String combinedRegex = "^(\\d+[.、]|\\[[0-9]+])";
  90. String output = claim.replaceAll(combinedRegex, "").replaceAll("[\\n\\r]+$", "");
  91. return output; // 未找到匹配时返回空字符串
  92. }
  93. public String getClaimText(String claim) {
  94. String combinedRegex = "^(\\d+[.、]|\\[[0-9]+])";
  95. String output = claim.replaceAll(combinedRegex, "").replaceAll("[\\n\\r]+$", "");
  96. return output; // 未找到匹配时返回空字符串
  97. }
  98. private XWPFTemplate getTemplate(Map<String, Object> map, String filePath) {
  99. //装载标的专利信息
  100. XWPFTemplate template = null;
  101. try {
  102. Configure configure = Configure.builder()
  103. .build();
  104. template = XWPFTemplate.compile(filePath, configure).render(map);
  105. } catch (Exception e) {
  106. e.printStackTrace();
  107. throw new XiaoShiException(ExceptionEnum.BUSINESS_ERROR, "未匹配到模版文件");
  108. }
  109. return template;
  110. }
  111. public Flux<String> generateInstruction2(GenerateClaimDTO generateClaimDTO) throws Exception {
  112. Integer templeId = 19;
  113. String claim = generateClaimDTO.getClaim();
  114. String background = generateClaimDTO.getBackground();
  115. Map<String, Object> addMap = new HashMap<>();
  116. Map<String, Object> queryMap = new HashMap<>();
  117. queryMap.put("claim", claim);
  118. queryMap.put("background", background);
  119. addMap.put("query", queryMap);
  120. String addStr = JSONObject.toJSONString(addMap);
  121. AddConfessionSessionDTO addConfessionSessionDTO = new AddConfessionSessionDTO();
  122. addConfessionSessionDTO.setType(3);
  123. addConfessionSessionDTO.setContent(addStr);
  124. ConfessionSession confessionSession = confessionSessionService.addSessionReDO(addConfessionSessionDTO);
  125. SESSION_ID = confessionSession.getId();
  126. ReportTemple reportTemplate = templeService.getById(templeId);
  127. String templateFilePath = fileUtils.getPath(reportTemplate.getTemplatePath());
  128. Map<String, Object> map = new HashMap<>();
  129. return Flux.create(emitter -> {
  130. new Thread(() -> {
  131. try {
  132. //;流程开始
  133. String startMess = getFluxMessage("", ALL_START, "");
  134. emitter.next(startMess);
  135. PatentRightParams params = new PatentRightParams();
  136. params.setCountry("CN");
  137. params.setContent(claim);
  138. params.setPatentNo("CN");
  139. List<RePatentClaim> rePatentClaims = ClaimSplitUtils.formatPatentRight(params);
  140. //生成标题和技术领域
  141. GenerateInstructAnswerVO generateInstructAnswerVO = this.genrateTechcialAndTitle(emitter, claim, background);
  142. String conversionId = generateInstructAnswerVO.getConversionId();
  143. String title = generateInstructAnswerVO.getTitle();
  144. String technical = generateInstructAnswerVO.getTechnical();
  145. map.put("title", title);
  146. map.put("conversionId", conversionId);
  147. map.put("technical", technical);
  148. //生成背景技术
  149. GenerateInstructAnswerVO generateInstructAnswerVO4 = this.generateBackGround(emitter, background);
  150. map.put("background", generateInstructAnswerVO4.getAnswers());
  151. //更新会话
  152. String name = DateUtils.dateTimeToStr(new Date(), "yyyyMMdd");
  153. name = name + "-" + title + "-生成说明书";
  154. confessionSession.setConversationName(name);
  155. confessionSession.setConversationId(conversionId);
  156. confessionSession.updateById();
  157. //生成发明内容
  158. String startMessage = getFluxMessage(FIELD_CONTENT, START, "");
  159. emitter.next(startMessage);
  160. ClaimExplainVO claimExplainVO = this.getFirstImplementation(rePatentClaims.get(0), background, conversionId);
  161. GenerateInstructAnswerVO generateInstructAnswerVO3 = this.generateContent(emitter, rePatentClaims, claimExplainVO);
  162. map.put("content",generateInstructAnswerVO3.getAnswers());
  163. //生成具体实施方式
  164. GenerateInstructAnswerVO generateInstructAnswerVO2 = this.generateImplementation(emitter, claimExplainVO, background, conversionId, rePatentClaims);
  165. map.put("implementation", generateInstructAnswerVO2.getImplementations());
  166. //生成文档
  167. String fileGuid = this.generateFile(map, templateFilePath, name);
  168. AssoConfessionSessionFile assoConfessionSessionFile = new AssoConfessionSessionFile();
  169. assoConfessionSessionFile.setGuid(fileGuid);
  170. assoConfessionSessionFile.setConfessionSessionId(confessionSession.getId());
  171. assoConfessionSessionFile.insert();
  172. String endMess = getFluxMessage("", ALL_END, fileGuid);
  173. emitter.next(endMess);
  174. } catch (Exception e) {
  175. e.printStackTrace();
  176. } finally {
  177. emitter.complete();
  178. }
  179. }).start();
  180. });
  181. }
  182. /**
  183. * 生成文件
  184. *
  185. * @param map
  186. * @param templateFilePath
  187. * @param name
  188. * @return
  189. * @throws Exception
  190. */
  191. public String generateFile(Map<String, Object> map, String templateFilePath, String name) throws Exception {
  192. XWPFTemplate xwpfTemplate = this.getTemplate(map, templateFilePath);
  193. String fileName = name + ".docx";
  194. String directoryName = fileUtils.createDirectory();
  195. String outPath = fileUtils.getSavePath(directoryName) + fileName;
  196. File file = new File(outPath);
  197. // 生成word保存在指定目录
  198. xwpfTemplate.writeToFile(outPath);
  199. xwpfTemplate.close();
  200. List<String> ids = fileManagerService.uploadFileGetGuid2(Arrays.asList(file));
  201. if (ids == null || ids.size() == 0) {
  202. throw new XiaoShiException("保存记录失败");
  203. }
  204. return ids.get(0);
  205. }
  206. /**
  207. * 生成标题和技术领域
  208. *
  209. * @param fluxSink
  210. * @param claim
  211. * @param background
  212. * @return
  213. * @throws Exception
  214. */
  215. public GenerateInstructAnswerVO genrateTechcialAndTitle(FluxSink fluxSink, String claim, String background) throws Exception {
  216. GenerateInstructAnswerVO generateInstructAnswerVO = null;
  217. GenerateTechnicalVO generateTechnicalVO = null;
  218. String startMessage = getFluxMessage(FIELD_TITLE, START, "");
  219. fluxSink.next(startMessage);
  220. Boolean ifError = false;
  221. try {
  222. generateInstructAnswerVO = this.getAnswerFromAI(claim, background, null, "g&technical", null);
  223. String answer = generateInstructAnswerVO.getAnswer();
  224. generateTechnicalVO = JSONObject.parseObject(answer, GenerateTechnicalVO.class);
  225. } catch (Exception e) {
  226. e.printStackTrace();
  227. ifError = true;
  228. }
  229. generateInstructAnswerVO.setTitle(generateTechnicalVO.getTitle());
  230. generateInstructAnswerVO.setTechnical(generateTechnicalVO.getTechnical());
  231. String message = "";
  232. if (ifError) {
  233. message = getFluxMessage(FIELD_TITLE, ERROR, "生成标题异常");
  234. } else {
  235. message = getFluxMessage(FIELD_TITLE, MESSAGE, generateTechnicalVO.getTitle());
  236. }
  237. fluxSink.next(message);
  238. String endMessage = getFluxMessage(FIELD_TITLE, END, "");
  239. fluxSink.next(endMessage);
  240. String startMessage2 = getFluxMessage(FIELD_TECHNICAL, START, "");
  241. fluxSink.next(startMessage2);
  242. String message2 = "";
  243. if (ifError) {
  244. message2 = getFluxMessage(FIELD_TECHNICAL, ERROR, "生成技术领域异常");
  245. } else {
  246. message2 = getFluxMessage(FIELD_TECHNICAL, MESSAGE, generateTechnicalVO.getTechnical());
  247. }
  248. fluxSink.next(message2);
  249. String endMessage2 = getFluxMessage(FIELD_TECHNICAL, END, "");
  250. fluxSink.next(endMessage2);
  251. return generateInstructAnswerVO;
  252. }
  253. /**
  254. * 生成第一个权利要求解释
  255. *
  256. * @param rePatentClaim
  257. * @return
  258. */
  259. public ClaimExplainVO getFirstImplementation(RePatentClaim rePatentClaim, String background, String conversationId) throws Exception {
  260. ClaimExplainVO claimExplainVO = null;
  261. try {
  262. String claimContent = rePatentClaim.getContent();
  263. GenerateInstructAnswerVO generateInstructAnswerVO = this.getAnswerFromAI(claimContent, background, 0, "g&implementation", conversationId);
  264. String answer = generateInstructAnswerVO.getAnswer();
  265. claimExplainVO = JSONObject.parseObject(answer, ClaimExplainVO.class);
  266. } catch (Exception e) {
  267. e.printStackTrace();
  268. }
  269. return claimExplainVO;
  270. }
  271. /**
  272. * 生成权要的具体实施方式
  273. *
  274. * @param fluxSink
  275. * @param firstClaimExplainVO
  276. * @param background
  277. * @param conversationId
  278. * @param rePatentClaims
  279. * @return
  280. * @throws Exception
  281. */
  282. public GenerateInstructAnswerVO generateImplementation(FluxSink fluxSink, ClaimExplainVO firstClaimExplainVO, String background, String conversationId, List<RePatentClaim> rePatentClaims) throws Exception {
  283. String startMessage = getFluxMessage(FIELD_IMPLEMENTATION, START, "");
  284. fluxSink.next(startMessage);
  285. GenerateInstructAnswerVO mainVO = new GenerateInstructAnswerVO();
  286. List<String> reContents = new ArrayList<>();
  287. for (int i = 0; i < rePatentClaims.size(); i++) {
  288. ClaimExplainVO claimExplainVO = null;
  289. if (i == 0) {
  290. claimExplainVO = firstClaimExplainVO;
  291. } else {
  292. try {
  293. RePatentClaim rePatentClaim = rePatentClaims.get(i);
  294. String claimContent = rePatentClaim.getContent();
  295. GenerateInstructAnswerVO generateInstructAnswerVO = this.getAnswerFromAI(claimContent, background, i, "g&implementation", conversationId);
  296. String answer = generateInstructAnswerVO.getAnswer();
  297. if (generateInstructAnswerVO.getConversionId() != null) {
  298. mainVO.setConversionId(generateInstructAnswerVO.getConversionId());
  299. }
  300. claimExplainVO = JSONObject.parseObject(answer, ClaimExplainVO.class);
  301. } catch (Exception e) {
  302. }
  303. }
  304. String message = "";
  305. String reStr = null;
  306. if (claimExplainVO != null) {
  307. List<String> contents = this.formatImplementation(claimExplainVO);
  308. if(contents.size()>0){
  309. reContents.addAll(contents);
  310. reStr = StringUtils.join(contents, "\n");
  311. }
  312. if (i != 0) {
  313. reStr = "\n" + reStr;
  314. }
  315. message = getFluxMessage(FIELD_IMPLEMENTATION, MESSAGE, reStr);
  316. } else {
  317. message = getFluxMessage(FIELD_IMPLEMENTATION, MESSAGE, "生成权要" + (i + 1) + "的具体实施方式异常");
  318. }
  319. fluxSink.next(message);
  320. }
  321. mainVO.setImplementations(reContents);
  322. String endMessage = getFluxMessage(FIELD_IMPLEMENTATION, END, "");
  323. fluxSink.next(endMessage);
  324. return mainVO;
  325. }
  326. /**
  327. * 生成单个权要的具体实施方式
  328. *
  329. * @param claimExplainVO
  330. * @return
  331. */
  332. private List<String> formatImplementation(ClaimExplainVO claimExplainVO) {
  333. String reStr = null;
  334. List<String> contents = new ArrayList<>();
  335. String explainVOClaim = claimExplainVO.getClaim();
  336. String effect = claimExplainVO.getEffects();
  337. String explain = claimExplainVO.getExplain();
  338. if (explainVOClaim != null && !explainVOClaim.trim().equals("")) {
  339. String tem= this.getClaimText(explainVOClaim);
  340. contents.add(tem);
  341. }
  342. if (effect != null && !effect.trim().equals("")) {
  343. contents.add(effect);
  344. }
  345. if (explain != null && !explain.trim().equals("")) {
  346. contents.add(explain);
  347. }
  348. return contents;
  349. }
  350. private String getFluxMessage(String field, String event, String content) {
  351. FluxMessageVO fluxMessage = new FluxMessageVO();
  352. fluxMessage.setEvent(event);
  353. fluxMessage.setField(field);
  354. fluxMessage.setContent(content);
  355. fluxMessage.setId(SESSION_ID);
  356. String json = JSONObject.toJSONString(fluxMessage);
  357. return json;
  358. }
  359. public GenerateInstructAnswerVO getAnswerFromAI(String claim, String background, Integer index, String type, String conversationId) throws Exception {
  360. GenerateInstructAnswerVO generateInstructAnswerVO = new GenerateInstructAnswerVO();
  361. DifyChatMessageDTO difyChatMessageDTO = new DifyChatMessageDTO();
  362. difyChatMessageDTO.setUser("1");
  363. difyChatMessageDTO.setResponseMode("blocking");
  364. difyChatMessageDTO.setQuery(type);
  365. difyChatMessageDTO.setConversationId(conversationId);
  366. Map<String, Object> map = new HashMap<>();
  367. map.put("claim", claim);
  368. map.put("background", background);
  369. map.put("num_index", index);
  370. difyChatMessageDTO.setInputs(map);
  371. String re = difyService.chatMessage(difyChatMessageDTO, gInstructionKey);
  372. JSONObject jsonObject = JSONObject.parseObject(re);
  373. String answer = jsonObject.get("answer").toString();
  374. String conversionId = jsonObject.get("conversation_id").toString();
  375. generateInstructAnswerVO.setAnswer(answer);
  376. generateInstructAnswerVO.setConversionId(conversionId);
  377. return generateInstructAnswerVO;
  378. }
  379. /**
  380. * 生成背景技术
  381. *
  382. * @param fluxSink
  383. * @param background
  384. * @return
  385. */
  386. public GenerateInstructAnswerVO generateBackGround(FluxSink fluxSink, String background) {
  387. GenerateInstructAnswerVO generateInstructAnswerVO = new GenerateInstructAnswerVO();
  388. generateInstructAnswerVO.setAnswer(background);
  389. String startMessage = getFluxMessage(FIELD_BACKGROUND, START, "");
  390. fluxSink.next(startMessage);
  391. String message = getFluxMessage(FIELD_BACKGROUND, MESSAGE, background);
  392. fluxSink.next(message);
  393. String endMessage = getFluxMessage(FIELD_BACKGROUND, END, "");
  394. fluxSink.next(endMessage);
  395. List<String> answers =Arrays.asList( background.split("\n"));
  396. generateInstructAnswerVO.setAnswers(answers);
  397. return generateInstructAnswerVO;
  398. }
  399. /**
  400. * 生成发明/实用新型内容
  401. *
  402. * @param fluxSink
  403. * @param rePatentClaims
  404. * @return
  405. */
  406. public GenerateInstructAnswerVO generateContent(FluxSink fluxSink, List<RePatentClaim> rePatentClaims, ClaimExplainVO claimExplainVO) {
  407. GenerateInstructAnswerVO generateInstructAnswerVO = new GenerateInstructAnswerVO();
  408. List<String> contentStrs = new ArrayList<>();
  409. for (RePatentClaim rePatentClaim : rePatentClaims) {
  410. String claimContent = rePatentClaim.getContent();
  411. String temContent = "";
  412. if (rePatentClaim != null && rePatentClaim.getType() != null && rePatentClaim.getType().equals(1)) {
  413. temContent = "为解决上述问题,本申请提出"+ this.getClaimText(claimContent);
  414. } else {
  415. temContent = this.getClaimContent(claimContent);
  416. }
  417. contentStrs.add(temContent);
  418. }
  419. String reContent = "";
  420. if (contentStrs.size() != 0) {
  421. reContent = StringUtils.join(contentStrs, "\n");
  422. }
  423. String message = getFluxMessage(FIELD_CONTENT, MESSAGE, reContent);
  424. fluxSink.next(message);
  425. if (claimExplainVO != null) {
  426. String temContent="有益效果是:" + claimExplainVO.getEffects();
  427. contentStrs.add(temContent);
  428. message = getFluxMessage(FIELD_CONTENT, MESSAGE,"\n"+temContent);
  429. fluxSink.next(message);
  430. } else {
  431. message = getFluxMessage(FIELD_CONTENT, ERROR, "生成有益效果异常");
  432. fluxSink.next(message);
  433. }
  434. String endMessage = getFluxMessage(FIELD_CONTENT, END, "");
  435. fluxSink.next(endMessage);
  436. generateInstructAnswerVO.setAnswer(reContent);
  437. generateInstructAnswerVO.setAnswers(contentStrs);
  438. return generateInstructAnswerVO;
  439. }
  440. }