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