You need to sign in before continuing.

Commit 148bdd8c0a43e97412156fb5d65e55320c74cfd3

Authored by qianbao
1 parent 0c696213

添加未清选择 改成动态引导语

src/main/java/com/xly/agent/ErpAiAgent.java
1 package com.xly.agent; 1 package com.xly.agent;
2 2
3 3
4 -import dev.langchain4j.service.MemoryId;  
5 -import dev.langchain4j.service.SystemMessage;  
6 -import dev.langchain4j.service.UserMessage;  
7 -import dev.langchain4j.service.V; 4 +import dev.langchain4j.service.*;
8 5
9 /** 6 /**
10 * 优化后:新增场景专属交互规则,大模型仅处理当前场景业务指令 7 * 优化后:新增场景专属交互规则,大模型仅处理当前场景业务指令
@@ -13,7 +10,7 @@ public interface ErpAiAgent { @@ -13,7 +10,7 @@ public interface ErpAiAgent {
13 10
14 @SystemMessage("{{sSystemPrompt}}") 11 @SystemMessage("{{sSystemPrompt}}")
15 @UserMessage("用户输入:{{userInput}}") 12 @UserMessage("用户输入:{{userInput}}")
16 - String chat( 13 + Result<String> chat(
17 @MemoryId String userId, 14 @MemoryId String userId,
18 @V("userInput") String userInput, 15 @V("userInput") String userInput,
19 @V("sSystemPrompt") String sSystemPrompt 16 @V("sSystemPrompt") String sSystemPrompt
src/main/java/com/xly/service/XlyErpService.java
@@ -22,13 +22,18 @@ import com.xly.thread.AiSqlErrorHistoryThread; @@ -22,13 +22,18 @@ import com.xly.thread.AiSqlErrorHistoryThread;
22 import com.xly.thread.AiUserAgentQuestionThread; 22 import com.xly.thread.AiUserAgentQuestionThread;
23 import com.xly.thread.MultiThreadPoolServer; 23 import com.xly.thread.MultiThreadPoolServer;
24 import com.xly.tool.DynamicToolProvider; 24 import com.xly.tool.DynamicToolProvider;
  25 +import com.xly.tool.ToolSpecificationHolder;
25 import com.xly.util.*; 26 import com.xly.util.*;
  27 +import dev.langchain4j.agent.tool.ReturnBehavior;
26 import dev.langchain4j.agent.tool.ToolExecutionRequest; 28 import dev.langchain4j.agent.tool.ToolExecutionRequest;
  29 +import dev.langchain4j.agent.tool.ToolSpecification;
27 import dev.langchain4j.data.message.AiMessage; 30 import dev.langchain4j.data.message.AiMessage;
28 import dev.langchain4j.data.message.ChatMessage; 31 import dev.langchain4j.data.message.ChatMessage;
29 32
30 import dev.langchain4j.model.ollama.OllamaChatModel; 33 import dev.langchain4j.model.ollama.OllamaChatModel;
31 import dev.langchain4j.service.AiServices; 34 import dev.langchain4j.service.AiServices;
  35 +import dev.langchain4j.service.Result;
  36 +import dev.langchain4j.service.tool.ToolExecutor;
32 import lombok.RequiredArgsConstructor; 37 import lombok.RequiredArgsConstructor;
33 import lombok.extern.slf4j.Slf4j; 38 import lombok.extern.slf4j.Slf4j;
34 import org.apache.commons.lang3.time.DateFormatUtils; 39 import org.apache.commons.lang3.time.DateFormatUtils;
@@ -131,7 +136,8 @@ public class XlyErpService { @@ -131,7 +136,8 @@ public class XlyErpService {
131 && ObjectUtil.isNotEmpty(session.getCurrentTool().getSInputTabelName()) 136 && ObjectUtil.isNotEmpty(session.getCurrentTool().getSInputTabelName())
132 && ObjectUtil.isNotEmpty(session.getCurrentTool().getSStructureMemo())) 137 && ObjectUtil.isNotEmpty(session.getCurrentTool().getSStructureMemo()))
133 ){ 138 ){
134 - sResponMessage = aiAgent.chat(userId, input , AgentSystemPrompt.sSystemPrompt); 139 + Result<String> rs = aiAgent.chat(userId, input , AgentSystemPrompt.sSystemPrompt);
  140 + sResponMessage = rs.content();
135 } 141 }
136 142
137 if(ObjectUtil.isNotEmpty(session.getCurrentTool()) 143 if(ObjectUtil.isNotEmpty(session.getCurrentTool())
@@ -350,7 +356,8 @@ public class XlyErpService { @@ -350,7 +356,8 @@ public class XlyErpService {
350 if(ObjectUtil.isNotEmpty(session.getSSystemPrompt()) && isConfirmed){ 356 if(ObjectUtil.isNotEmpty(session.getSSystemPrompt()) && isConfirmed){
351 sSystemPrompt = session.getSSystemPrompt(); 357 sSystemPrompt = session.getSSystemPrompt();
352 } 358 }
353 - sResponMessage = aiAgent.chat(userId, input,sSystemPrompt); 359 + Result<String> rs = aiAgent.chat(userId, input,sSystemPrompt);
  360 + sResponMessage = rs.content();
354 } 361 }
355 methodName = ObjectUtil.isNotEmpty(session.getCurrentTool())?session.getCurrentTool().getSMethodName():StrUtil.EMPTY; 362 methodName = ObjectUtil.isNotEmpty(session.getCurrentTool())?session.getCurrentTool().getSMethodName():StrUtil.EMPTY;
356 if(ObjectUtil.isNotEmpty(session.getCurrentTool()) 363 if(ObjectUtil.isNotEmpty(session.getCurrentTool())
@@ -945,19 +952,24 @@ public class XlyErpService { @@ -945,19 +952,24 @@ public class XlyErpService {
945 // 4. 获取/创建用Agent 952 // 4. 获取/创建用Agent
946 ErpAiAgent aiAgent = UserSceneSessionService.ERP_AGENT_CACHE.get(userId); 953 ErpAiAgent aiAgent = UserSceneSessionService.ERP_AGENT_CACHE.get(userId);
947 if(ObjectUtil.isEmpty(aiAgent)){ 954 if(ObjectUtil.isEmpty(aiAgent)){
  955 + List<ToolSpecificationHolder> dataList = dynamicToolProvider.sceneToolCacheMap.get(session.getCurrentScene().getSId());
  956 + Set<String> immediateReturnToolNames = new HashSet<>();
  957 + Map<ToolSpecification, ToolExecutor> executors = new HashMap<>();
  958 + if(ObjectUtil.isNotEmpty(dataList)){
  959 + dataList.forEach(one->{
  960 + immediateReturnToolNames.add(one.getsName());
  961 + executors.put(one.getToolSpecification(),one.getToolExecutor());
  962 + });
  963 + }
948 aiAgent = AiServices.builder(ErpAiAgent.class) 964 aiAgent = AiServices.builder(ErpAiAgent.class)
949 .chatModel(chatModel) 965 .chatModel(chatModel)
950 .chatMemoryProvider(operableChatMemoryProvider) 966 .chatMemoryProvider(operableChatMemoryProvider)
951 - .toolProvider(dynamicToolProvider)  
952 -// .toolChoice(ChatCompletionToolChoice.ofRequired()) // 👈 必须调用一个工具 967 + .tools(executors,immediateReturnToolNames)
  968 +// .toolProvider(dynamicToolProvider)
  969 +// .returnBehavior(ReturnBehavior.IMMEDIATE)
  970 +// .toolChoice(ChatCompletionToolChoice.ofRequired())
953 .build(); 971 .build();
954 UserSceneSessionService.ERP_AGENT_CACHE.put(userId, aiAgent); 972 UserSceneSessionService.ERP_AGENT_CACHE.put(userId, aiAgent);
955 - // 初始化AiService 以防止热加载太慢 找不到相应的方法  
956 -// try{  
957 -// aiAgent.chat(userId, "initAiService",AgentSystemPrompt.sSystemPrompt);  
958 -// }catch (Exception e){  
959 -// e.printStackTrace();  
960 -// }  
961 log.info("用户{}Agent构建完成,已选场景:{},场景ID{}", userId, session.isSceneSelected() ? session.getCurrentScene().getSSceneName() : "未选(全场景匹配)", dynamicToolProvider.sSceneIdMap.get(userId)); 973 log.info("用户{}Agent构建完成,已选场景:{},场景ID{}", userId, session.isSceneSelected() ? session.getCurrentScene().getSSceneName() : "未选(全场景匹配)", dynamicToolProvider.sSceneIdMap.get(userId));
962 } 974 }
963 return aiAgent; 975 return aiAgent;
src/main/java/com/xly/tool/DynamicToolProvider.java
@@ -14,6 +14,7 @@ import com.xly.config.OperableChatMemoryProvider; @@ -14,6 +14,7 @@ import com.xly.config.OperableChatMemoryProvider;
14 import com.xly.constant.*; 14 import com.xly.constant.*;
15 import com.xly.entity.*; 15 import com.xly.entity.*;
16 import com.xly.exception.dto.BusinessException; 16 import com.xly.exception.dto.BusinessException;
  17 +import com.xly.exception.dto.DataException;
17 import com.xly.mapper.ParamRuleMapper; 18 import com.xly.mapper.ParamRuleMapper;
18 import com.xly.mapper.ToolMetaMapper; 19 import com.xly.mapper.ToolMetaMapper;
19 import com.xly.service.DynamicExeDbService; 20 import com.xly.service.DynamicExeDbService;
@@ -30,12 +31,7 @@ import dev.langchain4j.memory.ChatMemory; @@ -30,12 +31,7 @@ import dev.langchain4j.memory.ChatMemory;
30 31
31 import dev.langchain4j.model.chat.request.json.JsonObjectSchema; 32 import dev.langchain4j.model.chat.request.json.JsonObjectSchema;
32 import dev.langchain4j.model.chat.request.json.JsonSchema; 33 import dev.langchain4j.model.chat.request.json.JsonSchema;
33 -import dev.langchain4j.service.tool.ToolExecutor;  
34 -import dev.langchain4j.service.tool.ToolProvider;  
35 -  
36 -import dev.langchain4j.service.tool.ToolProviderRequest;  
37 -  
38 -import dev.langchain4j.service.tool.ToolProviderResult; 34 +import dev.langchain4j.service.tool.*;
39 35
40 36
41 import lombok.Getter; 37 import lombok.Getter;
@@ -59,58 +55,42 @@ import java.util.stream.IntStream; @@ -59,58 +55,42 @@ import java.util.stream.IntStream;
59 @RequiredArgsConstructor 55 @RequiredArgsConstructor
60 public class DynamicToolProvider implements ToolProvider { 56 public class DynamicToolProvider implements ToolProvider {
61 57
62 - // private final ToolMetaMapper toolMetaMapper;  
63 private final ObjectMapper objectMapper; 58 private final ObjectMapper objectMapper;
64 private final ToolMetaMapper toolMetaMapper; 59 private final ToolMetaMapper toolMetaMapper;
65 private final ParamRuleMapper paramRuleMapper; 60 private final ParamRuleMapper paramRuleMapper;
66 private final DynamicExeDbService dynamicExeDbService; 61 private final DynamicExeDbService dynamicExeDbService;
67 private final OperableChatMemoryProvider operableChatMemoryProvider; 62 private final OperableChatMemoryProvider operableChatMemoryProvider;
68 63
69 -  
70 - // 内存缓存:toolName -> ToolSpecificationHolder  
71 private final Map<String, ToolSpecificationHolder> toolCache = new ConcurrentHashMap<>(); 64 private final Map<String, ToolSpecificationHolder> toolCache = new ConcurrentHashMap<>();
72 public final Map<String, String> sSceneIdMap = new ConcurrentHashMap<>(); 65 public final Map<String, String> sSceneIdMap = new ConcurrentHashMap<>();
73 -  
74 - private final Map<String, List<ToolSpecificationHolder>> sceneToolCacheMap = new ConcurrentHashMap<>(); 66 + public final Map<String, List<ToolSpecificationHolder>> sceneToolCacheMap = new ConcurrentHashMap<>();
75 private final List<ParamRule> paramRuleDataAll = new ArrayList<>(); 67 private final List<ParamRule> paramRuleDataAll = new ArrayList<>();
76 68
77 @Value("${erp.baseurl}") 69 @Value("${erp.baseurl}")
78 private String baseUrl; 70 private String baseUrl;
79 71
80 - /***  
81 - * @Author 钱豹  
82 - * @Date 14:05 2026/2/10  
83 - * @Param []  
84 - * @return void  
85 - * @Description 移除所有动态方法缓存  
86 - **/  
87 public void cleanAllToolProvider() { 72 public void cleanAllToolProvider() {
88 toolCache.clear(); 73 toolCache.clear();
89 sceneToolCacheMap.clear(); 74 sceneToolCacheMap.clear();
90 paramRuleDataAll.clear(); 75 paramRuleDataAll.clear();
91 } 76 }
92 77
93 - /**  
94 - * 初始化时加载所有启用的工具到缓存  
95 - */  
96 @jakarta.annotation.PostConstruct 78 @jakarta.annotation.PostConstruct
97 public void init() { 79 public void init() {
98 - //  
99 List<ToolMeta> metas = toolMetaMapper.findAll(); 80 List<ToolMeta> metas = toolMetaMapper.findAll();
100 for (ToolMeta meta : metas) { 81 for (ToolMeta meta : metas) {
101 try { 82 try {
102 - //补全业务类型查询类显示的字段  
103 doSetToolAIshowfieldShow(meta); 83 doSetToolAIshowfieldShow(meta);
104 ToolSpecification spec = buildToolSpecification(meta); 84 ToolSpecification spec = buildToolSpecification(meta);
105 ToolExecutor executor = createToolExecutor(meta); 85 ToolExecutor executor = createToolExecutor(meta);
106 - toolCache.put(meta.getSMethodNo(), new ToolSpecificationHolder(spec, executor)); 86 + toolCache.put(meta.getSMethodNo(), new ToolSpecificationHolder(spec, executor,meta.getSMethodNo()));
107 log.info("已加载动态工具:{}", meta.getSMethodNo()); 87 log.info("已加载动态工具:{}", meta.getSMethodNo());
108 String sceneId = meta.getSSceneId(); 88 String sceneId = meta.getSSceneId();
109 List<ToolSpecificationHolder> dataList = new ArrayList<>(); 89 List<ToolSpecificationHolder> dataList = new ArrayList<>();
110 if(ObjectUtil.isNotEmpty(sceneToolCacheMap.get(sceneId))) { 90 if(ObjectUtil.isNotEmpty(sceneToolCacheMap.get(sceneId))) {
111 dataList = sceneToolCacheMap.get(sceneId); 91 dataList = sceneToolCacheMap.get(sceneId);
112 } 92 }
113 - dataList.add(new ToolSpecificationHolder(spec, executor)); 93 + dataList.add(new ToolSpecificationHolder(spec, executor,meta.getSMethodNo()));
114 sceneToolCacheMap.put(sceneId, dataList); 94 sceneToolCacheMap.put(sceneId, dataList);
115 } catch (Exception e) { 95 } catch (Exception e) {
116 e.printStackTrace(); 96 e.printStackTrace();
@@ -119,8 +99,136 @@ public class DynamicToolProvider implements ToolProvider { @@ -119,8 +99,136 @@ public class DynamicToolProvider implements ToolProvider {
119 } 99 }
120 } 100 }
121 101
122 - //补全业务类型查询类显示的字段  
123 - //{"1":"存储过程","2":"SQL查询","3":"第三方API","4":"窗体查询","5":"按钮执行","6":"其它"} 102 + @Override
  103 + public ToolProviderResult provideTools(ToolProviderRequest request) {
  104 + String sUserId = request.chatMemoryId().toString();
  105 + Map<ToolSpecification, ToolExecutor> executors = new HashMap<>();
  106 + UserSceneSession session = UserSceneSessionService.USER_SCENE_SESSION_CACHE.get(sUserId);
  107 +
  108 + // ====================== 防重复调用核心拦截 ======================
  109 + if (session != null && (session.getToolExecuted() || StrUtil.isNotBlank(session.getSFunPrompts()))) {
  110 + log.info("工具已执行/等待用户回复,禁止提供工具");
  111 + return ToolProviderResult.builder().build();
  112 + }
  113 +
  114 + List<ToolSpecificationHolder> datalist = new ArrayList<>();
  115 + List<ToolMeta> toolMetaAll = new ArrayList<>();
  116 +
  117 + if(session.getCurrentTool() != null){
  118 + toolMetaAll.add(session.getCurrentTool());
  119 + log.info("使用 currentTool: {}", session.getCurrentTool().getSMethodNo());
  120 + } else {
  121 + toolMetaAll = session.getAuthTool();
  122 + }
  123 +
  124 + if(ObjectUtil.isNotEmpty(toolMetaAll)){
  125 + toolMetaAll = toolMetaAll.stream()
  126 + .filter(to -> to.getSSceneId().equals(sSceneIdMap.get(sUserId)))
  127 + .collect(Collectors.toUnmodifiableList());
  128 +
  129 + if(ObjectUtil.isNotEmpty(toolMetaAll)){
  130 + toolMetaAll.forEach(to -> {
  131 + ToolSpecificationHolder holder = toolCache.get(to.getSMethodNo());
  132 + if (holder != null) {
  133 + datalist.add(holder);
  134 + log.debug("添加工具到提供器: {}", to.getSMethodNo());
  135 + } else {
  136 + log.warn("工具缓存缺失: {}", to.getSMethodNo());
  137 + }
  138 + });
  139 + }
  140 + }
  141 +
  142 + datalist.forEach(holder -> {
  143 + executors.put(holder.getToolSpecification(), holder.getToolExecutor());
  144 + });
  145 + log.info("provideTools 返回工具数量: {}", executors.size());
  146 + return ToolProviderResult.builder().addAll(executors).build();
  147 + }
  148 +
  149 +
  150 + /***
  151 + * @Author 钱豹
  152 + * @Date 23:59 2026/5/17
  153 + * @Param [meta]
  154 + * @return dev.langchain4j.service.tool.ToolExecutor
  155 + * @Description AI 自动调用工具执行方法
  156 + **/
  157 + private ToolExecutor createToolExecutor(ToolMeta meta) {
  158 + log.info("创建工具执行器: {}", meta.getSMethodNo());
  159 +
  160 + return (toolExecutionRequest, memoryId) -> {
  161 + log.info("===== 工具执行器开始执行 =====");
  162 + log.info("工具编号: {}", meta.getSMethodNo());
  163 + log.info("工具名称: {}", meta.getSMethodName());
  164 + log.info("memoryId: {}", memoryId);
  165 + log.info("请求参数: {}", toolExecutionRequest.arguments());
  166 + UserSceneSession session = UserSceneSessionService.USER_SCENE_SESSION_CACHE.get(memoryId.toString());
  167 + session.setCurrentTool(meta);
  168 +
  169 + // ====================== 防重复调用:立即上锁 ======================
  170 + session.setToolExecuted(true);
  171 + if (StrUtil.isNotBlank(session.getSFunPrompts())) {
  172 + // 关键:返回 工具执行失败 = 框架强制停止循环
  173 + throw new IllegalStateException("STOP_INVOCATION: 任务已完成,停止调用");
  174 +// return "【任务已完成】请勿重复调用工具,请直接总结结果回复用户:"+session.getSFunPrompts();
  175 + }
  176 + //解析参数失败
  177 + Map<String, Object> argsNew;
  178 + try {
  179 + argsNew = objectMapper.readValue(toolExecutionRequest.arguments(), new TypeReference<>() {});
  180 + log.info("解析后的参数: {}", argsNew);
  181 + } catch (Exception e) {
  182 + log.error("参数解析失败", e);
  183 + // 抛异常
  184 + throw new RuntimeException("参数解析失败,请重新输入");
  185 + }
  186 +
  187 + //获取之前获取的参数
  188 + Map<String, Object> args = session.getArgs();
  189 + if(ObjectUtil.isEmpty(args)) args = new HashMap<>();
  190 + Map<String, Object> finalArgs = args;
  191 + argsNew.forEach((k, v)->{
  192 + //获取对应的英文参数
  193 + List<ParamRule> data = meta.getParamRuleList().stream().filter(one->one.getSParam().equals(k)).collect(Collectors.toUnmodifiableList());
  194 + if(ObjectUtil.isNotEmpty(data) && data.size()>0){
  195 + finalArgs.remove(data.get(0).getSParamValue());
  196 + finalArgs.remove(data.get(0).getSParam());
  197 + }
  198 + if(ObjectUtil.isNotEmpty(v)){
  199 + finalArgs.put(k,v);
  200 + }
  201 + });
  202 +
  203 + // 2 【补全动态参数】动态参数补全
  204 + try{
  205 + args = applyValues(args, meta.getParamRuleListCheck());
  206 + }catch (Exception e){
  207 + log.error("返回信息",e);
  208 + String askMsg = e.getMessage();
  209 + session.setSFunPrompts(askMsg);
  210 + // 需要提问用户 → 抛异常停止循环
  211 + throw new RuntimeException(askMsg);
  212 + }
  213 + // 2.1 【自动补全】应用参数的默认值
  214 + List<ParamRule> paramRuleData = meta.getParamRuleListAll();
  215 + args = applyDefaultValues(args, paramRuleData);
  216 + session.setArgs(args);
  217 + // 3. 【自动校验】检查必填项
  218 + List<String> missing = checkRequiredParams(args, paramRuleData);
  219 + if (!missing.isEmpty()) {
  220 + // 4.1 参数缺失,生成“提问”消息,直接返给客户
  221 + String askMsg = buildAskUserMessage(meta, missing,args);
  222 + session.setSFunPrompts(askMsg);
  223 + return String.valueOf(successResult(toolExecutionRequest, askMsg));
  224 + }
  225 + // ====================== 返回时带终止指令 ======================
  226 +// String resp = JSONUtil.toJsonStr(finalArgs) ;
  227 + String resp = doDynamicTool( meta, session);
  228 + return String.valueOf(successResult(toolExecutionRequest, resp));
  229 + };
  230 + }
  231 +
124 private void doSetToolAIshowfieldShow(ToolMeta meta){ 232 private void doSetToolAIshowfieldShow(ToolMeta meta){
125 String sToolId = meta.getSId(); 233 String sToolId = meta.getSId();
126 List<ParamRule> paramRuleData = getParamRuleDataAll(); 234 List<ParamRule> paramRuleData = getParamRuleDataAll();
@@ -137,7 +245,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -137,7 +245,6 @@ public class DynamicToolProvider implements ToolProvider {
137 List<String> sAIshowfieldArry = new ArrayList<>(mutableList); 245 List<String> sAIshowfieldArry = new ArrayList<>(mutableList);
138 sAIshowfieldArry.add("sSlaveId"); 246 sAIshowfieldArry.add("sSlaveId");
139 String sSrcFormId = meta.getSSrcFormId(); 247 String sSrcFormId = meta.getSSrcFormId();
140 - //获取对应的窗体配置  
141 StringBuffer sSql =new StringBuffer().append("SELECT 10000 AS iOrderShow,A.sChinese AS label,A.sName,A.sControlName,B.sId AS sFormcustomId,A.sName AS sId FROM gdsconfigformslave AS A ") 248 StringBuffer sSql =new StringBuffer().append("SELECT 10000 AS iOrderShow,A.sChinese AS label,A.sName,A.sControlName,B.sId AS sFormcustomId,A.sName AS sId FROM gdsconfigformslave AS A ")
142 .append("JOIN gdsconfigformmaster AS B ON A.sParentId = B.sId ") 249 .append("JOIN gdsconfigformmaster AS B ON A.sParentId = B.sId ")
143 .append("WHERE B.sParentId = #{sSrcFormId} AND A.sName <> '' AND INSTR(A.sControlName,'Btn')=0 AND (A.bVisible = 1 OR A.sName =#{sName}) "); 250 .append("WHERE B.sParentId = #{sSrcFormId} AND A.sName <> '' AND INSTR(A.sControlName,'Btn')=0 AND (A.bVisible = 1 OR A.sName =#{sName}) ");
@@ -193,78 +300,20 @@ public class DynamicToolProvider implements ToolProvider { @@ -193,78 +300,20 @@ public class DynamicToolProvider implements ToolProvider {
193 return "string"; 300 return "string";
194 } 301 }
195 } 302 }
196 - @Override  
197 - public ToolProviderResult provideTools(ToolProviderRequest request) {  
198 - String sUserId = request.chatMemoryId().toString();  
199 - Map<ToolSpecification, ToolExecutor> executors = new HashMap<>();  
200 - // 获取Session  
201 - UserSceneSession session = UserSceneSessionService.USER_SCENE_SESSION_CACHE.get(sUserId);  
202 - // 工具已执行,不再提供任何工具  
203 - if (session != null && session.getToolExecuted()) {  
204 - log.info("工具已执行完成,清空可用工具列表");  
205 - return ToolProviderResult.builder().build();  
206 - }  
207 -  
208 - // 过滤对应的权限方法  
209 - List<ToolSpecificationHolder> datalist = new ArrayList<>();  
210 - List<ToolMeta> toolMetaAll = new ArrayList<>();  
211 - // 确保 currentTool 不为空,或者 authTool 有数据  
212 - if(session.getCurrentTool() != null){  
213 - // 【关键修改】添加全局引导语  
214 - StringBuffer stoolDesc = new StringBuffer();  
215 - stoolDesc.append("【重要】这是当前唯一可用的工具,无论用户问题是什么,都必须调用此工具。");  
216 - stoolDesc.append("如果用户没有明确指定要做什么,也默认使用此工具来处理。");  
217 - stoolDesc.append(System.lineSeparator());  
218 - stoolDesc.append(session.getCurrentTool().getStoolDesc());  
219 - session.getCurrentTool().setStoolDesc(stoolDesc.toString());  
220 - toolMetaAll.add(session.getCurrentTool());  
221 - log.info("使用 currentTool: {}", session.getCurrentTool().getSMethodNo());  
222 - } else {  
223 - toolMetaAll = session.getAuthTool();  
224 - log.info("使用 authTool, 数量: {}", toolMetaAll.size());  
225 - }  
226 303
227 - if(ObjectUtil.isNotEmpty(toolMetaAll)){  
228 - toolMetaAll = toolMetaAll.stream()  
229 - .filter(to -> to.getSSceneId().equals(sSceneIdMap.get(sUserId)))  
230 - .collect(Collectors.toUnmodifiableList());  
231 -  
232 - if(ObjectUtil.isNotEmpty(toolMetaAll)){  
233 - toolMetaAll.forEach(to -> {  
234 - ToolSpecificationHolder holder = toolCache.get(to.getSMethodNo());  
235 - if (holder != null) {  
236 - datalist.add(holder);  
237 - log.debug("添加工具到提供器: {}", to.getSMethodNo());  
238 - } else {  
239 - log.warn("工具缓存缺失: {}", to.getSMethodNo());  
240 - }  
241 - });  
242 - }  
243 - }  
244 - // 将工具添加到返回结果中  
245 - datalist.forEach(holder -> {  
246 - executors.put(holder.getToolSpecification(), holder.getToolExecutor());  
247 - });  
248 - log.info("provideTools 返回工具数量: {}", executors.size());  
249 - return ToolProviderResult.builder().addAll(executors).build();  
250 - }  
251 304
252 private ToolSpecification buildToolSpecification(ToolMeta meta) { 305 private ToolSpecification buildToolSpecification(ToolMeta meta) {
253 ToolSpecification.Builder builder = ToolSpecification.builder() 306 ToolSpecification.Builder builder = ToolSpecification.builder()
254 .name(meta.getSMethodNo()); 307 .name(meta.getSMethodNo());
255 308
256 StringBuffer stoolDesc = new StringBuffer(); 309 StringBuffer stoolDesc = new StringBuffer();
257 - StringBuffer sbt = new StringBuffer();  
258 - StringBuffer xt = new StringBuffer();  
259 -  
260 - // 强制指令【完全保留】  
261 - String forceToolPrompt = StrUtil.EMPTY;  
262 -// """  
263 -// 【重要·强制指令】  
264 -// 1. 这是当前唯一可用工具,必须调用,禁止直接回答  
265 -// 2. 用户输入包含:确认、全部确认、合并确认、行号(第1行/第一行等)  
266 -// 3. 必须调用本工具,只调用一次!  
267 -// """; 310 + String forceToolPrompt = """
  311 + 【工具调用规则】
  312 + 1. 每个自定义方法最多只能调用 1 次
  313 + 2. 只要方法返回结果,必须停止调用
  314 + 3. 禁止重复调用同一个方法
  315 + 4. 禁止无意义循环调用
  316 + """;
268 stoolDesc.append(forceToolPrompt); 317 stoolDesc.append(forceToolPrompt);
269 if (ObjectUtil.isNotEmpty(meta.getStoolDesc())) { 318 if (ObjectUtil.isNotEmpty(meta.getStoolDesc())) {
270 stoolDesc.append("MethodNo:").append(meta.getSMethodNo()) 319 stoolDesc.append("MethodNo:").append(meta.getSMethodNo())
@@ -287,97 +336,51 @@ public class DynamicToolProvider implements ToolProvider { @@ -287,97 +336,51 @@ public class DynamicToolProvider implements ToolProvider {
287 String sRuleCost = getConstMeg(paramRule); 336 String sRuleCost = getConstMeg(paramRule);
288 switch (paramType.toLowerCase()) { 337 switch (paramType.toLowerCase()) {
289 case "string": 338 case "string":
290 - if (bEmpty) sbt.append(paramDesc).append("(字符串)、");  
291 - else xt.append(paramDesc).append("(字符串)、");  
292 schemaBuilder.addStringProperty(paramDesc, paramDesc); 339 schemaBuilder.addStringProperty(paramDesc, paramDesc);
293 break; 340 break;
294 -  
295 case "integer": 341 case "integer":
296 case "int": 342 case "int":
297 - if (bEmpty) sbt.append(paramDesc).append("(数字)、");  
298 - else xt.append(paramDesc).append("(数字)、");  
299 schemaBuilder.addIntegerProperty(paramDesc, paramDesc); 343 schemaBuilder.addIntegerProperty(paramDesc, paramDesc);
300 break; 344 break;
301 -  
302 case "number": 345 case "number":
303 case "double": 346 case "double":
304 case "float": 347 case "float":
305 - if (bEmpty) sbt.append(paramDesc).append("(浮点)、");  
306 - else xt.append(paramDesc).append("(浮点)、");  
307 schemaBuilder.addNumberProperty(paramDesc, paramDesc); 348 schemaBuilder.addNumberProperty(paramDesc, paramDesc);
308 break; 349 break;
309 -  
310 case "boolean": 350 case "boolean":
311 case "bool": 351 case "bool":
312 - if (bEmpty) sbt.append(paramDesc).append("(布尔)、");  
313 - else xt.append(paramDesc).append("(布尔)、");  
314 schemaBuilder.addBooleanProperty(paramDesc, paramDesc); 352 schemaBuilder.addBooleanProperty(paramDesc, paramDesc);
315 break; 353 break;
316 -  
317 case "array": 354 case "array":
318 - // 印后工艺:从SQL获取可选工艺列表  
319 - String postProcessArray = getArrrayBySql(paramRule);  
320 - List<String> postProcessEnums = new ArrayList<>();  
321 - if (StrUtil.isNotBlank(postProcessArray)) {  
322 - postProcessEnums = Arrays.asList(postProcessArray.split("/"));  
323 - }  
324 - StringBuffer paramDescTs = new StringBuffer();  
325 - paramDescTs.append(paramDesc).append("(数组类型,可多选印后工艺 [").append(postProcessArray).append("]");  
326 - // 处理默认值  
327 - if (ObjectUtil.isNotEmpty(paramRule.getSDefaultValue()) ||  
328 - (ObjectUtil.isNotEmpty(postProcessArray) && postProcessArray.split("/").length == 1)) {  
329 - String defaultVal = (ObjectUtil.isNotEmpty(postProcessArray) && postProcessArray.split("/").length == 1)  
330 - ? postProcessArray  
331 - : paramRule.getSDefaultValue();  
332 - paramDescTs.append(",默认值[").append(defaultVal).append("]");  
333 - } else {  
334 - paramDescTs.append(",无默认值");  
335 - }  
336 - paramDescTs.append(")、");  
337 - // 有枚举值走枚举,没有走普通字符串  
338 - if (postProcessEnums.isEmpty()) {  
339 - sbt.append(paramDescTs);  
340 - schemaBuilder.addStringProperty(paramDesc, paramDescTs.toString()); 355 + String enumStr = getArrrayBySql(paramRule);
  356 + List<String> enums = StrUtil.isNotBlank(enumStr) ? Arrays.asList(enumStr.split("/")) : new ArrayList<>();
  357 + if (enums.isEmpty()) {
  358 + schemaBuilder.addStringProperty(paramDesc, paramDesc + "(数组)");
341 } else { 359 } else {
342 - xt.append(paramDescTs);  
343 - schemaBuilder.addEnumProperty(paramDesc, postProcessEnums, paramDescTs.toString()); 360 + schemaBuilder.addEnumProperty(paramDesc, enums, paramDesc + "(数组)");
344 } 361 }
345 break; 362 break;
346 -  
347 case "enum": 363 case "enum":
348 - // 印后工艺单选枚举  
349 - List<String> postProcessList = new ArrayList<>();  
350 - if (StrUtil.isNotBlank(sRuleCost)) {  
351 - postProcessList = Arrays.asList(sRuleCost.split("/"));  
352 - }  
353 - if (postProcessList.isEmpty()) {  
354 - schemaBuilder.addStringProperty(paramDesc, sRuleCost); 364 + String constStr = getConstMeg(paramRule);
  365 + List<String> constList = StrUtil.isNotBlank(constStr) ? Arrays.asList(constStr.split("/")) : new ArrayList<>();
  366 + if (constList.isEmpty()) {
  367 + schemaBuilder.addStringProperty(paramDesc, paramDesc);
355 } else { 368 } else {
356 - schemaBuilder.addEnumProperty(paramDesc, postProcessList, sRuleCost); 369 + schemaBuilder.addEnumProperty(paramDesc, constList, paramDesc);
357 } 370 }
358 break; 371 break;
359 default: 372 default:
360 schemaBuilder.addStringProperty(paramDesc, paramDesc); 373 schemaBuilder.addStringProperty(paramDesc, paramDesc);
361 break; 374 break;
362 } 375 }
363 -  
364 if (bEmpty) { 376 if (bEmpty) {
365 requiredParams.add(paramDesc); 377 requiredParams.add(paramDesc);
366 } 378 }
367 } 379 }
368 -  
369 -// if (ObjectUtil.isNotEmpty(sbt)) {  
370 -// stoolDesc.append(System.lineSeparator()).append("1.必填参数:").append(sbt);  
371 -// }  
372 -// if (ObjectUtil.isNotEmpty(xt)) {  
373 -// stoolDesc.append(System.lineSeparator()).append("2.选填参数:").append(xt);  
374 -// }  
375 -  
376 } catch (Exception e) { 380 } catch (Exception e) {
377 e.printStackTrace(); 381 e.printStackTrace();
378 } 382 }
379 383
380 - // 固定添加 operateType  
381 if (meta.getIBizType() == 4 || meta.getIBizType() == 5) { 384 if (meta.getIBizType() == 4 || meta.getIBizType() == 5) {
382 schemaBuilder.addStringProperty("operateType", "操作类型:全部确认/合并确认/单行确认"); 385 schemaBuilder.addStringProperty("operateType", "操作类型:全部确认/合并确认/单行确认");
383 requiredParams.add("operateType"); 386 requiredParams.add("operateType");
@@ -392,13 +395,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -392,13 +395,6 @@ public class DynamicToolProvider implements ToolProvider {
392 .build(); 395 .build();
393 } 396 }
394 397
395 - /***  
396 - * @Author 钱豹  
397 - * @Date 23:42 2026/2/3  
398 - * @Param [sConstConfig, sRule]  
399 - * @return java.lang.String  
400 - * @Description 常量类型枚举  
401 - **/  
402 private String getConstMeg(ParamRule paramRule){ 398 private String getConstMeg(ParamRule paramRule){
403 if(!RuleCode.CONST.getCode().equals(paramRule.getSRule())){ 399 if(!RuleCode.CONST.getCode().equals(paramRule.getSRule())){
404 return StrUtil.EMPTY; 400 return StrUtil.EMPTY;
@@ -414,13 +410,11 @@ public class DynamicToolProvider implements ToolProvider { @@ -414,13 +410,11 @@ public class DynamicToolProvider implements ToolProvider {
414 paramRule.setSRuleTs(sb.toString()); 410 paramRule.setSRuleTs(sb.toString());
415 return sb.toString(); 411 return sb.toString();
416 } 412 }
417 -  
418 return StrUtil.EMPTY; 413 return StrUtil.EMPTY;
419 } 414 }
420 - //数组类型枚举 415 +
421 private String getArrrayBySql(ParamRule paramRule){ 416 private String getArrrayBySql(ParamRule paramRule){
422 Boolean bCheckArray = !(RuleCode.SQL.getCode().equals(paramRule.getSRule())); 417 Boolean bCheckArray = !(RuleCode.SQL.getCode().equals(paramRule.getSRule()));
423 -// {"string":"字符","integer":"数字","double":"浮点","boolean":"布尔型","array":"数组","enum":"枚举"}  
424 Boolean bCheckArray2= !("array".equals(paramRule.getSType()) || "enum".equals(paramRule.getSType())); 418 Boolean bCheckArray2= !("array".equals(paramRule.getSType()) || "enum".equals(paramRule.getSType()));
425 Boolean bCheckArray3= ObjectUtil.isEmpty(paramRule.getSParamConfig()); 419 Boolean bCheckArray3= ObjectUtil.isEmpty(paramRule.getSParamConfig());
426 if(bCheckArray || bCheckArray2 || bCheckArray3){ 420 if(bCheckArray || bCheckArray2 || bCheckArray3){
@@ -434,10 +428,8 @@ public class DynamicToolProvider implements ToolProvider { @@ -434,10 +428,8 @@ public class DynamicToolProvider implements ToolProvider {
434 if(data.get(0).containsKey("sGroupName")){ 428 if(data.get(0).containsKey("sGroupName")){
435 Map<Object, List<Map<String, Object>>> groupData = data.stream() 429 Map<Object, List<Map<String, Object>>> groupData = data.stream()
436 .collect(Collectors.groupingBy(map -> map.get("sGroupName"))); 430 .collect(Collectors.groupingBy(map -> map.get("sGroupName")));
437 - // 打印结果  
438 Integer sUpKeySize =groupData.size(); 431 Integer sUpKeySize =groupData.size();
439 groupData.forEach((key, value) -> { 432 groupData.forEach((key, value) -> {
440 -// System.out.println("key: " + key);  
441 value.forEach(one->{ 433 value.forEach(one->{
442 sb.append(one.get(paramRule.getSParamValue())).append("/"); 434 sb.append(one.get(paramRule.getSParamValue())).append("/");
443 }); 435 });
@@ -446,8 +438,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -446,8 +438,6 @@ public class DynamicToolProvider implements ToolProvider {
446 sb.append(","); 438 sb.append(",");
447 } 439 }
448 }); 440 });
449 -  
450 -  
451 }else{ 441 }else{
452 data.forEach(one->{ 442 data.forEach(one->{
453 if(ObjectUtil.isNotEmpty(one.get(paramRule.getSParamValue()))){ 443 if(ObjectUtil.isNotEmpty(one.get(paramRule.getSParamValue()))){
@@ -462,135 +452,34 @@ public class DynamicToolProvider implements ToolProvider { @@ -462,135 +452,34 @@ public class DynamicToolProvider implements ToolProvider {
462 return sb.toString(); 452 return sb.toString();
463 } 453 }
464 454
465 -  
466 - /***  
467 - * @Author 钱豹  
468 - * @Date 15:08 2026/1/30  
469 - * @Param []  
470 - * @return java.util.List<com.xly.entity.ParamRule>  
471 - * @Description 获取所有参数  
472 - **/  
473 private List<ParamRule> getParamRuleDataAll(){ 455 private List<ParamRule> getParamRuleDataAll(){
474 if(paramRuleDataAll==null || paramRuleDataAll.size()==0){ 456 if(paramRuleDataAll==null || paramRuleDataAll.size()==0){
475 paramRuleDataAll.addAll(paramRuleMapper.findAll()); 457 paramRuleDataAll.addAll(paramRuleMapper.findAll());
476 } 458 }
477 return paramRuleDataAll; 459 return paramRuleDataAll;
478 } 460 }
479 - /***  
480 - * @Author 钱豹  
481 - * @Date 12:37 2026/3/16  
482 - * @Param [meta]  
483 - * @return dev.langchain4j.service.tool.ToolExecutor  
484 - * @Description 参数采集执行器  
485 - **/  
486 - private ToolExecutor createToolExecutor(ToolMeta meta) {  
487 - log.info("创建工具执行器: {}", meta.getSMethodNo());  
488 -  
489 - return (toolExecutionRequest, memoryId) -> {  
490 - log.info("===== 工具执行器开始执行 =====");  
491 - log.info("工具编号: {}", meta.getSMethodNo());  
492 - log.info("工具名称: {}", meta.getSMethodName());  
493 - log.info("memoryId: {}", memoryId);  
494 - log.info("请求参数: {}", toolExecutionRequest.arguments());  
495 461
496 - UserSceneSession session = UserSceneSessionService.USER_SCENE_SESSION_CACHE.get(memoryId.toString());  
497 - session.setCurrentTool(meta); // 标记当前工具  
498 - // 防止重复执行  
499 - if (session.getToolExecuted()) {  
500 - log.warn("工具已执行过,拒绝重复调用: {}", meta.getSMethodNo());  
501 - return String.valueOf(successResult(toolExecutionRequest, "{\"status\":\"already_executed\"}"));  
502 - }  
503 - //标记执行了(所有工具方法只执行一次)  
504 - session.setToolExecuted(true);  
505 - // 1. 解析参数  
506 - Map<String, Object> argsNew;  
507 - try {  
508 - argsNew = objectMapper.readValue(toolExecutionRequest.arguments(), new TypeReference<>() {});  
509 - log.info("解析后的参数: {}", argsNew);  
510 - } catch (Exception e) {  
511 - log.error("参数解析失败", e);  
512 - String errorMsg = "参数解析失败,请重新输入";  
513 - return String.valueOf(errorResult(toolExecutionRequest, errorMsg));  
514 - }  
515 - Map<String, Object> args = session.getArgs();  
516 - if(ObjectUtil.isEmpty(args)){  
517 - args = new HashMap<>();  
518 - }  
519 - Map<String, Object> finalArgs = args;  
520 - argsNew.forEach((k, v)->{  
521 - //获取对应的英文参数  
522 - List<ParamRule> data = meta.getParamRuleList().stream().filter(one->one.getSParam().equals(k)).collect(Collectors.toUnmodifiableList());  
523 - if(ObjectUtil.isNotEmpty(data) && data.size()>0){  
524 - finalArgs.remove(data.get(0).getSParamValue());  
525 - finalArgs.remove(data.get(0).getSParam());  
526 - }  
527 - if(ObjectUtil.isNotEmpty(v)){  
528 - finalArgs.put(k,v);  
529 - }  
530 - });  
531 - // 2 【补全动态参数】动态参数补全  
532 - try{  
533 - args = applyValues(args, meta.getParamRuleListCheck());  
534 - }catch (Exception e){  
535 - log.error("返回信息",e);  
536 - String askMsg = e.getMessage();  
537 - session.setSFunPrompts(askMsg);  
538 - return String.valueOf(successResult(toolExecutionRequest, askMsg));  
539 - }  
540 - List<ParamRule> paramRuleData = meta.getParamRuleListAll();  
541 - // 2.1 【自动补全】应用参数的默认值  
542 - args = applyDefaultValues(args, paramRuleData);  
543 - session.setArgs(args);  
544 - // 3. 【自动校验】检查必填项  
545 - List<String> missing = checkRequiredParams(args, paramRuleData);  
546 - if (!missing.isEmpty()) {  
547 - // 4.1 参数缺失,生成“提问”消息,直接返给客户  
548 - String askMsg = buildAskUserMessage(meta, missing,args);  
549 - session.setSFunPrompts(askMsg);  
550 - return String.valueOf(successResult(toolExecutionRequest, askMsg));  
551 - }  
552 - // 2. 获取必填参数规则  
553 -// List<ParamRule> sParamRules = meta.getParamRuleListCheck();  
554 -// List<String> missingParams = getRequiredParams(sParamRules);  
555 -// String collectPrompt = buildCollectParamsPrompt(meta, missingParams, args);  
556 -// log.info("参数缺失,返回收集提示: {}", collectPrompt);  
557 - return String.valueOf(successResult(toolExecutionRequest, JSONUtil.toJsonStr(finalArgs)));  
558 - };  
559 - }  
560 462
561 public String doDynamicTool(ToolMeta meta,UserSceneSession session) { 463 public String doDynamicTool(ToolMeta meta,UserSceneSession session) {
562 List<ParamRule> paramRuleData = meta.getParamRuleListAll(); 464 List<ParamRule> paramRuleData = meta.getParamRuleListAll();
563 List<ParamRule> paramRuleDataCheck = meta.getParamRuleListCheck(); 465 List<ParamRule> paramRuleDataCheck = meta.getParamRuleListCheck();
564 Map<String, Object> args = session.getArgs(); 466 Map<String, Object> args = session.getArgs();
565 467
566 - // 3. 【自动校验】检查必填项  
567 List<String> missing = checkRequiredParams(args, paramRuleDataCheck); 468 List<String> missing = checkRequiredParams(args, paramRuleDataCheck);
568 if (!missing.isEmpty()) { 469 if (!missing.isEmpty()) {
569 - // 4.1 参数缺失,生成“提问”消息,直接返给客户  
570 String askMsg = buildAskUserMessage(meta, missing,args); 470 String askMsg = buildAskUserMessage(meta, missing,args);
571 - //告知AI 缺失参数  
572 -// operableChatMemoryProvider.get(session.getUserId()).add(UserMessage.from(askMsg));  
573 return askMsg; 471 return askMsg;
574 } 472 }
575 473
576 - // 6. 【最终确认信息】所有检测通过后,需要和客户确认交互  
577 List<ChatMessage> chatMessage = operableChatMemoryProvider.getCurrentChatMessages(session.getUserId()); 474 List<ChatMessage> chatMessage = operableChatMemoryProvider.getCurrentChatMessages(session.getUserId());
578 ChatMessage userMessage = getLastUserMessage(chatMessage); 475 ChatMessage userMessage = getLastUserMessage(chatMessage);
579 String input = ""; 476 String input = "";
580 if (userMessage != null) { 477 if (userMessage != null) {
581 input = StrUtil.replace(getChatMessageContent(userMessage), "用户输入:", StrUtil.EMPTY); 478 input = StrUtil.replace(getChatMessageContent(userMessage), "用户输入:", StrUtil.EMPTY);
582 } 479 }
583 -// {"0":"查询","1":"执行"} 查询不需要确认 480 +
584 Boolean isConfirmed = isConfirmed(input) || input.contains("生成") || input.contains("确认"); 481 Boolean isConfirmed = isConfirmed(input) || input.contains("生成") || input.contains("确认");
585 -// //判断是否生成数据  
586 -// List<Map<String,Object>> sRowData = new ArrayList<>();  
587 -// String sHandleType = "merge";  
588 -// if(4== meta.getIBizType() && ObjectUtil.isNotEmpty(session.getCurrentRowData())){  
589 -// Map<String,Object> sRowDataMap = UserChoseIntentParser.getSelectedRows( input, session.getCurrentRowData());  
590 -// sRowData = (List<Map<String, Object>>) sRowDataMap.get("sRowData");  
591 -// sHandleType = sRowDataMap.get("sHandleType").toString();  
592 -// }  
593 - //{"1":"存储过程","2":"SQL查询","3":"第三方API","4":"ERP未清","5":"ERP列表(报表)","6":"ERP单据","7":"其它","8":"自然语言TEXT2SQL"} 482 +
594 if((isConfirmed && (4== meta.getIBizType() ||1== meta.getIBizType())) 483 if((isConfirmed && (4== meta.getIBizType() ||1== meta.getIBizType()))
595 || 2== meta.getIBizType() 484 || 2== meta.getIBizType()
596 || 3== meta.getIBizType() 485 || 3== meta.getIBizType()
@@ -599,40 +488,29 @@ public class DynamicToolProvider implements ToolProvider { @@ -599,40 +488,29 @@ public class DynamicToolProvider implements ToolProvider {
599 || 8== meta.getIBizType() 488 || 8== meta.getIBizType()
600 ) 489 )
601 { 490 {
602 - // 确认后必填项校验  
603 List<String> missingAfter = checkConfirmAfterParam(args, paramRuleData); 491 List<String> missingAfter = checkConfirmAfterParam(args, paramRuleData);
604 if (!missingAfter.isEmpty()) { 492 if (!missingAfter.isEmpty()) {
605 - // 4.1 参数缺失,生成“提问”消息,直接返给客户  
606 String askMsg = buildAskUserMessage(meta, missingAfter,args); 493 String askMsg = buildAskUserMessage(meta, missingAfter,args);
607 - return askMsg; 494 + throw new DataException(askMsg);
608 } 495 }
609 - // 7. 【业务校验】执行业务层面的逻辑校验 + 所有校验通过,执行核心业务逻辑  
610 return executeTool(meta, args, paramRuleData, session.getUserId(), session); 496 return executeTool(meta, args, paramRuleData, session.getUserId(), session);
611 } 497 }
  498 +
612 String askconfirmMsg =StrUtil.EMPTY; 499 String askconfirmMsg =StrUtil.EMPTY;
613 if(4== meta.getIBizType() || meta.getIBizType()==5){ 500 if(4== meta.getIBizType() || meta.getIBizType()==5){
614 askconfirmMsg = doGetFromData( meta,args,session); 501 askconfirmMsg = doGetFromData( meta,args,session);
615 - // ===================== 加入这一行 =====================  
616 String sSystemPrompt = buildDynamicSystemPrompt(session); 502 String sSystemPrompt = buildDynamicSystemPrompt(session);
617 session.setSSystemPrompt(sSystemPrompt); 503 session.setSSystemPrompt(sSystemPrompt);
618 - //===================== AI 返回需要确认 =====================  
619 return executeWithConfirmation(askconfirmMsg, session, meta); 504 return executeWithConfirmation(askconfirmMsg, session, meta);
620 }else{ 505 }else{
621 askconfirmMsg =getDefMessage(args,meta.getSControlName(),meta); 506 askconfirmMsg =getDefMessage(args,meta.getSControlName(),meta);
622 } 507 }
623 - // 返回需要确认的结果  
624 return executeWithConfirmation(askconfirmMsg, session, meta); 508 return executeWithConfirmation(askconfirmMsg, session, meta);
625 } 509 }
626 510
627 - /**  
628 - * 安全获取 ChatMessage 内容,适配你当前所有版本  
629 - * 不依赖 UserMessage / .text()  
630 - */  
631 private String getChatMessageContent(ChatMessage message) { 511 private String getChatMessageContent(ChatMessage message) {
632 if (message == null) return ""; 512 if (message == null) return "";
633 -  
634 try { 513 try {
635 - // 通用反射获取内容(兼容所有版本)  
636 return message.toString() 514 return message.toString()
637 .replace("ChatMessage{", "") 515 .replace("ChatMessage{", "")
638 .replace("}", "") 516 .replace("}", "")
@@ -642,9 +520,9 @@ public class DynamicToolProvider implements ToolProvider { @@ -642,9 +520,9 @@ public class DynamicToolProvider implements ToolProvider {
642 return ""; 520 return "";
643 } 521 }
644 } 522 }
  523 +
645 private ChatMessage getLastUserMessage(List<ChatMessage> messages) { 524 private ChatMessage getLastUserMessage(List<ChatMessage> messages) {
646 if (messages == null || messages.isEmpty()) return null; 525 if (messages == null || messages.isEmpty()) return null;
647 -  
648 for (int i = messages.size() - 1; i >= 0; i--) { 526 for (int i = messages.size() - 1; i >= 0; i--) {
649 ChatMessage msg = messages.get(i); 527 ChatMessage msg = messages.get(i);
650 if (msg.type() == ChatMessageType.USER) { 528 if (msg.type() == ChatMessageType.USER) {
@@ -654,14 +532,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -654,14 +532,6 @@ public class DynamicToolProvider implements ToolProvider {
654 return null; 532 return null;
655 } 533 }
656 534
657 -  
658 - /***  
659 - * @Author 钱豹  
660 - * @Date 15:16 2026/2/9  
661 - * @Param [argMap]  
662 - * @return java.lang.String  
663 - * @Description MAP转提示  
664 - **/  
665 private String getDefMessage(Map<String,Object> argMap,String sName,ToolMeta meta){ 535 private String getDefMessage(Map<String,Object> argMap,String sName,ToolMeta meta){
666 List<ParamRule> showList = meta.getParamRuleListAll(); 536 List<ParamRule> showList = meta.getParamRuleListAll();
667 List<ParamRule> showListData = new ArrayList<>(); 537 List<ParamRule> showListData = new ArrayList<>();
@@ -684,67 +554,31 @@ public class DynamicToolProvider implements ToolProvider { @@ -684,67 +554,31 @@ public class DynamicToolProvider implements ToolProvider {
684 appendConfirm(markdown,sName); 554 appendConfirm(markdown,sName);
685 return markdown.toString(); 555 return markdown.toString();
686 } 556 }
687 - /***  
688 - * @Author 钱豹  
689 - * @Date 14:56 2026/2/9  
690 - * @Param [markdown]  
691 - * @return void  
692 - * @Description 全部确认  
693 - **/ 557 +
694 private void appendConfirmAll(StringBuilder markdown,String sName){ 558 private void appendConfirmAll(StringBuilder markdown,String sName){
695 sName = ObjectUtil.isEmpty(sName)?StrUtil.EMPTY:"["+sName+"]"; 559 sName = ObjectUtil.isEmpty(sName)?StrUtil.EMPTY:"["+sName+"]";
696 markdown.append("请确认是否执行").append(sName).append("操作?1.全部数据生成多个单据 回复【全部确认】;2.全部数据生成一个单据 回复【合并确认】;3.按自然语义描述生成一个单据 如"第1行确认"\n"); 560 markdown.append("请确认是否执行").append(sName).append("操作?1.全部数据生成多个单据 回复【全部确认】;2.全部数据生成一个单据 回复【合并确认】;3.按自然语义描述生成一个单据 如"第1行确认"\n");
697 - //全部确认 ,部分确认,取消  
698 markdown.append("回复:&emsp;&emsp;").append("**<a href=\"#\" data-action=\"reset\" data-text=\"全部确认\" >全部确认</a>**").append("&emsp;") 561 markdown.append("回复:&emsp;&emsp;").append("**<a href=\"#\" data-action=\"reset\" data-text=\"全部确认\" >全部确认</a>**").append("&emsp;")
699 .append("**<a href=\"#\" data-action=\"reset\" data-text=\"合并确认\" >合并确认</a>**").append("&emsp;") 562 .append("**<a href=\"#\" data-action=\"reset\" data-text=\"合并确认\" >合并确认</a>**").append("&emsp;")
700 .append("**<a href=\"#\" data-action=\"reset\" data-text=\"取消\" >取消</a>**"); 563 .append("**<a href=\"#\" data-action=\"reset\" data-text=\"取消\" >取消</a>**");
701 } 564 }
702 - /***  
703 - * @Author 钱豹  
704 - * @Date 14:56 2026/2/9  
705 - * @Param [markdown]  
706 - * @return void  
707 - * @Description 单条确认  
708 - **/ 565 +
709 private void appendConfirm(StringBuilder markdown,String sName){ 566 private void appendConfirm(StringBuilder markdown,String sName){
710 sName = ObjectUtil.isEmpty(sName)?StrUtil.EMPTY:"["+sName+"]"; 567 sName = ObjectUtil.isEmpty(sName)?StrUtil.EMPTY:"["+sName+"]";
711 markdown.append("请确认是否执行").append(sName).append("操作?请回复:&emsp;&emsp;").append("**<a href=\"#\" data-action=\"reset\" data-text=\"确认\">确认</a>**").append("&emsp;") 568 markdown.append("请确认是否执行").append(sName).append("操作?请回复:&emsp;&emsp;").append("**<a href=\"#\" data-action=\"reset\" data-text=\"确认\">确认</a>**").append("&emsp;")
712 .append("**<a href=\"#\" data-action=\"reset\" data-text=\"取消\">取消</a>**"); 569 .append("**<a href=\"#\" data-action=\"reset\" data-text=\"取消\">取消</a>**");
713 } 570 }
714 571
715 - private ChatMessage getLasterUserMssage(List<ChatMessage> chatMessage){  
716 - if(chatMessage!=null){  
717 - for(int i=chatMessage.size()-1;i>0;i--){  
718 - ChatMessage data = chatMessage.get(i);  
719 - ChatMessageType sType = data.type();  
720 - if(ChatMessageType.USER.equals(sType)){  
721 - return chatMessage.get(i);  
722 - }  
723 - }  
724 - }  
725 - return null;  
726 - }  
727 -  
728 - /***  
729 - * @Author 钱豹  
730 - * @Date 13:35 2026/1/31  
731 - * @Param [args, paramDefs]  
732 - * @return java.util.Map<java.lang.String,java.lang.Object>  
733 - * @Description Map 值转换  
734 - **/  
735 private Map<String, Object> transformationArgs(Map<String, Object> args, List<ParamRule> paramDefs) { 572 private Map<String, Object> transformationArgs(Map<String, Object> args, List<ParamRule> paramDefs) {
736 Map<String, Object> result = new HashMap<>(args); 573 Map<String, Object> result = new HashMap<>(args);
737 paramDefs.forEach(pd->{ 574 paramDefs.forEach(pd->{
738 String name = pd.getSParam(); 575 String name = pd.getSParam();
739 String sValue = pd.getSParamValue(); 576 String sValue = pd.getSParamValue();
740 - //中文  
741 Boolean bCheck = result.containsKey(name) && ObjectUtil.isNotEmpty(result.get(name)); 577 Boolean bCheck = result.containsKey(name) && ObjectUtil.isNotEmpty(result.get(name));
742 - //英文字段  
743 Boolean bCheck2 = result.containsKey(sValue) && ObjectUtil.isNotEmpty(result.get(sValue)); 578 Boolean bCheck2 = result.containsKey(sValue) && ObjectUtil.isNotEmpty(result.get(sValue));
744 if (!bCheck2 && bCheck ) { 579 if (!bCheck2 && bCheck ) {
745 result.put(sValue,args.get(name)); 580 result.put(sValue,args.get(name));
746 } 581 }
747 - //常量value -> key 转换 用于后面入库  
748 if(RuleCode.CONST.getCode().equals(pd.getSRule()) && ObjectUtil.isNotEmpty(result.get(sValue))){ 582 if(RuleCode.CONST.getCode().equals(pd.getSRule()) && ObjectUtil.isNotEmpty(result.get(sValue))){
749 String sData = result.get(sValue).toString(); 583 String sData = result.get(sValue).toString();
750 Map<String,Object> configData = JSONUtil.parseObj(pd.getSParamConfig()); 584 Map<String,Object> configData = JSONUtil.parseObj(pd.getSParamConfig());
@@ -758,13 +592,9 @@ public class DynamicToolProvider implements ToolProvider { @@ -758,13 +592,9 @@ public class DynamicToolProvider implements ToolProvider {
758 return result; 592 return result;
759 } 593 }
760 594
761 - /**  
762 - * 动态参数补全SQL  
763 - */  
764 private Map<String, Object> applyValues(Map<String, Object> args, List<ParamRule> paramDefsCheck) { 595 private Map<String, Object> applyValues(Map<String, Object> args, List<ParamRule> paramDefsCheck) {
765 Map<String, Object> result = new HashMap<>(args); 596 Map<String, Object> result = new HashMap<>(args);
766 result = transformationArgs( result, paramDefsCheck); 597 result = transformationArgs( result, paramDefsCheck);
767 - //根据iOrder 排序  
768 List<ParamRule> paramDefs = new ArrayList<>(paramDefsCheck); 598 List<ParamRule> paramDefs = new ArrayList<>(paramDefsCheck);
769 paramDefs.sort(Comparator.comparing(ParamRule::getIOrder)); 599 paramDefs.sort(Comparator.comparing(ParamRule::getIOrder));
770 for (ParamRule pd : paramDefs) { 600 for (ParamRule pd : paramDefs) {
@@ -777,38 +607,30 @@ public class DynamicToolProvider implements ToolProvider { @@ -777,38 +607,30 @@ public class DynamicToolProvider implements ToolProvider {
777 bCheck = bCheck && ObjectUtil.isNotEmpty(result.get(name)); 607 bCheck = bCheck && ObjectUtil.isNotEmpty(result.get(name));
778 bCheck = bCheck && RuleCode.SQL.getCode().equals(sRule); 608 bCheck = bCheck && RuleCode.SQL.getCode().equals(sRule);
779 bCheck = bCheck && ObjectUtil.isNotEmpty(pd.getSParamConfig()); 609 bCheck = bCheck && ObjectUtil.isNotEmpty(pd.getSParamConfig());
780 -// bCheck = bCheck && !"array".equals(sType);  
781 610
782 Boolean bCheck2 = result.containsKey(sValue); 611 Boolean bCheck2 = result.containsKey(sValue);
783 bCheck2 = bCheck2 && ObjectUtil.isNotEmpty(result.get(sValue)); 612 bCheck2 = bCheck2 && ObjectUtil.isNotEmpty(result.get(sValue));
784 bCheck2 = bCheck2 && RuleCode.SQL.getCode().equals(sRule); 613 bCheck2 = bCheck2 && RuleCode.SQL.getCode().equals(sRule);
785 bCheck2 = bCheck2 && ObjectUtil.isNotEmpty(pd.getSParamConfig()); 614 bCheck2 = bCheck2 && ObjectUtil.isNotEmpty(pd.getSParamConfig());
786 -// bCheck2 = bCheck2 && !"array".equals(sType);  
787 - //存在动态SQL 并且是枚举的需要 615 +
788 if ((bCheck || bCheck2) &&("enum".equals(sType) || "string".equals(sType))){ 616 if ((bCheck || bCheck2) &&("enum".equals(sType) || "string".equals(sType))){
789 String sSql = pd.getSParamConfig(); 617 String sSql = pd.getSParamConfig();
790 String sKey = bCheck?name:sValue; 618 String sKey = bCheck?name:sValue;
791 String nameValue = result.get(sKey).toString(); 619 String nameValue = result.get(sKey).toString();
792 List<Map<String,Object>> dataList = dynamicExeDbService.findSql(result,sSql); 620 List<Map<String,Object>> dataList = dynamicExeDbService.findSql(result,sSql);
793 - //传入的参数无效返回继续盘问消息  
794 if(ObjectUtil.isEmpty(dataList)){ 621 if(ObjectUtil.isEmpty(dataList)){
795 throw new BusinessException(ErrorCode.PARAM_REQUIRED,String.format("%s 您描述的%s 不存在,请重新告诉我",name,nameValue)); 622 throw new BusinessException(ErrorCode.PARAM_REQUIRED,String.format("%s 您描述的%s 不存在,请重新告诉我",name,nameValue));
796 } 623 }
797 - //如果SQL没有条件 多个数据集中进行匹配 如果只匹配一个也算成功  
798 if(ObjectUtil.isNotEmpty(args.get(name)) || ObjectUtil.isNotEmpty(args.get(sValue))){ 624 if(ObjectUtil.isNotEmpty(args.get(name)) || ObjectUtil.isNotEmpty(args.get(sValue))){
799 if(("enum".equals(sType) ||"string".equals(sType)) && (args.get(name) instanceof List || args.get(sValue) instanceof List)){ 625 if(("enum".equals(sType) ||"string".equals(sType)) && (args.get(name) instanceof List || args.get(sValue) instanceof List)){
800 - //枚举返回了数组 纠正成字符串  
801 if(args.get(name) instanceof List){ 626 if(args.get(name) instanceof List){
802 args.put(name,((List<?>) args.get(name)).get(0)); 627 args.put(name,((List<?>) args.get(name)).get(0));
803 -// args.put(sValue,((List<?>) args.get(name)).get(0));  
804 } 628 }
805 if(args.get(sValue) instanceof List){ 629 if(args.get(sValue) instanceof List){
806 args.put(sValue,((List<?>) args.get(sValue)).get(0)); 630 args.put(sValue,((List<?>) args.get(sValue)).get(0));
807 -// args.put(name,((List<?>) args.get(sValue)).get(0));  
808 } 631 }
809 } 632 }
810 List<Map<String,Object>> dataListNew = dataList.stream().filter(one-> one.get(sValue).equals(args.get(name)) || one.get(sValue).equals(args.get(sValue))).collect(Collectors.toUnmodifiableList()); 633 List<Map<String,Object>> dataListNew = dataList.stream().filter(one-> one.get(sValue).equals(args.get(name)) || one.get(sValue).equals(args.get(sValue))).collect(Collectors.toUnmodifiableList());
811 - //如果枚举类型枚举值中又不存在AI 返回的数据  
812 if("enum".equals(sType) && ObjectUtil.isEmpty(dataListNew)){ 634 if("enum".equals(sType) && ObjectUtil.isEmpty(dataListNew)){
813 args.remove(name); 635 args.remove(name);
814 args.remove(sValue); 636 args.remove(sValue);
@@ -827,7 +649,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -827,7 +649,6 @@ public class DynamicToolProvider implements ToolProvider {
827 result.put(sValue, dataList.get(0).get(sValue)); 649 result.put(sValue, dataList.get(0).get(sValue));
828 result.put(name, dataList.get(0).get(sValue)); 650 result.put(name, dataList.get(0).get(sValue));
829 }else{ 651 }else{
830 - //赋值到  
831 String[] sCopyToA = sCopyTo.split(","); 652 String[] sCopyToA = sCopyTo.split(",");
832 for(String sCopyToOne:sCopyToA){ 653 for(String sCopyToOne:sCopyToA){
833 String[] sCopyToOneA = sCopyToOne.split(":"); 654 String[] sCopyToOneA = sCopyToOne.split(":");
@@ -836,7 +657,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -836,7 +657,6 @@ public class DynamicToolProvider implements ToolProvider {
836 } 657 }
837 } 658 }
838 StringBuffer sData=new StringBuffer(); 659 StringBuffer sData=new StringBuffer();
839 - //存在多个形成提示语  
840 if(dataList.size()>1){ 660 if(dataList.size()>1){
841 List<Map<String, Object>> finalDataList = dataList; 661 List<Map<String, Object>> finalDataList = dataList;
842 IntStream.range(0, dataList.size()) 662 IntStream.range(0, dataList.size())
@@ -858,17 +678,12 @@ public class DynamicToolProvider implements ToolProvider { @@ -858,17 +678,12 @@ public class DynamicToolProvider implements ToolProvider {
858 return result; 678 return result;
859 } 679 }
860 680
861 - /**  
862 - * 应用参数的默认值  
863 - */  
864 private Map<String, Object> applyDefaultValues(Map<String, Object> args, List<ParamRule> paramDefs) { 681 private Map<String, Object> applyDefaultValues(Map<String, Object> args, List<ParamRule> paramDefs) {
865 Map<String, Object> result = new HashMap<>(args); 682 Map<String, Object> result = new HashMap<>(args);
866 for (ParamRule pd : paramDefs) { 683 for (ParamRule pd : paramDefs) {
867 String name = pd.getSParam(); 684 String name = pd.getSParam();
868 if ((!result.containsKey(name)|| ObjectUtil.isEmpty(result.get(name))) 685 if ((!result.containsKey(name)|| ObjectUtil.isEmpty(result.get(name)))
869 && ObjectUtil.isNotEmpty(pd.getSDefaultValue()) 686 && ObjectUtil.isNotEmpty(pd.getSDefaultValue())
870 -// && !"enum".equals(pd.getSType())  
871 -// && !"array".equals(pd.getSType())  
872 ) { 687 ) {
873 Object defaultValue = pd.getSDefaultValue(); 688 Object defaultValue = pd.getSDefaultValue();
874 result.put(name, defaultValue); 689 result.put(name, defaultValue);
@@ -876,18 +691,7 @@ public class DynamicToolProvider implements ToolProvider { @@ -876,18 +691,7 @@ public class DynamicToolProvider implements ToolProvider {
876 } 691 }
877 return result; 692 return result;
878 } 693 }
879 - /**  
880 - * 检查必填参数  
881 - */  
882 - private List<String> getRequiredParams(List<ParamRule> paramDefs) {  
883 - return paramDefs.stream()  
884 - .map(ParamRule::getSParam)  
885 - .toList();  
886 - }  
887 694
888 - /**  
889 - * 检查必填参数  
890 - */  
891 private List<String> checkRequiredParams(Map<String, Object> args, List<ParamRule> paramDefs) { 695 private List<String> checkRequiredParams(Map<String, Object> args, List<ParamRule> paramDefs) {
892 Map<String,Object> returnMap = transformationArgs( args, paramDefs); 696 Map<String,Object> returnMap = transformationArgs( args, paramDefs);
893 return paramDefs.stream() 697 return paramDefs.stream()
@@ -915,10 +719,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -915,10 +719,6 @@ public class DynamicToolProvider implements ToolProvider {
915 return bDbZero || bBhcs || (!returnMap.containsKey(pd.getSParamValue()) || (ObjectUtil.isEmpty(returnMap.get(pd.getSParamValue())))); 719 return bDbZero || bBhcs || (!returnMap.containsKey(pd.getSParamValue()) || (ObjectUtil.isEmpty(returnMap.get(pd.getSParamValue()))));
916 } 720 }
917 721
918 -  
919 - /**  
920 - * 确认后必填参数  
921 - */  
922 private List<String> checkConfirmAfterParam(Map<String, Object> args, List<ParamRule> paramDefs) { 722 private List<String> checkConfirmAfterParam(Map<String, Object> args, List<ParamRule> paramDefs) {
923 Map<String,Object> returnMap = transformationArgs( args, paramDefs); 723 Map<String,Object> returnMap = transformationArgs( args, paramDefs);
924 return paramDefs.stream() 724 return paramDefs.stream()
@@ -931,13 +731,8 @@ public class DynamicToolProvider implements ToolProvider { @@ -931,13 +731,8 @@ public class DynamicToolProvider implements ToolProvider {
931 .toList(); 731 .toList();
932 } 732 }
933 733
934 -  
935 - /**  
936 - * 模拟执行工具  
937 - */  
938 public String executeTool(ToolMeta meta, Map<String, Object> args, List<ParamRule> paramRuleData,String userId,UserSceneSession session ) { 734 public String executeTool(ToolMeta meta, Map<String, Object> args, List<ParamRule> paramRuleData,String userId,UserSceneSession session ) {
939 log.info("执行工具:{},参数:{}", meta.getSMethodNo(), args); 735 log.info("执行工具:{},参数:{}", meta.getSMethodNo(), args);
940 - // 2.2 将中文key转换成英文key  
941 args = transformationArgs( args, paramRuleData); 736 args = transformationArgs( args, paramRuleData);
942 String sReturn ="执行成功"; 737 String sReturn ="执行成功";
943 try{ 738 try{
@@ -951,100 +746,86 @@ public class DynamicToolProvider implements ToolProvider { @@ -951,100 +746,86 @@ public class DynamicToolProvider implements ToolProvider {
951 session.setBCleanMemory(true); 746 session.setBCleanMemory(true);
952 } 747 }
953 return sReturn; 748 return sReturn;
954 -  
955 } 749 }
956 - /****  
957 - * @Author 钱豹  
958 - * @Date 10:26 2026/2/1  
959 - * @Param  
960 - * @return  
961 - * @Description 返回结果后 执行业务类  
962 - **/ 750 +
963 private String executeToolAfter(ToolMeta meta, Map<String, Object> args,List<ParamRule> paramDefs,UserSceneSession session) { 751 private String executeToolAfter(ToolMeta meta, Map<String, Object> args,List<ParamRule> paramDefs,UserSceneSession session) {
964 -// {"1":"存储过程","2":"SQL查询","3":"第三方API","4":"ERP未清","5":"ERP列表(报表)","6":"ERP单据","7":"其它","8":"自然语言TEXT2SQL"}  
965 - String sBizContent = meta.getSBizContent();  
966 - Integer iBizType = meta.getIBizType();  
967 - args.put("sUserId", session.getUserId());  
968 - args.put("sLoginId", session.getUserName());  
969 - args.put("sMakePerson", session.getUserName());  
970 - args.put("sBrId", session.getSBrandsId());  
971 - args.put("sBrandsId", session.getSBrandsId());  
972 - args.put("sSuId", session.getSSubsidiaryId());  
973 - args.put("sSrcFormId", meta.getSSrcFormId());  
974 - args.put("sControlName", meta.getSControlName());  
975 - args.put("iBizType", iBizType);  
976 - args.put("sSubsidiaryId", session.getSSubsidiaryId());  
977 - args.put("sToolId", meta.getSId());  
978 - if (iBizType == 1 || iBizType == 4) {  
979 - Map<String, Object> data = new HashMap<>(args);  
980 - data.put("sData", JSONObject.toJSONString((data)));  
981 - if(ObjectUtil.isEmpty(sBizContent) && iBizType == 4){  
982 - sBizContent ="Sp_Ai_AddCommonAfterNew";  
983 - //获取未清数据  
984 - if(ObjectUtil.isEmpty(args.get("sSlaveId"))){  
985 - throw new BusinessException(-1,"请选择操作数据");  
986 - }  
987 - List<Map<String,Object>> sRowData = doGetFromDataWq( meta, args, session);  
988 - data.put("sRowData", JSONObject.toJSONString(sRowData));  
989 - }  
990 - Map<String, Object> searMap = this.dynamicExeDbService.getDoProMap(sBizContent, data);  
991 - Map<String, Object> sReturn = this.dynamicExeDbService.getCallPro(searMap, sBizContent);  
992 - Integer sCode = ObjectUtil.isNotEmpty(sReturn.get(ProcedureConstant.SCODE)) ? Integer.valueOf(sReturn.get(ProcedureConstant.SCODE).toString()) : 0;  
993 - String sMsgText = ObjectUtil.isNotEmpty(sReturn.get(ProcedureConstant.SRETURN)) ? sReturn.get(ProcedureConstant.SRETURN).toString() : "操作成功";  
994 - if (sCode < 0) {  
995 - sMsgText = ObjectUtil.isEmpty(sMsgText) ? "调用过程sCode:" + Integer.valueOf(searMap.get(ProcedureConstant.SCODE).toString()) : sMsgText;  
996 - session.setSFunPrompts(sMsgText);  
997 - throw new BusinessException(sCode,sMsgText);  
998 - }  
999 - Map<String,Object> outMap = (Map<String, Object>) sReturn.get("outMap");  
1000 - String sId = ObjectUtil.isNotEmpty(outMap.get("sBillId")) ? outMap.get("sBillId").toString() : "";  
1001 - session.setSCopyTo(meta.getSControlName());  
1002 - session.setSCopyToSrcId(sId);  
1003 - session.setSFunPrompts(sMsgText);  
1004 - return sMsgText;  
1005 - } else if (iBizType == 2 && ObjectUtil.isNotEmpty(sBizContent)) {  
1006 - //SQL查询  
1007 - if (sBizContent.toLowerCase().startsWith("update")) {  
1008 - this.dynamicExeDbService.updateSql(args, sBizContent);  
1009 - } else if (sBizContent.toLowerCase().startsWith("delete")) {  
1010 - this.dynamicExeDbService.delSql(args, sBizContent);  
1011 - } else if (sBizContent.toLowerCase().startsWith("insert")) {  
1012 - this.dynamicExeDbService.addSql(args, sBizContent);  
1013 - } else {  
1014 - List<Map<String, Object>> retData = this.dynamicExeDbService.findSql(args, sBizContent);  
1015 - if (ObjectUtil.isNotEmpty(retData)) {  
1016 - StringBuffer sb = new StringBuffer();  
1017 - retData.forEach(one -> {  
1018 - one.forEach((k, v) -> {  
1019 - sb.append(v).append(" ");  
1020 - });  
1021 - sb.append("<br/>");  
1022 - });  
1023 - if (ObjectUtil.isNotEmpty(retData)) {  
1024 - sb.append("请根据这些信息安排今天的工作吧!如果有具体任务需要进一步处理,请告诉我");  
1025 - }  
1026 - session.setSFunPrompts(sb.toString());  
1027 - if ("queryTodayTask".equals(meta.getSMethodNo())) {  
1028 - session.setBCleanMemory(true);  
1029 - }  
1030 - return sb.toString();  
1031 - } else {  
1032 - String sMsgText = "未找到对应的数据";  
1033 - session.setSFunPrompts(sMsgText);  
1034 - throw new BusinessException(-1,sMsgText);  
1035 - }  
1036 - }  
1037 - } else if (iBizType == 3) {  
1038 - return HttpsRequestUtil.me().doRequestHttp(sBizContent, JSONUtil.toJsonStr(args),  
1039 - new HashMap<>(), "POST", "JSON");  
1040 - }  
1041 - return "操作成功"; 752 + String sBizContent = meta.getSBizContent();
  753 + Integer iBizType = meta.getIBizType();
  754 + args.put("sUserId", session.getUserId());
  755 + args.put("sLoginId", session.getUserName());
  756 + args.put("sMakePerson", session.getUserName());
  757 + args.put("sBrId", session.getSBrandsId());
  758 + args.put("sBrandsId", session.getSBrandsId());
  759 + args.put("sSuId", session.getSSubsidiaryId());
  760 + args.put("sSrcFormId", meta.getSSrcFormId());
  761 + args.put("sControlName", meta.getSControlName());
  762 + args.put("iBizType", iBizType);
  763 + args.put("sSubsidiaryId", session.getSSubsidiaryId());
  764 + args.put("sToolId", meta.getSId());
  765 + if (iBizType == 1 || iBizType == 4) {
  766 + Map<String, Object> data = new HashMap<>(args);
  767 + data.put("sData", JSONObject.toJSONString((data)));
  768 + if(ObjectUtil.isEmpty(sBizContent) && iBizType == 4){
  769 + sBizContent ="Sp_Ai_AddCommonAfterNew";
  770 + if(ObjectUtil.isEmpty(args.get("sSlaveId"))){
  771 + throw new BusinessException(-1,"请选择操作数据");
  772 + }
  773 + List<Map<String,Object>> sRowData = doGetFromDataWq( meta, args, session);
  774 + data.put("sRowData", JSONObject.toJSONString(sRowData));
  775 + }
  776 + Map<String, Object> searMap = this.dynamicExeDbService.getDoProMap(sBizContent, data);
  777 + Map<String, Object> sReturn = this.dynamicExeDbService.getCallPro(searMap, sBizContent);
  778 + Integer sCode = ObjectUtil.isNotEmpty(sReturn.get(ProcedureConstant.SCODE)) ? Integer.valueOf(sReturn.get(ProcedureConstant.SCODE).toString()) : 0;
  779 + String sMsgText = ObjectUtil.isNotEmpty(sReturn.get(ProcedureConstant.SRETURN)) ? sReturn.get(ProcedureConstant.SRETURN).toString() : "操作成功";
  780 + if (sCode < 0) {
  781 + sMsgText = ObjectUtil.isEmpty(sMsgText) ? "调用过程sCode:" + Integer.valueOf(searMap.get(ProcedureConstant.SCODE).toString()) : sMsgText;
  782 + session.setSFunPrompts(sMsgText);
  783 + throw new BusinessException(sCode,sMsgText);
  784 + }
  785 + Map<String,Object> outMap = (Map<String, Object>) sReturn.get("outMap");
  786 + String sId = ObjectUtil.isNotEmpty(outMap.get("sBillId")) ? outMap.get("sBillId").toString() : "";
  787 + session.setSCopyTo(meta.getSControlName());
  788 + session.setSCopyToSrcId(sId);
  789 + session.setSFunPrompts(sMsgText);
  790 + return sMsgText;
  791 + } else if (iBizType == 2 && ObjectUtil.isNotEmpty(sBizContent)) {
  792 + if (sBizContent.toLowerCase().startsWith("update")) {
  793 + this.dynamicExeDbService.updateSql(args, sBizContent);
  794 + } else if (sBizContent.toLowerCase().startsWith("delete")) {
  795 + this.dynamicExeDbService.delSql(args, sBizContent);
  796 + } else if (sBizContent.toLowerCase().startsWith("insert")) {
  797 + this.dynamicExeDbService.addSql(args, sBizContent);
  798 + } else {
  799 + List<Map<String, Object>> retData = this.dynamicExeDbService.findSql(args, sBizContent);
  800 + if (ObjectUtil.isNotEmpty(retData)) {
  801 + StringBuffer sb = new StringBuffer();
  802 + retData.forEach(one -> {
  803 + one.forEach((k, v) -> {
  804 + sb.append(v).append(" ");
  805 + });
  806 + sb.append("<br/>");
  807 + });
  808 + if (ObjectUtil.isNotEmpty(retData)) {
  809 + sb.append("请根据这些信息安排今天的工作吧!如果有具体任务需要进一步处理,请告诉我");
  810 + }
  811 + session.setSFunPrompts(sb.toString());
  812 + if ("queryTodayTask".equals(meta.getSMethodNo())) {
  813 + session.setBCleanMemory(true);
  814 + }
  815 + return sb.toString();
  816 + } else {
  817 + String sMsgText = "未找到对应的数据";
  818 + session.setSFunPrompts(sMsgText);
  819 + throw new BusinessException(-1,sMsgText);
  820 + }
  821 + }
  822 + } else if (iBizType == 3) {
  823 + return HttpsRequestUtil.me().doRequestHttp(sBizContent, JSONUtil.toJsonStr(args),
  824 + new HashMap<>(), "POST", "JSON");
  825 + }
  826 + return "操作成功";
1042 } 827 }
1043 828
1044 - /***  
1045 - * @Author  
1046 - * 确认获取未清数据  
1047 - **/  
1048 private List<Map<String,Object>> doGetFromDataWq(ToolMeta meta, Map<String, Object> args,UserSceneSession session){ 829 private List<Map<String,Object>> doGetFromDataWq(ToolMeta meta, Map<String, Object> args,UserSceneSession session){
1049 String sUrl = meta.getSendUrl(); 830 String sUrl = meta.getSendUrl();
1050 Map<String,Object> sBody = new HashMap<>(); 831 Map<String,Object> sBody = new HashMap<>();
@@ -1064,13 +845,9 @@ public class DynamicToolProvider implements ToolProvider { @@ -1064,13 +845,9 @@ public class DynamicToolProvider implements ToolProvider {
1064 headers.put("Authorization",session.getAuthorization()); 845 headers.put("Authorization",session.getAuthorization());
1065 String result; 846 String result;
1066 try{ 847 try{
1067 - // 1. 获取实例  
1068 result = HttpsRequestUtil.me().doRequestHttp(sUrl,JSONObject.toJSONString(sBody),headers,"POST","JSON"); 848 result = HttpsRequestUtil.me().doRequestHttp(sUrl,JSONObject.toJSONString(sBody),headers,"POST","JSON");
1069 log.info("请求URL========================{}", sUrl); 849 log.info("请求URL========================{}", sUrl);
1070 log.info("请求URLresult========================{}", result); 850 log.info("请求URLresult========================{}", result);
1071 - log.info("JSON==========================={}", JSONObject.toJSONString(sBody));  
1072 - log.info("headers=============================={}", JSONObject.toJSONString(headers));  
1073 - log.info("请求URL,JSON,headers=={},{},{}",sUrl,JSONObject.toJSONString(sBody),JSONObject.toJSONString(headers));  
1074 ErpResult erpResult = JsonUtils.toObject(result,ErpResult.class); 851 ErpResult erpResult = JsonUtils.toObject(result,ErpResult.class);
1075 if(ObjectUtil.isNotEmpty(erpResult) 852 if(ObjectUtil.isNotEmpty(erpResult)
1076 && ObjectUtil.isNotEmpty(erpResult.getDataset()) 853 && ObjectUtil.isNotEmpty(erpResult.getDataset())
@@ -1081,19 +858,10 @@ public class DynamicToolProvider implements ToolProvider { @@ -1081,19 +858,10 @@ public class DynamicToolProvider implements ToolProvider {
1081 return erpResult.getDataset().getRows().get(0).getDataSet(); 858 return erpResult.getDataset().getRows().get(0).getDataSet();
1082 } 859 }
1083 }catch (Exception e){ 860 }catch (Exception e){
1084 -// result ="执行异常:"+e.getMessage();  
1085 } 861 }
1086 return new ArrayList<>(); 862 return new ArrayList<>();
1087 } 863 }
1088 864
1089 -  
1090 - /***  
1091 - * @Author 钱豹  
1092 - * @Date 23:38 2026/2/5  
1093 - * @Param []  
1094 - * @return void  
1095 - * @Description 窗体获取数据方法 未清或者明细  
1096 - **/  
1097 private String doGetFromData(ToolMeta meta, Map<String, Object> args,UserSceneSession session){ 865 private String doGetFromData(ToolMeta meta, Map<String, Object> args,UserSceneSession session){
1098 String sUrl = meta.getSendUrl(); 866 String sUrl = meta.getSendUrl();
1099 Map<String,Object> sBody = new HashMap<>(); 867 Map<String,Object> sBody = new HashMap<>();
@@ -1101,7 +869,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -1101,7 +869,6 @@ public class DynamicToolProvider implements ToolProvider {
1101 sBody.put("pageSize",10000); 869 sBody.put("pageSize",10000);
1102 log.info("doGetFromData========================"); 870 log.info("doGetFromData========================");
1103 List<Map<String,Object>> list = new ArrayList<>(); 871 List<Map<String,Object>> list = new ArrayList<>();
1104 - //移除确认标识  
1105 args.remove("operateType"); 872 args.remove("operateType");
1106 if(ObjectUtil.isNotEmpty(args)){ 873 if(ObjectUtil.isNotEmpty(args)){
1107 List<ParamRule> paramDefs = meta.getParamRuleList(); 874 List<ParamRule> paramDefs = meta.getParamRuleList();
@@ -1140,13 +907,9 @@ public class DynamicToolProvider implements ToolProvider { @@ -1140,13 +907,9 @@ public class DynamicToolProvider implements ToolProvider {
1140 headers.put("Authorization",session.getAuthorization()); 907 headers.put("Authorization",session.getAuthorization());
1141 String result; 908 String result;
1142 try{ 909 try{
1143 - // 1. 获取实例  
1144 result = HttpsRequestUtil.me().doRequestHttp(sUrl,JSONObject.toJSONString(sBody),headers,"POST","JSON"); 910 result = HttpsRequestUtil.me().doRequestHttp(sUrl,JSONObject.toJSONString(sBody),headers,"POST","JSON");
1145 log.info("请求URL========================{}", sUrl); 911 log.info("请求URL========================{}", sUrl);
1146 log.info("请求URLresult========================{}", result); 912 log.info("请求URLresult========================{}", result);
1147 - log.info("JSON==========================={}", JSONObject.toJSONString(sBody));  
1148 - log.info("headers=============================={}", JSONObject.toJSONString(headers));  
1149 - log.info("请求URL,JSON,headers=={},{},{}",sUrl,JSONObject.toJSONString(sBody),JSONObject.toJSONString(headers));  
1150 ErpResult erpResult = JsonUtils.toObject(result,ErpResult.class); 913 ErpResult erpResult = JsonUtils.toObject(result,ErpResult.class);
1151 result = buildResultMessageWithTable( meta, erpResult, session); 914 result = buildResultMessageWithTable( meta, erpResult, session);
1152 }catch (Exception e){ 915 }catch (Exception e){
@@ -1155,13 +918,9 @@ public class DynamicToolProvider implements ToolProvider { @@ -1155,13 +918,9 @@ public class DynamicToolProvider implements ToolProvider {
1155 return result; 918 return result;
1156 } 919 }
1157 920
1158 - /**  
1159 - * 构建 窗体获取数据方法 未清或者明细  
1160 - */  
1161 public String buildResultMessageWithTable(ToolMeta meta,ErpResult erpResult,UserSceneSession session){ 921 public String buildResultMessageWithTable(ToolMeta meta,ErpResult erpResult,UserSceneSession session){
1162 Map<Integer,Map<String,Object>> currentRowData = new HashMap<>(); 922 Map<Integer,Map<String,Object>> currentRowData = new HashMap<>();
1163 ErpDataset dataset = erpResult.getDataset(); 923 ErpDataset dataset = erpResult.getDataset();
1164 - //返回错误信息  
1165 if(erpResult.getCode()<0 && ObjectUtil.isNotEmpty(erpResult.getMsg())){ 924 if(erpResult.getCode()<0 && ObjectUtil.isNotEmpty(erpResult.getMsg())){
1166 return erpResult.getMsg(); 925 return erpResult.getMsg();
1167 } 926 }
@@ -1175,7 +934,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -1175,7 +934,6 @@ public class DynamicToolProvider implements ToolProvider {
1175 } 934 }
1176 List<Map<String, Object>> recordData = findFieldNameByChinese(sAIshowfieldShow, rows); 935 List<Map<String, Object>> recordData = findFieldNameByChinese(sAIshowfieldShow, rows);
1177 int recordCount = dataset != null ? dataset.getTotalCount() : 0; 936 int recordCount = dataset != null ? dataset.getTotalCount() : 0;
1178 - // 动态生成表头  
1179 Set<String> headers = new LinkedHashSet<>(); 937 Set<String> headers = new LinkedHashSet<>();
1180 for (Map<String, Object> record : sAIshowfieldShow) { 938 for (Map<String, Object> record : sAIshowfieldShow) {
1181 String chineseName = (String) record.get("label"); 939 String chineseName = (String) record.get("label");
@@ -1185,7 +943,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -1185,7 +943,6 @@ public class DynamicToolProvider implements ToolProvider {
1185 } 943 }
1186 944
1187 StringBuilder markdown = new StringBuilder(); 945 StringBuilder markdown = new StringBuilder();
1188 - //状态  
1189 if(ObjectUtil.isNotEmpty(session.getArgs())){ 946 if(ObjectUtil.isNotEmpty(session.getArgs())){
1190 markdown.append("**查询条件**:"); 947 markdown.append("**查询条件**:");
1191 List<ParamRule> pr = session.getCurrentTool().getParamRuleListCheck(); 948 List<ParamRule> pr = session.getCurrentTool().getParamRuleListCheck();
@@ -1205,7 +962,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -1205,7 +962,6 @@ public class DynamicToolProvider implements ToolProvider {
1205 .append(one.getSParam()).append(":").append(argsOld.get(one.getSParam()).toString()).append(" ") 962 .append(one.getSParam()).append(":").append(argsOld.get(one.getSParam()).toString()).append(" ")
1206 .append(" <span style=\"font-weight: bold;font-size: 22px;position: absolute;right: -5px;top: -12px;color: #ff4d4f;display: inline-block;\" data-action=\"clearSql\" data-text=\""+one.getSParam()+","+one.getSParamValue()+"\" onclick=\"clearSql('"+one.getSParam()+","+one.getSParamValue()+"')\"> × </span>") 963 .append(" <span style=\"font-weight: bold;font-size: 22px;position: absolute;right: -5px;top: -12px;color: #ff4d4f;display: inline-block;\" data-action=\"clearSql\" data-text=\""+one.getSParam()+","+one.getSParamValue()+"\" onclick=\"clearSql('"+one.getSParam()+","+one.getSParamValue()+"')\"> × </span>")
1207 .append("</span>"); 964 .append("</span>");
1208 -// markdown.append(one.getSParam()).append(":").append(argsOld.get(one.getSParam()).toString()).append(" ");  
1209 } 965 }
1210 } 966 }
1211 } 967 }
@@ -1225,39 +981,29 @@ public class DynamicToolProvider implements ToolProvider { @@ -1225,39 +981,29 @@ public class DynamicToolProvider implements ToolProvider {
1225 markdown.append(",显示前").append(rows.size()).append("条。如需查看全部,请指定筛选条件。"); 981 markdown.append(",显示前").append(rows.size()).append("条。如需查看全部,请指定筛选条件。");
1226 } 982 }
1227 } 983 }
1228 -// markdown.append("\n---\n");  
1229 markdown.append("\n\n").append("| 序号 | "); 984 markdown.append("\n\n").append("| 序号 | ");
1230 headers.forEach(header -> markdown.append(header).append(" | ")); 985 headers.forEach(header -> markdown.append(header).append(" | "));
1231 markdown.append("\n|").append("---|".repeat(headers.size() + 1)).append("\n"); 986 markdown.append("\n|").append("---|".repeat(headers.size() + 1)).append("\n");
1232 - // 填充表格数据  
1233 List<Map<String,Object>> machineData = new LinkedList<>(); 987 List<Map<String,Object>> machineData = new LinkedList<>();
1234 for (int i = 0; i < recordData.size(); i++) { 988 for (int i = 0; i < recordData.size(); i++) {
1235 - // 保存隐藏列的值(如"唯一"字段)  
1236 String uniqueValue = recordData.get(i).get("sSlaveId") != null ? recordData.get(i).get("sSlaveId").toString() : ""; 989 String uniqueValue = recordData.get(i).get("sSlaveId") != null ? recordData.get(i).get("sSlaveId").toString() : "";
1237 markdown.append("| ").append(i + 1).append(" | "); 990 markdown.append("| ").append(i + 1).append(" | ");
1238 Map<String,Object> rMap = new HashMap<>(); 991 Map<String,Object> rMap = new HashMap<>();
1239 for (String header : headers) { 992 for (String header : headers) {
1240 - // 这里需要根据你的数据结构来获取对应的值  
1241 Object value = recordData.get(i)!= null ? recordData.get(i).get(header) : null; 993 Object value = recordData.get(i)!= null ? recordData.get(i).get(header) : null;
1242 markdown.append(value != null ? value : "—").append(" | "); 994 markdown.append(value != null ? value : "—").append(" | ");
1243 rMap.put(header,value); 995 rMap.put(header,value);
1244 } 996 }
1245 rMap.put("sSlaveId",uniqueValue); 997 rMap.put("sSlaveId",uniqueValue);
1246 rMap.put("唯一",uniqueValue); 998 rMap.put("唯一",uniqueValue);
1247 - // 在行末添加隐藏数据的特殊标记(AI可以解析)  
1248 markdown.append(" <span style=\"display:none;\">HIDDEN_DATA:") 999 markdown.append(" <span style=\"display:none;\">HIDDEN_DATA:")
1249 .append(JSONUtil.toJsonStr(rMap)) 1000 .append(JSONUtil.toJsonStr(rMap))
1250 .append("</span>"); 1001 .append("</span>");
1251 -// markdown.append(" <!-- HIDDEN_DATA:").append(JSONUtil.toJsonStr(rMap)).append("-->");  
1252 markdown.append("\n"); 1002 markdown.append("\n");
1253 machineData.add(rMap); 1003 machineData.add(rMap);
1254 currentRowData.put(i + 1,recordData.get(i)); 1004 currentRowData.put(i + 1,recordData.get(i));
1255 } 1005 }
1256 markdown.append(">"); 1006 markdown.append(">");
1257 -// // 4. 机器可读的结构化数据(只出现一次!)  
1258 -// markdown.append("<!-- MACHINE_DATA_START -->\n");  
1259 -// markdown.append(JSONUtil.toJsonStr(machineData));  
1260 -// markdown.append("\n<!-- MACHINE_DATA_END -->\n\n");  
1261 if(meta.getIBizType()==4){ 1007 if(meta.getIBizType()==4){
1262 markdown.append("\n---\n"); 1008 markdown.append("\n---\n");
1263 appendConfirmAll(markdown,meta.getSControlName()); 1009 appendConfirmAll(markdown,meta.getSControlName());
@@ -1295,40 +1041,8 @@ public class DynamicToolProvider implements ToolProvider { @@ -1295,40 +1041,8 @@ public class DynamicToolProvider implements ToolProvider {
1295 } 1041 }
1296 """.formatted(rowJson, methodNo); 1042 """.formatted(rowJson, methodNo);
1297 } 1043 }
1298 -// public String buildDynamicSystemPrompt(UserSceneSession session) {  
1299 -// // 动态获取当前工具方法号  
1300 -// String methodNo = session.getCurrentTool().getSMethodNo();  
1301 -// String promptHead = """  
1302 -// 【极强约束·必须执行】  
1303 -// 1. 禁止说话!禁止解释!  
1304 -// 2. 必须调用工具,固定方法编号:MethodNo = %s  
1305 -// 3. 只输出JSON,无任何其他内容  
1306 -// 以下是【行号 → sSlaveId】对应数据:  
1307 -// """.formatted(methodNo);  
1308 -//  
1309 -// Map<Integer, Map<String, Object>> rowDataMap = session.getCurrentRowData();  
1310 -// StringBuilder rowDataSb = new StringBuilder();  
1311 -// if (ObjectUtil.isNotEmpty(rowDataMap)) {  
1312 -// for (Map.Entry<Integer, Map<String, Object>> entry : rowDataMap.entrySet()) {  
1313 -// int rowNum = entry.getKey();  
1314 -// String sSlaveId = StrUtil.toString(entry.getValue().get("sSlaveId"));  
1315 -// rowDataSb.append("第").append(rowNum).append("行 → ").append(sSlaveId).append("\n");  
1316 -// }  
1317 -// }  
1318 -// String promptFoot = """  
1319 -// 【输出JSON格式·严格遵守】  
1320 -// 根据用户选择的行,自动填写 sSlaveId,多行用英文逗号拼接  
1321 -// {  
1322 -// "operateType": "全部确认/合并确认/单行确认",  
1323 -// "sSlaveId": "填写对应的ID,多个用逗号分隔"  
1324 -// }  
1325 -// """;  
1326 -// return promptHead + rowDataSb + promptFoot;  
1327 -// }  
1328 -  
1329 - // 辅助方法:根据中文名查找字段名(通过映射关系转换) 1044 +
1330 private List<Map<String, Object>> findFieldNameByChinese(List<Map<String, Object>> sAIshowfieldShow,List<Map<String, Object>> rows){ 1045 private List<Map<String, Object>> findFieldNameByChinese(List<Map<String, Object>> sAIshowfieldShow,List<Map<String, Object>> rows){
1331 - //获取映射关系  
1332 Map<String,String> keyMappings = new HashMap<>(); 1046 Map<String,String> keyMappings = new HashMap<>();
1333 List<String> selectedKeys = new ArrayList<>(); 1047 List<String> selectedKeys = new ArrayList<>();
1334 sAIshowfieldShow.forEach(one->{ 1048 sAIshowfieldShow.forEach(one->{
@@ -1342,13 +1056,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -1342,13 +1056,6 @@ public class DynamicToolProvider implements ToolProvider {
1342 return sRowData; 1056 return sRowData;
1343 } 1057 }
1344 1058
1345 - /***  
1346 - * @Author 钱豹  
1347 - * @Date 2:04 2026/2/6  
1348 - * @Param [rows, limit, selectedKeys]  
1349 - * @return java.util.List<java.util.Map<java.lang.String,java.lang.Object>>  
1350 - * @Description 返回指定数量并筛选指定key  
1351 - **/  
1352 public List<Map<String, Object>> getFilteredDataStream(List<Map<String, Object>> rows, 1059 public List<Map<String, Object>> getFilteredDataStream(List<Map<String, Object>> rows,
1353 int limit, 1060 int limit,
1354 List<String> selectedKeys, 1061 List<String> selectedKeys,
@@ -1357,13 +1064,11 @@ public class DynamicToolProvider implements ToolProvider { @@ -1357,13 +1064,11 @@ public class DynamicToolProvider implements ToolProvider {
1357 return Collections.emptyList(); 1064 return Collections.emptyList();
1358 } 1065 }
1359 return rows.stream() 1066 return rows.stream()
1360 - .limit(limit) // 限制数量 1067 + .limit(limit)
1361 .map(original -> { 1068 .map(original -> {
1362 - // 创建新的Map,只包含指定key  
1363 Map<String, Object> filtered = new HashMap<>(); 1069 Map<String, Object> filtered = new HashMap<>();
1364 selectedKeys.forEach(key -> { 1070 selectedKeys.forEach(key -> {
1365 if (original.containsKey(key)) { 1071 if (original.containsKey(key)) {
1366 - //指定映射的key 放中文  
1367 filtered.put(keyMappings.get(key), original.get(key)); 1072 filtered.put(keyMappings.get(key), original.get(key));
1368 } 1073 }
1369 }); 1074 });
@@ -1373,9 +1078,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -1373,9 +1078,6 @@ public class DynamicToolProvider implements ToolProvider {
1373 .collect(Collectors.toList()); 1078 .collect(Collectors.toList());
1374 } 1079 }
1375 1080
1376 - /**  
1377 - * 构建确认操作消息  
1378 - */  
1379 private String buildConfirmUserMessage(ToolMeta meta, Map<String, Object> args) { 1081 private String buildConfirmUserMessage(ToolMeta meta, Map<String, Object> args) {
1380 StringBuilder markdown = new StringBuilder(); 1082 StringBuilder markdown = new StringBuilder();
1381 markdown.append("参数提取如下:\n\n"); 1083 markdown.append("参数提取如下:\n\n");
@@ -1390,11 +1092,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -1390,11 +1092,6 @@ public class DynamicToolProvider implements ToolProvider {
1390 return markdown.toString(); 1092 return markdown.toString();
1391 } 1093 }
1392 1094
1393 -  
1394 -  
1395 - /**  
1396 - * 构建提问消息  
1397 - */  
1398 private String buildAskUserMessage(ToolMeta meta, List<String> missing,Map<String,Object> arg) { 1095 private String buildAskUserMessage(ToolMeta meta, List<String> missing,Map<String,Object> arg) {
1399 StringBuilder sb = new StringBuilder(); 1096 StringBuilder sb = new StringBuilder();
1400 sb.append("缺少参数请补全:\n"); 1097 sb.append("缺少参数请补全:\n");
@@ -1429,18 +1126,15 @@ public class DynamicToolProvider implements ToolProvider { @@ -1429,18 +1126,15 @@ public class DynamicToolProvider implements ToolProvider {
1429 return sb.toString(); 1126 return sb.toString();
1430 } 1127 }
1431 1128
1432 - // 创建提前成功的结果  
1433 private String createEarlySuccessResult(ToolExecutionRequest request, String message) { 1129 private String createEarlySuccessResult(ToolExecutionRequest request, String message) {
1434 - // 设置一个标志,告诉执行器不要继续执行  
1435 return JSONUtil.toJsonStr(Map.of( 1130 return JSONUtil.toJsonStr(Map.of(
1436 "status", "success", 1131 "status", "success",
1437 "message", message, 1132 "message", message,
1438 - // 关键标志  
1439 "executionCompleted", true, 1133 "executionCompleted", true,
1440 "data", successResult(request, message) 1134 "data", successResult(request, message)
1441 )); 1135 ));
1442 } 1136 }
1443 - // 创建终止执行的结果 1137 +
1444 private String createTerminationResult(String message) { 1138 private String createTerminationResult(String message) {
1445 return JSONUtil.toJsonStr(Map.of( 1139 return JSONUtil.toJsonStr(Map.of(
1446 "status", "terminated", 1140 "status", "terminated",
@@ -1449,70 +1143,30 @@ public class DynamicToolProvider implements ToolProvider { @@ -1449,70 +1143,30 @@ public class DynamicToolProvider implements ToolProvider {
1449 )); 1143 ));
1450 } 1144 }
1451 1145
1452 - /***  
1453 - * @Author 钱豹  
1454 - * @Date 10:15 2026/1/31  
1455 - * @Param [request, errorMsg]  
1456 - * @return dev.langchain4j.data.message.ToolExecutionResultMessage  
1457 - * @Description 错误返回  
1458 - **/  
1459 private ToolExecutionResultMessage errorResult(ToolExecutionRequest request, String errorMsg) { 1146 private ToolExecutionResultMessage errorResult(ToolExecutionRequest request, String errorMsg) {
1460 return ToolExecutionResultMessage.from(request, errorMsg); 1147 return ToolExecutionResultMessage.from(request, errorMsg);
1461 } 1148 }
1462 - /***  
1463 - * @Author 钱豹  
1464 - * @Date 10:15 2026/1/31  
1465 - * @Param [request, text]  
1466 - * @return dev.langchain4j.data.message.ToolExecutionResultMessage  
1467 - * @Description 构建正确返回  
1468 - **/ 1149 +
1469 private ToolExecutionResultMessage successResult(ToolExecutionRequest request, String text) { 1150 private ToolExecutionResultMessage successResult(ToolExecutionRequest request, String text) {
1470 return ToolExecutionResultMessage.from(request, text); 1151 return ToolExecutionResultMessage.from(request, text);
1471 } 1152 }
1472 1153
1473 - /**  
1474 - * 执行方法后需要用户确认的扩展版本  
1475 - */  
1476 private String executeWithConfirmation(String initialResult, UserSceneSession session,ToolMeta meta) { 1154 private String executeWithConfirmation(String initialResult, UserSceneSession session,ToolMeta meta) {
1477 -  
1478 - // 第一步:执行原始操作,返回初步结果  
1479 Map<String, Object> step1Result = new HashMap<>(); 1155 Map<String, Object> step1Result = new HashMap<>();
1480 step1Result.put("initialResult", initialResult); 1156 step1Result.put("initialResult", initialResult);
1481 step1Result.put("status", "PENDING_CONFIRMATION"); 1157 step1Result.put("status", "PENDING_CONFIRMATION");
1482 step1Result.put("confirmationRequired", true); 1158 step1Result.put("confirmationRequired", true);
1483 step1Result.put("confirmationMessage", initialResult); 1159 step1Result.put("confirmationMessage", initialResult);
1484 -// // 将确认状态保存到对话记忆  
1485 -// chatMemory.add(UserMessage.from("SYSTEM: 等待用户确认操作"));  
1486 String userMessage = formatConfirmationResult(step1Result); 1160 String userMessage = formatConfirmationResult(step1Result);
1487 session.setCurrentTool(meta); 1161 session.setCurrentTool(meta);
1488 -// session.setSFunPrompts(userMessage);  
1489 - // 6. 返回确认请求  
1490 -// return ToolExecutionResultMessage.from(request,userMessage);  
1491 -// ToolExecutionResultMessage.from(request, text);  
1492 return userMessage; 1162 return userMessage;
1493 } 1163 }
1494 1164
1495 private String formatConfirmationResult(Map<String, Object> result) { 1165 private String formatConfirmationResult(Map<String, Object> result) {
1496 - return String.format(  
1497 - """  
1498 - %s  
1499 - """,  
1500 - result.get("initialResult"),  
1501 - result.get("confirmationMessage")  
1502 - ); 1166 + return String.format("%s", result.get("initialResult"));
1503 } 1167 }
1504 1168
1505 - /***  
1506 - * @Author 钱豹  
1507 - * @Date 0:54 2026/2/4  
1508 - * @Param [userResponse]  
1509 - * @return boolean  
1510 - * @Description 检查是确认  
1511 - **/  
1512 public boolean isConfirmed(String userResponse) { 1169 public boolean isConfirmed(String userResponse) {
1513 return userResponse.matches("(?i)(确认|全部确认|部分确认|是|yes|confirm|true|是的|可以|没问题|确定|好的|生成|)"); 1170 return userResponse.matches("(?i)(确认|全部确认|部分确认|是|yes|confirm|true|是的|可以|没问题|确定|好的|生成|)");
1514 } 1171 }
1515 -  
1516 -  
1517 -  
1518 -} 1172 +}
1519 \ No newline at end of file 1173 \ No newline at end of file
src/main/java/com/xly/tool/ToolSpecificationHolder.java
@@ -7,9 +7,11 @@ import dev.langchain4j.agent.tool.ToolSpecification; @@ -7,9 +7,11 @@ import dev.langchain4j.agent.tool.ToolSpecification;
7 public class ToolSpecificationHolder { 7 public class ToolSpecificationHolder {
8 private final ToolSpecification toolSpecification; 8 private final ToolSpecification toolSpecification;
9 private final ToolExecutor toolExecutor; 9 private final ToolExecutor toolExecutor;
10 - public ToolSpecificationHolder(ToolSpecification toolSpecification, ToolExecutor toolExecutor) { 10 + private final String sName;
  11 + public ToolSpecificationHolder(ToolSpecification toolSpecification, ToolExecutor toolExecutor,String sName) {
11 this.toolSpecification = toolSpecification; 12 this.toolSpecification = toolSpecification;
12 this.toolExecutor = toolExecutor; 13 this.toolExecutor = toolExecutor;
  14 + this.sName = sName;
13 } 15 }
14 16
15 public ToolSpecification getToolSpecification() { 17 public ToolSpecification getToolSpecification() {
@@ -18,4 +20,11 @@ public class ToolSpecificationHolder { @@ -18,4 +20,11 @@ public class ToolSpecificationHolder {
18 20
19 public ToolExecutor getToolExecutor() { 21 public ToolExecutor getToolExecutor() {
20 return toolExecutor; 22 return toolExecutor;
21 - }} 23 + }
  24 +
  25 + public String getsName() {
  26 + return sName;
  27 + }
  28 +
  29 +}
  30 +
src/main/resources/application.yml
@@ -135,8 +135,8 @@ langchain4j: @@ -135,8 +135,8 @@ langchain4j:
135 ollama: 135 ollama:
136 # 聊天模型配置(用于一般对话) 136 # 聊天模型配置(用于一般对话)
137 base-url: http://112.82.245.194:11434 137 base-url: http://112.82.245.194:11434
138 -# chat-model-name: qwen2.5:7b-instruct  
139 - chat-model-name: qwen3:14b 138 + chat-model-name: qwen2.5:7b-instruct
  139 +# chat-model-name: qwen3:14b
140 # chat-model-name: qwen3.5:9b 140 # chat-model-name: qwen3.5:9b
141 # SQL/代码模型配置(专门用于代码和SQL生成) 141 # SQL/代码模型配置(专门用于代码和SQL生成)
142 sql-model-name: qwen2.5-coder:7b 142 sql-model-name: qwen2.5-coder:7b
@@ -171,4 +171,4 @@ tts: @@ -171,4 +171,4 @@ tts:
171 timeout: 30000 171 timeout: 30000
172 max-connections: 10 172 max-connections: 10
173 erp: 173 erp:
174 - baseurl: http://8.130.144.93:8080/xlyEntry_saas  
175 \ No newline at end of file 174 \ No newline at end of file
  175 + baseurl: http://118.178.19.35:8080/xlyEntry_saas
176 \ No newline at end of file 176 \ No newline at end of file