package cn.cslg.pas.service.dify; import cn.cslg.pas.common.model.dify.*; import cn.cslg.pas.common.model.dify.confessionSession.AddConfessionSessionDTO; import cn.cslg.pas.common.utils.ClaimUtils.ClaimSplitUtils; import cn.cslg.pas.common.utils.DateUtils; import cn.cslg.pas.common.utils.FileUtils; import cn.cslg.pas.common.utils.StringUtils; import cn.cslg.pas.common.vo.PatentRightParams; import cn.cslg.pas.common.vo.RePatentClaim; import cn.cslg.pas.domain.business.ReportProject; import cn.cslg.pas.domain.business.ReportTemple; import cn.cslg.pas.domain.dify.AssoConfessionSessionFile; import cn.cslg.pas.domain.dify.ConfessionSession; import cn.cslg.pas.exception.ExceptionEnum; import cn.cslg.pas.exception.XiaoShiException; import cn.cslg.pas.service.business.ReportTempleService; import cn.cslg.pas.service.common.DifyService; import cn.cslg.pas.service.common.FileManagerService; import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.deepoove.poi.XWPFTemplate; import com.deepoove.poi.config.Configure; import com.google.gson.Gson; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import reactor.core.publisher.Flux; import reactor.core.publisher.FluxSink; import java.io.File; import java.io.IOException; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @Service public class GenerateInstructionService { @Autowired private ReportTempleService templeService; @Autowired private FileUtils fileUtils; @Autowired private AssoConfessionSessionFileService assoConfessionSessionFileService; @Autowired private DifyService difyService; @Autowired private FileManagerService fileManagerService; @Autowired private ConfessionSessionService confessionSessionService; private final static String ALL_START = "all_start"; private final static String ALL_END = "all_end"; private final static String START = "start"; private final static String END = "end"; private final static String MESSAGE = "message"; private final static String FIELD_TITLE = "title"; private final static String FIELD_TECHNICAL = "technical"; private final static String FIELD_IMPLEMENTATION = "implementation"; private final static String FIELD_BACKGROUND = "background"; private final static String FIELD_CONTENT = "content"; private final static String ERROR = "error"; private Integer SESSION_ID; @Value("${DIFY.gInstructionKey}") private String gInstructionKey; public String getClaimContent(String claim) { // 正则表达式模式(注意 Java 中需要双反斜杠转义) String regex = "其特征在于[,。;!?、]+(.+)"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(claim); if (matcher.find()) { // 提取第一个捕获组的内容(即括号内的部分) return matcher.group(1).trim(); } return "其中," + claim; // 未找到匹配时返回空字符串 } public String getMainClaimContent(String claim) { // 正则表达式模式(注意 Java 中需要双反斜杠转义) // String regex1 = "^[0-9]+\\."; // String regex2 = "^\\[[0-9]+]"; // String regex3 = "^[0-9]+、"; // String outPut1 = claim.replaceAll(regex1, ""); // String outPut2 = outPut1.replaceAll(regex2, ""); // String outPut3 =outPut2.replaceAll(regex3,""); String combinedRegex = "^(\\d+[.、]|\\[[0-9]+])"; String output = claim.replaceAll(combinedRegex, "").replaceAll("[\\n\\r]+$", ""); return output; // 未找到匹配时返回空字符串 } public String getClaimText(String claim) { String combinedRegex = "^(\\d+[.、]|\\[[0-9]+])"; String output = claim.replaceAll(combinedRegex, "").replaceAll("[\\n\\r]+$", ""); return output; // 未找到匹配时返回空字符串 } private XWPFTemplate getTemplate(Map map, String filePath) { //装载标的专利信息 XWPFTemplate template = null; try { Configure configure = Configure.builder() .build(); template = XWPFTemplate.compile(filePath, configure).render(map); } catch (Exception e) { e.printStackTrace(); throw new XiaoShiException(ExceptionEnum.BUSINESS_ERROR, "未匹配到模版文件"); } return template; } public Flux generateInstruction2(GenerateClaimDTO generateClaimDTO) throws Exception { Integer templeId = 19; String claim = generateClaimDTO.getClaim(); String background = generateClaimDTO.getBackground(); Map addMap = new HashMap<>(); Map queryMap = new HashMap<>(); queryMap.put("claim", claim); queryMap.put("background", background); addMap.put("query", queryMap); String addStr = JSONObject.toJSONString(addMap); AddConfessionSessionDTO addConfessionSessionDTO = new AddConfessionSessionDTO(); addConfessionSessionDTO.setType(3); addConfessionSessionDTO.setContent(addStr); ConfessionSession confessionSession = confessionSessionService.addSessionReDO(addConfessionSessionDTO); SESSION_ID = confessionSession.getId(); ReportTemple reportTemplate = templeService.getById(templeId); String templateFilePath = fileUtils.getPath(reportTemplate.getTemplatePath()); Map map = new HashMap<>(); return Flux.create(emitter -> { new Thread(() -> { try { //;流程开始 String startMess = getFluxMessage("", ALL_START, ""); emitter.next(startMess); PatentRightParams params = new PatentRightParams(); params.setCountry("CN"); params.setContent(claim); params.setPatentNo("CN"); List rePatentClaims = ClaimSplitUtils.formatPatentRight(params); //生成标题和技术领域 GenerateInstructAnswerVO generateInstructAnswerVO = this.genrateTechcialAndTitle(emitter, claim, background); String conversionId = generateInstructAnswerVO.getConversionId(); String title = generateInstructAnswerVO.getTitle(); String technical = generateInstructAnswerVO.getTechnical(); map.put("title", title); map.put("conversionId", conversionId); map.put("technical", technical); //生成背景技术 GenerateInstructAnswerVO generateInstructAnswerVO4 = this.generateBackGround(emitter, background); map.put("background", generateInstructAnswerVO4.getAnswers()); //更新会话 String name = DateUtils.dateTimeToStr(new Date(), "yyyyMMdd"); name = name + "-" + title + "-生成说明书"; confessionSession.setConversationName(name); confessionSession.setConversationId(conversionId); confessionSession.updateById(); //生成发明内容 String startMessage = getFluxMessage(FIELD_CONTENT, START, ""); emitter.next(startMessage); ClaimExplainVO claimExplainVO = this.getFirstImplementation(rePatentClaims.get(0), background, conversionId); GenerateInstructAnswerVO generateInstructAnswerVO3 = this.generateContent(emitter, rePatentClaims, claimExplainVO); map.put("content",generateInstructAnswerVO3.getAnswers()); //生成具体实施方式 GenerateInstructAnswerVO generateInstructAnswerVO2 = this.generateImplementation(emitter, claimExplainVO, background, conversionId, rePatentClaims); map.put("implementation", generateInstructAnswerVO2.getImplementations()); //生成文档 String fileGuid = this.generateFile(map, templateFilePath, name); AssoConfessionSessionFile assoConfessionSessionFile = new AssoConfessionSessionFile(); assoConfessionSessionFile.setGuid(fileGuid); assoConfessionSessionFile.setConfessionSessionId(confessionSession.getId()); assoConfessionSessionFile.insert(); String endMess = getFluxMessage("", ALL_END, fileGuid); emitter.next(endMess); } catch (Exception e) { e.printStackTrace(); } finally { emitter.complete(); } }).start(); }); } /** * 生成文件 * * @param map * @param templateFilePath * @param name * @return * @throws Exception */ public String generateFile(Map map, String templateFilePath, String name) throws Exception { XWPFTemplate xwpfTemplate = this.getTemplate(map, templateFilePath); String fileName = name + ".docx"; String directoryName = fileUtils.createDirectory(); String outPath = fileUtils.getSavePath(directoryName) + fileName; File file = new File(outPath); // 生成word保存在指定目录 xwpfTemplate.writeToFile(outPath); xwpfTemplate.close(); List ids = fileManagerService.uploadFileGetGuid2(Arrays.asList(file)); if (ids == null || ids.size() == 0) { throw new XiaoShiException("保存记录失败"); } return ids.get(0); } /** * 生成标题和技术领域 * * @param fluxSink * @param claim * @param background * @return * @throws Exception */ public GenerateInstructAnswerVO genrateTechcialAndTitle(FluxSink fluxSink, String claim, String background) throws Exception { GenerateInstructAnswerVO generateInstructAnswerVO = null; GenerateTechnicalVO generateTechnicalVO = null; String startMessage = getFluxMessage(FIELD_TITLE, START, ""); fluxSink.next(startMessage); Boolean ifError = false; try { generateInstructAnswerVO = this.getAnswerFromAI(claim, background, null, "g&technical", null); String answer = generateInstructAnswerVO.getAnswer(); generateTechnicalVO = JSONObject.parseObject(answer, GenerateTechnicalVO.class); } catch (Exception e) { e.printStackTrace(); ifError = true; } generateInstructAnswerVO.setTitle(generateTechnicalVO.getTitle()); generateInstructAnswerVO.setTechnical(generateTechnicalVO.getTechnical()); String message = ""; if (ifError) { message = getFluxMessage(FIELD_TITLE, ERROR, "生成标题异常"); } else { message = getFluxMessage(FIELD_TITLE, MESSAGE, generateTechnicalVO.getTitle()); } fluxSink.next(message); String endMessage = getFluxMessage(FIELD_TITLE, END, ""); fluxSink.next(endMessage); String startMessage2 = getFluxMessage(FIELD_TECHNICAL, START, ""); fluxSink.next(startMessage2); String message2 = ""; if (ifError) { message2 = getFluxMessage(FIELD_TECHNICAL, ERROR, "生成技术领域异常"); } else { message2 = getFluxMessage(FIELD_TECHNICAL, MESSAGE, generateTechnicalVO.getTechnical()); } fluxSink.next(message2); String endMessage2 = getFluxMessage(FIELD_TECHNICAL, END, ""); fluxSink.next(endMessage2); return generateInstructAnswerVO; } /** * 生成第一个权利要求解释 * * @param rePatentClaim * @return */ public ClaimExplainVO getFirstImplementation(RePatentClaim rePatentClaim, String background, String conversationId) throws Exception { ClaimExplainVO claimExplainVO = null; try { String claimContent = rePatentClaim.getContent(); GenerateInstructAnswerVO generateInstructAnswerVO = this.getAnswerFromAI(claimContent, background, 0, "g&implementation", conversationId); String answer = generateInstructAnswerVO.getAnswer(); claimExplainVO = JSONObject.parseObject(answer, ClaimExplainVO.class); } catch (Exception e) { e.printStackTrace(); } return claimExplainVO; } /** * 生成权要的具体实施方式 * * @param fluxSink * @param firstClaimExplainVO * @param background * @param conversationId * @param rePatentClaims * @return * @throws Exception */ public GenerateInstructAnswerVO generateImplementation(FluxSink fluxSink, ClaimExplainVO firstClaimExplainVO, String background, String conversationId, List rePatentClaims) throws Exception { String startMessage = getFluxMessage(FIELD_IMPLEMENTATION, START, ""); fluxSink.next(startMessage); GenerateInstructAnswerVO mainVO = new GenerateInstructAnswerVO(); List reContents = new ArrayList<>(); for (int i = 0; i < rePatentClaims.size(); i++) { ClaimExplainVO claimExplainVO = null; if (i == 0) { claimExplainVO = firstClaimExplainVO; } else { try { RePatentClaim rePatentClaim = rePatentClaims.get(i); String claimContent = rePatentClaim.getContent(); GenerateInstructAnswerVO generateInstructAnswerVO = this.getAnswerFromAI(claimContent, background, i, "g&implementation", conversationId); String answer = generateInstructAnswerVO.getAnswer(); if (generateInstructAnswerVO.getConversionId() != null) { mainVO.setConversionId(generateInstructAnswerVO.getConversionId()); } claimExplainVO = JSONObject.parseObject(answer, ClaimExplainVO.class); } catch (Exception e) { } } String message = ""; String reStr = null; if (claimExplainVO != null) { List contents = this.formatImplementation(claimExplainVO); if(contents.size()>0){ reContents.addAll(contents); reStr = StringUtils.join(contents, "\n"); } if (i != 0) { reStr = "\n" + reStr; } message = getFluxMessage(FIELD_IMPLEMENTATION, MESSAGE, reStr); } else { message = getFluxMessage(FIELD_IMPLEMENTATION, MESSAGE, "生成权要" + (i + 1) + "的具体实施方式异常"); } fluxSink.next(message); } mainVO.setImplementations(reContents); String endMessage = getFluxMessage(FIELD_IMPLEMENTATION, END, ""); fluxSink.next(endMessage); return mainVO; } /** * 生成单个权要的具体实施方式 * * @param claimExplainVO * @return */ private List formatImplementation(ClaimExplainVO claimExplainVO) { String reStr = null; List contents = new ArrayList<>(); String explainVOClaim = claimExplainVO.getClaim(); String effect = claimExplainVO.getEffects(); String explain = claimExplainVO.getExplain(); if (explainVOClaim != null && !explainVOClaim.trim().equals("")) { String tem= this.getClaimText(explainVOClaim); contents.add(tem); } if (effect != null && !effect.trim().equals("")) { contents.add(effect); } if (explain != null && !explain.trim().equals("")) { contents.add(explain); } return contents; } private String getFluxMessage(String field, String event, String content) { FluxMessageVO fluxMessage = new FluxMessageVO(); fluxMessage.setEvent(event); fluxMessage.setField(field); fluxMessage.setContent(content); fluxMessage.setId(SESSION_ID); String json = JSONObject.toJSONString(fluxMessage); return json; } public GenerateInstructAnswerVO getAnswerFromAI(String claim, String background, Integer index, String type, String conversationId) throws Exception { GenerateInstructAnswerVO generateInstructAnswerVO = new GenerateInstructAnswerVO(); DifyChatMessageDTO difyChatMessageDTO = new DifyChatMessageDTO(); difyChatMessageDTO.setUser("1"); difyChatMessageDTO.setResponseMode("blocking"); difyChatMessageDTO.setQuery(type); difyChatMessageDTO.setConversationId(conversationId); Map map = new HashMap<>(); map.put("claim", claim); map.put("background", background); map.put("num_index", index); difyChatMessageDTO.setInputs(map); String re = difyService.chatMessage(difyChatMessageDTO, gInstructionKey); JSONObject jsonObject = JSONObject.parseObject(re); String answer = jsonObject.get("answer").toString(); String conversionId = jsonObject.get("conversation_id").toString(); generateInstructAnswerVO.setAnswer(answer); generateInstructAnswerVO.setConversionId(conversionId); return generateInstructAnswerVO; } /** * 生成背景技术 * * @param fluxSink * @param background * @return */ public GenerateInstructAnswerVO generateBackGround(FluxSink fluxSink, String background) { GenerateInstructAnswerVO generateInstructAnswerVO = new GenerateInstructAnswerVO(); generateInstructAnswerVO.setAnswer(background); String startMessage = getFluxMessage(FIELD_BACKGROUND, START, ""); fluxSink.next(startMessage); String message = getFluxMessage(FIELD_BACKGROUND, MESSAGE, background); fluxSink.next(message); String endMessage = getFluxMessage(FIELD_BACKGROUND, END, ""); fluxSink.next(endMessage); List answers =Arrays.asList( background.split("\n")); generateInstructAnswerVO.setAnswers(answers); return generateInstructAnswerVO; } /** * 生成发明/实用新型内容 * * @param fluxSink * @param rePatentClaims * @return */ public GenerateInstructAnswerVO generateContent(FluxSink fluxSink, List rePatentClaims, ClaimExplainVO claimExplainVO) { GenerateInstructAnswerVO generateInstructAnswerVO = new GenerateInstructAnswerVO(); List contentStrs = new ArrayList<>(); for (RePatentClaim rePatentClaim : rePatentClaims) { String claimContent = rePatentClaim.getContent(); String temContent = ""; if (rePatentClaim != null && rePatentClaim.getType() != null && rePatentClaim.getType().equals(1)) { temContent = "为解决上述问题,本申请提出"+ this.getClaimText(claimContent); } else { temContent = this.getClaimContent(claimContent); } contentStrs.add(temContent); } String reContent = ""; if (contentStrs.size() != 0) { reContent = StringUtils.join(contentStrs, "\n"); } String message = getFluxMessage(FIELD_CONTENT, MESSAGE, reContent); fluxSink.next(message); if (claimExplainVO != null) { String temContent="有益效果是:" + claimExplainVO.getEffects(); contentStrs.add(temContent); message = getFluxMessage(FIELD_CONTENT, MESSAGE,"\n"+temContent); fluxSink.next(message); } else { message = getFluxMessage(FIELD_CONTENT, ERROR, "生成有益效果异常"); fluxSink.next(message); } String endMessage = getFluxMessage(FIELD_CONTENT, END, ""); fluxSink.next(endMessage); generateInstructAnswerVO.setAnswer(reContent); generateInstructAnswerVO.setAnswers(contentStrs); return generateInstructAnswerVO; } }