diff --git a/src/main/java/com/xly/service/XlyErpService.java b/src/main/java/com/xly/service/XlyErpService.java index a3c7e78..03e4d40 100644 --- a/src/main/java/com/xly/service/XlyErpService.java +++ b/src/main/java/com/xly/service/XlyErpService.java @@ -2,6 +2,7 @@ package com.xly.service; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.db.Session; import com.alibaba.fastjson2.JSON; import com.xly.agent.ChatiAgent; import com.xly.agent.DynamicTableNl2SqlAiAgent; @@ -23,6 +24,7 @@ import dev.langchain4j.data.message.AiMessage; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.ollama.OllamaChatModel; import dev.langchain4j.service.AiServices; +import jnr.ffi.annotations.In; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.python.antlr.ast.Str; @@ -47,6 +49,11 @@ public class XlyErpService { private final DynamicExeDbService dynamicExeDbService; private final ToolMetaMapper toolMetaMapper; + //执行动态语句 执行异常的情况下 最多执行次数 + private final Integer maxRetries = 5; + //没有找到对应方法重走一次补偿次数 + public final static Integer maxTollRetries = 1; + /*** @@ -102,26 +109,43 @@ public class XlyErpService { // 调用方法,参数缺失部分提示,就直接使用方法返回的 if(session.getCurrentTool() != null && session.getSFunPrompts()!=null - ){ // 缺失的参数明细 + ){ + // 缺失的参数明细 sResponMessage = session.getSFunPrompts(); } if (session.getCurrentTool()== null){ sResponMessage = StrUtil.EMPTY; } +// //说明没有找到动态方法重新走一次 +// if(maxToolRetries==1 && session.getCurrentTool()== null){ +// Thread.sleep(1000); +// return erpUserInput( userInput, +// userId , +// sUserName , +// sBrandsId , +// sSubsidiaryId, +// sUserType, +// authorization, +// 0); +// } + + if (session.getCurrentTool()== null){ + sResponMessage = StrUtil.EMPTY; + } //5.执行工具方法后,清除记忆 if(session.getBCleanMemory()){ - operableChatMemoryProvider.clearSpecifiedMemory(userId); - session.setCurrentTool(null); - UserSceneSessionService.ERP_AGENT_CACHE.remove(userId); - UserSceneSessionService.CHAT_AGENT_CACHE.remove(userId); - session.setBCleanMemory(false); +// operableChatMemoryProvider.clearSpecifiedMemory(userId); +// session.setCurrentTool(null); +// UserSceneSessionService.ERP_AGENT_CACHE.remove(userId); +// UserSceneSessionService.CHAT_AGENT_CACHE.remove(userId); + doCleanUserMemory(session,userId); } // 6.找到方法并且本方法带表结构描述时,需要调用 自然语言转SQL智能体 if((ObjectUtil.isNotEmpty(session.getCurrentTool()) && ObjectUtil.isNotEmpty(session.getCurrentTool().getSInputTabelName()) && ObjectUtil.isNotEmpty(session.getCurrentTool().getSStructureMemo())) ){ - sResponMessage = getDynamicTableSql(session, input, userId, userInput); + sResponMessage = getDynamicTableSql(session, input, userId, userInput,maxRetries); } //如果返回空的进入闲聊模式 if (ObjectUtil.isEmpty(sResponMessage)){ @@ -167,46 +191,79 @@ public class XlyErpService { * @return java.lang.String * @Description 获取执行动态SQL **/ - private String getDynamicTableSql(UserSceneSession session,String input,String userId,String userInput){ - String resultExplain = StrUtil.EMPTY; + private String getDynamicTableSql(UserSceneSession session,String input,String userId,String userInput,Integer maxRetries){ + String resultExplain = "信息模糊,请提供更具体的问题或指令"; try{ - // 1. 构建自然语言转SQLAgent, - DynamicTableNl2SqlAiAgent aiDynamicTableNl2SqlAiAgent = createDynamicTableNl2SqlAiAgent(userId, input, session); - String tableNames = session.getCurrentTool().getSInputTabelName(); - // "订单表:viw_salsalesorder,客户信息表:elecustomer,结算方式表:sispayment,产品表(无单价,无金额,无数量):viw_product_sort,销售人员表:viw_sissalesman_depart"; - String tableStruct = session.getCurrentTool().getSStructureMemo(); - String rawSql = aiDynamicTableNl2SqlAiAgent.generateMysqlSql(userId,tableNames,tableStruct,userInput); - if (rawSql == null || rawSql.trim().isEmpty()) { - throw new SqlGenerateException("AI服务生成SQL失败,返回结果为空"); + int attempt = 0; + while (attempt < maxRetries) { + try{ + attempt++; + return getDynamicTableSqlExec( session, input, userId, userInput); + }catch (Exception e){ + if (attempt == maxRetries) { + return resultExplain; + } else { + return getDynamicTableSql( session, input, userId, userInput, maxRetries); + } + } } - // 2. 清理SQL多余符号 + 生产级强校验(核心安全保障,不可省略) - String cleanSql = SqlValidateUtil.cleanSqlSymbol(rawSql); - SqlValidateUtil.validateMysqlSql(cleanSql); - log.info("SQL清理并强校验通过,可执行SQL:{}", cleanSql); - // 4. 执行SQL获取结构化结果 -// Map params = new HashMap<>(); - List> sqlResult = dynamicExeDbService.findSql(new HashMap<>(),cleanSql); - // 5. 调用AI服务生成自然语言解释(传入表结构,让解释更贴合业务) - String resultJson = JSON.toJSONString(sqlResult); - resultExplain = aiDynamicTableNl2SqlAiAgent.explainSqlResult( - userId, - userInput, - cleanSql, - tableStruct, - resultJson - ); }catch (Exception e){ - resultExplain = "信息模糊,请提供更具体的问题或指令"; }finally { - session.setSceneSelected(false); - session.setBCleanMemory(true); + doCleanUserMemory(session,userId); } - log.info("动态表结构NL2SQL流程执行完成"); return resultExplain; } + /*** + * @Author 钱豹 + * @Date 19:59 2026/3/4 + * @Param [session, sUserId] + * @return void + * @Description 删除用户记忆 方法 + **/ + private void doCleanUserMemory(UserSceneSession session,String userId){ + operableChatMemoryProvider.clearSpecifiedMemory(userId); + session.setCurrentTool(null); + session.setSceneSelected(false); + UserSceneSessionService.ERP_AGENT_CACHE.remove(userId); + UserSceneSessionService.CHAT_AGENT_CACHE.remove(userId); + session.setBCleanMemory(false); + } + /*** + * @Author 钱豹 + * @Date 19:49 2026/3/4 + * @Param [session, input, userId, userInput] + * @return java.lang.String + * @Description 执行动态sSql + **/ + private String getDynamicTableSqlExec(UserSceneSession session,String input,String userId,String userInput){ + // 1. 构建自然语言转SQLAgent, + DynamicTableNl2SqlAiAgent aiDynamicTableNl2SqlAiAgent = createDynamicTableNl2SqlAiAgent(userId, input, session); + String tableNames = session.getCurrentTool().getSInputTabelName(); + // "订单表:viw_salsalesorder,客户信息表:elecustomer,结算方式表:sispayment,产品表(无单价,无金额,无数量):viw_product_sort,销售人员表:viw_sissalesman_depart"; + String tableStruct = session.getCurrentTool().getSStructureMemo(); + String rawSql = aiDynamicTableNl2SqlAiAgent.generateMysqlSql(userId,tableNames,tableStruct,userInput); + if (rawSql == null || rawSql.trim().isEmpty()) { + throw new SqlGenerateException("AI服务生成SQL失败,返回结果为空"); + } + // 2. 清理SQL多余符号 + 生产级强校验(核心安全保障,不可省略) + String cleanSql = SqlValidateUtil.cleanSqlSymbol(rawSql); + SqlValidateUtil.validateMysqlSql(cleanSql); + // 4. 执行SQL获取结构化结果 +// Map params = new HashMap<>(); + List> sqlResult = dynamicExeDbService.findSql(new HashMap<>(),cleanSql); + // 5. 调用AI服务生成自然语言解释(传入表结构,让解释更贴合业务) + String resultJson = JSON.toJSONString(sqlResult); + return aiDynamicTableNl2SqlAiAgent.explainSqlResult( + userId, + userInput, + cleanSql, + tableStruct, + resultJson + ); + } /*** * @Author 钱豹