ETL 管線

萃取、轉換和載入 (ETL) 框架是檢索增強生成 (RAG) 用例中資料處理的骨幹。

ETL 管道協調從原始資料來源到結構化向量儲存庫的流程,確保資料處於 AI 模型檢索的最佳格式。

RAG 用例是透過從資料體中檢索相關資訊來增強生成模型的能力,從而提高生成輸出的品質和相關性。

API 總覽

ETL 管道建立、轉換和儲存 Document 實例。

Spring AI Message API

Document 類別包含文字、中繼資料以及可選的其他媒體類型,如圖像、音訊和影片。

ETL 管道有三個主要組件:

  • DocumentReader 實作 Supplier<List<Document>>

  • DocumentTransformer 實作 Function<List<Document>, List<Document>>

  • DocumentWriter 實作 Consumer<List<Document>>

Document 類別的內容是透過 DocumentReader 從 PDF、文字檔案和其他文件類型建立的。

要建構一個簡單的 ETL 管道,您可以將每種類型的實例串聯在一起。

etl pipeline

假設我們有以下三種 ETL 類型的實例

  • PagePdfDocumentReaderDocumentReader 的實作

  • TokenTextSplitterDocumentTransformer 的實作

  • VectorStoreDocumentWriter 的實作

若要執行將資料載入向量資料庫以用於檢索增強生成模式的基本操作,請使用以下 Java 函數樣式語法程式碼。

vectorStore.accept(tokenTextSplitter.apply(pdfReader.get()));

或者,您可以使用更自然地表達領域的方法名稱

vectorStore.write(tokenTextSplitter.split(pdfReader.read()));

ETL 介面

ETL 管道由以下介面和實作組成。詳細的 ETL 類別圖顯示在 ETL 類別圖 章節中。

DocumentReader

提供來自不同來源的文件來源。

public interface DocumentReader extends Supplier<List<Document>> {

    default List<Document> read() {
		return get();
	}
}

DocumentTransformer

在處理工作流程中轉換一批文件。

public interface DocumentTransformer extends Function<List<Document>, List<Document>> {

    default List<Document> transform(List<Document> transform) {
		return apply(transform);
	}
}

DocumentWriter

管理 ETL 流程的最後階段,準備文件以進行儲存。

public interface DocumentWriter extends Consumer<List<Document>> {

    default void write(List<Document> documents) {
		accept(documents);
	}
}

ETL 類別圖

以下類別圖說明了 ETL 介面和實作。

etl class diagram

DocumentReaders

JSON

JsonReader 處理 JSON 文件,將其轉換為 Document 物件的列表。

範例

@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();
	}
}

建構子選項

JsonReader 提供多個建構子選項

  1. JsonReader(Resource resource)

  2. JsonReader(Resource resource, String…​ jsonKeysToUse)

  3. JsonReader(Resource resource, JsonMetadataGenerator jsonMetadataGenerator, String…​ jsonKeysToUse)

參數

  • resource:指向 JSON 檔案的 Spring Resource 物件。

  • jsonKeysToUse:JSON 中的鍵陣列,應用作結果 Document 物件中的文字內容。

  • jsonMetadataGenerator:一個可選的 JsonMetadataGenerator,用於為每個 Document 建立中繼資料。

行為

JsonReader 處理 JSON 內容的方式如下

  • 它可以處理 JSON 陣列和單個 JSON 物件。

  • 對於每個 JSON 物件(無論是在陣列中還是單個物件中)

    • 它根據指定的 jsonKeysToUse 提取內容。

    • 如果未指定任何鍵,它將使用整個 JSON 物件作為內容。

    • 它使用提供的 JsonMetadataGenerator(如果未提供,則使用空的)產生中繼資料。

    • 它使用提取的內容和中繼資料建立 Document 物件。

使用 JSON 指標

