这一部分详细介绍了 LangChain4j 中的高级 RAG(Advanced RAG)实现。高级 RAG 通过多个模块化组件来增强检索功能,提供了高度的灵活性和定制化能力,一般要做好,多半都会采用此方案
高级 RAG(Advanced RAG)
高级 RAG 可以通过 LangChain4j 实现,涉及以下核心组件:
- QueryTransformer(查询转换器)
- QueryRouter(查询路由器)
- ContentRetriever(内容检索器)
- ContentAggregator(内容聚合器)
- ContentInjector(内容注入器)
以下图表展示了这些组件是如何协同工作的:
langchain4j.dev/assets/images/advanced-rag-fb84283d02470b835ff2f4913f08fdbf.png">
流程如下:
- 用户生成一个 UserMessage,该消息被转换为一个 Query。
- QueryTransformer 将 Query 转换为一个或多个 Query。
- 每个 Query 通过 QueryRouter 路由到一个或多个 ContentRetriever。
- 每个 ContentRetriever 检索与每个 Query 相关的 Content。
- ContentAggregator 将所有检索到的 Content 合并为一个最终的排序列表。
- 这些 Content 被注入到原始的 UserMessage 中。
- 最后,包含原始查询以及注入的相关内容的 UserMessage 被发送到语言模型(LLM)。
请参考每个组件的 JavaDoc 以获取更多详细信息。
Retrieval Augmentor(检索增强器)
RetrievalAugmentor 是 RAG 流程的入口点,负责将 ChatMessage 与从各种来源检索到的相关 Content 增强。
在创建 AI 服务时,可以指定一个 RetrievalAugmentor 实例:
Assistant assistant = AiServices.builder(Assistant.class)
...
.retrievalAugmentor(retrievalAugmentor)
.build();
每次调用 AI 服务时,指定的 RetrievalAugmentor 将被调用来增强当前的 UserMessage。
你可以使用默认的 RetrievalAugmentor 实现(如下所述),或者实现一个自定义的。
默认检索增强器(Default Retrieval Augmentor)
LangChain4j 提供了一个现成的 RetrievalAugmentor 接口实现:DefaultRetrievalAugmentor,它适用于大多数 RAG 使用场景。它的设计灵感来源于 这篇文章 和 这篇论文。建议查阅这些资源以更好地理解该概念。
Query(查询)
Query 表示 RAG 流程中的用户查询。它包含查询文本和查询元数据。
查询元数据(Query Metadata)
Query 中的 Metadata 包含以下可能在 RAG 流程的各个组件中有用的信息:
- Metadata.userMessage():应该被增强的原始 UserMessage。
- Metadata.chatMemoryId():@MemoryId 注解的方法参数的值。更多详情见 这里。这可以用于识别用户,并在检索过程中应用访问限制或过滤器。
- Metadata.chatMemory():所有之前的 ChatMessage。这有助于理解查询被提出时的上下文。
查询转换器(Query Transformer)
QueryTransformer 将给定的 Query 转换为一个或多个 Query。目标是通过修改或扩展原始查询来提高检索质量。
一些已知的改进检索的方法包括:
- 查询压缩(Query Compression)
- 查询扩展(Query Expansion)
- 查询重写(Query Re-writing)
- 回退提示(Step-back Prompting)
假设文档嵌入(Hypothetical Document Embeddings,HyDE)
更多详细信息可以在这里找到。
默认查询转换器(Default Query Transformer)
DefaultQueryTransformer 是在 DefaultRetrievalAugmentor 中使用的默认实现。它不对 Query 进行任何修改,只是将其传递下去。
压缩查询转换器(Compressing Query Transformer)
CompressingQueryTransformer 使用语言模型(LLM)将给定的查询和之前的对话压缩为一个独立的查询。这在用户可能提出涉及之前问题或答案中信息的后续问题时非常有用。
例如:
用户:告诉我关于 John Doe 的信息
AI:John Doe 是……
用户:他住在哪里?
仅凭 “他住在哪里?” 这个查询本身无法检索到所需的信息,因为它没有明确提及 John Doe,不清楚 “他” 指代的是谁。
当使用 CompressingQueryTransformer 时,LLM 将读取整个对话,并将 “他住在哪里?” 转换为 “John Doe 住在哪里?”。
扩展查询转换器(Expanding Query Transformer)
ExpandingQueryTransformer 使用语言模型(LLM)将给定的查询扩展为多个查询。这很有用,因为 LLM 可以以多种方式重新表述和重新构建查询,这将有助于检索到更相关的内容。
内容(Content)
Content 表示与用户查询相关的文本内容。目前,它仅限于文本内容(即 TextSegment),但未来可能会支持其他模态(例如图像、音频、视频等)。
内容检索器(Content Retriever)
ContentRetriever 使用给定的查询从底层数据源检索相关的内容。底层数据源可以是任何东西:
- 嵌入存储(Embedding Store)
- 全文搜索引擎(Full-text Search Engine)
- 向量和全文搜索的混合(Hybrid of Vector and Full-text Search)
- Web 搜索引擎(Web Search Engine)
- 知识图谱(Knowledge Graph)
- SQL 数据库(SQL Database)
- 等等
ContentRetriever 返回的内容列表按相关性从高到低排序。