Переглянути джерело

LangChainMilvusService向量数据库操作

lamphua 1 день тому
джерело
коміт
73b7bd7b0d

+ 108
- 0
llm-back/cmc-agent/pom.xml Переглянути файл

@@ -0,0 +1,108 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<project xmlns="http://maven.apache.org/POM/4.0.0"
3
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5
+    <parent>
6
+        <artifactId>ruoyi</artifactId>
7
+        <groupId>com.ruoyi</groupId>
8
+        <version>3.8.9</version>
9
+    </parent>
10
+    <modelVersion>4.0.0</modelVersion>
11
+    <packaging>jar</packaging>
12
+    <artifactId>cmc-agent</artifactId>
13
+
14
+    <description>
15
+        cmc智能体
16
+    </description>
17
+
18
+    <dependencies>
19
+
20
+        <dependency>
21
+            <groupId>com.ruoyi</groupId>
22
+            <artifactId>ruoyi-framework</artifactId>
23
+        </dependency>
24
+        <dependency>
25
+            <groupId>com.ruoyi</groupId>
26
+            <artifactId>ruoyi-system</artifactId>
27
+        </dependency>
28
+        <dependency>
29
+            <groupId>com.ruoyi</groupId>
30
+            <artifactId>ruoyi-common</artifactId>
31
+        </dependency>
32
+
33
+        <!-- spring-boot-devtools -->
34
+        <dependency>
35
+            <groupId>org.springframework.boot</groupId>
36
+            <artifactId>spring-boot-devtools</artifactId>
37
+            <optional>true</optional> <!-- 表示依赖不会传递 -->
38
+        </dependency>
39
+
40
+        <!-- 向量数据库-->
41
+        <dependency>
42
+            <groupId>io.milvus</groupId>
43
+            <artifactId>milvus-sdk-java</artifactId>
44
+            <version>2.3.3</version>
45
+        </dependency>
46
+
47
+        <!-- LangChain4j -->
48
+        <dependency>
49
+            <groupId>dev.langchain4j</groupId>
50
+            <artifactId>langchain4j</artifactId>
51
+            <version>0.35.0</version>
52
+        </dependency>
53
+
54
+        <!-- LangChain4j Milvus 集成 -->
55
+        <dependency>
56
+            <groupId>dev.langchain4j</groupId>
57
+            <artifactId>langchain4j-milvus</artifactId>
58
+            <version>0.35.0</version> <!-- 版本需与核心一致 -->
59
+        </dependency>
60
+
61
+        <!-- LangChain4j embedding 集成 -->
62
+        <dependency>
63
+            <groupId>dev.langchain4j</groupId>
64
+            <artifactId>langchain4j-embeddings-bge-small-zh-v15</artifactId>
65
+            <version>0.35.0</version>
66
+        </dependency>
67
+
68
+        <!-- 解析PDF -->
69
+        <dependency>
70
+            <groupId>org.apache.pdfbox</groupId>
71
+            <artifactId>pdfbox</artifactId>
72
+            <version>3.0.3</version>
73
+        </dependency>
74
+
75
+
76
+    </dependencies>
77
+
78
+    <build>
79
+        <plugins>
80
+            <plugin>
81
+                <groupId>org.springframework.boot</groupId>
82
+                <artifactId>spring-boot-maven-plugin</artifactId>
83
+                <version>2.5.15</version>
84
+                <configuration>
85
+                    <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
86
+                </configuration>
87
+                <executions>
88
+                    <execution>
89
+                        <goals>
90
+                            <goal>repackage</goal>
91
+                        </goals>
92
+                    </execution>
93
+                </executions>
94
+            </plugin>
95
+            <plugin>   
96
+                <groupId>org.apache.maven.plugins</groupId>   
97
+                <artifactId>maven-war-plugin</artifactId>   
98
+                <version>3.1.0</version>   
99
+                <configuration>
100
+                    <failOnMissingWebXml>false</failOnMissingWebXml>
101
+                    <warName>${project.artifactId}</warName>
102
+                </configuration>   
103
+           </plugin>   
104
+        </plugins>
105
+        <finalName>${project.artifactId}</finalName>
106
+    </build>
107
+
108
+</project>

+ 63
- 0
llm-back/cmc-agent/src/main/java/com/cmc/agent/controller/KnowLedgeController.java Переглянути файл

