C/C++教程

LangChain 和 LlamaIndex 在检索增强生成(RAG)中的大比拼:全面对比评测

本文主要是介绍LangChain 和 LlamaIndex 在检索增强生成(RAG)中的大比拼:全面对比评测,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

引言

检索增强生成(RAG)结合了信息检索与生成模型,使其成为一个强大的技术。在实现RAG时,目前最流行的两个框架是LangChainLlamaIndex。这两个框架都设计用于处理文档的摄入、分割、索引,并将这些步骤无缝整合到RAG工作流中。但哪一个更适合你的项目呢?

本文将探讨 RAG 的核心组件:加载器(Loaders)分割器(Splitters)索引(Indexing)链(Chains),并在 LangChain 和 LlamaIndex 中的工作方式做比较。每一步都包含代码示例,以便理解。

1 LangChain和LlamaIndex中的加载器

加载工具对于从各种来源(例如本地文件、API 或数据库)加载文档至关重要。LangChain 和 LlamaIndex 都内置了常见文档类型的加载器。

LangChain中的加载器 (LangChain)

LangChain 有多种加载工具,可以加载文本、PDF,甚至是网页。

代码示例 : 在LangChain中加载文本文件

    从langchain.document_loaders模块中导入TextLoader  
    # 加载一个文本文件  
    loader = TextLoader("sample.txt")  
    documents = loader.load()  
    # 读取sample.txt文件的内容  
    print(documents[0].page_content)

LangChain 加载器会返回一系列 Document 对象,这些对象可以接着处理。

在 LlamaIndex 中的加载器

LlamaIndex(原名GPT Index)也有类似的方法来加载文档,并且也支持额外格式,比如Pandas DataFrames。

加载文本的代码示例:在LlamaIndex中

    从llama_index导入SimpleDirectoryReader模块  
    # 从指定目录加载文档  
    loader = SimpleDirectoryReader('path/to/docs')  
    documents = loader.load_data()  
    print(documents[0].text)

在 LlamaIndex 中,加载器也会返回一个 Document 对象的列表,但结构可能与 LangChain 略有不同,这取决于具体的加载器。

2 LangChain 和 LlamaIndex 中的 Splitter 有何不同

拆分工具有助于将大型文档拆分成较小的部分,以确保它们不超过如GPT和BERT等模型的令牌限制。

LangChain 分割器

LangChain的TextSplitters,它让你自定义文本如何被分割——按字符、词语或句子。

代码示例:LangChain 中的文本分割

    从langchain.text_splitter导入CharacterTextSplitter

    # 定义一个字符分割器
    splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
    chunks = splitter.split_documents(documents)
    # 打印第一个分段的内容
    print(chunks[0].page_content)

这里,文档每1000字符分为一段,相邻段落之间保留200字符的重叠部分。

LlamaIndex中的分割器

LlamaIndex 使用 TokenTextSplitter 工具根据分词数量来分割文档,确保这些片段符合模型的分词限制。

代码示例:在 LlamaIndex 中拆分文本

    from llama_index import TokenTextSplitter

    # 定义一个分词器对象
    splitter = TokenTextSplitter(chunk_size=1000)
    chunks = splitter.split(documents)
    打印 chunks[0] 的文本内容

在 LlamaIndex 中,你可以指定每个分段包含多少个 tokens,从而实现对分段大小的精细控制。

3. LangChain与LlamaIndex索引的区别

索引是RAG系统的关键部分。它使得根据用户的查询需求快速且有效地检索相关片段。

LangChain中的索引

LangChain的VectorStoreIndex用于从文档嵌入创建索引,支持基于相似度的搜索。

索引示例:LangChain中的索引实现

from langchain.vectorstores import FAISS  
from langchain.embeddings.openai import OpenAIEmbeddings  

# 创建嵌入模型  
embedding_model = OpenAIEmbeddings()  

# 创建FAISS索引  
index = FAISS.from_documents(chunks, embedding_model)

在这里,LangChain 利用文档嵌入创建 FAISS 索引,来进行快速相似度搜索。

LlamaIndex中的索引

LlamaIndex 通过其 GPTTreeIndex 简化了索引,该索引使用树形结构实现高效检索。

索引示例:LlamaIndex 中的索引

从llama_index导入GPTTreeIndex模块

# 创建索引实例
index = GPTTreeIndex(docs)
query_engine = index.as_query_engine()  # 初始化查询引擎

在 LlamaIndex 中,GPTTreeIndex 构建层级结构,支持复杂的查询和更高效的检索。

4. LangChain和LlamaIndex中的链对比

在 RAG(检索后生成简写)中指的是结合检索和生成的操作序列。无论是 LangChain 还是 LlamaIndex,你都可以将组件串联。例如,先执行检索再使用生成模型。

LangChain 中的链

LangChain 允许创建灵活的链,支持使用不同组件(如 LLMChain 等)来结合语言模型和其他任务,从而实现复杂的工作流。

代码示例:LangChain 中的增强检索生成链

from langchain.chains import RetrievalQA  
from langchain.llms import OpenAI  

