From 584212c5690802dd488924b94a3735e7be34bc6b Mon Sep 17 00:00:00 2001
From: zhouweiyi
Date: 星期三, 14 五月 2025 16:13:07 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/main'

---
 ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/bo/QueryVectorBo.java             |    9 
 ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/service/VectorStoreService.java          |   10 
 ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/knowledge/KnowledgeInfoServiceImpl.java  |  500 ++++++++++++++-----------------------
 script/sql/update/20250514.sql                                                                         |    6 
 ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/SseServiceImpl.java            |   78 +++--
 ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/bo/StoreEmbeddingBo.java          |    9 
 ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/KnowledgeInfo.java                |   14 
 ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/vo/KnowledgeInfoVo.java           |   16 
 README.md                                                                                              |   17 +
 ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/bo/KnowledgeInfoBo.java           |   14 
 ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/service/impl/VectorStoreServiceImpl.java |   69 ++--
 11 files changed, 349 insertions(+), 393 deletions(-)

diff --git a/README.md b/README.md
index 4aff8d3..cfb13aa 100644
--- a/README.md
+++ b/README.md
@@ -34,6 +34,23 @@
     <a href="https://github.com/ageerle/ruoyi-ai/issues">鎻愬嚭鏂扮壒鎬�</a>
 </p>
 
+## 蹇�熷惎鍔�
+
+1. **鍏嬮殕椤圭洰**
+   ```bash
+   git clone https://github.com/alanpeng/ruoyi-ai-docker-deploy
+   cd ruoyi-ai-docker-deploy
+   ```
+
+2. **鍚姩鍏ㄥ搴旂敤**
+   ```bash
+   docker-compose up -d
+   ```
+
+3. **璁块棶搴旂敤鐣岄潰**
+   - 鐢ㄦ埛鐣岄潰锛歚http://your-server-ip:8081`
+   - 绠$悊鍛樼晫闈細`http://your-server-ip:8082`
+
 ## 鐩綍
 
 - [绯荤粺浣撻獙](#绯荤粺浣撻獙)
diff --git a/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/KnowledgeInfo.java b/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/KnowledgeInfo.java
index 230a1d6..34b1c2d 100644
--- a/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/KnowledgeInfo.java
+++ b/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/KnowledgeInfo.java
@@ -1,5 +1,6 @@
 package org.ruoyi.domain;
 
+import com.alibaba.excel.annotation.ExcelProperty;
 import com.baomidou.mybatisplus.annotation.*;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -78,14 +79,19 @@
     private Long textBlockSize;
 
     /**
-     * 鍚戦噺搴�
+     * 鍚戦噺搴撴ā鍨嬪悕绉�
      */
-    private String vector;
+    private String vectorModelName;
 
     /**
-     * 鍚戦噺妯″瀷
+     * 鍚戦噺鍖栨ā鍨嬪悕绉�
      */
-    private String vectorModel;
+    private String embeddingModelName;
+
+    /**
+     * 绯荤粺鎻愮ず璇�
+     */
+    private String systemPrompt;
 
     /**
      * 澶囨敞
diff --git a/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/bo/KnowledgeInfoBo.java b/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/bo/KnowledgeInfoBo.java
index 00a22b7..9a510a6 100644
--- a/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/bo/KnowledgeInfoBo.java
+++ b/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/bo/KnowledgeInfoBo.java
@@ -83,16 +83,22 @@
     private Long textBlockSize;
 
     /**
-     * 鍚戦噺搴�
+     * 鍚戦噺搴撴ā鍨嬪悕绉�
      */
     @NotBlank(message = "鍚戦噺搴撲笉鑳戒负绌�", groups = { AddGroup.class, EditGroup.class })
-    private String vector;
+    private String vectorModelName;
 
     /**
-     * 鍚戦噺妯″瀷
+     * 鍚戦噺鍖栨ā鍨嬪悕绉�
      */
     @NotBlank(message = "鍚戦噺妯″瀷涓嶈兘涓虹┖", groups = { AddGroup.class, EditGroup.class })
-    private String vectorModel;
+    private String embeddingModelName;
+
+
+    /**
+     * 绯荤粺鎻愮ず璇�
+     */
+    private String systemPrompt;
 
     /**
      * 澶囨敞
diff --git a/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/bo/QueryVectorBo.java b/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/bo/QueryVectorBo.java
index 33e8204..ff3a26e 100644
--- a/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/bo/QueryVectorBo.java
+++ b/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/bo/QueryVectorBo.java
@@ -26,9 +26,14 @@
     private Integer maxResults;
 
     /**
-     * 妯″瀷鍚嶇О
+     * 鍚戦噺搴撴ā鍨嬪悕绉�
      */
-    private String modelName;
+    private String vectorModelName;
+
+    /**
+     * 鍚戦噺鍖栨ā鍨嬪悕绉�
+     */
+    private String embeddingModelName;
 
     /**
      * 璇锋眰key
diff --git a/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/bo/StoreEmbeddingBo.java b/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/bo/StoreEmbeddingBo.java
index 9510403..e4d8c38 100644
--- a/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/bo/StoreEmbeddingBo.java
+++ b/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/bo/StoreEmbeddingBo.java
@@ -32,9 +32,14 @@
     private List<String> fids;
 
     /**
-     * 妯″瀷鍚嶇О
+     * 鍚戦噺搴撴ā鍨嬪悕绉�
      */
-    private String modelName;
+    private String vectorModelName;
+
+    /**
+     * 鍚戦噺鍖栨ā鍨嬪悕绉�
+     */
+    private String embeddingModelName;
 
     /**
      * 璇锋眰key
diff --git a/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/vo/KnowledgeInfoVo.java b/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/vo/KnowledgeInfoVo.java
index 6a5fdbf..ed4f6aa 100644
--- a/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/vo/KnowledgeInfoVo.java
+++ b/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/domain/vo/KnowledgeInfoVo.java
@@ -98,16 +98,20 @@
     private Integer textBlockSize;
 
     /**
-     * 鍚戦噺搴�
+     * 鍚戦噺搴撴ā鍨嬪悕绉�
      */
-    @ExcelProperty(value = "鍚戦噺搴�")
-    private String vector;
+    private String vectorModelName;
 
     /**
-     * 鍚戦噺妯″瀷
+     * 鍚戦噺鍖栨ā鍨嬪悕绉�
      */
-    @ExcelProperty(value = "鍚戦噺妯″瀷")
-    private String vectorModel;
+    private String embeddingModelName;
+
+
+    /**
+     * 绯荤粺鎻愮ず璇�
+     */
+    private String systemPrompt;
 
     /**
      * 澶囨敞
diff --git a/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/service/VectorStoreService.java b/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/service/VectorStoreService.java
index e27c94c..be445b9 100644
--- a/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/service/VectorStoreService.java
+++ b/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/service/VectorStoreService.java
@@ -13,14 +13,14 @@
 
     void storeEmbeddings(StoreEmbeddingBo storeEmbeddingBo);
 
-    void removeByDocId(String kid,String docId);
-
-    void removeByKid(String kid);
-
     List<String> getQueryVector(QueryVectorBo queryVectorBo);
 
     void createSchema(String kid,String modelName);
 
-    void removeByKidAndFid(String kid, String fid);
+    void removeByKid(String kid,String modelName);
+
+    void removeByDocId(String kid,String docId,String modelName);
+
+    void removeByKidAndFid(String kid, String fid,String modelName);
 
 }
diff --git a/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/service/impl/VectorStoreServiceImpl.java b/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/service/impl/VectorStoreServiceImpl.java
index d74176a..b5f7962 100644
--- a/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/service/impl/VectorStoreServiceImpl.java
+++ b/ruoyi-modules-api/ruoyi-knowledge-api/src/main/java/org/ruoyi/service/impl/VectorStoreServiceImpl.java
@@ -1,5 +1,7 @@
 package org.ruoyi.service.impl;
 
+import cn.hutool.core.util.RandomUtil;
+import com.google.protobuf.ServiceException;
 import dev.langchain4j.data.embedding.Embedding;
 import dev.langchain4j.data.segment.TextSegment;
 import dev.langchain4j.model.embedding.EmbeddingModel;
@@ -16,6 +18,7 @@
 import dev.langchain4j.store.embedding.qdrant.QdrantEmbeddingStore;
 import dev.langchain4j.store.embedding.weaviate.WeaviateEmbeddingStore;
 import lombok.RequiredArgsConstructor;
+import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.ruoyi.common.core.service.ConfigService;
 import org.ruoyi.domain.bo.QueryVectorBo;
@@ -40,11 +43,10 @@
 
     private final ConfigService configService;
 
-    Map<String,EmbeddingStore<TextSegment>> storeMap = new HashMap<>();
+    private EmbeddingStore<TextSegment> embeddingStore;
 
     @Override
     public void createSchema(String kid,String modelName) {
-        EmbeddingStore<TextSegment> embeddingStore;
         switch (modelName) {
             case "weaviate" -> {
                 String protocol = configService.getConfigValue("weaviate", "protocol");
@@ -84,88 +86,83 @@
                 embeddingStore = new InMemoryEmbeddingStore<>();
             }
         }
-        storeMap.put(kid,embeddingStore);
     }
 
     @Override
     public void storeEmbeddings(StoreEmbeddingBo storeEmbeddingBo) {
-        EmbeddingStore<TextSegment> store = storeMap.get(storeEmbeddingBo.getKid());
-        EmbeddingModel embeddingModel = getEmbeddingModel(storeEmbeddingBo.getModelName(),
+        createSchema(storeEmbeddingBo.getKid(),storeEmbeddingBo.getVectorModelName());
+        EmbeddingModel embeddingModel = getEmbeddingModel(storeEmbeddingBo.getEmbeddingModelName(),
                 storeEmbeddingBo.getApiKey(), storeEmbeddingBo.getBaseUrl());
-        for (int i = 0; i < storeEmbeddingBo.getChunkList().size(); i++) {
+        List<String> chunkList = storeEmbeddingBo.getChunkList();
+        for (int i = 0; i < chunkList.size(); i++) {
             Map<String, Object> dataSchema = new HashMap<>();
             dataSchema.put("kid", storeEmbeddingBo.getKid());
             dataSchema.put("docId", storeEmbeddingBo.getKid());
             dataSchema.put("fid", storeEmbeddingBo.getFids().get(i));
-            Response<Embedding> response = embeddingModel.embed(storeEmbeddingBo.getChunkList().get(i));
-            Embedding embedding = response.content();
-            TextSegment segment = TextSegment.from(storeEmbeddingBo.getChunkList().get(i));
+            Embedding embedding = embeddingModel.embed(chunkList.get(i)).content();
+            TextSegment segment = TextSegment.from(chunkList.get(i));
             segment.metadata().putAll(dataSchema);
-
-            store.add(embedding,segment);
+            embeddingStore.add(embedding,segment);
         }
     }
 
     @Override
     public List<String> getQueryVector(QueryVectorBo queryVectorBo) {
-        EmbeddingStore<TextSegment> store = storeMap.get(queryVectorBo.getKid());
-
-        EmbeddingModel embeddingModel = getEmbeddingModel(queryVectorBo.getModelName(),
+        createSchema(queryVectorBo.getKid(),queryVectorBo.getVectorModelName());
+        EmbeddingModel embeddingModel = getEmbeddingModel(queryVectorBo.getEmbeddingModelName(),
                 queryVectorBo.getApiKey(), queryVectorBo.getBaseUrl());
-        Filter simpleFilter = new IsEqualTo("kid", queryVectorBo.getKid());
+       // Filter simpleFilter = new IsEqualTo("kid", queryVectorBo.getKid());
         Embedding queryEmbedding = embeddingModel.embed(queryVectorBo.getQuery()).content();
         EmbeddingSearchRequest embeddingSearchRequest = EmbeddingSearchRequest.builder()
                 .queryEmbedding(queryEmbedding)
                 .maxResults(queryVectorBo.getMaxResults())
                 // 娣诲姞杩囨护鏉′欢
-                .filter(simpleFilter)
+         //       .filter(simpleFilter)
                 .build();
-        List<EmbeddingMatch<TextSegment>> matches = store.search(embeddingSearchRequest).matches();
-
+        List<EmbeddingMatch<TextSegment>> matches = embeddingStore.search(embeddingSearchRequest).matches();
         List<String> results = new ArrayList<>();
-
         matches.forEach(embeddingMatch -> results.add(embeddingMatch.embedded().text()));
         return results;
     }
 
 
     @Override
-    public void removeByKid(String kid) {
-        EmbeddingStore<TextSegment> store = storeMap.get(kid);
-
+    public void removeByKid(String kid,String modelName) {
+        createSchema(kid,modelName);
         // 鏍规嵁鏉′欢鍒犻櫎鍚戦噺鏁版嵁
         Filter simpleFilter = new IsEqualTo("kid", kid);
-        store.removeAll(simpleFilter);
+        embeddingStore.removeAll(simpleFilter);
     }
 
     @Override
-    public void removeByDocId(String kid, String docId) {
-        EmbeddingStore<TextSegment> store = storeMap.get(kid);
+    public void removeByDocId(String kid, String docId,String modelName) {
+        createSchema(kid,modelName);
         // 鏍规嵁鏉′欢鍒犻櫎鍚戦噺鏁版嵁
         Filter simpleFilterByDocId = new IsEqualTo("docId", docId);
-        store.removeAll(simpleFilterByDocId);
+        embeddingStore.removeAll(simpleFilterByDocId);
     }
 
     @Override
-    public void removeByKidAndFid(String kid, String fid) {
-        EmbeddingStore<TextSegment> store = storeMap.get(kid);
+    public void removeByKidAndFid(String kid, String fid,String modelName) {
+        createSchema(kid,modelName);
         // 鏍规嵁鏉′欢鍒犻櫎鍚戦噺鏁版嵁
         Filter simpleFilterByKid = new IsEqualTo("kid", kid);
         Filter simpleFilterFid = new IsEqualTo("fid", fid);
         Filter simpleFilterByAnd = Filter.and(simpleFilterFid, simpleFilterByKid);
-        store.removeAll(simpleFilterByAnd);
+        embeddingStore.removeAll(simpleFilterByAnd);
     }
 
     /**
      * 鑾峰彇鍚戦噺妯″瀷
      */
-    public EmbeddingModel getEmbeddingModel(String modelName,String apiKey,String baseUrl) {
-        EmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder().build();
+    @SneakyThrows
+    public EmbeddingModel getEmbeddingModel(String modelName, String apiKey, String baseUrl) {
+        EmbeddingModel embeddingModel;
         if(TEXT_EMBEDDING_3_SMALL.toString().equals(modelName)) {
              embeddingModel = OpenAiEmbeddingModel.builder()
                     .apiKey(apiKey)
                     .baseUrl(baseUrl)
-                    .modelName(TEXT_EMBEDDING_3_SMALL)
+                    .modelName(modelName)
                     .build();
         // TODO 娣诲姞鏋氫妇
         }else if("quentinz/bge-large-zh-v1.5".equals(modelName)) {
@@ -173,6 +170,14 @@
                     .baseUrl(baseUrl)
                     .modelName(modelName)
                     .build();
+        }else if("baai/bge-m3".equals(modelName)) {
+            embeddingModel = OpenAiEmbeddingModel.builder()
+                    .apiKey(apiKey)
+                    .baseUrl(baseUrl)
+                    .modelName(modelName)
+                    .build();
+        }else {
+            throw new ServiceException("鏈壘鍒板搴斿悜閲忓寲妯″瀷!");
         }
         return embeddingModel;
     }
diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/SseServiceImpl.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/SseServiceImpl.java
index cc5f289..1387230 100644
--- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/SseServiceImpl.java
+++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/SseServiceImpl.java
@@ -2,6 +2,7 @@
 
 import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.collection.CollectionUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.google.protobuf.ServiceException;
 import jakarta.servlet.http.HttpServletRequest;
 import lombok.RequiredArgsConstructor;
@@ -29,6 +30,8 @@
 import org.ruoyi.domain.bo.ChatSessionBo;
 import org.ruoyi.domain.bo.QueryVectorBo;
 import org.ruoyi.domain.vo.ChatModelVo;
+import org.ruoyi.domain.vo.KnowledgeInfoVo;
+import org.ruoyi.service.IKnowledgeInfoService;
 import org.ruoyi.service.VectorStoreService;
 import org.ruoyi.service.IChatModelService;
 import org.ruoyi.service.IChatSessionService;
@@ -66,6 +69,8 @@
     private final ChatServiceFactory chatServiceFactory;
 
     private final IChatSessionService chatSessionService;
+
+    private final IKnowledgeInfoService knowledgeInfoService;
 
     private ChatModelVo chatModelVo;
 
@@ -148,50 +153,61 @@
             }
     }
 