@@ -0,0 +1,63 @@
1
+package com.cmc.agent.controller;
2
+
3
+import com.ruoyi.common.config.RuoYiConfig;
4
+import com.ruoyi.common.core.controller.BaseController;
5
+import com.ruoyi.common.core.domain.AjaxResult;
6
+import com.cmc.agent.service.LangChainMilvusService;
7
+import dev.langchain4j.model.embedding.onnx.bgesmallzhv15.BgeSmallZhV15EmbeddingModel;
8
+import dev.langchain4j.model.embedding.EmbeddingModel;
9
+import org.springframework.web.bind.annotation.*;
10
+import org.springframework.web.multipart.MultipartFile;
11
+
12
+import java.io.File;
13
+import java.io.IOException;
14
+
15
+/**
16
+ * cmc知识库Controller
17
+ * 
18
+ * @author cmc
19
+ * @date 2025-04-08
20
+ */
21
+@RestController
22
+@RequestMapping("/llm/knowledge")
23
+public class KnowLedgeController extends BaseController
24
+{
25
+    private static final EmbeddingModel embeddingModel = new BgeSmallZhV15EmbeddingModel();
26
+
27
+    /**
28
+     * 新建知识库
29
+     */
30
+    @PostMapping("/create")
31
+    public AjaxResult createKnowLedgeBase(String collectionName)
32
+    {
33
+        LangChainMilvusService langChainMilvusService = new LangChainMilvusService(
34
+                "localhost",
35
+                19530,
36
+                collectionName,
37
+                embeddingModel);
38
+        langChainMilvusService.createCollection(512);
39
+        return success();
40
+    }
41
+
42
+    /**
43
+     * 插入知识库文件
44
+     */
45
+    @PostMapping("/insert")
46
+    public AjaxResult insertKnowledge(MultipartFile file, String collectionName) throws IOException {
47
+        LangChainMilvusService langChainMilvusService = new LangChainMilvusService(
48
+                "localhost",
49
+                19530,
50
+                collectionName,
51
+                embeddingModel);
52
+
53
+        File profilePath = new File( RuoYiConfig.getProfile() + "/upload/knowledge");
54
+        if (!profilePath.exists())
55
+            profilePath.mkdirs();
56
+        File transferFile = new File( profilePath + "/" + file.getOriginalFilename());
57
+        if (!transferFile.exists())
58
+            file.transferTo(transferFile);
59
+        langChainMilvusService.insertLangchainEmbeddingDocument(transferFile);
60
+        return success();
61
+    }
62
+
63
+}

+ 45
- 0
llm-back/cmc-agent/src/main/java/com/cmc/agent/controller/RagController.java Переглянути файл

@@ -0,0 +1,45 @@
1
+package com.cmc.agent.controller;
2
+
3
+import com.ruoyi.common.core.controller.BaseController;
4
+import com.ruoyi.common.core.domain.AjaxResult;
5
+import com.cmc.agent.service.LangChainMilvusService;
6
+import dev.langchain4j.model.embedding.EmbeddingModel;
7
+import dev.langchain4j.model.embedding.onnx.bgesmallzhv15.BgeSmallZhV15EmbeddingModel;
8
+import org.springframework.web.bind.annotation.PostMapping;
9
+import org.springframework.web.bind.annotation.RequestMapping;
10
+import org.springframework.web.bind.annotation.RestController;
11
+
12
+import java.io.IOException;
13
+import java.util.List;
14
+
15
+/**
16
+ * cmc知识库Controller
17
+ * 
18
+ * @author cmc
19
+ * @date 2025-04-08
20
+ */
21
+@RestController
22
+@RequestMapping("/llm/rag")
23
+public class RagController extends BaseController
24
+{
25
+    private static final EmbeddingModel embeddingModel = new BgeSmallZhV15EmbeddingModel();
26
+
27
+    /**
28
+     * 增强检索生成回答
29
+     */
30
+    @PostMapping("/answer")
31
+    public AjaxResult answerWithRAG(String question, String collectionName) throws IOException {
32
+        LangChainMilvusService langChainMilvusService = new LangChainMilvusService(
33
+                "localhost",
34
+                19530,
35
+                collectionName,
36
+                embeddingModel);
37
+
38
+        // 2. Milvus检索
39
+        List<String> contexts = langChainMilvusService.retrieveFromMilvus(question, 3);
40
+
41
+        // 3. 调用本地LLM或HTTP服务
42
+        return success(langChainMilvusService.generateAnswer(question, contexts));
43
+    }
44
+
45
+}

+ 194
- 0
llm-back/cmc-agent/src/main/java/com/cmc/agent/service/LangChainMilvusService.java Переглянути файл

