Commit a3f418f196c4ceb8849379f9f5e8c90e7b33fbb4

Authored by qianbao
1 parent 7b015560

1111

src/main/java/com/xly/service/XlyErpService.java
@@ -2,6 +2,7 @@ package com.xly.service; @@ -2,6 +2,7 @@ package com.xly.service;
2 2
3 import cn.hutool.core.util.ObjectUtil; 3 import cn.hutool.core.util.ObjectUtil;
4 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
  5 +import cn.hutool.db.Session;
5 import com.alibaba.fastjson2.JSON; 6 import com.alibaba.fastjson2.JSON;
6 import com.xly.agent.ChatiAgent; 7 import com.xly.agent.ChatiAgent;
7 import com.xly.agent.DynamicTableNl2SqlAiAgent; 8 import com.xly.agent.DynamicTableNl2SqlAiAgent;
@@ -23,6 +24,7 @@ import dev.langchain4j.data.message.AiMessage; @@ -23,6 +24,7 @@ import dev.langchain4j.data.message.AiMessage;
23 import dev.langchain4j.model.chat.ChatLanguageModel; 24 import dev.langchain4j.model.chat.ChatLanguageModel;
24 import dev.langchain4j.model.ollama.OllamaChatModel; 25 import dev.langchain4j.model.ollama.OllamaChatModel;
25 import dev.langchain4j.service.AiServices; 26 import dev.langchain4j.service.AiServices;
  27 +import jnr.ffi.annotations.In;
