本文经翻译并二次整理自LangChain Integrates NVIDIA NIM for GPU-optimized LLM Inference in RAG一文。NVIDIA NIM前脚刚推出,LangChain已经完成了集成适配,今天本文将展示基于NVIDIA NIM的RAG应用实战 。本系列合集,点击链接查看

大约在一年半前,OpenAI 推出了 ChatGPT,标志着生成式 AI 时代的开启。自此,这一领域经历了迅猛的发展,并被各行各业广泛采纳。企业在将注意力从 LLM 应用的原型制作转向实际生产时,往往更倾向于选择自主托管的解决方案,而非依赖第三方模型服务。鉴于许多人在这一转变过程中遇到困难,LangChain 对于能够整合全新的 NVIDIA NIM 推理微服务感到无比振奋。

NVIDIA NIM 是什么?

LangChain 携手 NVIDIA:RAG加速新篇章_微服务

NVIDIA NIM 是一系列用户友好的微服务,它们旨在加速企业内部生成式 AI 的部署进程。这种多功能的运行环境支持包括开源社区模型、NVIDIA AI 基础模型以及自定义 AI 模型在内的广泛 AI 模型。开发者可以利用行业标准的 API,仅需数行代码即可快速构建出企业级的 AI 应用。NIM 基于 NVIDIA Triton Inference Server、NVIDIA TensorRT、NVIDIA TensorRT-LLLLM 等强大的推理引擎,以及 PyTorch 等技术构建,旨在提供无缝的 AI 推理体验,确保您可以自信地在任何环境中部署 AI 应用。无论是在本地服务器还是云端环境中,NIM 都是实现大规模、高性能生成式 AI 推理的最佳选择。

为什么 LangChain 对 NVIDIA NIM 充满期待?

LangChain 携手 NVIDIA:RAG加速新篇章_开发者_02

我们对 NVIDIA NIM 充满期待的原因有几个。

首先,最引人注目的是它的自托管特性。这意味着您向基于 NVIDIA 的模型发送的任何数据都将保留在您的服务器上,不会外传。对于那些经常需要处理敏感信息的 RAG 应用来说,这一点尤其重要。

其次,NIM 提供了一系列预构建的容器,这让您可以轻松选择并使用最新的生成式 AI 模型,而无需进行复杂的配置。

LangChain 携手 NVIDIA:RAG加速新篇章_生成式_03

最后,NIM 的可扩展性。在个人电脑上本地运行模型是一回事,但要将其作为服务部署,并且保持与专业服务提供商相同的稳定性和可用性,则是另一回事。幸运的是,NIM 已经为您解决了这一挑战。

如何开始使用 NVIDIA NIM?

LangChain 携手 NVIDIA:RAG加速新篇章_微服务_04

开始使用 NIM 非常简单。在 NVIDIA API 目录中,开发者可以轻松访问多种 AI 模型,用于构建和部署生成式 AI 应用。NIM 是 NVIDIA AI Enterprise 的一部分,这是一个全面的、基于云的软件平台,旨在简化生产级 AI 应用的开发和部署流程。您可以通过 这篇博客 获取如何开始使用的详细指南。

如何将 NVIDIA NIM 与 LangChain 结合使用?

最后,让我们来谈谈如何将 NIM 与 LangChain 结合使用。我们新增了一个支持 NIM 的集成包。要开始使用这个集成,您需要先安装我们专门为 NIM 设计的集成包:

pip install langchain_nvidia_ai_endpoints

安装完成后,您就可以导入所需的模型了:

from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings, ChatNVIDIA

集成示例

接下来,我们将通过一个示例来展示如何构建应用程序。如果您更喜欢通过视频学习,您可以在 这里 观看视频教程。

我们将利用 LangSmith 文档的一部分来构建一个 RAG 应用。为了增加趣味性,我们将采用一种高级检索方法:假设文档嵌入(HyDE)。HyDE 的设计理念是,搜索查询可能与我们要检索的文档不在同一个嵌入空间中。为了解决这个问题,我们可以利用 LLM 生成一个假设文档,然后检索与该假设文档相似的文档。

首先,我们需要安装一些额外的包:

pip install langchain-community langchain-text-splitters faiss-cpu

然后,我们将加载 LangSmith 文档作为我们 RAG 应用的数据源:

from langchain_community.document_loaders import WebBaseLoader
loader = WebBaseLoader("https://docs.smith.langchain.com/user_guide") 

docs = loader.load()

在对文档进行索引之前,我们需要初始化嵌入模型:

from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings
embeddings = NVIDIAEmbeddings()

接下来,我们可以使用 FAISS 向量存储来执行索引操作:

from langchain_community.vectorstores import FAISS
from langchain_text_splitters import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
documents = text_splitter.split_documents(docs)
vector = FAISS.from_documents(documents, embeddings)
retriever = vector.as_retriever()

然后,我们可以初始化 LLM:

from langchain_core.prompts import ChatPromptTemplate
from langchain_nvidia_ai_endpoints import ChatNVIDIA
from langchain_core.output_parsers import StrOutputParser

model = ChatNVIDIA(model="mistral_7b")

现在,我们将创建一个假设文档生成器。这个生成器由一个提示模板、LLM 和一个简单的输出解析器组成:

hyde_template = """Even if you do not know the full answer, generate a one-paragraph hypothetical answer to the below question:

{question}"""
hyde_prompt = ChatPromptTemplate.from_template(hyde_template)
hyde_query_transformer = hyde_prompt | model | StrOutputParser()

接着,我们将创建一个新的链,用于生成假设文档:

from langchain_core.runnables import chain

@chain
def hyde_retriever(question):
    hypothetical_document = hyde_query_transformer.invoke({"question": question})
    return retriever.invoke(hypothetical_document)

然后,我们将创建一个链,用于根据检索到的文档和问题生成最终答案:

template = """Answer the question based only on the following context:
{context}

Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)
answer_chain = prompt | model | StrOutputParser()

最后,我们将创建一个最终的链,结合假设文档检索器和答案生成链,以产生最终的输出:

@chain
def final_chain(question):
    documents = hyde_retriever.invoke(question)
    for s in answer_chain.stream({"question": question, "context": documents}):
        yield s

请注意,我们通过生成令牌来实现最终链的流式输出。现在,让我们来测试一下这个链:

for s in final_chain.stream("how can langsmith help with testing"):
    print(s, end="")

通过这种方式,LangChain 利用 NVIDIA NIM 为 RAG 应用带来了 GPU 加速的 LLM 推理能力,大大提升了处理敏感数据的安全性,同时简化了从原型到生产的转变过程。