实现高级RAG(Advanced RAG)--RetrievalAugmentor--LangChain4j

高级RAG解决的痛点:

解决基础 RAG(Naive RAG)在面对复杂业务场景时暴露出的“找不到、找不准、用不好”等核心痛点,我们可以把基础 RAG 的痛点归纳为三个阶段:检索前(提问阶段)、检索中(寻找阶段)和检索后(生成阶段)。高级 RAG 正是通过引入更复杂的机制,精准干预了这三个阶段。

Advanced RAG流程(高级 RAG 流程):

RetrievalAugmentor  检索增强器

实现高级RAG的核心就是配置RetrievalAugmentor(检索增强器)

在配置AiServices的时候,官方包里有对应的获取retrievalAugmentor方法

package dev.langchain4j.service;


public abstract class AiServices<T> {

                                        ...
    
public AiServices<T> retrievalAugmentor(RetrievalAugmentor retrievalAugmentor) {
        if (this.contentRetrieverSet) {
            throw IllegalConfigurationException.illegalConfiguration("Only one out of [retriever, contentRetriever, retrievalAugmentor] can be set");
        } else {
            this.retrievalAugmentorSet = true;
            this.context.retrievalAugmentor = (RetrievalAugmentor)ValidationUtils.ensureNotNull(retrievalAugmentor, "retrievalAugmentor");
            return this;
        }
    }
                                        ...
}

所以可以直接注入AIservice:

注意:这里“MyAiService”必须是接口,LangChain4j 内部使用了 Java 的动态代理

当你调用 AiServices.builder(MyService.class).build() 时,自动为你生成了一个代理实现类。

/**
LangChain4j 的 AiServices 原生支持响应式流。
如果返回值是 Flux<String>,
LangChain4j 会自动将其识别为流式传输(Streaming)
*/
public interface MyAiService{

    public Flux<String> streamChat(自定义参数);

    public String chat(自定义参数);

}
===============================================================================

MyAiService aiService = AiServices.builder(MyAiService.class)
                                        ....
                            .retrievalAugmentor(retrievalAugmentor)//放到这里
                            .build();

 如何配置 RetrievalAugmentor?

RetrievalAugmentor主要组件:

可以通过 LangChain4j 配合以下核心组件实现

