在企业内部构建基于大型语言模型(LLM)的应用程序时,数据的提取、转换和加载(ETL)过程至关重要。Spring AI 提供了一个集成的框架,可以简化这一过程,特别是在使用 LLM 进行检索增强生成(RAG)时。以下是如何将 Spring AI 与 ETL 管道集成的基本步骤:
- 数据提取:使用 Spring AI 提供的
DocumentReader
来读取不同格式的文档,如文本、JSON、PDF 等。这些阅读器负责从原始数据源中提取内容,并将其转换为可以被 LLM 处理的格式。 - 数据转换:
DocumentTransformer
用于转换提取的数据,确保数据的格式统一,并进行必要的元数据增强。例如,可以使用KeywordMetadataEnricher
和SummaryMetadataEnricher
来从文档中提取关键词和摘要,以增强检索能力。 - 数据加载:转换后的数据可以通过
DocumentWriter
加载到向量数据库中,以便 LLM 可以检索和使用这些数据来生成响应。VectorStore
是一个常用的实现,它支持存储向量数据,便于进行相似性搜索。
在实施 ETL 管道时,可以利用 Spring AI 提供的现成组件和工具,这些组件和工具经过设计,可以协同工作,简化数据处理流程。
此外,Spring AI 的模块化设计允许开发者根据具体需求选择合适的组件,并根据应用程序的规模进行扩展。
SpringAI ETL设计
ETL 管道主要有三个组件:
- 文档加载:
DocumentReader
实现Supplier<List<Document>>
- 文档转换:
DocumentTransformer
实现Function<List<Document>, List<Document>>
- 写出数据:
DocumentWriter
实现Consumer<List<Document>>
要构造简单的 ETL 管道,您可以将每种类型的实例链接在一起。
文档提取Loader
文档的加载在SpringAI中提供了多种文件加载工具,如下:
- Json加载器:
JsonReader
- 文本加载器:
TextReader
- PDF加载器:
PagePdfDocumentReader
和段落PdfDocumentReader
- 三方工具:
TikaDocumentReader
测试文件:【免费】易车实战学习Langchain开发配套文档附件资源
加载Json文件
可以使用此reader加载Json格式的文件,代码如下所示:
/**
* 加载Json文档
*
* @return 文档内容
*/
@GetMapping("/json")
List<Document> loadJsonAsDocuments() {
// 加载文件
Resource resource = new ClassPathResource("etl.json");
// 创建reader对象
JsonReader jsonReader = new JsonReader(resource);
// 获取内容
return jsonReader.get();
}
加载文本
可以使用此reader加载txt格式的文件,代码如下所示:
/**
* 加兹文本文件内容
*
* @return 文本内容
*/
@GetMapping("/text")
List<Document> loadText() {
// 创建加载
TextReader textReader = new TextReader(new ClassPathResource("etl.txt"));
// 获取内容
return textReader.read();
}
加载文件档(PDF, DOC/DOCX, PPT/PPTX, HTML)
/**
* 使用tika加载PDF, DOC/DOCX, PPT/PPTX, and HTML等文件
* @return 文件内容
*/
@GetMapping("/file")
List<Document> loadFile() {
TikaDocumentReader tikaDocumentReader = new TikaDocumentReader(new ClassPathResource("汽车销售话术.pdf"));
return tikaDocumentReader.read();
}
文件转换Transform
在springai中所有的文件处理工具,都实现于DocumentTransformer
接口,如下所示:
TokenTextSplitter
:拆分文档,同时保留令牌级完整性。ContentFormatTransformer
(内容格式转换器):确保所有文档的内容格式统一。KeywordMetadataEnricher
(关键字MetadataEnricher):使用基本关键字元数据扩充文档。SummaryMetadataEnricher
(摘要元数据丰富):使用摘要元数据丰富文档,以增强检索能力。
基于上面提到的案例,文件加载之后,咱们继续使用transform工具对文件内容进行切分处理:
/**
* 1. 加载PDF内容
* 2. 文本进行切分
*
* @return
*/
@GetMapping("/file")
List<?> fileContentProcess() {
TikaDocumentReader tikaDocumentReader = new TikaDocumentReader(new ClassPathResource("汽车销售话术.pdf"));
List<Document> documentList = tikaDocumentReader.read();
if (CollectionUtil.isEmpty(documentList)) {
return Collections.EMPTY_LIST;
}
return new TokenTextSplitter().apply(documentList);
}
如果想要控制切分的Chunk size和分隔符的话,可以在创建TokenTextSplitter
进行设置。
public class TokenTextSplitter extends TextSplitter {
// The target size of each text chunk in tokens
private int defaultChunkSize = 800;
// The minimum size of each text chunk in characters
private int minChunkSizeChars = 350;
// Discard chunks shorter than this
private int minChunkLengthToEmbed = 5;
// The maximum number of chunks to generate from a text
private int maxNumChunks = 10000;
private boolean keepSeparator = true;
public TokenTextSplitter(int defaultChunkSize, int minChunkSizeChars, int minChunkLengthToEmbed, int maxNumChunks,
boolean keepSeparator) {
this.defaultChunkSize = defaultChunkSize;
this.minChunkSizeChars = minChunkSizeChars;
this.minChunkLengthToEmbed = minChunkLengthToEmbed;
this.maxNumChunks = maxNumChunks;
this.keepSeparator = keepSeparator;
}
// ...
}
文件向量化存储
此部分内容,下节详细说明。