From 9f972f5e30983c2def6f0cbe14fb0cf773b5283d Mon Sep 17 00:00:00 2001 From: JiaoTianBo Date: Mon, 30 Mar 2026 16:49:07 +0800 Subject: [PATCH] =?UTF-8?q?feat(ai-knowledge-base):=20=E5=AE=9E=E7=8E=B0AI?= =?UTF-8?q?=E7=9F=A5=E8=AF=86=E5=BA=93=E6=96=87=E6=A1=A3=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=E4=B8=8E=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增AiDocument实体类,映射数据库ai_document表结构 - 添加AiDocumentMapper接口,提供文档增删改查及状态更新等数据库操作 - 实现AiKnowledgeBaseService接口及其实现类AiKnowledgeBaseServiceImpl,支持文件上传、文档列表查询、删除和重新索引 - 在AiKnowledgeBaseController中提供REST接口支持文件上传、文档管理和异步重新索引操作 - 实现DocumentProcessor组件,负责文档解析、文本切片、摘要生成和向量化存储 - 集成MinioService实现文件的上传、下载和删除操作 - 设计KbDocumentVO作为知识库文档视图对象,方便接口数据传输和展示 - 增加文件类型支持和上传文件校验,限制最大50MB文件大小 - 使用异步机制处理文档解析和向量化,提高系统处理性能和响应速度 - 实现文档状态管理和错误处理,确保文档处理流程的正确性和稳定性 --- .../controller/ai/AiKnowledgeBaseController.java | 5 ++--- src/main/java/cn/yinlihupo/domain/entity/AiDocument.java | 3 +-- src/main/java/cn/yinlihupo/domain/vo/KbDocumentVO.java | 3 +-- src/main/java/cn/yinlihupo/mapper/AiDocumentMapper.java | 9 ++++----- .../cn/yinlihupo/service/ai/AiKnowledgeBaseService.java | 5 ++--- .../service/ai/impl/AiKnowledgeBaseServiceImpl.java | 7 ++++--- .../cn/yinlihupo/service/ai/rag/DocumentProcessor.java | 8 +++++--- 7 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/main/java/cn/yinlihupo/controller/ai/AiKnowledgeBaseController.java b/src/main/java/cn/yinlihupo/controller/ai/AiKnowledgeBaseController.java index d738ed0..8cb1b90 100644 --- a/src/main/java/cn/yinlihupo/controller/ai/AiKnowledgeBaseController.java +++ b/src/main/java/cn/yinlihupo/controller/ai/AiKnowledgeBaseController.java @@ -13,7 +13,6 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.util.List; -import java.util.UUID; /** * AI知识库控制器 @@ -98,7 +97,7 @@ public class AiKnowledgeBaseController { */ @DeleteMapping("/document/{docId}") @Operation(summary = "删除文档", description = "删除指定的知识库文档") - public BaseResponse deleteDocument(@PathVariable UUID docId) { + public BaseResponse deleteDocument(@PathVariable String docId) { Long userId = SecurityUtils.getCurrentUserId(); if (userId == null) { return ResultUtils.error("用户未登录"); @@ -121,7 +120,7 @@ public class AiKnowledgeBaseController { */ @PostMapping("/document/{docId}/reindex") @Operation(summary = "重新索引文档", description = "重新解析并索引指定的文档") - public BaseResponse reindexDocument(@PathVariable UUID docId) { + public BaseResponse reindexDocument(@PathVariable String docId) { Long userId = SecurityUtils.getCurrentUserId(); if (userId == null) { return ResultUtils.error("用户未登录"); diff --git a/src/main/java/cn/yinlihupo/domain/entity/AiDocument.java b/src/main/java/cn/yinlihupo/domain/entity/AiDocument.java index 19605c5..e2b25ea 100644 --- a/src/main/java/cn/yinlihupo/domain/entity/AiDocument.java +++ b/src/main/java/cn/yinlihupo/domain/entity/AiDocument.java @@ -7,7 +7,6 @@ import lombok.Data; import java.time.LocalDate; import java.time.LocalDateTime; -import java.util.UUID; /** * AI文档向量实体 @@ -23,7 +22,7 @@ public class AiDocument { /** * 文档唯一标识(UUID) */ - private UUID docId; + private String docId; /** * 关联项目ID diff --git a/src/main/java/cn/yinlihupo/domain/vo/KbDocumentVO.java b/src/main/java/cn/yinlihupo/domain/vo/KbDocumentVO.java index 46c006e..5f21392 100644 --- a/src/main/java/cn/yinlihupo/domain/vo/KbDocumentVO.java +++ b/src/main/java/cn/yinlihupo/domain/vo/KbDocumentVO.java @@ -3,7 +3,6 @@ package cn.yinlihupo.domain.vo; import lombok.Data; import java.time.LocalDateTime; -import java.util.UUID; /** * 知识库文档VO @@ -19,7 +18,7 @@ public class KbDocumentVO { /** * 文档UUID */ - private UUID docId; + private String docId; /** * 文档标题 diff --git a/src/main/java/cn/yinlihupo/mapper/AiDocumentMapper.java b/src/main/java/cn/yinlihupo/mapper/AiDocumentMapper.java index 05934b8..9377160 100644 --- a/src/main/java/cn/yinlihupo/mapper/AiDocumentMapper.java +++ b/src/main/java/cn/yinlihupo/mapper/AiDocumentMapper.java @@ -8,7 +8,6 @@ import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.List; -import java.util.UUID; /** * AI文档向量Mapper @@ -30,7 +29,7 @@ public interface AiDocumentMapper extends BaseMapper { * @param docId 文档UUID * @return 文档实体 */ - AiDocument selectByDocId(@Param("docId") UUID docId); + AiDocument selectByDocId(@Param("docId") String docId); /** * 根据docId删除文档 @@ -38,7 +37,7 @@ public interface AiDocumentMapper extends BaseMapper { * @param docId 文档UUID * @return 影响行数 */ - int deleteByDocId(@Param("docId") UUID docId); + int deleteByDocId(@Param("docId") String docId); /** * 批量查询引用文档信息 @@ -63,7 +62,7 @@ public interface AiDocumentMapper extends BaseMapper { * @param status 状态 * @return 影响行数 */ - int updateStatus(@Param("docId") UUID docId, @Param("status") String status); + int updateStatus(@Param("docId") String docId, @Param("status") String status); /** * 更新文档错误信息 @@ -72,7 +71,7 @@ public interface AiDocumentMapper extends BaseMapper { * @param errorMessage 错误信息 * @return 影响行数 */ - int updateErrorMessage(@Param("docId") UUID docId, @Param("errorMessage") String errorMessage); + int updateErrorMessage(@Param("docId") String docId, @Param("errorMessage") String errorMessage); /** * 增加文档查看次数 diff --git a/src/main/java/cn/yinlihupo/service/ai/AiKnowledgeBaseService.java b/src/main/java/cn/yinlihupo/service/ai/AiKnowledgeBaseService.java index 5fca4f7..baff9e9 100644 --- a/src/main/java/cn/yinlihupo/service/ai/AiKnowledgeBaseService.java +++ b/src/main/java/cn/yinlihupo/service/ai/AiKnowledgeBaseService.java @@ -4,7 +4,6 @@ import cn.yinlihupo.domain.vo.KbDocumentVO; import org.springframework.web.multipart.MultipartFile; import java.util.List; -import java.util.UUID; /** * AI知识库服务接口 @@ -35,7 +34,7 @@ public interface AiKnowledgeBaseService { * @param docId 文档UUID * @param userId 用户ID */ - void deleteDocument(UUID docId, Long userId); + void deleteDocument(String docId, Long userId); /** * 重新索引文档 @@ -43,7 +42,7 @@ public interface AiKnowledgeBaseService { * @param docId 文档UUID * @param userId 用户ID */ - void reindexDocument(UUID docId, Long userId); + void reindexDocument(String docId, Long userId); /** * 处理文档(解析、切片、向量化) diff --git a/src/main/java/cn/yinlihupo/service/ai/impl/AiKnowledgeBaseServiceImpl.java b/src/main/java/cn/yinlihupo/service/ai/impl/AiKnowledgeBaseServiceImpl.java index 382275d..97d25e1 100644 --- a/src/main/java/cn/yinlihupo/service/ai/impl/AiKnowledgeBaseServiceImpl.java +++ b/src/main/java/cn/yinlihupo/service/ai/impl/AiKnowledgeBaseServiceImpl.java @@ -39,7 +39,7 @@ public class AiKnowledgeBaseServiceImpl implements AiKnowledgeBaseService { validateFile(file); // 2. 生成文档UUID - UUID docId = UUID.randomUUID(); + String docId = UUID.randomUUID().toString(); // 3. 上传文件到MinIO String originalFilename = file.getOriginalFilename(); @@ -63,6 +63,7 @@ public class AiKnowledgeBaseServiceImpl implements AiKnowledgeBaseService { doc.setFileType(fileExtension); doc.setFileSize(file.getSize()); doc.setFilePath(filePath); + doc.setContent(""); doc.setStatus("pending"); // 待处理状态 doc.setChunkTotal(0); doc.setCreateBy(userId); @@ -86,7 +87,7 @@ public class AiKnowledgeBaseServiceImpl implements AiKnowledgeBaseService { } @Override - public void deleteDocument(UUID docId, Long userId) { + public void deleteDocument(String docId, Long userId) { // 1. 查询文档 AiDocument doc = documentMapper.selectByDocId(docId); if (doc == null) { @@ -111,7 +112,7 @@ public class AiKnowledgeBaseServiceImpl implements AiKnowledgeBaseService { } @Override - public void reindexDocument(UUID docId, Long userId) { + public void reindexDocument(String docId, Long userId) { // 1. 查询文档 AiDocument doc = documentMapper.selectByDocId(docId); if (doc == null) { diff --git a/src/main/java/cn/yinlihupo/service/ai/rag/DocumentProcessor.java b/src/main/java/cn/yinlihupo/service/ai/rag/DocumentProcessor.java index 8693f68..84e0fc2 100644 --- a/src/main/java/cn/yinlihupo/service/ai/rag/DocumentProcessor.java +++ b/src/main/java/cn/yinlihupo/service/ai/rag/DocumentProcessor.java @@ -13,7 +13,9 @@ import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import java.io.InputStream; -import java.util.*; +import java.util.Collections; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; /** @@ -167,7 +169,7 @@ public class DocumentProcessor { * @param chunks 切片列表 */ private void storeChunks(AiDocument parentDoc, List chunks) { - UUID docId = parentDoc.getDocId(); + String docId = parentDoc.getDocId(); Long parentId = parentDoc.getId(); for (int i = 0; i < chunks.size(); i++) { @@ -206,7 +208,7 @@ public class DocumentProcessor { * * @param docId 文档UUID */ - public void deleteDocumentVectors(UUID docId) { + public void deleteDocumentVectors(String docId) { try { // 查询所有相关切片 // 注意:pgvector store的删除需要根据metadata过滤