From d1b6a13a58afa4e03f4d6cb0a62cd759ccf306f4 Mon Sep 17 00:00:00 2001
From: ageerle <ageerle@163.com>
Date: 星期二, 04 三月 2025 10:06:00 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/main'

---
 ruoyi-modules/ruoyi-system/src/main/java/org/ruoyi/system/service/impl/SseServiceImpl.java |  249 ++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 180 insertions(+), 69 deletions(-)

diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/ruoyi/system/service/impl/SseServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/ruoyi/system/service/impl/SseServiceImpl.java
index 610b025..7ada900 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/org/ruoyi/system/service/impl/SseServiceImpl.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/org/ruoyi/system/service/impl/SseServiceImpl.java
@@ -3,6 +3,16 @@
 import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.collection.CollectionUtil;
 import com.alibaba.fastjson.JSONObject;
+import com.azure.ai.openai.OpenAIClient;
+import com.azure.ai.openai.OpenAIClientBuilder;
+import com.azure.ai.openai.models.*;
+import com.azure.core.credential.AzureKeyCredential;
+import io.github.ollama4j.OllamaAPI;
+import io.github.ollama4j.models.chat.OllamaChatMessageRole;
+import io.github.ollama4j.models.chat.OllamaChatRequestBuilder;
+import io.github.ollama4j.models.chat.OllamaChatRequestModel;
+import io.github.ollama4j.models.generate.OllamaStreamHandler;
+import io.github.ollama4j.utils.Options;
 import jakarta.servlet.http.HttpServletRequest;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -12,7 +22,10 @@
 import org.ruoyi.common.chat.domain.request.ChatRequest;
 import org.ruoyi.common.chat.domain.request.Dall3Request;
 import org.ruoyi.common.chat.entity.Tts.TextToSpeech;
-import org.ruoyi.common.chat.entity.chat.*;
+import org.ruoyi.common.chat.entity.chat.ChatCompletion;
+import org.ruoyi.common.chat.entity.chat.ChatCompletionResponse;
+import org.ruoyi.common.chat.entity.chat.Content;
+import org.ruoyi.common.chat.entity.chat.Message;
 import org.ruoyi.common.chat.entity.files.UploadFileResponse;
 import org.ruoyi.common.chat.entity.images.Image;
 import org.ruoyi.common.chat.entity.images.ImageResponse;
@@ -25,18 +38,17 @@
 import org.ruoyi.common.core.exception.base.BaseException;
 import org.ruoyi.common.core.service.ConfigService;
 import org.ruoyi.common.core.utils.StringUtils;
-import org.ruoyi.common.redis.utils.RedisUtils;
 import org.ruoyi.common.satoken.utils.LoginHelper;
 import org.ruoyi.system.domain.bo.ChatMessageBo;
 import org.ruoyi.system.domain.bo.SysModelBo;
-import org.ruoyi.system.domain.bo.SysPackagePlanBo;
+import org.ruoyi.system.domain.request.translation.TranslationRequest;
 import org.ruoyi.system.domain.vo.SysModelVo;
-import org.ruoyi.system.domain.vo.SysPackagePlanVo;
 import org.ruoyi.system.domain.vo.SysUserVo;
 import org.ruoyi.system.listener.SSEEventSourceListener;
 import org.ruoyi.system.service.*;
 import org.springframework.core.io.InputStreamResource;
 import org.springframework.core.io.Resource;
+import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
@@ -50,8 +62,11 @@
 import java.net.URLEncoder;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.util.Arrays;
+import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+import io.github.ollama4j.utils.OptionsBuilder;
 
 @Service
 @Slf4j
