在现代数据处理中,ETL(Extract, Transform, Load)管道是一个非常重要的概念。它允许我们从不同的数据源中提取数据,进行必要的转换,然后将数据加载到目标存储系统中。本文将介绍如何使用 Spring AI 和 Apache Tika 构建一个简单的 ETL 管道,特别是如何利用 spring-ai-tika-document-reader
依赖来处理和转换文档数据。
1. 框架介绍
1.1 Spring AI 简介
Spring AI 是一个基于 Spring 生态系统的框架,旨在简化人工智能和机器学习模型的集成。它提供了丰富的工具和库,帮助开发者快速构建智能应用。Spring AI 不仅支持常见的机器学习任务,还提供了与各种数据源的集成能力,使得数据处理变得更加高效。
1.2 Apache Tika 简介
Apache Tika 是一个内容分析工具包,能够从各种文档格式(如 PDF、Word、Excel 等)中提取文本和元数据。Tika 提供了一个简单的 API,使得开发者可以轻松地将文档内容提取并转换为结构化数据。
1.3 spring-ai-tika-document-reader
依赖
spring-ai-tika-document-reader
是 Spring AI 提供的一个扩展库,它集成了 Apache Tika 的功能,使得在 Spring 应用中处理文档变得更加简单。通过这个依赖,我们可以轻松地将文档内容提取并转换为 Spring AI 可以处理的格式。
2. 转换文档
2.1 添加依赖
首先,我们需要在 pom.xml 中添加 spring-ai-tika-document-reader
依赖:
<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-tika-document-reader</artifactId><version>1.0.0-M5</version>
</dependency>
- 读取文件。
/*** 从输入流中读取文件。像后端接收前端文件时,就可以使用。* @param file 附件信息* @return*/@PostMapping("etl/read/multipart-file")public String readMultipartFile(@RequestParam MultipartFile file) {// 从IO流中读取文件Resource resource = new InputStreamResource(file.getInputStream());List<Document> documents = new TikaDocumentReader(resource).get();return documents.get(0).getContent();}/*** 从本地文件读取文件。* @param filePath 本地文件地址* @return*/@GetMapping("etl/read/local-file")public String readFile(@RequestParam String filePath) {// 从本地文件读取文件Resource resource = new FileSystemResource("C:\\Users\\augjm\\Desktop\\note.txt");List<Document> documents = new TikaDocumentReader(resource).get();return documents.get(0).getContent();}/*** 从网络资源读取文件。* @param filePath 从网络资源读取文件地址* @return*/@GetMapping("etl/read/url-file")public String readUrl(@RequestParam String filePath) {// 从网络资源读取文件。Resource resource = new UrlResource(filePath);List<Document> documents = new TikaDocumentReader(resource).get();return documents.get(0).getContent();}
2.2 转换文档
Document对象是ETL Pipeline的核心对象,它包含了文档的元数据和内容。
内容转换器:
TokenTextSplitter:可以把内容切割成更小的块方便RAG的时候提升响应速度节省Token。
ContentFormatTransformer:可以把元数据的内容变成键值对字符串。
元数据转换器:
SummaryMetadataEnricher:使用大模型总结文档。会在元数据里面增加一个summary字段。
KeywordMetadataEnricher:使用大模型提取文档关键词。可以在元数据里面增加一个keywords字段。
/*** 将文本内容划分成更小的块。* @param file 附件信息* @return*/@SneakyThrows@PostMapping("etl/transform/split")public List<String> split(@RequestParam MultipartFile file) {// 从IO流中读取文件TikaDocumentReader tikaDocumentReader = new TikaDocumentReader(new InputStreamResource(file.getInputStream()));// 将文本内容划分成更小的块List<Document> splitDocuments = new TokenTextSplitter().apply(tikaDocumentReader.get());return splitDocuments.stream().map(Document::getContent).toList();}
在这个例子中,split
方法会将每个 Document
对象的内容切割成更小的块,并返回一个新的 Document
对象列表。
2.2 存储文档
根据以上步骤,就将文档切割各个块,然后就可以将其存储到向量数据库中了
/*** 嵌入文件** @param file 待嵌入的文件* @return 是否成功*/@PostMapping("save/file/vectorStore")public Boolean saveFileVectorStore(@RequestParam MultipartFile file) {// 从IO流中读取文件TikaDocumentReader tikaDocumentReader = new TikaDocumentReader(new InputStreamResource(file.getInputStream()));// 将文本内容划分成更小的块List<Document> splitDocuments = new TokenTextSplitter().apply(tikaDocumentReader.get());// 存入向量数据库,这个过程会自动调用embeddingModel,将文本变成向量再存入。elasticVectorStore.add(splitDocuments);return true;}