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 2  
3 3 import cn.hutool.core.util.ObjectUtil;
4 4 import cn.hutool.core.util.StrUtil;
  5 +import cn.hutool.db.Session;
5 6 import com.alibaba.fastjson2.JSON;
6 7 import com.xly.agent.ChatiAgent;
7 8 import com.xly.agent.DynamicTableNl2SqlAiAgent;
... ... @@ -23,6 +24,7 @@ import dev.langchain4j.data.message.AiMessage;
23 24 import dev.langchain4j.model.chat.ChatLanguageModel;
24 25 import dev.langchain4j.model.ollama.OllamaChatModel;
25 26 import dev.langchain4j.service.AiServices;
  27 +import jnr.ffi.annotations.In;
26 28 import lombok.RequiredArgsConstructor;
27 29 import lombok.extern.slf4j.Slf4j;
28 30 import org.python.antlr.ast.Str;
... ... @@ -47,6 +49,11 @@ public class XlyErpService {
47 49 private final DynamicExeDbService dynamicExeDbService;
48 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 109 // 调用方法,参数缺失部分提示,就直接使用方法返回的
103 110 if(session.getCurrentTool() != null
104 111 && session.getSFunPrompts()!=null
105   - ){ // 缺失的参数明细
  112 + ){
  113 + // 缺失的参数明细
106 114 sResponMessage = session.getSFunPrompts();
107 115 }
108 116 if (session.getCurrentTool()== null){
109 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 135 //5.执行工具方法后,清除记忆
112 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 143 // 6.找到方法并且本方法带表结构描述时,需要调用 自然语言转SQL智能体
120 144 if((ObjectUtil.isNotEmpty(session.getCurrentTool())
121 145 && ObjectUtil.isNotEmpty(session.getCurrentTool().getSInputTabelName())
122 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 151 if (ObjectUtil.isEmpty(sResponMessage)){
... ... @@ -167,46 +191,79 @@ public class XlyErpService {
167 191 * @return java.lang.String
168 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 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 210 }catch (Exception e){
199   - resultExplain = "信息模糊,请提供更具体的问题或指令";
200 211 }finally {
201   - session.setSceneSelected(false);
202   - session.setBCleanMemory(true);
  212 + doCleanUserMemory(session,userId);
203 213 }
204   - log.info("动态表结构NL2SQL流程执行完成");
205 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 269 * @Author 钱豹
... ...