LLM之RAG实战(一):使用Mistral-7b, LangChain, ChromaDB搭建自己的WEB聊天界面

一、RAG介绍

      如何使用没有被LLM训练过的数据来提高LLM性能?检索增强生成(RAG)是未来的发展方向,下面将解释一下它的含义和实际工作原理。

​       假设您有自己的数据集,例如来自公司的文本文档。如何让ChatGPT和其他LLM了解它并回答问题?

        这可以通过四个步骤轻松完成:

  1. Embedding:使用embedding模型对文档进行embedding操作,比如OpenAI的text-Embedding-ada-002或S-BERT(https://arxiv.org/abs/1908.10084)。将文档的句子或单词块转换为数字向量。就向量之间的距离而言,彼此相似的句子应该很近,而不同的句子应该离得更远;

  2. Vector Store:embedding文档之后就可以把它们存储在矢量存储中,比如ChromaDB、FAISS或Pinecone。矢量存储就像一个数据库,但顾名思义,它对矢量嵌入进行索引和存储,以实现快速检索和相似性搜索;

  3. Query:既然你的文档已经嵌入并存储,当你向LLM提出特定问题时,它会embedding你的查询,并在向量存储中找到余弦相似度最接近你问题的句子;

  4. Answering Your Question:一旦找到最接近的句子,它们就会被注入到Prompt中,就这样!LLM现在可以在没有经过任何再训练或微调的情况下回答有关数据的特定问题!

整体的架构,如下图所示:

PS:有关RAG的更多信息,请查看IBM高级研究科学家Marina Danilevsky的这段来自IBM的精彩视频,地址是:https://www.youtube.com/watch?v=T-D1OfcDW1M。

二、安装python环境以及相关的包

!pip install gradio --quiet!pip install xformer --quiet!pip install chromadb --quiet!pip install langchain --quiet!pip install accelerate --quiet!pip install transformers --quiet!pip install bitsandbytes --quiet!pip install unstructured --quiet!pip install sentence-transformers --quiet

三、导入相关包

import torchimport gradio as grfrom textwrap import fillfrom IPython.display import Markdown, displayfrom langchain.prompts.chat import (    ChatPromptTemplate,    HumanMessagePromptTemplate,    SystemMessagePromptTemplate,    )from langchain import PromptTemplatefrom langchain import HuggingFacePipelinefrom langchain.vectorstores import Chromafrom langchain.schema import AIMessage, HumanMessagefrom langchain.memory import ConversationBufferMemoryfrom langchain.embeddings import HuggingFaceEmbeddingsfrom langchain.text_splitter import RecursiveCharacterTextSplitterfrom langchain.document_loaders import UnstructuredMarkdownLoader, UnstructuredURLLoaderfrom langchain.chains import LLMChain, SimpleSequentialChain, RetrievalQA, ConversationalRetrievalChainfrom transformers import BitsAndBytesConfig, AutoModelForCausalLM, AutoTokenizer, GenerationConfig, pipelineimport warningswarnings.filterwarnings('ignore')

四、Mistral-7b模型介绍

       Mistral-7B是由Mistral AI开源的,在多个benchmark上超过LLaMA2,如下图所示:

      下面将使用Mistral AI开发的基础LLM Mistral-7b建立了一个文本生成Pipeline,对其进行量化、分词和生成参数进行配置:

  • quantiation_config=BitsAndBytesConfig(…):这里,使用BitsAndBytesConfig定义量化配置。量化是一种用于降低深度学习模型的内存和计算需求的技术,通常通过使用更少的比特(在我们的情况下为4比特)来表示模型参数;
  • tokenizer=AutoTokenizer.from_pretrained(…):这一行初始化Mistral-7b模型的tokenizer,允许您预处理输入到模型的文本数据;
  • model=AutoModelForCausalLM.from_pretrained(…):这初始化了用于因果语言建模的预训练语言Mistral-7b模型。该模型配置有各种参数,包括先前设置的量化配置;
  • generation_config=GenerationConfig.from_pretrained(…):为模型创建一个生成配置,指定各种与生成相关的设置,如令牌的最大数量、采样温度、top-p采样和重复惩罚;
  • pipeline=pipeline(…):最后,使用pipeline函数创建一个文本生成管道。这个管道是为文本生成而设置的,它将预先训练的模型、标记器和生成配置作为输入。它被配置为返回全文输出。
MODEL_NAME = "mistralai/Mistral-7B-Instruct-v0.1"quantization_config = BitsAndBytesConfig(    load_in_4bit=True,    bnb_4bit_compute_dtype=torch.float16,    bnb_4bit_quant_type="nf4",    bnb_4bit_use_double_quant=True,)tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, use_fast=True)tokenizer.pad_token = tokenizer.eos_tokenmodel = AutoModelForCausalLM.from_pretrained(    MODEL_NAME, torch_dtype=torch.float16,    trust_remote_code=True,    device_map="auto",    quantization_config=quantization_config)generation_config = GenerationConfig.from_pretrained(MODEL_NAME)generation_config.max_new_tokens = 1024generation_config.temperature = 0.0001generation_config.top_p = 0.95generation_config.do_sample = Truegeneration_config.repetition_penalty = 1.15pipeline = pipeline(    "text-generation",    model=model,    tokenizer=tokenizer,    return_full_text=True,    generation_config=generation_config,)

      HuggingFacePipeline是一个允许您在本地运行Hugging Face模型的类,它用于访问和利用Hugging Face Model Hub上托管的各种预先训练的ML模型。在我们的案例中,我们将在LangChain环境中使用它作为本地包装器与Hugging Face模型进行交互。然而,当使用HuggingFacePipeline时,建议安装xformer(https://github.com/facebookresearch/xformers),以实现更高效的内存注意力实现。这就是我们在上面安装它的原因!

llm = HuggingFacePipeline(    pipeline=pipeline,    )

       在将我们的基础LLM Mistral-7b连接到我们的私人数据之前。首先,让我们问一些一般性的问题。当然,它将根据在训练前获得的一般知识做出回应。

query = "Explain the difference between ChatGPT and open source LLMs in a couple of lines."result = llm(    query)display(Markdown(f"<b>{query}</b>"))display(Markdown(f"<p>{result}</p>"))

       看起来回答的不错!如果我们问它一个在预训练阶段没有遇到的问题,会发生什么?

query = "What is Hiberus GenIA Ecosystem?"result = llm(    query)display(Markdown(f"<b>{query}</b>"))display(Markdown(f"<p>{result}</p>"))

      这不是预期的答案。GenIA生态系统甚至比这更酷,这是因为Mistral-7b LLM在预训练期间从未见过任何关于GenIA生态的信息。我保证在接下来的章节中引导您获得正确答案。

五、Embedding模型

       在配置基础LLM之后,我们继续来配置embedding模型。正如您所知,每个文档都应该转换为embedding向量,以便使用用户的查询进行语义搜索,该查询也应该被embedding。为了实现这一点,我们将利用阿里巴巴大摩学院预训练并在Hugging Face上开源的embedding模型GTE(https://arxiv.org/abs/2308.03281)。值得注意的是,这个模型既免费又强大。为了完成我们的任务,我们将使用HuggingFaceEmbeddings类,这是一个本地管道包装器,用于与Hugging Face Hub上托管的GTE模型进行交互。

embeddings = HuggingFaceEmbeddings(    model_name="thenlper/gte-large",    model_kwargs={"device": "cuda"},    encode_kwargs={"normalize_embeddings": True},)

六、Prompt Template

       PromptTemplate通过结构化Prompt格式使模型按照用户期望的格式进行输出,模板可以包括指令、few-shot例子以及适合特定任务的特定上下文和问题。

template = """[INST] <>Act as a Machine Learning engineer who is teaching high school students.<>{text} [/INST]"""prompt = PromptTemplate(    input_variables=["text"],    template=template,)

我们来看一下效果:

query = "Explain what are Deep Neural Networks in 2-3 sentences"result = llm(prompt.format(text=query))display(Markdown(f"<b>{query}</b>"))display(Markdown(f"<p>{result}</p>"))

七、数据加载

数据加载流程,如下图所示:

    为了准确回答我们之前的问题(What is Hiberus GenIA Ecosystem?),我们必须将LLM与GenIA生态系统的信息联系起来。很幸运!有两个网页是理解GenIA生态系统的关键。

urls = [    "https://www.hiberus.com/expertos-ia-generativa-ld",    "https://www.hiberus.com/en/experts-generative-ai-ld"]loader = UnstructuredURLLoader(urls=urls)documents = loader.load()len(documents)# Output

       由于这两个文档数据量较大,以及超过了Mistral-7b大模型的上下文窗口大小,因此我们需要将文档按照1024个tokens大小进行切分,生成21个较小的chunks,并且为了保证上下文的连续性,chunk与chunk直接设置64个重叠tokens,代码如下:

text_splitter = RecursiveCharacterTextSplitter(chunk_size=1024, chunk_overlap=64)texts_chunks = text_splitter.split_documents(documents)len(texts_chunks)

八、数据注入

       对数据分块之后,我们将对分块数据进行embedding并存储到向量数据库Chromdb中

db = Chroma.from_documents(texts_chunks, embeddings, persist_directory="db")

       数据被添加索引之后,我们可以在Prompt模板中添加RAG模型赋予营销经理专家的角色!

       此外,为了将LLM与矢量数据库检索功能相结合,我们使用了关键的链接组件RetrievalQA,其中k=2。这种设置确保检索器输出两个相关的块,然后LLM在提出问题时使用这两个块来制定答案。

template = """[INST] <>Act as an Hiberus marketing manager expert. Use the following information to answer the question at the end.<>{context}{question} [/INST]"""prompt = PromptTemplate(template=template, input_variables=["context", "question"])qa_chain = RetrievalQA.from_chain_type(    llm=llm,    chain_type="stuff",    retriever=db.as_retriever(search_kwargs={"k": 2}),    return_source_documents=True,    chain_type_kwargs={"prompt": prompt},)

九、查询

执行完上述步骤,我们就可以进行查询了。

例子一:

query = "What is GenAI Ecosystem?"result_ = qa_chain(    query)result = result_["result"].strip()display(Markdown(f"<b>{query}</b>"))display(Markdown(f"<p>{result}</p>"))

例子二:

query = "Why Hiberus has created GenAI Ecosystem?"result_ = qa_chain(    query)result = result_["result"].strip()display(Markdown(f"<b>{query}</b>"))display(Markdown(f"<p>{result}</p>"))

      这两个问题的答案都符合预期,包括我们之前错过的那个问题。我们还可以输出LLM生成答案的源文档或参考文档。

result_["source_documents"]

十、问答

       为了实现问答功能,我们首先对Prompt模板进行一些调整。然后,我们使用ConversationBufferMemory将对话存储在内存中,然后稍后检索消息。最后,使用链接组件ConversationalRetrievalChain将我们的LLM Mistral-7b与矢量数据库和聊天历史相结合。问答系统整体架构,如下图所示:

custom_template = """You are an Hiberus Marketing Manager AI Assistant. Given thefollowing conversation and a follow up question, rephrase the follow up questionto be a standalone question. At the end of standalone question add this'Answer the question in English language.' If you do not know the answer reply with 'I am sorry, I dont have enough information'.Chat History:{chat_history}Follow Up Input: {question}Standalone question:"""CUSTOM_QUESTION_PROMPT = PromptTemplate.from_template(custom_template)memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)qa_chain = ConversationalRetrievalChain.from_llm(    llm=llm,    retriever=db.as_retriever(search_kwargs={"k": 2}),    memory=memory,    condense_question_prompt=CUSTOM_QUESTION_PROMPT,)

我们来测试一下问答功能:

query = "Who you are?"result_ = qa_chain({"question": query})result = result_["answer"].strip()display(Markdown(f"<b>{query}</b>"))display(Markdown(f"<p>{result}</p>"))

query = "What is GenIA Ecosystem?"result_ = qa_chain({"question": query})result = result_["answer"].strip()display(Markdown(f"<b>{query}</b>"))display(Markdown(f"<p>{result}</p>"))

      我们可以通过查看HumanMessages中的问题和AIMessages中的模型响应来获取聊天的历史记录。

memory.chat_memory.messages

十一、基于Gradio搭建问答UI界面

       我之前写过一篇一键部署Huggingface模型工具Gradio介绍过Gradio的具体使用,Gradio具有用户友好的网络界面,任何人都可以从任何地方访问!它的工作原理如下:我们设置了一个名为querying()的函数,它将查询作为主要输入,并使用一个名为history的名称巧妙的假参数来解决一个小问题。当你启动这个函数时,它会返回我们的超级明星模型Mistral-7b生成的响应。

def querying(query, history):  memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)  qa_chain = ConversationalRetrievalChain.from_llm(      llm=llm,      retriever=db.as_retriever(search_kwargs={"k": 2}),      memory=memory,      condense_question_prompt=CUSTOM_QUESTION_PROMPT,  )  result = qa_chain({"question": query})  return result["answer"].strip()