JsonReader 現在支援使用 JSON 指標檢索 JSON 文件的特定部分。此功能可讓您輕鬆地從複雜的 JSON 結構中提取巢狀資料。

get(String pointer) 方法
public List<Document> get(String pointer)

此方法可讓您使用 JSON 指標檢索 JSON 文件的特定部分。

參數
  • pointer:JSON 指標字串(如 RFC 6901 中定義),用於在 JSON 結構中定位所需的元素。

傳回值
  • 傳回一個 List<Document>,其中包含從指標定位的 JSON 元素解析的文件。

行為
  • 該方法使用提供的 JSON 指標導航到 JSON 結構中的特定位置。

  • 如果指標有效且指向現有元素

    • 對於 JSON 物件:它傳回包含單個 Document 的列表。

    • 對於 JSON 陣列:它傳回 Document 的列表,陣列中的每個元素對應一個 Document。

  • 如果指標無效或指向不存在的元素,它將拋出 IllegalArgumentException

範例
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."
  }
]

在此範例中,如果 JsonReader 配置為使用 "description" 作為 jsonKeysToUse,它將建立 Document 物件,其中內容是陣列中每輛自行車的 "description" 欄位的值。

注意事項

  • JsonReader 使用 Jackson 進行 JSON 解析。

  • 它可以透過使用串流處理陣列來有效地處理大型 JSON 檔案。

  • 如果在 jsonKeysToUse 中指定了多個鍵,則內容將是這些鍵值的串聯。

  • 透過自訂 jsonKeysToUseJsonMetadataGenerator,讀取器具有彈性,可以適應各種 JSON 結構。

文字

TextReader 處理純文字文件,將其轉換為 Document 物件的列表。

範例

@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 提供兩個建構子選項

  1. TextReader(String resourceUrl)

  2. TextReader(Resource resource)

參數

  • resourceUrl:表示要讀取的資源 URL 的字串。

  • resource:指向文字檔案的 Spring Resource 物件。

配置

  • setCharset(Charset charset):設定用於讀取文字檔案的字元集。預設為 UTF-8。

  • getCustomMetadata():傳回可變地圖,您可以在其中為文件新增自訂中繼資料。

行為

TextReader 處理文字內容的方式如下

  • 它將文字檔案的整個內容讀取到單個 Document 物件中。

  • 檔案的內容成為 Document 的內容。

  • 中繼資料會自動新增到 Document

    • charset:用於讀取檔案的字元集(預設值:"UTF-8")。

    • source:來源文字檔案的檔案名稱。

  • 透過 getCustomMetadata() 新增的任何自訂中繼資料都包含在 Document 中。

注意事項

  • TextReader 將整個檔案內容讀取到記憶體中,因此可能不適合非常大的檔案。

  • 如果您需要將文字分割成較小的區塊,您可以在讀取文件後使用文字分割器,例如 TokenTextSplitter

List<Document> documents = textReader.get();
List<Document> splitDocuments = new TokenTextSplitter().apply(this.documents);
  • 讀取器使用 Spring 的 Resource 抽象,允許它從各種來源(類別路徑、檔案系統、URL 等)讀取。

  • 可以使用 getCustomMetadata() 方法將自訂中繼資料新增到讀取器建立的所有文件中。

Markdown

MarkdownDocumentReader 處理 Markdown 文件,將其轉換為 Document 物件的列表。

範例

@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();
    }
}

MarkdownDocumentReaderConfig 可讓您自訂 MarkdownDocumentReader 的行為

  • horizontalRuleCreateDocument:設定為 true 時,Markdown 中的水平線將建立新的 Document 物件。

  • includeCodeBlock:設定為 true 時,程式碼區塊將包含在與周圍文字相同的 Document 中。設定為 false 時,程式碼區塊會建立單獨的 Document 物件。

  • includeBlockquote:設定為 true 時,引文區塊將包含在與周圍文字相同的 Document 中。設定為 false 時,引文區塊會建立單獨的 Document 物件。

  • additionalMetadata:可讓您將自訂中繼資料新增到所有建立的 Document 物件。

