feat(ai): 新增AI对话与知识库功能模块
- 集成Fastjson2依赖优化JSON处理性能 - 配置专用文档处理异步线程池,提升任务并发处理能力 - 实现基于Spring AI的PgVectorStore向量存储配置 - 新增AI对话控制器,支持SSE流式对话及会话管理接口 - 新增AI知识库控制器,支持文件上传、文档管理及重新索引功能 - 定义AI对话和知识库相关的数据传输对象DTO与视图对象VO - 建立AI对话消息和文档向量的数据库实体与MyBatis Mapper - 实现AI对话服务接口及其具体业务逻辑,包括会话管理和RAG检索 - 完善安全校验和错误处理,确保接口调用的用户权限和参数有效性 - 提供对话消息流式响应机制,支持实时传输用户互动内容和引用文档信息
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
package cn.yinlihupo.controller.ai;
|
||||
|
||||
import cn.yinlihupo.common.core.BaseResponse;
|
||||
import cn.yinlihupo.common.util.ResultUtils;
|
||||
import cn.yinlihupo.common.util.SecurityUtils;
|
||||
import cn.yinlihupo.domain.vo.KbDocumentVO;
|
||||
import cn.yinlihupo.service.ai.AiKnowledgeBaseService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* AI知识库控制器
|
||||
* 提供知识库文件上传、管理等功能
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/ai/kb")
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "AI知识库", description = "AI知识库文档管理相关接口")
|
||||
public class AiKnowledgeBaseController {
|
||||
|
||||
private final AiKnowledgeBaseService knowledgeBaseService;
|
||||
|
||||
/**
|
||||
* 上传文件到知识库
|
||||
*
|
||||
* @param projectId 项目ID
|
||||
* @param file 文件
|
||||
* @return 文档信息
|
||||
*/
|
||||
@PostMapping("/upload")
|
||||
@Operation(summary = "上传文件", description = "上传文件到项目知识库,支持PDF、Word、TXT等格式")
|
||||
public BaseResponse<KbDocumentVO> uploadFile(
|
||||
@RequestParam Long projectId,
|
||||
@RequestParam MultipartFile file) {
|
||||
Long userId = SecurityUtils.getCurrentUserId();
|
||||
if (userId == null) {
|
||||
return ResultUtils.error("用户未登录");
|
||||
}
|
||||
|
||||
if (projectId == null) {
|
||||
return ResultUtils.error("项目ID不能为空");
|
||||
}
|
||||
|
||||
if (file == null || file.isEmpty()) {
|
||||
return ResultUtils.error("文件不能为空");
|
||||
}
|
||||
|
||||
try {
|
||||
KbDocumentVO doc = knowledgeBaseService.uploadFile(projectId, file, userId);
|
||||
return ResultUtils.success("上传成功", doc);
|
||||
} catch (Exception e) {
|
||||
log.error("上传文件失败: {}", e.getMessage(), e);
|
||||
return ResultUtils.error("上传失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取项目知识库文档列表
|
||||
*
|
||||
* @param projectId 项目ID
|
||||
* @return 文档列表
|
||||
*/
|
||||
@GetMapping("/documents")
|
||||
@Operation(summary = "获取文档列表", description = "获取指定项目的知识库文档列表")
|
||||
public BaseResponse<List<KbDocumentVO>> getDocuments(
|
||||
@RequestParam Long projectId) {
|
||||
Long userId = SecurityUtils.getCurrentUserId();
|
||||
if (userId == null) {
|
||||
return ResultUtils.error("用户未登录");
|
||||
}
|
||||
|
||||
if (projectId == null) {
|
||||
return ResultUtils.error("项目ID不能为空");
|
||||
}
|
||||
|
||||
try {
|
||||
List<KbDocumentVO> documents = knowledgeBaseService.getProjectDocuments(projectId);
|
||||
return ResultUtils.success("查询成功", documents);
|
||||
} catch (Exception e) {
|
||||
log.error("获取文档列表失败: {}", e.getMessage(), e);
|
||||
return ResultUtils.error("获取文档列表失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除知识库文档
|
||||
*
|
||||
* @param docId 文档UUID
|
||||
* @return 操作结果
|
||||
*/
|
||||
@DeleteMapping("/document/{docId}")
|
||||
@Operation(summary = "删除文档", description = "删除指定的知识库文档")
|
||||
public BaseResponse<Void> deleteDocument(@PathVariable UUID docId) {
|
||||
Long userId = SecurityUtils.getCurrentUserId();
|
||||
if (userId == null) {
|
||||
return ResultUtils.error("用户未登录");
|
||||
}
|
||||
|
||||
try {
|
||||
knowledgeBaseService.deleteDocument(docId, userId);
|
||||
return ResultUtils.success("删除成功", null);
|
||||
} catch (Exception e) {
|
||||
log.error("删除文档失败: {}", e.getMessage(), e);
|
||||
return ResultUtils.error("删除失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新索引文档
|
||||
*
|
||||
* @param docId 文档UUID
|
||||
* @return 操作结果
|
||||
*/
|
||||
@PostMapping("/document/{docId}/reindex")
|
||||
@Operation(summary = "重新索引文档", description = "重新解析并索引指定的文档")
|
||||
public BaseResponse<Void> reindexDocument(@PathVariable UUID docId) {
|
||||
Long userId = SecurityUtils.getCurrentUserId();
|
||||
if (userId == null) {
|
||||
return ResultUtils.error("用户未登录");
|
||||
}
|
||||
|
||||
try {
|
||||
knowledgeBaseService.reindexDocument(docId, userId);
|
||||
return ResultUtils.success("重新索引已启动", null);
|
||||
} catch (Exception e) {
|
||||
log.error("重新索引文档失败: {}", e.getMessage(), e);
|
||||
return ResultUtils.error("重新索引失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user