feat: mcp测试版

This commit is contained in:
ageer
2025-04-14 00:22:21 +08:00
parent 4b53939002
commit 731352fd04
461 changed files with 3110 additions and 13838 deletions

View File

@@ -8,7 +8,7 @@ import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.ruoyi.common.excel.utils.ExcelUtil;
import org.ruoyi.common.idempotent.annotation.RepeatSubmit;
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
import org.ruoyi.core.page.TableDataInfo;
import org.ruoyi.common.web.core.BaseController;
import org.ruoyi.domain.bo.ChatAgentManageBo;
import org.ruoyi.domain.vo.ChatAgentManageVo;
@@ -16,7 +16,7 @@ import org.ruoyi.service.IChatAgentManageService;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.ruoyi.common.log.annotation.Log;
import org.ruoyi.common.mybatis.core.page.PageQuery;
import org.ruoyi.core.page.PageQuery;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;

View File

@@ -8,7 +8,7 @@ import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.ruoyi.common.excel.utils.ExcelUtil;
import org.ruoyi.common.idempotent.annotation.RepeatSubmit;
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
import org.ruoyi.core.page.TableDataInfo;
import org.ruoyi.domain.bo.ChatAppStoreBo;
import org.ruoyi.domain.vo.ChatAppStoreVo;
import org.ruoyi.service.IChatAppStoreService;
@@ -16,7 +16,7 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.ruoyi.common.log.annotation.Log;
import org.ruoyi.common.web.core.BaseController;
import org.ruoyi.common.mybatis.core.page.PageQuery;
import org.ruoyi.core.page.PageQuery;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;

View File

