选择 LlamaIndex 与 LangChain 的全面指南

选择 LlamaIndex 与 LangChain 的全面指南

核心要点

  • LlamaIndex: 专注于数据摄取、结构化管理,以及利用私有或领域特定数据完成高级问答、文档理解等任务。
  • LangChain: 提供一个开源综合框架,用于开发、部署和扩展基于 LLM 的应用,支持包括对话代理、翻译和复杂工作流在内的多种用例。
  • 自定义 LLM 集成: 提供详细的逐步代码指南,展示如何在 LlamaIndex 和 LangChain 框架中实现自定义 LLM,包括如何集成外部 API(如 Novita AI)。

引言

在人工智能和自然语言处理快速发展的背景下,两个框架已成为开发者处理大型语言模型(LLM)的强大工具:LlamaIndex 和 LangChain。本文旨在全面比较 LlamaIndex 与 LangChain,探索其核心功能、用例和实际应用。通过深入了解每个框架的核心功能、定价模型和集成能力,我们将帮助您做出明智决策,选择最适合您具体需求的工具。

什么是 LlamaIndex?

LlamaIndex 是一个精良的数据框架,旨在通过提供上下文相关、用户特定的数据,增强大型语言模型(LLM)的能力。与基于公共数据预训练的通用 LLM 不同,LlamaIndex 使这些模型能够访问和利用通常被隔离在 API 后、数据库中或困在 PDF 等非结构化格式中的私有、领域特定或问题中心的数据。

LlamaIndex 架构图

核心功能与能力

  • 数据摄取:LlamaIndex 提供数据连接器,可从各种来源(包括 API、PDF 和 SQL 数据库)以其原生格式无缝摄取数据。
  • 数据结构化:它将摄取的数据结构化为中间表示形式,优化供 LLM 高效消费,确保高性能。
  • 自然语言访问:LlamaIndex 提供引擎,实现数据的自然语言访问,通过查询引擎支持问答,通过聊天引擎支持对话交互。
  • 知识工作者:该框架包含作为 LLM 驱动知识工作者的代理,并配备从简单助手到复杂 API 集成的一系列工具。
  • 可观测性与评估:它集成了用于严谨实验、评估和监控的工具,确保应用持续改进。

用例

LlamaIndex 支持多种用例,例如:

  • 检索增强生成(RAG) 用于高级问答系统。
  • 聊天机器人 能够进行有意义的上下文感知对话。
  • 文档理解 以及从非结构化文档中提取数据。
  • 自主代理 能够进行研究和执行操作。
  • 多模态应用 将文本与图像等数据类型集成。
  • 在特定数据上微调模型以提升性能。

什么是 LangChain?

LangChain 是一个前沿框架,专门设计用于简化基于大型语言模型(LLM)的应用的开发、生产化和部署。它提供一套全面的工具和库,覆盖 LLM 应用生命周期的各个阶段,确保无缝高效的开发过程。

LangChain 架构图

核心功能与能力

  • 开发:LangChain 提供开源构建块、组件和第三方集成,简化 LLM 应用的创建。关键组件 LangGraph 支持构建有状态代理,并提供强大的流式处理和人机协作工作流支持。
  • 生产化:LangSmith 是一个强大的工具,用于检查、监控和评估 LLM 链的性能。它提供对应用性能的深入洞察,确保持续优化和可靠部署。
  • 部署:LangGraph Cloud 便于将 LangGraph 应用转换为生产就绪的 API 和助手,使其易于扩展和集成到各种系统中。
  • 分层组织:该框架分层组织,各层之间相互关联,确保应用开发的模块化和灵活性。

开源库

  • langchain-core:提供基础抽象和 LangChain 表达式语言,作为框架的基础。
  • langchain-community:集成第三方服务,扩展 LangChain 的能力。
  • 合作伙伴包:轻量级包,如 langchain-openai 和 langchain-anthropic,提供特定集成,增强框架的通用性。
  • langchain:包含构成应用认知架构的链、代理和检索策略。
  • LangGraph:用于构建基于图模型的步骤化有状态多参与者应用程序的强大工具,可与 LangChain 集成或独立使用。
  • LangServe:将 LangChain 链部署为 REST API,便于与 Web 服务集成。
  • LangSmith:一个开发者平台,提供用于调试、测试、评估和监控 LLM 应用的全面工具套件。

