Commit f0318b7bafc221490c485a944620d9658d7d751a

Authored by qianbao
1 parent 1b14dc87

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

src/main/java/com/xly/agent/SystemPromptGenerator.java
1 1 package com.xly.agent;
2 2  
3 3 import cn.hutool.core.util.ObjectUtil;
4   -import cn.hutool.json.JSONConfig;
5   -import cn.hutool.json.JSONUtil;
6 4 import com.alibaba.fastjson2.JSON;
7 5 import com.alibaba.fastjson2.JSONObject;
8 6 import com.alibaba.fastjson2.JSONWriter;
... ... @@ -10,6 +8,7 @@ import com.xly.entity.ParamRule;
10 8 import com.xly.entity.UserSceneSession;
11 9  
12 10 import java.util.List;
  11 +import java.util.stream.Collectors;
13 12  
14 13 public class SystemPromptGenerator {
15 14  
... ... @@ -50,4 +49,64 @@ public class SystemPromptGenerator {
50 49  
51 50 return sb.toString();
52 51 }
  52 +
  53 + /**
  54 + * 缺失参数统一提示模板:强制AI调用自定义方法,一次性回填所有参数
  55 + */
  56 + public static String buildMissParamPrompt(UserSceneSession session, List<ParamRule> paramRuleDataMiss) {
  57 + String methodNo = session.getCurrentTool().getSMethodNo();
  58 + // 1. 拼接缺失参数的描述(增加“参数名”和“英文名”的对应,方便模型映射)
  59 + String paramDesc = paramRuleDataMiss.stream()
  60 + .map(p -> String.format("- 参数名:%s (对应字段: %s),示例值:%s",
  61 + p.getSParam(), p.getSParamValue(), p.getSExampleValue()))
  62 + .collect(Collectors.joining("\n"));
  63 + // 但根据你的需求,其实 prompt 里并不需要强行插入一个空的 JSON 片段,
  64 + // 直接告诉模型去“合并”即可。
  65 + return String.format("""
  66 + 请你根据用户最新的输入,补充缺失的参数,并带着【所有完整参数】立即发起工具调用。
  67 +
  68 + 【核心执行规则】
  69 + 1. **参数合并(至关重要)**:你必须保留上一轮对话中已经获取的参数(如 sSlaveId, operateType 等),并将用户本次提供的新参数与旧参数合并。
  70 + 2. **必须调用工具**:必须调用工具 `%s`。绝对禁止直接输出 JSON 文本,也绝对禁止向用户反问或索要信息。
  71 + 3. **完整调用**:请直接生成包含所有参数的 tool_calls 请求。
  72 + 【已获取数据】
  73 + %s
  74 + 【当前缺失的参数说明】
  75 + %s
  76 + """, methodNo,JSONObject.toJSONString(session.getArgs()), paramDesc);
  77 + }
  78 +
  79 + public static String buildDynamicSystemPrompt(UserSceneSession session) {
  80 + // 获取当前工具编号(用于 JSON 的 name 字段)
  81 + String methodNo = session.getCurrentTool().getSMethodNo();
  82 + return """
  83 + 【极强约束·必须执行】
  84 + 1. 禁止说话!禁止解释!
  85 + 2. 必须调用工具!
  86 + 3. 只输出标准工具调用JSON!
  87 +
  88 + ### 任务背景 ###
  89 + 用户会输入自然语言指令(如“第1行确认”、“全部合并”等)。
  90 + 你的任务是:解析出【操作类型】和【目标行号】。
  91 +
  92 + ### 解析规则(必须严格遵守) ###
  93 +
  94 + 1. **操作类型 (operateType)**:
  95 + - 如果用户说“全部确认”、“生成多个单据”,识别为:"全部确认"
  96 + - 如果用户说“合并确认”、“生成一个单据”,识别为:"合并确认"
  97 + - 其他情况,默认为:"单行确认"
  98 +
  99 + 2. **行号提取 (rowNumbers)**:
  100 + - 单选:如“第5行”,提取为 [5]
  101 + - 多选:如“第1、3、5行”,提取为 [1, 3, 5]
  102 + - 范围:如“第2到4行”,提取为 [2, 3, 4]
  103 + - 全选:如“全部”、“所有”,提取为 ["ALL"]
  104 +
  105 + ### 输出格式规范 ###
  106 + 请直接输出以下 JSON(不要任何 Markdown 格式,不要 ```json):
  107 + {"name": "%s", "parameters": {"operateType": "解析出的类型", "rowNumbers": [行号数组或"ALL"]}}
  108 +
  109 + """.formatted(methodNo);
  110 + }
  111 +
53 112 }
54 113 \ No newline at end of file
... ...
src/main/java/com/xly/constant/ReturnTypeCode.java
... ... @@ -14,6 +14,7 @@ public enum ReturnTypeCode {
14 14  
15 15 // 成功
16 16 HTML("html", "html"),
  17 + JSON("JSON", "JSON"),
17 18 STREAM("stream", "stream"),
18 19 MAKEDOWN("makedown", "makedown");
19 20  
... ...
src/main/java/com/xly/entity/ParamRule.java
... ... @@ -3,6 +3,8 @@ package com.xly.entity;
3 3 import lombok.Data;
4 4  
5 5 import java.time.LocalDateTime;
  6 +import java.util.List;
  7 +import java.util.Map;
6 8  
7 9 /***
8 10 * @Author 钱豹
... ... @@ -32,6 +34,9 @@ public class ParamRule {
32 34 private String sDynamicParamRuleSql;
33 35 private String sDynamicParam;
34 36 private String sDynamicParamName;
  37 + private String sGroup;
  38 + private Object sParamConfigValue;
  39 + private Boolean bStandardParam;
35 40 private Boolean bDynamicParam = false;
36 41  
37 42 }
... ...
src/main/java/com/xly/entity/ToolMeta.java
... ... @@ -53,5 +53,6 @@ public class ToolMeta {
53 53 private String sVectorfiledAll;
54 54 private String sVectorfiledShow;
55 55 private Boolean sQue = false;
  56 + private Boolean bQuo = false;
56 57  
57 58 }
... ...
src/main/java/com/xly/service/QuoService.java 0 → 100644
  1 +package com.xly.service;
  2 +
  3 +import cn.hutool.core.text.CharSequenceUtil;
  4 +import cn.hutool.core.util.ObjectUtil;
  5 +import cn.hutool.core.util.StrUtil;
  6 +import cn.hutool.json.JSONUtil;
  7 +import com.alibaba.fastjson2.JSONObject;
  8 +import com.xly.agent.SystemPromptGenerator;
  9 +import com.xly.constant.ErrorCode;
  10 +import com.xly.constant.ProcedureConstant;
  11 +import com.xly.entity.ParamRule;
  12 +import com.xly.entity.ToolMeta;
  13 +import com.xly.entity.UserSceneSession;
  14 +import com.xly.exception.dto.BusinessException;
  15 +import com.xly.mapper.DynamicExeDbMapper;
  16 +import com.xly.util.DeepCopyUtils;
  17 +import lombok.RequiredArgsConstructor;
  18 +import lombok.extern.slf4j.Slf4j;
  19 +import org.apache.commons.lang3.StringUtils;
  20 +import org.springframework.stereotype.Service;
  21 +
  22 +import java.util.*;
  23 +import java.util.stream.Collectors;
  24 +import java.util.stream.Stream;
  25 +
  26 +/***
  27 + * @Author 钱豹
  28 + * @Date 0:06 2026/7/7
  29 + * @Param
  30 + * @return
  31 + * @Description 报价业务类
  32 + **/
  33 +@Slf4j
  34 +@Service("quoService")
  35 +@RequiredArgsConstructor
  36 +public class QuoService {
  37 +
  38 +
  39 + /***
  40 + * @Author 钱豹
  41 + * @Date 1:25 2026/7/7
  42 + * @Param [argsNew, session, dynamicParamRule]
  43 + * @return java.util.Map<java.lang.String,java.lang.Object>
  44 + * @Description 报价获取参数组装
  45 + **/
  46 + public Map<String,Object> getQuoData(Map<String,Object> argsNew, UserSceneSession session, List<ParamRule> dynamicParamRule){
  47 + //获取当前方法
  48 + Map<String,Object> retData = new HashMap<>();
  49 + ToolMeta meta = session.getCurrentTool();
  50 + //放入方法动态参数中
  51 + meta.setDynamicParamRule(dynamicParamRule);
  52 + session.setCurrentTool(meta);
  53 + Map<String, Object> argsOld = session.getArgs();
  54 + Map<String, Object> args = DeepCopyUtils.deepCopy(argsNew);
  55 + if(ObjectUtil.isEmpty(argsOld)){
  56 + argsOld = new HashMap<>();
  57 + }
  58 + argsOld.putAll(args);
  59 + session.setArgs(argsOld);
  60 + List<ParamRule> dataAll = session.getCurrentTool().getParamRuleListAll();
  61 + //获取产品的参数
  62 + List<ParamRule> dataProduct = dataAll.stream().filter(one-> "产品".equals(one.getSGroup()) && !one.getBDynamicParam() ).collect(Collectors.toUnmodifiableList());
  63 + List<ParamRule> dataPart = dataAll.stream().filter(one-> "部件".equals(one.getSGroup()) && !one.getBDynamicParam()).collect(Collectors.toUnmodifiableList());
  64 + List<ParamRule> datasDynamicPart = dataAll.stream().filter(one-> "sDynamicPart".equals(one.getSParamValue()) && !one.getBDynamicParam()).collect(Collectors.toUnmodifiableList());
  65 + List<Map<String,Object>> sAll = new ArrayList<>();
  66 + List<Map<String,Object>> productList = new ArrayList<>();
  67 + Map<String, Object> finalArgsOld = argsOld;
  68 + dataProduct.forEach(p->{
  69 + Map<String,Object> product = new HashMap<>();
  70 + String sValue = ObjectUtil.isNotEmpty(finalArgsOld.get(p.getSParam()))? finalArgsOld.get(p.getSParam()).toString():(ObjectUtil.isNotEmpty(finalArgsOld.get(p.getSParam()))? finalArgsOld.get(p.getSParam()).toString():StrUtil.EMPTY);
  71 + product.put("sName",p.getSParamValue());
  72 + product.put("showName",p.getSParam());
  73 + product.put("bEmpty",p.getBEmpty());
  74 + product.put("sValue", sValue);
  75 + product.put("sParamMissMemo", p.getSParamMissMemo()==null?StrUtil.EMPTY:p.getSParamMissMemo());
  76 + product.put("iOrder", p.getIOrder());
  77 + product.put("sParamConfigValue",p.getSParamConfigValue()==null?StrUtil.EMPTY:p.getSParamConfigValue());
  78 + productList.add(product);
  79 + });
  80 + List<Map<String,Object>> partList = new ArrayList<>();
  81 + dataPart.forEach(p->{
  82 + Map<String,Object> part = new HashMap<>();
  83 + String sValue = ObjectUtil.isNotEmpty(finalArgsOld.get(p.getSParam()))?finalArgsOld.get(p.getSParam()).toString():(ObjectUtil.isNotEmpty(finalArgsOld.get(p.getSParam()))? finalArgsOld.get(p.getSParam()).toString():StrUtil.EMPTY);
  84 + part.put("sPartName",p.getSParam().split("-")[0]);
  85 + part.put("sName",p.getSParamValue());
  86 + part.put("showName",p.getSParam());
  87 + part.put("bEmpty",p.getBEmpty());
  88 + part.put("sValue", sValue);
  89 + part.put("iOrder", p.getIOrder());
  90 + part.put("sParamMissMemo", p.getSParamMissMemo()==null?StrUtil.EMPTY:p.getSParamMissMemo());
  91 + part.put("sParamConfigValue",p.getSParamConfigValue()==null?StrUtil.EMPTY:p.getSParamConfigValue());
  92 + //获取动态参数
  93 + if(ObjectUtil.isNotEmpty(sValue)){
  94 + List<ParamRule> dataParamDynamic = dataAll.stream().filter(d -> sValue.equals(d.getSDynamicParam()) && p.getSParamValue().equals(d.getSDynamicParamName())&&d.getBDynamicParam()).collect(Collectors.toUnmodifiableList());
  95 + if(ObjectUtil.isNotEmpty(dataParamDynamic)){
  96 + List<Map<String,Object>> dynamicData = new ArrayList<>();
  97 + dataParamDynamic.forEach(dynamic->{
  98 + Map<String,Object> dynamicOne = new HashMap<>();
  99 + String dynamicValue = ObjectUtil.isNotEmpty(finalArgsOld.get(dynamic.getSParam()))?finalArgsOld.get(dynamic.getSParam()).toString():(ObjectUtil.isNotEmpty(finalArgsOld.get(dynamic.getSParam()))? finalArgsOld.get(dynamic.getSParam()).toString():StrUtil.EMPTY);
  100 + dynamicOne.put("sName",dynamic.getSParamValue());
  101 + dynamicOne.put("showName",dynamic.getSParam());
  102 + dynamicOne.put("bEmpty",dynamic.getBEmpty());
  103 + dynamicOne.put("sValue", dynamicValue);
  104 + dynamicOne.put("iOrder", dynamic.getIOrder());
  105 + dynamicOne.put("sParamMissMemo", dynamic.getSParamMissMemo()==null?StrUtil.EMPTY:dynamic.getSParamMissMemo());
  106 + dynamicOne.put("sParamConfigValue",dynamic.getSParamConfigValue()==null?StrUtil.EMPTY:dynamic.getSParamConfigValue());
  107 + //获取动态参数
  108 + dynamicData.add(dynamicOne);
  109 + });
  110 + sAll.addAll(dynamicData);
  111 + part.put("dynamicData",dynamicData);
  112 + }
  113 + }
  114 +
  115 + partList.add(part);
  116 + });
  117 + //动态部件
  118 + if(ObjectUtil.isNotEmpty(datasDynamicPart)){
  119 + String datasDynamicPartValue = ObjectUtil.isNotEmpty(finalArgsOld.get("sDynamicPart"))? finalArgsOld.get("sDynamicPart").toString(): StrUtil.EMPTY;
  120 +// :(ObjectUtil.isNotEmpty(finalArgsOld.get(p.getSParam()))? finalArgsOld.get(p.getSParam()).toString():StrUtil.EMPTY);
  121 + if(StrUtil.isNotEmpty(datasDynamicPartValue)){
  122 + List<String> datasDynamicPartArray = Collections.singletonList(JSONObject.parseObject(datasDynamicPartValue, String.class));
  123 + datasDynamicPartArray.forEach(one->{
  124 + List<ParamRule> dataPartDynamic = dataAll.stream().filter(d -> one.equals(d.getSDynamicParam()) && "sDynamicPart".equals(d.getSDynamicParamName())&&d.getBDynamicParam()).collect(Collectors.toUnmodifiableList());
  125 + if(ObjectUtil.isNotEmpty(dataPartDynamic)){
  126 + dataPartDynamic.forEach(dynamic->{
  127 + Map<String,Object> part = new HashMap<>();
  128 + String sValue = ObjectUtil.isNotEmpty(finalArgsOld.get(dynamic.getSParam()))?finalArgsOld.get(dynamic.getSParam()).toString():(ObjectUtil.isNotEmpty(finalArgsOld.get(dynamic.getSParam()))? finalArgsOld.get(dynamic.getSParam()).toString():StrUtil.EMPTY);
  129 + part.put("sPartName",one);
  130 + part.put("sName",dynamic.getSParamValue());
  131 + part.put("showName",dynamic.getSParam());
  132 + part.put("bEmpty",dynamic.getBEmpty());
  133 + part.put("sValue", sValue);
  134 + part.put("iOrder", dynamic.getIOrder());
  135 + part.put("sParamConfigValue",dynamic.getSParamConfigValue());
  136 + part.put("sParamMissMemo", dynamic.getSParamMissMemo());
  137 + //获取动态参数
  138 + if(ObjectUtil.isNotEmpty(sValue)){
  139 + List<ParamRule> dataParamDynamic = dataAll.stream().filter(d -> sValue.equals(d.getSDynamicParam()) && dynamic.getSParamValue().equals(d.getSDynamicParamName())&&d.getBDynamicParam()).collect(Collectors.toUnmodifiableList());
  140 + if(ObjectUtil.isNotEmpty(dataParamDynamic)){
  141 + List<Map<String,Object>> dynamicData = new ArrayList<>();
  142 + dataParamDynamic.forEach(dynamicD->{
  143 + Map<String,Object> dynamicOne = new HashMap<>();
  144 + String dynamicValue = ObjectUtil.isNotEmpty(finalArgsOld.get(dynamicD.getSParam()))?finalArgsOld.get(dynamicD.getSParam()).toString():(ObjectUtil.isNotEmpty(finalArgsOld.get(dynamicD.getSParam()))? finalArgsOld.get(dynamicD.getSParam()).toString():StrUtil.EMPTY);
  145 + dynamicOne.put("sName",dynamicD.getSParamValue());
  146 + dynamicOne.put("showName",dynamicD.getSParam());
  147 + dynamicOne.put("bEmpty",dynamicD.getBEmpty());
  148 + dynamicOne.put("sValue", dynamicValue);
  149 + dynamicOne.put("iOrder", dynamicD.getIOrder());
  150 + dynamicOne.put("sParamMissMemo", dynamicD.getSParamMissMemo()==null?StrUtil.EMPTY:dynamicD.getSParamMissMemo());
  151 + dynamicOne.put("sParamConfigValue",dynamicD.getSParamConfigValue()==null?StrUtil.EMPTY:dynamicD.getSParamConfigValue());
  152 + //获取动态参数
  153 + dynamicData.add(dynamicOne);
  154 + });
  155 + sAll.addAll(dynamicData);
  156 + part.put("dynamicData",dynamicData);
  157 + }
  158 + }
  159 + partList.add(part);
  160 + });
  161 + }
  162 + });
  163 + }
  164 + }
  165 + sAll.addAll(productList);
  166 + sAll.addAll(partList);
  167 + retData.put("sAll",sAll);
  168 + retData.put("product",productList);
  169 + retData.put("partList",partList);
  170 + return retData;
  171 + }
  172 +
  173 +}
0 174 \ No newline at end of file
... ...
src/main/java/com/xly/service/XlyErpService.java
... ... @@ -311,6 +311,7 @@ public class XlyErpService {
311 311 String sceneName = StrUtil.EMPTY;
312 312 String methodName = StrUtil.EMPTY;
313 313 UserSceneSession session=null;
  314 + String sReturnType = ReturnTypeCode.HTML.getCode();
314 315 try {
315 316 // 0. 预处理用户输入:去空格、转小写(方便匹配)
316 317 String input= InputPreprocessor.preprocessWithCommons(userInput);
... ... @@ -363,7 +364,9 @@ public class XlyErpService {
363 364 aiAgent = createConfirmeAgent(session);
364 365 }
365 366 //存在动态参数需要重新定义引导语
366   - if(ObjectUtil.isNotEmpty(session.getCurrentTool())&&ObjectUtil.isNotEmpty(session.getCurrentTool().getDynamicParamRule())){
  367 + if(ObjectUtil.isNotEmpty(session.getCurrentTool())
  368 + && ObjectUtil.isNotEmpty(session.getCurrentTool().getDynamicParamRule())
  369 + ){
367 370 sSystemPrompt = SystemPromptGenerator.generate(session.getCurrentTool().getSMethodName(),session);
368 371 aiAgent = createConfirmeAgent(session);
369 372 }
... ... @@ -376,9 +379,10 @@ public class XlyErpService {
376 379 ){
377 380 input = session.getCurrentTool().getSMethodName()+","+input;
378 381 }
  382 + sReturnType = (session!=null && ObjectUtil.isNotEmpty(session.getCurrentTool()) && session.getCurrentTool().getBQuo())?ReturnTypeCode.JSON.getCode():ReturnTypeCode.HTML.getCode();
379 383 //动态方法或返回需要提示的信息
380 384 if(ObjectUtil.isNotEmpty(session.getSFunPrompts())){
381   - return AiResponseDTO.builder().sSceneName(sceneName).sMethodName(methodName).aiText(session.getSFunPrompts()).sReturnType(ReturnTypeCode.HTML.getCode()).build();
  385 + return AiResponseDTO.builder().sSceneName(sceneName).sMethodName(methodName).aiText(session.getSFunPrompts()).sReturnType(sReturnType).build();
382 386 }
383 387 // 1.找到方法并且本方法带表结构描述时,需要调用 自然语言转SQL智能体
384 388 if((ObjectUtil.isNotEmpty(session.getCurrentTool())
... ... @@ -408,7 +412,7 @@ public class XlyErpService {
408 412 session.setDbType("G");
409 413 sResponMessage = getDynamicTableSql(session, input, userId, userInput,0,StrUtil.EMPTY,StrUtil.EMPTY,"0",StrUtil.EMPTY, aiAgent,sCleanSql);
410 414 // }
411   - return AiResponseDTO.builder().sSceneName(sceneName).sMethodName(methodName).aiText(sResponMessage).sReturnType(ReturnTypeCode.HTML.getCode()).dbType(session.getDbType()).dbCach(session.getDbCach()).build();
  415 + return AiResponseDTO.builder().sSceneName(sceneName).sMethodName(methodName).aiText(sResponMessage).sReturnType(sReturnType).dbType(session.getDbType()).dbCach(session.getDbCach()).build();
412 416 } else if (ObjectUtil.isNotEmpty(session.getCurrentTool())) {
413 417 //2.处理工具参数采集结束后业务逻辑处理
414 418 //调用方法,参数缺失部分提示,就直接使用方法返回的
... ... @@ -420,16 +424,16 @@ public class XlyErpService {
420 424 .sCopyToSrcId(session.getSCopyToSrcId())
421 425 .dbType(session.getDbType())
422 426 .dbCach(session.getDbCach())
423   - .sReturnType(ReturnTypeCode.HTML.getCode())
  427 + .sReturnType(sReturnType)
424 428 .build();
425 429 }else if(session.getCurrentScene()== null ){
426   - return AiResponseDTO.builder().sSceneName(sceneName).sMethodName(methodName).aiText("当前场景:没有选择 退回当前场景 请输入 "+ CommonConstant.RESET + sResponMessage).dbType(session.getDbType()).dbCach(session.getDbCach()).sReturnType(ReturnTypeCode.HTML.getCode()).build();
  430 + return AiResponseDTO.builder().sSceneName(sceneName).sMethodName(methodName).aiText("当前场景:没有选择 退回当前场景 请输入 "+ CommonConstant.RESET + sResponMessage).dbType(session.getDbType()).dbCach(session.getDbCach()).sReturnType(sReturnType).build();
427 431 }else{
428 432 return getChatiAgent (input, session);
429 433 }
430 434 } catch (Exception e) {
431 435 e.printStackTrace();
432   - return AiResponseDTO.builder().sSceneName(sceneName).sMethodName(methodName).aiText("系统异常:" + e.getMessage() + ",请稍后重试!").dbType(session.getDbType()).dbCach(session.getDbCach()).sReturnType(ReturnTypeCode.HTML.getCode()).build();
  436 + return AiResponseDTO.builder().sSceneName(sceneName).sMethodName(methodName).aiText("系统异常:" + e.getMessage() + ",请稍后重试!").dbType(session.getDbType()).dbCach(session.getDbCach()).sReturnType(sReturnType).build();
433 437 }finally {
434 438 //5.执行工具方法后,清除记忆
435 439 if(session !=null && session.getBCleanMemory()){
... ...
src/main/java/com/xly/tool/DynamicToolProvider.java
... ... @@ -13,6 +13,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
13 13  
14 14 import com.fasterxml.jackson.databind.ObjectMapper;
15 15  
  16 +import com.xly.agent.SystemPromptGenerator;
16 17 import com.xly.config.OperableChatMemoryProvider;
17 18 import com.xly.constant.*;
18 19 import com.xly.entity.*;
... ... @@ -20,6 +21,7 @@ import com.xly.exception.dto.BusinessException;
20 21 import com.xly.mapper.ParamRuleMapper;
21 22 import com.xly.mapper.ToolMetaMapper;
22 23 import com.xly.service.DynamicExeDbService;
  24 +import com.xly.service.QuoService;
23 25 import com.xly.service.UserSceneSessionService;
24 26 import com.xly.util.*;
25 27 import dev.langchain4j.agent.tool.*;
... ... @@ -52,6 +54,7 @@ public class DynamicToolProvider implements ToolProvider {
52 54 private final ObjectMapper objectMapper;
53 55 private final ToolMetaMapper toolMetaMapper;
54 56 private final ParamRuleMapper paramRuleMapper;
  57 + private final QuoService quoService;
55 58 private final DynamicExeDbService dynamicExeDbService;
56 59 private final OperableChatMemoryProvider operableChatMemoryProvider;
57 60  
... ... @@ -186,9 +189,9 @@ public class DynamicToolProvider implements ToolProvider {
186 189 //需要移除的老的参数
187 190 List<ParamRule> data = meta.getParamRuleList().stream().filter(
188 191 one-> one.getSParam().equals(k)
189   - && ObjectUtil.isNotEmpty(v)
190   - && !"0".equals(v)
191   - && !"\"\"".equals(v)
  192 + && ObjectUtil.isNotEmpty(v)
  193 + && !"0".equals(v)
  194 + && !"\"\"".equals(v)
192 195 ).collect(Collectors.toUnmodifiableList());
193 196 if(ObjectUtil.isNotEmpty(data) && data.size()>0){
194 197 finalArgs.remove(data.get(0).getSParamValue());
... ... @@ -205,7 +208,6 @@ public class DynamicToolProvider implements ToolProvider {
205 208 log.error("返回信息",e);
206 209 String askMsg = e.getMessage();
207 210 session.setSFunPrompts(askMsg);
208   - addSystemMessage(session, askMsg);
209 211 // 需要提问用户 → 抛异常停止循环
210 212 throw new RuntimeException(askMsg);
211 213 }
... ... @@ -215,35 +217,36 @@ public class DynamicToolProvider implements ToolProvider {
215 217 //存入已采集参数
216 218 session.setArgs(args);
217 219 // 2.1.1 根据当前获取的新参数判断是否存在有值必填例如动态参数、动态部件
218   - List<ParamRule> dynamicParamRule = doSetParamgetArgsAfter(args, session);
219   - if(ObjectUtil.isNotEmpty(dynamicParamRule)){
220   - String askMsg = hasDynamicParamRule(argsNew, session,dynamicParamRule);
221   - session.getCurrentTool().setDynamicParamRule(dynamicParamRule);
222   - //此处修改动态参数
223   - session.setSFunPrompts(askMsg);
224   - addSystemMessage(session, askMsg);
225   - // 需要提问用户 → 抛异常停止循环
226   - return String.valueOf(successResult(toolExecutionRequest, askMsg));
  220 + if(meta.getBQuo()){
  221 + List<ParamRule> dynamicParamRule = doSetParamgetArgsAfter(args, session);
  222 + if(ObjectUtil.isNotEmpty(dynamicParamRule)){
  223 + Map<String,Object> data = quoService.getQuoData( argsNew, session, dynamicParamRule);
  224 + data.remove("sAll");
  225 + data.put("bTs",true);
  226 + String askMsg = JSONObject.toJSONString(data);
  227 + session.setSFunPrompts(askMsg);
  228 + String sSystemPrompt = SystemPromptGenerator.buildMissParamPrompt(session,dynamicParamRule);
  229 + session.setSSystemPrompt(sSystemPrompt);
  230 + // 需要提问用户 → 抛异常停止循环
  231 + return String.valueOf(successResult(toolExecutionRequest, askMsg));
  232 + }
227 233 }
  234 +
228 235 //客户选择行号转sSLaveId
229 236 if(ObjectUtil.isNotEmpty(args)
230 237 &&(
231 238 (args.containsKey("rowNumbers") && ObjectUtil.isNotEmpty(args.get("rowNumbers")))
232   - || (args.containsKey("operateType") && "全部确认".equals(args.get("operateType")))
233   - )&& ObjectUtil.isNotEmpty(session.getCurrentRowData())
  239 + || (args.containsKey("operateType") && "全部确认".equals(args.get("operateType")))
  240 + )&& ObjectUtil.isNotEmpty(session.getCurrentRowData())
234 241 ){
235 242 doSetSlaveIdToArgs( args, session);
236 243 }
237 244 //存入已采集参数
238 245 session.setArgs(args);
239   - // 3. 【自动校验】检查必填项
240   - List<String> missing = checkRequiredParams(args, paramRuleData);
241   - if (!missing.isEmpty()) {
242   - // 4.1 参数缺失,生成“提问”消息,直接返给客户
243   - String askMsg = buildAskUserMessage(meta, missing,args);
244   - session.setSFunPrompts(askMsg);
245   - addSystemMessage(session, askMsg);
246   - return String.valueOf(successResult(toolExecutionRequest, askMsg));
  246 + //获取是否缺失参数
  247 + String askMsg = getMissParamMsg( meta, session, args);
  248 + if(ObjectUtil.isNotEmpty(askMsg)){
  249 + return askMsg;
247 250 }
248 251 // ====================== 返回时带终止指令 ======================
249 252 String resp = JSONUtil.toJsonStr(args) ;
... ... @@ -271,7 +274,7 @@ public class DynamicToolProvider implements ToolProvider {
271 274 List<ParamRule> paramRuleData = tool.getParamRuleListAll();
272 275 paramRuleData = paramRuleData.stream().filter(one->
273 276 ( ObjectUtil.isNotEmpty(args.get(one.getSParam())) ||ObjectUtil.isNotEmpty(args.get(one.getSParamValue())))
274   - && ObjectUtil.isNotEmpty(one.getSDynamicParamRuleSql())
  277 + && ObjectUtil.isNotEmpty(one.getSDynamicParamRuleSql())
275 278 ).collect(Collectors.toUnmodifiableList());
276 279 List<ParamRule> dynamicParamRule = new ArrayList<>();
277 280 //为空的时候需要重新插入 不为空 表示之前已经放过了
... ... @@ -283,9 +286,9 @@ public class DynamicToolProvider implements ToolProvider {
283 286 searMap.putAll(args);
284 287 //新参数如果值变了移除掉之前插入的
285 288 List<ParamRule> paramRuleDataAllNew = paramRuleDataAll.get().stream().filter(d->
286   - !one.getSParam().equals(d.getSDynamicParam())
287   - ||(one.getSParam().equals(d.getSDynamicParam()) && one.getSParamValue().equals(d.getSParamValue()))
288   - ).collect(Collectors.toUnmodifiableList());
  289 + !one.getSParam().equals(d.getSDynamicParam())
  290 + ||(one.getSParam().equals(d.getSDynamicParam()) && one.getSParamValue().equals(d.getSParamValue()))
  291 + ).collect(Collectors.toUnmodifiableList());
289 292 List<ParamRule> paramRuleList = tool.getParamRuleList().stream().filter(d->
290 293 !one.getSParam().equals(d.getSDynamicParam())
291 294 ||(one.getSParam().equals(d.getSDynamicParam()) && one.getSParamValue().equals(d.getSParamValue()))
... ... @@ -334,7 +337,6 @@ public class DynamicToolProvider implements ToolProvider {
334 337 }
335 338 }else{
336 339 //表示过程走自定义参数
337   -
338 340 }
339 341 if(ObjectUtil.isNotEmpty(dynamicParamRuleOne)){
340 342 //转换成BEAN
... ... @@ -407,34 +409,6 @@ public class DynamicToolProvider implements ToolProvider {
407 409 .stream()
408 410 .collect(Collectors.toList());
409 411 }
410   - /***
411   - * @Author 钱豹
412   - * @Date 23:35 2026/6/28
413   - * @Param [argsNew, session]
414   - * @return java.util.List<com.xly.entity.ParamRule>
415   - * @Description 存在动态参数返回提示
416   - **/
417   - private String hasDynamicParamRule(Map<String,Object> argsNew,UserSceneSession session,List<ParamRule> dynamicParamRule){
418   - //获取当前方法
419   - ToolMeta meta = session.getCurrentTool();
420   - meta.setDynamicParamRule(dynamicParamRule);
421   - session.setCurrentTool(meta);
422   - Map<String, Object> argsOld = session.getArgs();
423   - Map<String, Object> args = DeepCopyUtils.deepCopy(argsNew);
424   - if(ObjectUtil.isEmpty(argsOld)){
425   - argsOld = new HashMap<>();
426   - }
427   - argsOld.putAll(args);
428   - //根据获取的参数获取数据
429   - List<String> dynamicParamRuleTs = dynamicParamRule.stream().map(ParamRule::getSParam).toList();
430   - session.setArgs(argsOld);
431   - String askMsg = buildAskUserMessage(meta, dynamicParamRuleTs,args);
432   - session.setSFunPrompts(askMsg);
433   - String sSystemPrompt = buildMissParamPrompt(session,dynamicParamRule);
434   - session.setSSystemPrompt(sSystemPrompt);
435   - addSystemMessage(session, askMsg);
436   - return askMsg;
437   - }
438 412  
439 413  
440 414 private void doSetSlaveIdToArgs(Map<String,Object> args,UserSceneSession session){
... ... @@ -545,14 +519,6 @@ public class DynamicToolProvider implements ToolProvider {
545 519 2. 只要方法返回结果,必须停止调用
546 520 3. 当用户输入包含【数据确认】、确认数据、确认、第*条数据确认时,必须调用本工具
547 521 """;
548   -// String forceToolPrompt = """
549   -// 【工具调用规则】
550   -// 1. 每个自定义方法最多只能调用 1 次
551   -// 2. 只要方法返回结果,必须停止调用
552   -// 3. 禁止重复调用同一个方法
553   -// 4. 禁止无意义循环调用
554   -// 5. 当用户输入包含【数据确认】、确认数据、确认、第*条数据确认时,必须调用本工具
555   -// """;
556 522 stoolDesc.append(forceToolPrompt);
557 523 if (ObjectUtil.isNotEmpty(meta.getStoolDesc())) {
558 524 stoolDesc.append("MethodNo:").append(meta.getSMethodNo())
... ... @@ -661,6 +627,8 @@ public class DynamicToolProvider implements ToolProvider {
661 627 });
662 628 sb.delete(sb.length()-1,sb.length());
663 629 paramRule.setSRuleTs(sb.toString());
  630 + //存入动态配置
  631 + paramRule.setSParamConfigValue(constMap);
664 632 return sb.toString();
665 633 }
666 634 return StrUtil.EMPTY;
... ... @@ -678,6 +646,7 @@ public class DynamicToolProvider implements ToolProvider {
678 646 if(ObjectUtil.isEmpty(data)){
679 647 return StrUtil.EMPTY;
680 648 }
  649 +
681 650 if(data.get(0).containsKey("sGroupName")){
682 651 Map<Object, List<Map<String, Object>>> groupData = data.stream()
683 652 .collect(Collectors.groupingBy(map -> map.get("sGroupName")));
... ... @@ -691,12 +660,16 @@ public class DynamicToolProvider implements ToolProvider {
691 660 sb.append(",");
692 661 }
693 662 });
  663 + //放入动态配置值
  664 + paramRule.setSParamConfigValue(groupData);
694 665 }else{
695 666 data.forEach(one->{
696 667 if(ObjectUtil.isNotEmpty(one.get(paramRule.getSParamValue()))){
697 668 sb.append(one.get(paramRule.getSParamValue())).append("/");
698 669 }
699 670 });
  671 + //放入动态配置值
  672 + paramRule.setSParamConfigValue(data);
700 673 }
701 674 if(ObjectUtil.isNotEmpty(sb)){
702 675 sb.delete(sb.length()-1,sb.length());
... ... @@ -712,22 +685,47 @@ public class DynamicToolProvider implements ToolProvider {
712 685 return paramRuleDataAll;
713 686 }
714 687  
  688 + //校验是否缺失参数
  689 + private String getMissParamMsg(ToolMeta meta,UserSceneSession session, Map<String, Object> args){
  690 + if(meta.getBQuo()){
  691 + List<ParamRule> dataParamDynamic = session.getCurrentTool().getParamRuleListAll().stream().filter(d ->
  692 + d.getBDynamicParam()).collect(Collectors.toUnmodifiableList());
  693 + Map<String,Object> data = quoService.getQuoData(args, session, dataParamDynamic);
  694 + List<Map<String,Object>> sAll = (List<Map<String, Object>>) data.get("sAll");
  695 + List<Map<String,Object>> sEmpty = sAll.stream().filter(one-> BooleanUtil.toBoolean(one.get("bEmpty").toString())
  696 + && (ObjectUtil.isEmpty(one.get("sValue")) || "0".equals(one.get("sValue")))).collect(Collectors.toUnmodifiableList());
  697 + if(ObjectUtil.isNotEmpty(sEmpty)){
  698 + data.remove("sAll");
  699 + data.put("bTs",true);
  700 + String askMsg = JSONObject.toJSONString(data);
  701 + session.setSFunPrompts(askMsg);
  702 + String sSystemPrompt = SystemPromptGenerator.buildMissParamPrompt(session,dataParamDynamic);
  703 + session.setSSystemPrompt(sSystemPrompt);
  704 + // 需要提问用户 → 抛异常停止循环
  705 + return askMsg;
  706 + }
  707 + }else{
  708 + List<String> missing = checkRequiredParams(args, meta.getParamRuleListCheck());
  709 + if (!missing.isEmpty()) {
  710 + String askMsg = buildAskUserMessage(meta, missing,args);
  711 + return askMsg;
  712 + }
  713 + }
  714 + return null;
  715 + }
715 716  
716 717 public String doDynamicTool(ToolMeta meta,UserSceneSession session) {
717 718 List<ParamRule> paramRuleData = meta.getParamRuleListAll();
718   - List<ParamRule> paramRuleDataCheck = meta.getParamRuleListCheck();
719 719 Map<String, Object> argsOld = session.getArgs();
720 720 if(ObjectUtil.isEmpty(argsOld)){
721 721 argsOld = new HashMap<>();
722 722 }
723 723 Map<String, Object> args = session.getArgs();
724   - List<String> missing = checkRequiredParams(args, paramRuleDataCheck);
725   - if (!missing.isEmpty()) {
726   - String askMsg = buildAskUserMessage(meta, missing,args);
727   - addSystemMessage(session, askMsg);
  724 + //获取是否缺失参数
  725 + String askMsg = getMissParamMsg( meta, session, args);
  726 + if(ObjectUtil.isNotEmpty(askMsg)){
728 727 return askMsg;
729 728 }
730   -
731 729 List<ChatMessage> chatMessage = operableChatMemoryProvider.getCurrentChatMessages(session.getUserId());
732 730 ChatMessage userMessage = getLastUserMessage(chatMessage);
733 731 String input = "";
... ... @@ -750,12 +748,11 @@ public class DynamicToolProvider implements ToolProvider {
750 748 //合并已选择数据
751 749 argsOld.putAll(args);
752 750 session.setArgs(argsOld);
753   - String askMsg = buildAskUserMessage(meta, missingAfter,args);
  751 + askMsg = buildAskUserMessage(meta, missingAfter,args);
754 752 session.setSFunPrompts(askMsg);
755 753 List<ParamRule> paramRuleDataMiss = getMissParamRuleAfter(args, paramRuleData);
756   - String sSystemPrompt = buildMissParamPrompt(session,paramRuleDataMiss);
  754 + String sSystemPrompt = SystemPromptGenerator.buildMissParamPrompt(session,paramRuleDataMiss);
757 755 session.setSSystemPrompt(sSystemPrompt);
758   - addSystemMessage(session, askMsg);
759 756 return askMsg;
760 757 }
761 758 return executeTool(meta, args, paramRuleData, session.getUserId(), session);
... ... @@ -764,7 +761,7 @@ public class DynamicToolProvider implements ToolProvider {
764 761 String askconfirmMsg =StrUtil.EMPTY;
765 762 if(4== meta.getIBizType() || meta.getIBizType()==5){
766 763 askconfirmMsg = doGetFromData( meta,args,session);
767   - String sSystemPrompt = buildDynamicSystemPrompt(session);
  764 + String sSystemPrompt = SystemPromptGenerator.buildDynamicSystemPrompt(session);
768 765 session.setSSystemPrompt(sSystemPrompt);
769 766 return executeWithConfirmation(askconfirmMsg, session, meta);
770 767 }else{
... ... @@ -961,9 +958,9 @@ public class DynamicToolProvider implements ToolProvider {
961 958 Map<String,Object> returnMap = transformationArgs( args, paramDefs);
962 959 List<ParamRule> paramDefsCheck = paramDefs.stream()
963 960 .filter(pd -> !"sDynamicPart".equals(pd.getSParamValue())).collect(Collectors.toUnmodifiableList());
964   - paramDefsCheck = paramDefsCheck.stream()
  961 + paramDefsCheck = paramDefsCheck.stream()
965 962 .filter(pd -> Boolean.TRUE.equals(pd.getBEmpty()) && pd.getBTipModel()).collect(Collectors.toUnmodifiableList());
966   - paramDefsCheck = paramDefsCheck.stream()
  963 + paramDefsCheck = paramDefsCheck.stream()
967 964 .filter(pd -> checkMiss( returnMap, pd)).collect(Collectors.toUnmodifiableList());
968 965 return paramDefsCheck.stream().map(ParamRule::getSParam)
969 966 .toList();
... ... @@ -1024,10 +1021,10 @@ public class DynamicToolProvider implements ToolProvider {
1024 1021 private List<ParamRule> getMissParamRuleAfter(Map<String, Object> args, List<ParamRule> paramDefs) {
1025 1022 Map<String,Object> returnMap = transformationArgs( args, paramDefs);
1026 1023 return paramDefs.stream()
1027   - .filter(pd -> ObjectUtil.isNotEmpty(pd.getBConfirmAfter()) && BooleanUtil.toBoolean(pd.getBConfirmAfter().toString()))
1028   - .filter(pd -> (!returnMap.containsKey(pd.getSParam()) || (ObjectUtil.isEmpty(returnMap.get(pd.getSParam()))))
  1024 + .filter(pd -> ObjectUtil.isNotEmpty(pd.getBConfirmAfter()) && BooleanUtil.toBoolean(pd.getBConfirmAfter().toString()))
  1025 + .filter(pd -> (!returnMap.containsKey(pd.getSParam()) || (ObjectUtil.isEmpty(returnMap.get(pd.getSParam()))))
1029 1026 && (!returnMap.containsKey(pd.getSParamValue()) || (ObjectUtil.isEmpty(returnMap.get(pd.getSParamValue()))))
1030   - )
  1027 + )
1031 1028 .toList();
1032 1029 }
1033 1030  
... ... @@ -1050,14 +1047,7 @@ public class DynamicToolProvider implements ToolProvider {
1050 1047 return sReturn;
1051 1048 }
1052 1049  
1053   - //参数进行处理
1054   - private void doArgs(ToolMeta meta, Map<String, Object> args,List<ParamRule> paramDefs) {
1055   - List<ParamRule> paramDefsD = paramDefs.stream().filter(one-> ObjectUtil.isNotEmpty(one.getSDynamicParamRuleSql())).collect(Collectors.toUnmodifiableList());
1056   -
1057   -
1058   -
1059   - }
1060   -
  1050 + //执行工具后
1061 1051 private String executeToolAfter(ToolMeta meta, Map<String, Object> args,List<ParamRule> paramDefs,UserSceneSession session) {
1062 1052 String sBizContent = meta.getSBizContent();
1063 1053 Integer iBizType = meta.getIBizType();
... ... @@ -1084,7 +1074,6 @@ public class DynamicToolProvider implements ToolProvider {
1084 1074 sessA.remove("sSlaveId");
1085 1075 sessA.remove("operateType");
1086 1076 session.setArgs(sessA);
1087   - addSystemMessage(session, sMsg);
1088 1077 throw new BusinessException(-1,sMsg);
1089 1078 }
1090 1079 List<Map<String,Object>> sRowData = doGetFromDataWq( meta, args, session);
... ... @@ -1095,8 +1084,6 @@ public class DynamicToolProvider implements ToolProvider {
1095 1084 sessA.remove("sSlaveId");
1096 1085 sessA.remove("operateType");
1097 1086 session.setArgs(sessA);
1098   - //插入AI记忆
1099   - addSystemMessage(session, sMsg);
1100 1087 throw new BusinessException(-1,sMsg);
1101 1088 }
1102 1089 Map<String,Object> dataOne = DeepCopyUtils.deepCopy(args);
... ... @@ -1150,7 +1137,6 @@ public class DynamicToolProvider implements ToolProvider {
1150 1137 } else {
1151 1138 String sMsgText = "未找到对应的数据";
1152 1139 session.setSFunPrompts(sMsgText);
1153   - addSystemMessage(session, sMsgText);
1154 1140 throw new BusinessException(-1,sMsgText);
1155 1141 }
1156 1142 }
... ... @@ -1161,12 +1147,6 @@ public class DynamicToolProvider implements ToolProvider {
1161 1147 return "操作成功";
1162 1148 }
1163 1149  
1164   - private void addSystemMessage(UserSceneSession session,String sMsg){
1165   -// if(ObjectUtil.isNotEmpty(operableChatMemoryProvider) && ObjectUtil.isNotEmpty(operableChatMemoryProvider.get(session.getUserId()))){
1166   -// operableChatMemoryProvider.get(session.getUserId()).add(SystemMessage.from("上一次工具调用失败。原因:" + sMsg + "。请根据用户意图修正参数,并再次调用工具。"));
1167   -// }
1168   - }
1169   -
1170 1150 private List<Map<String,Object>> doGetFromDataWq(ToolMeta meta, Map<String, Object> args,UserSceneSession session){
1171 1151 String sUrl = meta.getSendUrl();
1172 1152 Map<String,Object> sBody = new HashMap<>();
... ... @@ -1367,103 +1347,6 @@ public class DynamicToolProvider implements ToolProvider {
1367 1347 return markdown.toString();
1368 1348 }
1369 1349  
1370   -
1371   - /**
1372   - * 缺失参数统一提示模板:强制AI调用自定义方法,一次性回填所有参数
1373   - */
1374   - public String buildMissParamPrompt(UserSceneSession session, List<ParamRule> paramRuleDataMiss) {
1375   - String methodNo = session.getCurrentTool().getSMethodNo();
1376   - // 1. 拼接缺失参数的描述(增加“参数名”和“英文名”的对应,方便模型映射)
1377   - String paramDesc = paramRuleDataMiss.stream()
1378   - .map(p -> String.format("- 参数名:%s (对应字段: %s),示例值:%s",
1379   - p.getSParam(), p.getSParamValue(), p.getSExampleValue()))
1380   - .collect(Collectors.joining("\n"));
1381   - // 但根据你的需求,其实 prompt 里并不需要强行插入一个空的 JSON 片段,
1382   - // 直接告诉模型去“合并”即可。
1383   - return String.format("""
1384   - 请你根据用户最新的输入,补充缺失的参数,并带着【所有完整参数】立即发起工具调用。
1385   -
1386   - 【核心执行规则】
1387   - 1. **参数合并(至关重要)**:你必须保留上一轮对话中已经获取的参数(如 sSlaveId, operateType 等),并将用户本次提供的新参数与旧参数合并。
1388   - 2. **必须调用工具**:必须调用工具 `%s`。绝对禁止直接输出 JSON 文本,也绝对禁止向用户反问或索要信息。
1389   - 3. **完整调用**:请直接生成包含所有参数的 tool_calls 请求。
1390   - 【已获取数据】
1391   - %s
1392   - 【当前缺失的参数说明】
1393   - %s
1394   - """, methodNo,JSONObject.toJSONString(session.getArgs()), paramDesc);
1395   - }
1396   -
1397   - public String buildDynamicSystemPrompt(UserSceneSession session) {
1398   - // 获取当前工具编号(用于 JSON 的 name 字段)
1399   - String methodNo = session.getCurrentTool().getSMethodNo();
1400   - return """
1401   - 【极强约束·必须执行】
1402   - 1. 禁止说话!禁止解释!
1403   - 2. 必须调用工具!
1404   - 3. 只输出标准工具调用JSON!
1405   -
1406   - ### 任务背景 ###
1407   - 用户会输入自然语言指令(如“第1行确认”、“全部合并”等)。
1408   - 你的任务是:解析出【操作类型】和【目标行号】。
1409   -
1410   - ### 解析规则(必须严格遵守) ###
1411   -
1412   - 1. **操作类型 (operateType)**:
1413   - - 如果用户说“全部确认”、“生成多个单据”,识别为:"全部确认"
1414   - - 如果用户说“合并确认”、“生成一个单据”,识别为:"合并确认"
1415   - - 其他情况,默认为:"单行确认"
1416   -
1417   - 2. **行号提取 (rowNumbers)**:
1418   - - 单选:如“第5行”,提取为 [5]
1419   - - 多选:如“第1、3、5行”,提取为 [1, 3, 5]
1420   - - 范围:如“第2到4行”,提取为 [2, 3, 4]
1421   - - 全选:如“全部”、“所有”,提取为 ["ALL"]
1422   -
1423   - ### 输出格式规范 ###
1424   - 请直接输出以下 JSON(不要任何 Markdown 格式,不要 ```json):
1425   - {"name": "%s", "parameters": {"operateType": "解析出的类型", "rowNumbers": [行号数组或"ALL"]}}
1426   -
1427   - """.formatted(methodNo);
1428   - }
1429   -// public String buildDynamicSystemPrompt(UserSceneSession session) {
1430   -// // 获取当前工具编号
1431   -// String methodNo = session.getCurrentTool().getSMethodNo();
1432   -// // 格式化表格数据(保持缩进,方便模型阅读)
1433   -// String rowJson = JSONUtil.toJsonPrettyStr(session.getCurrentRowData());
1434   -//
1435   -// return """
1436   -// 【极强约束·必须执行】
1437   -// 1. 禁止说话!禁止解释!
1438   -// 2. 必须调用工具!
1439   -// 3. 只输出标准工具调用JSON!
1440   -//
1441   -// ### 任务背景 ###
1442   -// 用户会输入类似“第5行确认”或“确认第3条”的指令。
1443   -// 你的任务是:解析行号 -> 在下方表格中找到对应行 -> 提取 sSlaveId -> 调用工具。
1444   -//
1445   -// ### 数据源(表格 key 是行号) ###
1446   -// %s
1447   -//
1448   -// ### 防错黄金法则(必须严格遵守) ###
1449   -// 1. **查找阶段**:不要凭空编造 ID。必须先在“思考步骤”中明确写出:
1450   -// “用户输入是[xx],提取行号[N] -> 查找表格 Key=[N] -> 对应的 sSlaveId 是 [这里填入表格里的完整数字]”
1451   -// 2. **复制阶段**:sSlaveId 是一长串数字,请务必**直接复制**表格中的原始值,不要加省略号(...),不要改变数字。
1452   -// 3. **输出阶段**:只有确认复制无误后,才在 JSON 的 sSlaveId 字段中填入该值。
1453   -//
1454   -// ### 输出格式规范 ###
1455   -// {"name": "%s", "parameters": {"operateType": "单行确认", "sSlaveId": "在这里填入你从表格中复制的ID"}}
1456   -//
1457   -// ### 执行流程(一步一步来) ###
1458   -// 1. **解析**:阅读用户输入,确定他想操作的是第几行(N)。
1459   -// 2. **思考**:在回复的第一行,写出你的查找过程(例如:用户要求第5行...)。
1460   -// 3. **JSON**:换行后,输出最终的工具调用 JSON。
1461   -//
1462   -// 【警告】
1463   -// 如果用户要求的行号在表格中不存在,请返回错误信息,不要调用工具。
1464   -// """.formatted(rowJson, methodNo);
1465   -// }
1466   -
1467 1350 private List<Map<String, Object>> findFieldNameByChinese(List<Map<String, Object>> sAIshowfieldShow,List<Map<String, Object>> rows){
1468 1351 Map<String,String> keyMappings = new HashMap<>();
1469 1352 List<String> selectedKeys = new ArrayList<>();
... ... @@ -1596,9 +1479,9 @@ public class DynamicToolProvider implements ToolProvider {
1596 1479 return check || userResponse.contains("生成")
1597 1480 || userResponse.contains("确认")
1598 1481 || (ObjectUtil.isNotEmpty(session.getArgs())
1599   - && session.getArgs().containsKey("operateType")
1600   - && session.getArgs().containsKey("sSlaveId")
1601   - && ObjectUtil.isNotEmpty(session.getArgs().get("sSlaveId"))
1602   - );
  1482 + && session.getArgs().containsKey("operateType")
  1483 + && session.getArgs().containsKey("sSlaveId")
  1484 + && ObjectUtil.isNotEmpty(session.getArgs().get("sSlaveId"))
  1485 + );
1603 1486 }
1604 1487 }
1605 1488 \ No newline at end of file
... ...