Commit f0318b7bafc221490c485a944620d9658d7d751a
1 parent
1b14dc87
添加未清选择 改成动态引导语
Showing
7 changed files
with
332 additions
and
206 deletions
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
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
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 | ... | ... |