Spring-AI 利用KeywordMetadataEnricher & SummaryMetadataEnricher 构建文本智能元数据

在构建基于Spring AI的RAG(检索增强生成)应用时,数据的质量 直接决定了回答的智商

RAG时,不仅需要原始文本,还需要文本的上下文摘要或核心关键词来辅助检索和生成。

Spring AI提供的ETL Pipeline模块中,KeywordMetadataEnricher和SummaryMetadataEnricher正是为此而生。它们利用大模型的能力,生成文件的核心关键词及摘要信息。

Enricher

KeywordMetadataEnricher:关键词提取专家

它的核心任务是从文档内容中提取出最具代表性的关键词,并将这些关键词存入文档的元数据中。

● 作用:提升检索的召回率。当用户查询使用了同义词或相关术语时,关键词元数据可以帮助匹配到原文未直接出现但语义相关的文档。

● 机制:它调用配置好的ChatModel,通过特定的Prompt模板(默认是{context_str}. Give %s unique keywords for this document. Format as comma separated. Keywords:)让模型提取关键词。

● 输出:生成的关键词会以逗号分隔的字符串形式,存入元数据的excerpt_keywords字段中。

java 复制代码
    public KeywordMetadataEnricher(ChatModel chatModel, int keywordCount) {
        Assert.notNull(chatModel, "chatModel must not be null");
        Assert.isTrue(keywordCount >= 1, "keywordCount must be >= 1");
        this.chatModel = chatModel;
        this.keywordsTemplate = new PromptTemplate(String.format("{context_str}. Give %s unique keywords for this\ndocument. Format as comma separated. Keywords:", keywordCount));
    }

	public List<Document> apply(List<Document> documents) {
        for(Document document : documents) {
            Prompt prompt = this.keywordsTemplate.create(Map.of("context_str", document.getText()));
            String keywords = this.chatModel.call(prompt).getResult().getOutput().getText();
            document.getMetadata().put("excerpt_keywords", keywords);
        }

        return documents;
    }

SummaryMetadataEnricher:摘要生成引擎

它的核心任务是为文档生成摘要,并且不仅能生成当前文档的摘要,还能结合上下文生成"上一段"和"下一段"的摘要。

● 作用:解决文档片段(Chunk)上下文丢失的问题。由于文本分割(Splitting)会导致段落被切断,单独的片段可能语义不明。通过注入摘要元数据,可以让模型在检索时快速理解该片段的核心内容及周边上下文。

● 机制:它同样依赖ChatModel,使用默认或自定义的摘要模板(如"Here is the content of the section:\n{context_str}\n\nSummarize the key topics and entities of the section.\n\nSummary:)来生成文本。

● 输出:生成的摘要会存入元数据的section_summary字段。如果配置了PREVIOUS或NEXT,还会生成prev_section_summarynext_section_summary

java 复制代码
 public List<Document> apply(List<Document> documents) {
        List<String> documentSummaries = new ArrayList();

        for(Document document : documents) {
            String documentContext = document.getFormattedContent(this.metadataMode);
            Prompt prompt = (new PromptTemplate(this.summaryTemplate)).create(Map.of("context_str", documentContext));
            documentSummaries.add(this.chatModel.call(prompt).getResult().getOutput().getText());
        }

        for(int i = 0; i < documentSummaries.size(); ++i) {
            Map<String, Object> summaryMetadata = this.getSummaryMetadata(i, documentSummaries);
            ((Document)documents.get(i)).getMetadata().putAll(summaryMetadata);
        }

        return documents;
    }
    
private Map<String, Object> getSummaryMetadata(int i, List<String> documentSummaries) {
        Map<String, Object> summaryMetadata = new HashMap();
        if (i > 0 && this.summaryTypes.contains(SummaryMetadataEnricher.SummaryType.PREVIOUS)) {
            summaryMetadata.put("prev_section_summary", documentSummaries.get(i - 1));
        }

        if (i < documentSummaries.size() - 1 && this.summaryTypes.contains(SummaryMetadataEnricher.SummaryType.NEXT)) {
            summaryMetadata.put("next_section_summary", documentSummaries.get(i + 1));
        }

        if (this.summaryTypes.contains(SummaryMetadataEnricher.SummaryType.CURRENT)) {
            summaryMetadata.put("section_summary", documentSummaries.get(i));
        }

        return summaryMetadata;
    }

使用示例

KeywordMetadataEnricher

java 复制代码
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(doc));

        Document enrichedDoc = enrichedDocs.get(0);
        String keywords = (String) enrichedDoc.getMetadata().get("excerpt_keywords");
        System.out.println("Extracted keywords: " + keywords);

SummaryMetadataEnricher

