From efeb0bd6fb60a6216cb3626df204100546466b23 Mon Sep 17 00:00:00 2001 From: ageerle <ageerle@163.com> Date: 星期五, 11 四月 2025 12:05:13 +0800 Subject: [PATCH] fix: ollama兼容联网查询 知识库检索 --- ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/request/ChatRequest.java | 5 + ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/SseServiceImpl.java | 152 ++++++++++++++++++++++++++++++-------------------- ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/openai/OpenAiStreamClient.java | 2 3 files changed, 97 insertions(+), 62 deletions(-) diff --git a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/openai/OpenAiStreamClient.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/openai/OpenAiStreamClient.java index 381e4d7..ef03cb2 100644 --- a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/openai/OpenAiStreamClient.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/openai/OpenAiStreamClient.java @@ -466,8 +466,8 @@ * @since 1.1.3 */ public ResponseBody textToSpeech(TextToSpeech textToSpeech){ - Call<ResponseBody> responseBody = this.openAiApi.textToSpeech(textToSpeech); try { + Call<ResponseBody> responseBody = this.openAiApi.textToSpeech(textToSpeech); return responseBody.execute().body(); } catch (IOException e) { throw new BaseException("鏂囨湰杞闊筹紙鍚屾锛夊け璐�: "+e.getMessage()); diff --git a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/request/ChatRequest.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/request/ChatRequest.java index 4538526..97b8958 100644 --- a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/request/ChatRequest.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/request/ChatRequest.java @@ -27,6 +27,11 @@ private String prompt; /** + * 绯荤粺鎻愮ず璇� + */ + private String sysPrompt; + + /** * 鏄惁寮�鍚祦寮忓璇� */ private Boolean stream = Boolean.TRUE; diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/SseServiceImpl.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/SseServiceImpl.java index 357280d..6cf19b4 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/SseServiceImpl.java +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/SseServiceImpl.java @@ -84,11 +84,9 @@ private final IChatCostService chatCostService; - private static final String requestIdTemplate = "mycompany-%d"; + private static final String requestIdTemplate = "company-%d"; private static final ObjectMapper mapper = new ObjectMapper(); - - private OpenAiStreamClient openAiModelStreamClient; @Override public SseEmitter sseChat(ChatRequest chatRequest, HttpServletRequest request) { @@ -96,65 +94,33 @@ SSEEventSourceListener openAIEventSourceListener = new SSEEventSourceListener(sseEmitter); // 鑾峰彇瀵硅瘽娑堟伅鍒楄〃 List<Message> messages = chatRequest.getMessages(); - // 鐢ㄦ埛瀵硅瘽鍐呭 - String chatString = null; try { - if (StpUtil.isLogin()) { - // 閫氳繃妯″瀷鍚嶇О鏌ヨ妯″瀷淇℃伅 - ChatModelVo chatModelVo = chatModelService.selectModelByName(chatRequest.getModel()); - if(chatModelVo!=null){ - // 閫氳繃妯″瀷淇℃伅鏋勫缓璇锋眰瀹㈡埛绔� - openAiModelStreamClient = chatConfig.createOpenAiStreamClient(chatModelVo.getApiHost(), chatModelVo.getApiKey()); - }else { - // 浣跨敤榛樿瀹㈡埛绔� - openAiModelStreamClient = openAiStreamClient; - } + // 鏌ヨ妯″瀷淇℃伅 + ChatModelVo chatModelVo = chatModelService.selectModelByName(chatRequest.getModel()); + + OpenAiStreamClient openAiModelStreamClient; + if(chatModelVo!=null){ + // 寤鸿姹傚鎴风 + openAiModelStreamClient = chatConfig.createOpenAiStreamClient(chatModelVo.getApiHost(), chatModelVo.getApiKey()); // 璁剧疆榛樿鎻愮ず璇� - Message sysMessage = Message.builder().content(chatModelVo.getSystemPrompt()).role(Message.Role.SYSTEM).build(); - messages.add(0,sysMessage); - - // 鏌ヨ鍚戦噺搴撶浉鍏充俊鎭姞鍏ュ埌涓婁笅鏂� - if(chatRequest.getKid()!=null){ - List<Message> knMessages = new ArrayList<>(); - String content = messages.get(messages.size() - 1).getContent().toString(); - List<String> nearestList; - List<Double> queryVector = embeddingService.getQueryVector(content, chatRequest.getKid()); - nearestList = vectorStore.nearest(queryVector, chatRequest.getKid()); - for (String prompt : nearestList) { - Message userMessage = Message.builder().content(prompt).role(Message.Role.USER).build(); - knMessages.add(userMessage); - } - Message userMessage = Message.builder().content(content + (!nearestList.isEmpty() ? "\n\n娉ㄦ剰锛氬洖绛旈棶棰樻椂锛岄』涓ユ牸鏍规嵁鎴戠粰浣犵殑绯荤粺涓婁笅鏂囧唴瀹瑰師鏂囪繘琛屽洖绛旓紝璇蜂笉瑕佽嚜宸卞彂鎸�,鍥炵瓟鏃朵繚鎸佸師鏉ユ枃鏈殑娈佃惤灞傜骇" : "")).role(Message.Role.USER).build(); - knMessages.add(userMessage); - messages.addAll(knMessages); - } - - // 鑾峰彇鐢ㄦ埛瀵硅瘽淇℃伅 - Object content = messages.get(messages.size() - 1).getContent(); - if (content instanceof List<?> listContent) { - if (CollectionUtil.isNotEmpty(listContent)) { - chatString = listContent.get(0).toString(); - } - } else if (content instanceof String) { - chatString = (String) content; - } - - // 鍔犺浇鑱旂綉淇℃伅 - if(chatRequest.getSearch()){ - Message message = Message.builder().role(Message.Role.ASSISTANT).content("鑱旂綉淇℃伅:"+webSearch(chatString)).build(); - messages.add(message); - } + chatRequest.setSysPrompt(chatModelVo.getSystemPrompt()); }else { - // 鏈櫥褰曠敤鎴烽檺鍒跺璇濇鏁� - String clientIp = IpUtil.getClientIp(request); + // 浣跨敤榛樿瀹㈡埛绔� + openAiModelStreamClient = openAiStreamClient; + } + // 鏋勫缓娑堟伅鍒楄〃澧炲姞鑱旂綉銆佺煡璇嗗簱绛夊唴瀹� + buildChatMessageList(chatRequest); + // 鏍规嵁妯″瀷鍚嶇О鍓嶇紑璋冪敤涓嶅悓鐨勫鐞嗛�昏緫 + switchModelAndHandle(chatRequest); + + // 鏈櫥褰曠敤鎴烽檺鍒跺璇濇鏁� + if (!StpUtil.isLogin()) { + String clientIp = IpUtil.getClientIp(request); // 璁垮姣忓ぉ榛樿鍙兘瀵硅瘽5娆� int timeWindowInSeconds = 5; - String redisKey = "clientIp:" + clientIp; - int count = 0; - if (RedisUtils.getCacheObject(redisKey) == null) { // 缂撳瓨鏈夋晥鏃堕棿1澶� RedisUtils.setCacheObject(redisKey, count, Duration.ofSeconds(86400)); @@ -175,6 +141,7 @@ .stream(chatRequest.getStream()) .build(); openAiModelStreamClient.streamChatCompletion(completion, openAIEventSourceListener); + // 淇濆瓨娑堟伅璁板綍 骞舵墸闄よ垂鐢� chatCostService.deductToken(chatRequest); } catch (Exception e) { @@ -185,6 +152,69 @@ return sseEmitter; } + /** + * 鏍规嵁妯″瀷鍚嶇О鍓嶇紑璋冪敤涓嶅悓鐨勫鐞嗛�昏緫 + */ + private void switchModelAndHandle(ChatRequest chatRequest) { + String model = chatRequest.getModel(); + // 濡傛灉妯″瀷鍚嶇О浠llama寮�澶达紝鍒欒皟鐢╫llama涓儴缃茬殑鏈湴妯″瀷 + if (model.startsWith("ollama-")) { + String[] parts = chatRequest.getModel().split("ollama-", 2); // 闄愬埗鍒嗗壊娆℃暟涓�2 + if (parts.length > 1) { + chatRequest.setModel(parts[1]); + ollamaChat(chatRequest); + } else { + throw new IllegalArgumentException("Invalid ollama model name: " + chatRequest.getModel()); + } + } else if (model.startsWith("gpt-4-gizmo")) { + chatRequest.setModel("gpt-4-gizmo"); + } + } + + /** + * 鏋勫缓娑堟伅鍒楄〃 + */ + private void buildChatMessageList(ChatRequest chatRequest){ + // 鑾峰彇瀵硅瘽娑堟伅鍒楄〃 + List<Message> messages = chatRequest.getMessages(); + // 璁剧疆绯荤粺榛樿鎻愮ず璇� + Message sysMessage = Message.builder().content(chatRequest.getSysPrompt()).role(Message.Role.SYSTEM).build(); + messages.add(0,sysMessage); + + // 鏌ヨ鍚戦噺搴撶浉鍏充俊鎭姞鍏ュ埌涓婁笅鏂� + if(chatRequest.getKid()!=null){ + List<Message> knMessages = new ArrayList<>(); + String content = messages.get(messages.size() - 1).getContent().toString(); + List<String> nearestList; + List<Double> queryVector = embeddingService.getQueryVector(content, chatRequest.getKid()); + nearestList = vectorStore.nearest(queryVector, chatRequest.getKid()); + for (String prompt : nearestList) { + Message userMessage = Message.builder().content(prompt).role(Message.Role.USER).build(); + knMessages.add(userMessage); + } + Message userMessage = Message.builder().content(content + (!nearestList.isEmpty() ? "\n\n娉ㄦ剰锛氬洖绛旈棶棰樻椂锛岄』涓ユ牸鏍规嵁鎴戠粰浣犵殑绯荤粺涓婁笅鏂囧唴瀹瑰師鏂囪繘琛屽洖绛旓紝璇蜂笉瑕佽嚜宸卞彂鎸�,鍥炵瓟鏃朵繚鎸佸師鏉ユ枃鏈殑娈佃惤灞傜骇" : "")).role(Message.Role.USER).build(); + knMessages.add(userMessage); + messages.addAll(knMessages); + } + // 鐢ㄦ埛瀵硅瘽鍐呭 + String chatString = null; + // 鑾峰彇鐢ㄦ埛瀵硅瘽淇℃伅 + Object content = messages.get(messages.size() - 1).getContent(); + if (content instanceof List<?> listContent) { + if (CollectionUtil.isNotEmpty(listContent)) { + chatString = listContent.get(0).toString(); + } + } else if (content instanceof String) { + chatString = (String) content; + } + // 璁剧疆瀵硅瘽淇℃伅 + chatRequest.setPrompt(chatString); + // 鍔犺浇鑱旂綉淇℃伅 + if(chatRequest.getSearch()){ + Message message = Message.builder().role(Message.Role.ASSISTANT).content("鑱旂綉淇℃伅:"+webSearch(chatString)).build(); + messages.add(message); + } + } /** * 鍙戦�丼SE閿欒浜嬩欢鐨勫皝瑁呮柟娉� @@ -295,13 +325,13 @@ @Override public SseEmitter ollamaChat(ChatRequest chatRequest) { - String[] parts = chatRequest.getModel().split("ollama-"); + ChatModelVo chatModelVo = chatModelService.selectModelByName(chatRequest.getModel()); final SseEmitter emitter = new SseEmitter(); String host = chatModelVo.getApiHost(); List<Message> msgList = chatRequest.getMessages(); - List<OllamaChatMessage> messages = new ArrayList<>(); + List<OllamaChatMessage> messages = new ArrayList<>(); for (Message message : msgList) { OllamaChatMessage ollamaChatMessage = new OllamaChatMessage(); ollamaChatMessage.setRole(OllamaChatMessageRole.USER); @@ -310,7 +340,7 @@ } OllamaAPI api = new OllamaAPI(host); api.setRequestTimeoutSeconds(100); - OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(parts[1]); + OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(chatRequest.getModel()); OllamaChatRequestModel requestModel = builder .withMessages(messages) @@ -356,11 +386,11 @@ @Override public String webSearch (String prompt) { - String zhipuValue = configService.getConfigValue("zhipu", "key"); - if(StringUtils.isEmpty(zhipuValue)){ - throw new IllegalStateException("zhipu config value is empty,璇峰湪chat_config涓厤缃畓hipu key淇℃伅"); + String zpValue = configService.getConfigValue("zhipu", "key"); + if(StringUtils.isEmpty(zpValue)){ + throw new IllegalStateException("璇峰湪chat_config涓厤缃櫤璋眐ey淇℃伅"); }else { - ClientV4 client = new ClientV4.Builder(zhipuValue) + ClientV4 client = new ClientV4.Builder(zpValue) .networkConfig(300, 100, 100, 100, TimeUnit.SECONDS) .connectionPool(new okhttp3.ConnectionPool(8, 1, TimeUnit.SECONDS)) .build(); -- Gitblit v1.9.3