diff --git a/ai-chat/pom.xml b/ai-chat/pom.xml
index ec573ea..d6de28d 100644
--- a/ai-chat/pom.xml
+++ b/ai-chat/pom.xml
@@ -46,12 +46,19 @@
org.springframework.boot
spring-boot-starter-test
-
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
cn.hutool
hutool-all
5.8.22
+
+ org.springframework.ai
+ spring-ai-pdf-document-reader
+
diff --git a/ai-chat/src/main/java/cn/szsd/ai/chat/controller/ChatController.java b/ai-chat/src/main/java/cn/szsd/ai/chat/controller/ChatController.java
index 6a12cd0..c8ab918 100644
--- a/ai-chat/src/main/java/cn/szsd/ai/chat/controller/ChatController.java
+++ b/ai-chat/src/main/java/cn/szsd/ai/chat/controller/ChatController.java
@@ -2,13 +2,16 @@ package cn.szsd.ai.chat.controller;
import cn.szsd.ai.chat.pojo.ElectromagneticResult;
import cn.szsd.ai.chat.pojo.QueryDTO;
-import cn.szsd.ai.chat.pojo.UploadDTO;
import cn.szsd.ai.chat.service.ChatService;
import cn.szsd.ai.chat.service.ElectromagneticResultUtil;
import cn.szsd.ai.chat.utils.ChatTaskThread;
+import cn.szsd.ai.chat.utils.ChatTaskThread1;
import cn.szsd.ai.chat.utils.ThreadUtil;
import jakarta.annotation.Resource;
+import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import reactor.core.publisher.Flux;
import java.util.concurrent.*;
import java.util.logging.Logger;
@@ -18,12 +21,11 @@ import java.util.logging.Logger;
public class ChatController {
Logger log = Logger.getLogger(ChatController.class.getName());
-
@Resource
private ChatService chatService;
@PostMapping("/chat")
- public ElectromagneticResult test(@RequestBody QueryDTO queryDTO) throws Exception {
+ public ElectromagneticResult chat(@RequestBody QueryDTO queryDTO) throws Exception {
log.info("question is --->" + queryDTO.getMsg());
ChatTaskThread chatTaskThread = new ChatTaskThread(chatService, queryDTO);
Future future = ThreadUtil.getThreadPool().submit(chatTaskThread);
@@ -32,10 +34,16 @@ public class ChatController {
return ElectromagneticResultUtil.success(res);
}
- @PostMapping("/upload")
- public ElectromagneticResult> upload(@RequestBody UploadDTO uploadDTO) {
- chatService.add(uploadDTO.getContent());
- return ElectromagneticResultUtil.success("");
+ @PostMapping(path = "/chatStream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
+ public Flux chatStream(@RequestBody QueryDTO queryDTO) throws ExecutionException, InterruptedException {
+ ChatTaskThread1 chatTaskThread = new ChatTaskThread1(chatService, queryDTO);
+ Future> future = ThreadUtil.getThreadPool().submit(chatTaskThread);
+ return future.get();
+ }
+
+ @RequestMapping("/upload")
+ public ElectromagneticResult> upload(@RequestParam("file") MultipartFile file) throws Exception {
+ return chatService.addFromUpload(file);
}
}
\ No newline at end of file
diff --git a/ai-chat/src/main/java/cn/szsd/ai/chat/service/ChatService.java b/ai-chat/src/main/java/cn/szsd/ai/chat/service/ChatService.java
index 72b403d..6c8ebee 100644
--- a/ai-chat/src/main/java/cn/szsd/ai/chat/service/ChatService.java
+++ b/ai-chat/src/main/java/cn/szsd/ai/chat/service/ChatService.java
@@ -1,19 +1,27 @@
package cn.szsd.ai.chat.service;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.crypto.digest.DigestUtil;
+import cn.szsd.ai.chat.pojo.ElectromagneticResult;
import cn.szsd.ai.chat.pojo.QueryDTO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.*;
-import org.springframework.ai.chat.messages.UserMessage;
-import org.springframework.ai.chat.model.ChatResponse;
-import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.document.Document;
import org.springframework.ai.ollama.OllamaChatModel;
+import org.springframework.ai.reader.pdf.PagePdfDocumentReader;
import org.springframework.ai.vectorstore.VectorStore;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;
+import java.io.File;
+import java.nio.charset.Charset;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -34,11 +42,44 @@ public class ChatService {
@Resource
private QuestionAnswerAdvisor questionAnswerAdvisor;
+ @Value("file.md5RecordPath")
+ private String uploadFileMd5RecordPath;
+
+ @PostMapping
+ public void init() {
+ if (!FileUtil.exist(uploadFileMd5RecordPath)) {
+ FileUtil.touch(uploadFileMd5RecordPath);
+ }
+ }
+
public void add(String content) {
List documents = Stream.of(content).map(Document::new).collect(Collectors.toList());
vectorStore.write(documents);
}
+
+ public ElectromagneticResult> addFromUpload(MultipartFile file) throws Exception{
+ String fileType = FileUtil.extName(file.getOriginalFilename());
+ if (!StrUtil.equals(fileType, "pdf")) {
+ return ElectromagneticResultUtil.fail("当前仅支持pdf格式文件");
+ }
+ String fileMd5 = DigestUtil.md5Hex(file.getInputStream());
+ List lines = FileUtil.readLines(uploadFileMd5RecordPath, Charset.defaultCharset());
+ if (lines.contains(fileMd5)) {
+ return ElectromagneticResultUtil.success(fileMd5);
+ }
+ String pdfTmpPath = FileUtil.getParent(uploadFileMd5RecordPath, 1) + File.separator + IdUtil.fastSimpleUUID() + "." + fileType;
+ FileUtil.writeFromStream(file.getInputStream(), pdfTmpPath);
+
+ PagePdfDocumentReader pagePdfDocumentReader = new PagePdfDocumentReader(pdfTmpPath);
+ List documents = pagePdfDocumentReader.read();
+ vectorStore.write(documents);
+ lines.add(fileMd5);
+ FileUtil.writeLines(lines, uploadFileMd5RecordPath, Charset.defaultCharset());
+ FileUtil.del(pdfTmpPath);
+ return ElectromagneticResultUtil.success(fileMd5);
+ }
+
public String chat(QueryDTO queryDTO) {
log.info("Start call model to answer");
@@ -52,8 +93,7 @@ public class ChatService {
.content();
}
- public Flux chat1(String msg, String userId) {
- Prompt prompt = new Prompt(new UserMessage(msg));
- return this.model.stream(prompt);
+ public Flux chatStream(String msg) {
+ return ChatClient.builder(model).defaultAdvisors(messageChatMemoryAdvisor, questionAnswerAdvisor).build().prompt(msg).stream().content();
}
}
diff --git a/ai-chat/src/main/java/cn/szsd/ai/chat/utils/ChatTaskThread1.java b/ai-chat/src/main/java/cn/szsd/ai/chat/utils/ChatTaskThread1.java
new file mode 100644
index 0000000..04d84a5
--- /dev/null
+++ b/ai-chat/src/main/java/cn/szsd/ai/chat/utils/ChatTaskThread1.java
@@ -0,0 +1,23 @@
+package cn.szsd.ai.chat.utils;
+
+import cn.szsd.ai.chat.pojo.QueryDTO;
+import cn.szsd.ai.chat.service.ChatService;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+import reactor.core.publisher.Flux;
+
+import java.util.concurrent.Callable;
+
+@AllArgsConstructor
+@NoArgsConstructor
+public class ChatTaskThread1 implements Callable> {
+
+ private ChatService chatService;
+ private QueryDTO queryDTO;
+
+
+ @Override
+ public Flux call() throws Exception {
+ return chatService.chatStream(queryDTO.getMsg());
+ }
+}
diff --git a/ai-chat/src/main/resources/application.yml b/ai-chat/src/main/resources/application.yml
index a3ce2c2..6652624 100644
--- a/ai-chat/src/main/resources/application.yml
+++ b/ai-chat/src/main/resources/application.yml
@@ -1,8 +1,8 @@
spring:
elasticsearch:
- password: LCFLr9iQx*mKtwfjJj40
+ password: _oO*of_l-b+4mrzXo6B0
username: elastic
- uris: http://127.0.0.1:9200
+ uris: http://139.196.179.195:9200
ai:
ollama:
@@ -28,4 +28,7 @@ spring:
request-timeout: 3600000
server:
- port: 8186
\ No newline at end of file
+ port: 8186
+
+file:
+ md5RecordPath: /workspace/app/ai/ele-ai/record.txt