From 38cc822b35c666ea38d7b0c780706318f05c47db Mon Sep 17 00:00:00 2001 From: qianbao Date: Fri, 24 Apr 2026 10:30:30 +0800 Subject: [PATCH] 添加未清选择 改成动态引导语 --- src/main/java/com/xly/entity/UserSceneSession.java | 11 ++++++++++- src/main/java/com/xly/tool/DynamicToolProvider.java | 21 +++++++++++++++++---- src/main/java/com/xly/tts/service/PythonTtsProxyService.java | 11 +++++++++++ src/main/resources/templates/chat.html | 2 +- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/xly/entity/UserSceneSession.java b/src/main/java/com/xly/entity/UserSceneSession.java index 4e1ebfd..4b2c46f 100644 --- a/src/main/java/com/xly/entity/UserSceneSession.java +++ b/src/main/java/com/xly/entity/UserSceneSession.java @@ -6,6 +6,7 @@ import lombok.Data; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; @@ -101,6 +102,15 @@ public class UserSceneSession { **/ private String sCopyToSrcId; + /*** + * @Author 钱豹 + * @Date 10:03 2026/4/24 + * @Param + * @return + * @Description 工具是否已执行 + **/ + private Boolean toolExecuted=false; + /** * 构建场景选择提示语:展示权限内场景,引导用户选择 * @return 自然语言提示语 @@ -181,5 +191,4 @@ public class UserSceneSession { return false; } - } \ No newline at end of file diff --git a/src/main/java/com/xly/tool/DynamicToolProvider.java b/src/main/java/com/xly/tool/DynamicToolProvider.java index a19355e..ae75673 100644 --- a/src/main/java/com/xly/tool/DynamicToolProvider.java +++ b/src/main/java/com/xly/tool/DynamicToolProvider.java @@ -198,6 +198,11 @@ public class DynamicToolProvider implements ToolProvider { Map executors = new HashMap<>(); // 获取Session UserSceneSession session = UserSceneSessionService.USER_SCENE_SESSION_CACHE.get(sUserId); + // 工具已执行,不再提供任何工具 + if (session != null && session.getToolExecuted()) { + log.info("工具已执行完成,清空可用工具列表"); + return ToolProviderResult.builder().build(); + } // 过滤对应的权限方法 List datalist = new ArrayList<>(); @@ -255,9 +260,9 @@ public class DynamicToolProvider implements ToolProvider { // ====================== 【超级强制:必须调用工具】 ====================== String forceToolPrompt = """ 【重要·强制指令】 - 1. 这是当前唯一可用工具,必须调用,禁止直接回答 - 2. 用户输入包含:确认、全部确认、合并确认、行号(第1行/第一行等) - 3. 必须调用本工具,必须调用,必须调用! + 1. 这是当前唯一可用工具,必须调用,禁止直接回答 + 2. 用户输入包含:确认、全部确认、合并确认、行号(第1行/第一行等) + 3. 必须调用本工具,必须调用,并且只调用一次,不要重复调用! """; stoolDesc.append(forceToolPrompt); // ======================================================================== @@ -530,7 +535,13 @@ public class DynamicToolProvider implements ToolProvider { UserSceneSession session = UserSceneSessionService.USER_SCENE_SESSION_CACHE.get(memoryId.toString()); session.setCurrentTool(meta); // 标记当前工具 - + // 防止重复执行 + if (session.getToolExecuted()) { + log.warn("工具已执行过,拒绝重复调用: {}", meta.getSMethodNo()); + return String.valueOf(successResult(toolExecutionRequest, "{\"status\":\"already_executed\"}")); + } + //标记执行了(所有工具方法只执行一次) + session.setToolExecuted(true); // 1. 解析参数 Map argsNew; try { @@ -1096,6 +1107,8 @@ public class DynamicToolProvider implements ToolProvider { sBody.put("pageSize",10000); log.info("doGetFromData========================"); List> list = new ArrayList<>(); + //移除确认标识 + args.remove("operateType"); if(ObjectUtil.isNotEmpty(args)){ List paramDefs = meta.getParamRuleList(); args.forEach((k,v)->{ diff --git a/src/main/java/com/xly/tts/service/PythonTtsProxyService.java b/src/main/java/com/xly/tts/service/PythonTtsProxyService.java index 3cee0a5..a1cbe48 100644 --- a/src/main/java/com/xly/tts/service/PythonTtsProxyService.java +++ b/src/main/java/com/xly/tts/service/PythonTtsProxyService.java @@ -6,6 +6,7 @@ import com.xly.constant.BusinessCode; import com.xly.constant.ReturnTypeCode; import com.xly.entity.AiResponseAccumulator; import com.xly.entity.AiResponseDTO; +import com.xly.entity.UserSceneSession; import com.xly.service.UserSceneSessionService; import com.xly.service.XlyErpService; import com.xly.tts.bean.*; @@ -117,10 +118,20 @@ public class PythonTtsProxyService { String sSubsidiaryId = request.getSubsidiaryid(); String sUserType = request.getUsertype(); String authorization = request.getAuthorization(); + cleanupAfterExecution(sUserId); AiResponseDTO voiceText = xlyErpService.erpUserInput(userInput, sUserId, sUserName, sBrandsId, sSubsidiaryId, sUserType, authorization); return synthesizeStreamAi(request, voiceText); } + + // 4. 在 AI 回复后清理 session + public void cleanupAfterExecution(String memoryId) { + UserSceneSession session = UserSceneSessionService.USER_SCENE_SESSION_CACHE.get(memoryId); + if (session != null) { + session.setToolExecuted(false); // 重置状态 + } + } + /** * 流式ERP + 流式TTS合成 */ diff --git a/src/main/resources/templates/chat.html b/src/main/resources/templates/chat.html index 9037f10..38789c1 100644 --- a/src/main/resources/templates/chat.html +++ b/src/main/resources/templates/chat.html @@ -466,7 +466,7 @@ let brandsid= "1111111111"; let subsidiaryid= "1111111111"; let usertype= "sysadmin"; - let authorization="CE444885A9BCFDDE1FD793F8A0931301E9D7DE6CEDD9DE4B83ECE2219C7829A8F3419238942A93E9AD666629E18D159A8BB22EBE26EF12CD9A1EEDB89DC6FB3386549BD9F3EBBD954D17D31CED5EED2E9C9A98822AD3F0E3100F8DBBB5963377538155B7ADAEE71E899235DC1122F426"; + let authorization="CE444885A9BCFDDE1FD793F8A0931301E9D7DE6CEDD9DE4B83ECE2219C7829A8F3419238942A93E9AD666629E18D159A8BB22EBE26EF12CD9A1EEDB89DC6FB33178153C379FB82F53B4B689DA1BE7060687D4EF8281542FFC87C4EB776974C6A538155B7ADAEE71E899235DC1122F426"; let hrefLock = window.location.origin+"/xlyAi"; const CONFIG = { -- libgit2 0.22.2