受众与用例

LangChain 面向各水平层次的开发者,从新手到专家,帮助他们利用 LLM 构建应用。其模块化、可扩展的架构使其适用于广泛的用例,包括但不限于:

  • 构建对话代理和聊天机器人。
  • 开发语言翻译和摘要工具。
  • 创建内容生成和分类系统。
  • 使用 LLM 实现复杂工作流。

LlamaIndex vs LangChain:主要区别

核心功能

  • LangChain 是一个综合框架,旨在简化数据感知和基于代理的应用程序的创建。它提供多种工具用于各种 LLM 驱动的应用,注重灵活性和高级 AI 能力。
  • LlamaIndex(前身为 GPT Index)是一个数据框架,专门专注于为 LLM 摄取、结构化和访问私有或领域特定数据。它简化了信息的索引和检索,非常适合基于文本的搜索和生成准确响应。

用例

  • LangChain 功能多样,可用于文本生成、语言翻译、文本摘要和文本分类等多种应用。它特别适合维持长而上下文相关的对话,因其出色的内存管理和链能力。
  • LlamaIndex 在文本搜索和质量响应为首要需求的场景中表现出色。常见用例包括内容生成、文档搜索与检索、增强聊天机器人和虚拟助手的 LLM。

定价与可用性

  • LangChain 是一个开源免费工具,其源代码可在 GitHub 等平台下载,任何人皆可使用。
  • LlamaIndex 是一个商业产品,其定价基于使用程度,意味着根据应用中的使用量可能产生费用。

定制化与灵活性

  • LangChain 提供高级定制选项,适合需要根据特定需求微调应用的开发者。
  • LlamaIndex 提供用户友好的功能和工具,便于将私有或领域特定数据无缝集成到 LLM 中,注重易用性和直接的数据管理。

数据处理

  • LangChain 设计用于处理多种数据类型和来源,提供 Schema 等组件用于数据组织,以及 Indexes 用于高效信息检索。
  • LlamaIndex 强调能够从其他索引组合索引,对于涉及多个数据源的复杂查询和工作流非常有效。

集成

  • LangChain 提供第三方服务集成,并可通过合作伙伴包扩展特定 LLM 提供商。
  • LlamaIndex 提供数据连接器,实现各种数据源的无缝集成,提升数据质量和性能。

LlamaIndex vs LangChain:实际示例对比

参考 Ming 在 Medium 上的文章,以下是一些实际示例,比较 LlamaIndex 与 LangChain。

使用本地 LLM 创建聊天机器人

代码示例展示了如何在两个框架中初始化 LLM,并打印聊天交互的输出。

LlamaIndex 代码:

from llama_index.llms import ChatMessage, OpenAILike

llm = OpenAILike(
    api_base="http://localhost:1234/v1",
    timeout=600,
    api_key="loremIpsum",
    is_chat_model=True,
    context_window=32768,
)
chat_history = [
    ChatMessage(role="system", content="You are a bartender."),
    ChatMessage(role="user", content="What do I enjoy drinking?"),
]
output = llm.chat(chat_history)
print(output)

LangChain 代码:

from langchain.schema import HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    openai_api_base="http://localhost:1234/v1",
    request_timeout=600,
    openai_api_key="loremIpsum",
    max_tokens=32768,
)
chat_history = [
    SystemMessage(content="You are a bartender."),
    HumanMessage(content="What do I enjoy drinking?"),
]
print(llm(chat_history))

为本地文件构建 RAG 系统

代码片段展示了如何加载数据、创建索引并执行查询。

LlamaIndex 代码:

from llama_index import ServiceContext, SimpleDirectoryReader, VectorStoreIndex

service_context = ServiceContext.from_defaults(  
    embed_model="local",  
    llm=llm, # This should be the LLM initialized in the task above.
)  
documents = SimpleDirectoryReader(
    input_dir="mock_notebook/",
).load_data()  
index = VectorStoreIndex.from_documents(  
    documents=documents,
    service_context=service_context,
)
engine = index.as_query_engine(  
    service_context=service_context,  
)
output = engine.query("What do I like to drink?")  
print(output)

LangChain 代码:

from langchain_community.document_loaders import DirectoryLoader  
  
# pip install "unstructured[md]"  
loader = DirectoryLoader("mock_notebook/", glob="*.md")  
docs = loader.load()  
  
