检索增强生成(RAG)通过在大型语言模型生成回复前为其提供相关外部信息来提升其表现。此过程包含两个主要环节:一是获取相关数据,二是根据原始查询和获取到的数据生成回答。像 LangChain 和 LlamaIndex 这样的 Python 库经常配合使用,以有效地搭建 RAG 系统。尽管每个库都能执行一些重叠功能,但它们各自具备的主要优势使得它们在构建 RAG 流程时高度互补。LlamaIndex 主要擅长 RAG 过程中数据摄取、建立索引和数据获取的部分。它的强项在于连接各种数据源(文件、数据库、API),解析文档,并创建结构化的索引,尤其是针对语义搜索优化的向量索引。在典型的 RAG 设置中,LlamaIndex 负责接收用户查询并从您的知识库中找出最相关的信息片段。另一方面,LangChain 为编排整个 LLM 工作流程提供了一个全面的框架。它提供与 LLM 交互、管理提示、将组件连接起来以及定义代理的抽象。在 RAG 的语境下,LangChain 通常管理着整体流程:它接收用户查询,使用一个检索器(通常由 LlamaIndex 提供支持)来获取相关上下文,利用其模板功能将此上下文与原始查询一同格式化为提示,将组合好的提示发送给 LLM,并可能解析 LLM 的输出。常见整合模式将这些库结合起来最常见的方式,是将 LlamaIndex 的索引和查询引擎用作 LangChain 链中的 Retriever。LangChain 定义了一个标准 Retriever 接口,该接口明确了如何根据查询获取相关文档。LlamaIndex 提供了与自身索引直接配合的该接口实现。LlamaIndex 作为 LangChain 检索器: 您首先使用 LlamaIndex 构建您的数据索引(例如,一个 VectorStoreIndex)。然后,使用 LlamaIndex 的 as_retriever() 方法从该索引创建一个检索器。这个检索器对象可以直接用于设计用于问答的 LangChain 链,例如 RetrievalQA 或使用 LangChain 表达式语言 (LCEL) 构建的链。LangChain 会处理与 LLM 的交互,自动将获取到的文档(通过 LlamaIndex 检索器获得)传入提示上下文。LlamaIndex 查询引擎作为 LangChain 工具: 对于涉及代理的更复杂工作流程,LlamaIndex QueryEngine 可以被包装为 LangChain Tool。代理可以决定何时使用此工具来查询知识库。这使得代理能够在推理过程中需要时动态地获取特定信息。流程示意以下图表展示了一个使用 LangChain 进行编排、LlamaIndex 进行获取的标准 RAG 流程:digraph G { rankdir=LR; node [shape=box, style=rounded, fontname="Arial", fontsize=10, margin=0.2]; edge [fontname="Arial", fontsize=9]; subgraph cluster_0 { label = "LangChain 编排"; bgcolor="#e9ecef"; style=filled; color="#adb5bd"; prompt [label="提示词格式化"]; llm [label="LLM 交互"]; output [label="最终回答", shape=ellipse, style=filled, fillcolor="#b2f2bb"]; prompt -> llm [label="增强提示词"]; } subgraph cluster_1 { label = "LlamaIndex 获取"; bgcolor="#e9ecef"; style=filled; color="#adb5bd"; retriever [label="检索器\n(来自 LlamaIndex 索引)", style=filled, fillcolor="#a5d8ff"]; index [label="数据索引\n(向量存储等)", shape=cylinder, style=filled, fillcolor="#bac8ff"]; retriever -> index [style=dotted, arrowhead=none, label="查询"]; } query [label="用户查询", shape=ellipse, style=filled, fillcolor="#ffec99"]; query -> retriever [label="1. 查询"]; retriever -> prompt [label="2. 相关文档"]; query -> prompt [label="3. 原始查询"]; llm -> output [label="4. 生成回复"]; }用户查询触发 LlamaIndex 检索器,该检索器从索引中获取相关文档。LangChain 将这些文档与原始查询一同格式化为 LLM 的提示词,LLM 随后生成最终回答。简化整合示例我们来看一个将 LlamaIndex 检索器整合到 LangChain RetrievalQA 链中的简化 Python 示意。假设您已构建了一个 LlamaIndex index 对象(在 LlamaIndex 基础章节中有所涉及)。# 假设 'index' 是一个预先构建好的 LlamaIndex 索引对象 # 假设 'llm' 是一个预先配置好的 LangChain LLM 对象 from langchain.chains import RetrievalQA # LlamaIndex 提供了检索器接口的实现 llama_retriever = index.as_retriever() # LangChain 链使用 LlamaIndex 检索器 rag_chain = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff", # 仅为演示使用的简单链类型 retriever=llama_retriever ) # 使用整合后的链 query = "使用向量数据库进行 RAG 的主要优点是什么?" response = rag_chain.run(query) # LangChain 编排调用 print(response) # 输出将是 LLM 的回答,其依据是 LlamaIndex 获取到的文档在该代码片段中:我们直接从 LlamaIndex index 中获得一个 retriever 对象。我们实例化一个 LangChain RetrievalQA 链,并将 LLM 接口和 llama_retriever 都传递给它。当调用 rag_chain.run() 时,LangChain 会使用 llama_retriever(其内部调用 LlamaIndex)来获取与 query 相关的文档。接着,它会构建提示词,调用 llm,并返回结果。通过整合这些库,您可以发挥 LlamaIndex 在高效数据处理和数据获取方面的独特优势,同时结合 LangChain 灵活的框架来构建和管理整体 LLM 应用逻辑。这种职责分离有助于 RAG 系统更清晰、更易于维护,并且通常性能也更好。后续章节将详细介绍向量存储的设置和这些流程的构建步骤。