diff --git a/src/main/java/com/supervision/pdfqaserver/cache/PromptCache.java b/src/main/java/com/supervision/pdfqaserver/cache/PromptCache.java index 510aed8..2ac1f02 100644 --- a/src/main/java/com/supervision/pdfqaserver/cache/PromptCache.java +++ b/src/main/java/com/supervision/pdfqaserver/cache/PromptCache.java @@ -195,60 +195,47 @@ public class PromptCache { """; private static final String TEXT_TO_CYPHER_PROMPT = """ - 你是一个专业的 Neo4j Cypher 查询语句生成器,专门用于构建针对特定结构的查询语句。 - - --- - - **【数据库结构说明】** - - - **关系类型(relationType)**: - {relationTypeList} - - - **源节点类型(sourceType)**: - {sourceTypeList} - - - **目标节点类型(targetType)**: - {targetTypeList} - - --- - - **【生成规则】** - - 1. 识别用户问题中的实体及意图,映射为 `Cypher 查询语句` - 2. 使用无条件匹配,不假设任何属性名称,不添加 `WHERE` 子句过滤。 - 3. 返回所有满足该关系的查询语句,并包含节点和关系的**所有属性**。 - 4. 仅输出 字符串格式的json对象,不需要加任何解释。 - 5. 如无法从结构中推断 relationType、sourceType 或 targetType,输出: - "无法根据数据库结构生成查询" - - --- - - **【示例】** - - 1. - **用户问题:** 查询“宝塔盛华商贸集团”的基本信息? - - **生成的 Cypher 查询:** - "\\{ - "cypherQueries": [ - "MATCH (c:Company)-[r:HAS_LEGAL_REP]->(t) RETURN c, r, t", - "MATCH (c:Company)-[r:HAS_PHONE]->(t) RETURN c, r, t", - ..... - ] - \\}" - - 2. - **用户问题:** 查询“宝塔盛华商贸集团”出具的电子银行承兑汇票金额是多少? - - **生成的 Cypher 查询:** - "\\{ - "cypherQueries": [ - "MATCH (c:Company)-[r:IssueDocument]->(t:FinancialBill) RETURN c, r, t", - ..... - ] - \\}" - - 【用户问题】 - {query} - - 【你的任务】 - 根据以上数据库结构和用户问题,生成正确的Cypher查询语句。 + 你是一个专业的 Neo4j Cypher 查询语句生成器,专门用于构建针对特定结构的查询语句。 + --- + **【数据库结构说明】** + - **关系类型(relationType)**: + {relationTypeList} + - **源节点类型(sourceType)**: + {sourceTypeList} + - **目标节点类型(targetType)**: + {targetTypeList} + --- + **【生成规则】** + 1. 识别用户问题中的实体及意图,映射为 `Cypher 查询语句` + 2. 使用无条件匹配,不假设任何属性名称,不添加 `WHERE` 子句过滤。 + 3. 返回所有满足该关系的查询语句,仅使用 c 表示源节点,r 表示关系,t 表示目标节点,并返回它们的所有属性。 + 4. 仅输出 字符串格式的 JSON 对象,格式为:\\{ "cypherQueries": [ "MATCH ... RETURN c, r, t", ... ] \\},不需要加任何解释或说明。 + 5. 如无法从结构中推断 relationType、sourceType 或 targetType,输出: + "无法根据数据库结构生成查询" + 6. 只能使用relationType、sourceType 或 targetType中的数据 + --- + **【示例】** + 1. - **用户问题:** 龙源电力收购了哪些公司? + - **生成的 Cypher 查询:** + "\\{ + "cypherQueries": [ + "MATCH (c:`公司`)-[r:`收购`]->(t:`公司`) RETURN c, r, t", + "MATCH (c:`公司`)-[r:`收购`]->(t:`上市公司`) RETURN c, r, t", + ..... + ] + \\}" + 2. - **用户问题:** 龙源电力包含了哪些报告? + - **生成的 Cypher 查询:** + "\\{ + "cypherQueries": [ + "MATCH (c:`公司`)-[r:`包含`]->(t:`报告`) RETURN c, r, t", + ..... + ] + \\}" + 【用户问题】 + {query} + 【你的任务】 + 根据以上数据库结构和用户问题,生成正确的Cypher查询语句。 """; private static final String GENERATE_ANSWER_PROMPT = """ @@ -263,6 +250,7 @@ public class PromptCache { 2. 信息时效:可能需要确认数据的时间。 3. 问题范围界定:当用户提问超出审计报告分析范畴时,统一采用以下话术回复: "您好!当前系统功能聚焦于审计报告相关内容分析,您的问题暂不在支持范围内。如需查询财务数据、票据详情或其他审计相关信息,请提供具体问题,我们将全力协助。" + /no_think """; private static final String CHINESE_TO_ENGLISH_PROMPT = """ diff --git a/src/main/java/com/supervision/pdfqaserver/config/OllamaChatModelAspect.java b/src/main/java/com/supervision/pdfqaserver/config/OllamaChatModelAspect.java index e8724d7..9ebebdd 100644 --- a/src/main/java/com/supervision/pdfqaserver/config/OllamaChatModelAspect.java +++ b/src/main/java/com/supervision/pdfqaserver/config/OllamaChatModelAspect.java @@ -25,7 +25,14 @@ public class OllamaChatModelAspect { */ @Around("execution(* org.springframework.ai.chat.model.ChatModel.call(..))") public Object aroundMethodExecution(ProceedingJoinPoint joinPoint) throws Throwable { + String signature = joinPoint.getSignature().toString(); + // 获取原始参数 + Object[] args = joinPoint.getArgs(); + // 如果是String类型的call方法,修改其参数 + if (StrUtil.equals(signature, callStringMessage) && args.length > 0 && args[0] instanceof String originalPrompt) { + args[0] = originalPrompt + "/no_think"; + } // 执行原方法 Object result = joinPoint.proceed(); if (StrUtil.equals(model,"qwen3:30b-a3b") ) { diff --git a/src/main/java/com/supervision/pdfqaserver/dao/Neo4jRepository.java b/src/main/java/com/supervision/pdfqaserver/dao/Neo4jRepository.java index 6ecafd5..9b27f04 100644 --- a/src/main/java/com/supervision/pdfqaserver/dao/Neo4jRepository.java +++ b/src/main/java/com/supervision/pdfqaserver/dao/Neo4jRepository.java @@ -39,6 +39,9 @@ public class Neo4jRepository { while (result.hasNext()) { org.neo4j.driver.Record record = result.next(); // 从 Record 中取出三部分 + if (record.get("c") == null || record.get("r") == null || record.get("t") == null) { + continue; + } Node a = record.get("c").asNode(); Relationship r = record.get("r").asRelationship(); Node b = record.get("t").asNode(); diff --git a/src/main/java/com/supervision/pdfqaserver/service/impl/ChatServiceImpl.java b/src/main/java/com/supervision/pdfqaserver/service/impl/ChatServiceImpl.java index 57173eb..48e5dcc 100644 --- a/src/main/java/com/supervision/pdfqaserver/service/impl/ChatServiceImpl.java +++ b/src/main/java/com/supervision/pdfqaserver/service/impl/ChatServiceImpl.java @@ -56,19 +56,19 @@ public class ChatServiceImpl implements ChatService { List targetTypeList = domainMetadataService.list().stream().map(DomainMetadata::getTargetType).distinct().toList(); //将三个集合分别结合chineseEnglishWordsMap的key转化为value集合 - List sourceTypeListEnList = sourceTypeList.stream().map(chineseEnglishWordsMap::get).toList(); - List relationListEnList = relationList.stream().map(chineseEnglishWordsMap::get).toList(); - List targetTypeListEnList = targetTypeList.stream().map(chineseEnglishWordsMap::get).toList(); +// List sourceTypeEnList = sourceTypeList.stream().map(chineseEnglishWordsMap::get).toList(); +// List relationEnList = relationList.stream().map(chineseEnglishWordsMap::get).toList(); +// List targetTypeEnList = targetTypeList.stream().map(chineseEnglishWordsMap::get).toList(); //将三个集合分别转换为英文逗号分隔的字符串 - String sourceTypeListEn = String.join(",", sourceTypeListEnList); - String relationListEn = String.join(",", relationListEnList); - String targetTypeListEn = String.join(",", targetTypeListEnList); - log.info("sourceTypeListEn: {}, relationListEn: {}, targetTypeListEn: {}", sourceTypeListEn, relationListEn, targetTypeListEn); + String sourceTypeListEn = String.join(",", sourceTypeList); + String relationListEn = String.join(",", relationList); + String targetTypeListEn = String.join(",", targetTypeList); //LLM生成CYPHER SystemPromptTemplate textToCypherTemplate = new SystemPromptTemplate(PromptCache.promptMap.get(TEXT_TO_CYPHER)); Message textToCypherMessage = textToCypherTemplate.createMessage(Map.of(PROMPT_PARAM_SOURCE_TYPE_LIST, sourceTypeListEn, PROMPT_PARAM_RELATION_TYPE_LIST, relationListEn, PROMPT_PARAM_TARGET_TYPE_LIST, targetTypeListEn, PROMPT_PARAM_QUERY, userQuery)); + log.info("生成CYPHER语句的消息:{}", textToCypherMessage); String cypherJsonStr = ollamaChatModel.call(textToCypherMessage.getText()); log.info(cypherJsonStr); List cypherQueries;