RAG 入门指南:从零开始构建一个 RAG 体系

打印 上一主题 下一主题

主题 1724|帖子 1724|积分 5172


本文正笔墨数约 3300 字,阅读时间 10 分钟。
从零开始构建一个应用可以让我们快速理解应用的各个部门。
这个方法实在非常适用于 RAG。
我在以前的文章中有介绍过 RAG 的概念、原理以及应用等,但实在,亲身动手来构建一个 RAG 体系大概能够让我们更快速的理解 RAG 到底是什么。
本文将为读者提供一个从零开始搭建一个 RAG 应用的入门教程。
RAG 简介

在开始之前,我还是打算再次扼要的介绍一下 RAG。
在 Meta 的官方 Blog 上有如许一段话:
   Building a model that researches and contextualizes is more challenging, but it’s essential for future advancements. We recently made substantial progress in this realm with our Retrieval Augmented Generation (RAG) architecture, an end-to-end differentiable model that combines an information retrieval component (Facebook AI’s dense-passage retrieval system) with a seq2seq generator (our Bidirectional and Auto-Regressive Transformers BART model). RAG can be fine-tuned on knowledge-intensive downstream tasks to achieve state-of-the-art results compared with even the largest pretrained seq2seq language models. And unlike these pretrained models, RAG’s internal knowledge can be easily altered or even supplemented on the fly, enabling researchers and engineers to control what RAG knows and doesn’t know without wasting time or compute power retraining the entire model.
  这段话重要讲述了一个新的模子架构,也就是 RAG (检索增强生成) 的紧张性和上风。可以概括为以下几点:

  • 1. 构建一个能够举行研究和上下文分析的模子虽然更具挑衅性,但对未来的技术进步非常关键;
  • 2. 通过在知识密集的卑鄙任务上微调,RAG 可以实现最先辈的结果,比现有的最大的预训练序列到序列语言模子还要好;
  • 3. 与传统的预训练模子不同,RAG 的内部知识可以轻松地震态更改或增补。也就是说,研究人员和工程师可以控制 RAG 知道和不知道的内容,而不需要浪费时间或盘算资源重新训练整个模子。
这段话信息量很大,但是作为初学者,简而言之:
RAG 的本质是在传递给 LLM 的提示语中,通过一个检索工具来添加自己的数据。
接下来,我们就要开始预备我们的 RAG 应用了。
RAG 体系的高层组件



  • • 一组文档,正式说法为语料库
  • • 用户输入
  • • 语料库和用户输入之间的相似性度量
这是简化版的 RAG 组件体系,我们不需要考虑向量存储,甚至现在还不需要 LLM。
以下是一篇 RAG 论文中的体系概述:

它假设了很多背景信息,比我们预设的简化版要复杂的多。
对于想要深入研究的人来说,这篇论文很有代价,但是对于我们想要入门的人来说,通过一步一步构建自己的 RAG 体系来学习才更得当。
RAG 体系的查询步骤



    • 查询用户输入


    • 举行相似性度量


    • 对用户输入和检索到的文档举行后处置惩罚

这里的后处置惩罚即将检索到的文档和用户输入发送给 LLM 举行处置惩罚,终极生成回答。
   相似性度量是指用来评估两个对象之间相似水平的方法。在文本处置惩罚和信息检索中,相似性度量可以资助我们确定两个文本之间的相似度。在 RAG 体系中,我们可以使用这些相似性度量方法之一来比较用户输入和文档集合中的每个文档,从而找到最相关的文档。
  从零开始构建 RAG 体系

现在,我们将以一个具体的案例从零开始来构建一个 RAG 体系。
以下是简化版的流程图。

以下是具体步骤。
获取文档集合

我们起首定义一个简单的文档语料库。
  1. corpus_of_documents = [       "Take a leisurely walk in the park and enjoy the fresh air.",       "Visit a local museum and discover something new.",       "Attend a live music concert and feel the rhythm.",       "Go for a hike and admire the natural scenery.",       "Have a picnic with friends and share some laughs.",       "Explore a new cuisine by dining at an ethnic restaurant.",       "Take a yoga class and stretch your body and mind.",       "Join a local sports league and enjoy some friendly competition.",       "Attend a workshop or lecture on a topic you're interested in.",       "Visit an amusement park and ride the roller coasters."   ]
复制代码
定义和实行相似性度量

现在我们需要一种方法来权衡我们将要吸收的用户输入与我们组织的文档集合之间的相似性。
可以说,最简单的相似性度量是杰卡德相似性。
   杰卡德相似性(Jaccard Similarity)是一种权衡两个集合相似水平的简单方法。它盘算两个集合的交集和并集的比例,用于比较两个文本之间的相似性。简而言之就是,杰卡德相似性看两个集合中共同元素的数目占所有元素的总数目的比例。
  对语料库举行预处置惩罚

由于我们需要举行相似性度量,所以需要将字符串处置惩罚成集合。
我们可以使用最简单的方式来举行预处置惩罚,也就是将字符串转换为小写并按照空格分割。
  1. # 将语料库字符串按照空格分割,并返回杰卡德相似性的结果   def jaccard_similarity(query, document):       query = query.lower().split(" ")       document = document.lower().split(" ")       intersection = set(query).intersection(set(document))       union = set(query).union(set(document))       return len(intersection)/len(union)
复制代码
然后,我们需要定义一个函数,该函数接受用户的准确查询和我们的语料库,并根据相似性的结果将最匹配的文档返回给用户。
  1. def return_response(query, corpus):       similarities = []       for doc in corpus:           similarity = jaccard_similarity(user_input, doc)           similarities.append(similarity)       return corpus_of_documents[similarities.index(max(similarities))]