範例文件: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
```

行為:MarkdownDocumentReader 處理 Markdown 內容並根據配置建立 Document 物件

  • 標題成為 Document 物件中的中繼資料。

  • 段落成為 Document 物件的內容。

  • 程式碼區塊可以分隔到它們自己的 Document 物件中,或與周圍文字一起包含。

  • 引文區塊可以分隔到它們自己的 Document 物件中,或與周圍文字一起包含。

  • 水平線可用於將內容分割成單獨的 Document 物件。

讀取器保留 Document 物件內容中的格式,例如行內程式碼、列表和文字樣式。

PDF 頁面

PagePdfDocumentReader 使用 Apache PdfBox 庫解析 PDF 文件

使用 Maven 或 Gradle 將依賴項新增到您的專案。

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-pdf-document-reader</artifactId>
</dependency>

或新增到您的 Gradle build.gradle 建置檔案。

dependencies {
    implementation 'org.springframework.ai:spring-ai-pdf-document-reader'
}

範例

@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 段落

ParagraphPdfDocumentReader 使用 PDF 目錄(例如 TOC)資訊將輸入 PDF 分割成文字段落,並為每個段落輸出一個 Document。注意:並非所有 PDF 文件都包含 PDF 目錄。

依賴項

使用 Maven 或 Gradle 將依賴項新增到您的專案。

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-pdf-document-reader</artifactId>
</dependency>

或新增到您的 Gradle build.gradle 建置檔案。

dependencies {
    implementation 'org.springframework.ai:spring-ai-pdf-document-reader'
}

範例

@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…​)

TikaDocumentReader 使用 Apache Tika 從各種文件格式(例如 PDF、DOC/DOCX、PPT/PPTX 和 HTML)中提取文字。如需支援格式的完整列表,請參閱 Tika 文件

依賴項

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-tika-document-reader</artifactId>
</dependency>

或新增到您的 Gradle build.gradle 建置檔案。

dependencies {
    implementation 'org.springframework.ai:spring-ai-tika-document-reader'
}

範例

@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();
    }
}

轉換器

TextSplitter

TextSplitter 是一個抽象基底類別,有助於分割文件以適應 AI 模型的上下文視窗。

TokenTextSplitter

TokenTextSplitterTextSplitter 的實作,它使用 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);
        return splitter.apply(documents);
    }
}

建構子選項

TokenTextSplitter 提供兩個建構子選項

  1. TokenTextSplitter():使用預設設定建立分割器。

  2. TokenTextSplitter(int defaultChunkSize, int minChunkSizeChars, int minChunkLengthToEmbed, int maxNumChunks, boolean keepSeparator)

參數

  • defaultChunkSize:每個文字區塊的目標大小(以權杖為單位)(預設值:800)。

  • minChunkSizeChars:每個文字區塊的最小大小(以字元為單位)(預設值:350)。

  • minChunkLengthToEmbed:要包含的區塊的最小長度(預設值:5)。

  • maxNumChunks:從文字產生的最大區塊數(預設值:10000)。

  • keepSeparator:是否在區塊中保留分隔符(例如換行符)(預設值:true)。

行為

TokenTextSplitter 處理文字內容的方式如下

  1. 它使用 CL100K_BASE 編碼將輸入文字編碼為權杖。

  2. 它根據 defaultChunkSize 將編碼的文字分割成區塊。

  3. 對於每個區塊

    1. 它將區塊解碼回文字。

    2. 它嘗試在 minChunkSizeChars 之後找到合適的斷點(句號、問號、驚嘆號或換行符)。

    3. 如果找到斷點,它會在該點截斷區塊。

    4. 它會修剪區塊,並根據 keepSeparator 設定選擇性地移除換行符。

    5. 如果結果區塊長度超過 minChunkLengthToEmbed,則會將其新增到輸出。

  4. 此過程會持續到處理完所有權杖或達到 maxNumChunks 為止。

  5. 如果任何剩餘文字長度超過 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());
}

注意事項

  • TokenTextSplitter 使用來自 jtokkit 庫的 CL100K_BASE 編碼,該編碼與較新的 OpenAI 模型相容。

  • 分割器嘗試透過在句子邊界處斷開(如果可能)來建立語義上有意義的區塊。

  • 原始文件中的中繼資料會被保留並複製到從該文件衍生的所有區塊。

  • 如果 `copyContentFormatter` 設定為 `true`(預設行為),則原始文件中的內容格式器(如果已設定)也會複製到衍生的區塊。

  • 此分割器特別適用於為具有權杖限制的大型語言模型準備文字,確保每個區塊都在模型的處理能力範圍內。

ContentFormatTransformer

確保所有文件的內容格式一致。

KeywordMetadataEnricher

KeywordMetadataEnricher 是一個 DocumentTransformer,它使用生成式 AI 模型從文件內容中提取關鍵字並將其新增為中繼資料。

用法

@Component
class MyKeywordEnricher {

    private final ChatModel chatModel;

    MyKeywordEnricher(ChatModel chatModel) {
        this.chatModel = chatModel;
    }

    List<Document> enrichDocuments(List<Document> documents) {
        KeywordMetadataEnricher enricher = new KeywordMetadataEnricher(this.chatModel, 5);
        return enricher.apply(documents);
    }
}

建構子

KeywordMetadataEnricher 建構子接受兩個參數

  1. ChatModel chatModel:用於產生關鍵字的 AI 模型。

  2. int keywordCount:每個文件要提取的關鍵字數量。

行為

KeywordMetadataEnricher 處理文件的方式如下

  1. 對於每個輸入文件,它都會使用文件的內容建立提示。

  2. 它將此提示傳送給提供的 ChatModel 以產生關鍵字。

  3. 產生的關鍵字會新增到文件的中繼資料中,鍵為 "excerpt_keywords"。

  4. 傳回豐富的文件。

自訂

可以透過修改類別中的 KEYWORDS_TEMPLATE 常數來自訂關鍵字提取提示。預設範本為

\{context_str}. Give %s unique keywords for this document. Format as comma separated. Keywords:

其中 {context_str} 會被文件內容取代,而 %s 會被指定的關鍵字計數取代。

範例

ChatModel chatModel = // initialize your chat model
KeywordMetadataEnricher enricher = new KeywordMetadataEnricher(chatModel, 5);

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);

注意事項

  • KeywordMetadataEnricher 需要一個運作正常的 ChatModel 才能產生關鍵字。

  • 關鍵字計數必須為 1 或更大。

  • 豐富器會將 "excerpt_keywords" 中繼資料欄位新增到每個處理的文件。

  • 產生的關鍵字以逗號分隔字串的形式傳回。

  • 此豐富器特別適用於提高文件可搜尋性以及為文件產生標籤或類別。

SummaryMetadataEnricher

SummaryMetadataEnricher 是一個 DocumentTransformer,它使用生成式 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 提供兩個建構子

  1. SummaryMetadataEnricher(ChatModel chatModel, List<SummaryType> summaryTypes)

  2. SummaryMetadataEnricher(ChatModel chatModel, List<SummaryType> summaryTypes, String summaryTemplate, MetadataMode metadataMode)

參數

  • chatModel:用於產生摘要的 AI 模型。

  • summaryTypesSummaryType 列舉值的列表,指示要產生哪些摘要(PREVIOUS、CURRENT、NEXT)。

  • summaryTemplate:用於摘要產生的自訂範本(可選)。

  • metadataMode:指定在產生摘要時如何處理文件元資料(可選)。

行為

SummaryMetadataEnricher 處理文件的方式如下

  1. 對於每個輸入文件,它都會使用文件的內容和指定的摘要範本建立提示。

  2. 它將此提示傳送給提供的 ChatModel 以產生摘要。

  3. 根據指定的 summaryTypes,它會將以下中繼資料新增到每個文件

    • section_summary:目前文件的摘要。

    • prev_section_summary:上一個文件的摘要(如果可用且已請求)。

    • next_section_summary:下一個文件的摘要(如果可用且已請求)。

  4. 傳回豐富的文件。

自訂

可以透過提供自訂 summaryTemplate 來自訂摘要產生提示。預設範本為

"""
Here is the content of the section:
{context_str}

Summarize the key topics and entities of the section.

Summary:
"""

範例

ChatModel chatModel = // initialize your chat model
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));

// Check the metadata of the enriched documents
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 相符。

注意事項

  • SummaryMetadataEnricher 需要一個運作正常的 ChatModel 才能產生摘要。

  • 豐富器可以處理任何大小的文件列表,並正確處理第一個和最後一個文件的邊緣情況。

  • 此豐富器特別適用於建立上下文感知的摘要,從而更好地理解序列中文件之間的關係。

  • MetadataMode 參數允許控制如何將現有中繼資料併入摘要產生過程中。

寫入器

檔案

FileDocumentWriter 是一個 DocumentWriter 實作,它將 Document 物件列表的內容寫入到檔案中。

用法

@Component
class MyDocumentWriter {

    public void writeDocuments(List<Document> documents) {
        FileDocumentWriter writer = new FileDocumentWriter("output.txt", true, MetadataMode.ALL, false);
        writer.accept(documents);
    }
}

建構子

FileDocumentWriter 提供三個建構子

  1. FileDocumentWriter(String fileName)

  2. FileDocumentWriter(String fileName, boolean withDocumentMarkers)

  3. FileDocumentWriter(String fileName, boolean withDocumentMarkers, MetadataMode metadataMode, boolean append)

參數

  • fileName:要將文件寫入的檔案名稱。

  • withDocumentMarkers:是否在輸出中包含文件標記(預設值:false)。

  • metadataMode:指定要寫入檔案的文件內容(預設值:MetadataMode.NONE)。

  • append:如果為 true,資料將寫入檔案的末尾而不是開頭(預設值:false)。

行為

FileDocumentWriter 處理文件的方式如下

  1. 它為指定的檔案名稱開啟一個 FileWriter。

  2. 對於輸入列表中的每個文件

    1. 如果 withDocumentMarkers 為 true,它會寫入文件標記,包括文件索引和頁碼。

    2. 它根據指定的 metadataMode 寫入文件的格式化內容。

  3. 在寫入所有文件後,檔案會關閉。

文件標記

withDocumentMarkers 設定為 true 時,寫入器會在每個文件中包含以下格式的標記

### Doc: [index], pages:[start_page_number,end_page_number]

中繼資料處理

寫入器使用兩個特定的中繼資料鍵

  • page_number:表示文件的起始頁碼。

  • end_page_number:表示文件的結束頁碼。

這些用於寫入文件標記時。

範例

List<Document> documents = // initialize your documents
FileDocumentWriter writer = new FileDocumentWriter("output.txt", true, MetadataMode.ALL, true);
writer.accept(documents);

這會將所有文件寫入 "output.txt",包括文件標記,使用所有可用的中繼資料,並在檔案已存在時附加到檔案。

注意事項

  • 寫入器使用 FileWriter,因此它使用作業系統的預設字元編碼寫入文字檔案。

  • 如果在寫入期間發生錯誤,則會拋出 RuntimeException,並將原始例外作為其原因。

  • metadataMode 參數允許控制如何將現有中繼資料併入寫入的內容中。

  • 此寫入器特別適用於偵錯或建立文件集合的人工可讀輸出。

VectorStore

提供與各種向量儲存庫的整合。如需完整列表,請參閱 向量資料庫文件