From c02f66636dee27fe7ea29c82b094a4d0b63ec2b1 Mon Sep 17 00:00:00 2001 From: winkey Date: Mon, 7 Apr 2025 11:00:55 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E5=90=91=E9=87=8F=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E9=80=9A=E8=BF=87=E6=A8=A1=E5=9E=8B=E7=AE=A1=E7=90=86=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chain/vectorizer/OpenAiVectorization.java | 16 +++++++++++++++- .../system/service/impl/SysModelServiceImpl.java | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/ruoyi-modules/ruoyi-knowledge/src/main/java/org/ruoyi/knowledge/chain/vectorizer/OpenAiVectorization.java b/ruoyi-modules/ruoyi-knowledge/src/main/java/org/ruoyi/knowledge/chain/vectorizer/OpenAiVectorization.java index f15c4927..bc82dbff 100644 --- a/ruoyi-modules/ruoyi-knowledge/src/main/java/org/ruoyi/knowledge/chain/vectorizer/OpenAiVectorization.java +++ b/ruoyi-modules/ruoyi-knowledge/src/main/java/org/ruoyi/knowledge/chain/vectorizer/OpenAiVectorization.java @@ -11,6 +11,8 @@ import org.ruoyi.common.chat.entity.embeddings.EmbeddingResponse; import org.ruoyi.common.chat.openai.OpenAiStreamClient; import org.ruoyi.knowledge.domain.vo.KnowledgeInfoVo; import org.ruoyi.knowledge.service.IKnowledgeInfoService; +import org.ruoyi.system.domain.SysModel; +import org.ruoyi.system.service.ISysModelService; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; @@ -31,6 +33,9 @@ public class OpenAiVectorization implements Vectorization { @Lazy @Resource private LocalModelsVectorization localModelsVectorization; + @Lazy + @Resource + private ISysModelService sysModelService; @Getter private OpenAiStreamClient openAiStreamClient; @@ -40,9 +45,18 @@ public class OpenAiVectorization implements Vectorization { @Override public List> batchVectorization(List chunkList, String kid) { List> vectorList; - openAiStreamClient = chatConfig.getOpenAiStreamClient(); // 获取知识库信息 KnowledgeInfoVo knowledgeInfoVo = knowledgeInfoService.queryById(Long.valueOf(kid)); + if(knowledgeInfoVo == null){ + log.warn("知识库不存在:请查检ID {}",kid); + vectorList=new ArrayList<>(); + vectorList.add(new ArrayList<>()); + return vectorList; + } + SysModel sysModel = sysModelService.selectModelByName(knowledgeInfoVo.getVectorModel()); + String apiHost= sysModel.getApiHost(); + String apiKey= sysModel.getApiKey(); + openAiStreamClient = chatConfig.createOpenAiStreamClient(apiHost,apiKey); Embedding embedding = buildEmbedding(chunkList, knowledgeInfoVo); EmbeddingResponse embeddings = openAiStreamClient.embeddings(embedding); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/ruoyi/system/service/impl/SysModelServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/ruoyi/system/service/impl/SysModelServiceImpl.java index 9ed3bd1f..d48ac6de 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/ruoyi/system/service/impl/SysModelServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/ruoyi/system/service/impl/SysModelServiceImpl.java @@ -63,6 +63,7 @@ public class SysModelServiceImpl implements ISysModelService { lqw.like(StringUtils.isNotBlank(bo.getModelShow()), SysModel::getModelShow, bo.getModelShow()); lqw.eq(StringUtils.isNotBlank(bo.getModelDescribe()), SysModel::getModelDescribe, bo.getModelDescribe()); lqw.eq(StringUtils.isNotBlank(bo.getModelType()), SysModel::getModelType, bo.getModelType()); + lqw.eq(StringUtils.isNotBlank(bo.getCategory()), SysModel::getCategory, bo.getCategory()); return lqw; } From fab6de1f5c52b541a0ce2a8afd005eb05c9dab4e Mon Sep 17 00:00:00 2001 From: winkey Date: Mon, 7 Apr 2025 15:09:35 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E7=9F=A5=E8=AF=86=E5=BA=93=E5=AF=B9?= =?UTF-8?q?=E8=AF=9D=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ruoyi/controller/KnowledgeController.java | 49 +++++-------------- 1 file changed, 13 insertions(+), 36 deletions(-) diff --git a/ruoyi-admin/src/main/java/org/ruoyi/controller/KnowledgeController.java b/ruoyi-admin/src/main/java/org/ruoyi/controller/KnowledgeController.java index d51b2f5b..1b5b2fa5 100644 --- a/ruoyi-admin/src/main/java/org/ruoyi/controller/KnowledgeController.java +++ b/ruoyi-admin/src/main/java/org/ruoyi/controller/KnowledgeController.java @@ -1,16 +1,14 @@ package org.ruoyi.controller; import cn.dev33.satoken.stp.StpUtil; +import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.RequiredArgsConstructor; -import org.ruoyi.common.chat.config.ChatConfig; import org.ruoyi.common.chat.domain.request.ChatRequest; -import org.ruoyi.common.chat.entity.chat.ChatCompletion; import org.ruoyi.common.chat.entity.chat.Message; -import org.ruoyi.common.chat.openai.OpenAiStreamClient; import org.ruoyi.common.core.domain.R; import org.ruoyi.common.core.validate.AddGroup; import org.ruoyi.common.excel.utils.ExcelUtil; @@ -20,6 +18,7 @@ import org.ruoyi.common.mybatis.core.page.PageQuery; import org.ruoyi.common.mybatis.core.page.TableDataInfo; import org.ruoyi.common.satoken.utils.LoginHelper; import org.ruoyi.common.web.core.BaseController; +import org.ruoyi.knowledge.chain.vectorstore.VectorStore; import org.ruoyi.knowledge.domain.bo.KnowledgeAttachBo; import org.ruoyi.knowledge.domain.bo.KnowledgeFragmentBo; import org.ruoyi.knowledge.domain.bo.KnowledgeInfoBo; @@ -31,11 +30,9 @@ import org.ruoyi.knowledge.service.EmbeddingService; import org.ruoyi.knowledge.service.IKnowledgeAttachService; import org.ruoyi.knowledge.service.IKnowledgeFragmentService; import org.ruoyi.knowledge.service.IKnowledgeInfoService; -import org.ruoyi.system.listener.SSEEventSourceListener; import org.ruoyi.system.service.ISseService; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import org.ruoyi.knowledge.chain.vectorstore.VectorStore; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import java.util.List; @@ -63,47 +60,27 @@ public class KnowledgeController extends BaseController { private final EmbeddingService embeddingService; - private OpenAiStreamClient openAiStreamClient; - - private final ChatConfig chatConfig; - private final ISseService sseService; /** * 知识库对话 */ @PostMapping("/send") - public SseEmitter send(@RequestBody @Valid ChatRequest chatRequest) { - - openAiStreamClient = chatConfig.getOpenAiStreamClient(); - SseEmitter sseEmitter = new SseEmitter(0L); - SSEEventSourceListener openAIEventSourceListener = new SSEEventSourceListener(sseEmitter); + public SseEmitter send(@RequestBody @Valid ChatRequest chatRequest, HttpServletRequest request) { List messages = chatRequest.getMessages(); - String content = messages.get(messages.size() - 1).getContent().toString(); + // 获取知识库信息 + Message message = messages.get(messages.size() - 1); + StringBuilder sb = new StringBuilder(message.getContent().toString()); List nearestList; - List queryVector = embeddingService.getQueryVector(content, chatRequest.getKid()); - nearestList = vectorStore.nearest(queryVector,chatRequest.getKid()); + List queryVector = embeddingService.getQueryVector(message.getContent().toString(), chatRequest.getKid()); + nearestList = vectorStore.nearest(queryVector, chatRequest.getKid()); for (String prompt : nearestList) { - Message sysMessage = Message.builder().content(prompt).role(Message.Role.USER).build(); - messages.add(sysMessage); + sb.append("\n####").append(prompt); } - Message userMessage = Message.builder().content(content + (nearestList.size() > 0 ? "\n\n注意:回答问题时,须严格根据我给你的系统上下文内容原文进行回答,请不要自己发挥,回答时保持原来文本的段落层级" : "") ).role(Message.Role.USER).build(); - messages.add(userMessage); - if (chatRequest.getModel().startsWith("ollama")) { - return sseService.ollamaChat(chatRequest); - } - - ChatCompletion completion = ChatCompletion - .builder() - .messages(messages) - .model(chatRequest.getModel()) - .temperature(chatRequest.getTemperature()) - .topP(chatRequest.getTop_p()) - .stream(true) - .build(); - openAiStreamClient.streamChatCompletion(completion, openAIEventSourceListener); - - return sseEmitter; + sb.append( (nearestList.size() > 0 ? "\n\n注意:回答问题时,须严格根据我给你的系统上下文内容原文进行回答,请不要自己发挥,回答时保持原来文本的段落层级" : "")); + message.setRole(Message.Role.USER.getName()); + message.setContent(sb.toString()); + return sseService.sseChat(chatRequest, request); } /** From c884f4f2d3bffa071b0d9fda1ab1d0ccdad970d0 Mon Sep 17 00:00:00 2001 From: winkey Date: Mon, 7 Apr 2025 15:27:20 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=90=91=E9=87=8F=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E6=8F=92=E5=85=A5=E6=A8=A1=E5=9E=8B=E5=BA=93sql?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- script/sql/update/updatdata20250407.sql | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 script/sql/update/updatdata20250407.sql diff --git a/script/sql/update/updatdata20250407.sql b/script/sql/update/updatdata20250407.sql new file mode 100644 index 00000000..a40a8396 --- /dev/null +++ b/script/sql/update/updatdata20250407.sql @@ -0,0 +1,4 @@ +INSERT INTO `ruoyi-ai`.`chat_model` (`id`, `tenant_id`, `category`, `model_name`, `model_describe`, `model_price`, `model_type`, `model_show`, `system_prompt`, `api_host`, `api_key`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1907575746601119746, '000000', 'vector', 'text-embedding-3-small', 'text-embedding-3-small', 0, '2', '0', NULL, 'https://api.pandarobot.chat/', 'sk-cdBlIaZcufccm2RaDe547cBd054d49C7B0782eCa72A0052b', 103, 1, '2025-04-03 07:27:54', 1, '2025-04-03 07:27:54', 'text-embedding-3-small'); +INSERT INTO `ruoyi-ai`.`chat_model` (`id`, `tenant_id`, `category`, `model_name`, `model_describe`, `model_price`, `model_type`, `model_show`, `system_prompt`, `api_host`, `api_key`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1907576007017066497, '000000', 'vector', 'quentinz/bge-large-zh-v1.5', 'bge-large-zh-v1.5', 0, '2', '0', NULL, 'https://api.pandarobot.chat/', 'cdBlIaZcufccm2RaDe547cBd054d49C7B0782eCa72A0052b', 103, 1, '2025-04-03 07:28:56', 1, '2025-04-03 07:28:56', 'bge-large-zh-v1.5'); +INSERT INTO `ruoyi-ai`.`chat_model` (`id`, `tenant_id`, `category`, `model_name`, `model_describe`, `model_price`, `model_type`, `model_show`, `system_prompt`, `api_host`, `api_key`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1907576806191362049, '000000', 'vector', 'nomic-embed-text', 'nomic-embed-text', 0, '2', '0', NULL, 'http://127.0.0.1:11434/', 'nomic-embed-text', 103, 1, '2025-04-03 07:32:06', 1, '2025-04-03 07:32:06', 'nomic-embed-text'); +INSERT INTO `ruoyi-ai`.`chat_model` (`id`, `tenant_id`, `category`, `model_name`, `model_describe`, `model_price`, `model_type`, `model_show`, `system_prompt`, `api_host`, `api_key`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1907577073490161665, '000000', 'vector', 'snowflake-arctic-embed', 'snowflake-arctic-embed', 0, '2', '0', NULL, 'http://127.0.0.1:11434/', 'snowflake-arctic-embed', 103, 1, '2025-04-03 07:33:10', 1, '2025-04-03 07:33:10', 'snowflake-arctic-embed');