@@ -8,7 +8,7 @@ import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.ruoyi.common.excel.utils.ExcelUtil;
import org.ruoyi.common.idempotent.annotation.RepeatSubmit;
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
import org.ruoyi.core.page.TableDataInfo;
import org.ruoyi.system.domain.bo.ChatConfigBo;
import org.ruoyi.system.domain.vo.ChatConfigVo;
import org.ruoyi.system.service.IChatConfigService;
@@ -16,7 +16,7 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.ruoyi.common.log.annotation.Log;
import org.ruoyi.common.web.core.BaseController;
import org.ruoyi.common.mybatis.core.page.PageQuery;
import org.ruoyi.core.page.PageQuery;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;
@@ -31,7 +31,7 @@ import org.ruoyi.common.log.enums.BusinessType;
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/system/config")
@RequestMapping("/system/chatConfig")
public class ChatConfigController extends BaseController {
private final IChatConfigService chatConfigService;

View File

@@ -1,4 +1,4 @@
package org.ruoyi.chat.controller.api;
package org.ruoyi.chat.controller.chat;
import jakarta.servlet.http.HttpServletRequest;
@@ -13,8 +13,8 @@ import org.ruoyi.common.chat.entity.whisper.WhisperResponse;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.domain.model.LoginUser;
import org.ruoyi.common.core.exception.base.BaseException;
import org.ruoyi.common.mybatis.core.page.PageQuery;
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
import org.ruoyi.core.page.PageQuery;
import org.ruoyi.core.page.TableDataInfo;
import org.ruoyi.common.satoken.utils.LoginHelper;
import org.ruoyi.domain.bo.ChatMessageBo;
import org.ruoyi.domain.vo.ChatMessageVo;

View File

@@ -8,7 +8,7 @@ import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.ruoyi.common.excel.utils.ExcelUtil;
import org.ruoyi.common.idempotent.annotation.RepeatSubmit;
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
import org.ruoyi.core.page.TableDataInfo;
import org.ruoyi.domain.bo.ChatGptsBo;
import org.ruoyi.domain.vo.ChatGptsVo;
import org.ruoyi.service.IChatGptsService;
@@ -16,7 +16,7 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.ruoyi.common.log.annotation.Log;
import org.ruoyi.common.web.core.BaseController;
import org.ruoyi.common.mybatis.core.page.PageQuery;
import org.ruoyi.core.page.PageQuery;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;

View File

@@ -8,7 +8,7 @@ import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.ruoyi.common.excel.utils.ExcelUtil;
import org.ruoyi.common.idempotent.annotation.RepeatSubmit;
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
import org.ruoyi.core.page.TableDataInfo;
import org.ruoyi.domain.bo.ChatMessageBo;
import org.ruoyi.domain.vo.ChatMessageVo;
import org.ruoyi.service.IChatMessageService;
@@ -16,7 +16,7 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.ruoyi.common.log.annotation.Log;
import org.ruoyi.common.web.core.BaseController;
import org.ruoyi.common.mybatis.core.page.PageQuery;
import org.ruoyi.core.page.PageQuery;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;

View File

@@ -9,7 +9,7 @@ import cn.dev33.satoken.annotation.SaCheckPermission;
import org.ruoyi.chat.service.chat.UserModelService;
import org.ruoyi.common.excel.utils.ExcelUtil;
import org.ruoyi.common.idempotent.annotation.RepeatSubmit;
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
import org.ruoyi.core.page.TableDataInfo;
import org.ruoyi.domain.bo.ChatModelBo;
import org.ruoyi.domain.vo.ChatModelVo;
import org.ruoyi.service.IChatModelService;
@@ -17,7 +17,7 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.ruoyi.common.log.annotation.Log;
import org.ruoyi.common.web.core.BaseController;
import org.ruoyi.common.mybatis.core.page.PageQuery;
import org.ruoyi.core.page.PageQuery;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;

View File

@@ -8,7 +8,7 @@ import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.ruoyi.common.excel.utils.ExcelUtil;
import org.ruoyi.common.idempotent.annotation.RepeatSubmit;
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
import org.ruoyi.core.page.TableDataInfo;
import org.ruoyi.domain.bo.ChatPackagePlanBo;
import org.ruoyi.domain.vo.ChatPackagePlanVo;
import org.ruoyi.service.IChatPackagePlanService;
@@ -16,7 +16,7 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.ruoyi.common.log.annotation.Log;
import org.ruoyi.common.web.core.BaseController;
import org.ruoyi.common.mybatis.core.page.PageQuery;
import org.ruoyi.core.page.PageQuery;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;

View File

@@ -8,7 +8,7 @@ import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.ruoyi.common.excel.utils.ExcelUtil;
import org.ruoyi.common.idempotent.annotation.RepeatSubmit;
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
import org.ruoyi.core.page.TableDataInfo;
import org.ruoyi.domain.bo.ChatPayOrderBo;
import org.ruoyi.domain.vo.ChatPayOrderVo;
import org.ruoyi.service.IChatPayOrderService;
@@ -16,7 +16,7 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.ruoyi.common.log.annotation.Log;
import org.ruoyi.common.web.core.BaseController;
import org.ruoyi.common.mybatis.core.page.PageQuery;
import org.ruoyi.core.page.PageQuery;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;

View File

@@ -8,7 +8,7 @@ import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.ruoyi.common.excel.utils.ExcelUtil;
import org.ruoyi.common.idempotent.annotation.RepeatSubmit;
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
import org.ruoyi.core.page.TableDataInfo;
import org.ruoyi.domain.bo.ChatPluginBo;
import org.ruoyi.domain.vo.ChatPluginVo;
import org.ruoyi.service.IChatPluginService;
@@ -16,7 +16,7 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.ruoyi.common.log.annotation.Log;
import org.ruoyi.common.web.core.BaseController;
import org.ruoyi.common.mybatis.core.page.PageQuery;
import org.ruoyi.core.page.PageQuery;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;

View File

@@ -7,7 +7,7 @@ import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.ruoyi.common.idempotent.annotation.RepeatSubmit;
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
import org.ruoyi.core.page.TableDataInfo;
import org.ruoyi.domain.bo.ChatVoucherBo;
import org.ruoyi.domain.vo.ChatVoucherVo;
import org.ruoyi.service.IChatVoucherService;
@@ -15,7 +15,7 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.ruoyi.common.log.annotation.Log;
import org.ruoyi.common.web.core.BaseController;
import org.ruoyi.common.mybatis.core.page.PageQuery;
import org.ruoyi.core.page.PageQuery;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;

View File

@@ -1,4 +1,4 @@
package org.ruoyi.chat.controller.api;
package org.ruoyi.chat.controller.tripartite;
import cn.hutool.json.JSONUtil;
import io.swagger.annotations.Api;

View File

@@ -1,4 +1,4 @@
package org.ruoyi.chat.controller.api;
package org.ruoyi.chat.controller.tripartite;
import cn.hutool.json.JSONUtil;
import io.swagger.annotations.ApiOperation;

View File

@@ -1,4 +1,4 @@
package org.ruoyi.chat.controller.api;
package org.ruoyi.chat.controller.tripartite;
import cn.hutool.json.JSONUtil;
import io.swagger.annotations.Api;

View File

@@ -1,4 +1,4 @@
package org.ruoyi.chat.controller.api;
package org.ruoyi.chat.controller.tripartite;
import cn.hutool.json.JSONUtil;
import io.swagger.annotations.ApiOperation;

View File

@@ -1,4 +1,4 @@
package org.ruoyi.chat.controller.api;
package org.ruoyi.chat.controller.tripartite;
import cn.hutool.json.JSONUtil;
import io.swagger.annotations.Api;

View File

@@ -1,24 +0,0 @@
package org.ruoyi.chat.factory;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.chat.service.chat.IChatService;
import org.ruoyi.chat.service.chat.impl.OllamaServiceImpl;
import org.ruoyi.chat.service.chat.impl.OpenAIServiceImpl;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class SseServiceFactory {
public IChatService getSseService(String type) {
if ("openai".equals(type)) {
return new OpenAIServiceImpl();
} else if ("ollama".equals(type)) {
return new OllamaServiceImpl();
} else {
throw new IllegalArgumentException("Unknown type: " + type);
}
}
}

View File

@@ -1,44 +0,0 @@
package org.ruoyi.chat.factory;
import cn.hutool.core.util.StrUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.chat.service.knowledge.vectorstore.MilvusVectorStore;
import org.ruoyi.chat.service.knowledge.vectorstore.WeaviateVectorStore;
import org.ruoyi.domain.vo.KnowledgeInfoVo;
import org.ruoyi.mapper.KnowledgeInfoMapper;
import org.ruoyi.service.VectorStoreService;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class VectorStoreFactory {
private final WeaviateVectorStore weaviateVectorStore;
private final MilvusVectorStore milvusVectorStore;
@Resource
private KnowledgeInfoMapper knowledgeInfoMapper;
public VectorStoreFactory(WeaviateVectorStore weaviateVectorStore, MilvusVectorStore milvusVectorStore) {
this.weaviateVectorStore = weaviateVectorStore;
this.milvusVectorStore = milvusVectorStore;
}
public VectorStoreService getVectorStore(String kid){
String vectorModel = "weaviate";
if (StrUtil.isNotEmpty(kid)) {
KnowledgeInfoVo knowledgeInfoVo = knowledgeInfoMapper.selectVoById(Long.valueOf(kid));
if (knowledgeInfoVo != null && StrUtil.isNotEmpty(knowledgeInfoVo.getVector())) {
vectorModel = knowledgeInfoVo.getVector();
}
}
if ("weaviate".equals(vectorModel)){
return weaviateVectorStore;
}else if ("milvus".equals(vectorModel)){
return milvusVectorStore;
}
return null;
}
}

View File

@@ -4,8 +4,8 @@ import cn.hutool.core.util.StrUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.chat.service.knowledge.vectorizer.BgeLargeVectorization;
import org.ruoyi.chat.service.knowledge.vectorizer.OpenAiVectorization;
import org.ruoyi.chat.service.knowledge.BgeLargeVectorizationImpl;
import org.ruoyi.chat.service.knowledge.OpenAiVectorizationImpl;
import org.ruoyi.domain.vo.KnowledgeInfoVo;
import org.ruoyi.service.IKnowledgeInfoService;
import org.ruoyi.service.VectorizationService;
@@ -20,15 +20,15 @@ import org.springframework.stereotype.Component;
@Slf4j
public class VectorizationFactory {
private final OpenAiVectorization openAiVectorization;
private final OpenAiVectorizationImpl openAiVectorization;
private final BgeLargeVectorization bgeLargeVectorization;
private final BgeLargeVectorizationImpl bgeLargeVectorization;
@Lazy
@Resource
private IKnowledgeInfoService knowledgeInfoService;
public VectorizationFactory(OpenAiVectorization openAiVectorization, BgeLargeVectorization bgeLargeVectorization) {
public VectorizationFactory(OpenAiVectorizationImpl openAiVectorization, BgeLargeVectorizationImpl bgeLargeVectorization) {
this.openAiVectorization = openAiVectorization;
this.bgeLargeVectorization = bgeLargeVectorization;
}

View File

@@ -39,13 +39,21 @@ public class OllamaServiceImpl implements IChatService {
@Autowired
private IChatModelService chatModelService;
@Autowired
private ChatClient chatClient;
@Autowired
private ToolCallbackProvider tools;
private final ChatClient chatClient;
private final ChatMemory chatMemory = new InMemoryChatMemory();
public OllamaServiceImpl(ChatClient.Builder chatClientBuilder,ToolCallbackProvider tools) {
this.chatClient = chatClientBuilder
.defaultTools(tools)
.defaultOptions(
OllamaOptions.builder()
.model(OllamaModel.QWEN_2_5_7B)
.temperature(0.4)
.build())
.build();
}
@Override
public SseEmitter chat(ChatRequest chatRequest,SseEmitter emitter) {
@@ -104,11 +112,6 @@ public class OllamaServiceImpl implements IChatService {
this.chatClient.prompt(chatRequest.getPrompt())
.advisors(messageChatMemoryAdvisor)
.tools(tools)
.options(OllamaOptions.builder()
.model(OllamaModel.QWEN_2_5_7B)
.temperature(0.4)
.build())
.stream()
.chatResponse()
.subscribe(

View File

@@ -1,114 +0,0 @@
package org.ruoyi.chat.service.chat.impl;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.chat.config.ChatConfig;
import org.ruoyi.chat.listener.SSEEventSourceListener;
import org.ruoyi.chat.service.chat.IChatService;
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.chat.request.ChatRequest;
import org.ruoyi.domain.vo.ChatModelVo;
import org.ruoyi.service.IChatModelService;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.io.IOException;
import java.util.List;
/**
* @author ageer
*/
@Service
@Slf4j
public class OpenAIServiceImpl implements IChatService {
@Autowired
private IChatModelService chatModelService;
@Autowired
private ChatConfig chatConfig;
@Autowired
private OpenAiStreamClient openAiStreamClient;
@Autowired
private ChatClient chatClient;
@Autowired
private ToolCallbackProvider tools;
private final ChatMemory chatMemory = new InMemoryChatMemory();
@Override
public SseEmitter chat(ChatRequest chatRequest,SseEmitter emitter) {
SSEEventSourceListener openAIEventSourceListener = new SSEEventSourceListener(emitter);
// 查询模型信息
ChatModelVo chatModelVo = chatModelService.selectModelByName(chatRequest.getModel());
if(chatModelVo!=null){
// 建请求客户端
openAiStreamClient = chatConfig.createOpenAiStreamClient(chatModelVo.getApiHost(), chatModelVo.getApiKey());
// 设置默认提示词
chatRequest.setSysPrompt(chatModelVo.getSystemPrompt());
}
ChatCompletion completion = ChatCompletion
.builder()
.messages(chatRequest.getMessages())
.model(chatRequest.getModel())
.stream(chatRequest.getStream())
.build();
openAiStreamClient.streamChatCompletion(completion, openAIEventSourceListener);
return emitter;
}
@Override
public SseEmitter mcpChat(ChatRequest chatRequest, SseEmitter emitter) {
List<Message> msgList = chatRequest.getMessages();
// 添加记忆
for (int i = 0; i < msgList.size(); i++) {
org.springframework.ai.chat.messages.Message springAiMessage = new UserMessage(msgList.get(i).getContent().toString());
chatMemory.add(String.valueOf(i),springAiMessage);
}
var messageChatMemoryAdvisor = new MessageChatMemoryAdvisor(chatMemory, chatRequest.getUserId(), 10);
this.chatClient.prompt(chatRequest.getPrompt())
.advisors(messageChatMemoryAdvisor)
.tools(tools)
.options(OpenAiChatOptions.builder().model(chatRequest.getModel()).build())
.stream()
.chatResponse()
.subscribe(
chatResponse -> {
try {
emitter.send(chatResponse, MediaType.APPLICATION_JSON);
} catch (IOException e) {
e.printStackTrace();
}
},
error -> {
try {
emitter.completeWithError(error);
} catch (Exception e) {
e.printStackTrace();
}
},
() -> {
try {
emitter.complete();
} catch (Exception e) {
e.printStackTrace();
}
}
);
return emitter;
}
}

View File

@@ -14,7 +14,6 @@ import okhttp3.*;
import org.ruoyi.chat.service.chat.IChatCostService;
import org.ruoyi.chat.service.chat.IChatService;
import org.ruoyi.chat.service.chat.ISseService;
import org.ruoyi.chat.factory.SseServiceFactory;
import org.ruoyi.chat.util.IpUtil;
import org.ruoyi.chat.util.SSEUtil;
import org.ruoyi.common.chat.request.ChatRequest;
@@ -73,7 +72,8 @@ public class SseServiceImpl implements ISseService {
private final IChatCostService chatCostService;
private final SseServiceFactory sseServiceFactory;
private final IChatService chatService;
private static final String requestIdTemplate = "company-%d";
@@ -135,11 +135,10 @@ public class SseServiceImpl implements ISseService {
String model = chatRequest.getModel();
// 如果模型名称以ollama开头则调用ollama中部署的本地模型
if (model.startsWith("ollama-")) {
String[] parts = chatRequest.getModel().split("ollama-", 2); // 限制分割次数为2
String[] parts = chatRequest.getModel().split("ollama-", 2);
if (parts.length > 1) {
chatRequest.setModel(parts[1]);
IChatService chatService = sseServiceFactory.getSseService("ollama");
chatService.chat(chatRequest,emitter);
chatService.mcpChat(chatRequest,emitter);
} else {
throw new IllegalArgumentException("Invalid ollama model name: " + chatRequest.getModel());
}

View File

@@ -1,4 +1,4 @@
package org.ruoyi.chat.service.knowledge.vectorizer;
package org.ruoyi.chat.service.knowledge;
import io.github.ollama4j.OllamaAPI;
import io.github.ollama4j.models.embeddings.OllamaEmbeddingsRequestModel;
@@ -13,8 +13,8 @@ import org.ruoyi.service.IKnowledgeInfoService;
import org.ruoyi.service.VectorizationService;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.List;
/**
@@ -23,7 +23,7 @@ import java.util.List;
@Component
@Slf4j
@RequiredArgsConstructor
public class BgeLargeVectorization implements VectorizationService {
public class BgeLargeVectorizationImpl implements VectorizationService {
@Lazy
@Resource

View File

@@ -1,4 +1,4 @@
package org.ruoyi.chat.service.knowledge.vectorizer;
package org.ruoyi.chat.service.knowledge;
import jakarta.annotation.Resource;
import lombok.Getter;
@@ -24,7 +24,7 @@ import java.util.stream.Collectors;
@Component
@Slf4j
@RequiredArgsConstructor
public class OpenAiVectorization implements VectorizationService {
public class OpenAiVectorizationImpl implements VectorizationService {
@Lazy
@Resource

View File

@@ -0,0 +1,30 @@
package org.ruoyi.chat.service.knowledge;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.chat.factory.VectorizationFactory;
import org.ruoyi.service.VectorizationService;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@Slf4j
@Primary
@AllArgsConstructor
public class VectorizationWrapper implements VectorizationService {
private final VectorizationFactory vectorizationFactory;
@Override
public List<List<Double>> batchVectorization(List<String> chunkList, String kid) {
VectorizationService embedding = vectorizationFactory.getEmbedding(kid);
return embedding.batchVectorization(chunkList, kid);
}
@Override
public List<Double> singleVectorization(String chunk, String kid) {
VectorizationService embedding = vectorizationFactory.getEmbedding(kid);
return embedding.singleVectorization(chunk, kid);
}
}

View File

@@ -1,387 +0,0 @@
package org.ruoyi.chat.service.knowledge.vectorstore;
import io.milvus.client.MilvusServiceClient;
import io.milvus.grpc.DataType;
import io.milvus.grpc.DescribeIndexResponse;
import io.milvus.grpc.MutationResult;
import io.milvus.grpc.SearchResults;
import io.milvus.param.*;
import io.milvus.param.collection.*;
import io.milvus.param.dml.DeleteParam;
import io.milvus.param.dml.InsertParam;
import io.milvus.param.dml.SearchParam;
import io.milvus.param.index.CreateIndexParam;
import io.milvus.param.index.DescribeIndexParam;
import io.milvus.param.partition.CreatePartitionParam;
import io.milvus.response.QueryResultsWrapper;
import io.milvus.response.SearchResultsWrapper;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.ruoyi.common.core.service.ConfigService;
import org.ruoyi.service.VectorStoreService;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Service
@Slf4j
public class MilvusVectorStore implements VectorStoreService {
private volatile Integer dimension;
private volatile String collectionName;
private MilvusServiceClient milvusServiceClient;
@Resource
private ConfigService configService;
@PostConstruct
public void loadConfig() {
this.dimension = Integer.parseInt(configService.getConfigValue("milvus", "dimension"));
this.collectionName = configService.getConfigValue("milvus", "collection");
}
@PostConstruct
public void init() {
String milvusHost = configService.getConfigValue("milvus", "host");
String milvausPort = configService.getConfigValue("milvus", "port");
milvusServiceClient = new MilvusServiceClient(
ConnectParam.newBuilder()
.withHost(milvusHost)
.withPort(Integer.parseInt(milvausPort))
.withDatabaseName("default")
.build()
);
}
private void createSchema(String kid) {
FieldType primaryField = FieldType.newBuilder()
.withName("row_id")
.withDataType(DataType.Int64)
.withPrimaryKey(true)
.withAutoID(true)
.build();
FieldType contentField = FieldType.newBuilder()
.withName("content")
.withDataType(DataType.VarChar)
.withMaxLength(1000)
.build();
FieldType kidField = FieldType.newBuilder()
.withName("kid")
.withDataType(DataType.VarChar)
.withMaxLength(20)
.build();
FieldType docIdField = FieldType.newBuilder()
.withName("docId")
.withDataType(DataType.VarChar)
.withMaxLength(20)
.build();
FieldType fidField = FieldType.newBuilder()
.withName("fid")
.withDataType(DataType.VarChar)
.withMaxLength(20)
.build();
FieldType vectorField = FieldType.newBuilder()
.withName("fv")
.withDataType(DataType.FloatVector)
.withDimension(dimension)
.build();
CreateCollectionParam createCollectionReq = CreateCollectionParam.newBuilder()
.withCollectionName(collectionName + kid)
.withDescription("local knowledge")
.addFieldType(primaryField)
.addFieldType(contentField)
.addFieldType(kidField)
.addFieldType(docIdField)
.addFieldType(fidField)
.addFieldType(vectorField)
.build();
milvusServiceClient.createCollection(createCollectionReq);
// 创建向量的索引
IndexType INDEX_TYPE = IndexType.IVF_FLAT;
String INDEX_PARAM = "{\"nlist\":1024}";
milvusServiceClient.createIndex(
CreateIndexParam.newBuilder()
.withCollectionName(collectionName + kid)
.withFieldName("fv")
.withIndexType(INDEX_TYPE)
.withMetricType(MetricType.IP)
.withExtraParam(INDEX_PARAM)
.withSyncMode(Boolean.FALSE)
.build()
);
}
@Override
public void newSchema(String kid) {
createSchema(kid);
}
@Override
public void removeByKidAndFid(String kid, String fid) {
milvusServiceClient.delete(
DeleteParam.newBuilder()
.withCollectionName(collectionName + kid)
.withExpr("fid == " + fid)
.build()
);
}
@Override
public void storeEmbeddings(List<String> chunkList, List<List<Double>> vectorList, String kid, String docId, List<String> fidList) {
String fullCollectionName = collectionName + kid;
// 检查集合是否存在
HasCollectionParam hasCollectionParam = HasCollectionParam.newBuilder()
.withCollectionName(fullCollectionName)
.build();
R<Boolean> booleanR = milvusServiceClient.hasCollection(hasCollectionParam);
if (booleanR.getStatus() == R.Status.Success.getCode()) {
boolean collectionExists = booleanR.getData().booleanValue();
if (!collectionExists) {
// 集合不存在,创建集合
List<FieldType> fieldTypes = new ArrayList<>();
// 假设这里定义 id 字段,根据实际情况修改
FieldType idField = FieldType.newBuilder()
.withName("id")
.withDataType(DataType.Int64)
.withPrimaryKey(true)
.withAutoID(true)
.build();
fieldTypes.add(idField);
// 定义向量字段
FieldType vectorField = FieldType.newBuilder()
.withName("fv")
.withDataType(DataType.FloatVector)
.withDimension(vectorList.get(0).size())
.build();
fieldTypes.add(vectorField);
// 定义其他字段
FieldType contentField = FieldType.newBuilder()
.withName("content")
.withDataType(DataType.VarChar)
.withMaxLength(chunkList.size() * 1024) // 根据实际情况修改
.build();
fieldTypes.add(contentField);
FieldType kidField = FieldType.newBuilder()
.withName("kid")
.withDataType(DataType.VarChar)
.withMaxLength(256) // 根据实际情况修改
.build();
fieldTypes.add(kidField);
FieldType docIdField = FieldType.newBuilder()
.withName("docId")
.withDataType(DataType.VarChar)
.withMaxLength(256) // 根据实际情况修改
.build();
fieldTypes.add(docIdField);
FieldType fidField = FieldType.newBuilder()
.withName("fid")
.withDataType(DataType.VarChar)
.withMaxLength(256) // 根据实际情况修改
.build();
fieldTypes.add(fidField);
CreateCollectionParam createCollectionParam = CreateCollectionParam.newBuilder()
.withCollectionName(fullCollectionName)
.withFieldTypes(fieldTypes)
.build();
R<RpcStatus> collection = milvusServiceClient.createCollection(createCollectionParam);
if (collection.getStatus() == R.Status.Success.getCode()) {
System.out.println("集合 " + fullCollectionName + " 创建成功");
// 创建索引
CreateIndexParam createIndexParam = CreateIndexParam.newBuilder()
.withCollectionName(fullCollectionName)
.withFieldName("fv") // 向量字段名
.withIndexType(IndexType.IVF_FLAT) // 索引类型
.withMetricType(MetricType.IP)
.withExtraParam("{\"nlist\":1024}") // 索引参数
.build();
R<RpcStatus> indexResponse = milvusServiceClient.createIndex(createIndexParam);
if (indexResponse.getStatus() == R.Status.Success.getCode()) {
System.out.println("索引创建成功");
} else {
System.err.println("索引创建失败: " + indexResponse.getMessage());
return;
}
} else {
System.err.println("集合创建失败: " + collection.getMessage());
return;
}
}
} else {
System.err.println("检查集合是否存在时出错: " + booleanR.getMessage());
return;
}
if (StringUtils.isNotBlank(docId)) {
milvusServiceClient.createPartition(
CreatePartitionParam.newBuilder()
.withCollectionName(fullCollectionName)
.withPartitionName(docId)
.build()
);
}
List<List<Float>> vectorFloatList = new ArrayList<>();
List<String> kidList = new ArrayList<>();
List<String> docIdList = new ArrayList<>();
for (int i = 0; i < Math.min(chunkList.size(), vectorList.size()); i++) {
List<Double> vector = vectorList.get(i);
List<Float> vfList = new ArrayList<>();
for (int j = 0; j < vector.size(); j++) {
Double value = vector.get(j);
vfList.add(value.floatValue());
}
vectorFloatList.add(vfList);
kidList.add(kid);
docIdList.add(docId);
}
List<InsertParam.Field> fields = new ArrayList<>();
fields.add(new InsertParam.Field("content", chunkList));
fields.add(new InsertParam.Field("kid", kidList));
fields.add(new InsertParam.Field("docId", docIdList));
fields.add(new InsertParam.Field("fid", fidList));
fields.add(new InsertParam.Field("fv", vectorFloatList));
InsertParam insertParam = InsertParam.newBuilder()
.withCollectionName(fullCollectionName)
.withPartitionName(docId)
.withFields(fields)
.build();
System.out.println("=========================");
R<MutationResult> insert = milvusServiceClient.insert(insertParam);
if (insert.getStatus() == R.Status.Success.getCode()) {
System.out.println("插入成功,插入的行数: " + insert.getData().getInsertCnt());
} else {
System.err.println("插入失败: " + insert.getMessage());
}
System.out.println("=========================");
// milvus在将数据装载到内存后才能进行向量计算.
LoadCollectionParam loadCollectionParam = LoadCollectionParam.newBuilder()
.withCollectionName(fullCollectionName)
.build();
R<RpcStatus> loadResponse = milvusServiceClient.loadCollection(loadCollectionParam);
if (loadResponse.getStatus() != R.Status.Success.getCode()) {
System.err.println("加载集合 " + fullCollectionName + " 到内存时出错:" + loadResponse.getMessage());
}
// milvusServiceClient.loadCollection(LoadCollectionParam.newBuilder().withCollectionName(fullCollectionName).build());
}
@Override
public void removeByDocId(String kid, String docId) {
milvusServiceClient.delete(
DeleteParam.newBuilder()
.withCollectionName(collectionName + kid)
.withExpr("1 == 1")
.withPartitionName(docId)
.build()
);
}
@Override
public void removeByKid(String kid) {
milvusServiceClient.dropCollection(
DropCollectionParam.newBuilder()
.withCollectionName(collectionName + kid)
.build()
);
}
@Override
public List<String> nearest(List<Double> queryVector, String kid) {
String fullCollectionName = collectionName + kid;
HasCollectionParam hasCollectionParam = HasCollectionParam.newBuilder()
.withCollectionName(fullCollectionName)
.build();
R<Boolean> booleanR = milvusServiceClient.hasCollection(hasCollectionParam);
if (booleanR.getStatus() != R.Status.Success.getCode() || !booleanR.getData().booleanValue()) {
System.err.println("集合 " + fullCollectionName + " 不存在或检查集合存在性时出错。");
return new ArrayList<>();
}
DescribeIndexParam describeIndexParam = DescribeIndexParam.newBuilder().withCollectionName(fullCollectionName).build();
R<DescribeIndexResponse> describeIndexResponseR = milvusServiceClient.describeIndex(describeIndexParam);
if (describeIndexResponseR.getStatus() == R.Status.Success.getCode()) {
System.out.println("索引信息: " + describeIndexResponseR.getData().getIndexDescriptionsCount());
} else {
System.err.println("获取索引失败: " + describeIndexResponseR.getMessage());
}
List<String> search_output_fields = Arrays.asList("content", "fv");
List<Float> fv = new ArrayList<>();
for (int i = 0; i < queryVector.size(); i++) {
fv.add(queryVector.get(i).floatValue());
}
List<List<Float>> vectors = new ArrayList<>();
vectors.add(fv);
String search_param = "{\"nprobe\":10, \"offset\":0}";
SearchParam searchParam = SearchParam.newBuilder()
.withCollectionName(collectionName + kid)
.withMetricType(MetricType.IP)
.withOutFields(search_output_fields)
.withTopK(10)
.withVectors(vectors)
.withVectorFieldName("fv")
.withParams(search_param)
.build();
System.out.println("SearchParam: " + searchParam.toString());
R<SearchResults> respSearch = milvusServiceClient.search(searchParam);
if (respSearch.getStatus() == R.Status.Success.getCode()) {
SearchResults searchResults = respSearch.getData();
if (searchResults != null) {
System.out.println(searchResults.getResults());
SearchResultsWrapper wrapperSearch = new SearchResultsWrapper(searchResults.getResults());
List<QueryResultsWrapper.RowRecord> rowRecords = wrapperSearch.getRowRecords();
List<String> resultList = new ArrayList<>();
if (rowRecords != null && !rowRecords.isEmpty()) {
for (QueryResultsWrapper.RowRecord rowRecord : rowRecords) {
String content = rowRecord.get("content").toString();
resultList.add(content);
}
}
return resultList;
} else {
System.err.println("搜索结果为空");
}
} else {
System.err.println("搜索操作失败: " + respSearch.getMessage());
}
return new ArrayList<>();
}
/**
* milvus 不支持通过文本检索相似性
*
* @param query
* @param kid
* @return
*/
@Override
public List<String> nearest(String query, String kid) {
return null;
}
}

View File

@@ -1,402 +0,0 @@
package org.ruoyi.chat.service.knowledge.vectorstore;
import cn.hutool.core.lang.UUID;
import cn.hutool.json.JSONObject;
import com.google.gson.internal.LinkedTreeMap;
import io.weaviate.client.Config;
import io.weaviate.client.WeaviateClient;
import io.weaviate.client.base.Result;
import io.weaviate.client.v1.data.model.WeaviateObject;
import io.weaviate.client.v1.data.replication.model.ConsistencyLevel;
import io.weaviate.client.v1.filters.Operator;
import io.weaviate.client.v1.filters.WhereFilter;
import io.weaviate.client.v1.graphql.model.GraphQLResponse;
import io.weaviate.client.v1.graphql.query.argument.NearTextArgument;
import io.weaviate.client.v1.graphql.query.argument.NearVectorArgument;
import io.weaviate.client.v1.graphql.query.fields.Field;
import io.weaviate.client.v1.misc.model.Meta;
import io.weaviate.client.v1.misc.model.ReplicationConfig;
import io.weaviate.client.v1.misc.model.ShardingConfig;
import io.weaviate.client.v1.misc.model.VectorIndexConfig;
import io.weaviate.client.v1.schema.model.DataType;
import io.weaviate.client.v1.schema.model.Property;
import io.weaviate.client.v1.schema.model.Schema;
import io.weaviate.client.v1.schema.model.WeaviateClass;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.ruoyi.common.core.service.ConfigService;
import org.ruoyi.domain.vo.KnowledgeInfoVo;
import org.ruoyi.service.IKnowledgeInfoService;
import org.ruoyi.service.VectorStoreService;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
@Slf4j
public class WeaviateVectorStore implements VectorStoreService {
private volatile String protocol;
private volatile String host;
private volatile String className;
@Lazy
@Resource
private IKnowledgeInfoService knowledgeInfoService;
@Lazy
@Resource
private ConfigService configService;
@PostConstruct
public void loadConfig() {
this.protocol = configService.getConfigValue("weaviate", "protocol");
this.host = configService.getConfigValue("weaviate", "host");
this.className = configService.getConfigValue("weaviate", "classname");
}
public WeaviateClient getClient() {
Config config = new Config(protocol, host);
WeaviateClient client = new WeaviateClient(config);
return client;
}
public Result<Meta> getMeta() {
WeaviateClient client = getClient();
Result<Meta> meta = client.misc().metaGetter().run();
if (meta.getError() == null) {
System.out.printf("meta.hostname: %s\n", meta.getResult().getHostname());
System.out.printf("meta.version: %s\n", meta.getResult().getVersion());
System.out.printf("meta.modules: %s\n", meta.getResult().getModules());
} else {
System.out.printf("Error: %s\n", meta.getError().getMessages());
}
return meta;
}
public Result<Schema> getSchemas() {
WeaviateClient client = getClient();
Result<Schema> result = client.schema().getter().run();
if (result.hasErrors()) {
System.out.println(result.getError());
} else {
System.out.println(result.getResult());
}
return result;
}
public Result<Boolean> createSchema(String kid) {
WeaviateClient client = getClient();
VectorIndexConfig vectorIndexConfig = VectorIndexConfig.builder()
.distance("cosine")
.cleanupIntervalSeconds(300)
.efConstruction(128)
.maxConnections(64)
.vectorCacheMaxObjects(500000L)
.ef(-1)
.skip(false)
.dynamicEfFactor(8)
.dynamicEfMax(500)
.dynamicEfMin(100)
.flatSearchCutoff(40000)
.build();
ShardingConfig shardingConfig = ShardingConfig.builder()
.desiredCount(3)
.desiredVirtualCount(128)
.function("murmur3")
.key("_id")
.strategy("hash")
.virtualPerPhysical(128)
.build();
ReplicationConfig replicationConfig = ReplicationConfig.builder()
.factor(1)
.build();
JSONObject classModuleConfigValue = new JSONObject();
classModuleConfigValue.put("vectorizeClassName", false);
JSONObject classModuleConfig = new JSONObject();
classModuleConfig.put("text2vec-transformers", classModuleConfigValue);
JSONObject propertyModuleConfigValueSkipTrue = new JSONObject();
propertyModuleConfigValueSkipTrue.put("vectorizePropertyName", false);
propertyModuleConfigValueSkipTrue.put("skip", true);
JSONObject propertyModuleConfigSkipTrue = new JSONObject();
propertyModuleConfigSkipTrue.put("text2vec-transformers", propertyModuleConfigValueSkipTrue);
JSONObject propertyModuleConfigValueSkipFalse = new JSONObject();
propertyModuleConfigValueSkipFalse.put("vectorizePropertyName", false);
propertyModuleConfigValueSkipFalse.put("skip", false);
JSONObject propertyModuleConfigSkipFalse = new JSONObject();
propertyModuleConfigSkipFalse.put("text2vec-transformers", propertyModuleConfigValueSkipFalse);
WeaviateClass clazz = WeaviateClass.builder()
.className(className + kid)
.description("local knowledge")
.vectorIndexType("hnsw")
.vectorizer("text2vec-transformers")
.shardingConfig(shardingConfig)
.vectorIndexConfig(vectorIndexConfig)
.replicationConfig(replicationConfig)
.moduleConfig(classModuleConfig)
.properties(new ArrayList() {
{
add(Property.builder()
.dataType(new ArrayList() {
{
add(DataType.TEXT);
}
})
.name("content")
.description("The content of the local knowledge,for search")
.moduleConfig(propertyModuleConfigSkipFalse)
.build());
add(Property.builder()
.dataType(new ArrayList() {
{
add(DataType.TEXT);
}
})
.name("kid")
.description("The knowledge id of the local knowledge,for search")
.moduleConfig(propertyModuleConfigSkipTrue)
.build());
add(Property.builder()
.dataType(new ArrayList() {
{
add(DataType.TEXT);
}
})
.name("docId")
.description("The doc id of the local knowledge,for search")
.moduleConfig(propertyModuleConfigSkipTrue)
.build());
add(Property.builder()
.dataType(new ArrayList() {
{
add(DataType.TEXT);
}
})
.name("fid")
.description("The fragment id of the local knowledge,for search")
.moduleConfig(propertyModuleConfigSkipTrue)
.build());
add(Property.builder()
.dataType(new ArrayList() {
{
add(DataType.TEXT);
}
})
.name("uuid")
.description("The uuid id of the local knowledge fragment(same with id properties),for search")
.moduleConfig(propertyModuleConfigSkipTrue)
.build());
} })
.build();
Result<Boolean> result = client.schema().classCreator().withClass(clazz).run();
if (result.hasErrors()) {
System.out.println(result.getError());
}
System.out.println(result.getResult());
return result;
}
@Override
public void newSchema(String kid) {
createSchema(kid);
}
@Override
public void removeByKidAndFid(String kid, String fid) {
List<String> resultList = new ArrayList<>();
WeaviateClient client = getClient();
Field fieldId = Field.builder().name("uuid").build();
WhereFilter where = WhereFilter.builder()
.path(new String[]{"fid"})
.operator(Operator.Equal)
.valueString(fid)
.build();
Result<GraphQLResponse> result = client.graphQL().get()
.withClassName(className + kid)
.withFields(fieldId)
.withWhere(where)
.run();
LinkedTreeMap<String, Object> t = (LinkedTreeMap<String, Object>) result.getResult().getData();
LinkedTreeMap<String, ArrayList<LinkedTreeMap>> l = (LinkedTreeMap<String, ArrayList<LinkedTreeMap>>) t.get("Get");
ArrayList<LinkedTreeMap> m = l.get(className + kid);
for (LinkedTreeMap linkedTreeMap : m) {
String uuid = linkedTreeMap.get("uuid").toString();
resultList.add(uuid);
}
for (String uuid : resultList) {
Result<Boolean> deleteResult = client.data().deleter()
.withID(uuid)
.withClassName(className + kid)
.withConsistencyLevel(ConsistencyLevel.ALL) // default QUORUM
.run();
}
}
@Override
public void storeEmbeddings(List<String> chunkList, List<List<Double>> vectorList, String kid, String docId, List<String> fidList) {
WeaviateClient client = getClient();
for (int i = 0; i < Math.min(chunkList.size(), vectorList.size()); i++) {
List<Double> vector = vectorList.get(i);
Float[] vf = vector.stream().map(Double::floatValue).toArray(Float[]::new);
Map<String, Object> dataSchema = new HashMap<>();
dataSchema.put("content", chunkList.get(i));
dataSchema.put("kid", kid);
dataSchema.put("docId", docId);
dataSchema.put("fid", fidList.get(i));
String uuid = UUID.randomUUID().toString();
dataSchema.put("uuid", uuid);
Result<WeaviateObject> result = client.data().creator()
.withClassName(className + kid)
.withID(uuid)
.withVector(vf)
.withProperties(dataSchema)
.run();
}
}
@Override
public void removeByDocId(String kid, String docId) {
List<String> resultList = new ArrayList<>();
WeaviateClient client = getClient();
Field fieldId = Field.builder().name("uuid").build();
WhereFilter where = WhereFilter.builder()
.path(new String[]{"docId"})
.operator(Operator.Equal)
.valueString(docId)
.build();
Result<GraphQLResponse> result = client.graphQL().get()
.withClassName(className + kid)
.withFields(fieldId)
.withWhere(where)
.run();
LinkedTreeMap<String, Object> t = (LinkedTreeMap<String, Object>) result.getResult().getData();
LinkedTreeMap<String, ArrayList<LinkedTreeMap>> l = (LinkedTreeMap<String, ArrayList<LinkedTreeMap>>) t.get("Get");
ArrayList<LinkedTreeMap> m = l.get(className + kid);
for (LinkedTreeMap linkedTreeMap : m) {
String uuid = linkedTreeMap.get("uuid").toString();
resultList.add(uuid);
}
for (String uuid : resultList) {
Result<Boolean> deleteResult = client.data().deleter()
.withID(uuid)
.withClassName(className + kid)
.withConsistencyLevel(ConsistencyLevel.ALL) // default QUORUM
.run();
}
}
@Override
public void removeByKid(String kid) {
WeaviateClient client = getClient();
Result<Boolean> result = client.schema().classDeleter().withClassName(className + kid).run();
if (result.hasErrors()) {
System.out.println("删除schema失败" + result.getError());
} else {
System.out.println("删除schema成功" + result.getResult());
}
log.info("drop schema by kid, result = {}", result);
}
@Override
public List<String> nearest(List<Double> queryVector, String kid) {
if (StringUtils.isBlank(kid)) {
return new ArrayList<String>();
}
List<String> resultList = new ArrayList<>();
Float[] vf = new Float[queryVector.size()];
for (int j = 0; j < queryVector.size(); j++) {
Double value = queryVector.get(j);
vf[j] = value.floatValue();
}
WeaviateClient client = getClient();
Field contentField = Field.builder().name("content").build();
Field _additional = Field.builder()
.name("_additional")
.fields(new Field[]{
Field.builder().name("distance").build()
}).build();
NearVectorArgument nearVector = NearVectorArgument.builder()
.vector(vf)
.distance(1.6f) // certainty = 1f - distance /2f
.build();
KnowledgeInfoVo knowledgeInfoVo = knowledgeInfoService.queryById(Long.valueOf(kid));
Result<GraphQLResponse> result = client.graphQL().get()
.withClassName(className + kid)
.withFields(contentField, _additional)
.withNearVector(nearVector)
.withLimit(knowledgeInfoVo.getRetrieveLimit())
.run();
LinkedTreeMap<String, Object> t = (LinkedTreeMap<String, Object>) result.getResult().getData();
LinkedTreeMap<String, ArrayList<LinkedTreeMap>> l = (LinkedTreeMap<String, ArrayList<LinkedTreeMap>>) t.get("Get");
ArrayList<LinkedTreeMap> m = l.get(className + kid);
for (LinkedTreeMap linkedTreeMap : m) {
String content = linkedTreeMap.get("content").toString();
resultList.add(content);
}
return resultList;
}
@Override
public List<String> nearest(String query, String kid) {
if (StringUtils.isBlank(kid)) {
return new ArrayList<String>();
}
List<String> resultList = new ArrayList<>();
WeaviateClient client = getClient();
Field contentField = Field.builder().name("content").build();
Field _additional = Field.builder()
.name("_additional")
.fields(new Field[]{
Field.builder().name("distance").build()
}).build();
NearTextArgument nearText = client.graphQL().arguments().nearTextArgBuilder()
.concepts(new String[]{query})
.distance(1.6f) // certainty = 1f - distance /2f
.build();
KnowledgeInfoVo knowledgeInfoVo = knowledgeInfoService.queryById(Long.valueOf(kid));
Result<GraphQLResponse> result = client.graphQL().get()
.withClassName(className + kid)
.withFields(contentField, _additional)
.withNearText(nearText)
.withLimit(knowledgeInfoVo.getRetrieveLimit())
.run();
LinkedTreeMap<String, Object> t = (LinkedTreeMap<String, Object>) result.getResult().getData();
LinkedTreeMap<String, ArrayList<LinkedTreeMap>> l = (LinkedTreeMap<String, ArrayList<LinkedTreeMap>>) t.get("Get");
ArrayList<LinkedTreeMap> m = l.get(className + kid);
for (LinkedTreeMap linkedTreeMap : m) {
String content = linkedTreeMap.get("content").toString();
resultList.add(content);
}
return resultList;
}
public Result<Boolean> deleteSchema(String kid) {
WeaviateClient client = getClient();
Result<Boolean> result = client.schema().classDeleter().withClassName(className + kid).run();
if (result.hasErrors()) {
System.out.println(result.getError());
} else {
System.out.println(result.getResult());
}
return result;
}
}