Commit a3e3d13989a505e3f50c1f87e48c99130946e2cb

Authored by qianbao
1 parent 6886121d

AI添加问题 历史问题记录

src/main/java/com/xly/agent/ErpAiAgent.java
@@ -14,14 +14,23 @@ public interface ErpAiAgent { @@ -14,14 +14,23 @@ public interface ErpAiAgent {
14 1. 方法匹配:先精准拆解用户查询的核心业务意图,再自动匹配唯一符合用户问题的工具方法(MethodNo),禁止自创,规则如下; 14 1. 方法匹配:先精准拆解用户查询的核心业务意图,再自动匹配唯一符合用户问题的工具方法(MethodNo),禁止自创,规则如下;
15 1.1 匹配方法时,无需考虑工具描述(@TOOL)中 1.必填参数,2.选填参数,示例,parameters内容 四个部分的内容; 15 1.1 匹配方法时,无需考虑工具描述(@TOOL)中 1.必填参数,2.选填参数,示例,parameters内容 四个部分的内容;
16 1.2 匹配方法时,只关注工具描述(@TOOL)中 “当用户” 和 “时,必须调用本工具”两个短语之间的内容; 16 1.2 匹配方法时,只关注工具描述(@TOOL)中 “当用户” 和 “时,必须调用本工具”两个短语之间的内容;
17 - 1.3 调用工具前,不需要询问用户提供缺失的参数  
18 2. 参数提取:提取该工具的全部参数,与描述完全一致,严格按标注类型赋值,规则如下: 17 2. 参数提取:提取该工具的全部参数,与描述完全一致,严格按标注类型赋值,规则如下:
19 2.1 数字无引号,为空时禁止赋值0; 18 2.1 数字无引号,为空时禁止赋值0;
20 2.2 如果有空格需要去掉空格后再提取。 19 2.2 如果有空格需要去掉空格后再提取。
  20 + 2.3 每次都需要进行参数提取
21 """) 21 """)
22 @UserMessage("用户输入:{{userInput}}") 22 @UserMessage("用户输入:{{userInput}}")
23 String chat(@MemoryId String userId, @V("userInput") String userInput); 23 String chat(@MemoryId String userId, @V("userInput") String userInput);
24 24
  25 + @SystemMessage("{{stoolDesc}}")
  26 + @UserMessage("用户输入:{{userInput}}")
  27 + String chatCurrentTool(@MemoryId String userId,
  28 + @V("userInput") String userInput,
  29 + @V("sMethodNo") String sMethodNo,
  30 + @V("sMethodName") String sMethodName,
  31 + @V("stoolDesc") String stoolDesc
  32 + );
  33 +
25 /** 34 /**
26 * 动态表结构:自然语言解释SQL执行结果 35 * 动态表结构:自然语言解释SQL执行结果
27 * 入参:用户问题、执行的SQL、表结构、JSON格式结果 36 * 入参:用户问题、执行的SQL、表结构、JSON格式结果
src/main/java/com/xly/entity/UserSceneSession.java
@@ -63,6 +63,9 @@ public class UserSceneSession { @@ -63,6 +63,9 @@ public class UserSceneSession {
63 private String sFunPrompts; //方法返回的参数补全提示 63 private String sFunPrompts; //方法返回的参数补全提示
64 64
65 private Boolean bCleanMemory = false; 65 private Boolean bCleanMemory = false;
  66 +
  67 + private Map<String, Object> args;
  68 +
66 /** 69 /**
67 * 构建场景选择提示语:展示权限内场景,引导用户选择 70 * 构建场景选择提示语:展示权限内场景,引导用户选择
68 * @return 自然语言提示语 71 * @return 自然语言提示语
src/main/java/com/xly/service/XlyErpService.java
@@ -83,11 +83,12 @@ public class XlyErpService { @@ -83,11 +83,12 @@ public class XlyErpService {
83 String authorization) { 83 String authorization) {
84 String sceneName = StrUtil.EMPTY; 84 String sceneName = StrUtil.EMPTY;
85 String methodName = StrUtil.EMPTY; 85 String methodName = StrUtil.EMPTY;
  86 + UserSceneSession session=null;
86 try { 87 try {
87 // 0. 预处理用户输入:去空格、转小写(方便匹配) 88 // 0. 预处理用户输入:去空格、转小写(方便匹配)
88 String input= InputPreprocessor.preprocessWithCommons(userInput); 89 String input= InputPreprocessor.preprocessWithCommons(userInput);
89 // 1. 初始化用户场景会话(权限内场景) 90 // 1. 初始化用户场景会话(权限内场景)
90 - UserSceneSession session = userSceneSessionService.getUserSceneSession(userId,sUserName,sBrandsId,sSubsidiaryId,sUserType,authorization); 91 + session = userSceneSessionService.getUserSceneSession(userId,sUserName,sBrandsId,sSubsidiaryId,sUserType,authorization);
91 session.setAuthorization(authorization); 92 session.setAuthorization(authorization);
92 session.setSFunPrompts(null); 93 session.setSFunPrompts(null);
93 sceneName = ObjectUtil.isNotEmpty(session.getCurrentScene())?session.getCurrentScene().getSSceneName():StrUtil.EMPTY; 94 sceneName = ObjectUtil.isNotEmpty(session.getCurrentScene())?session.getCurrentScene().getSSceneName():StrUtil.EMPTY;
@@ -102,9 +103,8 @@ public class XlyErpService { @@ -102,9 +103,8 @@ public class XlyErpService {
102 if (session.getCurrentScene() != null 103 if (session.getCurrentScene() != null
103 && Objects.equals(session.getCurrentScene().getSSceneNo(), "ChatZone")) 104 && Objects.equals(session.getCurrentScene().getSSceneNo(), "ChatZone"))
104 { 105 {
105 - return getChatiAgent(input, session,StrUtil.EMPTY); 106 + return getChatiAgent(input, session);
106 } 107 }
107 -  
108 // 3. 未选场景:先展示场景选择界面,处理用户序号选择 108 // 3. 未选场景:先展示场景选择界面,处理用户序号选择
109 if (!session.isSceneSelected() && ValiDataUtil.me().isPureNumber(input)){ 109 if (!session.isSceneSelected() && ValiDataUtil.me().isPureNumber(input)){
110 // 3.1 尝试处理场景选择(输入序号则匹配,否则展示选择提示) 110 // 3.1 尝试处理场景选择(输入序号则匹配,否则展示选择提示)
@@ -114,49 +114,44 @@ public class XlyErpService { @@ -114,49 +114,44 @@ public class XlyErpService {
114 ErpAiAgent aiAgent = createErpAiAgent(userId, input, session); 114 ErpAiAgent aiAgent = createErpAiAgent(userId, input, session);
115 // 没有选择到场景,进闲聊模式 115 // 没有选择到场景,进闲聊模式
116 if (aiAgent == null){ 116 if (aiAgent == null){
117 - return getChatiAgent (input, session,StrUtil.EMPTY); 117 + return getChatiAgent (input,session);
118 } 118 }
119 -// List<ChatMessage> chatMessage = operableChatMemoryProvider.getCurrentChatMessages(session.getUserId());  
120 - String sResponMessage = aiAgent.chat(userId, input);  
121 -// List<ChatMessage> chatMessage2 = operableChatMemoryProvider.getCurrentChatMessages(session.getUserId());  
122 - String sResponMessageOld = StrUtil.EMPTY;  
123 -// 调用方法,参数缺失部分提示,就直接使用方法返回的  
124 - if(session.getCurrentTool() != null  
125 - && session.getSFunPrompts()!=null 119 + //用户输入添加方法
  120 + String sResponMessage = StrUtil.EMPTY;
  121 + if(ObjectUtil.isNotEmpty(session.getCurrentTool())
  122 + && !ObjectUtil.isNotEmpty(session.getCurrentTool().getSInputTabelName())
126 ){ 123 ){
127 - // 缺失的参数明细  
128 - sResponMessage = session.getSFunPrompts();  
129 - }  
130 - if (session.getCurrentTool()== null){  
131 - sResponMessageOld = sResponMessage;  
132 - sResponMessage = StrUtil.EMPTY;  
133 - }  
134 - //5.执行工具方法后,清除记忆  
135 - if(session.getBCleanMemory()){  
136 - doCleanUserMemory(session,userId); 124 + input = session.getCurrentTool().getSMethodName()+","+input;
  125 + sResponMessage = aiAgent.chatCurrentTool(userId, input,session.getCurrentTool().getSMethodNo(),session.getCurrentTool().getSMethodName(),session.getCurrentTool().getStoolDesc());
  126 + }else{
  127 + sResponMessage = aiAgent.chat(userId, input);
137 } 128 }
138 -// 6.找到方法并且本方法带表结构描述时,需要调用 自然语言转SQL智能体 129 +
  130 +// 1.找到方法并且本方法带表结构描述时,需要调用 自然语言转SQL智能体
139 if((ObjectUtil.isNotEmpty(session.getCurrentTool()) 131 if((ObjectUtil.isNotEmpty(session.getCurrentTool())
140 && ObjectUtil.isNotEmpty(session.getCurrentTool().getSInputTabelName()) 132 && ObjectUtil.isNotEmpty(session.getCurrentTool().getSInputTabelName())
141 && ObjectUtil.isNotEmpty(session.getCurrentTool().getSStructureMemo())) 133 && ObjectUtil.isNotEmpty(session.getCurrentTool().getSStructureMemo()))
142 ){ 134 ){
143 sResponMessage = getDynamicTableSql(session, input, userId, userInput,0,StrUtil.EMPTY,StrUtil.EMPTY,"0",StrUtil.EMPTY, aiAgent); 135 sResponMessage = getDynamicTableSql(session, input, userId, userInput,0,StrUtil.EMPTY,StrUtil.EMPTY,"0",StrUtil.EMPTY, aiAgent);
144 - }  
145 - //如果返回空的进入闲聊模式  
146 - if (ObjectUtil.isEmpty(sResponMessage)){  
147 - return getChatiAgent (input, session,sResponMessageOld);  
148 - }  
149 - if (session.getCurrentScene()!= null ){  
150 - return AiResponseDTO.builder().aiText(sResponMessage)  
151 - .sSceneName(session.getCurrentScene().getSSceneName())  
152 - .sMethodName((ObjectUtil.isEmpty(session.getCurrentTool()))?StrUtil.EMPTY:session.getCurrentTool().getSMethodName())  
153 - .sReturnType(ReturnTypeCode.MAKEDOWN.getCode())  
154 - .build();  
155 - }else { 136 + return AiResponseDTO.builder().sSceneName(sceneName).sMethodName(methodName).aiText(sResponMessage).sReturnType(ReturnTypeCode.HTML.getCode()).build();
  137 + } else if (ObjectUtil.isNotEmpty(session.getCurrentTool())) {
  138 + //2.处理工具参数采集结束后业务逻辑处理
  139 + //调用方法,参数缺失部分提示,就直接使用方法返回的
  140 + sResponMessage = dynamicToolProvider.doDynamicTool(session.getCurrentTool(),session);
  141 + return AiResponseDTO.builder().sSceneName(sceneName).sMethodName(methodName).aiText(sResponMessage).sReturnType(ReturnTypeCode.HTML.getCode()).build();
  142 + }else if(session.getCurrentScene()== null ){
156 return AiResponseDTO.builder().sSceneName(sceneName).sMethodName(methodName).aiText("当前场景:没有选择 退回当前场景 请输入 "+ CommonConstant.RESET + sResponMessage).sReturnType(ReturnTypeCode.HTML.getCode()).build(); 143 return AiResponseDTO.builder().sSceneName(sceneName).sMethodName(methodName).aiText("当前场景:没有选择 退回当前场景 请输入 "+ CommonConstant.RESET + sResponMessage).sReturnType(ReturnTypeCode.HTML.getCode()).build();
  144 + }else{
  145 + return getChatiAgent (input, session);
157 } 146 }
158 } catch (Exception e) { 147 } catch (Exception e) {
  148 + e.printStackTrace();
159 return AiResponseDTO.builder().sSceneName(sceneName).sMethodName(methodName).aiText("系统异常:" + e.getMessage() + ",请稍后重试!").sReturnType(ReturnTypeCode.HTML.getCode()).build(); 149 return AiResponseDTO.builder().sSceneName(sceneName).sMethodName(methodName).aiText("系统异常:" + e.getMessage() + ",请稍后重试!").sReturnType(ReturnTypeCode.HTML.getCode()).build();
  150 + }finally {
  151 + //5.执行工具方法后,清除记忆
  152 + if(session !=null && session.getBCleanMemory()){
  153 + doCleanUserMemory(session,userId);
  154 + }
160 } 155 }
161 } 156 }
162 157
@@ -170,6 +165,7 @@ public class XlyErpService { @@ -170,6 +165,7 @@ public class XlyErpService {
170 UserSceneSession session = userSceneSessionService.getUserSceneSession(userId,sUserName,sBrandsId,sSubsidiaryId,sUserType,authorization); 165 UserSceneSession session = userSceneSessionService.getUserSceneSession(userId,sUserName,sBrandsId,sSubsidiaryId,sUserType,authorization);
171 operableChatMemoryProvider.clearSpecifiedMemory(userId); 166 operableChatMemoryProvider.clearSpecifiedMemory(userId);
172 session.setCurrentTool(null); 167 session.setCurrentTool(null);
  168 + session.setArgs(null);
173 session.setSUserQuestionList(new ArrayList<>()); 169 session.setSUserQuestionList(new ArrayList<>());
174 UserSceneSessionService.ERP_AGENT_CACHE.remove(userId); 170 UserSceneSessionService.ERP_AGENT_CACHE.remove(userId);
175 UserSceneSessionService.CHAT_AGENT_CACHE.remove(userId); 171 UserSceneSessionService.CHAT_AGENT_CACHE.remove(userId);
@@ -246,6 +242,7 @@ public class XlyErpService { @@ -246,6 +242,7 @@ public class XlyErpService {
246 operableChatMemoryProvider.clearSpecifiedMemory(userId); 242 operableChatMemoryProvider.clearSpecifiedMemory(userId);
247 session.setCurrentTool(null); 243 session.setCurrentTool(null);
248 session.setSUserQuestionList(new ArrayList<>()); 244 session.setSUserQuestionList(new ArrayList<>());
  245 + session.setArgs(new HashMap<>());
249 // session.setSceneSelected(false); 246 // session.setSceneSelected(false);
250 UserSceneSessionService.ERP_AGENT_CACHE.remove(userId); 247 UserSceneSessionService.ERP_AGENT_CACHE.remove(userId);
251 UserSceneSessionService.CHAT_AGENT_CACHE.remove(userId); 248 UserSceneSessionService.CHAT_AGENT_CACHE.remove(userId);
@@ -593,12 +590,9 @@ public class XlyErpService { @@ -593,12 +590,9 @@ public class XlyErpService {
593 * @return java.lang.String 590 * @return java.lang.String
594 * @Description 获取智普通智能体 591 * @Description 获取智普通智能体
595 **/ 592 **/
596 - private AiResponseDTO getChatiAgent (String input,UserSceneSession session,String sResponMessageOld){ 593 + private AiResponseDTO getChatiAgent (String input,UserSceneSession session){
597 String sceneName = ObjectUtil.isNotEmpty(session.getCurrentScene())?session.getCurrentScene().getSSceneName():StrUtil.EMPTY; 594 String sceneName = ObjectUtil.isNotEmpty(session.getCurrentScene())?session.getCurrentScene().getSSceneName():StrUtil.EMPTY;
598 String methodName = ObjectUtil.isNotEmpty(session.getCurrentTool())?session.getCurrentTool().getSMethodName():"随便聊聊"; 595 String methodName = ObjectUtil.isNotEmpty(session.getCurrentTool())?session.getCurrentTool().getSMethodName():"随便聊聊";
599 - if(ObjectUtil.isNotEmpty(sResponMessageOld)){  
600 - return AiResponseDTO.builder().sSceneName(sceneName).sMethodName(methodName).aiText(sResponMessageOld).systemText(StrUtil.EMPTY).sReturnType(ReturnTypeCode.HTML.getCode()).build();  
601 - }  
602 ChatiAgent chatiAgent = UserSceneSessionService.CHAT_AGENT_CACHE.get(session.getUserId()); 596 ChatiAgent chatiAgent = UserSceneSessionService.CHAT_AGENT_CACHE.get(session.getUserId());
603 if(ObjectUtil.isEmpty(chatiAgent)){ 597 if(ObjectUtil.isEmpty(chatiAgent)){
604 chatiAgent = AiServices.builder(ChatiAgent.class) 598 chatiAgent = AiServices.builder(ChatiAgent.class)
src/main/java/com/xly/tool/DynamicToolProvider.java
1 package com.xly.tool; 1 package com.xly.tool;
2 2
3 3
  4 +import cn.hutool.core.util.NumberUtil;
4 import cn.hutool.core.util.ObjectUtil; 5 import cn.hutool.core.util.ObjectUtil;
5 import cn.hutool.core.util.StrUtil; 6 import cn.hutool.core.util.StrUtil;
6 import cn.hutool.json.JSONUtil; 7 import cn.hutool.json.JSONUtil;
@@ -165,7 +166,7 @@ public class DynamicToolProvider implements ToolProvider { @@ -165,7 +166,7 @@ public class DynamicToolProvider implements ToolProvider {
165 pr.setSParamValue(sAIshowfieldShowAll.get(i).get("sName").toString()); 166 pr.setSParamValue(sAIshowfieldShowAll.get(i).get("sName").toString());
166 pr.setSParam(sAIshowfieldShowAll.get(i).get("label").toString()); 167 pr.setSParam(sAIshowfieldShowAll.get(i).get("label").toString());
167 pr.setBEmpty(false); 168 pr.setBEmpty(false);
168 - pr.setSType("array"); 169 + pr.setSType(getDefType(sAIshowfieldShowAll.get(i).get("sName").toString()));
169 if("sSlaveId".equals(sAIshowfieldShowAll.get(i).get("sName"))){ 170 if("sSlaveId".equals(sAIshowfieldShowAll.get(i).get("sName"))){
170 pr.setSParam("sSlaveId"); 171 pr.setSParam("sSlaveId");
171 } 172 }
@@ -186,35 +187,56 @@ public class DynamicToolProvider implements ToolProvider { @@ -186,35 +187,56 @@ public class DynamicToolProvider implements ToolProvider {
186 meta.setParamRuleListAll(paramRuleListAll); 187 meta.setParamRuleListAll(paramRuleListAll);
187 } 188 }
188 189
  190 + private String getDefType(String sColumn){
  191 + if(sColumn.startsWith("d")){
  192 + return "double";
  193 + }else{
  194 + return "string";
  195 + }
  196 + }
189 @Override 197 @Override
190 public ToolProviderResult provideTools(ToolProviderRequest request) { 198 public ToolProviderResult provideTools(ToolProviderRequest request) {
191 -// List<ToolSpecification> specs = new ArrayList<>();  
192 String sUserId = request.chatMemoryId().toString(); 199 String sUserId = request.chatMemoryId().toString();
193 Map<ToolSpecification, ToolExecutor> executors = new HashMap<>(); 200 Map<ToolSpecification, ToolExecutor> executors = new HashMap<>();
194 - // sceneToolCacheMap.get(sSceneIdMap.get(sUserId));  
195 - //获取Session 201 + // 获取Session
196 UserSceneSession session = UserSceneSessionService.USER_SCENE_SESSION_CACHE.get(sUserId); 202 UserSceneSession session = UserSceneSessionService.USER_SCENE_SESSION_CACHE.get(sUserId);
197 - //过滤对应的权限方法 203 +
  204 + // 过滤对应的权限方法
198 List<ToolSpecificationHolder> datalist = new ArrayList<>(); 205 List<ToolSpecificationHolder> datalist = new ArrayList<>();
199 List<ToolMeta> toolMetaAll = new ArrayList<>(); 206 List<ToolMeta> toolMetaAll = new ArrayList<>();
200 - if(session.getCurrentTool()!=null){ 207 +
  208 + // 确保 currentTool 不为空,或者 authTool 有数据
  209 + if(session.getCurrentTool() != null){
201 toolMetaAll.add(session.getCurrentTool()); 210 toolMetaAll.add(session.getCurrentTool());
202 - }else{ 211 + log.info("使用 currentTool: {}", session.getCurrentTool().getSMethodNo());
  212 + } else {
203 toolMetaAll = session.getAuthTool(); 213 toolMetaAll = session.getAuthTool();
  214 + log.info("使用 authTool, 数量: {}", toolMetaAll.size());
204 } 215 }
  216 +
205 if(ObjectUtil.isNotEmpty(toolMetaAll)){ 217 if(ObjectUtil.isNotEmpty(toolMetaAll)){
206 - toolMetaAll = toolMetaAll.stream().filter(to-> to.getSSceneId().equals(sSceneIdMap.get(sUserId))).collect(Collectors.toUnmodifiableList()); 218 + toolMetaAll = toolMetaAll.stream()
  219 + .filter(to -> to.getSSceneId().equals(sSceneIdMap.get(sUserId)))
  220 + .collect(Collectors.toUnmodifiableList());
  221 +
207 if(ObjectUtil.isNotEmpty(toolMetaAll)){ 222 if(ObjectUtil.isNotEmpty(toolMetaAll)){
208 - toolMetaAll.forEach(to->{  
209 - datalist.add(toolCache.get(to.getSMethodNo())); 223 + toolMetaAll.forEach(to -> {
  224 + ToolSpecificationHolder holder = toolCache.get(to.getSMethodNo());
  225 + if (holder != null) {
  226 + datalist.add(holder);
  227 + log.debug("添加工具到提供器: {}", to.getSMethodNo());
  228 + } else {
  229 + log.warn("工具缓存缺失: {}", to.getSMethodNo());
  230 + }
210 }); 231 });
211 } 232 }
212 } 233 }
213 - datalist.forEach(holder->{  
214 -// specs.add(holder.getToolSpecification());  
215 - executors.put(holder.getToolSpecification(),holder.getToolExecutor());  
216 -// executors.put(holder.getToolSpecification(), holder.getToolExecutor()); 234 +
  235 + // 将工具添加到返回结果中
  236 + datalist.forEach(holder -> {
  237 + executors.put(holder.getToolSpecification(), holder.getToolExecutor());
217 }); 238 });
  239 + log.info("provideTools 返回工具数量: {}", executors.size());
218 return ToolProviderResult.builder().addAll(executors).build(); 240 return ToolProviderResult.builder().addAll(executors).build();
219 } 241 }
220 242
@@ -240,10 +262,10 @@ public class DynamicToolProvider implements ToolProvider { @@ -240,10 +262,10 @@ public class DynamicToolProvider implements ToolProvider {
240 // stoolDesc.append(",").append("并选择数据后执行["+meta.getSControlName()+"]操作"); 262 // stoolDesc.append(",").append("并选择数据后执行["+meta.getSControlName()+"]操作");
241 // } 263 // }
242 stoolDesc.append("时,必须调用本工具").append(meta.getSMethodNo()).append(",").append(meta.getStoolDesc()); 264 stoolDesc.append("时,必须调用本工具").append(meta.getSMethodNo()).append(",").append(meta.getStoolDesc());
243 - if (meta.getIBizType()==4){  
244 - stoolDesc.append(",").append("并选择数据后执行 "+meta.getSControlName()+" 操作");  
245 -// .append("1.全部数据生成多个单据 回复【全部确认】;2.全部数据生成一个单据 回复【合并确认】;3.按自然语义描述生成一个单据 如"1,3行确认"");  
246 - } 265 +// if (meta.getIBizType()==4){
  266 +// stoolDesc.append(",").append("并选择数据后执行 "+meta.getSControlName()+" 操作");
  267 +//// .append("1.全部数据生成多个单据 回复【全部确认】;2.全部数据生成一个单据 回复【合并确认】;3.按自然语义描述生成一个单据 如"1,3行确认"");
  268 +// }
247 } 269 }
248 270
249 try { 271 try {
@@ -504,115 +526,129 @@ public class DynamicToolProvider implements ToolProvider { @@ -504,115 +526,129 @@ public class DynamicToolProvider implements ToolProvider {
504 } 526 }
505 return paramRuleDataAll; 527 return paramRuleDataAll;
506 } 528 }
507 -  
508 -  
509 /*** 529 /***
510 * @Author 钱豹 530 * @Author 钱豹
511 - * @Date 15:09 2026/1/30 531 + * @Date 12:37 2026/3/16
512 * @Param [meta] 532 * @Param [meta]
513 * @return dev.langchain4j.service.tool.ToolExecutor 533 * @return dev.langchain4j.service.tool.ToolExecutor
514 - * @Description 创建 ToolExecutor,内部包含参数自动补全与校验逻辑(创建执行器) 534 + * @Description 参数采集执行器
515 **/ 535 **/
516 private ToolExecutor createToolExecutor(ToolMeta meta) { 536 private ToolExecutor createToolExecutor(ToolMeta meta) {
  537 + log.info("创建工具执行器: {}", meta.getSMethodNo());
  538 +
517 return (toolExecutionRequest, memoryId) -> { 539 return (toolExecutionRequest, memoryId) -> {
  540 + log.info("===== 工具执行器开始执行 =====");
  541 + log.info("工具编号: {}", meta.getSMethodNo());
  542 + log.info("工具名称: {}", meta.getSMethodName());
  543 + log.info("memoryId: {}", memoryId);
  544 + log.info("请求参数: {}", toolExecutionRequest.arguments());
  545 +
518 UserSceneSession session = UserSceneSessionService.USER_SCENE_SESSION_CACHE.get(memoryId.toString()); 546 UserSceneSession session = UserSceneSessionService.USER_SCENE_SESSION_CACHE.get(memoryId.toString());
519 - session.setCurrentTool(meta); // 标记一下找到了相应方法  
520 - session.setSFunPrompts(null);  
521 - // 检查条件 - 如果条件满足,直接返回成功结果,不再执行后续逻辑  
522 - if (ObjectUtil.isNotEmpty(meta.getSInputTabelName())  
523 - && ObjectUtil.isNotEmpty(meta.getSStructureMemo())) {  
524 - // 直接返回成功结果,阻止后续执行  
525 - return createEarlySuccessResult(toolExecutionRequest, "执行成功,终止后续执行");  
526 - } 547 + session.setCurrentTool(meta); // 标记当前工具
527 548
528 - // 1. 解析模型传入的参数  
529 - Map<String, Object> args; 549 + // 1. 解析参数
  550 + Map<String, Object> argsNew;
530 try { 551 try {
531 - args = objectMapper.readValue(toolExecutionRequest.arguments(), new TypeReference<>() {}); 552 + argsNew = objectMapper.readValue(toolExecutionRequest.arguments(), new TypeReference<>() {});
  553 + log.info("解析后的参数: {}", argsNew);
532 } catch (Exception e) { 554 } catch (Exception e) {
533 - String errorMsg = "参数 JSON 解析失败,请检查参数格式是否正确。"  
534 - + "错误详情:" + e.getMessage();  
535 - log.warn("参数解析失败,tool={}, args={}", meta.getSMethodNo(), toolExecutionRequest.arguments(), e); 555 + log.error("参数解析失败", e);
  556 + String errorMsg = "参数解析失败,请重新输入";
536 return String.valueOf(errorResult(toolExecutionRequest, errorMsg)); 557 return String.valueOf(errorResult(toolExecutionRequest, errorMsg));
537 } 558 }
538 -// Map<String, Object> argsOld = DeepCopyUtils.deepCopy(args);  
539 - List<ParamRule> paramRuleData = meta.getParamRuleListAll();  
540 -  
541 - // 2 【补全动态参数】动态参数补全  
542 - try{  
543 - args = applyValues(args, meta.getParamRuleListCheck());  
544 - }catch (Exception e){  
545 - log.error("返回信息",e);  
546 - String sTsMsg = e.getMessage();  
547 - session.setSFunPrompts(sTsMsg);  
548 - //存在多个数据返回大模型,需要继续盘问选择出唯一结果  
549 - return String.valueOf(askUserResult(toolExecutionRequest, sTsMsg));  
550 - }  
551 -  
552 - // 2.1 【自动补全】应用参数的默认值  
553 - args = applyDefaultValues(args, paramRuleData);  
554 -  
555 - // 3. 【自动校验】检查必填项  
556 - List<String> missing = checkRequiredParams(args, paramRuleData);  
557 - if (!missing.isEmpty()) {  
558 - // 4.1 参数缺失,生成“提问”消息,直接返给客户  
559 - String askMsg = buildAskUserMessage(meta, missing,args);  
560 - session.setSFunPrompts(askMsg);  
561 - return String.valueOf(askUserResult(toolExecutionRequest, askMsg)); 559 + Map<String, Object> args = session.getArgs();
  560 + if(ObjectUtil.isEmpty(args)){
  561 + args = new HashMap<>();
562 } 562 }
  563 + Map<String, Object> finalArgs = args;
  564 + argsNew.forEach((k, v)->{
  565 + //获取对应的英文参数
  566 + List<ParamRule> data = meta.getParamRuleList().stream().filter(one->one.getSParam().equals(k)).collect(Collectors.toUnmodifiableList());
  567 + if(ObjectUtil.isNotEmpty(data) && data.size()>0){
  568 + finalArgs.remove(data.get(0).getSParamValue());
  569 + finalArgs.remove(data.get(0).getSParam());
  570 + }
  571 + if(ObjectUtil.isNotEmpty(v)){
  572 + finalArgs.put(k,v);
  573 + }
  574 + });
  575 + session.setArgs(finalArgs);
  576 + // 2. 获取必填参数规则
  577 +// List<ParamRule> sParamRules = meta.getParamRuleListCheck();
  578 +// List<String> missingParams = getRequiredParams(sParamRules);
  579 +// String collectPrompt = buildCollectParamsPrompt(meta, missingParams, args);
  580 +// log.info("参数缺失,返回收集提示: {}", collectPrompt);
  581 + return String.valueOf(successResult(toolExecutionRequest, JSONUtil.toJsonStr(finalArgs)));
  582 + };
  583 + }
563 584
564 - // 6. 【最终确认信息】所有检测通过后,需要和客户确认交互  
565 - List<ChatMessage> chatMessage = operableChatMemoryProvider.getCurrentChatMessages(memoryId.toString());  
566 - ChatMessage userMessage = getLasterUserMssage(chatMessage);  
567 - String input = StrUtil.replace(userMessage.text(),"用户输入:",StrUtil.EMPTY); 585 + public String doDynamicTool(ToolMeta meta,UserSceneSession session) {
  586 + List<ParamRule> paramRuleData = meta.getParamRuleListAll();
  587 + Map<String, Object> args = session.getArgs();
  588 + Map<String, Object> argsOld = new HashMap<>(args);
  589 + // 2 【补全动态参数】动态参数补全
  590 + try{
  591 + args = applyValues(args, meta.getParamRuleListCheck());
  592 + }catch (Exception e){
  593 + log.error("返回信息",e);
  594 + String sTsMsg = e.getMessage();
  595 + return sTsMsg;
  596 + }
  597 + // 2.1 【自动补全】应用参数的默认值
  598 + args = applyDefaultValues(args, paramRuleData);
  599 + session.setArgs(args);
  600 + // 3. 【自动校验】检查必填项
  601 + List<String> missing = checkRequiredParams(args, paramRuleData);
  602 + if (!missing.isEmpty()) {
  603 + // 4.1 参数缺失,生成“提问”消息,直接返给客户
  604 + String askMsg = buildAskUserMessage(meta, missing,args);
  605 + return askMsg;
  606 + }
568 607
  608 + // 6. 【最终确认信息】所有检测通过后,需要和客户确认交互
  609 + List<ChatMessage> chatMessage = operableChatMemoryProvider.getCurrentChatMessages(session.getUserId());
  610 + ChatMessage userMessage = getLasterUserMssage(chatMessage);
  611 + String input = StrUtil.replace(userMessage.text(),"用户输入:",StrUtil.EMPTY);
569 // {"0":"查询","1":"执行"} 查询不需要确认 612 // {"0":"查询","1":"执行"} 查询不需要确认
570 - Boolean isConfirmed = isConfirmed(input) || input.contains("生成") || input.contains("确认");  
571 - //判断是否生成数据  
572 - List<Map<String,Object>> sRowData = new ArrayList<>();  
573 - String sHandleType = "merge";  
574 - if(4== meta.getIBizType() && ObjectUtil.isNotEmpty(session.getCurrentRowData())){  
575 - Map<String,Object> sRowDataMap = UserChoseIntentParser.getSelectedRows( input, session.getCurrentRowData());  
576 - sRowData = (List<Map<String, Object>>) sRowDataMap.get("sRowData");  
577 - sHandleType = sRowDataMap.get("sHandleType").toString();  
578 - }  
579 - //{"1":"存储过程","2":"SQL查询","3":"第三方API","4":"ERP未清","5":"ERP列表(报表)","6":"ERP单据","7":"其它","8":"自然语言TEXT2SQL"}  
580 -  
581 - if((isConfirmed && (4== meta.getIBizType() ||1== meta.getIBizType()))  
582 - || 2== meta.getIBizType()  
583 - || 3== meta.getIBizType()  
584 - || 6== meta.getIBizType()  
585 - || 7== meta.getIBizType()  
586 - || 8== meta.getIBizType()  
587 - )  
588 - {  
589 - // 确认后必填项校验  
590 - List<String> missingAfter = checkConfirmAfterParam(args, paramRuleData);  
591 - if (!missingAfter.isEmpty()) {  
592 - // 4.1 参数缺失,生成“提问”消息,直接返给客户  
593 - String askMsg = buildAskUserMessage(meta, missingAfter,args);  
594 - session.setSFunPrompts(askMsg);  
595 - return String.valueOf(askUserResult(toolExecutionRequest, askMsg));  
596 - }  
597 - // 7. 【业务校验】执行业务层面的逻辑校验 + 所有校验通过,执行核心业务逻辑  
598 - return executeTool(toolExecutionRequest, meta, args, paramRuleData, memoryId.toString(), session);  
599 - }  
600 - String askconfirmMsg =StrUtil.EMPTY;  
601 -// if(0== meta.getIActionType() && 4!= meta.getIBizType() && 5!= meta.getIBizType()){  
602 -// askconfirmMsg = buildConfirmUserMessage(meta, args);  
603 -// }else  
604 - if(4== meta.getIBizType() || meta.getIBizType()==5){  
605 - askconfirmMsg = doGetFromData( meta,args,session);  
606 -// session.setSFunPrompts(askconfirmMsg);  
607 -// operableChatMemoryProvider.get(memoryId).add(UserMessage.from("SYSTEM: 等待用户确认或选择部分数据操作"));  
608 - return executeWithConfirmation(toolExecutionRequest,askconfirmMsg,operableChatMemoryProvider.get(memoryId), session, meta).text();  
609 - }else{  
610 - askconfirmMsg =getDefMessage(args,meta.getSControlName(),meta); 613 + Boolean isConfirmed = isConfirmed(input) || input.contains("生成") || input.contains("确认");
  614 + //判断是否生成数据
  615 + List<Map<String,Object>> sRowData = new ArrayList<>();
  616 + String sHandleType = "merge";
  617 + if(4== meta.getIBizType() && ObjectUtil.isNotEmpty(session.getCurrentRowData())){
  618 + Map<String,Object> sRowDataMap = UserChoseIntentParser.getSelectedRows( input, session.getCurrentRowData());
  619 + sRowData = (List<Map<String, Object>>) sRowDataMap.get("sRowData");
  620 + sHandleType = sRowDataMap.get("sHandleType").toString();
  621 + }
  622 + //{"1":"存储过程","2":"SQL查询","3":"第三方API","4":"ERP未清","5":"ERP列表(报表)","6":"ERP单据","7":"其它","8":"自然语言TEXT2SQL"}
  623 + if((isConfirmed && (4== meta.getIBizType() ||1== meta.getIBizType()))
  624 + || 2== meta.getIBizType()
  625 + || 3== meta.getIBizType()
  626 + || 6== meta.getIBizType()
  627 + || 7== meta.getIBizType()
  628 + || 8== meta.getIBizType()
  629 + )
  630 + {
  631 + // 确认后必填项校验
  632 + List<String> missingAfter = checkConfirmAfterParam(args, paramRuleData);
  633 + if (!missingAfter.isEmpty()) {
  634 + // 4.1 参数缺失,生成“提问”消息,直接返给客户
  635 + String askMsg = buildAskUserMessage(meta, missingAfter,args);
  636 + return askMsg;
611 } 637 }
612 - // 返回需要确认的结果  
613 - return executeWithConfirmation(toolExecutionRequest,askconfirmMsg,operableChatMemoryProvider.get(memoryId), session, meta).text();  
614 - }; 638 + // 7. 【业务校验】执行业务层面的逻辑校验 + 所有校验通过,执行核心业务逻辑
  639 + return executeTool(meta, args, paramRuleData, session.getUserId(), session);
  640 + }
  641 + String askconfirmMsg =StrUtil.EMPTY;
  642 + if(4== meta.getIBizType() || meta.getIBizType()==5){
  643 + askconfirmMsg = doGetFromData( meta,args,session);
  644 + return executeWithConfirmation(askconfirmMsg,operableChatMemoryProvider.get(session.getUserId()), session, meta);
  645 + }else{
  646 + askconfirmMsg =getDefMessage(args,meta.getSControlName(),meta);
  647 + }
  648 + // 返回需要确认的结果
  649 + return executeWithConfirmation(askconfirmMsg,operableChatMemoryProvider.get(session.getUserId()), session, meta);
615 } 650 }
  651 +
616 /*** 652 /***
617 * @Author 钱豹 653 * @Author 钱豹
618 * @Date 15:16 2026/2/9 654 * @Date 15:16 2026/2/9
@@ -651,7 +687,7 @@ public class DynamicToolProvider implements ToolProvider { @@ -651,7 +687,7 @@ public class DynamicToolProvider implements ToolProvider {
651 **/ 687 **/
652 private void appendConfirmAll(StringBuilder markdown,String sName){ 688 private void appendConfirmAll(StringBuilder markdown,String sName){
653 sName = ObjectUtil.isEmpty(sName)?StrUtil.EMPTY:"["+sName+"]"; 689 sName = ObjectUtil.isEmpty(sName)?StrUtil.EMPTY:"["+sName+"]";
654 - markdown.append("请确认是否执行").append(sName).append("操作?1.全部数据生成多个单据 回复【全部确认】;2.全部数据生成一个单据 回复【合并确认】;3.按自然语义描述生成一个单据 如"1,3行确认"\n"); 690 + markdown.append("请确认是否执行").append(sName).append("操作?1.全部数据生成多个单据 回复【全部确认】;2.全部数据生成一个单据 回复【合并确认】;3.按自然语义描述生成一个单据 如"第1行确认"\n");
655 //全部确认 ,部分确认,取消 691 //全部确认 ,部分确认,取消
656 markdown.append("回复:&emsp;&emsp;").append("**<a href=\"#\" data-action=\"reset\" data-text=\"全部确认\" >全部确认</a>**").append("&emsp;") 692 markdown.append("回复:&emsp;&emsp;").append("**<a href=\"#\" data-action=\"reset\" data-text=\"全部确认\" >全部确认</a>**").append("&emsp;")
657 .append("**<a href=\"#\" data-action=\"reset\" data-text=\"合并确认\" >合并确认</a>**").append("&emsp;") 693 .append("**<a href=\"#\" data-action=\"reset\" data-text=\"合并确认\" >合并确认</a>**").append("&emsp;")
@@ -666,9 +702,7 @@ public class DynamicToolProvider implements ToolProvider { @@ -666,9 +702,7 @@ public class DynamicToolProvider implements ToolProvider {
666 **/ 702 **/
667 private void appendConfirm(StringBuilder markdown,String sName){ 703 private void appendConfirm(StringBuilder markdown,String sName){
668 sName = ObjectUtil.isEmpty(sName)?StrUtil.EMPTY:"["+sName+"]"; 704 sName = ObjectUtil.isEmpty(sName)?StrUtil.EMPTY:"["+sName+"]";
669 - markdown.append("请确认是否执行").append(sName).append("操作?请直接回复"确认"或"取消"\n");  
670 - //全部确认 ,部分确认,取消  
671 - markdown.append("回复:&emsp;&emsp;").append("**<a href=\"#\" data-action=\"reset\" data-text=\"确认\">确认</a>**").append("&emsp;") 705 + markdown.append("请确认是否执行").append(sName).append("操作?请回复:&emsp;&emsp;").append("**<a href=\"#\" data-action=\"reset\" data-text=\"确认\">确认</a>**").append("&emsp;")
672 .append("**<a href=\"#\" data-action=\"reset\" data-text=\"取消\">取消</a>**"); 706 .append("**<a href=\"#\" data-action=\"reset\" data-text=\"取消\">取消</a>**");
673 } 707 }
674 708
@@ -836,6 +870,14 @@ public class DynamicToolProvider implements ToolProvider { @@ -836,6 +870,14 @@ public class DynamicToolProvider implements ToolProvider {
836 } 870 }
837 return result; 871 return result;
838 } 872 }
  873 + /**
  874 + * 检查必填参数
  875 + */
  876 + private List<String> getRequiredParams(List<ParamRule> paramDefs) {
  877 + return paramDefs.stream()
  878 + .map(ParamRule::getSParam)
  879 + .toList();
  880 + }
839 881
840 /** 882 /**
841 * 检查必填参数 883 * 检查必填参数
@@ -845,8 +887,11 @@ public class DynamicToolProvider implements ToolProvider { @@ -845,8 +887,11 @@ public class DynamicToolProvider implements ToolProvider {
845 return paramDefs.stream() 887 return paramDefs.stream()
846 .filter(pd -> Boolean.TRUE.equals(pd.getBEmpty()) && pd.getBTipModel()) 888 .filter(pd -> Boolean.TRUE.equals(pd.getBEmpty()) && pd.getBTipModel())
847 .filter(pd -> 889 .filter(pd ->
848 - (!returnMap.containsKey(pd.getSParam()) || (ObjectUtil.isEmpty(returnMap.get(pd.getSParam()))))  
849 - && (!returnMap.containsKey(pd.getSParamValue()) || (ObjectUtil.isEmpty(returnMap.get(pd.getSParamValue())))) 890 + (!returnMap.containsKey(pd.getSParam())
  891 + || (ObjectUtil.isEmpty(returnMap.get(pd.getSParam())))
  892 + || (pd.getSParamValue().startsWith("d") && 0==Double.valueOf (returnMap.get(pd.getSParam()).toString()))
  893 + )
  894 + && (!returnMap.containsKey(pd.getSParamValue()) || (ObjectUtil.isEmpty(returnMap.get(pd.getSParamValue()))))
850 ) 895 )
851 .map(ParamRule::getSParam) 896 .map(ParamRule::getSParam)
852 .toList(); 897 .toList();
@@ -867,16 +912,17 @@ public class DynamicToolProvider implements ToolProvider { @@ -867,16 +912,17 @@ public class DynamicToolProvider implements ToolProvider {
867 .toList(); 912 .toList();
868 } 913 }
869 914
  915 +
870 /** 916 /**
871 * 模拟执行工具 917 * 模拟执行工具
872 */ 918 */
873 - public String executeTool(ToolExecutionRequest toolExecutionRequest,ToolMeta meta, Map<String, Object> args, List<ParamRule> paramRuleData,String userId,UserSceneSession session ) { 919 + public String executeTool(ToolMeta meta, Map<String, Object> args, List<ParamRule> paramRuleData,String userId,UserSceneSession session ) {
874 log.info("执行工具:{},参数:{}", meta.getSMethodNo(), args); 920 log.info("执行工具:{},参数:{}", meta.getSMethodNo(), args);
875 // 2.2 将中文key转换成英文key 921 // 2.2 将中文key转换成英文key
876 args = transformationArgs( args, paramRuleData); 922 args = transformationArgs( args, paramRuleData);
877 String sReturn ="执行成功"; 923 String sReturn ="执行成功";
878 try{ 924 try{
879 - sReturn = executeToolAfter(meta, args,toolExecutionRequest,paramRuleData,session); 925 + sReturn = executeToolAfter(meta, args,paramRuleData,session);
880 }catch (BusinessException e) { 926 }catch (BusinessException e) {
881 return e.getMessage(); 927 return e.getMessage();
882 } 928 }
@@ -893,7 +939,7 @@ public class DynamicToolProvider implements ToolProvider { @@ -893,7 +939,7 @@ public class DynamicToolProvider implements ToolProvider {
893 * @return 939 * @return
894 * @Description 返回结果后 执行业务类 940 * @Description 返回结果后 执行业务类
895 **/ 941 **/
896 - private String executeToolAfter(ToolMeta meta, Map<String, Object> args,ToolExecutionRequest toolExecutionRequest,List<ParamRule> paramDefs,UserSceneSession session) { 942 + private String executeToolAfter(ToolMeta meta, Map<String, Object> args,List<ParamRule> paramDefs,UserSceneSession session) {
897 // {"1":"存储过程","2":"SQL查询","3":"第三方API","4":"ERP未清","5":"ERP列表(报表)","6":"ERP单据","7":"其它","8":"自然语言TEXT2SQL"} 943 // {"1":"存储过程","2":"SQL查询","3":"第三方API","4":"ERP未清","5":"ERP列表(报表)","6":"ERP单据","7":"其它","8":"自然语言TEXT2SQL"}
898 String sBizContent = meta.getSBizContent(); 944 String sBizContent = meta.getSBizContent();
899 Integer iBizType = meta.getIBizType(); 945 Integer iBizType = meta.getIBizType();
@@ -950,7 +996,7 @@ public class DynamicToolProvider implements ToolProvider { @@ -950,7 +996,7 @@ public class DynamicToolProvider implements ToolProvider {
950 if ("queryTodayTask".equals(meta.getSMethodNo())) { 996 if ("queryTodayTask".equals(meta.getSMethodNo())) {
951 session.setBCleanMemory(true); 997 session.setBCleanMemory(true);
952 } 998 }
953 - return String.valueOf(successResult(toolExecutionRequest, sb.toString())); 999 + return sb.toString();
954 } else { 1000 } else {
955 String sMsgText = "未找到对应的数据"; 1001 String sMsgText = "未找到对应的数据";
956 session.setSFunPrompts(sMsgText); 1002 session.setSFunPrompts(sMsgText);
@@ -961,7 +1007,7 @@ public class DynamicToolProvider implements ToolProvider { @@ -961,7 +1007,7 @@ public class DynamicToolProvider implements ToolProvider {
961 return HttpsRequestUtil.me().doRequestHttp(sBizContent, JSONUtil.toJsonStr(args), 1007 return HttpsRequestUtil.me().doRequestHttp(sBizContent, JSONUtil.toJsonStr(args),
962 new HashMap<>(), "POST", "JSON"); 1008 new HashMap<>(), "POST", "JSON");
963 } 1009 }
964 - return String.valueOf(successResult(toolExecutionRequest, "操作成功")); 1010 + return "操作成功";
965 } 1011 }
966 1012
967 1013
@@ -1051,8 +1097,37 @@ public class DynamicToolProvider implements ToolProvider { @@ -1051,8 +1097,37 @@ public class DynamicToolProvider implements ToolProvider {
1051 } 1097 }
1052 List<Map<String, Object>> recordData = findFieldNameByChinese(sAIshowfieldShow, rows); 1098 List<Map<String, Object>> recordData = findFieldNameByChinese(sAIshowfieldShow, rows);
1053 int recordCount = dataset != null ? dataset.getTotalCount() : 0; 1099 int recordCount = dataset != null ? dataset.getTotalCount() : 0;
  1100 + // 动态生成表头
  1101 + Set<String> headers = new LinkedHashSet<>();
  1102 + for (Map<String, Object> record : sAIshowfieldShow) {
  1103 + String chineseName = (String) record.get("label");
  1104 + if (chineseName != null && !"sSlaveId".equals(record.get("sName"))) {
  1105 + headers.add(chineseName);
  1106 + }
  1107 + }
  1108 +
1054 StringBuilder markdown = new StringBuilder(); 1109 StringBuilder markdown = new StringBuilder();
1055 //状态 1110 //状态
  1111 + if(ObjectUtil.isNotEmpty(session.getArgs())){
  1112 + markdown.append("**查询条件**:");
  1113 + List<ParamRule> pr = session.getCurrentTool().getParamRuleListCheck();
  1114 + Map<String, Object> argsOld = new HashMap<>(session.getArgs());
  1115 + pr.forEach(one->{
  1116 + if(argsOld.containsKey(one.getSParam())){
  1117 + if(ObjectUtil.isNotEmpty(argsOld.get(one.getSParam()))){
  1118 + if(one.getSParamValue().startsWith("d")){
  1119 + if(Double.valueOf(argsOld.get(one.getSParam()).toString())>0){
  1120 + markdown.append(one.getSParam()).append(":").append(argsOld.get(one.getSParam()).toString()).append(" ");
  1121 + }
  1122 + }else{
  1123 + markdown.append(one.getSParam()).append(":").append(argsOld.get(one.getSParam()).toString()).append(" ");
  1124 + }
  1125 + }
  1126 + }
  1127 + });
  1128 + markdown.append("\n\n");
  1129 + }
  1130 + markdown.append("**结果**:");
1056 String sStatus = erpResult.getCode()<0?ErrorCode.ERRORMSG.getMessage():ErrorCode.SUCCESSMSG.getMessage(); 1131 String sStatus = erpResult.getCode()<0?ErrorCode.ERRORMSG.getMessage():ErrorCode.SUCCESSMSG.getMessage();
1057 markdown.append(sStatus).append("\n"); 1132 markdown.append(sStatus).append("\n");
1058 if(erpResult.getCode()<0){ 1133 if(erpResult.getCode()<0){
@@ -1067,14 +1142,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -1067,14 +1142,6 @@ public class DynamicToolProvider implements ToolProvider {
1067 } 1142 }
1068 // markdown.append("\n---\n"); 1143 // markdown.append("\n---\n");
1069 markdown.append("\n\n").append("| 序号 | "); 1144 markdown.append("\n\n").append("| 序号 | ");
1070 - // 动态生成表头  
1071 - Set<String> headers = new LinkedHashSet<>();  
1072 - for (Map<String, Object> record : sAIshowfieldShow) {  
1073 - String chineseName = (String) record.get("label");  
1074 - if (chineseName != null && !"sSlaveId".equals(record.get("sName"))) {  
1075 - headers.add(chineseName);  
1076 - }  
1077 - }  
1078 headers.forEach(header -> markdown.append(header).append(" | ")); 1145 headers.forEach(header -> markdown.append(header).append(" | "));
1079 markdown.append("\n|").append("---|".repeat(headers.size() + 1)).append("\n"); 1146 markdown.append("\n|").append("---|".repeat(headers.size() + 1)).append("\n");
1080 // 填充表格数据 1147 // 填充表格数据
@@ -1256,20 +1323,9 @@ public class DynamicToolProvider implements ToolProvider { @@ -1256,20 +1323,9 @@ public class DynamicToolProvider implements ToolProvider {
1256 } 1323 }
1257 1324
1258 /** 1325 /**
1259 - * 询问用户工具执行结果  
1260 - * @param request 工具执行请求  
1261 - * @param text 回复文本内容  
1262 - * @return 工具执行结果消息  
1263 - * @author 钱豹  
1264 - */  
1265 - private ToolExecutionResultMessage askUserResult(ToolExecutionRequest request, String text) {  
1266 - // 直接返回标准结果  
1267 - return ToolExecutionResultMessage.from(request, text);  
1268 - }  
1269 - /**  
1270 * 执行方法后需要用户确认的扩展版本 1326 * 执行方法后需要用户确认的扩展版本
1271 */ 1327 */
1272 - private ToolExecutionResultMessage executeWithConfirmation(ToolExecutionRequest request, String initialResult,ChatMemory chatMemory, UserSceneSession session,ToolMeta meta) { 1328 + private String executeWithConfirmation(String initialResult,ChatMemory chatMemory, UserSceneSession session,ToolMeta meta) {
1273 1329
1274 // 第一步:执行原始操作,返回初步结果 1330 // 第一步:执行原始操作,返回初步结果
1275 Map<String, Object> step1Result = new HashMap<>(); 1331 Map<String, Object> step1Result = new HashMap<>();
@@ -1278,18 +1334,19 @@ public class DynamicToolProvider implements ToolProvider { @@ -1278,18 +1334,19 @@ public class DynamicToolProvider implements ToolProvider {
1278 step1Result.put("confirmationRequired", true); 1334 step1Result.put("confirmationRequired", true);
1279 step1Result.put("confirmationMessage", initialResult); 1335 step1Result.put("confirmationMessage", initialResult);
1280 // // 将确认状态保存到对话记忆 1336 // // 将确认状态保存到对话记忆
1281 - chatMemory.add(UserMessage.from("SYSTEM: 等待用户确认操作")); 1337 +// chatMemory.add(UserMessage.from("SYSTEM: 等待用户确认操作"));
1282 String userMessage = formatConfirmationResult(step1Result); 1338 String userMessage = formatConfirmationResult(step1Result);
1283 session.setCurrentTool(meta); 1339 session.setCurrentTool(meta);
1284 - session.setSFunPrompts(userMessage); 1340 +// session.setSFunPrompts(userMessage);
1285 // 6. 返回确认请求 1341 // 6. 返回确认请求
1286 - return ToolExecutionResultMessage.from(request,userMessage); 1342 +// return ToolExecutionResultMessage.from(request,userMessage);
  1343 + return userMessage;
1287 } 1344 }
1288 1345
1289 private String formatConfirmationResult(Map<String, Object> result) { 1346 private String formatConfirmationResult(Map<String, Object> result) {
1290 return String.format( 1347 return String.format(
1291 """ 1348 """
1292 - **结果** : %s 1349 + %s
1293 """, 1350 """,
1294 result.get("initialResult"), 1351 result.get("initialResult"),
1295 result.get("confirmationMessage") 1352 result.get("confirmationMessage")
src/main/resources/templates/chat.html
@@ -468,7 +468,7 @@ @@ -468,7 +468,7 @@
468 let subsidiaryid= "1111111111"; 468 let subsidiaryid= "1111111111";
469 let usertype= "sysadmin"; 469 let usertype= "sysadmin";
470 // let usertype= "General"; 470 // let usertype= "General";
471 - let authorization="CE444885A9BCFDDE1FD793F8A0931301E9D7DE6CEDD9DE4B83ECE2219C7829A8F3419238942A93E9AD666629E18D159AF7FE144A6407DE745BA0AEC8B235FC1D59FCE41E63C9FE20948A232F9F67AAE5687D4EF8281542FFC87C4EB776974C6A538155B7ADAEE71E899235DC1122F426"; 471 + let authorization="CE444885A9BCFDDE1FD793F8A0931301E9D7DE6CEDD9DE4B83ECE2219C7829A8F3419238942A93E9AD666629E18D159AF7FE144A6407DE745BA0AEC8B235FC1D0771D239F1C61B14219E1D1B3A166D73495FD8E662F2065F9430347C7E4472B5538155B7ADAEE71E899235DC1122F426";
472 let hrefLock = window.location.origin+"/xlyAi"; 472 let hrefLock = window.location.origin+"/xlyAi";
473 // ==================== 配置部分 ==================== 473 // ==================== 配置部分 ====================
474 const CONFIG = { 474 const CONFIG = {