java 复制代码
SummaryMetadataEnricher enricher = new SummaryMetadataEnricher(chatModel,
            List.of(SummaryType.PREVIOUS, SummaryType.CURRENT, SummaryType.NEXT),
            "以下是本节的内容:\n{context_str}\n\n总结本节的主要主题和实体。\n\n简介:",
            MetadataMode.ALL);

        Document doc1 = new Document("""
            自带光环的丑苹果
            越丑越甜,越丑越好吃
            丑苹果凭什么打败一众苹果,赢得大家的喜爱,高海拔是丑苹果美味的重要因素!
            四川盐源,依靠大凉山原始的生态环境,这里是世界公认的7项生态指标都符合苹果生长的优生区域,国家级优质苹果示范区
            """);
        Document doc2 = new Document("""
            这样的生态环境生长出来的苹果,简直自带光环,虽然其貌不扬,但一靠近,就能闻浓郁的到苹果味
            不套袋、不打蜡、不催熟,在枝头自由生长的彝家丑苹果,越丑越甜,越丑越好吃,丑苹果是浑然天成的实力派!
            """);

        List<Document> enrichedDocs = enricher.apply(List.of(doc1, 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"));
        }

程序输出结果

java 复制代码
Current summary: ### 总结:  
**主要主题**:介绍"丑苹果"因其独特的风味和高品质(越丑越甜)受到欢迎,并强调其产地的高海拔生态环境对品质的关键影响。  

**核心实体**:  
1. **丑苹果**:外形不美观但口感香甜的苹果品种。  
2. **四川盐源**:核心产地,位于大凉山地区,国家级优质苹果示范区。  
3. **高海拔/生态环境**:大凉山的高海拔和原始生态条件(符合7项世界公认指标)是苹果优质生长的关键因素。  

**亮点**:通过对比"丑"与"甜"的反差,突出自然生态对农产品品质的塑造,强化产地背书。
Previous summary: null
Next summary: ### 主要主题:
1. **自然生态种植**:强调苹果在自然生态环境中生长,不经过人工干预(不套袋、不打蜡、不催熟)。
2. **品质与外观的反差**:突出苹果虽然外观普通("其貌不扬""丑"),但内在品质优异("越丑越甜""实力派")。
3. **感官体验**:通过嗅觉("浓郁的苹果味")和味觉("越甜越好吃")描述苹果的天然魅力。

### 核心实体:
1. **彝家丑苹果**:产品名称,点明产地(彝家)和特点("丑"但好吃)。
2. **自然生长环境**:隐含的实体,指代苹果生长的原始生态环境。
3. **消费者感知**:通过"自带光环""实力派"等拟人化表达,体现产品的市场定位和口碑。  

### 总结:
本节通过对比外观与品质,突出彝家丑苹果"天然、健康、美味"的核心卖点,强调其自然种植方式和独特风味。
Current summary: ### 主要主题:
1. **自然生态种植**:强调苹果在自然生态环境中生长,不经过人工干预(不套袋、不打蜡、不催熟)。
2. **品质与外观的反差**:突出苹果虽然外观普通("其貌不扬""丑"),但内在品质优异("越丑越甜""实力派")。
3. **感官体验**:通过嗅觉("浓郁的苹果味")和味觉("越甜越好吃")描述苹果的天然魅力。

### 核心实体:
1. **彝家丑苹果**:产品名称,点明产地(彝家)和特点("丑"但好吃)。
2. **自然生长环境**:隐含的实体,指代苹果生长的原始生态环境。
3. **消费者感知**:通过"自带光环""实力派"等拟人化表达,体现产品的市场定位和口碑。  

### 总结:
本节通过对比外观与品质,突出彝家丑苹果"天然、健康、美味"的核心卖点,强调其自然种植方式和独特风味。
Previous summary: ### 总结:  
**主要主题**:介绍"丑苹果"因其独特的风味和高品质(越丑越甜)受到欢迎,并强调其产地的高海拔生态环境对品质的关键影响。  

**核心实体**:  
1. **丑苹果**:外形不美观但口感香甜的苹果品种。  
2. **四川盐源**:核心产地,位于大凉山地区,国家级优质苹果示范区。  
3. **高海拔/生态环境**:大凉山的高海拔和原始生态条件(符合7项世界公认指标)是苹果优质生长的关键因素。  

**亮点**:通过对比"丑"与"甜"的反差,突出自然生态对农产品品质的塑造,强化产地背书。
Next summary: null
相关推荐
talenteddriver1 小时前
java: 分页查询(自用笔记)
java·开发语言
边缘计算社区1 小时前
Nature 最新论文:边缘计算“任务卸载”新突破,时延降低 32.5% 的 MADRL 算法来了
人工智能·边缘计算
繁华似锦respect1 小时前
lambda表达式中的循环引用问题详解
java·开发语言·c++·单例模式·设计模式·哈希算法·散列表
AI虐我千百遍1 小时前
如何使用Kontext ComfyUI
人工智能
还是大剑师兰特1 小时前
利用AI辅助,快速生成gltf文件
人工智能
ModestCoder_1 小时前
强化学习 Policy 的 Tracking 能力全解析,以Legged_gym为例解说Policy的训练流程
人工智能·算法·自然语言处理·机器人·具身智能
hg01181 小时前
豫非搭建“黄金水道” 河南首个海外港口枢纽启动试运营
大数据·人工智能·物联网
heartbeat..1 小时前
介绍一下软件开发中常见的几种的架构模式
java·架构·开发