
在过去的几个星期里,我一直在玩几个大型语言模型(LLM),并利用互联网上可用的各种方法探索它们的潜力,但现在是时候分享我迄今为止学到的东西了!
我非常兴奋地知道Meta发布了下一代开源大型语言模型LLaMA 2(2023年7月18日),最有趣的部分是,他们免费向公众提供商业用途。所以,我决定试试看,看看它的表现如何。
在这篇文章中,我将分享我是如何像聊天机器人一样使用Llama-2- 7 b-chat模型和LangChain框架和FAISS库,在我从Databasericks文档网站在线获取的文档上执行Question-Answering(QA)的。
导言
LLaMA 2模型经过预训练和微调,使用2万亿令牌和7到700亿个参数,使其成为强大的开源模型之一。它有三种不同的型号(即图7B、图13B和图70B)具有比Llama 1模型显著的改进,包括在多40%的令牌上训练,具有更长的上下文长度(4k个令牌🤯),以及使用分组查询注意力来快速推断70B模型🔥。它在许多外部基准测试中优于其他开源LLM,包括推理,编码,熟练程度和知识测试。
Llama 1 vs Llama 2基准测试-资料来源:huggingface.co
LangChain是一个功能强大的开源框架,旨在帮助您开发由语言模型(特别是大型语言模型(LLM))驱动的应用程序。该库的核心思想是,我们可以将不同的组件“链接”在一起,以围绕LLM创建更高级的用例。LangChain由来自多个模块的多个组件组成。
LangChain Modules
模块:
-
提示:这个模块允许你使用模板构建动态提示。它可以适应不同的LLM类型,具体取决于上下文窗口大小和用作上下文的输入变量,例如会话历史记录,搜索结果,以前的答案等。 -
模型:这个模块提供了一个抽象层来连接到大多数可用的第三方LLM API。它有API连接到~40个公共LLM,聊天和嵌入模型。 -
内存:这使LLM可以访问会话历史。 -
索引:索引指的是构建文档的方法,以便LLM可以最好地与它们交互。此模块包含用于处理文档和集成到不同矢量数据库的实用程序函数。 -
代理:一些应用程序不仅需要对LLM或其他工具的预定调用链,而且可能需要依赖于用户输入的未知链。在这些类型的链中,有一个代理可以访问一套工具。根据用户的输入,代理可以决定调用哪个工具(如果有的话)。 -
链:对于一些简单的应用程序,单独使用LLM是可以的,但是许多更复杂的应用程序需要LLM的链接,或者是彼此之间,或者是其他专家。LangChain提供了一个标准的链接口,以及一些常见的链实现,以便于使用。
FAISS(Facebook AI Similarity Search)是一个用于高效相似性搜索和密集向量聚类的库。它可以搜索多媒体文档(例如图像),这在标准数据库引擎(SQL)中是低效或不可能的。它包含的算法可以搜索任何大小的向量集,直到可能不适合RAM的向量。它还包含用于评估和参数调优的支持代码。
FAISS索引和相似性搜索-来源:engineering.fb.com
流程
在本节中,我将简要介绍流程的各个部分。
流程图
-
初始化模型管道:为预训练的Llama-2- 7 b-chat-hf模型,使用拥抱面变换器初始化文本生成流水线。 -
摄取数据:以文本形式将来自任意源的数据加载到文档加载器中。 -
分成块:将加载的文本分割成更小的块。创建小块文本是必要的,因为语言模型可以处理有限数量的文本。 -
创建嵌入:将文本块转换成数值,也称为嵌入。这些嵌入用于在大型数据库中快速搜索和检索相似或相关的文档,因为它们代表文本的语义含义。 -
将嵌入加载到向量存储中:将嵌入加载到向量存储中,即在这种情况下,“FISS”。与传统的数据库相比,向量存储在使用文本嵌入的相似性搜索中表现非常好。 -
启用内存:将聊天记录与新问题结合起来并将其转换成单个独立问题对于能够提出后续问题非常重要。 -
查询数据:使用嵌入搜索存储在向量存储中的相关信息。 -
生成答案:将所述独立问题和所述相关信息传递到所述问答链,其中所述语言模型用于生成答案。
开始使用
你可以在Hugging Face Transformers和LangChain中使用开源Llama-2- 7 b-chat模型。但是,您必须首先通过Meta网站请求访问Llama 2模型,并同意在Hugging Face网站上与Meta分享您的帐户详细信息。通常需要几分钟或几个小时才能获得访问权限。
请注意,您的Hugging Face帐户电子邮件必须与您在Meta网站上提供的电子邮件相匹配,否则您的请求将不会被批准。
如果您使用Google Colab来运行代码。在笔记本电脑中,转到运行时>更改运行时类型>硬件加速器> GPU > GPU类型> T4。您将需要~ 8 GB的GPU RAM进行推理,在CPU上运行几乎是不可能的。
Google Colab中的笔记本资源
安装库
首先,让我们开始使用 pip install 安装所有必需的库。
!pip install -qU transformers accelerate einops langchain xformers bitsandbytes faiss-gpu sentence_transformers
初始化
您必须使用Hugging Face转换器初始化 text-generation 管道。管道要求您必须初始化以下三件事:
-
LLM,在这种情况下,它将是 meta-llama/Llama-2-7b-chat-hf -
模型的相应标记化程序。 -
停止条件对象。
您必须初始化模型并将其移动到启用CUDA的GPU。使用Colab,这可能需要5-10分钟来下载和初始化模型。
此外,您需要生成一个访问令牌,以允许在代码中从Hugging Face下载模型。为此,请转到您的Hugging Face配置文件>设置>访问令牌>新令牌>生成令牌。只需复制令牌并将其添加到下面的代码中即可。
from torch import cuda, bfloat16import transformersmodel_id = 'meta-llama/Llama-2-7b-chat-hf'device = f'cuda:{cuda.current_device()}' if cuda.is_available() else 'cpu'bnb_config = transformers.BitsAndBytesConfig( load_in_4bit=True, bnb_4bit_quant_type='nf4', bnb_4bit_use_double_quant=True, bnb_4bit_compute_dtype=bfloat16)hf_auth = '<add your access token here>'model_config = transformers.AutoConfig.from_pretrained( model_id, use_auth_token=hf_auth)model = transformers.AutoModelForCausalLM.from_pretrained( model_id, trust_remote_code=True, config=model_config, quantization_config=bnb_config, device_map='auto', use_auth_token=hf_auth)model.eval()print(f"Model loaded on {device}")
管道需要一个令牌化器,该令牌化器处理人类可读明文到LLM可读令牌ID的转换。Llama 2 7 B模型使用Llama 2 7 B标记器进行训练,可以使用以下代码初始化:
tokenizer = transformers.AutoTokenizer.from_pretrained( model_id, use_auth_token=hf_auth)
现在,我们需要定义模型的停止准则。停止条件允许我们指定模型何时停止生成文本。如果我们不提供一个停止准则,模型只是在回答了最初的问题后有点切线。
stop_list = ['\nHuman:', '\n```\n']stop_token_ids = [tokenizer(x)['input_ids'] for x in stop_list]stop_token_ids
您必须将这些停止令牌ID转换为 LongTensor 对象。
import torchstop_token_ids = [torch.LongTensor(x).to(device) for x in stop_token_ids]stop_token_ids
您可以进行快速抽查,确保 stop_token_ids 中没有出现 <unk> 令牌ID( 0 )-没有出现,因此我们可以继续构建停止标准对象,该对象将检查是否满足停止标准-这意味着是否生成了这些令牌ID组合。
from transformers import StoppingCriteria, StoppingCriteriaListclass StopOnTokens(StoppingCriteria): def __call__(self, input_ids: torch.LongTensor, scores: torch.FloatTensor, **kwargs) -> bool: for stop_ids in stop_token_ids: if torch.eq(input_ids[0][-len(stop_ids):], stop_ids).all(): return True return Falsestopping_criteria = StoppingCriteriaList([StopOnTokens()])
您已准备好初始化拥抱面管道。这里还有一些额外的参数我们必须定义。注释包含在代码中以供进一步解释。
generate_text = transformers.pipeline( model=model, tokenizer=tokenizer, return_full_text=True, task='text-generation', stopping_criteria=stopping_criteria, temperature=0.1, max_new_tokens=512, repetition_penalty=1.1 )
运行此代码以确认一切正常。
res = generate_text("Explain me the difference between Data Lakehouse and Data Warehouse.")print(res[0]["generated_text"])
在LangChain中实现HF流水线
现在,您必须在LangChain中实现Hugging Face管道。您仍然会得到相同的输出,因为这里没有做任何不同的事情。然而,这段代码将允许您在Llama 2中使用LangChain的高级代理工具、链等。
from langchain.llms import HuggingFacePipelinellm = HuggingFacePipeline(pipeline=generate_text)llm(prompt="Explain me the difference between Data Lakehouse and Data Warehouse.")
使用文档加载器接收数据
您必须使用 WebBaseLoader 文档加载器摄取数据,该加载器通过抓取网页来收集数据。在这种情况下,您将从Databricks文档网站收集数据。
from langchain.document_loaders import WebBaseLoaderweb_links = ["https://www.databricks.com/","https://help.databricks.com","https://databricks.com/try-databricks","https://help.databricks.com/s/","https://docs.databricks.com","https://kb.databricks.com/","http://docs.databricks.com/getting-started/index.html","http://docs.databricks.com/introduction/index.html","http://docs.databricks.com/getting-started/tutorials/index.html","http://docs.databricks.com/release-notes/index.html","http://docs.databricks.com/ingestion/index.html","http://docs.databricks.com/exploratory-data-analysis/index.html","http://docs.databricks.com/data-preparation/index.html","http://docs.databricks.com/data-sharing/index.html","http://docs.databricks.com/marketplace/index.html","http://docs.databricks.com/workspace-index.html","http://docs.databricks.com/machine-learning/index.html","http://docs.databricks.com/sql/index.html","http://docs.databricks.com/delta/index.html","http://docs.databricks.com/dev-tools/index.html","http://docs.databricks.com/integrations/index.html","http://docs.databricks.com/administration-guide/index.html","http://docs.databricks.com/security/index.html","http://docs.databricks.com/data-governance/index.html","http://docs.databricks.com/lakehouse-architecture/index.html","http://docs.databricks.com/reference/api.html","http://docs.databricks.com/resources/index.html","http://docs.databricks.com/whats-coming.html","http://docs.databricks.com/archive/index.html","http://docs.databricks.com/lakehouse/index.html","http://docs.databricks.com/getting-started/quick-start.html","http://docs.databricks.com/getting-started/etl-quick-start.html","http://docs.databricks.com/getting-started/lakehouse-e2e.html","http://docs.databricks.com/getting-started/free-training.html","http://docs.databricks.com/sql/language-manual/index.html","http://docs.databricks.com/error-messages/index.html","http://www.apache.org/","https://databricks.com/privacy-policy","https://databricks.com/terms-of-use"] loader = WebBaseLoader(web_links)documents = loader.load()
使用文本拆分器拆分成块
你必须确保把文本分成小块。您需要初始化 RecursiveCharacterTextSplitter 并通过传递文档调用它。
from langchain.text_splitter import RecursiveCharacterTextSplittertext_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=20)all_splits = text_splitter.split_documents(documents)
在矢量存储中创建嵌入和存储
你必须为每一小块文本创建嵌入,并将它们存储在向量存储中(即FAISS)。您将使用 all-mpnet-base-v2 Sentence Transformer将所有文本转换为向量,同时将它们存储在向量存储中。
from langchain.embeddings import HuggingFaceEmbeddingsfrom langchain.vectorstores import FAISSmodel_name = "sentence-transformers/all-mpnet-base-v2"model_kwargs = {"device": "cuda"}embeddings = HuggingFaceEmbeddings(model_name=model_name, model_kwargs=model_kwargs)vectorstore = FAISS.from_documents(all_splits, embeddings)
初始化链
您必须初始化 ConversationalRetrievalChain 。这个链允许你拥有一个带内存的聊天机器人,同时依靠矢量存储从你的文档中查找相关信息。
此外,您可以通过指定可选参数返回用于回答问题的源文档,即#00000在构建链时。
from langchain.chains import ConversationalRetrievalChainchain = ConversationalRetrievalChain.from_llm(llm, vectorstore.as_retriever(), return_source_documents=True)
现在,是时候对自己的数据进行一些问答了!
chat_history = []query = "What is Data lakehouse architecture in Databricks?"result = chain({"question": query, "chat_history": chat_history})print(result['answer'])
输出:
这一次,您之前的问题和答案将包括在聊天记录中,这将使您能够提出后续问题。
chat_history = [(query, result["answer"])]query = "What are Data Governance and Interoperability in it?"result = chain({"question": query, "chat_history": chat_history})print(result['answer'])
输出:
您还可以看到用于生成答案的信息的来源。
print(result['source_documents'])
输出:
终于...
瞧!您现在可以使用强大的语言模型对数据进行问答。此外,您还可以使用Streamlit将其进一步开发成聊天机器人应用程序。
来源:giphy.com
参考文献
[1]https://huggingface.co/blog/llama2
[2]https://venturebeat.com/ai/llama-2-how-to-access-and-use-metas-versatile-open-source-chatbot-right-now/
[3]https://www.pinecone.io/learn/series/langchain/langchain-intro/
[4]https://engineering.fb.com/2017/03/29/data-infrastructure/faiss-a-library-for-efficient-similarity-search/
[5]https://ai.meta.com/tools/faiss/
[6]https://blog.bytebytego.com/p/how-to-build-a-smart-chatbot-in-10
[7]https://newsletter.theaiedge.io/p/deep-dive-building-a-smart-chatbot
[8]https://www.youtube.com/watch? v= 61HVJyX2e50
[9]https://github.com/pinecone-io/examples/blob/master/learn/generation/llm-field-guide/llama-2/llama-2-70b-chat-agent.ipynb
记得关注哦,分享AIGC最前沿技术和思考

