Press "Enter" to skip to content

使用Amazon SageMaker Studio与Llama 2、LangChain和Pinecone来构建一个RAG问答解决方案,以便进行快速实验

检索增强生成(Retrieval Augmented Generation,简称RAG)允许您为大型语言模型(Large Language Model,简称LLM)提供对外部知识源(例如存储库、数据库和API)的访问,而无需对其进行精调。当使用生成式人工智能进行问题回答时,RAG使LLM能够使用最相关、最新的信息回答问题,并可选择引用其数据来源以进行验证。

从文档中检索知识的典型RAG解决方案使用嵌入模型将来自数据源的数据转换为嵌入,并将这些嵌入存储在向量数据库中。当用户提出问题时,它会搜索向量数据库并检索与用户查询最相似的文档。接下来,它将检索到的文档和用户查询组合成一个增强的提示,然后将其发送到LLM进行文本生成。这种实现中包含两个模型:嵌入模型和生成最终响应的LLM。

在本文中,我们演示了如何使用Amazon SageMaker Studio构建RAG问答解决方案。

使用笔记本进行基于RAG的问题回答

实施RAG通常需要尝试不同的嵌入模型、向量数据库、文本生成模型和提示,同时调试代码,直到实现一个功能性原型。Amazon SageMaker提供了配备GPU实例的托管Jupyter笔记本,让您可以在这个初始阶段快速进行实验,而无需启动额外的基础设施。在SageMaker中,使用笔记本有两个选项。第一个选项是通过SageMaker Studio提供的快速启动笔记本。在SageMaker Studio中,这是针对机器学习(ML)专门构建的集成开发环境(IDE),您可以在不同的实例类型和配置下启动笔记本,与同事合作,并访问其他针对机器学习(ML)的专门功能。第二个选项是使用SageMaker笔记本实例,它是一个完全托管的ML计算实例,运行Jupyter Notebook应用程序。

在本文中,我们介绍了一种RAG解决方案,通过从外部知识源中获取额外数据,增强模型的知识,以提供更准确的响应,以适应自定义领域的特定需求。我们使用单个在ml.g5.2xlarge实例(1个A10G GPU)上运行的SageMaker Studio笔记本和Llama 2 7b chat hf(Hugging Face Hub优化的Llama 2 7b的微调版本),后者针对对话使用案例进行了优化。我们使用两篇AWS Media & Entertainment博客文章作为示例外部数据,并使用BAAI/bge-small-en-v1.5嵌入将其转换为嵌入。我们将嵌入存储在高性能搜索和相似性匹配的向量数据库Pinecone中。我们还讨论了如何从笔记本中的实验过渡到在完成原型制作后将模型部署到SageMaker终端节点进行实时推理的步骤。同样的方法也可以用于不同的模型和向量数据库。

解决方案概述

下图说明了解决方案架构。

使用Amazon SageMaker Studio与Llama 2、LangChain和Pinecone来构建一个RAG问答解决方案,以便进行快速实验 四海 第1张

实施解决方案包括两个高级步骤:使用SageMaker Studio笔记本开发解决方案,以及将模型部署为推理。

使用SageMaker Studio笔记本开发解决方案

请按照以下步骤开始开发解决方案:

  1. 从Hugging Face Hub在笔记本中加载Llama-2 7b聊天模型。
  2. 使用LangChain创建一个PromptTemplate,并用它为您的用例创建提示。
  3. 对于1-2个示例提示,从外部文档中添加相关的静态文本作为提示上下文,并评估响应的质量是否提高。
  4. 假设质量提高,实施RAG问答工作流程:
    • 收集可以帮助模型更好地回答问题的外部文档。
    • 加载BGE嵌入模型,并使用它生成这些文档的嵌入。
    • 将这些嵌入存储在Pinecone索引中。
    • 当用户提问时,在Pinecone中执行相似性搜索,并将最相似文档的内容添加到提示的上下文中。

在SageMaker上部署模型以实现规模化推理

当您达到性能目标时,可以将模型部署到SageMaker,供生成性AI应用使用:

  1. 将Llama-2 7b聊天模型部署到SageMaker实时端点。
  2. BAAI/bge-small-en-v1.5嵌入模型部署到SageMaker实时端点。
  3. 在问答生成性AI应用中使用已部署的模型。

在接下来的章节中,我们将引导您逐步完成在SageMaker Studio笔记本中实现此解决方案的步骤。

先决条件

要按照本文中的步骤进行操作,您需要拥有一个AWS账户和一个具有创建和访问解决方案资源权限的AWS身份和访问管理(IAM)角色。如果您是AWS的新用户,请参阅创建一个独立的AWS账户

