瀏覽代碼

Merge branch 'master' of http://oa.sccehui.com:6101/cmc-coding/cmc-llm

余思翰 3 天之前
父節點
當前提交
76680c9d06

+ 3
- 11
llm-back/ruoyi-agent/src/main/java/com/ruoyi/agent/service/impl/McpServiceImpl.java 查看文件

@@ -21,8 +21,8 @@ import java.util.Collections;
21 21
 @McpServerEndpoint(sseEndpoint = "/llm/mcp/sse")
22 22
 public class McpServiceImpl implements IMcpService {
23 23
 
24
-    @ToolMapping(description = "查看招标文档")
25
-    public String openDocument(@Param(description = "文件路径") String document) throws IOException {
24
+    @ToolMapping(description = "梳理招标文件服务要求")
25
+    public String getBidRequest(@Param(description = "文件路径") String document) throws IOException {
26 26
         try (XWPFDocument doc = new XWPFDocument(new FileInputStream(document))) {
27 27
             StringBuilder content = new StringBuilder();
28 28
             for (XWPFParagraph paragraph : doc.getParagraphs()) {
@@ -32,15 +32,7 @@ public class McpServiceImpl implements IMcpService {
32 32
         }
33 33
     }
34 34
 
35
-    @ToolMapping(description = "开场白")
36
-    public String opening(@Param(description = "智能体名称") String agentName) {
37
-        String content = "";
38
-        if (agentName.contains("技术"))
39
-            content = "我是投标文件写作助手,我将助您完成技术文件部分撰写。请上传招标询价文件,分析后将依招标服务要求,运用技术方案知识库,为您提供参考。";
40
-        return content;
41
-    }
42
-
43
-    @ToolMapping(description = "补全技术方案")
35
+    @ToolMapping(description = "撰写技术方案")
44 36
     public String writeTechnicalPlan(@Param(description = "文件路径") String document, @Param(description = "技术方案内容") String resultContent) throws IOException {
45 37
         // 创建临时输出文件路径
46 38
 

+ 28
- 0
llm-back/ruoyi-llm/src/main/java/com/ruoyi/web/llm/controller/McpController.java 查看文件

@@ -2,15 +2,22 @@ package com.ruoyi.web.llm.controller;
2 2
 
3 3
 import com.alibaba.fastjson2.JSONObject;
4 4
 import com.ruoyi.common.core.controller.BaseController;
5
+import com.ruoyi.web.llm.service.ILangChainMilvusService;
6
+import dev.langchain4j.model.embedding.EmbeddingModel;
7
+import dev.langchain4j.model.embedding.onnx.bgesmallzhv15.BgeSmallZhV15EmbeddingModel;
8
+import io.milvus.client.MilvusServiceClient;
9
+import io.milvus.param.ConnectParam;
5 10
 import org.noear.solon.ai.chat.ChatModel;
6 11
 import org.noear.solon.ai.chat.ChatResponse;
7 12
 import org.noear.solon.ai.chat.message.AssistantMessage;
8 13
 import org.noear.solon.ai.chat.message.ChatMessage;
9 14
 import org.noear.solon.ai.mcp.client.McpClientProvider;
15
+import org.springframework.beans.factory.annotation.Autowired;
10 16
 import org.springframework.web.bind.annotation.GetMapping;
11 17
 import org.springframework.web.bind.annotation.RequestMapping;
12 18
 import org.springframework.web.bind.annotation.RestController;
13 19
 import org.springframework.web.multipart.MultipartFile;
20
+import reactor.core.publisher.Flux;
14 21
 
15 22
 import java.io.IOException;
16 23
 import java.util.*;
@@ -26,6 +33,17 @@ import java.util.*;
26 33
 @RequestMapping("/llm/mcp")
27 34
 public class McpController extends BaseController
28 35
 {
36
+    @Autowired
37
+    private ILangChainMilvusService langChainMilvusService;
38
+
39
+    private static final EmbeddingModel embeddingModel = new BgeSmallZhV15EmbeddingModel();
40
+
41
+    private static final MilvusServiceClient milvusClient = new MilvusServiceClient(
42
+            ConnectParam.newBuilder()
43
+                    .withHost("192.168.28.188")
44
+                    .withPort(19530)
45
+                    .build());
46
+
29 47
     /**
30 48
      * 同步问答
31 49
      * @return
@@ -54,6 +72,16 @@ public class McpController extends BaseController
54 72
         return assistantMessage;
55 73
     }
56 74
 
75
+    /**
76
+     * 调用LLM+RAG(外部文件)生成回答
77
+     */
78
+    @GetMapping("/answerWithDocument")
79
+    public Flux<AssistantMessage> answerWithDocumentAndCollection(String collectionName, String topicId, String chatId, String question) throws IOException
80
+    {
81
+        List<JSONObject> requests = langChainMilvusService.retrieveFromMilvus(milvusClient, embeddingModel, collectionName, question, 10);
82
+        return langChainMilvusService.generateAnswerWithDocumentAndCollection(embeddingModel, topicId, chatId, question, requests, "http://192.168.28.188:8000/v1/chat/completions");
83
+    }
84
+
57 85
 
58 86
     /**
59 87
      * 根据招标文件要求编写投标文件技术方案

+ 6
- 0
llm-back/ruoyi-llm/src/main/java/com/ruoyi/web/llm/service/ILangChainMilvusService.java 查看文件

@@ -49,4 +49,10 @@ public interface ILangChainMilvusService {
49 49
      */
50 50
     public Flux<AssistantMessage> generateAnswerWithDocument(EmbeddingModel embeddingModel, String topicId, String chatId, String question, String llmServiceUrl) throws IOException;
51 51
 
52
+    /**
53
+     * 调用LLM+RAG(外部文件+知识库)生成回答
54
+     * @return
55
+     */
56
+    public Flux<AssistantMessage> generateAnswerWithDocumentAndCollection(EmbeddingModel embeddingModel, String topicId, String chatId, String question,  List<JSONObject> requests, String llmServiceUrl) throws IOException;
57
+
52 58
 }

+ 34
- 0
llm-back/ruoyi-llm/src/main/java/com/ruoyi/web/llm/service/impl/LangChainMilvusServiceImpl.java 查看文件

@@ -214,6 +214,40 @@ public class LangChainMilvusServiceImpl implements ILangChainMilvusService
214 214
         return generateAnswer(topicId, sb.toString(), llmServiceUrl);
215 215
     }
216 216
 
217
+    /**
218
+     * 调用LLM生成回答
219
+     */
220
+    @Override
221
+    public Flux<AssistantMessage> generateAnswerWithDocumentAndCollection(EmbeddingModel embeddingModel, String topicId, String chatId, String question, List<JSONObject> requests, String llmServiceUrl) throws IOException {
222
+        CmcDocument cmcDocument = new CmcDocument();
223
+        cmcDocument.setChatId(chatId);
224
+        List<CmcDocument> documentList = cmcDocumentService.selectCmcDocumentList(cmcDocument);
225
+        StringBuilder sb = new StringBuilder("问题: " + question + "\n\n").append("根据以下要求:\n\n");
226
+        for (JSONObject request : requests) {
227
+            sb.append("要求").append(": ")
228
+                    .append(request.getString("content")).append("\n\n");
229
+        }
230
+        sb.append("参考以下文件上下文回答问题:\n\n");
231
+        for (CmcDocument document : documentList) {
232
+            File profilePath = new File(RuoYiConfig.getProfile() + "/upload/rag/document/" + document.getPath());
233
+            List<TextSegment> segments = splitDocument(document.getPath(), profilePath);
234
+            List<Embedding> embeddings = embeddingModel.embedAll(segments).content();
235
+            InMemoryEmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();
236
+            embeddingStore.addAll(embeddings, segments);
237
+            Embedding queryEmbedding = embeddingModel.embed(question).content();
238
+            EmbeddingSearchRequest embeddingSearchRequest = EmbeddingSearchRequest.builder()
239
+                    .queryEmbedding(queryEmbedding)
240
+                    .maxResults(1)
241
+                    .build();
242
+            String contexts = embeddingStore.search(embeddingSearchRequest).matches().get(0).embedded().text();
243
+            sb.append("文件").append(": ")
244
+                    .append(document.getPath()).append("\n\n")
245
+                    .append("上下文").append(": ")
246
+                    .append(contexts).append("\n\n");
247
+        }
248
+        return generateAnswer(topicId, sb.toString(), llmServiceUrl);
249
+    }
250
+
217 251
     /**
218 252
      * 检索知识库
219 253
      */

Loading…
取消
儲存