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 |  262 ++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 183 insertions(+), 79 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 c66f69e..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
@@ -2,8 +2,6 @@
 
 import cn.dev33.satoken.annotation.SaIgnore;
 import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.json.JSONArray;
-import cn.hutool.json.JSONObject;
 import com.agentsflex.core.llm.ChatContext;
 import com.agentsflex.core.llm.Llm;
 import com.agentsflex.core.llm.StreamResponseListener;
@@ -17,32 +15,32 @@
 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.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.jfinal.template.stat.ast.Break;
-import com.mybatisflex.core.paginate.Page;
+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 io.milvus.param.R;
 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.RequestParam;
 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.ai.vo.ModelConfig;
 import tech.aiflowy.common.ai.ChatManager;
 import tech.aiflowy.common.ai.MySseEmitter;
 import tech.aiflowy.common.domain.Result;
@@ -57,14 +55,8 @@
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
 import java.math.BigInteger;
-import java.time.Duration;
 import java.util.*;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.stream.Collectors;
 
 /**
  * 鎺у埗灞傘��
@@ -149,91 +141,139 @@
     @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())){
-            // 浣跨敤Dify妯″瀷鐨勯�昏緫
-            String apiUrl = aiBot.getModelAPI();
-            String bearerToken = aiBot.getModelKey();
+            if (aiBot.getBotTypeId() == 2) {
 
-            // 鏋勫缓璇锋眰JSON
-            JSONObject jsonBody = new JSONObject();
-            jsonBody.put("inputs", new JSONObject());
-            jsonBody.put("query", prompt);
-            jsonBody.put("response_mode", "blocking");
-            jsonBody.put("conversation_id", "");
-            jsonBody.put("user", userId.toString());
+                String apiUrl = aiBot.getModelAPI()+"/workflows/run"; // 鏇挎崲涓哄疄闄匒PI URL
+                String apiKey = aiBot.getModelKEY(); // 鏇挎崲涓哄疄闄匒PI Key
 
-            JSONArray files = new JSONArray();
-            JSONObject fileObj = new JSONObject();
-            fileObj.put("type", "");
-            fileObj.put("transfer_method", "");
-            fileObj.put("url", "");
-            files.put(fileObj);
-            jsonBody.put("files", files);
+                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();
 
-            // 鍙戦�丠TTP璇锋眰
-            HttpClient client = HttpClient.newBuilder()
-                    .connectTimeout(Duration.ofSeconds(30))
-                    .build();
+                // 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" 绛�
 
-            HttpRequest request = HttpRequest.newBuilder()
-                    .uri(URI.create(apiUrl))
-                    .header("Content-Type", "application/json")
-                    .header("Authorization", "Bearer " + bearerToken)
-                    .POST(HttpRequest.BodyPublishers.ofString(jsonBody.toString()))
-                    .build();
+                // 3. 缁勮 inputs 鍙傛暟
+                Map<String, Object> inputs = new HashMap<>();
+                inputs.put("w", fileParam); // 娣诲姞鏂囦欢鍙傛暟锛寁ariableName 濡� "document"
 
-            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
 
-            // 澶勭悊鎴愬姛鍝嶅簲
-            JSONObject responseJson = new JSONObject(response.body());
 
-            // 淇濆瓨鐢ㄦ埛娑堟伅鍒板巻鍙茶褰�
-            ChatHistory userChat = new ChatHistory();
-            userChat.setContent(prompt);
-            userChat.setRole("user");
-            userChat.setUserId(userId);
-            userChat.setBotId(botId.intValue());
-            userChat.setModel("dify");
-            userChat.setChatId(responseJson.optString("conversation_id", ""));
-            Integer userHistoryId = chatHistoryService.saveChatHistory(userChat);
+                AiBotMessageMemory memory = new AiBotMessageMemory(botId, SaTokenUtil.getLoginAccount().getId(),
+                        sessionId, isExternalMsg, aiBotMessageService, aiBotConversationMessageMapper,
+                        aiBotConversationMessageService);
 
-            // 淇濆瓨AI鍥炲鍒板巻鍙茶褰�
-            ChatHistory assistantChat = new ChatHistory();
-            assistantChat.setContent(responseJson.getString("answer"));
-            assistantChat.setRole("assistant");
-            assistantChat.setUserId(userId);
-            assistantChat.setBotId(botId.intValue());
-            assistantChat.setModel("dify");
-            assistantChat.setChatId(userChat.getChatId());
-            Integer assistantHistoryId = chatHistoryService.saveChatHistory(assistantChat);
+                final HistoriesPrompt historiesPrompt = new HistoriesPrompt();
+                if (systemPrompt != null) {
+                    historiesPrompt.setSystemMessage(SystemMessage.of(systemPrompt));
+                }
 
-            // 鏋勫缓鍝嶅簲鏁版嵁
-            int count = chatHistoryService.getChatHistoryCount(userId, botId.intValue());
-            JSONObject result = new JSONObject();
-            result.put("Count", count);
-            result.put("Data", responseJson.getString("answer"));
-            result.put("UserId", userHistoryId);
-            result.put("AssistantId", assistantHistoryId);
+                historiesPrompt.setMemory(memory);
 
-            // 鍙戦�丼SE鍝嶅簲
-            emitter.send(SseEmitter.event()
-                    .name("message")
-                    .data(result.toString()));
-            emitter.complete();
-        }else{
-            Map<String, Object> llmOptions = aiBot.getLlmOptions();
-            String systemPrompt = llmOptions != null ? (String) llmOptions.get("systemPrompt") : null;
+                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) {
@@ -290,6 +330,7 @@
                                 if (response.getMessage() != null) {
                                     String content = response.getMessage().getContent();
                                     if (StringUtil.hasText(content)) {
+                                        System.out.println(response);
                                         emitter.send(JSON.toJSONString(response.getMessage()));
                                     }
                                 }
@@ -315,10 +356,73 @@
                 }
             });
 
+            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);
+    }
+
+
 
     /**
      * 澶栭儴鐢ㄦ埛璋冪敤鏅鸿兘浣撹繘琛屽璇�
@@ -641,4 +745,4 @@
 
 
     }
-}
+}
\ No newline at end of file

--
Gitblit v1.8.0