@@ -0,0 +1,194 @@
1
+package com.cmc.agent.service;
2
+
3
+import com.google.gson.Gson;
4
+import dev.langchain4j.data.document.Document;
5
+import dev.langchain4j.data.document.parser.apache.pdfbox.ApachePdfBoxDocumentParser;
6
+import dev.langchain4j.data.document.splitter.DocumentByParagraphSplitter;
7
+import dev.langchain4j.data.segment.TextSegment;
8
+import dev.langchain4j.model.embedding.EmbeddingModel;
9
+
10
+import io.milvus.client.MilvusServiceClient;
11
+import io.milvus.grpc.DataType;
12
+import io.milvus.grpc.MutationResult;
13
+import io.milvus.grpc.SearchResults;
14
+import io.milvus.param.ConnectParam;
15
+import io.milvus.param.IndexType;
16
+import io.milvus.param.MetricType;
17
+import io.milvus.param.R;
18
+import io.milvus.param.collection.CreateCollectionParam;
19
+import io.milvus.param.collection.FieldType;
20
+import io.milvus.param.dml.InsertParam;
21
+import io.milvus.param.dml.SearchParam;
22
+import io.milvus.param.index.CreateIndexParam;
23
+import io.milvus.response.SearchResultsWrapper;
24
+import okhttp3.*;
25
+
26
+import java.io.File;
27
+import java.io.FileInputStream;
28
+import java.io.IOException;
29
+import java.io.InputStream;
30
+import java.util.*;
31
+import java.util.stream.Collectors;
32
+
33
+public class LangChainMilvusService {
34
+    private static final String LLM_SERVICE_URL = "http://localhost:8000/generate";
35
+    private final MilvusServiceClient milvusClient;
36
+    private final String collectionName;
37
+    private  EmbeddingModel embeddingModel;
38
+
39
+    /**
40
+     * 连接milvus知识库,加入langchain自带emdding
41
+     */
42
+    public LangChainMilvusService(String host, int port, String collectionName, EmbeddingModel embeddingModel) {
43
+        this.milvusClient = new MilvusServiceClient(
44
+                ConnectParam.newBuilder()
45
+                        .withHost(host)
46
+                        .withPort(port)
47
+                        .build()
48
+        );
49
+        this.collectionName = collectionName;
50
+        this.embeddingModel = embeddingModel;
51
+    }
52
+
53
+    /**
54
+     * 新建知识库Collection(含Schema、Field、Index)
55
+     */
56
+    public void createCollection(int dimension) {
57
+        FieldType idField = FieldType.newBuilder()
58
+                .withName("id")
59
+                .withDataType(DataType.Int64)
60
+                .withPrimaryKey(true)
61
+                .withAutoID(true)
62
+                .build();
63
+
64
+        FieldType fileNameField = FieldType.newBuilder()
65
+                .withName("file_name")
66
+                .withDataType(DataType.VarChar)
67
+                .withMaxLength(256)
68
+                .build();
69
+
70
+        FieldType contentField = FieldType.newBuilder()
71
+                .withName("content")
72
+                .withDataType(DataType.VarChar)
73
+                .withMaxLength(65535)
74
+                .build();
75
+
76
+        FieldType vectorField = FieldType.newBuilder()
77
+                .withName("embedding")
78
+                .withDataType(DataType.Float16Vector)
79
+                .withDimension(dimension)
80
+                .build();
81
+
82
+        CreateCollectionParam createCollectionParam = CreateCollectionParam.newBuilder()
83
+                .withCollectionName(collectionName)
84
+                .addFieldType(idField)
85
+                .addFieldType(fileNameField)
86
+                .addFieldType(contentField)
87
+                .addFieldType(vectorField)
88
+                .build();
89
+
90
+        milvusClient.createCollection(createCollectionParam);
91
+
92
+        // 创建索引
93
+        CreateIndexParam createIndexParam = CreateIndexParam.newBuilder()
94
+                .withCollectionName(collectionName)
95
+                .withFieldName("embedding")
96
+                .withIndexType(IndexType.IVF_FLAT)
97
+                .withMetricType(MetricType.COSINE)
98
+                .withExtraParam("{\"nlist\": 64}")
99
+                .build();
100
+
101
+        milvusClient.createIndex(createIndexParam);
102
+    }
103
+
104
+    public void insertLangchainEmbeddingDocument(File file) throws IOException {
105
+        // 加载文档
106
+        InputStream fileInputStream = new FileInputStream(file);
107
+        Document document = new ApachePdfBoxDocumentParser().parse(fileInputStream);
108
+        DocumentByParagraphSplitter splitter = new DocumentByParagraphSplitter(150,10);;
109
+        List<TextSegment> segments = splitter.split(document);
110
+
111
+        // 提取文本和生成嵌入
112
+        List<String> texts = new ArrayList<>();
113
+        List<List<Float>> embeddings = new ArrayList<>();
114
+
115
+        for (TextSegment segment : segments) {
116
+            String text = segment.text();
117
+            if (text.trim().isEmpty())
118
+                continue;
119
+            texts.add(text);
120
+            embeddings.add(embeddingModel.embed(text).content().vectorAsList());
121
+        }
122
+
123
+        // 准备插入数据
124
+        List<InsertParam.Field> fields = new ArrayList<>();
125
+        fields.add(new InsertParam.Field("file_name", Arrays.asList(file.getName())));
126
+        fields.add(new InsertParam.Field("content", Arrays.asList(texts)));
127
+        fields.add(new InsertParam.Field("embedding", Arrays.asList(embeddings)));
128
+
129
+        InsertParam insertParam = InsertParam.newBuilder()
130
+                .withCollectionName(collectionName)
131
+                .withFields(fields)
132
+                .build();
133
+
134
+        // 执行插入
135
+        R<MutationResult> insertResult = milvusClient.insert(insertParam);
136
+
137
+        if (insertResult.getStatus() != R.Status.Success.getCode()) {
138
+            throw new RuntimeException("Failed to insert document: " + insertResult.getMessage());
139
+        }
140
+    }
141
+
142
+    // 从Milvus检索相关文档
143
+    public List<String> retrieveFromMilvus(String query, int topK) throws IOException {
144
+        List<Float> queryVector = embeddingModel.embed(query).content().vectorAsList();
145
+
146
+        SearchParam searchParam = SearchParam.newBuilder()
147
+                .withCollectionName(collectionName)
148
+                .withVectors(queryVector)
149
+                .withTopK(topK)
150
+                .withOutFields(Arrays.asList("content"))
151
+                .build();
152
+
153
+        R<SearchResults> response = milvusClient.search(searchParam);
154
+        SearchResultsWrapper wrapper = new SearchResultsWrapper(response.getData().getResults());
155
+
156
+        return wrapper.getRowRecords(0).stream()
157
+                .map(record -> (String) record.get("content"))
158
+                .collect(Collectors.toList());
159
+    }
160
+
161
+    // 调用LLM生成回答
162
+    public String generateAnswer(String question, List<String> contexts) throws IOException {
163
+        String prompt = buildPrompt(question, contexts);
164
+        Gson gson = new Gson();
165
+        Map<String, String> hashMap = new HashMap<>();
166
+        hashMap.put("prompt", prompt);
167
+        hashMap.put("max_tokens", "512");
168
+        RequestBody body = RequestBody.create(
169
+                MediaType.parse("application/json"),
170
+                new Gson().toJson(hashMap));
171
+
172
+        Request request = new Request.Builder()
173
+                .url(LLM_SERVICE_URL)
174
+                .post(body)
175
+                .build();
176
+
177
+        try (Response response = new OkHttpClient().newCall(request).execute()) {
178
+            return gson.fromJson(response.body().string(), Map.class).get("text").toString();
179
+        }
180
+    }
181
+
182
+    private String buildPrompt(String question, List<String> contexts) {
183
+        StringBuilder sb = new StringBuilder();
184
+        sb.append("根据以下上下文回答问题:\n\n");
185
+        for (int i = 0; i < contexts.size(); i++) {
186
+            sb.append("上下文").append(i+1).append(": ").append(contexts.get(i)).append("\n\n");
187
+        }
188
+        sb.append("问题: ").append(question).append("\n回答: ");
189
+        return sb.toString();
190
+    }
191
+    public void close() {
192
+        milvusClient.close();
193
+    }
194
+}