启动Gradio聊天界面

iface = gr.ChatInterface(    fn = querying,    chatbot=gr.Chatbot(height=600),    textbox=gr.Textbox(placeholder="What is GenAI Ecosystem?", container=False, scale=7),    title="HiberusBot",    theme="soft",    examples=["Why Hiberus has created GenAI Ecosystem?",              "What is GenAI Ecosystem?"],    cache_examples=True,    retry_btn="Repetir",    undo_btn="Deshacer",    clear_btn="Borrar",    submit_btn="Enviar"    )iface.launch(share=True)

最终展示的聊天界面,如下图所示:

参考文献:

[1] https://medium.com/@zekaouinoureddine/ask-your-web-pages-using-mistral-7b-langchain-f976e1e151ca

[2] https://arxiv.org/abs/2005.11401

[3] https://arxiv.org/abs/2310.06825

[4] https://arxiv.org/abs/2308.03281

[5] https://www.youtube.com/watch?v=PuU_qf23u_8

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/209491.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ZPLPrinter Emulator SDK for .NET 6.0.23.1123​ Crack

ZPLPrinter Emulator SDK for .NET 适用于 .NET 的 ZPLPrinter 仿真器 SDK 允许您通过编写 C# 或VB.NET 代码针对任何 .NET Framework、.NET CORE、旧版 ASP.NET MVC 和 CORE、Xamarin、Mono 和通用 Windows 平台 (UWP) 作业。 适用于 .NET 的 ZPLPrinter 仿真器 SDK 允许您将…

