欢迎光临
我们一直在努力

实现高级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);
}

支持多种场景:
  • 查询改写(Query Rewriting)- 把一个查询改写成另一个更好的形式
  • 查询扩展(Query Expansion)- 把一个查询扩展成多个相关查询
  • 查询压缩(Query Compression)- 从对话历史中提取核心查询
  • 查询分解(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();

    赞(0)
    未经允许不得转载:171主机测评 » 实现高级RAG(Advanced RAG)--RetrievalAugmentor--LangChain4j
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址