QueryTransformer优化检索词解决“用户不会提问”问题
QueryRouter查询路由允许同一个系统同时向不同的介质(向量库、关系型数据库、Web 搜索引擎)发起检索
ContentRetriever检索器
ContentAggregator聚合检索结果(重排序对这些杂乱的数据进行合并、去重、筛选和重新排序。
ContentInjector将检索到的内容注入 prompt“高质量上下文”
代码实现:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package dev.langchain4j.rag;

public interface RetrievalAugmentor {
    AugmentationResult augment(AugmentationRequest var1);
}
									|
									V
public class DefaultRetrievalAugmentor implements RetrievalAugmentor{...}

===============================上面是源码==========================================

									|
									V

RetrievalAugmentor retrievalAugmentor = DefaultRetrievalAugmentor.builder()
                            .queryRouter(...)
                            .queryTransformer(...)
                            .contentAggregator(...)
                            .contentInjector(...)
                            .build();

1.QueryTransformer(优化检索词)

langchain4j包中实现查询转换的接口
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package dev.langchain4j.rag.query.transformer;

import dev.langchain4j.rag.query.Query;
import java.util.Collection;

public interface QueryTransformer {
    Collection<Query> transform(Query var1);
}

支持多种场景:
  1. 查询改写(Query Rewriting)- 把一个查询改写成另一个更好的形式
  2. 查询扩展(Query Expansion)- 把一个查询扩展成多个相关查询
  3. 查询压缩(Query Compression)- 从对话历史中提取核心查询
  4. 查询分解(Query Decomposition)- 把复杂查询拆分成多个子查询

代码实现:

//核心就是编写个专门用来优化检索词的prompt

//核心就是编写个专门用来优化检索词的prompt
private static final PromptTemplate LG_AGENT_PROMPT = PromptTemplate.from("""
                                  编写优化检索词的提示词
""");


public class MyQueryTransformer implements QueryTransformer {
    @Override
    public Collection<Query> transform(Query query) {
        // 你的转换逻辑
        				...
    }
}

MyQueryTransformer queryTransformer = new MyQueryTransformer();

RetrievalAugmentor retrievalAugmentor = DefaultRetrievalAugmentor.builder()
                            .queryRouter(...)
                            .queryTransformer(queryTransformer) // 这里
                            .contentAggregator(...)
                            .contentInjector(...)
                            .build();

放进去后,当用AIservice调用接口中的方法时: 自动调用 queryTransformer.transform(query)

2、QueryRouter(查询路由)

langchain4j包里的queryRouter方法:

package dev.langchain4j.rag;

public class DefaultRetrievalAugmentor implements RetrievalAugmentor {
                                ...
public static class DefaultRetrievalAugmentorBuilder {
                                ...
public DefaultRetrievalAugmentorBuilder queryRouter(QueryRouter queryRouter) {
            this.queryRouter = queryRouter;
            return this;
        }
                                ...
  }
}

接收的是QueryRouter类型的参数,这是个接口:

package dev.langchain4j.rag.query.router;


public interface QueryRouter {
    Collection<ContentRetriever> route(Query var1);
}

直接实现这个接口:

核心:构建prompt,让llm返回该问题属于哪种场景:
常见的 RAG 查询路由场景:

  1. 向量检索:语义相似性、模糊匹配、概念理解

  2. 关键词检索:精确匹配、专有名词、编号、错误码

  3. 结构化查询:聚合、统计、范围查询、排序

  4. 图查询(Graph/Neo4j)

根据返回的场景从所有检索器(Collection<ContentRetriever>)中筛选出 对应的 检索器

代码实现:
public class MyQueryRouter implements QueryRouter {

 private static final PromptTemplate QUERY_ROUTE_PROMPT = PromptTemplate.from(...)

    @Override
    public Collection<ContentRetriever> route(Query query) {

                    //路由问题,获取结果
                    //判断执行哪个检索器
        }

}
RetrievalAugmentor retrievalAugmentor = DefaultRetrievalAugmentor.builder()
                            .queryRouter(new MyQueryRouter(检索器集合...))
                            .queryTransformer(queryTransformer) 
                            .contentAggregator(...)
                            .contentInjector(...)
                            .build();

3.ContentAggregator(聚合检索结果(去重、重排序))

核心是:RAG重排序

什么是重排序?
重排序(Reranking)是在通过混合检索(或其他方式)获得初步检索结果(候选文本块)后,再通过更強的模型(通常是Cross-Encoder或专用Reranker模型)对这些候选文本块进行重新打分和排序,将真正最相关、最有价值的内容排在前面。

重排序作用:

过滤噪声:初步检索往往会召回数十条文档,其中可能混杂着相关性较低的"噪声"内容。

提升答案精度,

优化上下文窗口利用率:把最相关的放前面

实现方式:

原理使用
RRF(Reciprocal Rank Fusion,倒数排名融合)

不看各个检索模型给出的绝对评分(Score),只看文档在各个检索结果列表中的相对排名(Rank),并通过倒数求和的方式进行多路召回结果的融合。

当向 DefaultContentAggregator 传入多个检索器或使用了QueryTransformer 导致产生了多个查询时,LangChain4j 内部就会自动触发 RRF 算法为你融合排名
ReRank模型

基于语义模型重新打分使用深度学习模型计算相关性

三种实现方式:

1.用云服务API  eg:Cohere

2.去Hugging Face下载到本地

3.将重排模型独立部署(Hugging Face的TEI)

用哪个?

只用RRF       
DefaultContentAggregator(内置RRF)
只用ReRank自己实现聚合器,调用scoringModel
二者兼得
ReRankingContentAggregator

项目里先用 RRF 将多路检索(如向量+全文)的结果融合成一路,再用 ReRank 模型进行高精度的深度打分。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package dev.langchain4j.rag.content.aggregator;

public interface ContentAggregator {
    List<Content> aggregate(Map<Query, Collection<List<Content>>> var1);
}
package dev.langchain4j.rag.content.aggregator;


public class ReRankingContentAggregator implements ContentAggregator {
                                ...
}

LangChain4j 官方已经内置了 ReRankingContentAggregator。 只需要直接通过 ReRankingContentAggregator.builder().scoringModel(...).build() 就能实现重排序。

// 聚合器
ContentAggregator contentAggregator = new ProgressAwareContentAggregator(
                            ReRankingContentAggregator.builder()
                                    .scoringModel(scoringModel)//ReRank模型
                                    .maxResults(5)
                                    .build());
RetrievalAugmentor retrievalAugmentor = DefaultRetrievalAugmentor.builder()
                            .queryRouter(new MyQueryRouter(检索器集合...))
                            .queryTransformer(queryTransformer) 
                            .contentAggregator(contentAggregator)
                            .contentInjector(...)
                            .build();

4、ContentInjector (将检索到的内容注入 prompt)

直接用的 LangChain4j 的 DefaultContentInjector。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package dev.langchain4j.rag.content.injector;

public class DefaultContentInjector implements ContentInjector {
                                ....

    public DefaultContentInjector() {
        this(DEFAULT_PROMPT_TEMPLATE, (List)null);
    }

    public DefaultContentInjector(PromptTemplate promptTemplate, List<String> metadataKeysToInclude) {
        this.promptTemplate = (PromptTemplate)Utils.getOrDefault(promptTemplate, DEFAULT_PROMPT_TEMPLATE);
        this.metadataKeysToInclude = Utils.copy(metadataKeysToInclude);
    }

}

只需要:放进RetrievalAugmentor 里就行,底层自动完成,内容注入

 //将检索到的内容注入到 LLM 的 Prompt 中
ContentInjector contentInjector = new DefaultContentInjector();

RetrievalAugmentor retrievalAugmentor = DefaultRetrievalAugmentor.builder()
                            .queryRouter(new MyQueryRouter(检索器集合...))
                            .queryTransformer(queryTransformer) 
                            .contentAggregator(contentAggregator)
                            .contentInjector(contentInjector)
                            .build();

// 注入到 AI Service 中
MyAiService aiService = AiServices.builder(MyAiService.class)
                    ...
        .retrievalAugmentor(retrievalAugmentor)
        .build();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值