复制代码
现在,我们可以试着运行一下。
定义用户查询输入。
  1. user_input = "I like to hike"
复制代码
将输出的结果打印出来。
print(return_response(user_input, corpus_of_documents))

   假如不想在自己电脑上设置 Python 情况,可以直接使用线上的 Python 编辑器,比如:https://www.programiz.com/python-programming/online-compiler/
  至此,我们已经构建出了一个最基本的 RAG 体系。
相似性题目

由于我们选择了一个非常简单的相似性度量方法来学习,所以会带来一些题目。
它没有语义概念,只是简单地看两个文档中有哪些词,然后举行对比。
也就是说,只要我们提供的用户输入里包含这些词,那么我们就会得到雷同的结果,因为那就是最接近的文档。
比如,我将用户输入换成了 user_input = "I don't like to hike"。

输出结果和上文的输出结果一样。
这是一个在 RAG 中会经常遇到的话题,我们会在背面解决这个题目。
现在,我们还没有对我们检索到的文档举行任何后处置惩罚。只是实现了 RAG 的「检索」功能。
下一步是通过结合 LLM 来增强生成。
添加 LLM

要方便快捷的添加 LLM,我们可以直接在本地机器上运行一个开源的 LLM。
这里,我将使用 Ollama 的 Llama 3.1 模子。固然,你也可以使用 OpenAI 的 GPT-4 或 Anthropic 的 Claude 或者其他 LLM。
   可以到 ollama 官网下载安装自己想要的 LLM:https://ollama.com/
  现在,我们需要对代码做些修改了。
   假如是在本地运行 LLM,那么,你需要在自己电脑上设置好 Python 相关的情况,如许在后续步骤中,才能将代码运行起来。
  现在,需要引入一些库。
  1. import requests   import json
复制代码
我们的步骤会有所变化:

  • 1. 获取用户输入;
  • 2. 获取最相似的文档(通过我们的相似性度量来权衡);
  • 3. 将这个文档作为提示语传递给 LLM;
  • 4. 末了将结果返回给用户。
  1. user_input = "I like to hike"
  2.    relevant_document = return_response(user_input, corpus_of_documents)   full_response = []      prompt = """   You are a bot that makes recommendations for activities. You answer in very short sentences and do not include extra information.   This is the recommended activity: {relevant_document}   The user input is: {user_input}   Compile a recommendation to the user based on the recommended activity and the user input.   """
复制代码
定义好以上步骤之后,我们现在来调用 Ollama 的 API。
在编辑此代码之前,你需要先运行 LLM 在后台,直接在下令行里输入 ollama serve 即可。
  1. url = 'http://localhost:11434/api/generate'   data = {       "model": "llama3.1",       "prompt": prompt.format(user_input=user_input, relevant_document=relevant_document)   }   headers = {'Content-Type': 'application/json'}   response = requests.post(url, data=json.dumps(data), headers=headers, stream=True)   try:       count = 0       for line in response.iter_lines():           if line:               decoded_line = json.loads(line.decode('utf-8'))                              full_response.append(decoded_line['response'])   finally:       response.close()      print(''.join(full_response))
复制代码
运行以上代码,即可看到结果。

现在我们已经从零开始构建了一个完整的 RAG 体系。
现在 LLM 就可以直接帮我们处置惩罚上文提到的相似性题目。假如把用户输入改成 I don't like to hike.,那么我们会得到以下如许的回答。

总结以及改进点

尽管我们已经搭建出了一个完整的 RAG 体系,但是,真实场景下的 RAG 体系也许会更加复杂,涉及向量数据库(Vector Database)、嵌入(Embedding)和提示语工程(Prompt Engineering)等。
假如想要更加深入的学习 RAG,你也许需要在此基础之上考虑以下的一些改进点。


    • 文档数目:更多的文档可能意味着更多的推荐,现在,我们只给 LLM 提供一个文档。我们可以输入多个文档作为“上下文”,让模子根据用户输入提供更个性化的推荐。


    • 文档的深度/大小:更高质量的内容和包含更多信息的长文档可能更好。


    • 提供给 LLM 的文档部门:假如我们有更大或更全面的文档,我们可能只想添加这些文档的部门内容,或者多个文档的部门内容,或一些变体。在词汇中,这称为分块(chunking)。


    • 文档存储工具:我们可能会以不同的方式或不同的数据库存储文档。特别是假如我们有大量文档,可能会考虑将它们存储在向量存储中。


    • 相似性度量:我们怎样权衡相似性是至关紧张的,我们可能需要在性能和全面性之间权衡。


    • 文档和用户输入的预处置惩罚:我们可以在将用户输入传递给相似性度量之前举行一些额外的预处置惩罚或增强。例如,我们可以使用嵌入将输入转换为向量。


    • 提示语:我们可以对 LLM/模子使用不同的提示语,并根据我们想要的输出举行调解,以获得我们想要的结果。

   你可以在我的 GitHub 上获取到本文所有代码:https://github.com/Erichain/ai-application-demos/blob/main/create-rag-from-scratch.py
  
怎样体系的去学习大模子LLM ?

作为一名热心肠的互联网老兵,我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。
但苦于知识流传途径有限,很多互联网行业朋侪无法获得正确的资料得到学习提升,故此将并将紧张的 AI大模子资料 包括AI大模子入门学习思维导图、精品AI大模子学习书籍手册、视频教程、实战学习等录播视频免费分享出来
所有资料 ⚡️ ,朋侪们假如有需要全套 《LLM大模子入门+进阶学习资源包》,扫码获取~
   

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

水军大提督

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表