# 结合FAISS索引和OpenAI进行RAG回答
llm = OpenAI()  # llm为OpenAI模型
qa_chain = RetrievalQA(llm=llm, retriever=index.as_retriever())  # 索引的检索器()
result = qa_chain.run("文档里面写了什么?")  
print(result)  # 打印结果

LangChain的RetrievalQA功能将文档检索与语言生成相结合,从而创建了一个RAG工作流(RAG流程,Retrieval-Augmented Generation的简称)。

LlamaIndex 中的链式结构

LlamaIndex 也采用了类似的方法,其查询引擎结合了检索和语言模型的生成。

代码示例:增强检索生成链:在 LlamaIndex 中

response = query_engine.query("这个文档的内容是什么?")  
print(response)

LlamaIndex 简化了 query 方法中的许多复杂性,使得实现 RAG 更加简单,不像在 LangChain 中那样需要很多自定义设置。

要何时选择LangChain或LlamaIndex做RAG

选择 LangChain 和 LlamaIndex 进行检索增强生成(RAG)取决于项目的复杂程度、你需要的灵活性程度以及每个框架的具体功能和特点。让我们分析在什么情况下你应该选择哪一个,并通过实际例子来帮助阐明每个框架的强项和限制。

1. 控制与定制

LangChain 提供了对 RAG 流程中不同组件的更细致的控制。它允许你通过将语言模型、检索机制和自定义逻辑相连,构建高度灵活的工作流程。如果你的应用程序需要处理多种数据源(比如文本、API、PDF 等),并需应对不同的检索策略,LangChain 的灵活性将显得非常有用。

示例:想象你在构建一个多模态RAG系统,其中一些查询需要从PDF中获取信息,而其他查询则需要进行网络抓取和API访问。借助LangChain,你可以连接多个加载器,为每种类型使用不同的检索器,并将结果结合。

LangChain 中复杂的工作流程的代码示例:

    from langchain.chains import SequentialChain  # 这里引入SequentialChain,但代码中并未直接使用它,可能为示例中的复制错误或后续步骤的准备。
    from langchain.llms import OpenAI  
    from langchain.document_loaders import WebPageLoader, TextLoader  
    from langchain.vectorstores import FAISS  

    # 步骤1:从多个来源加载数据  
    pdf_loader = TextLoader("docs/sample.pdf")  
    web_loader = WebPageLoader(url="https://example.com")  
    documents = pdf_loader.load() + web_loader.load()  

    # 步骤2:创建嵌入并向量索引  
    embedding_model = OpenAIEmbeddings()  # 注意这里的模型应该是用于生成嵌入的特定模型,而不是通用的OpenAI模型,此处可能需要根据实际使用调整。
    index = FAISS.from_documents(documents, embedding_model)  

    # 步骤3:构建一个能检索并生成响应的链  
    llm = OpenAI()  
    qa_chain = RetrievalQA(llm=llm, retriever=index.as_retriever())  

    # 运行链  
    response = qa_chain.run("PDF和网站中的关键点是什么?")  # 这里询问的是PDF和网站中的关键点是什么。
    print(response)  # 这里直接打印了响应,实际应用中可能需要进一步处理或展示。

在这里,LangChain 能够无缝集成不同的文档来源,并将检索与生成链接起来,非常适合这种应用场景。

LlamaIndex 相比之下更加直接且结构化,围绕更简单的流程。它在处理较小范围的文档时非常高效,例如文本文档或分层文档结构。如果你的使用场景主要涉及大量文本数据,或者你正在寻找一个快速实现且设置简单的解决方案,LlamaIndex 可以简化这个过程。

例如:对于只需要对结构化的文档(例如法律文件、医疗报告)执行RAG的项目,LlamaIndex 可以快速搞定这项任务,几乎无需配置。

LlamaIndex 中一个简单的流程代码示例:

from llama_index import SimpleDirectoryReader, GPTTreeIndex  

# 从文件夹中加载文档  
loader = SimpleDirectoryReader('docs/')  
documents = loader.load_data()  

# 构建树型索引并发起查询  
index = GPTTreeIndex(documents)  
query_engine = index.as_query_engine()  

# 发起查询  
response = query_engine.query("总结这份法律文件。")  
print(response)

这个示例说明了LlamaIndex(LlamaIndex)处理层级文档结构的简单,重点在于快速设置,无需对每一步进行繁琐的自定义。

2. 集成和支持生态系统

LangChain 在你需要更广泛的集成支持时,就会表现得非常出色。它内置了各种向量数据库(FAISS、Pinecone、Chroma)、语言模型(OpenAI、GPT-4、Anthropic 的 Claude 语言模型)和 API(Hugging Face、Cohere)的内置连接器。这使得 LangChain 非常灵活,适用于处理复杂工作流程或集成不同类型的语言模型和检索工具的应用。

比如说,如果你需要在你的RAG流程中,在OpenAI的GPT-4和Hugging Face的BERT之间切换用于不同任务,LangChain支持多LLM和多检索器是一个很大的优势。

代码示例:集成多个大型语言模型(在LangChain中)

从langchain.chains导入SimpleSequentialChain
从langchain.llms导入OpenAI, HuggingFaceHub