要在您的AWS账户中使用SageMaker Studio笔记本,您需要拥有一个具有权限启动SageMaker Studio应用程序的用户配置文件的SageMaker域。如果您是第一次使用SageMaker Studio,最快的方法是使用快速设置向导。只需单击一次,SageMaker会根据默认预设配置SageMaker域,包括设置用户配置文件、IAM角色、IAM身份验证和公共互联网访问。本文的笔记本假设使用的是ml.g5.2xlarge实例类型。要查看或增加您的配额,请打开AWS服务配额控制台,在导航窗格中选择AWS服务,选择Amazon SageMaker,并参考运行在ml.g5.2xlarge实例上的KernelGateway应用程序的值。

使用Amazon SageMaker Studio与Llama 2、LangChain和Pinecone来构建一个RAG问答解决方案,以便进行快速实验 四海 第2张

确认配额限制后,您需要完成使用Llama 2 7b chat的依赖项。

Llama 2 7b chat在Llama 2许可证下可用。要访问Hugging Face上的Llama 2,您需要先完成一些步骤:

  1. 如果您还没有Hugging Face账户,请创建一个。
  2. 在Meta 网站上填写“请求访问Llama的下一个版本”表单。
  3. 在Hugging Face上请求访问Llama 2 7b chat

在获得访问权限之后,您可以创建一个新的访问令牌来访问模型。要创建访问令牌,请转到Hugging Face网站上的设置页面。

您需要有一个Pinecone账户才能将其用作向量数据库。可以通过AWS Marketplace来使用Pinecone。Pinecone网站还提供了创建免费账户的选项,该账户具有创建单个索引的权限,这足以满足本文的需求。要获取您的Pinecone密钥,请打开Pinecone控制台并选择API Keys

使用Amazon SageMaker Studio与Llama 2、LangChain和Pinecone来构建一个RAG问答解决方案,以便进行快速实验 四海 第3张

设置笔记本和环境

要按照本文中的代码操作,请打开SageMaker Studio,并克隆以下的GitHub存储库。接下来,打开笔记本studio-local-gen-ai/rag/RAG-with-Llama-2-on-Studio.ipynb并选择PyTorch 2.0.0 Python 3.10 GPU Optimized图像、Python 3内核和ml.g5.2xlarge作为实例类型。如果这是您第一次使用SageMaker Studio笔记本,请参考创建或打开Amazon SageMaker Studio笔记本

使用Amazon SageMaker Studio与Llama 2、LangChain和Pinecone来构建一个RAG问答解决方案,以便进行快速实验 四海 第4张

要设置开发环境,您需要安装必要的Python库,如下面的代码所示:

%%writefile requirements.txtsagemaker>=2.175.0transformers==4.33.0accelerate==0.21.0datasets==2.13.0langchain==0.0.297pypdf>=3.16.3pinecone-clientsentence_transformerssafetensors>=0.3.3

!pip install -U -r requirements.txt

加载预训练模型和分词器

在导入所需的库之后,您可以加载Hugging Face上Llama-2 7b chat模型以及其对应的分词器。这些加载好的模型文件存储在SageMaker Studio的本地目录中。这使您能够在需要在其他时间继续工作时快速重新加载它们到内存中。

import torchfrom transformers import ( AutoTokenizer,  LlamaTokenizer, LlamaForCausalLM,   GenerationConfig,   AutoModelForCausalLM)import transformerstg_model_id = "meta-llama/Llama-2-7b-chat-hf" #the model id in Hugging Facetg_model_path = f"./tg_model/{tg_model_id}" #the local directory where the model will be savedtg_model = AutoModelForCausalLM.from_pretrained(tg_model_id, token=hf_access_token,do_sample=True, use_safetensors=True, device_map="auto", torch_dtype=torch.float16tg_tokenizer = AutoTokenizer.from_pretrained(tg_model_id, token=hf_access_token)tg_model.save_pretrained(save_directory=tg_model_path, from_pt=True)tg_tokenizer.save_pretrained(save_directory=tg_model_path, from_pt=True)

提问需要最新信息

您现在可以开始使用模型并提问了。Llama-2聊天模型期望提示符遵循以下格式:

<s>[INST] <<SYS>>系统提示符<<SYS>>{{ 用户消息 }} [/INST]

您可以使用LangChain的PromptTemplate根据提示格式创建一个基于配方的模板,以便以后可以轻松创建提示:

