From 3732bde983f34f5cb729ac1724b9795fb97d8941 Mon Sep 17 00:00:00 2001
From: admin <cgf12138@163.com>
Date: 星期六, 07 六月 2025 18:12:05 +0800
Subject: [PATCH] 0606

---
 aiflowy-modules/aiflowy-module-ai/src/main/java/tech/aiflowy/ai/controller/AiBotController.java |  693 +++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 596 insertions(+), 97 deletions(-)

diff --git a/aiflowy-modules/aiflowy-module-ai/src/main/java/tech/aiflowy/ai/controller/AiBotController.java b/aiflowy-modules/aiflowy-module-ai/src/main/java/tech/aiflowy/ai/controller/AiBotController.java
index 72c236a..d5543f2 100644
--- a/aiflowy-modules/aiflowy-module-ai/src/main/java/tech/aiflowy/ai/controller/AiBotController.java
+++ b/aiflowy-modules/aiflowy-module-ai/src/main/java/tech/aiflowy/ai/controller/AiBotController.java
@@ -1,14 +1,6 @@
 package tech.aiflowy.ai.controller;
 
-import tech.aiflowy.ai.entity.*;
-import tech.aiflowy.ai.service.*;
-import tech.aiflowy.common.ai.ChatManager;
-import tech.aiflowy.common.ai.MySseEmitter;
-import tech.aiflowy.common.domain.Result;
-import tech.aiflowy.common.util.StringUtil;
-import tech.aiflowy.common.web.controller.BaseCurdController;
-import tech.aiflowy.common.web.jsonbody.JsonBody;
-import tech.aiflowy.common.satoken.util.SaTokenUtil;
+import cn.dev33.satoken.annotation.SaIgnore;
 import cn.hutool.core.util.ObjectUtil;
 import com.agentsflex.core.llm.ChatContext;
 import com.agentsflex.core.llm.Llm;
@@ -16,25 +8,55 @@
 import com.agentsflex.core.llm.functions.Function;
 import com.agentsflex.core.llm.response.AiMessageResponse;
 import com.agentsflex.core.llm.response.FunctionCaller;
+import com.agentsflex.core.message.AiMessage;
 import com.agentsflex.core.message.HumanMessage;
 import com.agentsflex.core.message.SystemMessage;
 import com.agentsflex.core.prompt.HistoriesPrompt;
+import com.agentsflex.core.prompt.ToolPrompt;
 import com.agentsflex.core.util.CollectionUtil;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.serializer.SerializeConfig;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonObject;
 import com.mybatisflex.core.query.QueryWrapper;
+import com.mybatisflex.core.table.TableInfo;
+import com.mybatisflex.core.table.TableInfoFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.*;
 import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.RestTemplate;
 import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
+import tech.aiflowy.ai.config.DifyStreamClient;
+import tech.aiflowy.ai.config.FileReference;
+import tech.aiflowy.ai.entity.*;
+import tech.aiflowy.ai.mapper.AiBotConversationMessageMapper;
+import tech.aiflowy.ai.service.*;
+import tech.aiflowy.common.ai.ChatManager;
+import tech.aiflowy.common.ai.MySseEmitter;
+import tech.aiflowy.common.domain.Result;
+import tech.aiflowy.common.entity.LoginAccount;
+import tech.aiflowy.common.satoken.util.SaTokenUtil;
+import tech.aiflowy.common.util.StringUtil;
+import tech.aiflowy.common.web.controller.BaseCurdController;
+import tech.aiflowy.common.web.jsonbody.JsonBody;
+import tech.aiflowy.system.entity.SysApiKey;
+import tech.aiflowy.system.mapper.SysApiKeyMapper;
 
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.math.BigInteger;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
  * 鎺у埗灞傘��
@@ -50,6 +72,16 @@
     private final AiBotWorkflowService aiBotWorkflowService;
     private final AiBotKnowledgeService aiBotKnowledgeService;
     private final AiBotMessageService aiBotMessageService;
+    @Resource
+    private SysApiKeyMapper aiBotApiKeyMapper;
+    @Resource
+    private AiBotConversationMessageService aiBotConversationMessageService;
+    @Resource
+    private AiBotConversationMessageMapper aiBotConversationMessageMapper;
+
+    private static final Logger logger = LoggerFactory.getLogger(AiBotController.class);
+    @Autowired
+    private RestTemplate restTemplate;
 
     public AiBotController(AiBotService service, AiLlmService aiLlmService, AiBotWorkflowService aiBotWorkflowService, AiBotKnowledgeService aiBotKnowledgeService, AiBotMessageService aiBotMessageService) {
         super(service);
@@ -60,9 +92,9 @@
     }
 
     @Resource