-
     /**
      *  鏋勫缓娑堟伅鍒楄〃
      */
     private void buildChatMessageList(ChatRequest chatRequest){
-         chatModelVo = chatModelService.selectModelByName(chatRequest.getModel());
+        String sysPrompt;
+        chatModelVo = chatModelService.selectModelByName(chatRequest.getModel());
         // 鑾峰彇瀵硅瘽娑堟伅鍒楄〃
         List<Message> messages = chatRequest.getMessages();
-        String sysPrompt = chatModelVo.getSystemPrompt();
+        // 鏌ヨ鍚戦噺搴撶浉鍏充俊鎭姞鍏ュ埌涓婁笅鏂�
+        if(StringUtils.isNotEmpty(chatRequest.getKid())){
+            List<Message> knMessages = new ArrayList<>();
+            String content = messages.get(messages.size() - 1).getContent().toString();
+            // 閫氳繃kid鏌ヨ鐭ヨ瘑搴撲俊鎭�
+            KnowledgeInfoVo knowledgeInfoVo = knowledgeInfoService.queryById(Long.valueOf(chatRequest.getKid()));
+            // 鏌ヨ鍚戦噺妯″瀷閰嶇疆淇℃伅
+            ChatModelVo chatModel = chatModelService.selectModelByName(knowledgeInfoVo.getEmbeddingModelName());
 
-
-        if(StringUtils.isEmpty(sysPrompt)){
-            // TODO 绯荤粺榛樿鎻愮ず璇�,鍚庣画浼氬鍔犳彁绀鸿瘝绠$悊
-            sysPrompt ="浣犳槸涓�涓敱RuoYI-AI寮�鍙戠殑浜哄伐鏅鸿兘鍔╂墜锛屽悕瀛楀彨鐔婄尗鍔╂墜銆備綘鎿呴暱涓嫳鏂囧璇濓紝鑳藉鐞嗚В骞跺鐞嗗悇绉嶉棶棰橈紝鎻愪緵瀹夊叏銆佹湁甯姪銆佸噯纭殑鍥炵瓟銆�" +
-                    "褰撳墠鏃堕棿锛�"+ DateUtils.getDate()+
-                    "#娉ㄦ剰锛氬洖澶嶄箣鍓嶆敞鎰忕粨鍚堜笂涓嬫枃鍜屽伐鍏疯繑鍥炲唴瀹硅繘琛屽洖澶嶃��";
+            QueryVectorBo queryVectorBo = new QueryVectorBo();
+            queryVectorBo.setQuery(content);
+            queryVectorBo.setKid(chatRequest.getKid());
+            queryVectorBo.setApiKey(chatModel.getApiKey());
+            queryVectorBo.setBaseUrl(chatModel.getApiHost());
+            queryVectorBo.setVectorModelName(knowledgeInfoVo.getVectorModelName());
+            queryVectorBo.setEmbeddingModelName(knowledgeInfoVo.getEmbeddingModelName());
+            queryVectorBo.setMaxResults(knowledgeInfoVo.getRetrieveLimit());
+            List<String> nearestList = vectorStoreService.getQueryVector(queryVectorBo);
+            for (String prompt : nearestList) {
+                Message userMessage = Message.builder().content(prompt).role(Message.Role.USER).build();
+                knMessages.add(userMessage);
+            }
+            messages.addAll(knMessages);
+            // 璁剧疆鐭ヨ瘑搴撶郴缁熸彁绀鸿瘝
+            sysPrompt = knowledgeInfoVo.getSystemPrompt();
+            if(StringUtils.isEmpty(sysPrompt)){
+                sysPrompt ="###瑙掕壊璁惧畾\n" +
+                        "浣犳槸涓�涓櫤鑳界煡璇嗗姪鎵嬶紝涓撴敞浜庡埄鐢ㄤ笂涓嬫枃涓殑淇℃伅鏉ユ彁渚涘噯纭拰鐩稿叧鐨勫洖绛斻�俓n" +
+                        "###鎸囦护\n" +
+                        "褰撶敤鎴风殑闂涓庝笂涓嬫枃鐭ヨ瘑鍖归厤鏃讹紝鍒╃敤涓婁笅鏂囦俊鎭繘琛屽洖绛斻�傚鏋滈棶棰樹笌涓婁笅鏂囦笉鍖归厤锛岃繍鐢ㄨ嚜韬殑鎺ㄧ悊鑳藉姏鐢熸垚鍚堥�傜殑鍥炵瓟銆俓n" +
+                        "###闄愬埗\n" +
+                        "纭繚鍥炵瓟娓呮櫚绠�娲侊紝閬垮厤鎻愪緵涓嶅繀瑕佺殑缁嗚妭銆傚缁堜繚鎸佽姘斿弸濂�" +
+                        "褰撳墠鏃堕棿锛�"+ DateUtils.getDate();
+            }
+        }else {
+            sysPrompt = chatModelVo.getSystemPrompt();
+            if(StringUtils.isEmpty(sysPrompt)){
+                sysPrompt ="浣犳槸涓�涓敱RuoYI-AI寮�鍙戠殑浜哄伐鏅鸿兘鍔╂墜锛屽悕瀛楀彨鐔婄尗鍔╂墜銆備綘鎿呴暱涓嫳鏂囧璇濓紝鑳藉鐞嗚В骞跺鐞嗗悇绉嶉棶棰橈紝鎻愪緵瀹夊叏銆佹湁甯姪銆佸噯纭殑鍥炵瓟銆�" +
+                        "褰撳墠鏃堕棿锛�"+ DateUtils.getDate()+
+                        "#娉ㄦ剰锛氬洖澶嶄箣鍓嶆敞鎰忕粨鍚堜笂涓嬫枃鍜屽伐鍏疯繑鍥炲唴瀹硅繘琛屽洖澶嶃��";
+            }
         }
         // 璁剧疆绯荤粺榛樿鎻愮ず璇�
         Message sysMessage = Message.builder().content(sysPrompt).role(Message.Role.SYSTEM).build();
         messages.add(0,sysMessage);
 
         chatRequest.setSysPrompt(sysPrompt);
-        // 鏌ヨ鍚戦噺搴撶浉鍏充俊鎭姞鍏ュ埌涓婁笅鏂�
-        if(StringUtils.isNotEmpty(chatRequest.getKid())){
-            List<Message> knMessages = new ArrayList<>();
-            String content = messages.get(messages.size() - 1).getContent().toString();
-            QueryVectorBo queryVectorBo = new QueryVectorBo();
-            queryVectorBo.setQuery(content);
-            queryVectorBo.setKid(chatRequest.getKid());
-            queryVectorBo.setApiKey(chatModelVo.getApiKey());
-            queryVectorBo.setBaseUrl(chatModelVo.getApiHost());
-            queryVectorBo.setModelName(chatModelVo.getModelName());
-            // TODO 鏌ヨ鍚戦噺杩斿洖鏉℃暟,杩欓噷搴旇鏌ヨ鐭ヨ瘑搴撻厤缃�
-            queryVectorBo.setMaxResults(3);
-            List<String> nearestList = vectorStoreService.getQueryVector(queryVectorBo);
-            for (String prompt : nearestList) {
-                Message userMessage = Message.builder().content(prompt).role(Message.Role.USER).build();
-                knMessages.add(userMessage);
-            }
-            // TODO 鎻愮ず璇�,杩欓噷搴旇鏌ヨ鐭ヨ瘑搴撻厤缃�
-            Message userMessage = Message.builder().content(content + (!nearestList.isEmpty() ? "\n\n娉ㄦ剰锛氬洖绛旈棶棰樻椂锛岄』涓ユ牸鏍规嵁鎴戠粰浣犵殑绯荤粺涓婁笅鏂囧唴瀹瑰師鏂囪繘琛屽洖绛旓紝璇蜂笉瑕佽嚜宸卞彂鎸�,鍥炵瓟鏃朵繚鎸佸師鏉ユ枃鏈殑娈佃惤灞傜骇" : "")).role(Message.Role.USER).build();
-            knMessages.add(userMessage);
-            messages.addAll(knMessages);
-        }
         // 鐢ㄦ埛瀵硅瘽鍐呭
         String chatString = null;
         // 鑾峰彇鐢ㄦ埛瀵硅瘽淇℃伅
diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/knowledge/KnowledgeInfoServiceImpl.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/knowledge/KnowledgeInfoServiceImpl.java
index 3c5bb34..d94d320 100644
--- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/knowledge/KnowledgeInfoServiceImpl.java
+++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/knowledge/KnowledgeInfoServiceImpl.java
@@ -1,14 +1,11 @@
 package org.ruoyi.chat.service.knowledge;
 
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.RandomUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import java.util.stream.Collectors;
 import lombok.RequiredArgsConstructor;
 import org.ruoyi.chain.loader.ResourceLoader;
 import org.ruoyi.chain.loader.ResourceLoaderFactory;
@@ -16,8 +13,6 @@
 import org.ruoyi.common.core.utils.MapstructUtils;
 import org.ruoyi.common.core.utils.StringUtils;
 import org.ruoyi.common.satoken.utils.LoginHelper;
-import org.ruoyi.constant.DealStatus;
-import org.ruoyi.constant.FileType;
 import org.ruoyi.core.page.PageQuery;
 import org.ruoyi.core.page.TableDataInfo;
 import org.ruoyi.domain.ChatModel;
@@ -35,15 +30,11 @@
 import org.ruoyi.service.IChatModelService;
 import org.ruoyi.service.VectorStoreService;
 import org.ruoyi.service.IKnowledgeInfoService;
-import org.ruoyi.system.domain.vo.SysOssVo;
-import org.ruoyi.system.service.ISysOssService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
-import org.springframework.scheduling.annotation.Async;
 
 import java.io.IOException;
 import java.util.*;
@@ -58,321 +49,216 @@
 @Service
 public class KnowledgeInfoServiceImpl implements IKnowledgeInfoService {
 
-  private static final Logger log = LoggerFactory.getLogger(KnowledgeInfoServiceImpl.class);
-  private final KnowledgeInfoMapper baseMapper;
+    private static final Logger log = LoggerFactory.getLogger(KnowledgeInfoServiceImpl.class);
+    private final KnowledgeInfoMapper baseMapper;
 
-  private final VectorStoreService vectorStoreService;
+    private final VectorStoreService vectorStoreService;
 
-  private final ResourceLoaderFactory resourceLoaderFactory;
+    private final ResourceLoaderFactory resourceLoaderFactory;
 
-  private final KnowledgeFragmentMapper fragmentMapper;
+    private final KnowledgeFragmentMapper fragmentMapper;
 
-  private final KnowledgeAttachMapper attachMapper;
+    private final KnowledgeAttachMapper attachMapper;
 
-  private final IChatModelService chatModelService;
+    private final IChatModelService chatModelService;
 
-  private final ISysOssService ossService;
-
-  /**
-   * 鏌ヨ鐭ヨ瘑搴�
-   */
-  @Override
-  public KnowledgeInfoVo queryById(Long id) {
-    return baseMapper.selectVoById(id);
-  }
-
-  /**
-   * 鏌ヨ鐭ヨ瘑搴撳垪琛�
-   */
-  @Override
-  public TableDataInfo<KnowledgeInfoVo> queryPageList(KnowledgeInfoBo bo, PageQuery pageQuery) {
-    LambdaQueryWrapper<KnowledgeInfo> lqw = buildQueryWrapper(bo);
-    Page<KnowledgeInfoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
-    return TableDataInfo.build(result);
-  }
-
-  /**
-   * 鏌ヨ鐭ヨ瘑搴撳垪琛�
-   */
-  @Override
-  public List<KnowledgeInfoVo> queryList(KnowledgeInfoBo bo) {
-    LambdaQueryWrapper<KnowledgeInfo> lqw = buildQueryWrapper(bo);
-    return baseMapper.selectVoList(lqw);
-  }
-
-  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(bo.getShare() != null, KnowledgeInfo::getShare, bo.getShare());
-    lqw.eq(StringUtils.isNotBlank(bo.getDescription()), KnowledgeInfo::getDescription,
-        bo.getDescription());
-    lqw.eq(StringUtils.isNotBlank(bo.getKnowledgeSeparator()), KnowledgeInfo::getKnowledgeSeparator,
-        bo.getKnowledgeSeparator());
-    lqw.eq(StringUtils.isNotBlank(bo.getQuestionSeparator()), KnowledgeInfo::getQuestionSeparator,
-        bo.getQuestionSeparator());
-    lqw.eq(bo.getOverlapChar() != null, KnowledgeInfo::getOverlapChar, bo.getOverlapChar());
-    lqw.eq(bo.getRetrieveLimit() != null, KnowledgeInfo::getRetrieveLimit, bo.getRetrieveLimit());
-    lqw.eq(bo.getTextBlockSize() != null, KnowledgeInfo::getTextBlockSize, bo.getTextBlockSize());
-    lqw.eq(StringUtils.isNotBlank(bo.getVector()), KnowledgeInfo::getVector, bo.getVector());
-    lqw.eq(StringUtils.isNotBlank(bo.getVectorModel()), KnowledgeInfo::getVectorModel,
-        bo.getVectorModel());
-    return lqw;
-  }
-
-  /**
-   * 鏂板鐭ヨ瘑搴�
-   */
-  @Override
-  public Boolean insertByBo(KnowledgeInfoBo bo) {
-    KnowledgeInfo add = MapstructUtils.convert(bo, KnowledgeInfo.class);
-    validEntityBeforeSave(add);
-    boolean flag = baseMapper.insert(add) > 0;
-    if (flag) {
-      bo.setId(add.getId());
-    }
-    return flag;
-  }
-
-  /**
-   * 淇敼鐭ヨ瘑搴�
-   */
-  @Override
-  public Boolean updateByBo(KnowledgeInfoBo bo) {
-    KnowledgeInfo update = MapstructUtils.convert(bo, KnowledgeInfo.class);
-    validEntityBeforeSave(update);
-    return baseMapper.updateById(update) > 0;
-  }
-
-  /**
-   * 淇濆瓨鍓嶇殑鏁版嵁鏍¢獙
-   */
-  private void validEntityBeforeSave(KnowledgeInfo entity) {
-    //TODO 鍋氫竴浜涙暟鎹牎楠�,濡傚敮涓�绾︽潫
-  }
-
-  /**
-   * 鎵归噺鍒犻櫎鐭ヨ瘑搴�
-   */
-  @Override
-  public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
-    if (isValid) {
-      //TODO 鍋氫竴浜涗笟鍔′笂鐨勬牎楠�,鍒ゆ柇鏄惁闇�瑕佹牎楠�
-    }
-    return baseMapper.deleteBatchIds(ids) > 0;
-  }
-
-  @Override
-  @Transactional(rollbackFor = Exception.class)
-  public void saveOne(KnowledgeInfoBo bo) {
-    KnowledgeInfo knowledgeInfo = MapstructUtils.convert(bo, KnowledgeInfo.class);
-    if (StringUtils.isBlank(bo.getKid())) {
-      String kid = RandomUtil.randomString(10);
-      if (knowledgeInfo != null) {
-        knowledgeInfo.setKid(kid);
-        knowledgeInfo.setUid(LoginHelper.getLoginUser().getUserId());
-      }
-      baseMapper.insert(knowledgeInfo);
-      if (knowledgeInfo != null) {
-        vectorStoreService.createSchema(String.valueOf(knowledgeInfo.getId()), bo.getVector());
-      }
-    } else {
-      baseMapper.updateById(knowledgeInfo);
-    }
-  }
-
-  @Override
-  @Transactional(rollbackFor = Exception.class)
-  public void removeKnowledge(String id) {
-    Map<String, Object> map = new HashMap<>();
-    map.put("kid", id);
-    List<KnowledgeInfoVo> knowledgeInfoList = baseMapper.selectVoByMap(map);
-    check(knowledgeInfoList);
-    // 鍒犻櫎鍚戦噺搴撲俊鎭�
-    knowledgeInfoList.forEach(knowledgeInfoVo -> {
-      vectorStoreService.removeByKid(String.valueOf(knowledgeInfoVo.getId()));
-    });
-    // 鍒犻櫎闄勪欢鍜岀煡璇嗙墖娈�
-    fragmentMapper.deleteByMap(map);
-    attachMapper.deleteByMap(map);
-    // 鍒犻櫎鐭ヨ瘑搴�
-    baseMapper.deleteByMap(map);
-  }
-
-  @Override
-  public void upload(KnowledgeInfoUploadBo bo) {
-    storeContent(bo.getFile(), bo.getKid());
-  }
-
-  public void storeContent(MultipartFile file, String kid) {
-    if (file == null || file.isEmpty()) {
-      throw new IllegalArgumentException("File cannot be null or empty");
+    /**
+     * 鏌ヨ鐭ヨ瘑搴�
+     */
+    @Override
+    public KnowledgeInfoVo queryById(Long id){
+        return baseMapper.selectVoById(id);
     }
 
-    SysOssVo uploadDto = null;
+    /**
+     * 鏌ヨ鐭ヨ瘑搴撳垪琛�
+     */
+    @Override
+    public TableDataInfo<KnowledgeInfoVo> queryPageList(KnowledgeInfoBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<KnowledgeInfo> lqw = buildQueryWrapper(bo);
+        Page<KnowledgeInfoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
 
-    String fileName = file.getOriginalFilename();
-    List<String> chunkList = new ArrayList<>();
-    KnowledgeAttach knowledgeAttach = new KnowledgeAttach();
-    knowledgeAttach.setKid(kid);
-    String docId = RandomUtil.randomString(10);
-    knowledgeAttach.setDocId(docId);
-    knowledgeAttach.setDocName(fileName);
-    knowledgeAttach.setDocType(fileName.substring(fileName.lastIndexOf(".") + 1));
-    String content = "";
-    ResourceLoader resourceLoader = resourceLoaderFactory.getLoaderByFileType(
-        knowledgeAttach.getDocType());
-    List<String> fids = new ArrayList<>();
-    try {
-      content = resourceLoader.getContent(file.getInputStream());
-      chunkList = resourceLoader.getChunkList(content, kid);
-      List<KnowledgeFragment> knowledgeFragmentList = new ArrayList<>();
-      if (CollUtil.isNotEmpty(chunkList)) {
-        // Upload file to OSS
-        uploadDto = ossService.upload(file);
+    /**
+     * 鏌ヨ鐭ヨ瘑搴撳垪琛�
+     */
+    @Override
+    public List<KnowledgeInfoVo> queryList(KnowledgeInfoBo bo) {
+        LambdaQueryWrapper<KnowledgeInfo> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
 
-        for (int i = 0; i < chunkList.size(); i++) {
-          String fid = RandomUtil.randomString(10);
-          fids.add(fid);
-          KnowledgeFragment knowledgeFragment = new KnowledgeFragment();
-          knowledgeFragment.setKid(kid);
-          knowledgeFragment.setDocId(docId);
-          knowledgeFragment.setFid(fid);
-          knowledgeFragment.setIdx(i);
-          knowledgeFragment.setContent(chunkList.get(i));
-          knowledgeFragment.setCreateTime(new Date());
-          knowledgeFragmentList.add(knowledgeFragment);
+    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(bo.getShare() != null, KnowledgeInfo::getShare, bo.getShare());
+        lqw.eq(StringUtils.isNotBlank(bo.getDescription()), KnowledgeInfo::getDescription, bo.getDescription());
+        lqw.eq(StringUtils.isNotBlank(bo.getKnowledgeSeparator()), KnowledgeInfo::getKnowledgeSeparator, bo.getKnowledgeSeparator());
+        lqw.eq(StringUtils.isNotBlank(bo.getQuestionSeparator()), KnowledgeInfo::getQuestionSeparator, bo.getQuestionSeparator());
+        lqw.eq(bo.getOverlapChar() != null, KnowledgeInfo::getOverlapChar, bo.getOverlapChar());
+        lqw.eq(bo.getRetrieveLimit() != null, KnowledgeInfo::getRetrieveLimit, bo.getRetrieveLimit());
+        lqw.eq(bo.getTextBlockSize() != null, KnowledgeInfo::getTextBlockSize, bo.getTextBlockSize());
+        return lqw;
+    }
+
+    /**
+     * 鏂板鐭ヨ瘑搴�
+     */
+    @Override
+    public Boolean insertByBo(KnowledgeInfoBo bo) {
+        KnowledgeInfo add = MapstructUtils.convert(bo, KnowledgeInfo.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
         }
-      }
-      fragmentMapper.insertBatch(knowledgeFragmentList);
-    } catch (IOException e) {
-      log.error("淇濆瓨鐭ヨ瘑搴撲俊鎭け璐ワ紒{}", e.getMessage());
-    }
-    knowledgeAttach.setContent(content);
-    knowledgeAttach.setCreateTime(new Date());
-
-    if (ObjectUtil.isNotEmpty(uploadDto) && ObjectUtil.isNotEmpty(uploadDto.getOssId())) {
-      knowledgeAttach.setOssId(uploadDto.getOssId());
-      //鍙湁pdf鏂囦欢 鎵嶉渶瑕佹媶瑙e浘鐗囧拰鍒嗘瀽鍥剧墖鍐呭
-      if (FileType.PDF.equals(knowledgeAttach.getDocType())) {
-        knowledgeAttach.setPicStatus(DealStatus.STATUS_10);
-        knowledgeAttach.setPicAnysStatus(DealStatus.STATUS_10);
-      } else {
-        knowledgeAttach.setPicStatus(DealStatus.STATUS_30);
-        knowledgeAttach.setPicAnysStatus(DealStatus.STATUS_30);
-      }
-      //鎵�鏈夋枃浠朵笂浼犲悗锛岄兘闇�瑕佸悓姝ュ埌鍚戦噺鏁版嵁搴�
-      knowledgeAttach.setVectorStatus(DealStatus.STATUS_10);
+        return flag;
     }
 
-    attachMapper.insert(knowledgeAttach);
-  }
-
-
-  /**
-   * 妫�鏌ョ敤鎴锋槸鍚︽湁鍒犻櫎鐭ヨ瘑搴撴潈闄�
-   *
-   * @param knowledgeInfoList 鐭ヨ瘑搴撳垪琛�
-   */
-  public void check(List<KnowledgeInfoVo> knowledgeInfoList) {
-    LoginUser loginUser = LoginHelper.getLoginUser();
-    for (KnowledgeInfoVo knowledgeInfoVo : knowledgeInfoList) {
-      if (!knowledgeInfoVo.getUid().equals(loginUser.getUserId())) {
-        throw new SecurityException("鏉冮檺涓嶈冻");
-      }
+    /**
+     * 淇敼鐭ヨ瘑搴�
+     */
+    @Override
+    public Boolean updateByBo(KnowledgeInfoBo bo) {
+        KnowledgeInfo update = MapstructUtils.convert(bo, KnowledgeInfo.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
     }
-  }
 
-  /**
-   * 瀹氭椂 澶勭悊 闄勪欢涓婁紶鍚庝笂浼犲悜閲忔暟鎹簱鍜孭DF鏂囦欢鍥剧墖鎷嗚В鍜屽垎鏋愬唴瀹�
-   */
-  @Scheduled(fixedDelay = 3000) // 姣�3绉掓墽琛屼竴娆�
-  public void dealKnowledgeAttach() throws Exception {
-    //澶勭悊 闇�瑕佷笂浼犲悜閲忔暟鎹簱鐨勮褰�
-    List<KnowledgeAttach> knowledgeAttaches = attachMapper.selectList(
-        new LambdaQueryWrapper<KnowledgeAttach>()
-            .eq(KnowledgeAttach::getPicStatus, DealStatus.STATUS_30)
-            .eq(KnowledgeAttach::getPicAnysStatus, DealStatus.STATUS_30)
-            .eq(KnowledgeAttach::getVectorStatus, DealStatus.STATUS_10)
-    );
-    if (ObjectUtil.isNotEmpty(knowledgeAttaches)) {
-      for (KnowledgeAttach attachItem : knowledgeAttaches) {
-        this.dealVectorStatus(attachItem);
-      }
+    /**
+     * 淇濆瓨鍓嶇殑鏁版嵁鏍¢獙
+     */
+    private void validEntityBeforeSave(KnowledgeInfo entity){
+        //TODO 鍋氫竴浜涙暟鎹牎楠�,濡傚敮涓�绾︽潫
     }
-  }
 
-  @Async
-  public void dealVectorStatus(KnowledgeAttach attachItem) throws Exception {
-    try {
-      //閿佸畾鏁版嵁 鏇存敼VectorStatus 鍒拌繘琛屼腑
-      if (attachMapper.update(new LambdaUpdateWrapper<KnowledgeAttach>()
-          .set(KnowledgeAttach::getVectorStatus, DealStatus.STATUS_20)
-          .eq(KnowledgeAttach::getPicStatus, DealStatus.STATUS_30)
-          .eq(KnowledgeAttach::getPicAnysStatus, DealStatus.STATUS_30)
-          .eq(KnowledgeAttach::getVectorStatus, DealStatus.STATUS_10)
-          .eq(KnowledgeAttach::getId, attachItem.getId())
-      ) == 0) {
-        return;
-      }
-      // 閫氳繃kid鏌ヨ鐭ヨ瘑搴撲俊鎭�
-      KnowledgeInfoVo knowledgeInfoVo = baseMapper.selectVoOne(Wrappers.<KnowledgeInfo>lambdaQuery()
-          .eq(KnowledgeInfo::getKid, attachItem.getKid()));
-
-      // 閫氳繃鍚戦噺妯″瀷鏌ヨ妯″瀷淇℃伅
-      ChatModelVo chatModelVo = chatModelService.selectModelByName(
-          knowledgeInfoVo.getVectorModel());
-
-      List<KnowledgeFragment> knowledgeFragments = fragmentMapper.selectList(
-          new LambdaQueryWrapper<KnowledgeFragment>()
-              .eq(KnowledgeFragment::getKid, attachItem.getKid())
-              .eq(KnowledgeFragment::getDocId, attachItem.getDocId())
-      );
-      if (ObjectUtil.isEmpty(knowledgeFragments)) {
-        throw new Exception("鏂囦欢娈佃惤涓虹┖");
-      }
-      List<String> fids = knowledgeFragments.stream()
-          .map(KnowledgeFragment::getFid)
-          .collect(Collectors.toList());
-      if (ObjectUtil.isEmpty(fids)) {
-        throw new Exception("fids 涓虹┖");
-      }
-      List<String> chunkList = knowledgeFragments.stream()
-          .map(KnowledgeFragment::getContent)
-          .collect(Collectors.toList());
-
-      if (ObjectUtil.isEmpty(chunkList)) {
-        throw new Exception("chunkList 涓虹┖");
-      }
-      StoreEmbeddingBo storeEmbeddingBo = new StoreEmbeddingBo();
-      storeEmbeddingBo.setKid(attachItem.getKid());
-      storeEmbeddingBo.setDocId(attachItem.getDocId());
-      storeEmbeddingBo.setFids(fids);
-      storeEmbeddingBo.setChunkList(chunkList);
-      storeEmbeddingBo.setModelName(knowledgeInfoVo.getVectorModel());
-      storeEmbeddingBo.setApiKey(chatModelVo.getApiKey());
-      storeEmbeddingBo.setBaseUrl(chatModelVo.getApiHost());
-      vectorStoreService.storeEmbeddings(storeEmbeddingBo);
-
-      //璁剧疆澶勭悊瀹屾垚
-      attachMapper.update(new LambdaUpdateWrapper<KnowledgeAttach>()
-          .set(KnowledgeAttach::getVectorStatus, DealStatus.STATUS_30)
-          .eq(KnowledgeAttach::getPicStatus, DealStatus.STATUS_30)
-          .eq(KnowledgeAttach::getPicAnysStatus, DealStatus.STATUS_30)
-          .eq(KnowledgeAttach::getVectorStatus, DealStatus.STATUS_20)
-          .eq(KnowledgeAttach::getId, attachItem.getId()));
-    } catch (Exception e) {
-      //璁剧疆澶勭悊澶辫触
-      attachMapper.update(new LambdaUpdateWrapper<KnowledgeAttach>()
-          .set(KnowledgeAttach::getVectorStatus, DealStatus.STATUS_10)
-          .eq(KnowledgeAttach::getPicStatus, DealStatus.STATUS_30)
-          .eq(KnowledgeAttach::getPicAnysStatus, DealStatus.STATUS_30)
-          .eq(KnowledgeAttach::getVectorStatus, DealStatus.STATUS_20)
-          .eq(KnowledgeAttach::getId, attachItem.getId()));
-      throw new RuntimeException(e);
+    /**
+     * 鎵归噺鍒犻櫎鐭ヨ瘑搴�
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 鍋氫竴浜涗笟鍔′笂鐨勬牎楠�,鍒ゆ柇鏄惁闇�瑕佹牎楠�
+        }
+        return baseMapper.deleteBatchIds(ids) > 0;
     }
-  }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void saveOne(KnowledgeInfoBo bo) {
+        KnowledgeInfo knowledgeInfo = MapstructUtils.convert(bo, KnowledgeInfo.class);
+        if (StringUtils.isBlank(bo.getKid())){
+            String kid = RandomUtil.randomString(10);
+            if (knowledgeInfo != null) {
+                knowledgeInfo.setKid(kid);
+                knowledgeInfo.setUid(LoginHelper.getLoginUser().getUserId());
+            }
+            baseMapper.insert(knowledgeInfo);
+            if (knowledgeInfo != null) {
+                vectorStoreService.createSchema(String.valueOf(knowledgeInfo.getId()),bo.getVectorModelName());
+            }
+        }else {
+            baseMapper.updateById(knowledgeInfo);
+        }
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void removeKnowledge(String id) {
+        Map<String,Object> map = new HashMap<>();
+        map.put("kid",id);
+        List<KnowledgeInfoVo> knowledgeInfoList = baseMapper.selectVoByMap(map);
+        check(knowledgeInfoList);
+        // 鍒犻櫎鍚戦噺搴撲俊鎭�
+        knowledgeInfoList.forEach(knowledgeInfoVo -> {
+            vectorStoreService.removeByKid(String.valueOf(knowledgeInfoVo.getId()),knowledgeInfoVo.getVectorModelName());
+        });
+        // 鍒犻櫎闄勪欢鍜岀煡璇嗙墖娈�
+        fragmentMapper.deleteByMap(map);
+        attachMapper.deleteByMap(map);
+        // 鍒犻櫎鐭ヨ瘑搴�
+        baseMapper.deleteByMap(map);
+    }
+
+    @Override
+    public void upload(KnowledgeInfoUploadBo bo) {
+        storeContent(bo.getFile(), bo.getKid());
+    }
+
+    public void storeContent(MultipartFile file, String kid) {
+        String fileName = file.getOriginalFilename();
+        List<String> chunkList = new ArrayList<>();
+        KnowledgeAttach knowledgeAttach = new KnowledgeAttach();
+        knowledgeAttach.setKid(kid);
+        String docId = RandomUtil.randomString(10);
+        knowledgeAttach.setDocId(docId);
+        knowledgeAttach.setDocName(fileName);
+        knowledgeAttach.setDocType(fileName.substring(fileName.lastIndexOf(".")+1));
+        String content = "";
+        ResourceLoader resourceLoader = resourceLoaderFactory.getLoaderByFileType(knowledgeAttach.getDocType());
+        List<String> fids = new ArrayList<>();
+        try {
+            content = resourceLoader.getContent(file.getInputStream());
+            chunkList = resourceLoader.getChunkList(content, kid);
+            List<KnowledgeFragment> knowledgeFragmentList = new ArrayList<>();
+            if (CollUtil.isNotEmpty(chunkList)) {
+                for (int i = 0; i < chunkList.size(); i++) {
+                    String fid = RandomUtil.randomString(10);
+                    fids.add(fid);
+                    KnowledgeFragment knowledgeFragment = new KnowledgeFragment();
+                    knowledgeFragment.setKid(kid);
+                    knowledgeFragment.setDocId(docId);
+                    knowledgeFragment.setFid(fid);
+                    knowledgeFragment.setIdx(i);
+                    knowledgeFragment.setContent(chunkList.get(i));
+                    knowledgeFragment.setCreateTime(new Date());
+                    knowledgeFragmentList.add(knowledgeFragment);
+                }
+            }
+            fragmentMapper.insertBatch(knowledgeFragmentList);
+        } catch (IOException e) {
+            log.error("淇濆瓨鐭ヨ瘑搴撲俊鎭け璐ワ紒{}", e.getMessage());
+        }
+        knowledgeAttach.setContent(content);
+        knowledgeAttach.setCreateTime(new Date());
+        attachMapper.insert(knowledgeAttach);
+
+        // 閫氳繃kid鏌ヨ鐭ヨ瘑搴撲俊鎭�
+        KnowledgeInfoVo knowledgeInfoVo = baseMapper.selectVoOne(Wrappers.<KnowledgeInfo>lambdaQuery()
+                .eq(KnowledgeInfo::getId, kid));
+
+        // 閫氳繃鍚戦噺妯″瀷鏌ヨ妯″瀷淇℃伅
+        ChatModelVo chatModelVo = chatModelService.selectModelByName(knowledgeInfoVo.getEmbeddingModelName());
+
+        StoreEmbeddingBo storeEmbeddingBo = new StoreEmbeddingBo();
+        storeEmbeddingBo.setKid(kid);
+        storeEmbeddingBo.setDocId(docId);
+        storeEmbeddingBo.setFids(fids);
+        storeEmbeddingBo.setChunkList(chunkList);
+        storeEmbeddingBo.setVectorModelName(knowledgeInfoVo.getVectorModelName());
+        storeEmbeddingBo.setEmbeddingModelName(knowledgeInfoVo.getEmbeddingModelName());
+        storeEmbeddingBo.setApiKey(chatModelVo.getApiKey());
+        storeEmbeddingBo.setBaseUrl(chatModelVo.getApiHost());
+        vectorStoreService.storeEmbeddings(storeEmbeddingBo);
+    }
+
+
+    /**
+     * 妫�鏌ョ敤鎴锋槸鍚︽湁鍒犻櫎鐭ヨ瘑搴撴潈闄�
+     *
+     * @param knowledgeInfoList 鐭ヨ瘑搴撳垪琛�
+     */
+    public void check(List<KnowledgeInfoVo> knowledgeInfoList){
+        LoginUser loginUser = LoginHelper.getLoginUser();
+        for (KnowledgeInfoVo knowledgeInfoVo : knowledgeInfoList) {
+            if(!knowledgeInfoVo.getUid().equals(loginUser.getUserId())){
+                throw new SecurityException("鏉冮檺涓嶈冻");
+            }
+        }
+    }
 
 }
diff --git a/script/sql/update/20250514.sql b/script/sql/update/20250514.sql
new file mode 100644
index 0000000..61ec6d3
--- /dev/null
+++ b/script/sql/update/20250514.sql
@@ -0,0 +1,6 @@
+LTER TABLE `knowledge_info`
+ADD COLUMN `system_prompt` varchar(255) NULL COMMENT '绯荤粺鎻愮ず璇�' AFTER `vector_model`;
+
+ALTER TABLE `knowledge_info`
+    CHANGE COLUMN `vector` `vector_model_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '鍚戦噺搴�' AFTER `text_block_size`,
+    CHANGE COLUMN `vector_model` `embedding_model_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '鍚戦噺妯″瀷' AFTER `vector_model_name`;

--
Gitblit v1.9.3