Commit 8e54eef8af762e77084c4d7742307afa2cdf212a

Authored by xiaoxin
1 parent b4af042c

【新增】AI 知识库:文档切片向量化入库

Showing 14 changed files with 190 additions and 34 deletions
yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/knowledge/AiKnowledgeDocumentStatusEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.ai.enums.knowledge;
  2 +
  3 +import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
  4 +import lombok.AllArgsConstructor;
  5 +import lombok.Getter;
  6 +
  7 +import java.util.Arrays;
  8 +
  9 +/**
  10 + * AI 知识库-文档状态的枚举
  11 + *
  12 + * @author xiaoxin
  13 + */
  14 +@AllArgsConstructor
  15 +@Getter
  16 +public enum AiKnowledgeDocumentStatusEnum implements IntArrayValuable {
  17 +
  18 + IN_PROGRESS(10, "索引中"),
  19 + SUCCESS(20, "可用"),
  20 + FAIL(30, "失败");
  21 +
  22 + /**
  23 + * 状态
  24 + */
  25 + private final Integer status;
  26 +
  27 + /**
  28 + * 状态名
  29 + */
  30 + private final String name;
  31 +
  32 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(AiKnowledgeDocumentStatusEnum::getStatus).toArray();
  33 +
  34 + @Override
  35 + public int[] array() {
  36 + return ARRAYS;
  37 + }
  38 +
  39 +}
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/AiKnowledgeCreateMyReqVO.java
@@ -14,11 +14,11 @@ import java.util.List; @@ -14,11 +14,11 @@ import java.util.List;
14 @Data 14 @Data
15 public class AiKnowledgeCreateMyReqVO { 15 public class AiKnowledgeCreateMyReqVO {
16 16
17 - @Schema(description = "知识库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "") 17 + @Schema(description = "知识库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "ruoyi-vue-pro 用户指南")
18 @NotBlank(message = "知识库名称不能为空") 18 @NotBlank(message = "知识库名称不能为空")
19 private String name; 19 private String name;
20 20
21 - @Schema(description = "知识库描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "") 21 + @Schema(description = "知识库描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "存储 ruoyi-vue-pro 操作文档")
22 private String description; 22 private String description;
23 23
24 @Schema(description = "可见权限,只能选择哪些人可见", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1]") 24 @Schema(description = "可见权限,只能选择哪些人可见", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1]")
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/AiKnowledgeDocumentCreateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import jakarta.validation.constraints.NotBlank;
  5 +import jakarta.validation.constraints.NotNull;
  6 +import lombok.Data;
  7 +
  8 +/**
  9 + * @author xiaoxin
  10 + */
  11 +@Schema(description = "管理后台 - AI 知识库【创建文档】 Request VO")
  12 +@Data
  13 +public class AiKnowledgeDocumentCreateReqVO {
  14 +
  15 +
  16 + @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1204")
  17 + @NotNull(message = "知识库编号不能为空")
  18 + private Long knowledgeId;
  19 +
  20 + @Schema(description = "文档名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "三方登陆")
  21 + @NotBlank(message = "文档名称不能为空")
  22 + private String name;
  23 +
  24 + @Schema(description = "文档 url", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://doc.iocoder.cn")
  25 + private String url;
  26 +
  27 +}
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeBaseDO.java
1 package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge; 1 package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge;
2 2
3 3
  4 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 5 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
5 import com.baomidou.mybatisplus.annotation.IdType; 6 import com.baomidou.mybatisplus.annotation.IdType;
  7 +import com.baomidou.mybatisplus.annotation.TableField;
6 import com.baomidou.mybatisplus.annotation.TableId; 8 import com.baomidou.mybatisplus.annotation.TableId;
7 import com.baomidou.mybatisplus.annotation.TableName; 9 import com.baomidou.mybatisplus.annotation.TableName;
  10 +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
8 import lombok.Data; 11 import lombok.Data;
9 12
10 import java.util.List; 13 import java.util.List;
@@ -40,7 +43,8 @@ public class AiKnowledgeBaseDO extends BaseDO { @@ -40,7 +43,8 @@ public class AiKnowledgeBaseDO extends BaseDO {
40 /** 43 /**
41 * 可见权限,只能选择哪些人可见 44 * 可见权限,只能选择哪些人可见
42 */ 45 */
43 - private List<String> visibilityPermissions; 46 + @TableField(typeHandler = JacksonTypeHandler.class)
  47 + private List<Long> visibilityPermissions;
44 /** 48 /**
45 * 嵌入模型编号,高质量模式时维护 49 * 嵌入模型编号,高质量模式时维护
46 */ 50 */
@@ -50,7 +54,9 @@ public class AiKnowledgeBaseDO extends BaseDO { @@ -50,7 +54,9 @@ public class AiKnowledgeBaseDO extends BaseDO {
50 */ 54 */
51 private String model; 55 private String model;
52 /** 56 /**
53 - * 是否启用 57 + * 状态
  58 + * <p>
  59 + * 枚举 {@link CommonStatusEnum}
54 */ 60 */
55 - private Boolean status; 61 + private Integer status;
56 } 62 }
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeDocumentDO.java
1 package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge; 1 package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge;
2 2
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  5 +import cn.iocoder.yudao.module.ai.enums.knowledge.AiKnowledgeDocumentStatusEnum;
4 import com.baomidou.mybatisplus.annotation.IdType; 6 import com.baomidou.mybatisplus.annotation.IdType;
5 import com.baomidou.mybatisplus.annotation.TableId; 7 import com.baomidou.mybatisplus.annotation.TableId;
6 import com.baomidou.mybatisplus.annotation.TableName; 8 import com.baomidou.mybatisplus.annotation.TableName;
@@ -46,10 +48,15 @@ public class AiKnowledgeDocumentDO extends BaseDO { @@ -46,10 +48,15 @@ public class AiKnowledgeDocumentDO extends BaseDO {
46 private Integer wordCount; 48 private Integer wordCount;
47 /** 49 /**
48 * 切片状态 50 * 切片状态
  51 + * <p>
  52 + * 枚举 {@link AiKnowledgeDocumentStatusEnum}
49 */ 53 */
50 private Integer sliceStatus; 54 private Integer sliceStatus;
  55 +
51 /** 56 /**
52 - * 是否启用 57 + * 状态
  58 + * <p>
  59 + * 枚举 {@link CommonStatusEnum}
53 */ 60 */
54 - private Boolean status; 61 + private Integer status;
55 } 62 }
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeSegmentDO.java
1 package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge; 1 package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge;
2 2
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 import com.baomidou.mybatisplus.annotation.IdType; 5 import com.baomidou.mybatisplus.annotation.IdType;
5 import com.baomidou.mybatisplus.annotation.TableId; 6 import com.baomidou.mybatisplus.annotation.TableId;
@@ -41,8 +42,10 @@ public class AiKnowledgeSegmentDO extends BaseDO { @@ -41,8 +42,10 @@ public class AiKnowledgeSegmentDO extends BaseDO {
41 */ 42 */
42 private Integer tokens; 43 private Integer tokens;
43 /** 44 /**
44 - * 是否启用 45 + * 状态
  46 + * <p>
  47 + * 枚举 {@link CommonStatusEnum}
45 */ 48 */
46 - private Boolean status; 49 + private Integer status;
47 50
48 } 51 }
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeBaseMapper.java
@@ -2,11 +2,13 @@ package cn.iocoder.yudao.module.ai.dal.mysql.knowledge; @@ -2,11 +2,13 @@ package cn.iocoder.yudao.module.ai.dal.mysql.knowledge;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
4 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeBaseDO; 4 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeBaseDO;
  5 +import org.apache.ibatis.annotations.Mapper;
5 6
6 /** 7 /**
7 * AI 知识库基础信息 Mapper 8 * AI 知识库基础信息 Mapper
8 * 9 *
9 * @author xiaoxin 10 * @author xiaoxin
10 */ 11 */
  12 +@Mapper
11 public interface AiKnowledgeBaseMapper extends BaseMapperX<AiKnowledgeBaseDO> { 13 public interface AiKnowledgeBaseMapper extends BaseMapperX<AiKnowledgeBaseDO> {
12 } 14 }
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeDocumentMapper.java
@@ -2,11 +2,13 @@ package cn.iocoder.yudao.module.ai.dal.mysql.knowledge; @@ -2,11 +2,13 @@ package cn.iocoder.yudao.module.ai.dal.mysql.knowledge;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
4 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO; 4 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO;
  5 +import org.apache.ibatis.annotations.Mapper;
5 6
6 /** 7 /**
7 * AI 知识库-文档 Mapper 8 * AI 知识库-文档 Mapper
8 * 9 *
9 * @author xiaoxin 10 * @author xiaoxin
10 */ 11 */
  12 +@Mapper
11 public interface AiKnowledgeDocumentMapper extends BaseMapperX<AiKnowledgeDocumentDO> { 13 public interface AiKnowledgeDocumentMapper extends BaseMapperX<AiKnowledgeDocumentDO> {
12 } 14 }
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeSegmentMapper.java
@@ -2,11 +2,13 @@ package cn.iocoder.yudao.module.ai.dal.mysql.knowledge; @@ -2,11 +2,13 @@ package cn.iocoder.yudao.module.ai.dal.mysql.knowledge;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
4 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO; 4 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO;
  5 +import org.apache.ibatis.annotations.Mapper;
5 6
6 /** 7 /**
7 * AI 知识库-分片 Mapper 8 * AI 知识库-分片 Mapper
8 * 9 *
9 * @author xiaoxin 10 * @author xiaoxin
10 */ 11 */
  12 +@Mapper
11 public interface AiKnowledgeSegmentMapper extends BaseMapperX<AiKnowledgeSegmentDO> { 13 public interface AiKnowledgeSegmentMapper extends BaseMapperX<AiKnowledgeSegmentDO> {
12 } 14 }
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiEmbeddingService.java
1 package cn.iocoder.yudao.module.ai.service.knowledge; 1 package cn.iocoder.yudao.module.ai.service.knowledge;
2 2
3 import org.springframework.ai.document.Document; 3 import org.springframework.ai.document.Document;
  4 +import org.springframework.ai.vectorstore.SearchRequest;
4 5
5 import java.util.List; 6 import java.util.List;
6 7
@@ -12,9 +13,9 @@ import java.util.List; @@ -12,9 +13,9 @@ import java.util.List;
12 public interface AiEmbeddingService { 13 public interface AiEmbeddingService {
13 14
14 /** 15 /**
15 - * 向量化文档 16 + * 向量化文档并存储
16 */ 17 */
17 - void embeddingDoc(); 18 + void add(List<Document> documents);
18 19
19 20
20 /** 21 /**
@@ -22,5 +23,5 @@ public interface AiEmbeddingService { @@ -22,5 +23,5 @@ public interface AiEmbeddingService {
22 * 23 *
23 * @param content 查询内容 24 * @param content 查询内容
24 */ 25 */
25 - List<Document> similaritySearch(String content); 26 + List<Document> similaritySearch(SearchRequest request);
26 } 27 }
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiEmbeddingServiceImpl.java
@@ -2,11 +2,9 @@ package cn.iocoder.yudao.module.ai.service.knowledge; @@ -2,11 +2,9 @@ package cn.iocoder.yudao.module.ai.service.knowledge;
2 2
3 import jakarta.annotation.Resource; 3 import jakarta.annotation.Resource;
4 import org.springframework.ai.document.Document; 4 import org.springframework.ai.document.Document;
5 -import org.springframework.ai.reader.tika.TikaDocumentReader;  
6 -import org.springframework.ai.transformer.splitter.TokenTextSplitter;  
7 import org.springframework.ai.vectorstore.RedisVectorStore; 5 import org.springframework.ai.vectorstore.RedisVectorStore;
8 import org.springframework.ai.vectorstore.SearchRequest; 6 import org.springframework.ai.vectorstore.SearchRequest;
9 -import org.springframework.beans.factory.annotation.Value; 7 +import org.springframework.scheduling.annotation.Async;
10 import org.springframework.stereotype.Service; 8 import org.springframework.stereotype.Service;
11 9
12 import java.util.List; 10 import java.util.List;
@@ -21,27 +19,14 @@ public class AiEmbeddingServiceImpl implements AiEmbeddingService { @@ -21,27 +19,14 @@ public class AiEmbeddingServiceImpl implements AiEmbeddingService {
21 19
22 @Resource 20 @Resource
23 private RedisVectorStore vectorStore; 21 private RedisVectorStore vectorStore;
24 - @Resource  
25 - private TokenTextSplitter tokenTextSplitter;  
26 -  
27 - // TODO @xin 临时测试用,后续删  
28 - @Value("classpath:/webapp/test/Fel.pdf")  
29 - private org.springframework.core.io.Resource data;  
30 22
31 @Override 23 @Override
32 - public void embeddingDoc() {  
33 - // 读取文件  
34 - TikaDocumentReader loader = new TikaDocumentReader(data);  
35 - List<Document> documents = loader.get();  
36 - // 文档分段  
37 - List<Document> segments = tokenTextSplitter.apply(documents);  
38 - // 向量化并存储  
39 - vectorStore.add(segments); 24 + public void add(List<Document> documents) {
  25 + vectorStore.add(documents);
40 } 26 }
41 27
42 @Override 28 @Override
43 - public List<Document> similaritySearch(String content) {  
44 - SearchRequest request = SearchRequest.query(content); 29 + public List<Document> similaritySearch(SearchRequest request) {
45 return vectorStore.similaritySearch(request); 30 return vectorStore.similaritySearch(request);
46 } 31 }
47 } 32 }
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeBaseServiceImpl.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.service.knowledge; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.service.knowledge;
2 2
3 import cn.hutool.core.lang.Assert; 3 import cn.hutool.core.lang.Assert;
4 import cn.hutool.core.util.ObjUtil; 4 import cn.hutool.core.util.ObjUtil;
  5 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6 import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.AiKnowledgeCreateMyReqVO; 7 import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.AiKnowledgeCreateMyReqVO;
7 import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.AiKnowledgeUpdateMyReqVO; 8 import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.AiKnowledgeUpdateMyReqVO;
@@ -26,16 +27,18 @@ import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.KNOWLEDGE_NOT_ @@ -26,16 +27,18 @@ import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.KNOWLEDGE_NOT_
26 public class AiKnowledgeBaseServiceImpl implements AiKnowledgeBaseService { 27 public class AiKnowledgeBaseServiceImpl implements AiKnowledgeBaseService {
27 28
28 @Resource 29 @Resource
29 - private AiKnowledgeBaseMapper knowledgeBaseMapper;  
30 - @Resource  
31 private AiChatModelService chatModalService; 30 private AiChatModelService chatModalService;
32 31
  32 + @Resource
  33 + private AiKnowledgeBaseMapper knowledgeBaseMapper;
  34 +
  35 +
33 @Override 36 @Override
34 public Long createKnowledgeMy(AiKnowledgeCreateMyReqVO createReqVO, Long userId) { 37 public Long createKnowledgeMy(AiKnowledgeCreateMyReqVO createReqVO, Long userId) {
35 AiChatModelDO model = validateChatModel(createReqVO.getModelId()); 38 AiChatModelDO model = validateChatModel(createReqVO.getModelId());
36 39
37 AiKnowledgeBaseDO knowledgeBaseDO = BeanUtils.toBean(createReqVO, AiKnowledgeBaseDO.class); 40 AiKnowledgeBaseDO knowledgeBaseDO = BeanUtils.toBean(createReqVO, AiKnowledgeBaseDO.class);
38 - knowledgeBaseDO.setModel(model.getModel()).setUserId(userId); 41 + knowledgeBaseDO.setModel(model.getModel()).setUserId(userId).setStatus(CommonStatusEnum.ENABLE.getStatus());
39 42
40 knowledgeBaseMapper.insert(knowledgeBaseDO); 43 knowledgeBaseMapper.insert(knowledgeBaseDO);
41 return knowledgeBaseDO.getId(); 44 return knowledgeBaseDO.getId();
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentService.java
1 package cn.iocoder.yudao.module.ai.service.knowledge; 1 package cn.iocoder.yudao.module.ai.service.knowledge;
2 2
  3 +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.AiKnowledgeDocumentCreateReqVO;
  4 +
3 /** 5 /**
4 * AI 知识库-文档 Service 接口 6 * AI 知识库-文档 Service 接口
5 * 7 *
@@ -7,4 +9,13 @@ package cn.iocoder.yudao.module.ai.service.knowledge; @@ -7,4 +9,13 @@ package cn.iocoder.yudao.module.ai.service.knowledge;
7 */ 9 */
8 public interface AiKnowledgeDocumentService { 10 public interface AiKnowledgeDocumentService {
9 11
  12 +
  13 + /**
  14 + * 创建文档
  15 + *
  16 + * @param createReqVO 文档创建 Request VO
  17 + * @return 文档编号
  18 + */
  19 + Long createKnowledgeDocument(AiKnowledgeDocumentCreateReqVO createReqVO);
  20 +
10 } 21 }
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentServiceImpl.java
1 package cn.iocoder.yudao.module.ai.service.knowledge; 1 package cn.iocoder.yudao.module.ai.service.knowledge;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  5 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  6 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  7 +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.AiKnowledgeDocumentCreateReqVO;
  8 +import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO;
  9 +import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO;
  10 +import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeDocumentMapper;
  11 +import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeSegmentMapper;
  12 +import cn.iocoder.yudao.module.ai.enums.knowledge.AiKnowledgeDocumentStatusEnum;
  13 +import jakarta.annotation.Resource;
3 import lombok.extern.slf4j.Slf4j; 14 import lombok.extern.slf4j.Slf4j;
  15 +import org.springframework.ai.document.Document;
  16 +import org.springframework.ai.reader.tika.TikaDocumentReader;
  17 +import org.springframework.ai.transformer.splitter.TokenTextSplitter;
  18 +import org.springframework.beans.factory.annotation.Value;
4 import org.springframework.stereotype.Service; 19 import org.springframework.stereotype.Service;
  20 +import org.springframework.transaction.annotation.Transactional;
  21 +
  22 +import java.util.List;
5 23
6 /** 24 /**
7 * AI 知识库-文档 Service 实现类 25 * AI 知识库-文档 Service 实现类
@@ -12,5 +30,55 @@ import org.springframework.stereotype.Service; @@ -12,5 +30,55 @@ import org.springframework.stereotype.Service;
12 @Slf4j 30 @Slf4j
13 public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentService { 31 public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentService {
14 32
  33 + @Resource
  34 + private AiKnowledgeDocumentMapper documentMapper;
  35 + @Resource
  36 + private AiKnowledgeSegmentMapper segmentMapper;
  37 +
  38 + @Resource
  39 + private TokenTextSplitter tokenTextSplitter;
  40 +
  41 + @Resource
  42 + private AiEmbeddingService embeddingService;
  43 +
  44 + // TODO @xin 临时测试用,后续删
  45 + @Value("classpath:/webapp/test/Fel.pdf")
  46 + private org.springframework.core.io.Resource data;
  47 +
  48 +
  49 + @Override
  50 + @Transactional(rollbackFor = Exception.class)
  51 + public Long createKnowledgeDocument(AiKnowledgeDocumentCreateReqVO createReqVO) {
  52 + AiKnowledgeDocumentDO documentDO = BeanUtils.toBean(createReqVO, AiKnowledgeDocumentDO.class);
  53 + documentDO
  54 + //todo
  55 + .setTokens(0).setWordCount(0)
  56 + .setStatus(CommonStatusEnum.ENABLE.getStatus()).setSliceStatus(AiKnowledgeDocumentStatusEnum.SUCCESS.getStatus());
  57 + documentMapper.insert(documentDO);
  58 +
  59 + TikaDocumentReader loader = new TikaDocumentReader(data);
  60 + List<Document> documents = loader.get();
  61 + Long documentId = documentDO.getId();
  62 + if (CollUtil.isEmpty(documents)) {
  63 + log.info("文档内容为空");
  64 + return documentId;
  65 + }
  66 +
  67 + // 文档分段
  68 + List<Document> segments = tokenTextSplitter.apply(documents);
  69 +
  70 + List<AiKnowledgeSegmentDO> segmentDOList = CollectionUtils.convertList(segments,
  71 + segment -> new AiKnowledgeSegmentDO().setContent(segment.getContent()).setDocumentId(documentId)
  72 + //todo
  73 + .setTokens(0).setWordCount(0)
  74 + .setStatus(CommonStatusEnum.ENABLE.getStatus()));
  75 +
  76 + // 分段内容入库
  77 + segmentMapper.insertBatch(segmentDOList);
  78 +
  79 + //向量化并存储
  80 + embeddingService.add(segments);
15 81
  82 + return documentId;
  83 + }
16 } 84 }