| | |
| | | List<Message> messages = chatRequest.getMessages(); |
| | | String content = messages.get(messages.size() - 1).getContent().toString(); |
| | | List<String> nearestList; |
| | | List<Double> queryVector = embeddingService.getQueryVector(content); |
| | | List<Double> queryVector = embeddingService.getQueryVector(content, chatRequest.getKid()); |
| | | nearestList = vectorStore.nearest(queryVector,chatRequest.getKid()); |
| | | for (String prompt : nearestList) { |
| | | Message sysMessage = Message.builder().content(prompt).role(Message.Role.USER).build(); |
| | |
| | | driverClassName: com.mysql.cj.jdbc.Driver |
| | | url: jdbc:mysql://43.139.70.230:3306/ruoyi-ai?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true |
| | | username: ruoyi-ai |
| | | password: ruoyi-ai |
| | | password: eCaZ278N62k6fhYj |
| | | |
| | | hikari: |
| | | # æå¤§è¿æ¥æ± æ°é |
| | |
| | | |
| | | # ä¼ä¸å¾®ä¿¡åºç¨ |
| | | wechat: |
| | | # æ¯å¦ä½¿ç¨å¾®ä¿¡ true/false |
| | | enable: true |
| | | # çæçç»å½äºç»´ç è·¯å¾ é»è®¤ä¸é¡¹ç®å级 |
| | | qrPath: "./" |
| | | # ä¼ä¸å¾®ä¿¡åºç¨ |
| | | cp: |
| | | corpId: |
| | | appConfigs: |
| | |
| | | token: '' |
| | | aesKey: '' |
| | | |
| | | # ç¥è¯åºé
ç½® |
| | | chain: |
| | | split: |
| | | chunk: |
| | | endspliter: "<STOP>" |
| | | # ååææ¬å¤§å° |
| | | size: 200 |
| | | overlay: 30 |
| | | qaspliter: "###" |
| | | # ç¥è¯åºä¸æ£ç´¢çæ¡æ° |
| | | limits: 5 |
| | | vector: |
| | | model: 'text-embedding-3-small' |
| | | store: |
| | | type: weaviate |
| | | weaviate: |
| | | protocol: http |
| | | host: 127.0.0.1:6038 |
| | | classname: LocalKnowledge |
| | | milvus: |
| | | host: 127.0.0.1 |
| | | port: 19530 |
| | | dimension: 1536 |
| | | collection: LocalKnowledge |
| | | |
| | | |
| | |
| | | return stringBuffer.toString(); |
| | | } |
| | | @Override |
| | | public List<String> getChunkList(String content){ |
| | | return textSplitter.split(content); |
| | | public List<String> getChunkList(String content, String kid){ |
| | | return textSplitter.split(content, kid); |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<String> getChunkList(String content) { |
| | | public List<String> getChunkList(String content, String kid) { |
| | | return null; |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<String> getChunkList(String content) { |
| | | public List<String> getChunkList(String content, String kid) { |
| | | return null; |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<String> getChunkList(String content) { |
| | | public List<String> getChunkList(String content, String kid) { |
| | | return null; |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<String> getChunkList(String content) { |
| | | public List<String> getChunkList(String content, String kid) { |
| | | return null; |
| | | } |
| | | } |
| | |
| | | return stringBuffer.toString(); |
| | | } |
| | | @Override |
| | | public List<String> getChunkList(String content){ |
| | | return textSplitter.split(content); |
| | | public List<String> getChunkList(String content, String kid){ |
| | | return textSplitter.split(content, kid); |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<String> getChunkList(String content) { |
| | | return characterTextSplitter.split(content); |
| | | public List<String> getChunkList(String content, String kid) { |
| | | return characterTextSplitter.split(content, kid); |
| | | } |
| | | } |
| | |
| | | * èµæºè½½å
¥ |
| | | */ |
| | | public interface ResourceLoader { |
| | | |
| | | String getContent(InputStream inputStream); |
| | | List<String> getChunkList(String content); |
| | | |
| | | List<String> getChunkList(String content, String kid); |
| | | } |
| | |
| | | return stringBuffer.toString(); |
| | | } |
| | | @Override |
| | | public List<String> getChunkList(String content){ |
| | | return textSplitter.split(content); |
| | | public List<String> getChunkList(String content, String kid){ |
| | | return textSplitter.split(content, kid); |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<String> getChunkList(String content) { |
| | | return textSplitter.split(content); |
| | | public List<String> getChunkList(String content, String kid) { |
| | | return textSplitter.split(content, kid); |
| | | } |
| | | |
| | | } |
| | |
| | | package org.ruoyi.knowledge.chain.split; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import jakarta.annotation.Resource; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.ruoyi.knowledge.domain.vo.KnowledgeInfoVo; |
| | | import org.ruoyi.knowledge.service.IKnowledgeInfoService; |
| | | import org.springframework.context.annotation.Lazy; |
| | | import org.springframework.context.annotation.Primary; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | |
| | | import java.util.List; |
| | | |
| | | @Component |
| | | @AllArgsConstructor |
| | | @Slf4j |
| | | @Primary |
| | | public class CharacterTextSplitter implements TextSplitter{ |
| | | private final SplitterProperties splitterProperties; |
| | | public class CharacterTextSplitter implements TextSplitter { |
| | | |
| | | @Lazy |
| | | @Resource |
| | | private IKnowledgeInfoService knowledgeInfoService; |
| | | |
| | | @Override |
| | | public List<String> split(String content) { |
| | | public List<String> split(String content, String kid) { |
| | | // ä»ç¥è¯åºè¡¨ä¸è·åé
ç½® |
| | | KnowledgeInfoVo knowledgeInfoVo = knowledgeInfoService.queryById(Long.valueOf(kid)); |
| | | String knowledgeSeparator = knowledgeInfoVo.getKnowledgeSeparator(); |
| | | int textBlockSize = knowledgeInfoVo.getTextBlockSize(); |
| | | int overlapChar = knowledgeInfoVo.getOverlapChar(); |
| | | List<String> chunkList = new ArrayList<>(); |
| | | if (content.contains(splitterProperties.getEndspliter())){ |
| | | if (content.contains(knowledgeSeparator)) { |
| | | // æèªå®ä¹åé符åå |
| | | String[] chunks = content.split(splitterProperties.getEndspliter()); |
| | | String[] chunks = content.split(knowledgeSeparator); |
| | | chunkList.addAll(Arrays.asList(chunks)); |
| | | }else { |
| | | } else { |
| | | int indexMin = 0; |
| | | int len = content.length(); |
| | | int i = 0; |
| | | int right = 0; |
| | | while (true) { |
| | | if (len > right ){ |
| | | int begin = i*splitterProperties.getSize() - splitterProperties.getOverlay(); |
| | | if (begin < indexMin){ |
| | | if (len > right) { |
| | | int begin = i * textBlockSize - overlapChar; |
| | | if (begin < indexMin) { |
| | | begin = indexMin; |
| | | } |
| | | int end = splitterProperties.getSize()*(i+1) + splitterProperties.getOverlay(); |
| | | if (end > len){ |
| | | int end = textBlockSize * (i + 1) + overlapChar; |
| | | if (end > len) { |
| | | end = len; |
| | | } |
| | | String chunk = content.substring(begin,end); |
| | | String chunk = content.substring(begin, end); |
| | | chunkList.add(chunk); |
| | | i++; |
| | | right = right + splitterProperties.getSize(); |
| | | }else { |
| | | right = right + textBlockSize; |
| | | } else { |
| | | break; |
| | | } |
| | | } |
| | |
| | | @Slf4j |
| | | public class CodeTextSplitter implements TextSplitter{ |
| | | @Override |
| | | public List<String> split(String content) { |
| | | public List<String> split(String content, String kid) { |
| | | return null; |
| | | } |
| | | } |
| | |
| | | @Slf4j |
| | | public class MarkdownTextSplitter implements TextSplitter{ |
| | | @Override |
| | | public List<String> split(String content) { |
| | | public List<String> split(String content, String kid) { |
| | | return null; |
| | | } |
| | | } |
| | |
| | | */ |
| | | public interface TextSplitter { |
| | | |
| | | List<String> split(String content); |
| | | /** |
| | | * ææ¬åå |
| | | * |
| | | * @param content ææ¬å
容 |
| | | * @param kid ç¥è¯åºid |
| | | * @return åååçææ¬å表 |
| | | */ |
| | | List<String> split(String content, String kid); |
| | | } |
| | |
| | | @Slf4j |
| | | public class TokenTextSplitter implements TextSplitter{ |
| | | @Override |
| | | public List<String> split(String content) { |
| | | public List<String> split(String content, String kid) { |
| | | return null; |
| | | } |
| | | } |
| | |
| | | package org.ruoyi.knowledge.chain.vectorizer; |
| | | |
| | | import jakarta.annotation.Resource; |
| | | import lombok.Getter; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | |
| | | |
| | | 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.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.context.annotation.Lazy; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.math.BigDecimal; |
| | |
| | | @RequiredArgsConstructor |
| | | public class OpenAiVectorization implements Vectorization { |
| | | |
| | | @Value("${chain.vector.model}") |
| | | private String embeddingModel; |
| | | @Lazy |
| | | @Resource |
| | | private IKnowledgeInfoService knowledgeInfoService; |
| | | |
| | | @Getter |
| | | private OpenAiStreamClient openAiStreamClient; |
| | |
| | | private final ChatConfig chatConfig; |
| | | |
| | | @Override |
| | | public List<List<Double>> batchVectorization(List<String> chunkList) { |
| | | public List<List<Double>> batchVectorization(List<String> chunkList, String kid) { |
| | | openAiStreamClient = chatConfig.getOpenAiStreamClient(); |
| | | |
| | | KnowledgeInfoVo knowledgeInfoVo = knowledgeInfoService.queryById(Long.valueOf(kid)); |
| | | Embedding embedding = Embedding.builder() |
| | | .input(chunkList) |
| | | .model(embeddingModel) |
| | | .model(knowledgeInfoVo.getVectorModel()) |
| | | .build(); |
| | | EmbeddingResponse embeddings = openAiStreamClient.embeddings(embedding); |
| | | List<List<Double>> vectorList = new ArrayList<>(); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<Double> singleVectorization(String chunk) { |
| | | public List<Double> singleVectorization(String chunk, String kid) { |
| | | List<String> chunkList = new ArrayList<>(); |
| | | chunkList.add(chunk); |
| | | List<List<Double>> vectorList = batchVectorization(chunkList); |
| | | List<List<Double>> vectorList = batchVectorization(chunkList, kid); |
| | | return vectorList.get(0); |
| | | } |
| | | |
| | |
| | | * åéå |
| | | */ |
| | | public interface Vectorization { |
| | | List<List<Double>> batchVectorization(List<String> chunkList); |
| | | List<Double> singleVectorization(String chunk); |
| | | List<List<Double>> batchVectorization(List<String> chunkList, String kid); |
| | | |
| | | List<Double> singleVectorization(String chunk, String kid); |
| | | } |
| | |
| | | |
| | | private final VectorizationFactory vectorizationFactory; |
| | | @Override |
| | | public List<List<Double>> batchVectorization(List<String> chunkList) { |
| | | public List<List<Double>> batchVectorization(List<String> chunkList, String kid) { |
| | | Vectorization embedding = vectorizationFactory.getEmbedding(); |
| | | return embedding.batchVectorization(chunkList); |
| | | return embedding.batchVectorization(chunkList, kid); |
| | | } |
| | | |
| | | @Override |
| | | public List<Double> singleVectorization(String chunk) { |
| | | public List<Double> singleVectorization(String chunk, String kid) { |
| | | Vectorization embedding = vectorizationFactory.getEmbedding(); |
| | | return embedding.singleVectorization(chunk); |
| | | return embedding.singleVectorization(chunk, kid); |
| | | } |
| | | } |
| | |
| | | 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.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | |
| | | @Slf4j |
| | | public class MilvusVectorStore implements VectorStore{ |
| | | |
| | | |
| | | @Value("${chain.vector.store.milvus.host}") |
| | | private String milvusHost; |
| | | @Value("${chain.vector.store.milvus.port}") |
| | | private Integer milvausPort; |
| | | |
| | | @Value("${chain.vector.store.milvus.dimension}") |
| | | private Integer dimension; |
| | | |
| | | @Value("${chain.vector.store.milvus.collection}") |
| | | private String collectionName; |
| | | |
| | | 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(milvausPort) |
| | | .withPort(Integer.parseInt(milvausPort)) |
| | | .withDatabaseName("default") |
| | | .build() |
| | | ); |
| | |
| | | package org.ruoyi.knowledge.chain.vectorstore; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.ruoyi.knowledge.domain.KnowledgeInfo; |
| | | import org.ruoyi.knowledge.domain.vo.KnowledgeInfoVo; |
| | | import org.ruoyi.knowledge.mapper.KnowledgeInfoMapper; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | @Component |
| | | @Slf4j |
| | | @RequiredArgsConstructor |
| | | public class VectorStoreFactory { |
| | | |
| | | @Value("${chain.vector.store.type}") |
| | | private String type; |
| | | |
| | | private final WeaviateVectorStore weaviateVectorStore; |
| | | |
| | | private final MilvusVectorStore milvusVectorStore; |
| | | |
| | | public VectorStoreFactory(WeaviateVectorStore weaviateVectorStore, MilvusVectorStore milvusVectorStore) { |
| | | this.weaviateVectorStore = weaviateVectorStore; |
| | | this.milvusVectorStore = milvusVectorStore; |
| | | } |
| | | private final KnowledgeInfoMapper knowledgeInfoMapper; |
| | | |
| | | public VectorStore getVectorStore(){ |
| | | if ("weaviate".equals(type)){ |
| | | public VectorStore getVectorStore(String kid){ |
| | | KnowledgeInfoVo knowledgeInfoVo = knowledgeInfoMapper.selectVoOne( |
| | | new LambdaQueryWrapper<KnowledgeInfo>().eq(KnowledgeInfo::getKid,kid) |
| | | ); |
| | | String vectorModel = knowledgeInfoVo.getVector(); |
| | | if ("weaviate".equals(vectorModel)){ |
| | | return weaviateVectorStore; |
| | | }else if ("milvus".equals(type)){ |
| | | }else if ("milvus".equals(vectorModel)){ |
| | | return milvusVectorStore; |
| | | } |
| | | return null; |
| | |
| | | private final VectorStoreFactory vectorStoreFactory; |
| | | @Override |
| | | public void storeEmbeddings(List<String> chunkList, List<List<Double>> vectorList, String kid, String docId, List<String> fidList) { |
| | | VectorStore vectorStore = vectorStoreFactory.getVectorStore(); |
| | | VectorStore vectorStore = vectorStoreFactory.getVectorStore(kid); |
| | | vectorStore.storeEmbeddings(chunkList, vectorList, kid, docId, fidList); |
| | | } |
| | | |
| | | @Override |
| | | public void removeByDocId(String kid, String docId) { |
| | | VectorStore vectorStore = vectorStoreFactory.getVectorStore(); |
| | | VectorStore vectorStore = vectorStoreFactory.getVectorStore(kid); |
| | | vectorStore.removeByDocId(kid,docId); |
| | | } |
| | | |
| | | @Override |
| | | public void removeByKid(String kid) { |
| | | VectorStore vectorStore = vectorStoreFactory.getVectorStore(); |
| | | VectorStore vectorStore = vectorStoreFactory.getVectorStore(kid); |
| | | vectorStore.removeByKid(kid); |
| | | } |
| | | |
| | | @Override |
| | | public List<String> nearest(List<Double> queryVector, String kid) { |
| | | VectorStore vectorStore = vectorStoreFactory.getVectorStore(); |
| | | VectorStore vectorStore = vectorStoreFactory.getVectorStore(kid); |
| | | return vectorStore.nearest(queryVector,kid); |
| | | } |
| | | |
| | | @Override |
| | | public List<String> nearest(String query, String kid) { |
| | | VectorStore vectorStore = vectorStoreFactory.getVectorStore(); |
| | | VectorStore vectorStore = vectorStoreFactory.getVectorStore(kid); |
| | | return vectorStore.nearest(query, kid); |
| | | } |
| | | |
| | | @Override |
| | | public void newSchema(String kid) { |
| | | VectorStore vectorStore = vectorStoreFactory.getVectorStore(); |
| | | VectorStore vectorStore = vectorStoreFactory.getVectorStore(kid); |
| | | vectorStore.newSchema(kid); |
| | | } |
| | | |
| | | @Override |
| | | public void removeByKidAndFid(String kid, String fid) { |
| | | VectorStore vectorStore = vectorStoreFactory.getVectorStore(); |
| | | VectorStore vectorStore = vectorStoreFactory.getVectorStore(kid); |
| | | vectorStore.removeByKidAndFid(kid, fid); |
| | | } |
| | | } |
| | |
| | | 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.knowledge.chain.retrieve.PromptRetrieverProperties; |
| | | import org.ruoyi.common.core.service.ConfigService; |
| | | import org.ruoyi.knowledge.domain.vo.KnowledgeInfoVo; |
| | | import org.ruoyi.knowledge.service.IKnowledgeInfoService; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.context.annotation.Lazy; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.ArrayList; |
| | |
| | | @Slf4j |
| | | public class WeaviateVectorStore implements VectorStore{ |
| | | |
| | | @Value("${chain.vector.store.weaviate.protocol}") |
| | | private String protocol; |
| | | @Value("${chain.vector.store.weaviate.host}") |
| | | private String host; |
| | | private volatile String protocol; |
| | | private volatile String host; |
| | | private volatile String className; |
| | | |
| | | @Value("${chain.vector.store.weaviate.classname}") |
| | | private String className; |
| | | @Lazy |
| | | @Resource |
| | | private IKnowledgeInfoService knowledgeInfoService; |
| | | |
| | | private final PromptRetrieverProperties promptRetrieverProperties; |
| | | @Lazy |
| | | @Resource |
| | | private ConfigService configService; |
| | | |
| | | public WeaviateVectorStore(PromptRetrieverProperties promptRetrieverProperties) { |
| | | this.promptRetrieverProperties = promptRetrieverProperties; |
| | | @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(){ |
| | |
| | | .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(promptRetrieverProperties.getLimits()) |
| | | .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"); |
| | |
| | | .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(promptRetrieverProperties.getLimits()) |
| | | .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"); |
| | |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serial; |
| | |
| | | private String kname; |
| | | |
| | | /** |
| | | * ç¥è¯åºåç§° |
| | | */ |
| | | private String share; |
| | | |
| | | /** |
| | | * æè¿° |
| | | */ |
| | | private String description; |
| | |
| | | */ |
| | | private Date createTime; |
| | | |
| | | /** |
| | | * ç¥è¯åé符 |
| | | */ |
| | | private String knowledgeSeparator; |
| | | |
| | | /** |
| | | * æé®åé符 |
| | | */ |
| | | private String questionSeparator; |
| | | |
| | | /** |
| | | * éå åç¬¦æ° |
| | | */ |
| | | private Integer overlapChar; |
| | | |
| | | /** |
| | | * ç¥è¯åºä¸æ£ç´¢çæ¡æ° |
| | | */ |
| | | private Integer retrieveLimit; |
| | | |
| | | /** |
| | | * ææ¬åå¤§å° |
| | | */ |
| | | private Integer textBlockSize; |
| | | |
| | | /** |
| | | * åéåº |
| | | */ |
| | | private String vector; |
| | | |
| | | /** |
| | | * å鿍¡å |
| | | */ |
| | | private String vectorModel; |
| | | } |
| | |
| | | private String kname; |
| | | |
| | | /** |
| | | * ç¥è¯åºåç§° |
| | | */ |
| | | @NotBlank(message = "æ¯å¦å
¬å¼ç¥è¯åº") |
| | | private String share; |
| | | |
| | | /** |
| | | * æè¿° |
| | | */ |
| | | @NotBlank(message = "æè¿°ä¸è½ä¸ºç©º") |
| | | private String description; |
| | | |
| | | /** |
| | | * ç¥è¯åé符 |
| | | */ |
| | | @NotBlank(message = "ç¥è¯åé符ä¸è½ä¸ºç©º") |
| | | private String knowledgeSeparator; |
| | | |
| | | /** |
| | | * æé®åé符 |
| | | */ |
| | | @NotBlank(message = "æé®åé符ä¸è½ä¸ºç©º") |
| | | private String questionSeparator; |
| | | |
| | | /** |
| | | * éå åç¬¦æ° |
| | | */ |
| | | @NotNull(message = "éå å符æ°ä¸è½ä¸ºç©º") |
| | | private Integer overlapChar; |
| | | |
| | | /** |
| | | * ç¥è¯åºä¸æ£ç´¢çæ¡æ° |
| | | */ |
| | | @NotNull(message = "ç¥è¯åºä¸æ£ç´¢çæ¡æ°ä¸è½ä¸ºç©º") |
| | | private Integer retrieveLimit; |
| | | |
| | | /** |
| | | * ææ¬åå¤§å° |
| | | */ |
| | | @NotNull(message = "ææ¬å大å°ä¸è½ä¸ºç©º") |
| | | private Integer textBlockSize; |
| | | |
| | | /** |
| | | * åéåº |
| | | */ |
| | | @NotBlank(message = "åéåºä¸è½ä¸ºç©º") |
| | | private String vector; |
| | | |
| | | /** |
| | | * å鿍¡å |
| | | */ |
| | | @NotBlank(message = "å鿍¡åä¸è½ä¸ºç©º") |
| | | private String vectorModel; |
| | | } |
| | |
| | | private String kname; |
| | | |
| | | /** |
| | | * ç¥è¯åºåç§° |
| | | */ |
| | | private String share; |
| | | |
| | | /** |
| | | * æè¿° |
| | | */ |
| | | @ExcelProperty(value = "æè¿°") |
| | | private String description; |
| | | |
| | | /** |
| | | * ç¥è¯åé符 |
| | | */ |
| | | @ExcelProperty(value = "ç¥è¯åé符") |
| | | private String knowledgeSeparator; |
| | | |
| | | /** |
| | | * æé®åé符 |
| | | */ |
| | | @ExcelProperty(value = "æé®åé符") |
| | | private String questionSeparator; |
| | | |
| | | /** |
| | | * éå åç¬¦æ° |
| | | */ |
| | | @ExcelProperty(value = "éå å符æ°") |
| | | private Integer overlapChar; |
| | | |
| | | /** |
| | | * ç¥è¯åºä¸æ£ç´¢çæ¡æ° |
| | | */ |
| | | @ExcelProperty(value = "ç¥è¯åºä¸æ£ç´¢çæ¡æ°") |
| | | private Integer retrieveLimit; |
| | | |
| | | /** |
| | | * ææ¬åå¤§å° |
| | | */ |
| | | @ExcelProperty(value = "ææ¬å大å°") |
| | | private Integer textBlockSize; |
| | | |
| | | /** |
| | | * åéåº |
| | | */ |
| | | @ExcelProperty(value = "åéåº") |
| | | private String vector; |
| | | |
| | | /** |
| | | * å鿍¡å |
| | | */ |
| | | @ExcelProperty(value = "å鿍¡å") |
| | | private String vectorModel; |
| | | } |
| | |
| | | |
| | | void removeByKid(String kid); |
| | | |
| | | List<Double> getQueryVector(String query); |
| | | List<Double> getQueryVector(String query, String kid); |
| | | |
| | | void createSchema(String kid); |
| | | |
| | |
| | | * å é¤ç¥è¯åº |
| | | */ |
| | | void removeKnowledge(String id); |
| | | |
| | | /** |
| | | * æ£æ¥æ¯å¦æå 餿é |
| | | * @param knowledgeInfoList ç¥è¯å表 |
| | | */ |
| | | void check(List<KnowledgeInfoVo> knowledgeInfoList); |
| | | } |
| | |
| | | */ |
| | | @Override |
| | | public void storeEmbeddings(List<String> chunkList, String kid, String docId,List<String> fidList) { |
| | | List<List<Double>> vectorList = vectorization.batchVectorization(chunkList); |
| | | List<List<Double>> vectorList = vectorization.batchVectorization(chunkList, kid); |
| | | vectorStore.storeEmbeddings(chunkList,vectorList,kid,docId,fidList); |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<Double> getQueryVector(String query) { |
| | | List<Double> queryVector = vectorization.singleVectorization(query); |
| | | public List<Double> getQueryVector(String query, String kid) { |
| | | List<Double> queryVector = vectorization.singleVectorization(query,kid); |
| | | return queryVector; |
| | | } |
| | | |
| | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.ruoyi.common.core.domain.model.LoginUser; |
| | | import org.ruoyi.common.core.utils.MapstructUtils; |
| | | import org.ruoyi.common.core.utils.StringUtils; |
| | | 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.knowledge.domain.KnowledgeAttach; |
| | | import org.ruoyi.knowledge.domain.bo.KnowledgeAttachBo; |
| | | import org.ruoyi.knowledge.domain.vo.KnowledgeAttachVo; |
| | | import org.ruoyi.knowledge.domain.vo.KnowledgeInfoVo; |
| | | import org.ruoyi.knowledge.mapper.KnowledgeAttachMapper; |
| | | import org.ruoyi.knowledge.mapper.KnowledgeFragmentMapper; |
| | | import org.ruoyi.knowledge.mapper.KnowledgeInfoMapper; |
| | | import org.ruoyi.knowledge.service.IKnowledgeAttachService; |
| | | import org.ruoyi.knowledge.service.IKnowledgeInfoService; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.Collection; |
| | |
| | | private final KnowledgeAttachMapper baseMapper; |
| | | |
| | | private final KnowledgeFragmentMapper fragmentMapper; |
| | | |
| | | private final KnowledgeInfoMapper knowledgeInfoMapper; |
| | | |
| | | private final IKnowledgeInfoService knowledgeInfoService; |
| | | |
| | | |
| | | /** |
| | | * æ¥è¯¢ç¥è¯åºéä»¶ |
| | |
| | | |
| | | @Override |
| | | public void removeKnowledgeAttach(String kid) { |
| | | HashMap<String, Object> map = new HashMap<>(); |
| | | map.put("kid", kid); |
| | | LoginUser loginUser = LoginHelper.getLoginUser(); |
| | | Map<String,Object> map = new HashMap<>(); |
| | | map.put("kid",kid); |
| | | List<KnowledgeInfoVo> knowledgeInfoList = knowledgeInfoMapper.selectVoByMap(map); |
| | | knowledgeInfoService.check(knowledgeInfoList); |
| | | |
| | | baseMapper.deleteByMap(map); |
| | | fragmentMapper.deleteByMap(map); |
| | | } |
| | |
| | | package org.ruoyi.knowledge.service.impl; |
| | | |
| | | import cn.hutool.core.util.RandomUtil; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import io.github.ollama4j.OllamaAPI; |
| | | import io.github.ollama4j.exceptions.OllamaBaseException; |
| | | 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.chat.OllamaChatResult; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.ruoyi.common.core.domain.model.LoginUser; |
| | | import org.ruoyi.common.core.utils.MapstructUtils; |
| | | import org.ruoyi.common.core.utils.StringUtils; |
| | | import org.ruoyi.common.mybatis.core.page.PageQuery; |
| | |
| | | import org.ruoyi.knowledge.domain.KnowledgeAttach; |
| | | import org.ruoyi.knowledge.domain.KnowledgeFragment; |
| | | import org.ruoyi.knowledge.domain.KnowledgeInfo; |
| | | 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.domain.req.KnowledgeInfoUploadRequest; |
| | | import org.ruoyi.knowledge.domain.vo.KnowledgeInfoVo; |
| | |
| | | import org.ruoyi.knowledge.mapper.KnowledgeFragmentMapper; |
| | | import org.ruoyi.knowledge.mapper.KnowledgeInfoMapper; |
| | | 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.springframework.stereotype.Service; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.io.IOException; |
| | | import java.time.LocalDateTime; |
| | | import java.util.*; |
| | | |
| | | /** |
| | |
| | | } |
| | | |
| | | private LambdaQueryWrapper<KnowledgeInfo> buildQueryWrapper(KnowledgeInfoBo bo) { |
| | | Map<String, Object> params = bo.getParams(); |
| | | LambdaQueryWrapper<KnowledgeInfo> lqw = Wrappers.lambdaQuery(); |
| | | lqw.eq(StringUtils.isNotBlank(bo.getKid()), KnowledgeInfo::getKid, bo.getKid()); |
| | | lqw.eq(bo.getUid() != null, KnowledgeInfo::getUid, bo.getUid()); |
| | | lqw.like(StringUtils.isNotBlank(bo.getKname()), KnowledgeInfo::getKname, bo.getKname()); |
| | | lqw.eq(StringUtils.isNotBlank(bo.getDescription()), KnowledgeInfo::getDescription, bo.getDescription()); |
| | | // æ¥è¯¢å
¬å¼çç¥è¯åº |
| | | lqw.or(wrapper -> wrapper.eq(KnowledgeInfo::getShare, "1")); |
| | | return lqw; |
| | | } |
| | | |
| | |
| | | List<String> fids = new ArrayList<>(); |
| | | try { |
| | | content = resourceLoader.getContent(file.getInputStream()); |
| | | chunkList = resourceLoader.getChunkList(content); |
| | | chunkList = resourceLoader.getChunkList(content, kid); |
| | | for (int i = 0; i < chunkList.size(); i++) { |
| | | String fid = RandomUtil.randomString(16); |
| | | fids.add(fid); |
| | |
| | | |
| | | Map<String,Object> map = new HashMap<>(); |
| | | map.put("kid",id); |
| | | List<KnowledgeInfoVo> knowledgeInfoList = baseMapper.selectVoByMap(map); |
| | | check(knowledgeInfoList); |
| | | // å é¤ç¥è¯åº |
| | | baseMapper.deleteByMap(map); |
| | | // å é¤éä»¶åç¥è¯ç段 |
| | |
| | | embeddingService.removeByKid(id); |
| | | } |
| | | |
| | | /** |
| | | * å°ææ¬å转æ¢ä¸ºé¢è®ç»æ°æ® |
| | | * @param chunk è§£æææ¬å |
| | | */ |
| | | public String convertTextBlockToPretrainData(String chunk){ |
| | | String host = "http://localhost:11434/"; |
| | | OllamaAPI ollama = new OllamaAPI(host); |
| | | OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance("qwen2.5:7b"); |
| | | // 设置è¶
æ¶æ¶é´ |
| | | ollama.setRequestTimeoutSeconds(100); |
| | | // create first user question |
| | | String json = "instruction:ç¨æ·æä»¤,æ ¹æ®è¯ä¹æåä¸ä¸ªå
³é®è¯;input:ç¨æ·è¾å
¥,æ ¹æ®è¯ä¹æåå¤ä¸ªå
³é®è¯;output:è¾åºææ¬å
容"; |
| | | |
| | | OllamaChatRequestModel requestModel = builder.withMessage |
| | | (OllamaChatMessageRole.USER, "ææ¬ï¼"+chunk+"çè§£ææ¬å
容ï¼å¹¶ä¸å°ææ¬å
容转æ¢ä¸º:"+json+",è¾åºJSONæ ¼å¼ï¼ä¸è¦å
å«å
¶ä»æ å
³å
容,å
é¨ä½¿ç¨æ éè±æ") |
| | | .build(); |
| | | |
| | | // start conversation with model |
| | | OllamaChatResult chatResult = null; |
| | | try { |
| | | chatResult = ollama.chat(requestModel); |
| | | } catch (Exception e) { |
| | | System.out.println("è§£æå¤±è´¥!"); |
| | | @Override |
| | | public void check(List<KnowledgeInfoVo> knowledgeInfoList){ |
| | | LoginUser loginUser = LoginHelper.getLoginUser(); |
| | | for (KnowledgeInfoVo knowledgeInfoVo : knowledgeInfoList) { |
| | | if(!knowledgeInfoVo.getUid().equals(loginUser.getUserId())){ |
| | | throw new SecurityException("æéä¸è¶³"); |
| | | } |
| | | return chatResult.getResponse(); |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | */ |
| | | @GetMapping("/list") |
| | | @SaCheckPermission("system:config:list") |
| | | public List<ChatConfigVo> list(ChatConfigBo bo) { |
| | | return chatConfigService.queryList(bo); |
| | | public R<List<ChatConfigVo>> list(ChatConfigBo bo) { |
| | | return R.ok(chatConfigService.queryList(bo)); |
| | | } |
| | | |
| | | /** |
| | |
| | | private String model; |
| | | |
| | | /** |
| | | * æºè¯è¨ |
| | | */ |
| | | private String sourceLanguage; |
| | | |
| | | /** |
| | | * ç®æ è¯è¨ |
| | | */ |
| | | private String targetLanguage; |
| | | private String targetLanguage; |
| | | |
| | | } |
| | |
| | | |
| | | List<Message> messageList = new ArrayList<>(); |
| | | |
| | | Message sysMessage = Message.builder().role(Message.Role.SYSTEM).content("ä½ä¸ºè±æ±ç¿»è¯ï¼æ¨ç任塿¯åç¡®å°å¨ä¸¤ç§è¯è¨ä¹é´ç¿»è¯ææ¬ãç¿»è¯æ¶ï¼è¯·æ³¨æä¸ä¸æï¼å确解éæè¯åè°è¯ã妿è¿ç»æ¶å°å¤ä¸ªè±æåè¯ï¼è¯·é»è®¤å°å
¶ç¿»è¯æä¸æå¥åãä½å¦æå颿'phrase:âï¼ååºç¿»è¯ä¸ºçè¯;妿æ'norma!:'ï¼åç¿»è¯ä¸ºå¤ä¸ªæ å
³çåè¯ãæ¨çç¿»è¯åºæ¥è¿æ¯è¯è
çæ°´å¹³ï¼å¹¶èèç¨æ·è¦æ±çç¹å®è¯è¨é£æ ¼æè¯æ°ãé¿å
使ç¨åç¯æ§è¯æ±ï¼å¿
è¦æ¶ç¨xæ¿æ¢ãæä¾ç¿»è¯æ¶ï¼è¯·ç¨ä¸æè§£éæ¯å¥è¯çæ¶æãä»å¥ã主è¯ãè°è¯ã宾è¯ãç¹æ®çè¯åè°è¯å¯¹äºéè¦ç¿»è¯ççè¯æåè¯ï¼è¯·æä¾æ¥æº(è¯å
¸)ãå¦æè¦æ±ç¿»è¯å¤ä¸ªçè¯ï¼è¯·ç¨|符å·åéã请记ä½:æ¨æ¯è±æ±ç¿»è¯ï¼ä¸æ¯æ±æ±ç¿»è¯æè±è±ç¿»è¯ãæäº¤å请ä»ç»æ£æ¥åä¿®è®¢çæ¡,å夿§å¶å¨50å以å
").build(); |
| | | Message sysMessage = Message.builder().role(Message.Role.SYSTEM).content("ä½ æ¯ä¸åç¿»è¯èå¸\n" + |
| | | "\n" + |
| | | "请å°ç¨æ·è¾å
¥è¯è¯ç¿»è¯æ{" + translationRequest.getTargetLanguage() + "}\n" + |
| | | "\n" + |
| | | "让æä»¬ä¸æ¥ä¸æ¥æ¥æè\n" + |
| | | "==示ä¾è¾åº==\n" + |
| | | "**ç¿»è¯** : <è¿éæ¾ç¤ºç¿»è¯æè±è¯çç»æ>\n" + |
| | | "\n" + |
| | | "**é å¥** : What's the weather like today? Use the 'Weather Query' plugin to find out instantly! <é ä¸ä¸ªè±è¯å¥å>\n" + |
| | | "\n" + |
| | | "**åä¹è¯** : Add-onãExtensionãModule <è¿éæ¾ç¤º1-3ä¸ªè±æçåä¹è¯>\n" + |
| | | "\n" + |
| | | "==示ä¾ç»æ==\n" + |
| | | "\n" + |
| | | "注æï¼è¯·ä¸¥æ ¼æç¤ºä¾è¿è¡è¾åº").build(); |
| | | messageList.add(sysMessage); |
| | | Message message = Message.builder().role(Message.Role.USER).content(translationRequest.getPrompt()).build(); |
| | | messageList.add(message); |
¶Ô±ÈÐÂÎļþ |
| | |
| | | ALTER TABLE `knowledge_info` ADD COLUMN `share` tinyint(4) NULL DEFAULT NULL COMMENT 'æ¯å¦å
¬å¼ç¥è¯åºï¼0 å¦ 1æ¯ï¼' AFTER `kname`; |