-    private AiPluginsService aiPluginsService;
-    @Resource
     private AiBotPluginsService aiBotPluginsService;
+    @Resource
+    private AiPluginToolService aiPluginToolService;
 
     @PostMapping("updateOptions")
     public Result updateOptions(@JsonBody("id") BigInteger id, @JsonBody("options") Map<String, Object> options) {
@@ -95,124 +127,572 @@
         return Result.success();
     }
 
+    /**
+     * 褰撳墠绯荤粺鐢ㄦ埛璋冪敤瀵硅瘽
+     *
+     * @param prompt
+     * @param botId
+     * @param sessionId
+     * @param isExternalMsg
+     * @param response
+     * @return
+     */
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+
     @PostMapping("chat")
     public SseEmitter chat(@JsonBody(value = "prompt", required = true) String prompt,
                            @JsonBody(value = "botId", required = true) BigInteger botId,
                            @JsonBody(value = "sessionId", required = true) String sessionId,
+                           @JsonBody(value = "isExternalMsg") int isExternalMsg,
+                           @JsonBody(value = "file") String file,
                            HttpServletResponse response) {
         response.setContentType("text/event-stream");
-
         AiBot aiBot = service.getById(botId);
         if (aiBot == null) {
             return ChatManager.getInstance().sseEmitterForContent("鏈哄櫒浜轰笉瀛樺湪");
         }
+        Map<String, Object> llmOptions = aiBot.getLlmOptions();
+        String systemPrompt = llmOptions != null ? (String) llmOptions.get("systemPrompt") : null;
+
+        if (StringUtil.hasText(aiBot.getModelAPI())){
+            if (aiBot.getBotTypeId() == 2) {
+
+                String apiUrl = aiBot.getModelAPI()+"/workflows/run"; // 鏇挎崲涓哄疄闄匒PI URL
+                String apiKey = aiBot.getModelKEY(); // 鏇挎崲涓哄疄闄匒PI Key
+
+                DifyStreamClient client = new DifyStreamClient(apiUrl, apiKey, aiBotMessageService);
+                DifyStreamClient uploadClient = new DifyStreamClient(aiBot.getModelAPI()+"/files/upload", apiKey, aiBotMessageService);
+                String test = uploadClient.fileUpload(SaTokenUtil.getLoginAccount().getId() + "", file);
+                System.out.println(test);
+                Gson gson = new GsonBuilder().setPrettyPrinting().create();
+                JsonObject fileJson = gson.fromJson(test, JsonObject.class);
+                String fileId = fileJson.get("id").getAsString();
+
+                // 2. 鏋勫缓鏂囦欢鍙傛暟瀵硅薄
+                Map<String, Object> fileParam = new HashMap<>();
+                fileParam.put("transfer_method", "local_file");
+                fileParam.put("upload_file_id", fileId);
+                String[] split = file.split("\\.");
+//                fileParam.put("type", fileJson.get("extension").getAsString()); // 渚嬪 "excel"銆�"pdf" 绛�
+                fileParam.put("type", "document"); // 渚嬪 "excel"銆�"pdf" 绛�
+
+                // 3. 缁勮 inputs 鍙傛暟
+                Map<String, Object> inputs = new HashMap<>();
+                inputs.put("w", fileParam); // 娣诲姞鏂囦欢鍙傛暟锛寁ariableName 濡� "document"
+
+
+
+                AiBotMessageMemory memory = new AiBotMessageMemory(botId, SaTokenUtil.getLoginAccount().getId(),
+                        sessionId, isExternalMsg, aiBotMessageService, aiBotConversationMessageMapper,
+                        aiBotConversationMessageService);
+
+                final HistoriesPrompt historiesPrompt = new HistoriesPrompt();
+                if (systemPrompt != null) {
+                    historiesPrompt.setSystemMessage(SystemMessage.of(systemPrompt));
+                }
+
+                historiesPrompt.setMemory(memory);
+
+                HumanMessage humanMessage = new HumanMessage(prompt);
+
+                // 娣诲姞鎻掍欢鐩稿叧鐨刦unction calling
+                appendPluginToolFunction(botId, humanMessage);
+
+                //娣诲姞宸ヤ綔娴佺浉鍏崇殑 Function Calling
+                appendWorkflowFunctions(botId, humanMessage);
+
+                //娣诲姞鐭ヨ瘑搴撶浉鍏崇殑 Function Calling
+                appendKnowledgeFunctions(botId, humanMessage);
+
+                historiesPrompt.addMessage(humanMessage);
+
+
+                final Boolean[] needClose = {true};
+
+                ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+
+
+                MySseEmitter emitter = new MySseEmitter(1000L * 60 * 2); // 2鍒嗛挓瓒呮椂
+
+                try {
+                    String userId = SaTokenUtil.getLoginAccount().getId() + "";
+                    client.runWorkflow(inputs, prompt, userId, emitter, sessionId, botId);
+                } catch (Exception e) {
+                    emitter.completeWithError(e);
+                }
+//                System.out.println(emitter.toString());
+
+                return emitter;
+            }
+            aiBot.setModelAPI(aiBot.getModelAPI()+"/chat-messages");
+            String apiUrl = aiBot.getModelAPI(); // 鏇挎崲涓哄疄闄匒PI URL
+            String apiKey = aiBot.getModelKEY(); // 鏇挎崲涓哄疄闄匒PI Key
+
+            DifyStreamClient client = new DifyStreamClient(apiUrl, apiKey, aiBotMessageService);
+            AiBotMessageMemory memory = new AiBotMessageMemory(botId, SaTokenUtil.getLoginAccount().getId(),
+                    sessionId, isExternalMsg, aiBotMessageService, aiBotConversationMessageMapper,
+                    aiBotConversationMessageService);
+
+            final HistoriesPrompt historiesPrompt = new HistoriesPrompt();
+            if (systemPrompt != null) {
+                historiesPrompt.setSystemMessage(SystemMessage.of(systemPrompt));
+            }
+
+            historiesPrompt.setMemory(memory);
+
+            HumanMessage humanMessage = new HumanMessage(prompt);
+
+            // 娣诲姞鎻掍欢鐩稿叧鐨刦unction calling
+            appendPluginToolFunction(botId, humanMessage);
+
+            //娣诲姞宸ヤ綔娴佺浉鍏崇殑 Function Calling
+            appendWorkflowFunctions(botId, humanMessage);
+
+            //娣诲姞鐭ヨ瘑搴撶浉鍏崇殑 Function Calling
+            appendKnowledgeFunctions(botId, humanMessage);
+
+            historiesPrompt.addMessage(humanMessage);
+
+
+            final Boolean[] needClose = {true};
+
+            ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+
+
+            MySseEmitter emitter = new MySseEmitter(1000L * 60 * 2); // 2鍒嗛挓瓒呮椂
+
+            try {
+                String userId = SaTokenUtil.getLoginAccount().getId() + "";
+                client.chatStream(prompt, userId, emitter, sessionId, botId);
+            } catch (Exception e) {
+                emitter.completeWithError(e);
+            }
+            System.out.println(emitter.toString());
+            return emitter;
+        }
+        else{
+            AiLlm aiLlm = aiLlmService.getById(aiBot.getLlmId());
+
+            if (aiLlm == null) {
+                return ChatManager.getInstance().sseEmitterForContent("LLM涓嶅瓨鍦�");
+            }
+
+            Llm llm = aiLlm.toLlm();
+            if (llm == null) {
+                return ChatManager.getInstance().sseEmitterForContent("LLM鑾峰彇涓虹┖");
+            }
+
+            AiBotMessageMemory memory = new AiBotMessageMemory(botId, SaTokenUtil.getLoginAccount().getId(),
+                    sessionId, isExternalMsg, aiBotMessageService, aiBotConversationMessageMapper,
+                    aiBotConversationMessageService);
+
+            final HistoriesPrompt historiesPrompt = new HistoriesPrompt();
+            if (systemPrompt != null) {
+                historiesPrompt.setSystemMessage(SystemMessage.of(systemPrompt));
+            }
+
+            historiesPrompt.setMemory(memory);
+
+            HumanMessage humanMessage = new HumanMessage(prompt);
+
+            // 娣诲姞鎻掍欢鐩稿叧鐨刦unction calling
+            appendPluginToolFunction(botId, humanMessage);
+
+            //娣诲姞宸ヤ綔娴佺浉鍏崇殑 Function Calling
+            appendWorkflowFunctions(botId, humanMessage);
+
+            //娣诲姞鐭ヨ瘑搴撶浉鍏崇殑 Function Calling
+            appendKnowledgeFunctions(botId, humanMessage);
+
+            historiesPrompt.addMessage(humanMessage);
+
+            MySseEmitter emitter = new MySseEmitter((long) (1000 * 60 * 2));
+
+            final Boolean[] needClose = {true};
+
+            ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+            // 缁熶竴浣跨敤娴佸紡澶勭悊锛屾棤璁烘槸鍚︽湁 Function Calling
+            llm.chatStream(historiesPrompt, new StreamResponseListener() {
+                @Override
+                public void onMessage(ChatContext context, AiMessageResponse response) {
+                    try {
+                        RequestContextHolder.setRequestAttributes(sra, true);
+                        if (response != null) {
+                            // 妫�鏌ユ槸鍚﹂渶瑕佽Е鍙� Function Calling
+                            if (response.getFunctionCallers() != null && CollectionUtil.hasItems(response.getFunctionCallers())) {
+                                needClose[0] = false;
+                                function_call(response, emitter, needClose, historiesPrompt, llm, prompt, false);
+                            } else {
+                                // 寮哄埗娴佸紡杩斿洖锛屽嵆浣挎湁 Function Calling 涔熷厛杩斿洖閮ㄥ垎缁撴灉
+                                if (response.getMessage() != null) {
+                                    String content = response.getMessage().getContent();
+                                    if (StringUtil.hasText(content)) {
+                                        System.out.println(response);
+                                        emitter.send(JSON.toJSONString(response.getMessage()));
+                                    }
+                                }
+                            }
+                        }
+
+
+                    } catch (Exception e) {
+                        emitter.completeWithError(e);
+                    }
+                }
+
+                @Override
+                public void onStop(ChatContext context) {
+                    if (needClose[0]) {
+                        emitter.complete();
+                    }
+                }
+
+                @Override
+                public void onFailure(ChatContext context, Throwable throwable) {
+                    emitter.completeWithError(throwable);
+                }
+            });
+
+            System.out.println(emitter.toString());
+            return emitter;
+        }
+
+    }
+
+    @PostMapping("files/upload")
+    public Result filesUpload(@JsonBody(value = "botId", required = true) BigInteger botId,
+                           String file,
+                           HttpServletResponse response){
+        try{
+            String userId = SaTokenUtil.getLoginAccount().getId() + "";
+            response.setContentType("text/event-stream");
+            AiBot aiBot = service.getById(botId);
+            aiBot.setModelAPI(aiBot.getModelAPI()+"/files/upload");
+            String apiUrl = aiBot.getModelAPI(); // 鏇挎崲涓哄疄闄匒PI URL
+            String apiKey = aiBot.getModelKEY(); // 鏇挎崲涓哄疄闄匒PI Key
+            DifyStreamClient client = new DifyStreamClient(apiUrl, apiKey, aiBotMessageService);
+            client.fileUpload(userId,file);
+            return Result.success("鎴愬姛锛�");
+        }catch (Exception e){
+            return Result.fail(400, String.valueOf(e));
+        }
+    }
+
+
+
+    public Result save(@RequestBody String jsonStr) {
+        // 瑙f瀽JSON
+        JSONObject json = JSONObject.parseObject(jsonStr);
+
+        // 鍚堝苟鎵�鏈塻econdMenuId*瀛楁
+        List<Integer> menuIds = new ArrayList<>();
+        for (String key : json.keySet()) {
+            if (key.startsWith("secondMenuId")) {
+                Object value = json.get(key);
+                if (value instanceof Integer) {
+                    menuIds.add((Integer) value);
+                }
+            }
+        }
+
+        // 淇濈暀绗竴涓狪D锛堟牴鎹渶瑕佽皟鏁达級
+        if (!menuIds.isEmpty()) {
+            json.put("secondMenuId", menuIds.get(0));
+        }
+
+        // 杞崲涓哄疄浣撶被
+        AiBot entity = json.toJavaObject(AiBot.class);
+
+        // 鍚庣画澶勭悊淇濇寔涓嶅彉
+        Result result = onSaveOrUpdateBefore(entity, true);
+        if (result != null) return result;
+
+        if (entity == null) {
+            throw new NullPointerException("entity is null");
+        }
+        LoginAccount loginAccount = SaTokenUtil.getLoginAccount();
+        commonFiled(entity,loginAccount.getId(),loginAccount.getTenantId(),loginAccount.getDeptId());
+        boolean success = service.save(entity);
+        onSaveOrUpdateAfter(entity, true);
+        TableInfo tableInfo = TableInfoFactory.ofEntityClass(entity.getClass());
+        Object[] pkArgs = tableInfo.buildPkSqlArgs(entity);
+        return Result.create(success).set("id", pkArgs);
+    }
+
+
+
+    /**
+     * 澶栭儴鐢ㄦ埛璋冪敤鏅鸿兘浣撹繘琛屽璇�
+     * 闇�瑕佺敤鎴蜂紶 apiKey 瀵圭敤鎴疯繘琛岃韩浠介獙璇�
+     *
+     * @param stream [true: 杩斿洖sse false锛� 杩斿洖json
+     * @return
+     */
+    @SaIgnore
+    @PostMapping("externalChat")
+    public Object externalChat(
+            @JsonBody(value = "messages", required = true) List<AiBotMessage> messages,
+            @JsonBody(value = "botId", required = true) BigInteger botId,
+            @JsonBody(value = "stream", required = false) boolean stream,
+            HttpServletResponse response,
+            HttpServletRequest request
+    ) {
+        // 璁剧疆鍝嶅簲绫诲瀷
+        if (stream) {
+            response.setContentType("text/event-stream");
+        } else {
+            response.setContentType("application/json");
+        }
+
+        // 鑾峰彇 API Key 鍜� Bot 淇℃伅
+        String apiKey = request.getHeader("Authorization");
+        QueryWrapper queryWrapper = QueryWrapper.create()
+                .select("api_key", "status", "expired_at")
+                .from("tb_sys_api_key")
+                .where("api_key = ? ", apiKey);
+        SysApiKey aiBotApiKey = aiBotApiKeyMapper.selectOneByQuery(queryWrapper);
+        if (aiBotApiKey == null) {
+            return createResponse(stream, JSON.toJSONString(errorRespnseMsg(1, "璇piKey涓嶅瓨鍦�")));
+        }
+        if (aiBotApiKey.getStatus() == 0) {
+            return createResponse(stream, JSON.toJSONString(errorRespnseMsg(2, "璇piKey鏈惎鐢�")));
+        }
+
+        if (aiBotApiKey.getExpiredAt().getTime() < new Date().getTime()) {
+            return createResponse(stream, JSON.toJSONString(errorRespnseMsg(3, "璇piKey宸插け鏁�")));
+
+        }
+
+        AiBot aiBot = service.getById(botId);
+        if (aiBot == null) {
+            return createResponse(stream, JSON.toJSONString(errorRespnseMsg(4, "鏈哄櫒浜轰笉瀛樺湪")));
+        }
 
         Map<String, Object> llmOptions = aiBot.getLlmOptions();
+        String systemPrompt = llmOptions != null ? (String) llmOptions.get("systemPrompt") : null;
 
         AiLlm aiLlm = aiLlmService.getById(aiBot.getLlmId());
         if (aiLlm == null) {
-            return ChatManager.getInstance().sseEmitterForContent("LLM涓嶅瓨鍦�");
+            return createResponse(stream, JSON.toJSONString(errorRespnseMsg(5, "LLM涓嶅瓨鍦�")));
         }
 
         Llm llm = aiLlm.toLlm();
+        AiBotExternalMessageMemory messageMemory = new AiBotExternalMessageMemory(messages);
+        HistoriesPrompt historiesPrompt = new HistoriesPrompt();
+        if (systemPrompt != null) {
+            historiesPrompt.setSystemMessage(SystemMessage.of(systemPrompt));
+        }
+        historiesPrompt.setMemory(messageMemory);
 
-        AiBotMessageMemory memory = new AiBotMessageMemory(botId, SaTokenUtil.getLoginAccount().getId(), sessionId, aiBotMessageService);
+        String prompt = messages.get(messages.size() - 1).getContent();
+        HumanMessage humanMessage = new HumanMessage();
 
-        final HistoriesPrompt historiesPrompt = new HistoriesPrompt();
-        historiesPrompt.setSystemMessage(SystemMessage.of((String) llmOptions.get("systemPrompt")));
-        historiesPrompt.setMemory(memory);
-
-        HumanMessage humanMessage = new HumanMessage(prompt);
-
-        // 娣诲姞鎻掍欢鐩稿叧鐨刦unction calling
-        appendPluginFunctions(botId, humanMessage);
-
-        //娣诲姞宸ヤ綔娴佺浉鍏崇殑 Function Calling
+        // 娣诲姞鎻掍欢銆佸伐浣滄祦銆佺煡璇嗗簱鐩稿叧鐨� Function Calling
+        appendPluginToolFunction(botId, humanMessage);
         appendWorkflowFunctions(botId, humanMessage);
-
-        //娣诲姞鐭ヨ瘑搴撶浉鍏崇殑 Function Calling
         appendKnowledgeFunctions(botId, humanMessage);
 
         historiesPrompt.addMessage(humanMessage);
 
-        MySseEmitter emitter = new MySseEmitter((long) (1000 * 60 * 2));
+        // 鏍规嵁 responseType 杩斿洖涓嶅悓鐨勫搷搴�
+        if (stream) {
+            MySseEmitter emitter = new MySseEmitter((long) (1000 * 60 * 2));
+            final Boolean[] needClose = {true};
 
-        final Boolean[] needClose = {true};
-
-        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
-
-        llm.chatStream(historiesPrompt, new StreamResponseListener() {
-            @Override
-            public void onMessage(ChatContext context, AiMessageResponse response) {
+            if (humanMessage.getFunctions() != null && !humanMessage.getFunctions().isEmpty()) {
                 try {
-                    RequestContextHolder.setRequestAttributes(sra, true);
-                    String content = response.getMessage().getContent();
-                    Object messageContent = response.getMessage();
-                    if (StringUtil.hasText(content)) {
-                        String jsonResult = JSON.toJSONString(messageContent);
-                        emitter.send(jsonResult);
-                    }
-                    List<FunctionCaller> functionCallers = response.getFunctionCallers();
-                    if (CollectionUtil.hasItems(functionCallers)) {
-                        needClose[0] = false;
-                        for (FunctionCaller functionCaller : functionCallers) {
-                            Object result = functionCaller.call();
-                            if (ObjectUtil.isNotEmpty(result)) {
-
-                                String newPrompt = "璇锋牴鎹互涓嬪唴瀹瑰洖绛旂敤鎴凤紝鍐呭鏄�:\n" + result + "\n 鐢ㄦ埛鐨勯棶棰樻槸锛�" + prompt;
-                                historiesPrompt.addMessageTemporary(new HumanMessage(newPrompt));
-
-                                llm.chatStream(historiesPrompt, new StreamResponseListener() {
-                                    @Override
-                                    public void onMessage(ChatContext context, AiMessageResponse response) {
-                                        needClose[0] = true;
-                                        String content = response.getMessage().getContent();
-                                        Object messageContent = response.getMessage();
-                                        if (StringUtil.hasText(content)) {
-                                            String jsonResult = JSON.toJSONString(messageContent);
-                                            emitter.send(jsonResult);
-                                        }
-                                    }
-
-                                    @Override
-                                    public void onStop(ChatContext context) {
-                                        if (needClose[0]) {
-                                            System.out.println("function chat complete");
-                                            emitter.complete();
-                                        }
-                                        historiesPrompt.clearTemporaryMessages();
-                                    }
-
-                                    @Override
-                                    public void onFailure(ChatContext context, Throwable throwable) {
-                                        emitter.completeWithError(throwable);
-                                    }
-                                });
-                            }
-                        }
-                    }
+                    AiMessageResponse aiMessageResponse = llm.chat(historiesPrompt);
+                    function_call(aiMessageResponse, emitter, needClose, historiesPrompt, llm, prompt, true);
                 } catch (Exception e) {
                     emitter.completeWithError(e);
+                }
+
+                if (needClose[0]) {
+                    System.out.println("function chat complete");
+                    emitter.complete();
+                }
+            } else {
+                llm.chatStream(historiesPrompt, new StreamResponseListener() {
+                    @Override
+                    public void onMessage(ChatContext context, AiMessageResponse response) {
+                        try {
+                            function_call(response, emitter, needClose, historiesPrompt, llm, prompt, true);
+                        } catch (Exception e) {
+                            emitter.completeWithError(e);
+                        }
+                    }
+
+                    @Override
+                    public void onStop(ChatContext context) {
+
+                        if (needClose[0]) {
+                            System.out.println("normal chat complete");
+                            emitter.complete();
+                        }
+                    }
+
+                    @Override
+                    public void onFailure(ChatContext context, Throwable throwable) {
+                        emitter.completeWithError(throwable);
+                    }
+                });
+            }
+
+            return emitter;
+        } else {
+            AiMessageResponse resultFunctionCall;
+            if (humanMessage.getFunctions() != null && !humanMessage.getFunctions().isEmpty()) {
+                try {
+                    AiMessageResponse aiMessageResponse = llm.chat(historiesPrompt);
+                    resultFunctionCall = jsonResultJsonFunctionCall(aiMessageResponse, historiesPrompt, llm, prompt);
+                    return JSON.toJSONString(resultFunctionCall.getMessage(), new SerializeConfig());
+                } catch (Exception e) {
+                    return createErrorResponse(e);
+                }
+            } else {
+                AiMessageResponse messageResponse = llm.chat(historiesPrompt);
+                resultFunctionCall = jsonResultJsonFunctionCall(messageResponse, historiesPrompt, llm, prompt);
+                AiBotExternalMsgJsonResult result = handleMessageResult(resultFunctionCall.getMessage());
+                return JSON.toJSONString(result, new SerializeConfig());
+            }
+        }
+    }
+
+    private AiBotExternalMsgJsonResult handleMessageResult(AiMessage aiMessage) {
+        AiBotExternalMsgJsonResult messageResult = new AiBotExternalMsgJsonResult();
+        messageResult.setCreated(new Date().getTime());
+        AiBotExternalMsgJsonResult.Usage usage = new AiBotExternalMsgJsonResult.Usage();
+        if (aiMessage.getTotalTokens() != null){
+            usage.setTotalTokens(aiMessage.getTotalTokens());
+        }
+        if (aiMessage.getCompletionTokens() != null){
+            usage.setCompletionTokens(aiMessage.getCompletionTokens());
+        }
+        if (aiMessage.getPromptTokens() != null){
+            usage.setPromptTokens(aiMessage.getPromptTokens());
+        }
+        messageResult.setUsage(usage);
+        AiBotExternalMsgJsonResult.Choice choice = new AiBotExternalMsgJsonResult.Choice();
+        AiBotExternalMsgJsonResult.Message message = new AiBotExternalMsgJsonResult.Message();
+        message.setContent(aiMessage.getContent());
+        message.setRole("assistant");
+        choice.setMessage(message);
+        messageResult.setChoices(choice);
+        messageResult.setStatus(aiMessage.getStatus().name());
+        return messageResult;
+    }
+
+    // 杈呭姪鏂规硶锛氬垱寤哄搷搴�
+    private Object createResponse(boolean stream, String content) {
+        if (stream) {
+            MySseEmitter emitter = new MySseEmitter((long) (1000 * 60 * 2));
+            emitter.send(content);
+            emitter.complete();
+            return emitter;
+        } else {
+            return ResponseEntity.ok(content);
+        }
+    }
+
+    // 杈呭姪鏂规硶锛氬垱寤洪敊璇搷搴�
+    private Object createErrorResponse(Exception e) {
+        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
+    }
+
+    /**
+     * @param aiMessageResponse 澶фā鍨嬭繑鍥炵殑娑堟伅
+     * @param emitter
+     * @param needClose         鏄惁闇�瑕佸叧闂祦
+     * @param historiesPrompt   娑堟伅鍘嗗彶璁板綍
+     * @param llm               澶фā鍨�
+     * @param prompt            鎻愮ず璇�
+     * @param isExternalChatApi true 澶栭儴绯荤粺璋冪敤bot  false 鍐呴儴绯荤粺璋冪敤bot
+     */
+    private String function_call(AiMessageResponse aiMessageResponse, MySseEmitter emitter, Boolean[] needClose, HistoriesPrompt historiesPrompt, Llm llm, String prompt, boolean isExternalChatApi) {
+        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+        RequestContextHolder.setRequestAttributes(sra, true);
+        String content = aiMessageResponse.getMessage().getContent();
+        Object messageContent = aiMessageResponse.getMessage();
+        if (StringUtil.hasText(content)) {
+            // 濡傛灉鏄閮ㄧ郴缁熻皟鐢╟hat
+            if (isExternalChatApi) {
+                AiBotExternalMsgJsonResult result = handleMessageStreamJsonResult(aiMessageResponse.getMessage());
+
+                emitter.send(JSON.toJSONString(result, new SerializeConfig()));
+            } else {
+                emitter.send(JSON.toJSONString(messageContent));
+            }
+
+        }
+        System.out.println("function call 鎺ユ敹鍒扮殑鍙傛暟message锛�" + aiMessageResponse);
+        llm.chatStream(ToolPrompt.of(aiMessageResponse), new StreamResponseListener() {
+            @Override
+            public void onMessage(ChatContext context, AiMessageResponse response) {
+                System.out.println("function call <UNK>message<UNK>" + aiMessageResponse);
+                String content = response.getMessage().getContent();
+                if (StringUtil.hasText(content)) {
+                    System.out.println("if content"  + content);
+                    emitter.send(JSON.toJSONString(response.getMessage()));
                 }
             }
 
             @Override
             public void onStop(ChatContext context) {
-                if (needClose[0]) {
-                    System.out.println("normal chat complete");
-                    emitter.complete();
-                }
+                System.out.println("function call complete");
+                emitter.complete();
             }
 
             @Override
             public void onFailure(ChatContext context, Throwable throwable) {
-                emitter.completeWithError(throwable);
+                logger.error("function_call鎶ラ敊:",throwable);
+                AiMessage aiMessage = new AiMessage();
+                aiMessage.setContent("鏈煡璇㈠埌鐩稿叧淇℃伅...");
+                emitter.send(JSON.toJSONString(aiMessage));
+                System.out.println("function call complete with error");
             }
         });
 
-        return emitter;
+        return JSON.toJSONString(messageContent);
     }
 
+    private Map<String, Object> errorRespnseMsg(int errorCode, String message) {
+        HashMap<String, Object> result = new HashMap<>();
+        result.put("error", errorCode);
+        result.put("message", message);
+        return result;
+    }
+
+    private AiBotExternalMsgJsonResult handleMessageStreamJsonResult(AiMessage message) {
+        AiBotExternalMsgJsonResult result = new AiBotExternalMsgJsonResult();
+        AiBotExternalMsgJsonResult.Choice choice = new AiBotExternalMsgJsonResult.Choice();
+        AiBotExternalMsgJsonResult.Delta delta = new AiBotExternalMsgJsonResult.Delta();
+        delta.setRole("assistant");
+        delta.setContent(message.getContent());
+        choice.setDelta(delta);
+        result.setCreated(new Date().getTime());
+        result.setChoices(choice);
+        result.setStatus(message.getStatus().name());
+
+        return result;
+    }
+
+    private AiMessageResponse jsonResultJsonFunctionCall(AiMessageResponse aiMessageResponse, HistoriesPrompt historiesPrompt, Llm llm, String prompt) {
+        List<FunctionCaller> functionCallers = aiMessageResponse.getFunctionCallers();
+        if (CollectionUtil.hasItems(functionCallers)) {
+            for (FunctionCaller functionCaller : functionCallers) {
+                Object result = functionCaller.call();
+                if (ObjectUtil.isNotEmpty(result)) {
+                    String newPrompt = "璇锋牴鎹互涓嬪唴瀹瑰洖绛旂敤鎴凤紝鍐呭鏄�:\n" + result + "\n 鐢ㄦ埛鐨勯棶棰樻槸锛�" + prompt;
+                    historiesPrompt.addMessageTemporary(new HumanMessage(newPrompt));
+                    return llm.chat(historiesPrompt);
+                }
+            }
+        }
+        return aiMessageResponse;
+    }
 
     private void appendWorkflowFunctions(BigInteger botId, HumanMessage humanMessage) {
         QueryWrapper queryWrapper = QueryWrapper.create().eq(AiBotWorkflow::getBotId, botId);
@@ -236,14 +716,33 @@
         }
     }
 
-    private void appendPluginFunctions(BigInteger botId, HumanMessage humanMessage) {
-        QueryWrapper queryWrapper = QueryWrapper.create().eq(AiBotPlugins::getBotId, botId);
-        List<AiBotPlugins> aiBotPlugins = aiBotPluginsService.getMapper().selectListWithRelationsByQuery(queryWrapper);
-        if (cn.hutool.core.collection.CollectionUtil.isNotEmpty(aiBotPlugins)) {
-            for (AiBotPlugins aiBotPlugin : aiBotPlugins) {
-                Function function = aiBotPlugin.getAiPlugins().toFunction();
-                humanMessage.addFunction(function);
-            }
+    //    private void appendPluginFunctions(BigInteger botId, HumanMessage humanMessage) {
+//        QueryWrapper queryWrapper = QueryWrapper.create().eq(AiBotPlugins::getBotId, botId);
+//        List<AiBotPlugins> aiBotPlugins = aiBotPluginsService.getMapper().selectListWithRelationsByQuery(queryWrapper);
+//        if (cn.hutool.core.collection.CollectionUtil.isNotEmpty(aiBotPlugins)) {
+//            for (AiBotPlugins aiBotPlugin : aiBotPlugins) {
+//                Function function = aiBotPlugin.getAiPlugins().toFunction();
+//                humanMessage.addFunction(function);
+//            }
+//        }
+//    }
+    private void appendPluginToolFunction(BigInteger botId, HumanMessage humanMessage) {
+        QueryWrapper queryWrapper = QueryWrapper.create().select("plugin_tool_id").eq(AiBotPlugins::getBotId, botId);
+        List<BigInteger> pluginToolIds = aiBotPluginsService.getMapper().selectListWithRelationsByQueryAs(queryWrapper, BigInteger.class);
+
+        if (pluginToolIds == null || pluginToolIds.isEmpty()) {
+            return;
         }
+
+        QueryWrapper queryTool = QueryWrapper.create()
+                .select("*")
+                .from("tb_ai_plugin_tool")
+                .in("id", pluginToolIds);
+        List<AiPluginTool> aiPluginTools = aiPluginToolService.getMapper().selectListWithRelationsByQuery(queryTool);
+        for (AiPluginTool item : aiPluginTools) {
+            humanMessage.addFunction(item.toFunction());
+        }
+
+
     }
 }
\ No newline at end of file

--
Gitblit v1.8.0