| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | |
| | | 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<Message> 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<String> nearestList; |
| | | List<Double> queryVector = embeddingService.getQueryVector(content, chatRequest.getKid()); |
| | | nearestList = vectorStore.nearest(queryVector,chatRequest.getKid()); |
| | | List<Double> 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); |
| | | } |
| | | |
| | | /** |
| | |
| | | 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; |
| | |
| | | @Lazy |
| | | @Resource |
| | | private LocalModelsVectorization localModelsVectorization; |
| | | @Lazy |
| | | @Resource |
| | | private ISysModelService sysModelService; |
| | | |
| | | @Getter |
| | | private OpenAiStreamClient openAiStreamClient; |
| | |
| | | @Override |
| | | public List<List<Double>> batchVectorization(List<String> chunkList, String kid) { |
| | | List<List<Double>> 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); |
| | |
| | | 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; |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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'); |