matplotlib与opencv图像读取与显示的问题

个人博客:Sekyoro的博客小屋 个人网站:Proanimer的个人网站 最近在用opencv和matplotlib展示图片,但是遇到了一些问题,这里展开说说 首先需要明确的是,opencv和matplotlib读取图片都是通道在最后,而前者默认可见光图像是BGR,后者是RGB.此外还有PIL以及imageio等读取图像的工具…

(学习笔记)Xposed模块编写(一)

前提&#xff1a;需要已经安装Xposed Installer 1. 新建一个AS项目 并把MainActvity和activity_main.xml这两个文件删掉&#xff0c;然后在AndriodManifest.xml中去掉这个Activity的声明 2. 在settings.gralde文件中加上阿里云的仓库地址&#xff0c;否则Xposed依赖无法下载 m…

9款热门API接口分享,值得收藏!

电商API接口 干货分享 开始 “ API是什么&#xff1f; API的主要目的是提供应用程序与开发人员以访问一组例程的能力&#xff0c;而又无需访问源码&#xff0c;或理解内部工作机制的细节。提供API所定义的功能的软件称作此API的实现。API是一种接口&#xff0c;故而是一种抽象…

Banana Pi最新的路由器板BPI-R4上市销售,基于MediaTek MT7988A

Banana Pi 发布了一款新的路由器板 Banana Pi BPI-R4&#xff0c;基于配备四核 Arm CPU 的 MediaTek MT7988A SoC。该板不仅仅是Raspberry Pi 的另一个替代品&#xff0c;而且是用于家庭网络和自动化的设备。 Banana Pi BPI-R4 的外形尺寸比单板计算机更像网络设备。对于那些希…