from langchain.text_splitter import RecursiveCharacterTextSplitter  
  
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)  
splits = text_splitter.split_documents(docs)  
  
from langchain_community.embeddings.fastembed import FastEmbedEmbeddings  
from langchain_community.vectorstores import Chroma  
  
vectorstore = Chroma.from_documents(documents=splits, embedding=FastEmbedEmbeddings())  
retriever = vectorstore.as_retriever()  
  
from langchain import hub  
  
# pip install langchainhub  
prompt = hub.pull("rlm/rag-prompt")  
  
  
def format_docs(docs):  
    return "\
\
".join(doc.page_content for doc in docs)  
  
  
from langchain_core.runnables import RunnablePassthrough  
  
rag_chain = (  
    {"context": retriever | format_docs, "question": RunnablePassthrough()}  
    | prompt  
    | llm # This should be the LLM initialized in the task above.
)  
print(rag_chain.invoke("What do I like to drink?"))

从比较来看,LlamaIndex 专注于 RAG 系统,提供了更简单的方法,而 LangChain 提供了更抽象、高层次的方法。

LlamaIndex vs LangChain:如何在 LlamaIndex 中使用自定义 LLM?

要将 Novita AI 的 LLM API 与 LlamaIndex 集成,您需要创建一个自定义适配器,将 Novita AI API 调用包装在 LlamaIndex 框架 内。以下是一个概念性示例。请注意,本示例假设您对 API 和 LlamaIndex 框架有基本了解。

步骤 1:为 Novita AI LLM 定义自定义适配器

首先,为 Novita AI LLM 定义自定义适配器:

class NovitaAILLM:
    def __init__(self, api_key):
        from openai import OpenAI
        self.client = OpenAI(api_key=api_key, base_url="https://api.novita.ai/v3/openai")

    def complete_chat(self, messages, stream=False, max_tokens=512):
        response = self.client.chat.completions.create(
            model="Nous-Hermes-2-Mixtral-8x7B-DPO",
            messages=messages,
            stream=stream,
            max_tokens=max_tokens
        )
        return response

步骤 2:集成到 LlamaIndex 服务上下文

接下来,您需要将此适配器集成到 LlamaIndex 服务上下文中。以下是概念性示例:

from llama_index import (
    KeywordTableIndex,
    SimpleDirectoryReader,
    ServiceContext,
)
from llama_index.llms import LLM

class NovitaAILLMAdapter(LLM):
    def __init__(self, api_key):
        self.novitailm = NovitaAILLM(api_key)

    def generate_text(self, prompt, stop_sequences=None, **kwargs):
        # Prepare the messages for the chat completion
        messages = [
            {"role": "system", "content": prompt}
        ]
        # Call the Novita AI LLM to complete the chat
        response = self.novitailm.complete_chat(messages)
        if isinstance(response, list):  # If streaming, collect all chunks
            return "".join([chunk.choices[0].delta.content for chunk in response])
        else:
            return response.choices[0].message.content

# Initialize the Novita AI LLM adapter with your API key
novitailm_adapter = NovitaAILLMAdapter(api_key="<YOUR Novita AI API Key>")

# Create the service context with the custom LLM adapter
service_context = ServiceContext.from_defaults(llm=novitailm_adapter)

# Load documents and build the index as before
documents = SimpleDirectoryReader("data").load_data()
index = KeywordTableIndex.from_documents(documents, service_context=service_context)

# Now you can use the index with the custom LLM for queries
query_engine = index.as_query_engine()
response = query_engine.query("What did the author do after his time at Y Combinator?")
print(response)

此示例展示了如何为 Novita AI 的 LLM 创建自定义适配器并集成到 LlamaIndex 框架中。您需要将 <YOUR Novita AI API Key> 替换为您的实际 Novita AI API 密钥。

请注意,这是一个概念性示例,可能需要根据您使用的库的具体版本以及 Novita AI LLM 的精确 API 细节进行调整。请始终参考官方文档以获取最准确和最新的信息。

LlamaIndex vs LangChain:如何在 LangChain 中使用自定义 LLM?

要将 Novita AI LLM API 与 LangChain 通过 ** 自定义 LLM** 集成,您需要创建一个继承 LangChain 的 LLM 类并使用 Novita AI API 逻辑的自定义类。

以下是逐步指南:

