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.LoginUtils; 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.domain.dify.GetInstructAnswerDTO; 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; @Value("${FileDownloadUrl}") private String fileDownloadUrl; 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 final static List DISABLE_WORD = Arrays.asList("权利要求", "所述", "其特征在于"); private static final String[] num_lower = {"一", "二", "三", "四", "五", "六", "七", "八", "九"}; private Integer SESSION_ID; @Value("${DIFY.gInstructionKey}") private String gInstructionKey; @Autowired private LoginUtils loginUtils; public String getClaimContent(String claim) { claim = claim.replaceAll("所述", ""); // 正则表达式模式(注意 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(Integer mainFlag, String claim) { if (mainFlag <= num_lower.length) { claim = "第" + num_lower[mainFlag] + "方面,本申请提供" + claim; } // 正则表达式模式(注意 Java 中需要双反斜杠转义) return claim; // 未找到匹配时返回空字符串 } 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 orgClaim = generateClaimDTO.getClaim(); String guid = generateClaimDTO.getFilePath(); String filePath = fileDownloadUrl + generateClaimDTO.getFilePath(); String claim = orgClaim.replaceAll("\n", "").replaceAll("\\\\n", ""); 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); addConfessionSessionDTO.setGuid(guid); ConfessionSession confessionSession = confessionSessionService.addSessionReDO(addConfessionSessionDTO); SESSION_ID = confessionSession.getId(); ReportTemple reportTemplate = templeService.getById(templeId); String templateFilePath = fileUtils.getPath(reportTemplate.getTemplatePath()); Map map = new HashMap<>(); PatentRightParams params = new PatentRightParams(); params.setCountry("CN"); params.setContent(claim); params.setPatentNo("CN"); List rePatentClaims = ClaimSplitUtils.formatPatentRight(params); List reMainPatentClaims = rePatentClaims.stream().filter(item -> item.getParentSort().equals("-1")).map(RePatentClaim::getContent).collect(Collectors.toList()); String mainClaimStr = ""; if (reMainPatentClaims != null && reMainPatentClaims.size() > 0) { mainClaimStr = StringUtils.join(reMainPatentClaims, "\n"); } String mainClaim = mainClaimStr; return Flux.create(emitter -> { new Thread(() -> { try { //;流程开始 String startMess = getFluxMessage("", ALL_START, ""); emitter.next(startMess); //生成标题和技术领域 GenerateInstructAnswerVO generateInstructAnswerVO = this.genrateTechcialAndTitle(emitter, mainClaim, background, filePath); 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, conversionId, title); List formClaimList = generateInstructAnswerVO3.getClaimList(); map.put("content", generateInstructAnswerVO3.getAnswers()); //生成具体实施方式 GenerateInstructAnswerVO generateInstructAnswerVO2 = this.generateImplementation(emitter, claimExplainVO, background, conversionId, rePatentClaims, formClaimList); 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 background * @return * @throws Exception */ public GenerateInstructAnswerVO genrateTechcialAndTitle(FluxSink fluxSink, String mainClaim, String background, String filePath) throws Exception { GenerateInstructAnswerVO generateInstructAnswerVO = null; GenerateTechnicalVO generateTechnicalVO = null; String startMessage = getFluxMessage(FIELD_TITLE, START, ""); fluxSink.next(startMessage); Boolean ifError = false; try { GetInstructAnswerDTO getInstructAnswerDTO = new GetInstructAnswerDTO(); getInstructAnswerDTO.setBackground(background); getInstructAnswerDTO.setMainClaim(mainClaim); getInstructAnswerDTO.setFilePath(filePath); getInstructAnswerDTO.setType("g&technical"); generateInstructAnswerVO = this.getAnswerFromAI(getInstructAnswerDTO); 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(); GetInstructAnswerDTO getInstructAnswerDTO = new GetInstructAnswerDTO(); getInstructAnswerDTO.setClaim(claimContent); getInstructAnswerDTO.setIndex(0); getInstructAnswerDTO.setBackground(background); getInstructAnswerDTO.setType("g&implementation"); getInstructAnswerDTO.setConversationId(conversationId); GenerateInstructAnswerVO generateInstructAnswerVO = this.getAnswerVO(getInstructAnswerDTO); 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, List formClaims) 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++) { RePatentClaim rePatentClaim = rePatentClaims.get(i); String formClaim = ""; if (formClaims.size() >= i + 1) { formClaim = formClaims.get(i); } ClaimExplainVO claimExplainVO = null; if (i == 0) { claimExplainVO = firstClaimExplainVO; } else { try { String claimContent = rePatentClaim.getContent(); GetInstructAnswerDTO getInstructAnswerDTO = new GetInstructAnswerDTO(); getInstructAnswerDTO.setClaim(claimContent); getInstructAnswerDTO.setBackground(background); getInstructAnswerDTO.setIndex(i); getInstructAnswerDTO.setType("g&implementation"); getInstructAnswerDTO.setConversationId(conversationId); GenerateInstructAnswerVO generateInstructAnswerVO = this.getAnswerVO(getInstructAnswerDTO); 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, rePatentClaim, formClaim); 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, RePatentClaim rePatentClaim, String formClaim) { String reStr = null; List contents = new ArrayList<>(); String explainVOClaim = formClaim; String effect = claimExplainVO.getEffects(); String explain = claimExplainVO.getExplain(); if (explainVOClaim != null && !explainVOClaim.trim().equals("")) { String tem = ""; if (rePatentClaim != null && rePatentClaim.getType() != null && rePatentClaim.getType().equals(1)) { tem = explainVOClaim; } else { tem = "在一实施方式中," + explainVOClaim; } contents.add(tem); } if (explain != null && !explain.trim().equals("")) { contents.add(explain); } if (effect != null && !effect.trim().equals("")) { contents.add(effect); } 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(GetInstructAnswerDTO getInstructAnswerDTO) throws Exception { String type = getInstructAnswerDTO.getType(); String conversationId = getInstructAnswerDTO.getConversationId(); String claim = getInstructAnswerDTO.getClaim(); String claims = getInstructAnswerDTO.getClaims(); String background = getInstructAnswerDTO.getBackground(); Integer index = getInstructAnswerDTO.getIndex(); String effects = getInstructAnswerDTO.getEffects(); String mainClaim = getInstructAnswerDTO.getMainClaim(); String filePath = getInstructAnswerDTO.getFilePath(); 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); map.put("effect", effects); map.put("claims", claims); map.put("main_claim", mainClaim); map.put("file_path", filePath); difyChatMessageDTO.setInputs(map); Integer cycle = 0; Boolean flag = false; String re = ""; while (cycle < 5 && flag == false) { re = difyService.chatMessage(difyChatMessageDTO, gInstructionKey); JSONObject jsonObject = JSONObject.parseObject(re); Object status = jsonObject.get("status"); if (status != null) { cycle++; } else { String answer = jsonObject.get("answer").toString(); String conversionId = jsonObject.get("conversation_id").toString(); generateInstructAnswerVO.setAnswer(answer); generateInstructAnswerVO.setConversionId(conversionId); flag = true; } } 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, String conversationId, String title) throws Exception { GenerateInstructAnswerVO generateInstructAnswerVO = new GenerateInstructAnswerVO(); List formClaims = new ArrayList<>(); List contentStrs = new ArrayList<>(); List claimStrsList = rePatentClaims.stream().map(RePatentClaim::getContent).collect(Collectors.toList()); GetInstructAnswerDTO getInstructAnswerDTO = new GetInstructAnswerDTO(); getInstructAnswerDTO.setConversationId(conversationId); getInstructAnswerDTO.setType("g&content"); GenerateInstructAnswerVO generateInstructAnswerVO2 = new GenerateInstructAnswerVO(); //发送说明书内容第一段信息 getInstructAnswerDTO.setEffects(claimExplainVO.getEffects()); getInstructAnswerDTO.setType("g&re_effect"); generateInstructAnswerVO2 = this.getAnswerVO(getInstructAnswerDTO); String answer = generateInstructAnswerVO2.getAnswer(); GenerateContentVO generateTechnicalVO = JSONObject.parseObject(answer, GenerateContentVO.class); String effects = generateTechnicalVO.getEffect(); String titleEffect = "本申请主要解决的技术问题是" + title + "," + effects; contentStrs.add(titleEffect); String message = getFluxMessage(FIELD_CONTENT, MESSAGE, titleEffect); fluxSink.next(message); Integer mainClaimFlag = 0; for (int i = 0; i < claimStrsList.size(); i++) { getInstructAnswerDTO.setType("g&content"); String claimStr = claimStrsList.get(i); getInstructAnswerDTO.setClaim(claimStr); generateInstructAnswerVO2 = this.getAnswerVO(getInstructAnswerDTO); String answer1 = generateInstructAnswerVO2.getAnswer(); GenerateContentVO generateTechnicalVO1 = JSONObject.parseObject(answer1, GenerateContentVO.class); String claim = generateTechnicalVO1.getClaim(); formClaims.add(claim); RePatentClaim rePatentClaim = rePatentClaims.get(i); String temContent = ""; if (rePatentClaim != null && rePatentClaim.getType() != null && rePatentClaim.getType().equals(1)) { temContent = this.getMainClaimContent(mainClaimFlag, claim); mainClaimFlag++; } else { temContent = "其中," + claim; } contentStrs.add(temContent); String message1 = getFluxMessage(FIELD_CONTENT, MESSAGE, "\n" + temContent); fluxSink.next(message1); } 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.setAnswers(contentStrs); generateInstructAnswerVO.setClaimList(formClaims); return generateInstructAnswerVO; } public GenerateInstructAnswerVO getAnswerVO(GetInstructAnswerDTO getInstructAnswerDTO) throws Exception { GenerateInstructAnswerVO generateInstructAnswerVO = null; Integer a = 0; Boolean flag = true; while (flag && a < 5) { generateInstructAnswerVO = this.getAnswerFromAI(getInstructAnswerDTO); String answer = generateInstructAnswerVO.getAnswer(); if ((answer == null) || answer != null && (answer.contains("所述") || answer.contains("权利要求") || answer.contains("其特征在于"))) { a++; continue; } flag = false; } return generateInstructAnswerVO; } }