Python函数的基本使用(一)

Python函数的基本使用&#xff08;一&#xff09; 一、函数概述二、函数的定义2.1 函数的语法2.2 语法说明2.3 函数定义的方式2.4 总结 三、函数的调用3.1 函数调用语法3.2 语法说明3.3 函数调用 四、函数的参数4.1 参数的分类4.2 必需参数4.3 默认值参数4.4 关键字参数4.5 不定…

风变科技千万营收的AIGC项目,在Fanbook成功落地,专访风变科技CMO江育麟

在AIGC时代&#xff0c;创作生产力被下放到了每一位普通人身上&#xff0c;然后用户与AIGC应用之间还存在一定的认知与技术沟壑。 最近&#xff0c;【AIGC开放社区】注意到一款AIGC课程项目受到了相当的关注&#xff0c;让许多0基础的学员轻松地学会了使用AIGC技术的基本方法。…

风控交易系统跟单系统资管软件都有哪些功能特点?

资管分仓软件的主要功能就是母账户可以添加子账号&#xff0c;并且设置出入金&#xff0c;手续费、保证金、风控等功能&#xff0c;同时监控端更可以直观的看子账户的交易情况直接折线图展示更加直观&#xff0c;在监控端的最高权限可以直接一键平仓子账户&#xff08;如果子账…

基于jsp的搜索引擎