+ 8
- 0
llm-back/pom.xml Переглянути файл

@@ -218,10 +218,18 @@
218 218
                 <version>${ruoyi.version}</version>
219 219
             </dependency>
220 220
 
221
+            <!-- 智能体-->
222
+            <dependency>
223
+                <groupId>com.cmc</groupId>
224
+                <artifactId>cmc-agent</artifactId>
225
+                <version>${ruoyi.version}</version>
226
+            </dependency>
227
+
221 228
         </dependencies>
222 229
     </dependencyManagement>
223 230
 
224 231
     <modules>
232
+        <module>cmc-agent</module>
225 233
         <module>ruoyi-admin</module>
226 234
         <module>ruoyi-framework</module>
227 235
         <module>ruoyi-system</module>

+ 1
- 10
llm-back/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java Переглянути файл

@@ -16,15 +16,6 @@ public class RuoYiApplication
16 16
     {
17 17
         // System.setProperty("spring.devtools.restart.enabled", "false");
18 18
         SpringApplication.run(RuoYiApplication.class, args);
19
-        System.out.println("(♥◠‿◠)ノ゙  若依启动成功   ლ(´ڡ`ლ)゙  \n" +
20
-                " .-------.       ____     __        \n" +
21
-                " |  _ _   \\      \\   \\   /  /    \n" +
22
-                " | ( ' )  |       \\  _. /  '       \n" +
23
-                " |(_ o _) /        _( )_ .'         \n" +
24
-                " | (_,_).' __  ___(_ o _)'          \n" +
25
-                " |  |\\ \\  |  ||   |(_,_)'         \n" +
26
-                " |  | \\ `'   /|   `-'  /           \n" +
27
-                " |  |  \\    /  \\      /           \n" +
28
-                " ''-'   `'-'    `-..-'              ");
19
+        System.out.println("办公助手启动成功 \n");
29 20
     }