@@ -87,12 +102,13 @@
         try {
             if (StpUtil.isLogin()) {
                 SysUserVo sysUserVo = userService.selectUserById(getUserId());
-                if (!checkModel(sysUserVo.getUserPlan(), chatRequest.getModel())) {
-                    throw new BaseException("褰撳墠濂楅涓嶆敮鎸佹妯″瀷!");
-                }
+//                if (!checkModel(sysUserVo.getUserPlan(), chatRequest.getModel())) {
+//                    throw new BaseException("褰撳墠濂楅涓嶆敮鎸佹妯″瀷!");
+//                }
                 LocalCache.CACHE.put("userId", getUserId());
 
-                Object content = messages.get(0).getContent();
+                Object content = messages.get(messages.size() - 1).getContent();
+
                 String chatString = "";
                 if (content instanceof List<?> listContent) {
                     if (!listContent.isEmpty() && listContent.get(0) instanceof Content) {
@@ -144,28 +160,28 @@
                        processByToken(chatRequest.getModel(), chatString, chatMessageBo);
                     }
                 }
-            } else {
-                if (checkModel("Visitor", chatRequest.getModel())) {
-                    // 鍒濆璇锋眰娆℃暟
-                    int number = 1;
-                    // 鑾峰彇璇锋眰IP
-                    String realIp = getClientIpAddress(request);
-                    // 鏍规嵁IP鑾峰彇娆℃暟
-                    Integer requestNumber = RedisUtils.getCacheObject(realIp);
-                    if (requestNumber == null) {
-                        // 璁板綍ip浣跨敤娆℃暟
-                        RedisUtils.setCacheObject(realIp, number);
-                    } else {
-                        String configValue = configService.getConfigValue("mail", "free");
-                        if (requestNumber > Integer.parseInt(configValue)) {
-                            throw new BaseException("鍓╀綑娆℃暟涓嶈冻锛岃鍏呭�煎悗浣跨敤");
-                        }
-                        RedisUtils.setCacheObject(realIp, requestNumber + 1);
-                    }
-                } else {
-                    throw new BaseException("褰撳墠濂楅涓嶆敮鎸佹妯″瀷!");
-                }
             }
+
+//            else {
+//
+//                    // 鍒濆璇锋眰娆℃暟
+//                    int number = 1;
+//                    // 鑾峰彇璇锋眰IP
+//                    String realIp = getClientIpAddress(request);
+//                    // 鏍规嵁IP鑾峰彇娆℃暟
+//                    Integer requestNumber = RedisUtils.getCacheObject(realIp);
+//                    if (requestNumber == null) {
+//                        // 璁板綍ip浣跨敤娆℃暟
+//                        RedisUtils.setCacheObject(realIp, number);
+//                    } else {
+//                        String configValue = configService.getConfigValue("mail", "free");
+//                        if (requestNumber > Integer.parseInt(configValue)) {
+//                            throw new BaseException("鍓╀綑娆℃暟涓嶈冻锛岃鍏呭�煎悗浣跨敤");
+//                        }
+//                        RedisUtils.setCacheObject(realIp, requestNumber + 1);
+//                    }
+//
+//            }
             ChatCompletion completion = ChatCompletion
                 .builder()
                 .messages(messages)
@@ -184,31 +200,31 @@
     }
 
 
