Commit 51694876c0e31062ff1a33d5d5afd50e647dad2b

Authored by qianbao
1 parent f3eace43

1111

logPath_IS_UNDEFINED/2026-02-09/2026-02-09.debug-0.log deleted
logPath_IS_UNDEFINED/2026-02-09/2026-02-09.error-0.log deleted
logPath_IS_UNDEFINED/2026-02-09/2026-02-09.info-0.log deleted
src/main/java/com/xly/agent/DynamicTableNl2SqlAiAgent.java
... ... @@ -25,9 +25,12 @@ public interface DynamicTableNl2SqlAiAgent {
25 25 3.1 多表关联必须使用 表名+字段名(如表名.字段名),严格按下面[涉及表名]中的表次序关联,聚合函数(SUM/COUNT/AVG/MIN/MAX)必须加业务化别名,日期过滤使用标准DATE格式(yyyy-MM-dd);
26 26 3.2 SQL所有字段均采用 表名.字段名 方式生成,务必确保 字段名 在相应的 表名 描述的字段中存在,如果不存在重试其它方式,直到满足条件
27 27 3.3 SQL所有字段涉及的所有表名,都要**严格**按下面[涉及表名]中的表次序关联,没有关联不允许使用
28   - 3.4 SQL所有的查询条件,如果是字符类型的字段,均需要加不为空判断(如ifnull(customername,'')<>'')
  28 + 3.4 SQL所有的查询条件,如果是字符类型的字段,均需要加不为空判断,用示例格式判断,示例:ifnull(customername,'')<>''
  29 + 3.5 SQL所有的显示字段的别名中,不能出现空格,如: tCreateDate as earliest 订单日期,正确的应是 tCreateDate as earliest订单日期
29 30 4. 安全约束:禁止生成任何DDL/DML语句(DROP/ALTER/INSERT/UPDATE/DELETE等),禁止使用子查询、存储过程、自定义函数、临时表;
30   - 5. 精准性:严格按用户需求+传入的表结构生成,仅使用指定字段/表,无多余字段、无无效表关联、无冗余过滤条件;
  31 + 5. 精准性:
  32 + 5.1 严格按用户需求+传入的表结构生成,仅使用指定字段/表,无多余字段、无无效表关联、无冗余过滤条件;
  33 + 5.2 用户需求中没有明确的日期条件,默认为全部数据,禁止增加任何日期过滤条件
31 34 6. 关联规则:多表关联时,必须使用外键/业务唯一键关联,禁止无意义关联。
32 35 """)
33 36 @UserMessage("""
... ...
src/main/java/com/xly/agent/ErpAiAgent.java
... ... @@ -14,7 +14,9 @@ public interface ErpAiAgent {
14 14 你是一个专业的 工具方法匹配与参数提取 助手,核心职责是根据用户输入(含历史对话)精准匹配工具方法、提取参数、判断缺失并生成交互式补全提示;
15 15 按严格按以下步骤处理,无任何额外输出!规则如下:
16 16 1. 方法匹配:先精准拆解用户查询的核心业务意图,再自动匹配唯一符合用户问题的工具方法(MethodNo),禁止自创;
17   - 2. 参数提取:提取该工具的全部参数,与描述完全一致,严格按标注类型赋值,数字无引号,为空时禁止赋值0;
  17 + 2. 参数提取:提取该工具的全部参数,与描述完全一致,严格按标注类型赋值,规则如下:
  18 + 2.1 数字无引号,为空时禁止赋值0;
  19 + 2.2 如果有空格需要去掉空格后再提取。
18 20 """)
19 21 @UserMessage("用户输入:{{userInput}}")
20 22 String chat(@MemoryId String userId, @V("userInput") String userInput);
... ...
src/main/java/com/xly/mapper/AiToolDetailParamsMapper.java
... ... @@ -12,6 +12,6 @@ import java.util.List;
12 12 public interface AiToolDetailParamsMapper {
13 13  
14 14 // XML配置方式
15   - @Select("SELECT * FROM ai_tool_detail_params")
  15 + @Select("SELECT * FROM ai_tool_detail_params ORDER BY iOrder,iIncrement ")
16 16 List<ParamRule> findAll();
17 17 }
18 18 \ No newline at end of file
... ...
src/main/java/com/xly/service/UserSceneSessionService.java
... ... @@ -75,6 +75,21 @@ public class UserSceneSessionService {
75 75 CHAT_AGENT_CACHE.clear();
76 76 ERP_DynamicTableNl2SqlAiAgent_CACHE.clear();
77 77 }
  78 +
  79 + /***
  80 + * @Author 钱豹
  81 + * @Date 14:03 2026/2/10
  82 + * @Param []
  83 + * @return void
  84 + * @Description 清除用户记忆
  85 + **/
  86 + public void cleanUserSession(String sUserId){
  87 + USER_SCENE_SESSION_CACHE.remove(sUserId);
  88 + ERP_AGENT_CACHE.remove(sUserId);
  89 + CHAT_AGENT_CACHE.remove(sUserId);
  90 + ERP_DynamicTableNl2SqlAiAgent_CACHE.remove(sUserId);
  91 + }
  92 +
78 93 public UserSceneSession getUserSceneSession(String sUserId, String sUserType,String authorization){
79 94 if (USER_SCENE_SESSION_CACHE.containsKey(sUserId)) {
80 95 return USER_SCENE_SESSION_CACHE.get(sUserId);
... ...
src/main/java/com/xly/service/XlyErpService.java
... ... @@ -111,6 +111,7 @@ public class XlyErpService {
111 111 ){
112 112 sResponMessage = getDynamicTableSql(session, input, userId, userInput);
113 113 }
  114 +
114 115 //如果返回空的进入闲聊模式
115 116 if (ObjectUtil.isEmpty(sResponMessage)){
116 117 return getChatiAgent (input, session);
... ... @@ -259,6 +260,8 @@ public class XlyErpService {
259 260 .toolProvider(dynamicToolProvider)
260 261 .build();
261 262 UserSceneSessionService.ERP_AGENT_CACHE.put(userId, aiAgent);
  263 +// 初始化AiService 以防止热加载太慢 找不到相应的方法
  264 + aiAgent.chat(userId, "initAiService");
262 265 log.info("用户{}Agent构建完成,已选场景:{},场景ID{}",
263 266 userId, session.isSceneSelected() ? session.getCurrentScene().getSSceneName() : "未选(全场景匹配)", dynamicToolProvider.sSceneIdMap.get(userId));
264 267 }
... ... @@ -353,8 +356,7 @@ public class XlyErpService {
353 356 .build();
354 357 UserSceneSessionService.CHAT_AGENT_CACHE.put(session.getUserId(), chatiAgent); }
355 358 String sChatMessage = chatiAgent.chat(session.getUserId(), input);
356   - String systemText = " 你已进入「随便聊聊」专栏, 可"+CommonConstant.RESET;
357   - return AiResponseDTO.builder().aiText(sChatMessage).sSceneName("随便聊聊").systemText(systemText).sReturnType(ReturnTypeCode.HTML.getCode()).build();
  359 + return AiResponseDTO.builder().aiText(sChatMessage).sSceneName("随便聊聊").systemText(StrUtil.EMPTY).sReturnType(ReturnTypeCode.HTML.getCode()).build();
358 360 }
359 361  
360 362 }
361 363 \ No newline at end of file
... ...
src/main/java/com/xly/tool/DynamicToolProvider.java
... ... @@ -62,7 +62,7 @@ import java.util.stream.IntStream;
62 62 @RequiredArgsConstructor
63 63 public class DynamicToolProvider implements ToolProvider {
64 64  
65   -// private final ToolMetaMapper toolMetaMapper;
  65 + // private final ToolMetaMapper toolMetaMapper;
66 66 private final ObjectMapper objectMapper;
67 67 private final ToolMetaMapper toolMetaMapper;
68 68 private final ParamRuleMapper paramRuleMapper;
... ... @@ -111,7 +111,7 @@ public class DynamicToolProvider implements ToolProvider {
111 111 String sceneId = meta.getSSceneId();
112 112 List<ToolSpecificationHolder> dataList = new ArrayList<>();
113 113 if(ObjectUtil.isNotEmpty(sceneToolCacheMap.get(sceneId))) {
114   - dataList = sceneToolCacheMap.get(sceneId);
  114 + dataList = sceneToolCacheMap.get(sceneId);
115 115 }
116 116 dataList.add(new ToolSpecificationHolder(spec, executor));
117 117 sceneToolCacheMap.put(sceneId, dataList);
... ... @@ -141,7 +141,7 @@ public class DynamicToolProvider implements ToolProvider {
141 141 sAIshowfieldArry.add("sSlaveId");
142 142 String sSrcFormId = meta.getSSrcFormId();
143 143 //获取对应的窗体配置
144   - StringBuffer sSql =new StringBuffer().append("SELECT A.sChinese AS label,A.sName,A.sControlName,B.sId AS sFormcustomId,A.sName AS sId FROM gdsconfigformslave AS A ")
  144 + StringBuffer sSql =new StringBuffer().append("SELECT 10000 AS iOrderShow,A.sChinese AS label,A.sName,A.sControlName,B.sId AS sFormcustomId,A.sName AS sId FROM gdsconfigformslave AS A ")
145 145 .append("JOIN gdsconfigformmaster AS B ON A.sParentId = B.sId ")
146 146 .append("WHERE B.sParentId = #{sSrcFormId} AND A.sName <> '' AND INSTR(A.sControlName,'Btn')=0 AND (A.bVisible = 1 OR A.sName =#{sName}) ");
147 147 Map<String,Object> searMap = new HashMap<>();
... ... @@ -150,11 +150,17 @@ public class DynamicToolProvider implements ToolProvider {
150 150 List<Map<String,Object>> sAIshowfieldShowAll = dynamicExeDbService.findSql(searMap,sSql.toString());
151 151 if(ObjectUtil.isNotEmpty(sAIshowfieldShowAll)){
152 152 sAIshowfieldShowAll = sAIshowfieldShowAll.stream().filter(m-> sAIshowfieldArry.contains(m.get("sName").toString())).collect(Collectors.toUnmodifiableList());
153   - meta.setSAIshowfieldShow(sAIshowfieldShowAll);
  153 + sAIshowfieldShowAll.forEach(one->{
  154 + one.put("iOrderShow",sAIshowfieldArry.indexOf(one.get("sName").toString())+1);
  155 + });
  156 + List<Map<String,Object>> sAIshowfieldShowData = new ArrayList<>();
  157 + sAIshowfieldShowData.addAll(sAIshowfieldShowAll);
  158 + sAIshowfieldShowData.sort(Comparator.comparing(h -> Integer.valueOf(h.get("iOrderShow").toString())));
  159 + meta.setSAIshowfieldShow(sAIshowfieldShowData);
154 160 }
155 161 List<ParamRule> paramRuleListNew = new ArrayList<>(paramRuleList);
156 162 for(int i=0;i<sAIshowfieldShowAll.size();i++){
157   - Map<String,Object> sAIshowfieldShow = sAIshowfieldShowAll.get(i);
  163 + Map<String,Object> sAIshowfieldShow = sAIshowfieldShowAll.get(i);
158 164 List<ParamRule> one = paramRuleList.stream().filter(m->m.getSParamValue().equals(sAIshowfieldShow.get("sName"))).collect(Collectors.toUnmodifiableList());
159 165 if(ObjectUtil.isEmpty(one)){
160 166 ParamRule pr = new ParamRule();
... ... @@ -188,7 +194,7 @@ public class DynamicToolProvider implements ToolProvider {
188 194 // List<ToolSpecification> specs = new ArrayList<>();
189 195 String sUserId = request.chatMemoryId().toString();
190 196 Map<ToolSpecification, ToolExecutor> executors = new HashMap<>();
191   - // sceneToolCacheMap.get(sSceneIdMap.get(sUserId));
  197 + // sceneToolCacheMap.get(sSceneIdMap.get(sUserId));
192 198 //获取Session
193 199 UserSceneSession session = UserSceneSessionService.USER_SCENE_SESSION_CACHE.get(sUserId);
194 200 //过滤对应的权限方法
... ... @@ -240,7 +246,7 @@ public class DynamicToolProvider implements ToolProvider {
240 246 // 示例:{\"客户名称\":\"小羚羊软件开发有限公司\",\"产品名称\":\"企业宣传册\",\"数量\":1000,\"产品描述\":\"黑色注意色差\",\"生产要求\":\"上光,覆膜\"}
241 247 Map<String,Object> slMap = new HashMap<>();
242 248 for (ParamRule paramRule : paramRuleData) {
243   - String paramName = ObjectUtil.isEmpty(paramRule.getSParamValue())?null:paramRule.getSParamValue();
  249 +// String paramName = ObjectUtil.isEmpty(paramRule.getSParamValue())?null:paramRule.getSParamValue();
244 250 String paramDesc = ObjectUtil.isEmpty(paramRule.getSParam())?null:paramRule.getSParam();
245 251 String paramType = paramRule.getSType();
246 252 Boolean bEmpty = paramRule.getBEmpty();
... ... @@ -251,7 +257,7 @@ public class DynamicToolProvider implements ToolProvider {
251 257 //中文
252 258 slMap.put(paramDesc,sExampleValue);
253 259 }
254   - if (paramName == null || paramName.trim().isEmpty()) {
  260 + if (paramDesc == null || paramDesc.trim().isEmpty()) {
255 261 continue;
256 262 }
257 263 // 构建参数属性
... ... @@ -335,7 +341,7 @@ public class DynamicToolProvider implements ToolProvider {
335 341 }else{
336 342 sRuleCost = getArrrayBySql(paramRule);
337 343 }
338   - // eg: 付款方式(字符串,互斥枚举值[90天、60天、现结],默认值[现结])
  344 + // eg: 付款方式(字符串,互斥枚举值[90天、60天、现结],默认值[现结])
339 345 if(bEmpty){
340 346 sbt.append(paramDesc).append("(").append("字符串") .append(",互斥枚举值 [").append(sRuleCost).append("]");
341 347 if(ObjectUtil.isNotEmpty(paramRule.getSDefaultValue())){
... ... @@ -369,9 +375,9 @@ public class DynamicToolProvider implements ToolProvider {
369 375 boolean required = bEmpty;
370 376 // 添加参数
371 377 if (required) {
372   - builder.addParameter(paramName, properties);
  378 + builder.addParameter(paramDesc, properties);
373 379 } else {
374   - builder.addOptionalParameter(paramName, properties);
  380 + builder.addOptionalParameter(paramDesc, properties);
375 381 }
376 382 }
377 383  
... ... @@ -500,15 +506,14 @@ public class DynamicToolProvider implements ToolProvider {
500 506 log.warn("参数解析失败,tool={}, args={}", meta.getSMethodNo(), toolExecutionRequest.arguments(), e);
501 507 return String.valueOf(errorResult(toolExecutionRequest, errorMsg));
502 508 }
503   - Map<String, Object> argsOld = DeepCopyUtils.deepCopy(args);
504   -
  509 +// Map<String, Object> argsOld = DeepCopyUtils.deepCopy(args);
505 510 List<ParamRule> paramRuleData = meta.getParamRuleListAll();
506 511 // 2. 【自动补全】应用参数的默认值
507 512 args = applyDefaultValues(args, paramRuleData);
508 513  
509 514 // 2.1 【补全动态参数】动态参数补全
510 515 try{
511   - args = applyValues(args, meta.getParamRuleListCheck());
  516 + args = applyValues(args, meta.getParamRuleListCheck());
512 517 }catch (Exception e){
513 518 log.error("返回信息",e);
514 519 String sTsMsg = e.getMessage();
... ... @@ -554,7 +559,7 @@ public class DynamicToolProvider implements ToolProvider {
554 559 operableChatMemoryProvider.get(memoryId).add(UserMessage.from("SYSTEM: 等待用户确认或选择部分数据操作"));
555 560 return String.valueOf(successResult(toolExecutionRequest,askconfirmMsg));
556 561 }else{
557   - askconfirmMsg =getDefMessage(argsOld,meta.getSControlName());
  562 + askconfirmMsg =getDefMessage(args,meta.getSControlName(),meta);
558 563 }
559 564 // 返回需要确认的结果
560 565 return executeWithConfirmation(toolExecutionRequest,askconfirmMsg,operableChatMemoryProvider.get(memoryId), session, meta).text();
... ... @@ -567,17 +572,23 @@ public class DynamicToolProvider implements ToolProvider {
567 572 * @return java.lang.String
568 573 * @Description MAP转提示
569 574 **/
570   - private String getDefMessage(Map<String,Object> argMap,String sName){
  575 + private String getDefMessage(Map<String,Object> argMap,String sName,ToolMeta meta){
  576 + List<ParamRule> showList = meta.getParamRuleListAll();
  577 + List<ParamRule> showListData = new ArrayList<>();
  578 + showList = showList.stream().filter(one->one.getBTipModel()).collect(Collectors.toUnmodifiableList());
  579 + showListData.addAll(showList);
  580 + showListData.sort(Comparator.comparing(h -> h.getIOrder()));
571 581 StringBuilder markdown = new StringBuilder().append("\n");
572 582 markdown.append("\n---\n");
573   - // 遍历 Map 生成表格行
574   - argMap.forEach((key, value) -> {
575   - String valueStr = value != null ? value.toString() : "";
576   - markdown.append("- ")
577   - .append(key)
578   - .append(": `")
579   - .append(valueStr)
580   - .append("`\n");
  583 + showListData.forEach(one->{
  584 + if(argMap.containsKey(one.getSParam())){
  585 + String valueStr = argMap.get(one.getSParam()) != null ? argMap.get(one.getSParam()).toString() : "";
  586 + markdown.append("- ")
  587 + .append(one.getSParam())
  588 + .append(": `")
  589 + .append(valueStr)
  590 + .append("`\n");
  591 + }
581 592 });
582 593 markdown.append("\n---\n");
583 594 appendConfirm(markdown,sName);
... ... @@ -595,8 +606,8 @@ public class DynamicToolProvider implements ToolProvider {
595 606 markdown.append("请确认是否执行").append(sName).append("操作?如果全部,直接回复"全部确认",如果部分,选择后回复"部分确认"\n");
596 607 //全部确认 ,部分确认,取消
597 608 markdown.append("回复:&emsp;&emsp;").append("**<a href=\"#\" data-action=\"reset\" data-text=\"全部确认\">全部确认</a>**").append("&emsp;")
598   - .append("**<a href=\"#\" data-action=\"reset\" data-text=\"确认\">部分确认</a>**").append("&emsp;")
599   - .append("**<a href=\"#\" data-action=\"reset\" data-text=\"取消\">取消</a>**");
  609 + .append("**<a href=\"#\" data-action=\"reset\" data-text=\"确认\">部分确认</a>**").append("&emsp;")
  610 + .append("**<a href=\"#\" data-action=\"reset\" data-text=\"取消\">取消</a>**");
600 611 }
601 612  
602 613 /***
... ... @@ -656,7 +667,7 @@ public class DynamicToolProvider implements ToolProvider {
656 667 }
657 668 });
658 669 }
659   - });
  670 + });
660 671 return result;
661 672 }
662 673  
... ... @@ -711,6 +722,12 @@ public class DynamicToolProvider implements ToolProvider {
711 722 }
712 723 }
713 724 List<Map<String,Object>> dataListNew = dataList.stream().filter(one-> one.get(sValue).equals(args.get(name)) || one.get(sValue).equals(args.get(sValue))).collect(Collectors.toUnmodifiableList());
  725 + //如果枚举类型枚举值中又不存在AI 返回的数据
  726 + if("enum".equals(sType) && ObjectUtil.isEmpty(dataListNew)){
  727 + args.remove(name);
  728 + args.remove(sValue);
  729 + continue;
  730 + }
714 731 if(ObjectUtil.isNotEmpty(dataListNew)){
715 732 dataList = new ArrayList<>();
716 733 dataList.add(dataListNew.get(0));
... ... @@ -735,14 +752,14 @@ public class DynamicToolProvider implements ToolProvider {
735 752 if(dataList.size()>1){
736 753 List<Map<String, Object>> finalDataList = dataList;
737 754 IntStream.range(0, dataList.size())
738   - .forEach(iRowNum ->{
739   - sData.append((iRowNum + 1)).append(".").append(finalDataList.get(iRowNum).get(pd.getSParamValue()))
740   - .append("\n");
  755 + .forEach(iRowNum ->{
  756 + sData.append((iRowNum + 1)).append(".").append(finalDataList.get(iRowNum).get(pd.getSParamValue()))
  757 + .append("\n\n");
741 758  
742   - });
  759 + });
743 760 String sParamMissMemo = StrUtil.EMPTY;
744 761 if(ObjectUtil.isEmpty(pd.getSParamMissMemo())){
745   - sParamMissMemo = pd.getSParam()+"存在多个,请选择:"+sData;
  762 + sParamMissMemo = pd.getSParam()+"存在多个,请选择:<br/>"+sData;
746 763 }else{
747 764 sParamMissMemo = StrUtil.format(pd.getSParamMissMemo(),sData.toString());
748 765 }
... ... @@ -779,7 +796,7 @@ public class DynamicToolProvider implements ToolProvider {
779 796 .filter(pd -> Boolean.TRUE.equals(pd.getBEmpty()) && pd.getBTipModel())
780 797 .filter(pd ->
781 798 (!returnMap.containsKey(pd.getSParam()) || (ObjectUtil.isEmpty(returnMap.get(pd.getSParam()))))
782   - && (!returnMap.containsKey(pd.getSParamValue()) || (ObjectUtil.isEmpty(returnMap.get(pd.getSParamValue()))))
  799 + && (!returnMap.containsKey(pd.getSParamValue()) || (ObjectUtil.isEmpty(returnMap.get(pd.getSParamValue()))))
783 800 )
784 801 .map(ParamRule::getSParam)
785 802 .toList();
... ... @@ -807,7 +824,7 @@ public class DynamicToolProvider implements ToolProvider {
807 824 log.info("执行工具:{},参数:{}", meta.getSMethodNo(), args);
808 825 // 2.2 将中文key转换成英文key
809 826 args = transformationArgs( args, paramRuleData);
810   - String sReturn ="成功";
  827 + String sReturn ="执行成功";
811 828 try{
812 829 sReturn = executeToolAfter(meta, args,toolExecutionRequest,paramRuleData,session);
813 830 }catch (Exception e) {
... ... @@ -827,55 +844,57 @@ public class DynamicToolProvider implements ToolProvider {
827 844 **/
828 845 private String executeToolAfter(ToolMeta meta, Map<String, Object> args,ToolExecutionRequest toolExecutionRequest,List<ParamRule> paramDefs,UserSceneSession session) {
829 846 // {"1":"存储过程","2":"SQL查询","3":"第三方API","4":"窗体查询","5":"按钮执行","6":"其它"}
830   - String sBizContent = meta.getSBizContent();
831   - Integer iBizType = meta.getIBizType();
832   - args.put("sUserId",session.getUserId());
833   - if(iBizType==1 || iBizType==4){
834   - Map<String,Object> data = new HashMap<>(args);
835   - data.put("sData", JSONObject.toJSONString(data));
836   - Map<String, Object> searMap = this.dynamicExeDbService.getDoProMap(sBizContent, data);
837   - Map<String,Object> sReturn = this.dynamicExeDbService.getCallPro(searMap,sBizContent);
838   - Integer sCode = ObjectUtil.isNotEmpty(sReturn.get(ProcedureConstant.SCODE))? Integer.valueOf(sReturn.get(ProcedureConstant.SCODE).toString()):0;
839   - String sMsgText = ObjectUtil.isNotEmpty(sReturn.get(ProcedureConstant.SRETURN))? sReturn.get(ProcedureConstant.SRETURN).toString():"操作成功";
840   - if(sCode< 0){
841   - String msg = ObjectUtil.isEmpty(sMsgText) ?"调用过程sCode:"+Integer.valueOf(searMap.get(ProcedureConstant.SCODE).toString()):sMsgText;
842   - return String.valueOf(askUserResult(toolExecutionRequest, msg));
843   - }
844   - return String.valueOf(successResult(toolExecutionRequest, sMsgText));
845   - }else if(iBizType==2 && ObjectUtil.isNotEmpty(sBizContent)){
846   - //SQL查询
847   - if(sBizContent.toLowerCase().startsWith("update")){
848   - this.dynamicExeDbService.updateSql(args,sBizContent);
849   - }else if(sBizContent.toLowerCase().startsWith("delete")){
850   - this.dynamicExeDbService.delSql(args,sBizContent);
851   - }else if(sBizContent.toLowerCase().startsWith("insert")){
852   - this.dynamicExeDbService.addSql(args,sBizContent);
853   - }else{
854   - List<Map<String,Object>> retData = this.dynamicExeDbService.findSql(args,sBizContent);
855   - if(ObjectUtil.isNotEmpty(retData)){
856   - StringBuffer sb = new StringBuffer();
857   - retData.forEach(one->{
858   - one.forEach((k,v)->{
859   - sb.append(v).append(" ");
860   - });
861   - sb.append("<br/>");
862   - });
863   - if(ObjectUtil.isNotEmpty(retData)){
864   - sb.append("请根据这些信息安排今天的工作吧!如果有具体任务需要进一步处理,请告诉我");
865   - }
866   - session.setSFunPrompts(sb.toString());
867   - if("queryTodayTask".equals(meta.getSMethodNo())){
868   - session.setBCleanMemory(true);
869   - }
870   - return String.valueOf(successResult(toolExecutionRequest, sb.toString()));
871   - }else{
872   - return String.valueOf(askUserResult(toolExecutionRequest, "未找到对应的数据"));
873   - }
874   - }
875   - }else if(iBizType==3){
876   - return HttpsRequestUtil.me().doRequestHttp(sBizContent,JSONUtil.toJsonStr(args),
877   - new HashMap<>(),"POST","JSON");
878   - }
  847 + String sBizContent = meta.getSBizContent();
  848 + Integer iBizType = meta.getIBizType();
  849 + args.put("sUserId",session.getUserId());
  850 + if(iBizType==1 || iBizType==4){
  851 + Map<String,Object> data = new HashMap<>(args);
  852 + data.put("sData", JSONObject.toJSONString(data));
  853 + Map<String, Object> searMap = this.dynamicExeDbService.getDoProMap(sBizContent, data);
  854 + Map<String,Object> sReturn = this.dynamicExeDbService.getCallPro(searMap,sBizContent);
  855 + Integer sCode = ObjectUtil.isNotEmpty(sReturn.get(ProcedureConstant.SCODE))? Integer.valueOf(sReturn.get(ProcedureConstant.SCODE).toString()):0;
  856 + String sMsgText = ObjectUtil.isNotEmpty(sReturn.get(ProcedureConstant.SRETURN))? sReturn.get(ProcedureConstant.SRETURN).toString():"操作成功";
  857 + if(sCode< 0){
  858 + String msg = ObjectUtil.isEmpty(sMsgText) ?"调用过程sCode:"+Integer.valueOf(searMap.get(ProcedureConstant.SCODE).toString()):sMsgText;
  859 + return String.valueOf(askUserResult(toolExecutionRequest, msg));
  860 + }
  861 + session.setSFunPrompts(sMsgText);
  862 + return sMsgText;
  863 + }else if(iBizType==2 && ObjectUtil.isNotEmpty(sBizContent)){
  864 + //SQL查询
  865 + if(sBizContent.toLowerCase().startsWith("update")){
  866 + this.dynamicExeDbService.updateSql(args,sBizContent);
  867 + }else if(sBizContent.toLowerCase().startsWith("delete")){
  868 + this.dynamicExeDbService.delSql(args,sBizContent);
  869 + }else if(sBizContent.toLowerCase().startsWith("insert")){
  870 + this.dynamicExeDbService.addSql(args,sBizContent);
  871 + }else{
  872 + List<Map<String,Object>> retData = this.dynamicExeDbService.findSql(args,sBizContent);
  873 + if(ObjectUtil.isNotEmpty(retData)){
  874 + StringBuffer sb = new StringBuffer();
  875 + retData.forEach(one->{
  876 + one.forEach((k,v)->{
  877 + sb.append(v).append(" ");
  878 + });
  879 + sb.append("<br/>");
  880 + });
  881 + if(ObjectUtil.isNotEmpty(retData)){
  882 + sb.append("请根据这些信息安排今天的工作吧!如果有具体任务需要进一步处理,请告诉我");
  883 + }
  884 + session.setSFunPrompts(sb.toString());
  885 + if("queryTodayTask".equals(meta.getSMethodNo())){
  886 + session.setBCleanMemory(true);
  887 + }
  888 + return String.valueOf(successResult(toolExecutionRequest, sb.toString()));
  889 + }else{
  890 + session.setSFunPrompts("未找到对应的数据");
  891 + return "未找到对应的数据";
  892 + }
  893 + }
  894 + }else if(iBizType==3){
  895 + return HttpsRequestUtil.me().doRequestHttp(sBizContent,JSONUtil.toJsonStr(args),
  896 + new HashMap<>(),"POST","JSON");
  897 + }
879 898 return String.valueOf(successResult(toolExecutionRequest, "操作成功"));
880 899 }
881 900  
... ... @@ -1056,7 +1075,7 @@ public class DynamicToolProvider implements ToolProvider {
1056 1075 .filter(Objects::nonNull)
1057 1076 .collect(Collectors.toList());
1058 1077 }
1059   -
  1078 +
1060 1079 /**
1061 1080 * 构建确认操作消息
1062 1081 */
... ...
src/main/java/com/xly/tts/service/PythonTtsProxyService.java
... ... @@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil;
4 4 import cn.hutool.core.util.StrUtil;
5 5 import com.xly.constant.ReturnTypeCode;
6 6 import com.xly.entity.AiResponseDTO;
  7 +import com.xly.service.UserSceneSessionService;
7 8 import com.xly.service.XlyErpService;
8 9 import com.xly.tts.bean.*;
9 10 import com.xly.util.AdvancedSymbolRemover;
... ... @@ -40,6 +41,8 @@ public class PythonTtsProxyService {
40 41  
41 42 private final XlyErpService xlyErpService;
42 43  
  44 + private final UserSceneSessionService userSceneSessionService;
  45 +
43 46 @PostConstruct
44 47 public void init() {
45 48 executorService = Executors.newFixedThreadPool(5);
... ... @@ -86,6 +89,8 @@ public class PythonTtsProxyService {
86 89 String sUserId = request.getUserid();
87 90 String sUserType = request.getUsertype();
88 91 String authorization = request.getAuthorization();
  92 + //清空记忆
  93 + userSceneSessionService.cleanUserSession(sUserId);
89 94 // xlyErpService.initSceneGuide(sUserId,sUserType,StrUtil.EMPTY)
90 95 AiResponseDTO voiceText = xlyErpService.initSceneGuide(StrUtil.EMPTY,sUserId,sUserType, authorization);
91 96 voiceText.setSReturnType(ReturnTypeCode.HTML.getCode());
... ...
src/main/resources/templates/chat.html
... ... @@ -461,12 +461,12 @@
461 461  
462 462 <script>
463 463 let sessionId ="";
464   - let userid= "17706006510007934913359242990000";
465   - // let userid= "17502321750004978169421209637000";
466   - // let usertype= "sysadmin";
467   - let usertype= "General";
468   - let authorization= "B52FF9DBEF24EA7F40A160E78A3AFF39D42BEDC4D9CB33A32B7BE6B68F15AF74F3419238942A93E9AD666629E18D159AF7FE144A6407DE745BA0AEC8B235FC1D686C9F04512DE45F9E176530AFD123789C9A98822AD3F0E3100F8DBBB5963377538155B7ADAEE71E899235DC1122F426";
469   - // let authorization= "1EDB99C9BF070115F7A57AC43D8CB09F0B8C49F979DAB63A2AEA84B372B2B42BF3419238942A93E9AD666629E18D159AF7FE144A6407DE745BA0AEC8B235FC1D7755CEF7BCCED5C5F3A6D8323EB6C67929D9BB4A0103841ED6E33C9191B264BF538155B7ADAEE71E899235DC1122F426";
  464 + // let userid= "17706006510007934913359242990000";
  465 + let userid= "17502321750004978169421209637000";
  466 + let usertype= "sysadmin";
  467 + // let usertype= "General";
  468 + let authorization="1EDB99C9BF070115F7A57AC43D8CB09F0B8C49F979DAB63A2AEA84B372B2B42BF3419238942A93E9AD666629E18D159AF7FE144A6407DE745BA0AEC8B235FC1D2D86C92E4DCE571A8ECF0767494BBDE2495FD8E662F2065F9430347C7E4472B5538155B7ADAEE71E899235DC1122F426";
  469 + //"1EDB99C9BF070115F7A57AC43D8CB09F0B8C49F979DAB63A2AEA84B372B2B42BF3419238942A93E9AD666629E18D159AF7FE144A6407DE745BA0AEC8B235FC1DC16A7526DEC4395CF09285C2BD330B9FD8668502224FF2D5675E74B8CDD2ABFB538155B7ADAEE71E899235DC1122F426";
470 470 let hrefLock = window.location.origin+"/xlyAi";
471 471 // ==================== 配置部分 ====================
472 472 const CONFIG = {
... ...