从langchain导入PromptTemplate
template = """<s>[INST] <<SYS>>\n您是一个问题回答任务的助手。您乐于助人友好。使用下面的检索上下文片段来回答查询。如果您不知道答案,只需说我不知道即可。最多使用三句话,回答简洁明了。<<SYS>>\n{context}\n{question} [/INST]"""
prompt_template = PromptTemplate(template=template, input_variables=['context','question'])

让我们向模型提一个需要2023年最新信息的问题。您可以使用LangChain和特别是LLMChain类型的链,将LLM、之前创建的提示模板和问题作为参数传递:

question = "我什么时候能够参观 AWS M&E 客户体验中心在纽约市?"
tg_tokenizer.add_special_tokens({"pad_token": "[PAD]"})
tg_tokenizer.padding_side = "left"
tg_pipe = transformers.pipeline(task='text-generation', model=tg_model, tokenizer=tg_tokenizer, num_return_sequences=1, eos_token_id=tg_tokenizer.eos_token_id, pad_token_id=tg_tokenizer.eos_token_id, max_new_tokens=400, temperature=0.7)
from langchain.chains import LLMChain
from langchain.llms import HuggingFacePipeline
llm=HuggingFacePipeline(pipeline=tg_pipe, model_kwargs={'temperature':0.7})
llm_chain = LLMChain(llm=llm, prompt=prompt_template)
no_context_response = llm_chain.predict(context="", question=question)
print(no_context_response)

我们得到以下生成的答案:

谢谢您的咨询!由于COVID-19大流行,AWS M&E客户体验中心在纽约市目前不开放参观。但是,您可以查看他们的官方网站或社交媒体账号,以获取关于中心何时重新开放的任何更新。同时,您可以探索他们提供的虚拟游览和在线资源。

通过给提示增加上下文来改进答案

我们生成的答案并不完全正确。让我们看看是否可以通过提供一些上下文来改进它。您可以从文章AWS在纽约市推出新的M&E客户体验中心中摘录一段内容,其中包含2023年的主题更新:

context = """媒体和娱乐(M&E)客户在努力为全球观众提供更多内容、更快分发到更多终端时,面临着越来越多的挑战。多年来,亚马逊网络服务(AWS)与AWS合作伙伴一起,在像全国广播协会(NAB)展览会和国际广播大会(IBC)这样的行业活动中展示了M&E解决方案的快速发展。直到现在,AWS在M&E技术演示方面的可访问性仅在一年中的几个星期内。现在,客户比以往任何时候都更加参与,他们希望就用户体验和媒体工具进行更高质量的交流。这些对话最好通过具有相互连接的解决方案架构进行支持。从11月13日开始,可以安排参观M&E客户体验中心,请发送电子邮件至AWS-MediaEnt-CXC@amazon.com。"""

再次使用LLMChain,并将上述文本作为上下文传递:

context_response = llm_chain.predict(context=context, question=question)
print(context_response)

新的回答以最新的信息回答了这个问题:

您可以从11月13日开始参观位于纽约市的AWS M&E客户体验中心。请发送电子邮件至AWS-MediaEnt-CXC@amazon.com以安排参观。

我们已确认通过添加正确的上下文,模型的性能得到了改善。现在您可以将精力集中于找到并添加问题所需的正确上下文。换句话说,实施RAG。

使用BGE嵌入和Pinecone实施RAG问答

在这个时刻,您必须决定用于增强模型知识的信息来源。这些来源可以是您组织内部的网页或文档,也可以是公开可用的数据来源。为了本文的目的和简单起见,我们选择了两篇2023年发布的AWS博客文章:

这些文章已经作为PDF文档在SageMaker Studio的数据项目目录中,以便快速访问。为了将文档分割为可管理的块,您可以使用LangChain的RecursiveCharacterTextSplitter方法:

from langchain.text_splitter import RecursiveCharacterTextSplitterfrom langchain.document_loaders import PyPDFDirectoryLoaderloader = PyPDFDirectoryLoader("./data/")documents = loader.load()text_splitter = RecursiveCharacterTextSplitter(     chunk_size=1000,     chunk_overlap=5)docs = text_splitter.split_documents(documents)

接下来,使用由北京人工智能学院(BAAI)创建的BGE嵌入模型bge-small-en,该模型可以在Hugging Face上获得,用于生成这些块的嵌入。下载并保存模型到本地目录中。我们使用fp32以便可以在实例的CPU上运行。