# 依次使用GPT-4和Hugging Face BERT
gpt_chain = LLMChain(llm=OpenAI(model="gpt-4"), prompt="What is AI?")
bert_chain = LLMChain(llm=HuggingFaceHub(model="bert-large-uncased"), prompt="Translate the response.")

# 将它们连接起来
chain = SimpleSequentialChain(chains=[gpt_chain, bert_chain])
result = chain.run("What is the future of AI?")
print(result)

LangChain 允许你在同一个管道中轻松地在不同模型之间切换。

LlamaIndex 虽然稳定,但其集成能力不及 LangChain。然而,如果你主要需要快速高效地处理和查询文档(而不需要多个检索模型或 API),LlamaIndex 提供了一种简单可靠的方案。

3. 复杂查询及检索

LangChain 更适合需要细致检索逻辑的场景,例如这样的情况,根据数据类型进行查询路由、结合关键词搜索和向量相似度的混合搜索、或者集成检索后的排名系统。通过使用 LangChain 的高级工具如 MultiRetriever 和为生成模型定义的自定义提示,您可以构建更复杂的检索逻辑。

例如:假设你希望将关键词检索用于法律文件,同时使用基于嵌入的检索方法来处理科学论文。LangChain 可以根据文档类型,自动将查询路由到适合的检索器。

自定义检索:LangChain 中的代码示例

    from langchain.retrievers.multi_retriever import MultiRetriever  
    from langchain.retrievers import FAISSRetriever, KeywordRetriever  

    # 定义关键词检索和嵌入检索系统  
    keyword_retriever = KeywordRetriever(documents=legal_documents)  
    embedding_retriever = FAISSRetriever(index=scientific_index)  

    # 将它们结合起来形成一个多检索器  
    retriever = MultiRetriever(retrievers={  
        'legal': keyword_retriever,  
        'science': embedding_retriever  
    })  

    # 用一个法律问题来查询这个检索器  
    response = retriever.retrieve('What are the recent changes in contract law?')  
    print(response)

LlamaIndex 提供了足够但有限的查询处理能力,适用于简单的任务,例如在文档中查找相关部分或概括文本。其树状索引方法在处理具有清晰层级结构的文档时非常高效。

示例:对于处理复杂合同这样的用例,其中条款以层次结构排列,LlamaIndex的GPTTreeIndex表现尤为出色。

代码示例(如下):LlamaIndex 示例中的基于树结构的检索

    从llama_index导入GPTTreeIndex模块

    # 加载并索引法律合同
    documents = SimpleDirectoryReader('contracts/ ').load_data()
    index = GPTTreeIndex.from_documents(documents)

    # 查询合同中的特定条款
    response = index.query("合同中的终止条款有哪些?")
    print(response)

LlamaIndex 的基于树的结构让您能够在大型且结构化的文档中进行目标性的检索。

4. 生态环境和支持社区

LangChain 拥有一个更活跃且不断扩大的社区,由于其多样的应用场景、集成性和高级功能,它拥有这样的社区。如果你的项目需要最新的自然语言处理技术,或者你需要支持来扩展你的系统规模,LangChain 的生态系统则更成熟。

LlamaIndex 相对较新,在涉及简单工作流程和层次化数据结构的场景中越来越受欢迎。如果你在寻找不需要大型基础设施支持的轻量级文档检索方案,LlamaIndex 可能更符合你的需求。

结论:对于 RAG(检索增强生成),是 LlamaIndex 还是 LangChain?

总之,LangChain 和 LlamaIndex 都是构建 RAG 更适合的框架,不过它们更适合的应用场景有所不同。

  • 选择 LangChain 如果你需要:

  • 如果你需要对工作流程中的每个组件 进行精细控制(例如,链接不同类型的数据检索器和LLM)。

  • 多模态数据处理,比如文本、PDF和API。

  • 高级检索策略(例如,结合关键词和嵌入的混合搜索以及检索后排序)。

  • 与多种模型和存储系统 集成(例如,OpenAI、Hugging Face、Pinecone、FAISS)。

  • 如果你想构建具有自定义行为的复杂管道,LangChain 是更强大和灵活的选择。它专为需要深度定制检索策略和生成模型行为的场景而设计。

  • 选择 LlamaIndex 如果你需要的话

  • 一个简单轻量的解决方案,用于快速实现RAG,主要目标是文档检索和摘要。

  • 树状索引系统,适用于合同或法律报告等分层文档

  • 最少的设置和配置,允许你快速构建一个功能完整的RAG系统,而无需大量自定义。

  • 如果你在处理较为简单的基于文档的任务,不需要像LangChain那样灵活,LlamaIndex 是更简洁高效的选择

最终,选择LangChain还是LlamaIndex最终取决于你的项目复杂性。如果你正在构建一个复杂且多来源的系统,需要高级检索功能的话,LangChain会是你更好的选择。对于快速构建的基于文档的RAG系统,特别是那些具有层次结构的系统,LlamaIndex提供了一个简洁高效的良好平衡。

这篇关于LangChain 和 LlamaIndex 在检索增强生成(RAG)中的大比拼:全面对比评测的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!