摘 要 随着互联网的不断发展和日益普及&#xff0c;网上的信息量在迅速地增长&#xff0c;在2004年4月&#xff0c;全球Web页面的数目已经超过40亿&#xff0c;中国的网页数估计也超过了3亿。 目前人们从网上获得信息的主要工具是浏览器&#xff0c;搜索引擎在网络中占有举足轻…

23种设计模式之C++实践(二)

23种设计模式之C++实践 3. 设计模式(二)组合型模式7. 适配器模式——不兼容结构的协调7.2:类适配器模式7.3:双向适配器模式适配器模式总结8.桥接模式——处理多维度变化桥接模式总结9. 组合模式——树形结构的处理9.2 透明组合模式9.3 安全组合模式组合模式总结10. 装饰模式…

【海思SS528 | VDEC】MPP媒体处理软件V5.0 | 视频解码模块——学习笔记

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

HR看好的字符函数和字符串处理函数!!!

本篇会加入个人的所谓‘鱼式疯言’❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言,而是理解过并总结出来通俗易懂的大白话,我会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的&#xff0c;可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念 前言 在本篇…

智能监控平台/视频共享融合系统EasyCVR接入RTSP协议视频流无法播放原因是什么?

视频集中存储/云存储/视频监控管理平台EasyCVR能在复杂的网络环境中&#xff0c;将分散的各类视频资源进行统一汇聚、整合、集中管理&#xff0c;实现视频资源的鉴权管理、按需调阅、全网分发、智能分析等。AI智能/大数据视频分析EasyCVR平台已经广泛应用在工地、工厂、园区、楼…

深入理解Go语言GC机制

1、Go 1.3之前的标记-清除&#xff08;mark and sweep&#xff09;算法 Go 1.3之前的时候主要用的是普通的标记-清除算法&#xff0c;此算法主要由两个主要的步骤&#xff1a; 标记&#xff08;Mark phase&#xff09;清除&#xff08;Sweep phase&#xff09; 1&#xff09…

Spring Boot整合RabbitMQ

一、简介 在Spring项目中&#xff0c;可以使用Spring-Rabbit去操作RabbitMQ 尤其是在spring boot项目中只需要引入对应的amqp启动器依赖即可&#xff0c;方便的使用RabbitTemplate发送消息&#xff0c;使用注解接收消息。 一般在开发过程中&#xff1a; 生产者工程&#xf…

文心一言 VS 讯飞星火 VS chatgpt (148)-- 算法导论12.2 3题

三、用go语言&#xff0c;写出过程 TREE-PREDECESSOR 的伪代码。 文心一言&#xff1a; 以下是使用Go语言编写的TREE-PREDECESSOR函数的伪代码&#xff1a; func TREE-PREDECESSOR(node) { if node.parent ! nil { return node.parent } // 如果节点是根节点&#xff0c…

TDA4VM EVM开发板调试笔记

文章目录 1. 前言2. 官网资料导读3. 安装 Linux SDK4. 制作SD 启动卡5. 验证启动1. 前言 TDA4作为一般经典的车规级SOC芯片,基于它的低阶智驾方案目前成为各家智驾方案公司的量产首选,这也使得基于TDA4的开发需求陡增,开发和使用TDA4既要熟悉Linux驱应用开发,还要熟悉传统…

「计算机网络」Cisco Packet Tracker计算机网络仿真器的使用

介绍 Cisco Packet Tracker&#xff1a;网络仿真工具&#xff0c;用于模拟网络配置。 &#xff08;一&#xff09; 配置交换机&#xff08;Switch&#xff09;&#xff08;通过 带外管理&#xff09; 带外&#xff1a;Out-of-Band, OOB写在前面&#xff1a;如何打开Console页…

数据结构与算法-动态查找表

查找 &#x1f388;3动态查找表&#x1f52d;3.1二叉排序树&#x1f3c6;3.1.1二叉排序树的类定义&#x1f3c6;3.1.2二叉排序树的插入和生成&#x1f3c6;3.1.3二叉树的查找&#x1f3c6;3.1.4二叉排序树的删除 &#x1f52d;3.2平衡二叉树&#x1f3c6;3.2.1平衡二叉树的调整…

YOLOv8 区域计数 | 入侵检测 | 人员闯入

大家好,昨天的 YOLOv8 新增加了一个功能,区域计数,用这个功能我们能实现很多的任务, 比如入侵检测,流量统计,人员闯入等,使用方式也非常的方便,但是一定要使用最新版的 YOLOv8 代码(2023/12/03更新的代码)。 低版本是不具备这个功能的,上面是演示效果。 使用非常的方…