em_model_name = "BAAI/bge-small-en"em_model_path = f"./em-model"from transformers import AutoModel# 从HuggingFace Hub加载模型em_model = AutoModel.from_pretrained(em_model_name,torch_dtype=torch.float32)em_tokenizer = AutoTokenizer.from_pretrained(em_model_name,device="cuda")# 将模型保存到磁盘em_tokenizer.save_pretrained(save_directory=f"{em_model_path}/model",from_pt=True)em_model.save_pretrained(save_directory=f"{em_model_path}/model",from_pt=True)em_model.eval()

使用以下代码创建一个embedding_generator函数,该函数以文档块作为输入,并使用BGE模型生成嵌入:

# 标记化句子def tokenize_text(_input, device):    return em_tokenizer(        [_input],         padding=True,         truncation=True,         return_tensors='pt'    ).to(device)# 作为函数运行嵌入任务,输入为模型和文本句子def embedding_generator(_input, normalize=True):    # 计算token嵌入    with torch.no_grad():        embedded_output = em_model(            **tokenize_text(                _input,                 em_model.device            )        )        sentence_embeddings = embedded_output[0][:, 0]        # 归一化嵌入        if normalize:            sentence_embeddings = torch.nn.functional.normalize(                sentence_embeddings,                 p=2,                 dim=1            )        return sentence_embeddings[0, :].tolist()    sample_sentence_embedding = embedding_generator(docs[0].page_content)print(f"文档的嵌入大小 --->", len(sample_sentence_embedding))

在本文中,我们使用Pinecone演示了一个RAG工作流程,Pinecone是一个托管的原生云向量数据库,还提供了一个API用于相似度搜索。您可以自由重写以下代码以使用您喜欢的向量数据库。

我们初始化一个Pinecone Python客户端并使用嵌入模型的输出长度创建一个新的向量搜索索引。我们使用LangChain内置的Pinecone类摄取之前步骤中创建的嵌入。它需要三个参数:要摄取的文档、嵌入生成函数和Pinecone索引的名称。

import pineconepinecone.init(    api_key = os.environ["PINECONE_API_KEY"],    environment = os.environ["PINECONE_ENV"])#检查索引是否已经存在,如果不存在则创建index_name = "rag-index"if index_name not in pinecone.list_indexes():    pinecone.create_index(        name=index_name,        dimension=len(sample_sentence_embedding),  ## 对于bge-small-en为384         metric='cosine'    )#插入嵌入from langchain.vectorstores import Pineconevector_store = Pinecone.from_documents(    docs,    embedding_generator,    index_name=index_name)

将Llama-2 7B聊天模型加载到内存中,并将嵌入集成到Pinecone索引中,您现在可以将这些元素组合起来,以增强Llama 2对我们的问答用例的响应。为了实现这一点,您可以使用LangChain的检索QA,它使用向量存储从最相似的文档中增强初始提示。通过设置return_source_documents=True,您可以查看用于生成答案作为响应的确切文档,以验证答案的准确性。

from langchain.chains import RetrievalQAimport textwrap#改进响应可读性的辅助方法def print_response(llm_response):    temp = [textwrap.fill(line, width=100) for line in llm_response['result'].split('\n')]    response = '\n'.join(temp)    print(f"{llm_response['query']}\n \n{response}'\n \n Source Documents:")    for source in llm_response["source_documents"]:        print(source.metadata)llm_qa_chain = RetrievalQA.from_chain_type(    llm=llm, #Llama-2 7B聊天模型    chain_type='stuff',    retriever=vector_store.as_retriever(search_kwargs={"k": 2}), #在Pinecone中执行相似性搜索    return_source_documents=True, #显示用于回答问题的文档    chain_type_kwargs={"prompt": prompt_template})print_response(llm_qa_chain(question))

我们得到以下回答:

Q: 我什么时候可以参观纽约AWS M&E客户体验中心?

A: 我很乐意帮助!根据背景,纽约AWS M&E客户体验中心将于11月13日开始接受访问。您可以发送电子邮件至AWS-MediaEnt-CXC@amazon.com安排参观。

源文档:

{‘page’: 4.0, ‘source’: ‘data/AWS announces new M&E Customer Experience Center in New York City _ AWS for M&E Blog.pdf’}

{‘page’: 2.0, ‘source’: ‘data/AWS announces new M&E Customer Experience Center in New York City _ AWS for M&E Blog.pdf’}

让我们尝试一个不同的问题:

question2=" AWS Media Services在2023年赢得了多少个奖项?"print_response(llm_qa_chain(question2))

我们得到以下回答:

Q: AWS Media Services在2023年赢得了多少个奖项?

A: 根据博客文章,AWS Media Services在2023年赢得了五个行业奖项。

源文档:

