新增 ChatDto 数据传输对象,更新聊天接口以支持知识库功能,优化聊天服务逻辑,调整前端组件以提升用户体验。

This commit is contained in:
ccmjga
2025-06-28 22:31:20 +08:00
parent 3e1d7e6fee
commit b6ecc929b0
30 changed files with 268 additions and 176 deletions

View File

@@ -1,5 +1,7 @@
package com.zl.mjga.config.ai;
import static dev.langchain4j.store.embedding.filter.MetadataFilterBuilder.metadataKey;
import com.zl.mjga.component.PromptConfiguration;
import com.zl.mjga.service.LlmService;
import dev.langchain4j.community.model.zhipu.ZhipuAiStreamingChatModel;
@@ -72,6 +74,11 @@ public class ChatModelInitializer {
.embeddingModel(zhipuEmbeddingModel)
.minScore(0.75)
.maxResults(5)
.dynamicFilter(
query -> {
String libraryId = (String) query.metadata().chatMemoryId();
return metadataKey("libraryId").isEqualTo(libraryId);
})
.build())
.build();
}

View File

@@ -2,6 +2,7 @@ package com.zl.mjga.controller;
import com.zl.mjga.dto.PageRequestDto;
import com.zl.mjga.dto.PageResponseDto;
import com.zl.mjga.dto.ai.ChatDto;
import com.zl.mjga.dto.ai.LlmQueryDto;
import com.zl.mjga.dto.ai.LlmVm;
import com.zl.mjga.exception.BusinessException;
@@ -72,9 +73,9 @@ public class AiController {
}
@PostMapping(value = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> chat(Principal principal, @RequestBody String userMessage) {
public Flux<String> chat(Principal principal, @RequestBody ChatDto chatDto) {
Sinks.Many<String> sink = Sinks.many().unicast().onBackpressureBuffer();
TokenStream chat = aiChatService.chatPrecedenceLlmWith(principal.getName(), userMessage);
TokenStream chat = aiChatService.chat(principal.getName(), chatDto);
chat.onPartialResponse(
text ->
sink.tryEmitNext(

View File

@@ -8,7 +8,6 @@ import com.zl.mjga.repository.LibraryRepository;
import com.zl.mjga.service.RagService;
import com.zl.mjga.service.UploadService;
import jakarta.validation.Valid;
import java.util.Comparator;
import java.util.List;
import lombok.RequiredArgsConstructor;
@@ -34,16 +33,16 @@ public class LibraryController {
@GetMapping("/libraries")
public List<Library> queryLibraries() {
return libraryRepository.findAll().stream().sorted(
Comparator.comparing(Library::getId).reversed()
).toList();
return libraryRepository.findAll().stream()
.sorted(Comparator.comparing(Library::getId).reversed())
.toList();
}
@GetMapping("/docs")
public List<LibraryDoc> queryLibraryDocs(@RequestParam Long libraryId) {
return libraryDocRepository.fetchByLibId(libraryId).stream().sorted(
Comparator.comparing(LibraryDoc::getId).reversed()
).toList();
return libraryDocRepository.fetchByLibId(libraryId).stream()
.sorted(Comparator.comparing(LibraryDoc::getId).reversed())
.toList();
}
@GetMapping("/segments")

View File

@@ -0,0 +1,7 @@
package com.zl.mjga.dto.ai;
import com.zl.mjga.model.urp.ChatMode;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
public record ChatDto(@NotNull ChatMode mode, Long libraryId, @NotEmpty String message) {}

View File

@@ -0,0 +1,6 @@
package com.zl.mjga.model.urp;
public enum ChatMode {
NORMAL,
WITH_LIBRARY
}

View File

@@ -2,6 +2,7 @@ package com.zl.mjga.service;
import com.zl.mjga.config.ai.AiChatAssistant;
import com.zl.mjga.config.ai.SystemToolAssistant;
import com.zl.mjga.dto.ai.ChatDto;
import com.zl.mjga.exception.BusinessException;
import dev.langchain4j.service.TokenStream;
import java.util.Optional;
@@ -39,8 +40,20 @@ public class AiChatService {
};
}
public TokenStream chatPrecedenceLlmWith(String sessionIdentifier, String userMessage) {
public TokenStream chat(String sessionIdentifier, ChatDto chatDto) {
return switch (chatDto.mode()) {
case NORMAL -> chatWithPrecedenceLlm(sessionIdentifier, chatDto);
case WITH_LIBRARY -> chatWithLibrary(chatDto.libraryId(), chatDto);
};
}
public TokenStream chatWithLibrary(Long libraryId, ChatDto chatDto) {
return zhiPuChatAssistant.chat(String.valueOf(libraryId), chatDto.message());
}
public TokenStream chatWithPrecedenceLlm(String sessionIdentifier, ChatDto chatDto) {
LlmCodeEnum code = getPrecedenceLlmCode();
String userMessage = chatDto.message();
return switch (code) {
case ZHI_PU -> zhiPuChatAssistant.chat(sessionIdentifier, userMessage);
case DEEP_SEEK -> deepSeekChatAssistant.chat(sessionIdentifier, userMessage);

View File

@@ -71,10 +71,6 @@ public class UploadService {
if (size > 1024 * 1024) {
throw new BusinessException("知识库文档大小不能超过1MB");
}
String contentType = multipartFile.getContentType();
if (!StringUtils.startsWith(contentType, "text/")) {
throw new BusinessException("非法的上传文件");
}
minioClient.putObject(
PutObjectArgs.builder().bucket(minIoConfig.getDefaultBucket()).object(objectName).stream(
multipartFile.getInputStream(), size, -1)