package com.supervision.pdfqaserver.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONArray; import cn.hutool.json.JSONUtil; import com.supervision.pdfqaserver.cache.PromptCache; import com.supervision.pdfqaserver.dto.CypherSchemaDTO; import com.supervision.pdfqaserver.dto.neo4j.RelationshipValueDTO; import com.supervision.pdfqaserver.service.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; import java.util.Map; import static com.supervision.pdfqaserver.cache.PromptCache.*; /** * 数据对比检索器 */ @Slf4j @Service("dataCompareRetriever") @RequiredArgsConstructor public class DataCompareRetriever implements Retriever { private final TripleToCypherExecutor tripleToCypherExecutor; private final AiCallService aiCallService; @Override public List> retrieval(String query) { log.info("retrieval: 执行数据对比检索器,查询内容:{}", query); if (StrUtil.isEmpty(query)) { log.warn("查询内容为空,无法执行数据对比检索"); return new ArrayList<>(); } // 对问题进行分词 CypherSchemaDTO schemaDTO = tripleToCypherExecutor.queryRelationSchema(query); log.info("retrieval: 查询到的关系图谱schema 节点个数:{} ,关系结束{} ", schemaDTO.getNodes().size(), schemaDTO.getRelations().size()); log.info("retrieval: 查询到的关系图谱schema :{} ", schemaDTO.format()); if (CollUtil.isEmpty(schemaDTO.getRelations()) || CollUtil.isEmpty(schemaDTO.getNodes())) { log.info("没有找到匹配的关系或实体,query: {}", query); return new ArrayList<>(); } // 利用大模型生成可执行的cypher语句 String prompt = PromptCache.promptMap.get(TEXT_TO_CYPHER_3); String format = StrUtil.format(prompt, Map.of("query", query, "schema", schemaDTO.format(), "env", "- 当前时间是:" + DateUtil.now())); log.info("retrieval: 生成的cypher语句:{}", format); String call = aiCallService.call(format); log.info("retrieval: AI调用返回结果:{}", call); if (StrUtil.isEmpty(call)) { log.warn("retrieval: AI调用返回结果为空,无法执行Cypher查询"); return new ArrayList<>(); } List> result = new ArrayList<>(); JSONArray js = JSONUtil.parseArray(call); Map>> cypherData = tripleToCypherExecutor.executeCypher(js.toList(String.class)); if (CollUtil.isNotEmpty(cypherData)) { boolean allEmpty = cypherData.values().stream().noneMatch(CollUtil::isNotEmpty); if (!allEmpty){ cypherData.values().stream().filter(CollUtil::isNotEmpty).forEach(result::addAll); return clearGraphElements(result); } } if (CollUtil.isEmpty(result)){ log.info("retrieval: 执行Cypher语句无结果,重新调整cypher语句:{}", query); prompt = PromptCache.promptMap.get(TEXT_TO_CYPHER_4); format = StrUtil.format(prompt, Map.of("query", query, "schema", schemaDTO.format(), "env", "- 当前时间是:" + DateUtil.now()),"cypher",js.toString()); log.info("retrieval: 生成的cypher语句:{}", format); call = aiCallService.call(format); log.info("retrieval: AI调用返回结果:{}", call); js = JSONUtil.parseArray(call); cypherData = tripleToCypherExecutor.executeCypher(js.toList(String.class)); if (CollUtil.isNotEmpty(cypherData)) { boolean allEmpty2 = cypherData.values().stream().noneMatch(CollUtil::isNotEmpty); if (!allEmpty2){ cypherData.values().stream().filter(CollUtil::isNotEmpty).forEach(result::addAll); return clearGraphElements(result); } } } return clearGraphElements(result); } /** * 清理图谱元素中的无效数据 * @param graphElements 图谱元素列表 * @return */ private List> clearGraphElements(List> graphElements) { if (CollUtil.isEmpty(graphElements)){ return graphElements; } for (Map element : graphElements) { for (Object value : element.values()) { if (value instanceof RelationshipValueDTO relationshipValueDTO) { relationshipValueDTO.clearGraphElement(); } if (value instanceof com.supervision.pdfqaserver.dto.neo4j.NodeDTO nodeDTO) { nodeDTO.clearGraphElement(); } } } return graphElements; } }