SpringAI-ETL-DocumentTransformer

接上文:SpringAI-ETL-DocumentReader

1、TextSplitter

TextSplitter 是一个抽象基类,用于帮助分割文档以适应 AI 模型的上下文窗口。
TokenTextSplitter 是 TextSplitter 的一个实现,它使用 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 提供两个构造函数选项

  • TokenTextSplitter():使用默认设置创建拆分器。
  • 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、对于每个块
    • a、它将块解码回文本。
    • b、它尝试在 minChunkSizeChars 之后找到合适的断点(句号、问号、感叹号或换行符)。
    • c、如果找到断点,它会在该点截断块。
    • d、它根据 keepSeparator 设置修剪块并可选地删除换行符。
    • e、如果生成的块长于 minChunkLengthToEmbed,则将其添加到输出中。
  • 4、此过程一直持续到所有令牌都处理完毕或达到 maxNumChunks。
  • 5、任何剩余文本如果长于 minChunkLengthToEmbed,则作为最后一个块添加。

2、KeywordMetadataEnricher

KeywordMetadataEnricher 是一个 DocumentTransformer,它使用生成式 AI 模型从文档内容中提取关键字并将其添加为元数据。

a、构造函数

  • KeywordMetadataEnricher(ChatModel chatModel, int keywordCount):使用默认模板并提取指定数量的关键字。
  • KeywordMetadataEnricher(ChatModel chatModel, PromptTemplate keywordsTemplate):使用自定义模板进行关键字提取。

b、处理过程

  • 对于每个输入文档,它使用文档内容创建一个提示。
  • 它将此提示发送到提供的 ChatModel 以生成关键字。
  • 生成的关键字将以 "excerpt_keywords" 键添加到文档的元数据中。

c、自定义模板

可以通过keywordsTemplate参数自定义模板。默认模板是:

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

其中{context_str}被文档内容替换,%s 被指定的关键字计数替换。

d、代码示例

配置Bean

@Configuration
public class DocumentConfig {

    @Bean
    public KeywordMetadataEnricher keywordMetadataEnricher(OpenAiChatModel chatModel) {
        return new KeywordMetadataEnricher(chatModel, 2);
    }
}

单元测试:

    @Test
    public void testKeyword() {
        FileSystemResource fileSystemResource = new FileSystemResource("/Users/cmc/Desktop/ai-file/小明个人信息.txt");
        TikaDocumentReader tikaDocumentReader = new TikaDocumentReader(fileSystemResource);
        List<Document> documents = tikaDocumentReader.get();

        List<Document> enrichedDocs = keywordMetadataEnricher.apply(documents);
        for (Document document : enrichedDocs) {
            String keywords = (String) document.getMetadata().get("excerpt_keywords");
            System.out.println("Extracted keywords: " + keywords);
        }
      // Extracted keywords: Java开发, 户外运动
    }

3、SummaryMetadataEnricher

SummaryMetadataEnricher 是一个 DocumentTransformer,它使用生成式 AI 模型为文档创建摘要并将其添加为元数据。它可以为当前文档以及相邻文档(上一文档和下一文档)生成摘要。

a、构造函数

  • SummaryMetadataEnricher(ChatModel chatModel, List summaryTypes)
  • SummaryMetadataEnricher(ChatModel chatModel, List summaryTypes, String summaryTemplate, MetadataMode metadataMode)
    参数解释:
  • chatModel:用于生成摘要的 AI 模型。
  • summaryTypes:一个 SummaryType 枚举值列表,指示要生成哪些摘要(PREVIOUS、CURRENT、NEXT)。
  • summaryTemplate:用于摘要生成的自定义模板(可选)。
  • metadataMode:指定在生成摘要时如何处理文档元数据(可选)。

b、处理过程

  • 对于每个输入文档,它使用文档内容和指定的摘要模板创建一个提示。
  • 它将此提示发送到提供的 ChatModel 以生成摘要。
  • 根据指定的 summaryTypes,它会向每个文档添加以下元数据
    • section_summary:当前文档的摘要。
    • prev_section_summary:上一文档的摘要(如果可用且已请求)。
    • next_section_summary:下一文档的摘要(如果可用且已请求)。

c、自定义模板

摘要生成提示可以通过提供自定义 summaryTemplate 来定制。默认模板是

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

Summarize the key topics and entities of the section.

Summary:
"""

其中{context_str}被文档内容替换。

d、代码示例

配置 Bean

@Configuration
public class DocumentConfig {

    @Bean
    public SummaryMetadataEnricher summaryMetadataEnricher(OpenAiChatModel chatModel) {
        return new SummaryMetadataEnricher(chatModel, List.of(), SystemPromptTemplateConstant.SUMMARY_TEMPLATE, MetadataMode.ALL);
    }
}

单元测试:

    @Autowired
    private SummaryMetadataEnricher summaryMetadataEnricher;
    @Test
    public void testSummary() {
        FileSystemResource fileSystemResource = new FileSystemResource("/Users/cmc/Desktop/ai-file/小明个人信息.txt");
        TikaDocumentReader tikaDocumentReader = new TikaDocumentReader(fileSystemResource);
        List<Document> documents = tikaDocumentReader.get();

        List<Document> documentList = summaryMetadataEnricher.apply(documents);
        for (Document document : documentList) {
            String keywords = (String) document.getMetadata().get("section_summary");
            System.out.println("section_summary: " + keywords);
        }
    }
    // 输出结果:
    //section_summary: 根据您提供的文本内容,主题和关键内容总结如下:
    //
    //**主题:**
    //个人简介
    //
    //**关键内容:**
    //1.  **姓名:** 小明
    //2.  **年龄:** 20岁
    //3.  **职业:** Java 开发工程师
    //4.  **爱好:** 户外活动、游戏、美食

posted @ 2026-01-15 11:31  0xCAFEBABE_001  阅读(5)  评论(0)    收藏  举报