Commit f0318b7bafc221490c485a944620d9658d7d751a

Authored by qianbao
1 parent 1b14dc87

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

src/main/java/com/xly/agent/SystemPromptGenerator.java
1 package com.xly.agent; 1 package com.xly.agent;
2 2
3 import cn.hutool.core.util.ObjectUtil; 3 import cn.hutool.core.util.ObjectUtil;
4 -import cn.hutool.json.JSONConfig;  
5 -import cn.hutool.json.JSONUtil;  
6 import com.alibaba.fastjson2.JSON; 4 import com.alibaba.fastjson2.JSON;
7 import com.alibaba.fastjson2.JSONObject; 5 import com.alibaba.fastjson2.JSONObject;
8 import com.alibaba.fastjson2.JSONWriter; 6 import com.alibaba.fastjson2.JSONWriter;
@@ -10,6 +8,7 @@ import com.xly.entity.ParamRule; @@ -10,6 +8,7 @@ import com.xly.entity.ParamRule;
10 import com.xly.entity.UserSceneSession; 8 import com.xly.entity.UserSceneSession;
11 9
12 import java.util.List; 10 import java.util.List;
  11 +import java.util.stream.Collectors;
13 12
14 public class SystemPromptGenerator { 13 public class SystemPromptGenerator {
15 14
@@ -50,4 +49,64 @@ public class SystemPromptGenerator { @@ -50,4 +49,64 @@ public class SystemPromptGenerator {
50 49
51 return sb.toString(); 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 \ No newline at end of file 113 \ No newline at end of file
src/main/java/com/xly/constant/ReturnTypeCode.java
@@ -14,6 +14,7 @@ public enum ReturnTypeCode { @@ -14,6 +14,7 @@ public enum ReturnTypeCode {
14 14
15 // 成功 15 // 成功
16 HTML("html", "html"), 16 HTML("html", "html"),
  17 + JSON("JSON", "JSON"),
17 STREAM("stream", "stream"), 18 STREAM("stream", "stream"),
18 MAKEDOWN("makedown", "makedown"); 19 MAKEDOWN("makedown", "makedown");
19 20
src/main/java/com/xly/entity/ParamRule.java
@@ -3,6 +3,8 @@ package com.xly.entity; @@ -3,6 +3,8 @@ package com.xly.entity;
3 import lombok.Data; 3 import lombok.Data;
4 4
5 import java.time.LocalDateTime; 5 import java.time.LocalDateTime;
  6 +import java.util.List;
  7 +import java.util.Map;
6 8
7 /*** 9 /***
8 * @Author 钱豹 10 * @Author 钱豹
@@ -32,6 +34,9 @@ public class ParamRule { @@ -32,6 +34,9 @@ public class ParamRule {
32 private String sDynamicParamRuleSql; 34 private String sDynamicParamRuleSql;
33 private String sDynamicParam; 35 private String sDynamicParam;
34 private String sDynamicParamName; 36 private String sDynamicParamName;
  37 + private String sGroup;
  38 + private Object sParamConfigValue;
  39 + private Boolean bStandardParam;
35 private Boolean bDynamicParam = false; 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,5 +53,6 @@ public class ToolMeta {
53 private String sVectorfiledAll; 53 private String sVectorfiledAll;
54 private String sVectorfiledShow; 54 private String sVectorfiledShow;
55 private Boolean sQue = false; 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 \ No newline at end of file 174 \ No newline at end of file
src/main/java/com/xly/service/XlyErpService.java
@@ -311,6 +311,7 @@ public class XlyErpService { @@ -311,6 +311,7 @@ public class XlyErpService {
311 String sceneName = StrUtil.EMPTY; 311 String sceneName = StrUtil.EMPTY;
312 String methodName = StrUtil.EMPTY; 312 String methodName = StrUtil.EMPTY;
313 UserSceneSession session=null; 313 UserSceneSession session=null;
  314 + String sReturnType = ReturnTypeCode.HTML.getCode();
314 try { 315 try {
315 // 0. 预处理用户输入:去空格、转小写(方便匹配) 316 // 0. 预处理用户输入:去空格、转小写(方便匹配)
316 String input= InputPreprocessor.preprocessWithCommons(userInput); 317 String input= InputPreprocessor.preprocessWithCommons(userInput);
@@ -363,7 +364,9 @@ public class XlyErpService { @@ -363,7 +364,9 @@ public class XlyErpService {
363 aiAgent = createConfirmeAgent(session); 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 sSystemPrompt = SystemPromptGenerator.generate(session.getCurrentTool().getSMethodName(),session); 370 sSystemPrompt = SystemPromptGenerator.generate(session.getCurrentTool().getSMethodName(),session);
368 aiAgent = createConfirmeAgent(session); 371 aiAgent = createConfirmeAgent(session);
369 } 372 }
@@ -376,9 +379,10 @@ public class XlyErpService { @@ -376,9 +379,10 @@ public class XlyErpService {
376 ){ 379 ){
377 input = session.getCurrentTool().getSMethodName()+","+input; 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 if(ObjectUtil.isNotEmpty(session.getSFunPrompts())){ 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 // 1.找到方法并且本方法带表结构描述时,需要调用 自然语言转SQL智能体 387 // 1.找到方法并且本方法带表结构描述时,需要调用 自然语言转SQL智能体
384 if((ObjectUtil.isNotEmpty(session.getCurrentTool()) 388 if((ObjectUtil.isNotEmpty(session.getCurrentTool())
@@ -408,7 +412,7 @@ public class XlyErpService { @@ -408,7 +412,7 @@ public class XlyErpService {
408 session.setDbType("G"); 412 session.setDbType("G");
409 sResponMessage = getDynamicTableSql(session, input, userId, userInput,0,StrUtil.EMPTY,StrUtil.EMPTY,"0",StrUtil.EMPTY, aiAgent,sCleanSql); 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 } else if (ObjectUtil.isNotEmpty(session.getCurrentTool())) { 416 } else if (ObjectUtil.isNotEmpty(session.getCurrentTool())) {
413 //2.处理工具参数采集结束后业务逻辑处理 417 //2.处理工具参数采集结束后业务逻辑处理
414 //调用方法,参数缺失部分提示,就直接使用方法返回的 418 //调用方法,参数缺失部分提示,就直接使用方法返回的
@@ -420,16 +424,16 @@ public class XlyErpService { @@ -420,16 +424,16 @@ public class XlyErpService {
420 .sCopyToSrcId(session.getSCopyToSrcId()) 424 .sCopyToSrcId(session.getSCopyToSrcId())
421 .dbType(session.getDbType()) 425 .dbType(session.getDbType())
422 .dbCach(session.getDbCach()) 426 .dbCach(session.getDbCach())
423 - .sReturnType(ReturnTypeCode.HTML.getCode()) 427 + .sReturnType(sReturnType)
424 .build(); 428 .build();
425 }else if(session.getCurrentScene()== null ){ 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 }else{ 431 }else{
428 return getChatiAgent (input, session); 432 return getChatiAgent (input, session);
429 } 433 }
430 } catch (Exception e) { 434 } catch (Exception e) {
431 e.printStackTrace(); 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 }finally { 437 }finally {
434 //5.执行工具方法后,清除记忆 438 //5.执行工具方法后,清除记忆
435 if(session !=null && session.getBCleanMemory()){ 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,6 +13,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
13 13
14 import com.fasterxml.jackson.databind.ObjectMapper; 14 import com.fasterxml.jackson.databind.ObjectMapper;
15 15
  16 +import com.xly.agent.SystemPromptGenerator;
16 import com.xly.config.OperableChatMemoryProvider; 17 import com.xly.config.OperableChatMemoryProvider;
17 import com.xly.constant.*; 18 import com.xly.constant.*;
18 import com.xly.entity.*; 19 import com.xly.entity.*;
@@ -20,6 +21,7 @@ import com.xly.exception.dto.BusinessException; @@ -20,6 +21,7 @@ import com.xly.exception.dto.BusinessException;
20 import com.xly.mapper.ParamRuleMapper; 21 import com.xly.mapper.ParamRuleMapper;
21 import com.xly.mapper.ToolMetaMapper; 22 import com.xly.mapper.ToolMetaMapper;
22 import com.xly.service.DynamicExeDbService; 23 import com.xly.service.DynamicExeDbService;
  24 +import com.xly.service.QuoService;
23 import com.xly.service.UserSceneSessionService; 25 import com.xly.service.UserSceneSessionService;
24 import com.xly.util.*; 26 import com.xly.util.*;
25 import dev.langchain4j.agent.tool.*; 27 import dev.langchain4j.agent.tool.*;
@@ -52,6 +54,7 @@ public class DynamicToolProvider implements ToolProvider { @@ -52,6 +54,7 @@ public class DynamicToolProvider implements ToolProvider {
52 private final ObjectMapper objectMapper; 54 private final ObjectMapper objectMapper;
53 private final ToolMetaMapper toolMetaMapper; 55 private final ToolMetaMapper toolMetaMapper;
54 private final ParamRuleMapper paramRuleMapper; 56 private final ParamRuleMapper paramRuleMapper;
  57 + private final QuoService quoService;
55 private final DynamicExeDbService dynamicExeDbService; 58 private final DynamicExeDbService dynamicExeDbService;
56 private final OperableChatMemoryProvider operableChatMemoryProvider; 59 private final OperableChatMemoryProvider operableChatMemoryProvider;
57 60
@@ -186,9 +189,9 @@ public class DynamicToolProvider implements ToolProvider { @@ -186,9 +189,9 @@ public class DynamicToolProvider implements ToolProvider {
186 //需要移除的老的参数 189 //需要移除的老的参数
187 List<ParamRule> data = meta.getParamRuleList().stream().filter( 190 List<ParamRule> data = meta.getParamRuleList().stream().filter(
188 one-> one.getSParam().equals(k) 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 ).collect(Collectors.toUnmodifiableList()); 195 ).collect(Collectors.toUnmodifiableList());
193 if(ObjectUtil.isNotEmpty(data) && data.size()>0){ 196 if(ObjectUtil.isNotEmpty(data) && data.size()>0){
194 finalArgs.remove(data.get(0).getSParamValue()); 197 finalArgs.remove(data.get(0).getSParamValue());
@@ -205,7 +208,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -205,7 +208,6 @@ public class DynamicToolProvider implements ToolProvider {
205 log.error("返回信息",e); 208 log.error("返回信息",e);
206 String askMsg = e.getMessage(); 209 String askMsg = e.getMessage();
207 session.setSFunPrompts(askMsg); 210 session.setSFunPrompts(askMsg);
208 - addSystemMessage(session, askMsg);  
209 // 需要提问用户 → 抛异常停止循环 211 // 需要提问用户 → 抛异常停止循环
210 throw new RuntimeException(askMsg); 212 throw new RuntimeException(askMsg);
211 } 213 }
@@ -215,35 +217,36 @@ public class DynamicToolProvider implements ToolProvider { @@ -215,35 +217,36 @@ public class DynamicToolProvider implements ToolProvider {
215 //存入已采集参数 217 //存入已采集参数
216 session.setArgs(args); 218 session.setArgs(args);
217 // 2.1.1 根据当前获取的新参数判断是否存在有值必填例如动态参数、动态部件 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 //客户选择行号转sSLaveId 235 //客户选择行号转sSLaveId
229 if(ObjectUtil.isNotEmpty(args) 236 if(ObjectUtil.isNotEmpty(args)
230 &&( 237 &&(
231 (args.containsKey("rowNumbers") && ObjectUtil.isNotEmpty(args.get("rowNumbers"))) 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 doSetSlaveIdToArgs( args, session); 242 doSetSlaveIdToArgs( args, session);
236 } 243 }
237 //存入已采集参数 244 //存入已采集参数
238 session.setArgs(args); 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 String resp = JSONUtil.toJsonStr(args) ; 252 String resp = JSONUtil.toJsonStr(args) ;
@@ -271,7 +274,7 @@ public class DynamicToolProvider implements ToolProvider { @@ -271,7 +274,7 @@ public class DynamicToolProvider implements ToolProvider {
271 List<ParamRule> paramRuleData = tool.getParamRuleListAll(); 274 List<ParamRule> paramRuleData = tool.getParamRuleListAll();
272 paramRuleData = paramRuleData.stream().filter(one-> 275 paramRuleData = paramRuleData.stream().filter(one->
273 ( ObjectUtil.isNotEmpty(args.get(one.getSParam())) ||ObjectUtil.isNotEmpty(args.get(one.getSParamValue()))) 276 ( ObjectUtil.isNotEmpty(args.get(one.getSParam())) ||ObjectUtil.isNotEmpty(args.get(one.getSParamValue())))
274 - && ObjectUtil.isNotEmpty(one.getSDynamicParamRuleSql()) 277 + && ObjectUtil.isNotEmpty(one.getSDynamicParamRuleSql())
275 ).collect(Collectors.toUnmodifiableList()); 278 ).collect(Collectors.toUnmodifiableList());
276 List<ParamRule> dynamicParamRule = new ArrayList<>(); 279 List<ParamRule> dynamicParamRule = new ArrayList<>();
277 //为空的时候需要重新插入 不为空 表示之前已经放过了 280 //为空的时候需要重新插入 不为空 表示之前已经放过了
@@ -283,9 +286,9 @@ public class DynamicToolProvider implements ToolProvider { @@ -283,9 +286,9 @@ public class DynamicToolProvider implements ToolProvider {
283 searMap.putAll(args); 286 searMap.putAll(args);
284 //新参数如果值变了移除掉之前插入的 287 //新参数如果值变了移除掉之前插入的
285 List<ParamRule> paramRuleDataAllNew = paramRuleDataAll.get().stream().filter(d-> 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 List<ParamRule> paramRuleList = tool.getParamRuleList().stream().filter(d-> 292 List<ParamRule> paramRuleList = tool.getParamRuleList().stream().filter(d->
290 !one.getSParam().equals(d.getSDynamicParam()) 293 !one.getSParam().equals(d.getSDynamicParam())
291 ||(one.getSParam().equals(d.getSDynamicParam()) && one.getSParamValue().equals(d.getSParamValue())) 294 ||(one.getSParam().equals(d.getSDynamicParam()) && one.getSParamValue().equals(d.getSParamValue()))
@@ -334,7 +337,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -334,7 +337,6 @@ public class DynamicToolProvider implements ToolProvider {
334 } 337 }
335 }else{ 338 }else{
336 //表示过程走自定义参数 339 //表示过程走自定义参数
337 -  
338 } 340 }
339 if(ObjectUtil.isNotEmpty(dynamicParamRuleOne)){ 341 if(ObjectUtil.isNotEmpty(dynamicParamRuleOne)){
340 //转换成BEAN 342 //转换成BEAN
@@ -407,34 +409,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -407,34 +409,6 @@ public class DynamicToolProvider implements ToolProvider {
407 .stream() 409 .stream()
408 .collect(Collectors.toList()); 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 private void doSetSlaveIdToArgs(Map<String,Object> args,UserSceneSession session){ 414 private void doSetSlaveIdToArgs(Map<String,Object> args,UserSceneSession session){
@@ -545,14 +519,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -545,14 +519,6 @@ public class DynamicToolProvider implements ToolProvider {
545 2. 只要方法返回结果,必须停止调用 519 2. 只要方法返回结果,必须停止调用
546 3. 当用户输入包含【数据确认】、确认数据、确认、第*条数据确认时,必须调用本工具 520 3. 当用户输入包含【数据确认】、确认数据、确认、第*条数据确认时,必须调用本工具
547 """; 521 """;
548 -// String forceToolPrompt = """  
549 -// 【工具调用规则】  
550 -// 1. 每个自定义方法最多只能调用 1 次  
551 -// 2. 只要方法返回结果,必须停止调用  
552 -// 3. 禁止重复调用同一个方法  
553 -// 4. 禁止无意义循环调用  
554 -// 5. 当用户输入包含【数据确认】、确认数据、确认、第*条数据确认时,必须调用本工具  
555 -// """;  
556 stoolDesc.append(forceToolPrompt); 522 stoolDesc.append(forceToolPrompt);
557 if (ObjectUtil.isNotEmpty(meta.getStoolDesc())) { 523 if (ObjectUtil.isNotEmpty(meta.getStoolDesc())) {
558 stoolDesc.append("MethodNo:").append(meta.getSMethodNo()) 524 stoolDesc.append("MethodNo:").append(meta.getSMethodNo())
@@ -661,6 +627,8 @@ public class DynamicToolProvider implements ToolProvider { @@ -661,6 +627,8 @@ public class DynamicToolProvider implements ToolProvider {
661 }); 627 });
662 sb.delete(sb.length()-1,sb.length()); 628 sb.delete(sb.length()-1,sb.length());
663 paramRule.setSRuleTs(sb.toString()); 629 paramRule.setSRuleTs(sb.toString());
  630 + //存入动态配置
  631 + paramRule.setSParamConfigValue(constMap);
664 return sb.toString(); 632 return sb.toString();
665 } 633 }
666 return StrUtil.EMPTY; 634 return StrUtil.EMPTY;
@@ -678,6 +646,7 @@ public class DynamicToolProvider implements ToolProvider { @@ -678,6 +646,7 @@ public class DynamicToolProvider implements ToolProvider {
678 if(ObjectUtil.isEmpty(data)){ 646 if(ObjectUtil.isEmpty(data)){
679 return StrUtil.EMPTY; 647 return StrUtil.EMPTY;
680 } 648 }
  649 +
681 if(data.get(0).containsKey("sGroupName")){ 650 if(data.get(0).containsKey("sGroupName")){
682 Map<Object, List<Map<String, Object>>> groupData = data.stream() 651 Map<Object, List<Map<String, Object>>> groupData = data.stream()
683 .collect(Collectors.groupingBy(map -> map.get("sGroupName"))); 652 .collect(Collectors.groupingBy(map -> map.get("sGroupName")));
@@ -691,12 +660,16 @@ public class DynamicToolProvider implements ToolProvider { @@ -691,12 +660,16 @@ public class DynamicToolProvider implements ToolProvider {
691 sb.append(","); 660 sb.append(",");
692 } 661 }
693 }); 662 });
  663 + //放入动态配置值
  664 + paramRule.setSParamConfigValue(groupData);
694 }else{ 665 }else{
695 data.forEach(one->{ 666 data.forEach(one->{
696 if(ObjectUtil.isNotEmpty(one.get(paramRule.getSParamValue()))){ 667 if(ObjectUtil.isNotEmpty(one.get(paramRule.getSParamValue()))){
697 sb.append(one.get(paramRule.getSParamValue())).append("/"); 668 sb.append(one.get(paramRule.getSParamValue())).append("/");
698 } 669 }
699 }); 670 });
  671 + //放入动态配置值
  672 + paramRule.setSParamConfigValue(data);
700 } 673 }
701 if(ObjectUtil.isNotEmpty(sb)){ 674 if(ObjectUtil.isNotEmpty(sb)){
702 sb.delete(sb.length()-1,sb.length()); 675 sb.delete(sb.length()-1,sb.length());
@@ -712,22 +685,47 @@ public class DynamicToolProvider implements ToolProvider { @@ -712,22 +685,47 @@ public class DynamicToolProvider implements ToolProvider {
712 return paramRuleDataAll; 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 public String doDynamicTool(ToolMeta meta,UserSceneSession session) { 717 public String doDynamicTool(ToolMeta meta,UserSceneSession session) {
717 List<ParamRule> paramRuleData = meta.getParamRuleListAll(); 718 List<ParamRule> paramRuleData = meta.getParamRuleListAll();
718 - List<ParamRule> paramRuleDataCheck = meta.getParamRuleListCheck();  
719 Map<String, Object> argsOld = session.getArgs(); 719 Map<String, Object> argsOld = session.getArgs();
720 if(ObjectUtil.isEmpty(argsOld)){ 720 if(ObjectUtil.isEmpty(argsOld)){
721 argsOld = new HashMap<>(); 721 argsOld = new HashMap<>();
722 } 722 }
723 Map<String, Object> args = session.getArgs(); 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 return askMsg; 727 return askMsg;
729 } 728 }
730 -  
731 List<ChatMessage> chatMessage = operableChatMemoryProvider.getCurrentChatMessages(session.getUserId()); 729 List<ChatMessage> chatMessage = operableChatMemoryProvider.getCurrentChatMessages(session.getUserId());
732 ChatMessage userMessage = getLastUserMessage(chatMessage); 730 ChatMessage userMessage = getLastUserMessage(chatMessage);
733 String input = ""; 731 String input = "";
@@ -750,12 +748,11 @@ public class DynamicToolProvider implements ToolProvider { @@ -750,12 +748,11 @@ public class DynamicToolProvider implements ToolProvider {
750 //合并已选择数据 748 //合并已选择数据
751 argsOld.putAll(args); 749 argsOld.putAll(args);
752 session.setArgs(argsOld); 750 session.setArgs(argsOld);
753 - String askMsg = buildAskUserMessage(meta, missingAfter,args); 751 + askMsg = buildAskUserMessage(meta, missingAfter,args);
754 session.setSFunPrompts(askMsg); 752 session.setSFunPrompts(askMsg);
755 List<ParamRule> paramRuleDataMiss = getMissParamRuleAfter(args, paramRuleData); 753 List<ParamRule> paramRuleDataMiss = getMissParamRuleAfter(args, paramRuleData);
756 - String sSystemPrompt = buildMissParamPrompt(session,paramRuleDataMiss); 754 + String sSystemPrompt = SystemPromptGenerator.buildMissParamPrompt(session,paramRuleDataMiss);
757 session.setSSystemPrompt(sSystemPrompt); 755 session.setSSystemPrompt(sSystemPrompt);
758 - addSystemMessage(session, askMsg);  
759 return askMsg; 756 return askMsg;
760 } 757 }
761 return executeTool(meta, args, paramRuleData, session.getUserId(), session); 758 return executeTool(meta, args, paramRuleData, session.getUserId(), session);
@@ -764,7 +761,7 @@ public class DynamicToolProvider implements ToolProvider { @@ -764,7 +761,7 @@ public class DynamicToolProvider implements ToolProvider {
764 String askconfirmMsg =StrUtil.EMPTY; 761 String askconfirmMsg =StrUtil.EMPTY;
765 if(4== meta.getIBizType() || meta.getIBizType()==5){ 762 if(4== meta.getIBizType() || meta.getIBizType()==5){
766 askconfirmMsg = doGetFromData( meta,args,session); 763 askconfirmMsg = doGetFromData( meta,args,session);
767 - String sSystemPrompt = buildDynamicSystemPrompt(session); 764 + String sSystemPrompt = SystemPromptGenerator.buildDynamicSystemPrompt(session);
768 session.setSSystemPrompt(sSystemPrompt); 765 session.setSSystemPrompt(sSystemPrompt);
769 return executeWithConfirmation(askconfirmMsg, session, meta); 766 return executeWithConfirmation(askconfirmMsg, session, meta);
770 }else{ 767 }else{
@@ -961,9 +958,9 @@ public class DynamicToolProvider implements ToolProvider { @@ -961,9 +958,9 @@ public class DynamicToolProvider implements ToolProvider {
961 Map<String,Object> returnMap = transformationArgs( args, paramDefs); 958 Map<String,Object> returnMap = transformationArgs( args, paramDefs);
962 List<ParamRule> paramDefsCheck = paramDefs.stream() 959 List<ParamRule> paramDefsCheck = paramDefs.stream()
963 .filter(pd -> !"sDynamicPart".equals(pd.getSParamValue())).collect(Collectors.toUnmodifiableList()); 960 .filter(pd -> !"sDynamicPart".equals(pd.getSParamValue())).collect(Collectors.toUnmodifiableList());
964 - paramDefsCheck = paramDefsCheck.stream() 961 + paramDefsCheck = paramDefsCheck.stream()
965 .filter(pd -> Boolean.TRUE.equals(pd.getBEmpty()) && pd.getBTipModel()).collect(Collectors.toUnmodifiableList()); 962 .filter(pd -> Boolean.TRUE.equals(pd.getBEmpty()) && pd.getBTipModel()).collect(Collectors.toUnmodifiableList());
966 - paramDefsCheck = paramDefsCheck.stream() 963 + paramDefsCheck = paramDefsCheck.stream()
967 .filter(pd -> checkMiss( returnMap, pd)).collect(Collectors.toUnmodifiableList()); 964 .filter(pd -> checkMiss( returnMap, pd)).collect(Collectors.toUnmodifiableList());
968 return paramDefsCheck.stream().map(ParamRule::getSParam) 965 return paramDefsCheck.stream().map(ParamRule::getSParam)
969 .toList(); 966 .toList();
@@ -1024,10 +1021,10 @@ public class DynamicToolProvider implements ToolProvider { @@ -1024,10 +1021,10 @@ public class DynamicToolProvider implements ToolProvider {
1024 private List<ParamRule> getMissParamRuleAfter(Map<String, Object> args, List<ParamRule> paramDefs) { 1021 private List<ParamRule> getMissParamRuleAfter(Map<String, Object> args, List<ParamRule> paramDefs) {
1025 Map<String,Object> returnMap = transformationArgs( args, paramDefs); 1022 Map<String,Object> returnMap = transformationArgs( args, paramDefs);
1026 return paramDefs.stream() 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 && (!returnMap.containsKey(pd.getSParamValue()) || (ObjectUtil.isEmpty(returnMap.get(pd.getSParamValue())))) 1026 && (!returnMap.containsKey(pd.getSParamValue()) || (ObjectUtil.isEmpty(returnMap.get(pd.getSParamValue()))))
1030 - ) 1027 + )
1031 .toList(); 1028 .toList();
1032 } 1029 }
1033 1030
@@ -1050,14 +1047,7 @@ public class DynamicToolProvider implements ToolProvider { @@ -1050,14 +1047,7 @@ public class DynamicToolProvider implements ToolProvider {
1050 return sReturn; 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 private String executeToolAfter(ToolMeta meta, Map<String, Object> args,List<ParamRule> paramDefs,UserSceneSession session) { 1051 private String executeToolAfter(ToolMeta meta, Map<String, Object> args,List<ParamRule> paramDefs,UserSceneSession session) {
1062 String sBizContent = meta.getSBizContent(); 1052 String sBizContent = meta.getSBizContent();
1063 Integer iBizType = meta.getIBizType(); 1053 Integer iBizType = meta.getIBizType();
@@ -1084,7 +1074,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -1084,7 +1074,6 @@ public class DynamicToolProvider implements ToolProvider {
1084 sessA.remove("sSlaveId"); 1074 sessA.remove("sSlaveId");
1085 sessA.remove("operateType"); 1075 sessA.remove("operateType");
1086 session.setArgs(sessA); 1076 session.setArgs(sessA);
1087 - addSystemMessage(session, sMsg);  
1088 throw new BusinessException(-1,sMsg); 1077 throw new BusinessException(-1,sMsg);
1089 } 1078 }
1090 List<Map<String,Object>> sRowData = doGetFromDataWq( meta, args, session); 1079 List<Map<String,Object>> sRowData = doGetFromDataWq( meta, args, session);
@@ -1095,8 +1084,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -1095,8 +1084,6 @@ public class DynamicToolProvider implements ToolProvider {
1095 sessA.remove("sSlaveId"); 1084 sessA.remove("sSlaveId");
1096 sessA.remove("operateType"); 1085 sessA.remove("operateType");
1097 session.setArgs(sessA); 1086 session.setArgs(sessA);
1098 - //插入AI记忆  
1099 - addSystemMessage(session, sMsg);  
1100 throw new BusinessException(-1,sMsg); 1087 throw new BusinessException(-1,sMsg);
1101 } 1088 }
1102 Map<String,Object> dataOne = DeepCopyUtils.deepCopy(args); 1089 Map<String,Object> dataOne = DeepCopyUtils.deepCopy(args);
@@ -1150,7 +1137,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -1150,7 +1137,6 @@ public class DynamicToolProvider implements ToolProvider {
1150 } else { 1137 } else {
1151 String sMsgText = "未找到对应的数据"; 1138 String sMsgText = "未找到对应的数据";
1152 session.setSFunPrompts(sMsgText); 1139 session.setSFunPrompts(sMsgText);
1153 - addSystemMessage(session, sMsgText);  
1154 throw new BusinessException(-1,sMsgText); 1140 throw new BusinessException(-1,sMsgText);
1155 } 1141 }
1156 } 1142 }
@@ -1161,12 +1147,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -1161,12 +1147,6 @@ public class DynamicToolProvider implements ToolProvider {
1161 return "操作成功"; 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 private List<Map<String,Object>> doGetFromDataWq(ToolMeta meta, Map<String, Object> args,UserSceneSession session){ 1150 private List<Map<String,Object>> doGetFromDataWq(ToolMeta meta, Map<String, Object> args,UserSceneSession session){
1171 String sUrl = meta.getSendUrl(); 1151 String sUrl = meta.getSendUrl();
1172 Map<String,Object> sBody = new HashMap<>(); 1152 Map<String,Object> sBody = new HashMap<>();
@@ -1367,103 +1347,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -1367,103 +1347,6 @@ public class DynamicToolProvider implements ToolProvider {
1367 return markdown.toString(); 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 private List<Map<String, Object>> findFieldNameByChinese(List<Map<String, Object>> sAIshowfieldShow,List<Map<String, Object>> rows){ 1350 private List<Map<String, Object>> findFieldNameByChinese(List<Map<String, Object>> sAIshowfieldShow,List<Map<String, Object>> rows){
1468 Map<String,String> keyMappings = new HashMap<>(); 1351 Map<String,String> keyMappings = new HashMap<>();
1469 List<String> selectedKeys = new ArrayList<>(); 1352 List<String> selectedKeys = new ArrayList<>();
@@ -1596,9 +1479,9 @@ public class DynamicToolProvider implements ToolProvider { @@ -1596,9 +1479,9 @@ public class DynamicToolProvider implements ToolProvider {
1596 return check || userResponse.contains("生成") 1479 return check || userResponse.contains("生成")
1597 || userResponse.contains("确认") 1480 || userResponse.contains("确认")
1598 || (ObjectUtil.isNotEmpty(session.getArgs()) 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 \ No newline at end of file 1488 \ No newline at end of file