抽取、转换与加载(ETL)框架是检索增强生成(RAG)应用场景中数据处理的核心支柱。
ETL 流水线统筹管理从原始数据源到结构化向量库的数据流,确保数据以最优格式供 AI 模型检索使用。
RAG 应用场景通过从数据集中检索相关信息来增强生成式模型的能力,以此提升生成输出的质量和相关性。
API 概述
ETL 流水线负责创建、转换并存储文档实例。
Spring AI 消息 API
文档类包含文本、元数据,以及可选的图片、音频、视频等其他媒体类型。
ETL 流水线包含三大核心组件:
文档读取器,实现了 Supplier<List<Document>> 接口
文档转换器,实现了 Function<List<Document>, List<Document>> 接口
文档写入器,实现了 Consumer<List<Document>> 接口
借助文档读取器,可从 PDF、文本文件及其他文档类型中创建文档类的内容。
构建一条简单的 ETL 流水线,你可以将这三类组件的实例串联使用。
ETL 流水线
假设我们拥有以下三种 ETL 类型的实例:
分页 PDF 文档读取器:文档读取器的一种实现
令牌文本分割器:文档转换器的一种实现
向量库:文档写入器的一种实现
若要按照检索增强生成模式将数据基础加载到向量数据库中,可使用以下 Java 函数式语法代码:
vectorStore.accept(tokenTextSplitter.apply(pdfReader.get()));
你也可以使用更贴合业务领域的自然表达方法名:
vectorStore.write(tokenTextSplitter.split(pdfReader.read()));
ETL 接口
ETL 流水线由以下接口和实现类组成。详细的 ETL 类图见 ETL 类图章节。
文档读取器
从多种来源提供文档数据。
public interface DocumentReader extends Supplier<List<Document>> {
default List<Document> read() {
return get();
}
}文档转换器
作为处理工作流的一部分,批量转换文档。
public interface DocumentTransformer extends Function<List<Document>, List<Document>> {
default List<Document> transform(List<Document> transform) {
return apply(transform);
}
}文档写入器
管理 ETL 流程的最终阶段,为文档存储做准备。
public interface DocumentWriter extends Consumer<List<Document>> {
default void write(List<Document> documents) {
accept(documents);
}
}文档读取器
JSON 格式
JSON 读取器用于处理 JSON 文档,将其转换为文档对象列表。
示例
@Component
class MyJsonReader {
private final Resource resource;
MyJsonReader(@Value("classpath:bikes.json") Resource resource) {
this.resource = resource;
}
List<Document> loadJsonAsDocuments() {
JsonReader jsonReader = new JsonReader(this.resource, "description", "content");
return jsonReader.get();
}
}构造方法选项
JSON 读取器提供多种构造方法:
JsonReader(Resource resource)
JsonReader(Resource resource, String… jsonKeysToUse)
JsonReader(Resource resource, JsonMetadataGenerator jsonMetadataGenerator, String… jsonKeysToUse)
参数
resource:指向 JSON 文件的 Spring 资源对象
jsonKeysToUse:JSON 中需作为结果文档对象文本内容的键数组
jsonMetadataGenerator:可选的 JSON 元数据生成器,用于为每个文档创建元数据
行为
JSON 读取器处理 JSON 内容的规则如下:
可同时处理 JSON 数组和单个 JSON 对象
对每个 JSON 对象(数组内或单个对象):
根据指定的 jsonKeysToUse 提取内容
若未指定键,则使用整个 JSON 对象作为内容
通过提供的 JSON 元数据生成器生成元数据(未提供则生成空元数据)
使用提取的内容和元数据创建文档对象
使用 JSON 指针
JSON 读取器现已支持通过 JSON 指针获取 JSON 文档的指定部分。该功能可轻松从复杂 JSON 结构中提取嵌套数据。
get(String pointer) 方法
public List<Document> get(String pointer)
该方法允许使用 JSON 指针获取 JSON 文档的指定部分。
参数
pointer:符合 RFC 6901 规范的 JSON 指针字符串,用于定位 JSON 结构中的目标元素
返回值
返回由 JSON 指针定位元素解析得到的文档列表。
行为
该方法通过传入的 JSON 指针导航至 JSON 结构的指定位置
若指针有效且指向存在的元素:
JSON 对象:返回包含单个文档的列表
JSON 数组:返回与数组元素一一对应的文档列表
若指针无效或指向不存在的元素,抛出非法参数异常
示例
JsonReader jsonReader = new JsonReader(resource, "description");
List<Document> documents = this.jsonReader.get("/store/books/0");示例 JSON 结构
[
{
"id": 1,
"brand": "Trek",
"description": "A high-performance mountain bike for trail riding."
},
{
"id": 2,
"brand": "Cannondale",
"description": "An aerodynamic road bike for racing enthusiasts."
}
]本示例中,若 JSON 读取器配置 "description" 为 jsonKeysToUse,会为数组中每辆自行车创建文档对象,内容为 "description" 字段的值。
注意事项
JSON 读取器基于 Jackson 解析 JSON
通过流式处理数组,可高效处理大型 JSON 文件
若 jsonKeysToUse 指定多个键,内容为这些键对应值的拼接结果
通过自定义 jsonKeysToUse 和 JSON 元数据生成器,可适配多种 JSON 结构
纯文本格式
文本读取器用于处理纯文本文档,将其转换为文档对象列表。
示例
@Component
class MyTextReader {
private final Resource resource;
MyTextReader(@Value("classpath:text-source.txt") Resource resource) {
this.resource = resource;
}
List<Document> loadText() {
TextReader textReader = new TextReader(this.resource);
textReader.getCustomMetadata().put("filename", "text-source.txt");
return textReader.read();
}
}构造方法选项
文本读取器提供两种构造方法:
TextReader(String resourceUrl)
TextReader(Resource resource)
参数
resourceUrl:表示待读取资源 URL 的字符串
resource:指向文本文件的 Spring 资源对象
配置
setCharset(Charset charset):设置读取文本文件的字符集,默认为 UTF-8
getCustomMetadata():返回可变映射,可添加文档的自定义元数据
行为
文本读取器处理文本内容的规则如下:
将文本文件全部内容读取到单个文档对象中
文件内容作为文档的内容
自动为文档添加元数据:
charset:读取文件使用的字符集(默认:UTF-8)
source:源文本文件的文件名
通过 getCustomMetadata() 添加的自定义元数据也会包含在文档中
注意事项
文本读取器会将文件全部内容加载到内存,不适合超大文件
若需将文本分割为更小片段,读取文档后可使用令牌文本分割器:
List<Document> documents = textReader.get(); List<Document> splitDocuments = new TokenTextSplitter().apply(this.documents);
读取器基于 Spring 资源抽象,可读取多种来源(类路径、文件系统、URL 等)
可通过 getCustomMetadata() 方法为读取器创建的所有文档添加自定义元数据
HTML 格式(基于 JSoup)
JSoup 文档读取器基于 JSoup 库处理 HTML 文档,将其转换为文档对象列表。
依赖
使用 Maven 或 Gradle 为项目添加依赖。
Maven
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-jsoup-document-reader</artifactId> </dependency>
示例
@Component
class MyHtmlReader {
private final Resource resource;
MyHtmlReader(@Value("classpath:/my-page.html") Resource resource) {
this.resource = resource;
}
List<Document> loadHtml() {
JsoupDocumentReaderConfig config = JsoupDocumentReaderConfig.builder()
.selector("article p") // 提取 article 标签内的段落
.charset("ISO-8859-1") // 使用 ISO-8859-1 编码
.includeLinkUrls(true) // 在元数据中包含链接 URL
.metadataTags(List.of("author", "date")) // 提取作者和日期元标签
.additionalMetadata("source", "my-page.html") // 添加自定义元数据
.build();
JsoupDocumentReader reader = new JsoupDocumentReader(this.resource, config);
return reader.get();
}
}JSoup 文档读取器配置可自定义读取器行为:
charset:指定 HTML 文档的字符编码,默认 UTF-8
selector:JSoup CSS 选择器,指定提取文本的元素,默认 body
separator:拼接多个选中元素文本的字符串,默认换行符
allElements:若为 true,提取 body 内所有文本,忽略选择器,默认 false
groupByElement:若为 true,选择器匹配的每个元素创建独立文档,默认 false
includeLinkUrls:若为 true,提取绝对链接 URL 并加入元数据,默认 false
metadataTags:需提取内容的 meta 标签列表,默认 ["description", "keywords"]
additionalMetadata:为所有创建的文档对象添加自定义元数据
示例文档:my-page.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>My Web Page</title> <meta name="description" content="A sample web page for Spring AI"> <meta name="keywords" content="spring, ai, html, example"> <meta name="author" content="John Doe"> <meta name="date" content="2024-01-15"> <link rel="stylesheet" href="style.css"> </head> <body> <header> <h1>Welcome to My Page</h1> </header> <nav> <ul> <li><a href="/">Home</a></li> <li><a href="/about">About</a></li> </ul> </nav> <article> <h2>Main Content</h2> <p>This is the main content of my web page.</p> <p>It contains multiple paragraphs.</p> <a href="https://www.example.com">External Link</a> </article> <footer> <p>© 2024 John Doe</p> </footer> </body> </html>
行为
JSoup 文档读取器处理 HTML 内容并根据配置创建文档对象:
选择器决定提取文本的元素
若 allElements 为 true,body 内所有文本提取到单个文档
若 groupByElement 为 true,选择器匹配的每个元素创建独立文档
若两者均为 false,选择器匹配的所有元素文本通过分隔符拼接
文档标题、指定 meta 标签内容、(可选)链接 URL 加入文档元数据
解析相对链接的基础 URI 从 URL 资源中提取
读取器保留选中元素的文本内容,移除内部 HTML 标签
Markdown 格式
Markdown 文档读取器用于处理 Markdown 文档,将其转换为文档对象列表。
依赖
使用 Maven 或 Gradle 为项目添加依赖。
Maven
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-markdown-document-reader</artifactId> </dependency>
示例
@Component
class MyMarkdownReader {
private final Resource resource;
MyMarkdownReader(@Value("classpath:code.md") Resource resource) {
this.resource = resource;
}
List<Document> loadMarkdown() {
MarkdownDocumentReaderConfig config = MarkdownDocumentReaderConfig.builder()
.withHorizontalRuleCreateDocument(true)
.withIncludeCodeBlock(false)
.withIncludeBlockquote(false)
.withAdditionalMetadata("filename", "code.md")
.build();
MarkdownDocumentReader reader = new MarkdownDocumentReader(this.resource, config);
return reader.get();
}
}Markdown 文档读取器配置可自定义读取器行为:
horizontalRuleCreateDocument:为 true 时,Markdown 中的水平分隔线创建新文档对象
includeCodeBlock:为 true 时,代码块与周围文本包含在同一文档;为 false 时,代码块创建独立文档
includeBlockquote:为 true 时,引用块与周围文本包含在同一文档;为 false 时,引用块创建独立文档
additionalMetadata:为所有创建的文档对象添加自定义元数据
示例文档:code.md
This is a Java sample application:
```java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
```
Markdown also provides the possibility to `use inline code formatting throughout` the entire sentence.
---
Another possibility is to set block code without specific highlighting:
```
./mvnw spring-javaformat:apply
```行为
Markdown 文档读取器处理 Markdown 内容并根据配置创建文档对象:
标题转为文档对象的元数据
段落转为文档对象的内容
代码块可分离为独立文档或与周围文本合并
引用块可分离为独立文档或与周围文本合并
水平分隔线可将内容分割为独立文档
读取器保留文档内容中的行内代码、列表、文本样式等格式
PDF 分页格式
分页 PDF 文档读取器基于 Apache PdfBox 库解析 PDF 文档。
依赖
使用 Maven 或 Gradle 为项目添加依赖。
Maven
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-pdf-document-reader</artifactId> </dependency>
示例
@Component
public class MyPagePdfDocumentReader {
List<Document> getDocsFromPdf() {
PagePdfDocumentReader pdfReader = new PagePdfDocumentReader("classpath:/sample1.pdf",
PdfDocumentReaderConfig.builder()
.withPageTopMargin(0)
.withPageExtractedTextFormatter(ExtractedTextFormatter.builder()
.withNumberOfTopTextLinesToDelete(0)
.build())
.withPagesPerDocument(1)
.build());
return pdfReader.read();
}
}PDF 段落格式
段落 PDF 文档读取器利用 PDF 目录(如目录)信息将输入 PDF 分割为文本段落,每个段落输出一个文档。注意:并非所有 PDF 文档都包含目录。
依赖
使用 Maven 或 Gradle 为项目添加依赖。
Maven
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-pdf-document-reader</artifactId> </dependency>
示例
@Component
public class MyPagePdfDocumentReader {
List<Document> getDocsFromPdfWithCatalog() {
ParagraphPdfDocumentReader pdfReader = new ParagraphPdfDocumentReader("classpath:/sample1.pdf",
PdfDocumentReaderConfig.builder()
.withPageTopMargin(0)
.withPageExtractedTextFormatter(ExtractedTextFormatter.builder()
.withNumberOfTopTextLinesToDelete(0)
.build())
.withPagesPerDocument(1)
.build());
return pdfReader.read();
}
}Tika 格式(DOCX、PPTX、HTML 等)
Tika 文档读取器基于 Apache Tika 从多种文档格式提取文本,包括 PDF、DOC/DOCX、PPT/PPTX、HTML 等。完整支持格式列表参考 Tika 官方文档。
依赖
使用 Maven 或 Gradle 为项目添加依赖。
Maven
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-tika-document-reader</artifactId> </dependency>
示例
@Component
class MyTikaDocumentReader {
private final Resource resource;
MyTikaDocumentReader(@Value("classpath:/word-sample.docx")
Resource resource) {
this.resource = resource;
}
List<Document> loadText() {
TikaDocumentReader tikaDocumentReader = new TikaDocumentReader(this.resource);
return tikaDocumentReader.read();
}
}转换器
文本分割器
文本分割器是抽象基类,用于分割文档以适配 AI 模型的上下文窗口。
令牌文本分割器
令牌文本分割器是文本分割器的实现类,基于令牌数量分割文本,使用 CL100K_BASE 编码。
用法
基础用法
@Component
class MyTokenTextSplitter {
public List<Document> splitDocuments(List<Document> documents) {
TokenTextSplitter splitter = new TokenTextSplitter();
return splitter.apply(documents);
}
public List<Document> splitCustomized(List<Document> documents) {
TokenTextSplitter splitter = new TokenTextSplitter(1000, 400, 10, 5000, true, List.of('.', '?', '!', '\n'));
return splitter.apply(documents);
}
}使用建造者模式
推荐使用建造者模式创建令牌文本分割器,API 更易读、更灵活:
@Component
class MyTokenTextSplitter {
public List<Document> splitWithBuilder(List<Document> documents) {
TokenTextSplitter splitter = TokenTextSplitter.builder()
.withChunkSize(1000)
.withMinChunkSizeChars(400)
.withMinChunkLengthToEmbed(10)
.withMaxNumChunks(5000)
.withKeepSeparator(true)
.build();
return splitter.apply(documents);
}
}自定义标点符号
可自定义用于将文本分割为语义片段的标点符号,对国际化场景尤为实用:
@Component
class MyInternationalTextSplitter {
public List<Document> splitChineseText(List<Document> documents) {
// 使用中文标点符号
TokenTextSplitter splitter = TokenTextSplitter.builder()
.withChunkSize(800)
.withMinChunkSizeChars(350)
.withPunctuationMarks(List.of('。', '?', '!', ';')) // 中文标点
.build();
return splitter.apply(documents);
}
public List<Document> splitWithCustomMarks(List<Document> documents) {
// 中英文标点混合
TokenTextSplitter splitter = TokenTextSplitter.builder()
.withChunkSize(800)
.withPunctuationMarks(List.of('.', '?', '!', '\n', ';', ':', '。'))
.build();
return splitter.apply(documents);
}
}构造方法选项
令牌文本分割器提供三种构造方法:
TokenTextSplitter():使用默认配置创建分割器
TokenTextSplitter(boolean keepSeparator):自定义分隔符行为创建分割器
TokenTextSplitter(int chunkSize, int minChunkSizeChars, int minChunkLengthToEmbed, int maxNumChunks, boolean keepSeparator, List<Character> punctuationMarks):全参数自定义构造方法
推荐使用建造者模式创建自定义配置的实例。
参数
chunkSize:每个文本片段的目标令牌大小,默认 800
minChunkSizeChars:每个文本片段的最小字符数,默认 350
minChunkLengthToEmbed:需纳入的片段最小长度,默认 5
maxNumChunks:单段文本生成的最大片段数,默认 10000
keepSeparator:是否在片段中保留分隔符(如换行符),默认 true
punctuationMarks:用于句子边界分割的字符列表,默认 . ? ! 换行符
行为
令牌文本分割器处理文本内容的规则如下:
通过 CL100K_BASE 编码将输入文本转为令牌
根据 chunkSize 将编码后的文本分割为片段
对每个片段:
将片段解码为文本
仅当总令牌数超过 chunkSize 时,在 minChunkSizeChars 后通过配置的标点符号寻找合适分割点
找到分割点则在该位置截断片段
修剪片段,并根据 keepSeparator 设置可选移除换行符
若结果片段长度大于 minChunkLengthToEmbed,加入输出列表
重复流程直至所有令牌处理完成或达到 maxNumChunks
剩余文本长度大于 minChunkLengthToEmbed 时,作为最终片段加入
仅当令牌数超过片段大小时,才基于标点分割。大小等于或小于片段大小的文本直接作为单个片段返回,避免小文本无意义分割。
示例
Document doc1 = new Document("This is a long piece of text that needs to be split into smaller chunks for processing.",
Map.of("source", "example.txt"));
Document doc2 = new Document("Another document with content that will be split based on token count.",
Map.of("source", "example2.txt"));
TokenTextSplitter splitter = new TokenTextSplitter();
List<Document> splitDocuments = this.splitter.apply(List.of(this.doc1, this.doc2));
for (Document doc : splitDocuments) {
System.out.println("Chunk: " + doc.getContent());
System.out.println("Metadata: " + doc.getMetadata());
}注意事项
令牌文本分割器使用 jtokkit 库的 CL100K_BASE 编码,兼容新版 OpenAI 模型
分割器尽可能在句子边界分割,创建语义完整的片段
原文档的元数据会保留并复制到所有派生片段
若 copyContentFormatter 设为 true(默认行为),原文档的内容格式化器会复制到派生片段
该分割器适合为有令牌限制的大语言模型准备文本,确保片段在模型处理能力范围内
自定义标点符号:默认标点适配英文文本,其他语言或专业内容可通过建造者的 withPunctuationMarks 方法自定义
性能考量:分割器可处理任意数量标点,但为优化性能,建议列表长度控制在 20 个字符以内
可扩展性:getLastPunctuationIndex 方法为保护类型,子类可重写标点检测逻辑适配特殊场景
小文本处理:2.0 版本起,令牌数小于等于片段大小的小文本不再按标点分割,避免符合大小限制的内容无意义碎片化
内容格式转换器
确保所有文档的内容格式统一。
关键词元数据增强器
关键词元数据增强器是一种文档转换器,使用生成式 AI 模型从文档内容提取关键词并作为元数据添加。
用法
@Component
class MyKeywordEnricher {
private final ChatModel chatModel;
MyKeywordEnricher(ChatModel chatModel) {
this.chatModel = chatModel;
}
List<Document> enrichDocuments(List<Document> documents) {
KeywordMetadataEnricher enricher = KeywordMetadataEnricher.builder(chatModel)
.keywordCount(5)
.build();
// 或使用自定义模板
KeywordMetadataEnricher enricher = KeywordMetadataEnricher.builder(chatModel)
.keywordsTemplate(YOUR_CUSTOM_TEMPLATE)
.build();
return enricher.apply(documents);
}
}构造方法选项
关键词元数据增强器提供两种构造方法:
KeywordMetadataEnricher(ChatModel chatModel, int keywordCount):使用默认模板提取指定数量关键词
KeywordMetadataEnricher(ChatModel chatModel, PromptTemplate keywordsTemplate):使用自定义模板提取关键词
行为
关键词元数据增强器处理文档的规则如下:
为每个输入文档基于内容创建提示词
将提示词发送给指定的对话模型生成关键词
生成的关键词以 "excerpt_keywords" 为键加入文档元数据
返回增强后的文档
自定义
可使用默认模板或通过 keywordsTemplate 参数自定义模板。默认模板:
{context_str}. Give %s unique keywords for this document. Format as comma separated. Keywords:其中 {context_str} 替换为文档内容,%s 替换为指定的关键词数量。
示例
ChatModel chatModel = // 初始化对话模型
KeywordMetadataEnricher enricher = KeywordMetadataEnricher.builder(chatModel)
.keywordCount(5)
.build();
// 或使用自定义模板
KeywordMetadataEnricher enricher = KeywordMetadataEnricher.builder(chatModel)
.keywordsTemplate(new PromptTemplate("Extract 5 important keywords from the following text and separate them with commas:\n{context_str}"))
.build();
Document doc = new Document("This is a document about artificial intelligence and its applications in modern technology.");
List<Document> enrichedDocs = enricher.apply(List.of(this.doc));
Document enrichedDoc = this.enrichedDocs.get(0);
String keywords = (String) this.enrichedDoc.getMetadata().get("excerpt_keywords");
System.out.println("Extracted keywords: " + keywords);注意事项
关键词元数据增强器需要可用的对话模型生成关键词
关键词数量必须大于等于 1
增强器为每个处理后的文档添加 "excerpt_keywords" 元数据字段
生成的关键词以逗号分隔字符串返回
该增强器可提升文档检索性,用于生成文档标签或分类
建造者模式中,若设置 keywordsTemplate 参数,keywordCount 参数会被忽略
摘要元数据增强器
摘要元数据增强器是一种文档转换器,使用生成式 AI 模型为文档生成摘要并作为元数据添加。可生成当前文档及相邻文档(上一个、下一个)的摘要。
用法
@Configuration
class EnricherConfig {
@Bean
public SummaryMetadataEnricher summaryMetadata(OpenAiChatModel aiClient) {
return new SummaryMetadataEnricher(aiClient,
List.of(SummaryType.PREVIOUS, SummaryType.CURRENT, SummaryType.NEXT));
}
}
@Component
class MySummaryEnricher {
private final SummaryMetadataEnricher enricher;
MySummaryEnricher(SummaryMetadataEnricher enricher) {
this.enricher = enricher;
}
List<Document> enrichDocuments(List<Document> documents) {
return this.enricher.apply(documents);
}
}构造方法
摘要元数据增强器提供两种构造方法:
SummaryMetadataEnricher(ChatModel chatModel, List<SummaryType> summaryTypes)
SummaryMetadataEnricher(ChatModel chatModel, List<SummaryType> summaryTypes, String summaryTemplate, MetadataMode metadataMode)
参数
chatModel:用于生成摘要的 AI 模型
summaryTypes:摘要类型枚举列表,指定生成哪些摘要(上一个、当前、下一个)
summaryTemplate:摘要生成自定义模板(可选)
metadataMode:生成摘要时处理文档元数据的方式(可选)
行为
摘要元数据增强器处理文档的规则如下:
为每个输入文档基于内容和指定摘要模板创建提示词
将提示词发送给指定的对话模型生成摘要
根据指定的 summaryTypes,为每个文档添加以下元数据:
section_summary:当前文档摘要
prev_section_summary:上一个文档摘要(可用且请求时)
next_section_summary:下一个文档摘要(可用且请求时)
返回增强后的文档
自定义
可通过提供自定义 summaryTemplate 定制摘要生成提示词。默认模板:
"""
Here is the content of the section:
{context_str}
Summarize the key topics and entities of the section.
Summary:
"""示例
ChatModel chatModel = // 初始化对话模型
SummaryMetadataEnricher enricher = new SummaryMetadataEnricher(chatModel,
List.of(SummaryType.PREVIOUS, SummaryType.CURRENT, SummaryType.NEXT));
Document doc1 = new Document("Content of document 1");
Document doc2 = new Document("Content of document 2");
List<Document> enrichedDocs = enricher.apply(List.of(this.doc1, this.doc2));
// 检查增强后文档的元数据
for (Document doc : enrichedDocs) {
System.out.println("Current summary: " + doc.getMetadata().get("section_summary"));
System.out.println("Previous summary: " + doc.getMetadata().get("prev_section_summary"));
System.out.println("Next summary: " + doc.getMetadata().get("next_section_summary"));
}示例展示预期行为:
两个文档的列表中,两个文档均获得 section_summary
第一个文档获得 next_section_summary,无 prev_section_summary
第二个文档获得 prev_section_summary,无 next_section_summary
第一个文档的 section_summary 与第二个文档的 prev_section_summary 一致
第一个文档的 next_section_summary 与第二个文档的 section_summary 一致
注意事项
摘要元数据增强器需要可用的对话模型生成摘要
增强器可处理任意长度的文档列表,正确处理首尾文档的边界情况
该增强器适合创建上下文感知摘要,更好理解序列中文档的关联关系
MetadataMode 参数可控制现有元数据如何纳入摘要生成流程
写入器
文件写入
文件文档写入器是文档写入器的实现类,将文档列表内容写入文件。
用法
@Component
class MyDocumentWriter {
public void writeDocuments(List<Document> documents) {
FileDocumentWriter writer = new FileDocumentWriter("output.txt", true, MetadataMode.ALL, false);
writer.accept(documents);
}
}构造方法
文件文档写入器提供三种构造方法:
FileDocumentWriter(String fileName)
FileDocumentWriter(String fileName, boolean withDocumentMarkers)
FileDocumentWriter(String fileName, boolean withDocumentMarkers, MetadataMode metadataMode, boolean append)
参数
fileName:写入文档的目标文件名
withDocumentMarkers:是否在输出中包含文档标记,默认 false
metadataMode:指定写入文件的文档内容,默认 MetadataMode.NONE
append:为 true 时数据追加到文件末尾,否则覆盖开头,默认 false
行为
文件文档写入器处理文档的规则如下:
为指定文件名打开文件写入器
对输入列表中的每个文档:
若 withDocumentMarkers 为 true,写入包含文档索引和页码的文档标记
根据指定的 metadataMode 写入格式化后的文档内容
所有文档写入完成后关闭文件
文档标记
withDocumentMarkers 设为 true 时,写入器为每个文档添加以下格式标记:
### Doc: [index], pages:[start_page_number,end_page_number]
元数据处理
写入器使用两个特定元数据键:
page_number:文档的起始页码
end_page_number:文档的结束页码
写入文档标记时使用这两个键。
示例
List<Document> documents = // 初始化文档
FileDocumentWriter writer = new FileDocumentWriter("output.txt", true, MetadataMode.ALL, true);
writer.accept(documents);该代码将所有文档写入 output.txt,包含文档标记、所有元数据,文件已存在时追加内容。
注意事项
写入器使用文件写入器,以操作系统默认字符编码写入文本文件
写入过程出错时,抛出运行时异常并封装原始异常
metadataMode 参数可控制现有元数据如何纳入写入内容
该写入器适合调试或创建文档集合的人类可读输出
向量库
提供与多种向量库的集成。完整列表参考向量数据库文档。