步骤 1:安装 OpenAI Python 库

首先,确保已安装 OpenAI 库,它将用于与 Novita AI 的 API 交互。

pip install 'openai>=1.0.0'

步骤 2:导入所需库

从 LangChain 和 OpenAI 库导入必要模块。

from typing import Any, Dict, Iterator, List, Optional
from langchain_core.callbacks.manager import CallbackManagerForLLMRun
from langchain_core.language_models.llms import LLM
from langchain_core.outputs import GenerationChunk
from openai import OpenAI

步骤 3:定义自定义 LLM 类

扩展 LLM 类以创建使用 Novita AI API 的自定义 LLM。

class NovitaAILLM(LLM):
    def __init__(self, api_key: str, model_name: str = "Nous-Hermes-2-Mixtral-8x7B-DPO"):
        self.api_key = api_key
        self.model_name = model_name
        self.client = OpenAI(api_key=api_key, base_url="https://api.novita.ai/v3/openai")

    def _call(
        self,
        prompt: str,
        stop: Optional[List[str]] = None,
        run_manager: Optional[CallbackManagerForLLMRun] = None,
        **kwargs: Any,
    ) -> str:
        """Run the LLM on the given input."""
        response = self.client.chat.completions.create(
            model=self.model_name,
            messages=[{"role": "user", "content": prompt}],
            stream=False,
            max_tokens=512,
        )
        return response.choices[0].message.content

    def _stream(
        self,
        prompt: str,
        stop: Optional[List[str]] = None,
        run_manager: Optional[CallbackManagerForLLMRun] = None,
        **kwargs: Any,
    ) -> Iterator[GenerationChunk]:
        """Stream the LLM on the given prompt."""
        response = self.client.chat.completions.create(
            model=self.model_name,
            messages=[{"role": "user", "content": prompt}],
            stream=True,
            max_tokens=512,
        )
        for chunk in response:
            chunk_text = chunk.choices[0].delta.content or ""
            yield GenerationChunk(text=chunk_text)

    @property
    def _identifying_params(self) -> Dict[str, Any]:
        """Return a dictionary of identifying parameters."""
        return {
            "model_name": self.model_name,
        }

    @property
    def _llm_type(self) -> str:
        """Get the type of language model used by this chat model. Used for logging purposes only."""
        return "NovitaAILLM"

步骤 4:初始化并使用自定义 LLM

使用您的 Novita AI API 密钥创建自定义 LLM 实例,并用于生成文本。

# Replace with your actual Novita AI API key
novita_api_key = "<YOUR Novita AI API Key>"

# Initialize the custom LLM
novita_llm = NovitaAILLM(api_key=novita_api_key)

# Generate text
prompt = "Hi there!"
response = novita_llm._call(prompt=prompt)
print(response)

# Or stream the response
for chunk in novita_llm._stream(prompt=prompt):
    print(chunk.text, end="")

此代码设置了一个自定义 LLM,使用 Novita AI 的 API 根据给定提示生成文本。_call 方法用于非流式响应,_stream 方法用于流式响应。根据 Novita AI 的 API 文档和您的具体需求调整 model_name 及其他参数。

结论

总而言之,LlamaIndex 和 LangChain 都是处理大型语言模型的有价值工具,各有优势。LlamaIndex 在数据摄取和检索方面表现出色,非常适合需要高效处理特定数据和高级问答系统的项目。LangChain 为开发和部署 LLM 应用提供了更全面的框架,具有模块化架构和广泛集成。两者之间的选择取决于您项目的具体需求。

常见问题

可以同时使用 LangChain 和 LlamaIndex 吗?

可以。这取决于您 LLM 项目的具体需求。

LangChain 适合生产环境吗?

是的,LangChain 0.1 及更高版本已做好生产准备。

对于 RAG,LlamaIndex 还是 LangChain 更好?

如果您的首要关注点是数据检索和搜索能力,建议使用 LlamaIndex。当您需要处理复杂工作流的灵活框架时,LangChain 更适合。

Novita AI 是全能云平台,助力您的 AI 愿景。集成 API、无服务器、GPU 实例——经济高效的工具。无需基础设施,免费开始,让您的 AI 愿景成为现实。

推荐阅读

如何使用 LangChain 创建您的 LLM:逐步指南

掌握 LangChain 流式处理:与 LLM 交互的技巧