-    /**
-     * 鏌ュ綋鍓嶇敤鎴锋槸鍚﹀彲浠ヨ皟鐢ㄦ妯″瀷
-     *
-     * @param planId
-     * @return
-     */
-    public Boolean checkModel(String planId, String modelName) {
-        SysPackagePlanBo sysPackagePlanBo = new SysPackagePlanBo();
-        if (modelName.startsWith("gpt-4-gizmo")) {
-            modelName = "gpt-4-gizmo";
-        }
-        if (StringUtils.isEmpty(planId)) {
-            sysPackagePlanBo.setName("Visitor");
-        } else if ("Visitor".equals(planId) || "Free".equals(planId)) {
-            sysPackagePlanBo.setName(planId);
-        } else {
-            // sysPackagePlanBo.setId(Long.valueOf(planId));
-            return true;
-        }
-
-        SysPackagePlanVo sysPackagePlanVo = sysPackagePlanService.queryList(sysPackagePlanBo).get(0);
-        // 灏嗗瓧绗︿覆杞崲涓烘暟缁�
-        String[] array = sysPackagePlanVo.getPlanDetail().split(",");
-        return Arrays.asList(array).contains(modelName);
-    }
+//    /**
+//     * 鏌ュ綋鍓嶇敤鎴锋槸鍚﹀彲浠ヨ皟鐢ㄦ妯″瀷
+//     *
+//     * @param planId
+//     * @return
+//     */
+//    public Boolean checkModel(String planId, String modelName) {
+//        SysPackagePlanBo sysPackagePlanBo = new SysPackagePlanBo();
+//        if (modelName.startsWith("gpt-4-gizmo")) {
+//            modelName = "gpt-4-gizmo";
+//        }
+//        if (StringUtils.isEmpty(planId)) {
+//            sysPackagePlanBo.setName("Visitor");
+//        } else if ("Visitor".equals(planId) || "Free".equals(planId)) {
+//            sysPackagePlanBo.setName(planId);
+//        } else {
+//            // sysPackagePlanBo.setId(Long.valueOf(planId));
+//            return true;
+//        }
+//
+//        SysPackagePlanVo sysPackagePlanVo = sysPackagePlanService.queryList(sysPackagePlanBo).get(0);
+//        // 灏嗗瓧绗︿覆杞崲涓烘暟缁�
+//        String[] array = sysPackagePlanVo.getPlanDetail().split(",");
+//        return Arrays.asList(array).contains(modelName);
+//    }
 
     /**
      * 鏍规嵁娆℃暟鎵i櫎浣欓
@@ -241,23 +257,21 @@
      */
     @Override
     public ResponseEntity<Resource> textToSpeed(TextToSpeech textToSpeech) {
+        ResponseBody body = openAiStreamClient.textToSpeech(textToSpeech);
+        if (body != null) {
+            // 灏哛esponseBody杞崲涓篒nputStreamResource
+            InputStreamResource resource = new InputStreamResource(body.byteStream());
 
-        try (ResponseBody body = openAiStreamClient.textToSpeech(textToSpeech)) {
-            if (body != null) {
-                // 灏哛esponseBody杞崲涓篒nputStreamResource
-                InputStreamResource resource = new InputStreamResource(body.byteStream());
-
-                // 鍒涘缓骞惰繑鍥濺esponseEntity
-                return ResponseEntity.ok()
-                    .contentType(MediaType.parseMediaType("audio/mpeg"))
-                    .body(resource);
-
-            } else {
-                // 濡傛灉ResponseBody涓虹┖锛岃繑鍥�404鐘舵�佺爜
-                return ResponseEntity.notFound().build();
-            }
+            // 鍒涘缓骞惰繑鍥濺esponseEntity
+            return ResponseEntity.ok()
+                .contentType(MediaType.parseMediaType("audio/mpeg"))
+                .body(resource);
+        } else {
+            // 濡傛灉ResponseBody涓虹┖锛岃繑鍥�404鐘舵�佺爜
+            return ResponseEntity.notFound().build();
         }
     }
+
 
     /**
      * 璇煶杞枃瀛�
@@ -309,6 +323,7 @@
      * @param request
      * @return
      */
+    @Override
     public List<Item> dall3(Dall3Request request) {
         openAiStreamClient = chatConfig.getOpenAiStreamClient();
         chatService.checkUserGrade();
@@ -521,4 +536,100 @@
 
         return "unknown";
     }
+
+
+    @Override
+    public String translation(TranslationRequest translationRequest) {
+
+        ChatMessageBo chatMessageBo = new ChatMessageBo();
+        chatMessageBo.setUserId(getUserId());
+        chatMessageBo.setModelName(translationRequest.getModel());
+        chatMessageBo.setContent(translationRequest.getPrompt());
+        chatMessageBo.setDeductCost(0.01);
+        chatMessageBo.setTotalTokens(0);
+        chatMessageService.insertByBo(chatMessageBo);
+
+        openAiStreamClient = chatConfig.getOpenAiStreamClient();
+
+        List<Message> messageList = new ArrayList<>();
+
+        Message sysMessage = Message.builder().role(Message.Role.SYSTEM).content("浣滀负鑻辨眽缈昏瘧锛屾偍鐨勪换鍔℃槸鍑嗙‘鍦板湪涓ょ璇█涔嬮棿缈昏瘧鏂囨湰銆傜炕璇戞椂锛岃娉ㄦ剰涓婁笅鏂囷紝鍑嗙‘瑙i噴鎴愯鍜岃皻璇�傚鏋滆繛缁敹鍒板涓嫳鏂囧崟璇嶏紝璇烽粯璁ゅ皢鍏剁炕璇戞垚涓枃鍙ュ瓙銆備絾濡傛灉鍓嶉潰鏈�'phrase:鈥欙紝鍒欏簲缈昏瘧涓虹煭璇�;濡傛灉鏈�'norma!:'锛屽垯缈昏瘧涓哄涓棤鍏崇殑鍗曡瘝銆傛偍鐨勭炕璇戝簲鎺ヨ繎姣嶈鑰呯殑姘村钩锛屽苟鑰冭檻鐢ㄦ埛瑕佹眰鐨勭壒瀹氳瑷�椋庢牸鎴栬姘斻�傞伩鍏嶄娇鐢ㄥ啋鐘�ц瘝姹囷紝蹇呰鏃剁敤x鏇挎崲銆傛彁渚涚炕璇戞椂锛岃鐢ㄤ腑鏂囪В閲婃瘡鍙ヨ瘽鐨勬椂鎬併�佷粠鍙ャ�佷富璇�佽皳璇�佸璇�佺壒娈婄煭璇拰璋氳瀵逛簬闇�瑕佺炕璇戠殑鐭鎴栧崟璇嶏紝璇锋彁渚涙潵婧�(璇嶅吀)銆傚鏋滆姹傜炕璇戝涓煭璇紝璇风敤|绗﹀彿鍒嗛殧銆傝璁颁綇:鎮ㄦ槸鑻辨眽缈昏瘧锛屼笉鏄眽姹夌炕璇戞垨鑻辫嫳缈昏瘧銆傛彁浜ゅ墠璇蜂粩缁嗘鏌ュ拰淇绛旀,鍥炲鎺у埗鍦�50瀛椾互鍐�").build();
+        messageList.add(sysMessage);
+        Message message = Message.builder().role(Message.Role.USER).content(translationRequest.getPrompt()).build();
+        messageList.add(message);
+        ChatCompletionResponse chatCompletionResponse = null;
+        try {
+           ChatCompletion chatCompletion = ChatCompletion
+               .builder()
+               .messages(messageList)
+               .model(translationRequest.getModel())
+               .stream(false)
+               .build();
+           chatCompletionResponse = openAiStreamClient.chatCompletion(chatCompletion);
+       }catch (Exception e) {
+           log.error(e.getMessage());
+       }
+
+        return chatCompletionResponse.getChoices().get(0).getMessage().getContent().toString();
+    }
+
+    @Override
+    public SseEmitter ollamaChat(ChatRequest chatRequest) {
+        final SseEmitter emitter = new SseEmitter();
+        String host = "http://localhost:11434/";
+
+        List<Message> msgList = chatRequest.getMessages();
+        Message message = msgList.get(msgList.size() - 1);
+
+        OllamaAPI ollamaAPI = new OllamaAPI(host);
+
+        ollamaAPI.setRequestTimeoutSeconds(100);
+
+        OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance("qwen2.5:7b");
+
+        OllamaChatRequestModel requestModel = builder
+            .withMessage(OllamaChatMessageRole.USER,
+                message.getContent().toString())
+            .build();
+
+
+        // 寮傛鎵ц Ollama API 璋冪敤
+        CompletableFuture.runAsync(() -> {
+            try {
+                StringBuilder response = new StringBuilder();
+                OllamaStreamHandler streamHandler = (s) -> {
+                    String substr = s.substring(response.length());
+                    response.append(substr);
+                    System.out.println(substr);
+                    try {
+                        emitter.send(substr);
+                    } catch (IOException e) {
+                        sendErrorEvent(emitter, e.getMessage());
+                    }
+                };
+                ollamaAPI.chat(requestModel, streamHandler);
+                emitter.complete();
+            } catch (Exception e) {
+                sendErrorEvent(emitter, e.getMessage());
+            }
+        });
+
+
+        return emitter;
+    }
+
+    @Override
+    public String wxCpChat(String prompt) {
+        List<Message> messageList = new ArrayList<>();
+        Message message = Message.builder().role(Message.Role.USER).content(prompt).build();
+        messageList.add(message);
+        ChatCompletion chatCompletion = ChatCompletion
+            .builder()
+            .messages(messageList)
+            .model("gpt-4o-mini")
+            .stream(false)
+            .build();
+        ChatCompletionResponse chatCompletionResponse = openAiStreamClient.chatCompletion(chatCompletion);
+        return chatCompletionResponse.getChoices().get(0).getMessage().getContent().toString();
+    }
 }

--
Gitblit v1.9.3