26 import lombok.RequiredArgsConstructor; 28 import lombok.RequiredArgsConstructor;
27 import lombok.extern.slf4j.Slf4j; 29 import lombok.extern.slf4j.Slf4j;
28 import org.python.antlr.ast.Str; 30 import org.python.antlr.ast.Str;
@@ -47,6 +49,11 @@ public class XlyErpService { @@ -47,6 +49,11 @@ public class XlyErpService {
47 private final DynamicExeDbService dynamicExeDbService; 49 private final DynamicExeDbService dynamicExeDbService;
48 private final ToolMetaMapper toolMetaMapper; 50 private final ToolMetaMapper toolMetaMapper;
49 51
  52 + //执行动态语句 执行异常的情况下 最多执行次数
  53 + private final Integer maxRetries = 5;
  54 + //没有找到对应方法重走一次补偿次数
  55 + public final static Integer maxTollRetries = 1;
  56 +
50 57
51 58
52 /*** 59 /***
@@ -102,26 +109,43 @@ public class XlyErpService { @@ -102,26 +109,43 @@ public class XlyErpService {
102 // 调用方法,参数缺失部分提示,就直接使用方法返回的 109 // 调用方法,参数缺失部分提示,就直接使用方法返回的
103 if(session.getCurrentTool() != null 110 if(session.getCurrentTool() != null
104 && session.getSFunPrompts()!=null 111 && session.getSFunPrompts()!=null
105 - ){ // 缺失的参数明细 112 + ){
  113 + // 缺失的参数明细
106 sResponMessage = session.getSFunPrompts(); 114 sResponMessage = session.getSFunPrompts();
107 } 115 }
108 if (session.getCurrentTool()== null){ 116 if (session.getCurrentTool()== null){
109 sResponMessage = StrUtil.EMPTY; 117 sResponMessage = StrUtil.EMPTY;
110 } 118 }
  119 +// //说明没有找到动态方法重新走一次
  120 +// if(maxToolRetries==1 && session.getCurrentTool()== null){
  121 +// Thread.sleep(1000);
  122 +// return erpUserInput( userInput,
  123 +// userId ,
  124 +// sUserName ,
  125 +// sBrandsId ,
  126 +// sSubsidiaryId,
  127 +// sUserType,
  128 +// authorization,
  129 +// 0);
  130 +// }
  131 +
  132 + if (session.getCurrentTool()== null){
  133 + sResponMessage = StrUtil.EMPTY;
  134 + }
111 //5.执行工具方法后,清除记忆 135 //5.执行工具方法后,清除记忆
112 if(session.getBCleanMemory()){ 136 if(session.getBCleanMemory()){
113 - operableChatMemoryProvider.clearSpecifiedMemory(userId);  
114 - session.setCurrentTool(null);  
115 - UserSceneSessionService.ERP_AGENT_CACHE.remove(userId);  
116 - UserSceneSessionService.CHAT_AGENT_CACHE.remove(userId);  
117 - session.setBCleanMemory(false); 137 +// operableChatMemoryProvider.clearSpecifiedMemory(userId);
  138 +// session.setCurrentTool(null);
  139 +// UserSceneSessionService.ERP_AGENT_CACHE.remove(userId);
  140 +// UserSceneSessionService.CHAT_AGENT_CACHE.remove(userId);
  141 + doCleanUserMemory(session,userId);
118 } 142 }
119 // 6.找到方法并且本方法带表结构描述时,需要调用 自然语言转SQL智能体 143 // 6.找到方法并且本方法带表结构描述时,需要调用 自然语言转SQL智能体
120 if((ObjectUtil.isNotEmpty(session.getCurrentTool()) 144 if((ObjectUtil.isNotEmpty(session.getCurrentTool())
121 && ObjectUtil.isNotEmpty(session.getCurrentTool().getSInputTabelName()) 145 && ObjectUtil.isNotEmpty(session.getCurrentTool().getSInputTabelName())
122 && ObjectUtil.isNotEmpty(session.getCurrentTool().getSStructureMemo())) 146 && ObjectUtil.isNotEmpty(session.getCurrentTool().getSStructureMemo()))
123 ){ 147 ){
124 - sResponMessage = getDynamicTableSql(session, input, userId, userInput); 148 + sResponMessage = getDynamicTableSql(session, input, userId, userInput,maxRetries);
125 } 149 }
126 //如果返回空的进入闲聊模式 150 //如果返回空的进入闲聊模式
127 if (ObjectUtil.isEmpty(sResponMessage)){ 151 if (ObjectUtil.isEmpty(sResponMessage)){
@@ -167,46 +191,79 @@ public class XlyErpService { @@ -167,46 +191,79 @@ public class XlyErpService {
167 * @return java.lang.String 191 * @return java.lang.String
168 * @Description 获取执行动态SQL 192 * @Description 获取执行动态SQL
169 **/ 193 **/
170 - private String getDynamicTableSql(UserSceneSession session,String input,String userId,String userInput){  
171 - String resultExplain = StrUtil.EMPTY; 194 + private String getDynamicTableSql(UserSceneSession session,String input,String userId,String userInput,Integer maxRetries){
  195 + String resultExplain = "信息模糊,请提供更具体的问题或指令";
172 try{ 196 try{
173 - // 1. 构建自然语言转SQLAgent,  
174 - DynamicTableNl2SqlAiAgent aiDynamicTableNl2SqlAiAgent = createDynamicTableNl2SqlAiAgent(userId, input, session);  
175 - String tableNames = session.getCurrentTool().getSInputTabelName();  
176 - // "订单表:viw_salsalesorder,客户信息表:elecustomer,结算方式表:sispayment,产品表(无单价,无金额,无数量):viw_product_sort,销售人员表:viw_sissalesman_depart";  
177 - String tableStruct = session.getCurrentTool().getSStructureMemo();  
178 - String rawSql = aiDynamicTableNl2SqlAiAgent.generateMysqlSql(userId,tableNames,tableStruct,userInput);  
179 - if (rawSql == null || rawSql.trim().isEmpty()) {  
180 - throw new SqlGenerateException("AI服务生成SQL失败,返回结果为空"); 197 + int attempt = 0;
  198 + while (attempt < maxRetries) {
  199 + try{
  200 + attempt++;
  201 + return getDynamicTableSqlExec( session, input, userId, userInput);
  202 + }catch (Exception e){
  203 + if (attempt == maxRetries) {
  204 + return resultExplain;
  205 + } else {
  206 + return getDynamicTableSql( session, input, userId, userInput, maxRetries);
  207 + }
  208 + }
181 } 209 }
182 - // 2. 清理SQL多余符号 + 生产级强校验(核心安全保障,不可省略)  
183 - String cleanSql = SqlValidateUtil.cleanSqlSymbol(rawSql);  
184 - SqlValidateUtil.validateMysqlSql(cleanSql);  
185 - log.info("SQL清理并强校验通过,可执行SQL:{}", cleanSql);  
186 - // 4. 执行SQL获取结构化结果  
187 -// Map<String,Object> params = new HashMap<>();  
188 - List<Map<String, Object>> sqlResult = dynamicExeDbService.findSql(new HashMap<>(),cleanSql);  
189 - // 5. 调用AI服务生成自然语言解释(传入表结构,让解释更贴合业务)  
190 - String resultJson = JSON.toJSONString(sqlResult);  
191 - resultExplain = aiDynamicTableNl2SqlAiAgent.explainSqlResult(  
192 - userId,  
193 - userInput,  
194 - cleanSql,  
195 - tableStruct,  
196 - resultJson  
197 - );  
198 }catch (Exception e){ 210 }catch (Exception e){
199 - resultExplain = "信息模糊,请提供更具体的问题或指令";  
200 }finally { 211 }finally {
201 - session.setSceneSelected(false);  
202 - session.setBCleanMemory(true); 212 + doCleanUserMemory(session,userId);
203 } 213 }
204 - log.info("动态表结构NL2SQL流程执行完成");  
205 return resultExplain; 214 return resultExplain;
206 } 215 }
207 216
  217 + /***
  218 + * @Author 钱豹
  219 + * @Date 19:59 2026/3/4
  220 + * @Param [session, sUserId]
  221 + * @return void
  222 + * @Description 删除用户记忆 方法
  223 + **/
  224 + private void doCleanUserMemory(UserSceneSession session,String userId){
  225 + operableChatMemoryProvider.clearSpecifiedMemory(userId);
  226 + session.setCurrentTool(null);
  227 + session.setSceneSelected(false);
  228 + UserSceneSessionService.ERP_AGENT_CACHE.remove(userId);
  229 + UserSceneSessionService.CHAT_AGENT_CACHE.remove(userId);
  230 + session.setBCleanMemory(false);
  231 + }
208 232
209 233
  234 + /***
  235 + * @Author 钱豹
  236 + * @Date 19:49 2026/3/4
  237 + * @Param [session, input, userId, userInput]
  238 + * @return java.lang.String
  239 + * @Description 执行动态sSql
  240 + **/
  241 + private String getDynamicTableSqlExec(UserSceneSession session,String input,String userId,String userInput){
  242 + // 1. 构建自然语言转SQLAgent,
  243 + DynamicTableNl2SqlAiAgent aiDynamicTableNl2SqlAiAgent = createDynamicTableNl2SqlAiAgent(userId, input, session);
  244 + String tableNames = session.getCurrentTool().getSInputTabelName();
  245 + // "订单表:viw_salsalesorder,客户信息表:elecustomer,结算方式表:sispayment,产品表(无单价,无金额,无数量):viw_product_sort,销售人员表:viw_sissalesman_depart";
  246 + String tableStruct = session.getCurrentTool().getSStructureMemo();
  247 + String rawSql = aiDynamicTableNl2SqlAiAgent.generateMysqlSql(userId,tableNames,tableStruct,userInput);
  248 + if (rawSql == null || rawSql.trim().isEmpty()) {
  249 + throw new SqlGenerateException("AI服务生成SQL失败,返回结果为空");
  250 + }
  251 + // 2. 清理SQL多余符号 + 生产级强校验(核心安全保障,不可省略)
  252 + String cleanSql = SqlValidateUtil.cleanSqlSymbol(rawSql);
  253 + SqlValidateUtil.validateMysqlSql(cleanSql);
  254 + // 4. 执行SQL获取结构化结果
  255 +// Map<String,Object> params = new HashMap<>();
  256 + List<Map<String, Object>> sqlResult = dynamicExeDbService.findSql(new HashMap<>(),cleanSql);
  257 + // 5. 调用AI服务生成自然语言解释(传入表结构,让解释更贴合业务)
  258 + String resultJson = JSON.toJSONString(sqlResult);
  259 + return aiDynamicTableNl2SqlAiAgent.explainSqlResult(
  260 + userId,
  261 + userInput,
  262 + cleanSql,
  263 + tableStruct,
  264 + resultJson
  265 + );
  266 + }
210 267
211 /*** 268 /***
212 * @Author 钱豹 269 * @Author 钱豹