Commit 238f603f690ef7e747b177729237af1a008b3056
1 parent
d3a4c3c7
【新增】AI 知识库:文档 token、字符数计算
Showing
3 changed files
with
21 additions
and
13 deletions
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiEmbeddingService.java
| @@ -21,7 +21,7 @@ public interface AiEmbeddingService { | @@ -21,7 +21,7 @@ public interface AiEmbeddingService { | ||
| 21 | /** | 21 | /** |
| 22 | * 相似查询 | 22 | * 相似查询 |
| 23 | * | 23 | * |
| 24 | - * @param content 查询内容 | 24 | + * @param request 查询实体 |
| 25 | */ | 25 | */ |
| 26 | List<Document> similaritySearch(SearchRequest request); | 26 | List<Document> similaritySearch(SearchRequest request); |
| 27 | } | 27 | } |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiEmbeddingServiceImpl.java
| @@ -4,7 +4,6 @@ import jakarta.annotation.Resource; | @@ -4,7 +4,6 @@ import jakarta.annotation.Resource; | ||
| 4 | import org.springframework.ai.document.Document; | 4 | import org.springframework.ai.document.Document; |
| 5 | import org.springframework.ai.vectorstore.RedisVectorStore; | 5 | import org.springframework.ai.vectorstore.RedisVectorStore; |
| 6 | import org.springframework.ai.vectorstore.SearchRequest; | 6 | import org.springframework.ai.vectorstore.SearchRequest; |
| 7 | -import org.springframework.scheduling.annotation.Async; | ||
| 8 | import org.springframework.stereotype.Service; | 7 | import org.springframework.stereotype.Service; |
| 9 | 8 | ||
| 10 | import java.util.List; | 9 | import java.util.List; |
| @@ -21,6 +20,8 @@ public class AiEmbeddingServiceImpl implements AiEmbeddingService { | @@ -21,6 +20,8 @@ public class AiEmbeddingServiceImpl implements AiEmbeddingService { | ||
| 21 | private RedisVectorStore vectorStore; | 20 | private RedisVectorStore vectorStore; |
| 22 | 21 | ||
| 23 | @Override | 22 | @Override |
| 23 | +// @Async | ||
| 24 | + // TODO xiaoxin 报错先注释 | ||
| 24 | public void add(List<Document> documents) { | 25 | public void add(List<Document> documents) { |
| 25 | vectorStore.add(documents); | 26 | vectorStore.add(documents); |
| 26 | } | 27 | } |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentServiceImpl.java
| @@ -14,12 +14,14 @@ import jakarta.annotation.Resource; | @@ -14,12 +14,14 @@ import jakarta.annotation.Resource; | ||
| 14 | import lombok.extern.slf4j.Slf4j; | 14 | import lombok.extern.slf4j.Slf4j; |
| 15 | import org.springframework.ai.document.Document; | 15 | import org.springframework.ai.document.Document; |
| 16 | import org.springframework.ai.reader.tika.TikaDocumentReader; | 16 | import org.springframework.ai.reader.tika.TikaDocumentReader; |
| 17 | +import org.springframework.ai.tokenizer.JTokkitTokenCountEstimator; | ||
| 17 | import org.springframework.ai.transformer.splitter.TokenTextSplitter; | 18 | import org.springframework.ai.transformer.splitter.TokenTextSplitter; |
| 18 | import org.springframework.beans.factory.annotation.Value; | 19 | import org.springframework.beans.factory.annotation.Value; |
| 19 | import org.springframework.stereotype.Service; | 20 | import org.springframework.stereotype.Service; |
| 20 | import org.springframework.transaction.annotation.Transactional; | 21 | import org.springframework.transaction.annotation.Transactional; |
| 21 | 22 | ||
| 22 | import java.util.List; | 23 | import java.util.List; |
| 24 | +import java.util.Objects; | ||
| 23 | 25 | ||
| 24 | /** | 26 | /** |
| 25 | * AI 知识库-文档 Service 实现类 | 27 | * AI 知识库-文档 Service 实现类 |
| @@ -41,7 +43,9 @@ public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentServic | @@ -41,7 +43,9 @@ public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentServic | ||
| 41 | @Resource | 43 | @Resource |
| 42 | private AiEmbeddingService embeddingService; | 44 | private AiEmbeddingService embeddingService; |
| 43 | 45 | ||
| 44 | - // TODO @xin 临时测试用,后续删 | 46 | + private static final JTokkitTokenCountEstimator TOKEN_COUNT_ESTIMATOR = new JTokkitTokenCountEstimator(); |
| 47 | + | ||
| 48 | + // TODO xiaoxin 临时测试用,后续删 | ||
| 45 | @Value("classpath:/webapp/test/Fel.pdf") | 49 | @Value("classpath:/webapp/test/Fel.pdf") |
| 46 | private org.springframework.core.io.Resource data; | 50 | private org.springframework.core.io.Resource data; |
| 47 | 51 | ||
| @@ -49,18 +53,23 @@ public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentServic | @@ -49,18 +53,23 @@ public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentServic | ||
| 49 | @Override | 53 | @Override |
| 50 | @Transactional(rollbackFor = Exception.class) | 54 | @Transactional(rollbackFor = Exception.class) |
| 51 | public Long createKnowledgeDocument(AiKnowledgeDocumentCreateReqVO createReqVO) { | 55 | 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 | 56 | ||
| 57 | + // TODO xiaoxin 后续从 url 加载 | ||
| 59 | TikaDocumentReader loader = new TikaDocumentReader(data); | 58 | TikaDocumentReader loader = new TikaDocumentReader(data); |
| 59 | + // 加载文档 | ||
| 60 | List<Document> documents = loader.get(); | 60 | List<Document> documents = loader.get(); |
| 61 | + Document document = CollUtil.getFirst(documents); | ||
| 62 | + // TODO 芋艿 文档层面有没有可能会比较大,这两个字段是否可以从分段表计算得出? | ||
| 63 | + Integer tokens = Objects.nonNull(document) ? TOKEN_COUNT_ESTIMATOR.estimate(document.getContent()) : 0; | ||
| 64 | + Integer wordCount = Objects.nonNull(document) ? document.getContent().length() : 0; | ||
| 65 | + | ||
| 66 | + AiKnowledgeDocumentDO documentDO = BeanUtils.toBean(createReqVO, AiKnowledgeDocumentDO.class); | ||
| 67 | + documentDO.setTokens(tokens).setWordCount(wordCount) | ||
| 68 | + .setStatus(CommonStatusEnum.ENABLE.getStatus()).setSliceStatus(AiKnowledgeDocumentStatusEnum.SUCCESS.getStatus()); | ||
| 69 | + // 文档记录入库 | ||
| 70 | + documentMapper.insert(documentDO); | ||
| 61 | Long documentId = documentDO.getId(); | 71 | Long documentId = documentDO.getId(); |
| 62 | if (CollUtil.isEmpty(documents)) { | 72 | if (CollUtil.isEmpty(documents)) { |
| 63 | - log.info("文档内容为空"); | ||
| 64 | return documentId; | 73 | return documentId; |
| 65 | } | 74 | } |
| 66 | 75 | ||
| @@ -69,10 +78,8 @@ public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentServic | @@ -69,10 +78,8 @@ public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentServic | ||
| 69 | 78 | ||
| 70 | List<AiKnowledgeSegmentDO> segmentDOList = CollectionUtils.convertList(segments, | 79 | List<AiKnowledgeSegmentDO> segmentDOList = CollectionUtils.convertList(segments, |
| 71 | segment -> new AiKnowledgeSegmentDO().setContent(segment.getContent()).setDocumentId(documentId) | 80 | segment -> new AiKnowledgeSegmentDO().setContent(segment.getContent()).setDocumentId(documentId) |
| 72 | - //todo | ||
| 73 | - .setTokens(0).setWordCount(0) | 81 | + .setTokens(TOKEN_COUNT_ESTIMATOR.estimate(segment.getContent())).setWordCount(segment.getContent().length()) |
| 74 | .setStatus(CommonStatusEnum.ENABLE.getStatus())); | 82 | .setStatus(CommonStatusEnum.ENABLE.getStatus())); |
| 75 | - | ||
| 76 | // 分段内容入库 | 83 | // 分段内容入库 |
| 77 | segmentMapper.insertBatch(segmentDOList); | 84 | segmentMapper.insertBatch(segmentDOList); |
| 78 | 85 |