{‘page’: 0.0, ‘source’: ‘data/AWS Media Services awarded industry accolades _ AWS for M&E Blog.pdf’}

{‘page’: 1.0, ‘source’: ‘data/AWS Media Services awarded industry accolades _ AWS for M&E Blog.pdf’}

在建立足够的信心之后,您可以将模型部署到SageMaker端点进行实时推理。这些端点是全面托管的,并支持自动缩放。

SageMaker提供了使用Large Model Inference容器(简称LMIs)进行大型模型推理的功能,我们可以利用它们来部署我们的模型。这些容器预装了诸如DeepSpeed之类的开源库,可以在推理期间实施诸如张量并行等性能增强技术。此外,它们还使用DJLServing作为预构建的综合模型服务器。DJLServing是一种高性能的通用模型服务解决方案,支持动态批处理和工作器自动扩展,从而提高吞吐量。

在我们的方法中,我们使用SageMaker LMI与DJLServing和DeepSpeed Inference将Llama-2-chat 7b和BGE模型部署到在ml.g5.2xlarge实例上运行的SageMaker端点,实现实时推理。如果您想自行按照这些步骤操作,请参考附带的笔记本提供的详细说明。

您需要两个ml.g5.2xlarge实例进行部署。要查看或增加配额,请打开AWS服务配额控制台,在导航窗格中选择AWS服务,选择Amazon SageMaker,并参考用于端点使用的ml.g5.2xlarge的值。

使用Amazon SageMaker Studio与Llama 2、LangChain和Pinecone来构建一个RAG问答解决方案,以便进行快速实验 四海 第5张

以下步骤概述了在SageMaker端点上部署RAG工作流程的自定义模型的过程:

  • 将Llama-2 7b聊天模型部署到运行在ml.g5.2xlarge实例上的SageMaker实时端点,以实现快速文本生成。
  • 将BAAI/bge-small-en-v1.5嵌入模型部署到运行在ml.g5.2xlarge实例上的SageMaker实时端点。或者,您可以部署自己的嵌入模型。
  • 提出一个问题,并使用LangChain RetrievalQA从Pinecone中获取与提示最相似的文档,这次使用在SageMaker实时端点中部署的模型:
# 将本地LLM转换为SageMaker端点LLMllm_sm_ep = SagemakerEndpoint(    endpoint_name=tg_sm_model.endpoint_name,    region_name=region,    model_kwargs={        "temperature": 0.05,         "max_new_tokens": 512    },    content_handler=content_handler,)llm_qa_smep_chain = RetrievalQA.from_chain_type(    llm=llm_sm_ep,    chain_type='stuff',    retriever=vector_store.as_retriever(search_kwargs={"k": 2}),    return_source_documents=True,    chain_type_kwargs={"prompt": prompt_template})
  • 使用LangChain验证嵌入模型的SageMaker端点是否按预期工作,以便将来进行文档导入:
response_model = smr_client.invoke_endpoint(    EndpointName=em_sm_model.endpoint_name,    Body=json.dumps({        "text": "这是一段示例文本"    }),    ContentType="application/json",)outputs = json.loads(response_model["Body"].read().decode("utf8"))['outputs']

清理

完成以下步骤以清理资源:

  • 当您在SageMaker Studio笔记本中完成工作后,确保通过选择停止图标关闭ml.g5.2xlarge实例,以避免任何费用。您还可以设置生命周期配置脚本,在资源不使用时自动关闭它们。

使用Amazon SageMaker Studio与Llama 2、LangChain和Pinecone来构建一个RAG问答解决方案,以便进行快速实验 四海 第6张

  • 如果您将模型部署到SageMaker终端节点,请在笔记本的最后运行以下代码以删除终端节点:
#删除您的文本生成终端节点
m_client.delete_endpoint(EndpointName=tg_sm_model.endpoint_name)
#删除您的文本嵌入终端节点
m_client.delete_endpoint(EndpointName=em_sm_model.endpoint_name)
  • 最后,运行以下行以删除Pinecone索引:
pinecone.delete_index(index_name)

结论

SageMaker笔记本提供了一种简单的方式,帮助您开始使用检索增强生成技术的旅程。它们允许您与各种模型、配置和问题进行交互式实验,而无需额外启动基础架构。在本文中,我们展示了如何使用LangChain、BGE嵌入模型和Pinecone来改进Llama 2 7b chat在问答场景中的性能。要开始,请启动SageMaker Studio并运行以下位于GitHub仓库notebook。请在评论区分享您的想法!

Leave a Reply

Your email address will not be published. Required fields are marked *