30 21
 }

+ 3
- 7
llm-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/llm/CmcChatController.java Переглянути файл

@@ -2,7 +2,8 @@ package com.ruoyi.web.controller.llm;
2 2
 
3 3
 import java.util.List;
4 4
 import javax.servlet.http.HttpServletResponse;
5
-import org.springframework.security.access.prepost.PreAuthorize;
5
+
6
+import com.ruoyi.common.utils.SnowFlake;
6 7
 import org.springframework.beans.factory.annotation.Autowired;
7 8
 import org.springframework.web.bind.annotation.GetMapping;
8 9
 import org.springframework.web.bind.annotation.PostMapping;
@@ -37,7 +38,6 @@ public class CmcChatController extends BaseController
37 38
     /**
38 39
      * 查询cmc聊天记录列表
39 40
      */
40
-    @PreAuthorize("@ss.hasPermi('llm:chat:list')")
41 41
     @GetMapping("/list")
42 42
     public TableDataInfo list(CmcChat cmcChat)
43 43
     {
@@ -49,7 +49,6 @@ public class CmcChatController extends BaseController
49 49
     /**
50 50
      * 导出cmc聊天记录列表
51 51
      */
52
-    @PreAuthorize("@ss.hasPermi('llm:chat:export')")
53 52
     @Log(title = "cmc聊天记录", businessType = BusinessType.EXPORT)
54 53
     @PostMapping("/export")
55 54
     public void export(HttpServletResponse response, CmcChat cmcChat)
@@ -62,7 +61,6 @@ public class CmcChatController extends BaseController
62 61
     /**
63 62
      * 获取cmc聊天记录详细信息
64 63
      */
65
-    @PreAuthorize("@ss.hasPermi('llm:chat:query')")
66 64
     @GetMapping(value = "/{chatId}")
67 65
     public AjaxResult getInfo(@PathVariable("chatId") String chatId)
68 66
     {
@@ -72,18 +70,17 @@ public class CmcChatController extends BaseController
72 70
     /**
73 71
      * 新增cmc聊天记录
74 72
      */
75
-    @PreAuthorize("@ss.hasPermi('llm:chat:add')")
76 73
     @Log(title = "cmc聊天记录", businessType = BusinessType.INSERT)
77 74
     @PostMapping
78 75
     public AjaxResult add(@RequestBody CmcChat cmcChat)
79 76
     {
77
+        cmcChat.setChatId(new SnowFlake().generateId());
80 78
         return toAjax(cmcChatService.insertCmcChat(cmcChat));
81 79
     }
82 80
 
83 81
     /**
84 82
      * 修改cmc聊天记录
85 83
      */
86
-    @PreAuthorize("@ss.hasPermi('llm:chat:edit')")
87 84
     @Log(title = "cmc聊天记录", businessType = BusinessType.UPDATE)
88 85
     @PutMapping
89 86
     public AjaxResult edit(@RequestBody CmcChat cmcChat)
@@ -94,7 +91,6 @@ public class CmcChatController extends BaseController
94 91
     /**
95 92
      * 删除cmc聊天记录
96 93
      */
97
-    @PreAuthorize("@ss.hasPermi('llm:chat:remove')")
98 94
     @Log(title = "cmc聊天记录", businessType = BusinessType.DELETE)
99 95
 	@DeleteMapping("/{chatIds}")
100 96
     public AjaxResult remove(@PathVariable String[] chatIds)

+ 3
- 7
llm-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/llm/CmcDocumentController.java Переглянути файл

@@ -2,7 +2,8 @@ package com.ruoyi.web.controller.llm;
2 2
 
3 3
 import java.util.List;
4 4
 import javax.servlet.http.HttpServletResponse;
5
-import org.springframework.security.access.prepost.PreAuthorize;
5
+
6
+import com.ruoyi.common.utils.SnowFlake;
6 7
 import org.springframework.beans.factory.annotation.Autowired;
7 8
 import org.springframework.web.bind.annotation.GetMapping;
8 9
 import org.springframework.web.bind.annotation.PostMapping;
@@ -37,7 +38,6 @@ public class CmcDocumentController extends BaseController
37 38
     /**
38 39
      * 查询cmc聊天附件列表
39 40
      */
40
-    @PreAuthorize("@ss.hasPermi('llm:document:list')")
41 41
     @GetMapping("/list")
42 42
     public TableDataInfo list(CmcDocument cmcDocument)
43 43
     {
@@ -49,7 +49,6 @@ public class CmcDocumentController extends BaseController
49 49
     /**
50 50
      * 导出cmc聊天附件列表
51 51
      */
52
-    @PreAuthorize("@ss.hasPermi('llm:document:export')")
53 52
     @Log(title = "cmc聊天附件", businessType = BusinessType.EXPORT)
54 53
     @PostMapping("/export")
55 54
     public void export(HttpServletResponse response, CmcDocument cmcDocument)
@@ -62,7 +61,6 @@ public class CmcDocumentController extends BaseController
62 61
     /**
63 62
      * 获取cmc聊天附件详细信息
64 63
      */
65
-    @PreAuthorize("@ss.hasPermi('llm:document:query')")
66 64
     @GetMapping(value = "/{documentId}")
67 65
     public AjaxResult getInfo(@PathVariable("documentId") String documentId)
68 66
     {
@@ -72,18 +70,17 @@ public class CmcDocumentController extends BaseController
72 70
     /**
73 71
      * 新增cmc聊天附件
74 72
      */
75
-    @PreAuthorize("@ss.hasPermi('llm:document:add')")
76 73
     @Log(title = "cmc聊天附件", businessType = BusinessType.INSERT)
77 74
     @PostMapping
78 75
     public AjaxResult add(@RequestBody CmcDocument cmcDocument)
79 76
     {
77
+        cmcDocument.setDocumentId(new SnowFlake().generateId());
80 78
         return toAjax(cmcDocumentService.insertCmcDocument(cmcDocument));
81 79
     }
82 80
 
83 81
     /**
84 82
      * 修改cmc聊天附件
85 83
      */
86
-    @PreAuthorize("@ss.hasPermi('llm:document:edit')")
87 84
     @Log(title = "cmc聊天附件", businessType = BusinessType.UPDATE)
88 85
     @PutMapping
89 86
     public AjaxResult edit(@RequestBody CmcDocument cmcDocument)
@@ -94,7 +91,6 @@ public class CmcDocumentController extends BaseController
94 91
     /**
95 92
      * 删除cmc聊天附件
96 93
      */
97
-    @PreAuthorize("@ss.hasPermi('llm:document:remove')")
98 94
     @Log(title = "cmc聊天附件", businessType = BusinessType.DELETE)
99 95
 	@DeleteMapping("/{documentIds}")
100 96
     public AjaxResult remove(@PathVariable String[] documentIds)

+ 2
- 0
llm-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/llm/CmcTopicController.java Переглянути файл

@@ -3,6 +3,7 @@ package com.ruoyi.web.controller.llm;
3 3
 import java.util.List;
4 4
 import javax.servlet.http.HttpServletResponse;
5 5
 
6
+import com.ruoyi.common.utils.SnowFlake;
6 7
 import org.springframework.beans.factory.annotation.Autowired;
7 8
 import org.springframework.web.bind.annotation.GetMapping;
8 9
 import org.springframework.web.bind.annotation.PostMapping;
@@ -73,6 +74,7 @@ public class CmcTopicController extends BaseController
73 74
     @PostMapping
74 75
     public AjaxResult add(@RequestBody CmcTopic cmcTopic)
75 76
     {
77
+        cmcTopic.setTopicId(new SnowFlake().generateId());
76 78
         return toAjax(cmcTopicService.insertCmcTopic(cmcTopic));
77 79
     }
78 80
 

+ 6
- 6
llm-back/ruoyi-admin/src/main/resources/application.yml Переглянути файл

@@ -1,13 +1,13 @@
1 1
 # 项目相关配置
2
-ruoyi:
2
+cmc:
3 3
   # 名称
4
-  name: RuoYi
4
+  name: llm
5 5
   # 版本
6 6
   version: 3.8.9
7 7
   # 版权年份
8 8
   copyrightYear: 2024
9 9
   # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
10
-  profile: D:/ruoyi/uploadPath
10
+  profile: /home/cmc/projects/cmc-llm
11 11
   # 获取ip地址开关
12 12
   addressEnabled: false
13 13
   # 验证码类型 math 数字计算 char 字符验证
@@ -57,9 +57,9 @@ spring:
57 57
   servlet:
58 58
     multipart:
59 59
       # 单个文件大小
60
-      max-file-size: 10MB
60
+      max-file-size: 1024MB
61 61
       # 设置总上传的文件大小
62
-      max-request-size: 20MB
62
+      max-request-size: 1024MB
63 63
   # 服务模块
64 64
   devtools:
65 65
     restart:
@@ -95,7 +95,7 @@ token:
95 95
   # 令牌密钥
96 96
   secret: abcdefghijklmnopqrstuvwxyz
97 97
   # 令牌有效期(默认30分钟)
98
-  expireTime: 30
98
+  expireTime: 480
99 99
 
100 100
 # MyBatis配置
101 101
 mybatis:

+ 1
- 23
llm-back/ruoyi-admin/src/main/resources/banner.txt Переглянути файл

@@ -1,24 +1,2 @@
1 1
 Application Version: ${ruoyi.version}
2
-Spring Boot Version: ${spring-boot.version}
3
-////////////////////////////////////////////////////////////////////
4
-//                          _ooOoo_                               //
5
-//                         o8888888o                              //
6
-//                         88" . "88                              //
7
-//                         (| ^_^ |)                              //
8
-//                         O\  =  /O                              //
9
-//                      ____/`---'\____                           //
10
-//                    .'  \\|     |//  `.                         //
11
-//                   /  \\|||  :  |||//  \                        //
12
-//                  /  _||||| -:- |||||-  \                       //
13
-//                  |   | \\\  -  /// |   |                       //
14
-//                  | \_|  ''\---/''  |   |                       //
15
-//                  \  .-\__  `-`  ___/-. /                       //
16
-//                ___`. .'  /--.--\  `. . ___                     //
17
-//              ."" '<  `.___\_<|>_/___.'  >'"".                  //
18
-//            | | :  `- \`.;`\ _ /`;.`/ - ` : | |                 //
19
-//            \  \ `-.   \_ __\ /__ _/   .-` /  /                 //
20
-//      ========`-.____`-.___\_____/___.-`____.-'========         //
21
-//                           `=---='                              //
22
-//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        //
23
-//             佛祖保佑       永不宕机      永无BUG               //
24
-////////////////////////////////////////////////////////////////////
2
+Spring Boot Version: ${spring-boot.version}

+ 1
- 1
llm-back/ruoyi-admin/src/main/resources/logback.xml Переглянути файл

@@ -1,7 +1,7 @@
1 1
 <?xml version="1.0" encoding="UTF-8"?>
2 2
 <configuration>
3 3
     <!-- 日志存放路径 -->
4
-	<property name="log.path" value="/home/ruoyi/logs" />
4
+	<property name="log.path" value="/home/cmc/projects/cmc-llm/logs" />
5 5
     <!-- 日志输出格式 -->
6 6
 	<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
7 7
 

+ 1
- 1
llm-back/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java Переглянути файл

@@ -9,7 +9,7 @@ import org.springframework.stereotype.Component;
9 9
  * @author ruoyi
10 10
  */
11 11
 @Component
12
-@ConfigurationProperties(prefix = "ruoyi")
12
+@ConfigurationProperties(prefix = "cmc")
13 13
 public class RuoYiConfig
14 14
 {
15 15
     /** 项目名称 */

+ 159
- 0
llm-back/ruoyi-common/src/main/java/com/ruoyi/common/utils/SnowFlake.java Переглянути файл

@@ -0,0 +1,159 @@
1
+package com.ruoyi.common.utils;
2
+
3
+import org.springframework.stereotype.Component;
4
+
5
+import java.lang.management.ManagementFactory;
6
+import java.net.InetAddress;
7
+import java.net.NetworkInterface;
8
+import java.util.concurrent.ThreadLocalRandom;
9
+
10
+/**
11
+ * 雪花id生成类
12
+ * @author zyl
13
+ */
14
+@Component
15
+public class SnowFlake {
16
+    /* 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动) */
17
+    private final long twepoch = 1715236540000L;
18
+    private final long workerIdBits = 5L;/* 机器标识位数 */
19
+    private final long datacenterIdBits = 5L;
20
+    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
21
+    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
22
+    private final long sequenceBits = 12L;/* 毫秒内自增位 */
23
+    private final long workerIdShift = sequenceBits;
24
+    private final long datacenterIdShift = sequenceBits + workerIdBits;
25
+    /* 时间戳左移动位 */
26
+    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
27
+    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
28
+
29
+    private long workerId;
30
+
31
+    /* 数据标识id部分 */
32
+    private long datacenterId;
33
+    private long sequence = 0L;/* 0,并发控制 */
34
+    private long lastTimestamp = -1L;/* 上次生产id时间戳 */
35
+
36
+    public SnowFlake() {
37
+        this.datacenterId = getDatacenterId(maxDatacenterId);
38
+        this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
39
+    }
40
+
41
+    /**
42
+     * @param workerId     工作机器ID
43
+     * @param datacenterId 序列号
44
+     */
45
+    public SnowFlake(long workerId, long datacenterId) {
46
+        if (workerId > maxWorkerId || workerId < 0) {
47
+            System.out.println(
48
+                    String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
49
+        }
50
+        if (datacenterId > maxDatacenterId || datacenterId < 0) {
51
+            System.out.println(
52
+                    String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
53
+        }
54
+        this.workerId = workerId;
55
+        this.datacenterId = datacenterId;
56
+    }
57
+
58
+    /**
59
+     * 获取 maxWorkerId
60
+     */
61
+    protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
62
+        StringBuilder mpid = new StringBuilder();
63
+        mpid.append(datacenterId);
64
+        String name = ManagementFactory.getRuntimeMXBean().getName();
65
+        if (name != null && "".equals(name)) {
66
+            /*
67
+             * GET jvmPid
68
+             */
69
+            mpid.append(name.split("@")[0]);
70
+        }
71
+        /*
72
+         * MAC + PID 的 hashcode 获取16个低位
73
+         */
74
+        return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
75
+    }
76
+
77
+    /**
78
+     * 数据标识id部分
79
+     */
80
+    protected static long getDatacenterId(long maxDatacenterId) {
81
+        long id = 0L;
82
+        try {
83
+            InetAddress ip = InetAddress.getLocalHost();
84
+            NetworkInterface network = NetworkInterface.getByInetAddress(ip);
85
+            if (network == null) {
86
+                id = 1L;
87
+            } else {
88
+                byte[] mac = network.getHardwareAddress();
89
+                if (null != mac) {
90
+                    id = ((0x000000FF & (long) mac[mac.length - 1]) | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
91
+                    id = id % (maxDatacenterId + 1);
92
+                }
93
+            }
94
+        } catch (Exception e) {
95
+            System.out.println(" getDatacenterId: " + e.getMessage());
96
+        }
97
+        return id;
98
+    }
99
+
100
+    /**
101
+     * 获取下一个ID
102
+     *
103
+     * @return
104
+     */
105
+    public synchronized long nextId() {
106
+        long timestamp = timeGen();
107
+        if (timestamp < lastTimestamp) {//闰秒
108
+            long offset = lastTimestamp - timestamp;
109
+            if (offset <= 5) {
110
+                try {
111
+                    wait(offset << 1);
112
+                    timestamp = timeGen();
113
+                    if (timestamp < lastTimestamp) {
114
+                        throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", offset));
115
+                    }
116
+                } catch (Exception e) {
117
+                    throw new RuntimeException(e);
118
+                }
119
+            } else {
120
+                throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", offset));
121
+            }
122
+        }
123
+
124
+        if (lastTimestamp == timestamp) {
125
+            // 相同毫秒内,序列号自增
126
+            sequence = (sequence + 1) & sequenceMask;
127
+            if (sequence == 0) {
128
+                // 同一毫秒的序列数已经达到最大
129
+                timestamp = tilNextMillis(lastTimestamp);
130
+            }
131
+        } else {
132
+            // 不同毫秒内,序列号置为 1 - 3 随机数
133
+            sequence = ThreadLocalRandom.current().nextLong(1, 3);
134
+        }
135
+
136
+        lastTimestamp = timestamp;
137
+
138
+        return ((timestamp - twepoch) << timestampLeftShift)    // 时间戳部分
139
+                | (datacenterId << datacenterIdShift)           // 数据中心部分
140
+                | (workerId << workerIdShift)                   // 机器标识部分
141
+                | sequence;                                     // 序列号部分
142
+    }
143
+
144
+    protected long tilNextMillis(long lastTimestamp) {
145
+        long timestamp = timeGen();
146
+        while (timestamp <= lastTimestamp) {
147
+            timestamp = timeGen();
148
+        }
149
+        return timestamp;
150
+    }
151
+
152
+    protected long timeGen() {
153
+        return System.currentTimeMillis();
154
+    }
155
+
156
+    public String generateId() {
157
+        return String.valueOf(this.nextId());
158
+    }
159
+}

Завантаження…
Відмінити
Зберегти