写点什么

LazyLLM 教程 | 第 2 讲:10 分钟上手一个最小可用 RAG 系统

  • 2025-07-31
    北京
  • 本文字数:10737 字

    阅读完需:约 35 分钟

贴心小梗概


本文将介绍使用 LazyLLM 搭建最基础的 RAG 的流程。首先介绍使用 LazyLLM 搭建 RAG 系统的必要环境配置,然后简单回顾 RAG 的基本流程,接下来分别介绍 RAG 中文档加载、检索组件、生成组件三个关键部分的参数和基本使用方法,最后利用 LazyLLM 实现最简单的 RAG,并展示相关效果。

环境准备


在使用 LazyLLM 搭建 RAG 系统之前,我们需要配置好相关的环境,包括 “开发环境搭建” 和 “环境变量配置” 两个步骤。

1. 开发环境搭建


您可以用以下任一方式搭建 LazyLLM 开发环境。


📌手动配置


LazyLLM 基于 Python 开发,我们需要保证系统中已经安装好了 Python, Pip 和 Git。在 Macbook 上安装这些比较复杂,安装方式见附录。

首先准备一个名为 lazyllm-venv 的虚拟环境并激活:


python -m venv lazyllm-venvsource lazyllm-venv/bin/activate
复制代码

如果运行正常,你可以在命令行的开头看到 (lazyllm-venv) 的提示。接下来我们的操作都在这个虚拟环境中进行。


从 GitHub 下载 LazyLLM 的代码:


git clone https://github.com/LazyAGI/LazyLLM.git
复制代码


并切换到下载后的代码目录:


cd LazyLLM
复制代码


安装基础依赖:


pip3 install -r requirements.txt
复制代码


把 LazyLLM 加入到模块搜索路径中:

export PYTHONPATH=$PWD:$PYTHONPATH
复制代码


这样我们在任意目录下都可以找到它。


📌拉取镜像


我们提供了包含最新版本的 LazyLLM 的 docker 镜像,开箱即用:


docker pull lazyllm/lazyllm
复制代码

也可以从 https://hub.docker.com/r/lazyllm/lazyllm/tags 查看并拉取需要的版本。


📌从 Pip 安装


LazyLLM 支持用 pip 直接安装,下面三种安装方式分别对应不同功能的使用。

安装 LazyLLM 基础功能的最小依赖包。可以支持线上各类模型的微调和推理。


pip3 install lazyllm
复制代码


安装 LazyLLM 的所有功能最小依赖包。不仅支持线上模型的微调和推理,而且支持离线模型的微调(主要依赖 LLaMA-Factory)和推理(大模型主要依赖 vLLM,多模态模型依赖 LMDeploy,Embedding 模型依赖 Infinity)。


pip3 install lazyllmlazyllm install standard
复制代码


安装 LazyLLM 的所有依赖包,所有功能以及高级功能都支持,比如自动框架选择(AutoFinetune、AutoDeploy 等)、更多的离线推理工具(如增加 LightLLM 等工具)、更多的离线训练工具(如增加 AlpacaloraFinetune、CollieFinetune 等工具)。


pip3 install lazyllmlazyllm install full
复制代码

2.API Key 配置

 

调用大模型主要分为线上调用和本地调用两种方式。对于线上调用,您需要提供相应平台的 API Key。如果您还没有对应平台的账号,首先需要在平台上注册一个账号。LazyLLM 框架提供了自动调用平台 API Key 的功能,只需将您的 API Key 设置为环境变量,并在调用时指定平台和模型名称,即可实现线上模型的调用。


LazyLLM 目前支持以下平台(api key 链接见附件):



要配置平台的 API Key 为环境变量,请按照以下步骤操作:

1️⃣根据您使用的平台,获取相应的 API Key(注意:SenseNova 平台需要获取两个 Key)。

2️⃣使用以下命令设置对应的环境变量:


export LAZYLLM_<使用的平台环境变量名称,大写>_API_KEY=<申请到的api key>
复制代码


例如,如果您需要访问 SenseNova 平台,如果您通过方法一获得密钥,您需要设置以下环境变量:


export LAZYLLM_SENSENOVA_API_KEY="您的Access Key ID"export LAZYLLM_SENSENOVA_SECRET_KEY="您的Access Key Secret"
复制代码


如果您通过方法二获得密钥,您需要设置以下环境变量:


export LAZYLLM_SENSENOVA_API_KEY="您的API-Key"
复制代码


在配置好环境变量后,当您实例化 OnelineChatModule 并指定模型来源时,LazyLLM 会自动根据配置的环境变量调用相应的 API Key。


通过这种方式,您可以轻松管理和调用不同平台的 API Key,简化了模型调用的流程。

RAG 实践剖析

1. 原理回顾


在准备好 LazyLLM 的环境和配置后,让我们快速回顾一下 RAG(Retrieval-augmented Generation,RAG,检索增强生成)的基本原理。RAG 的工作原理是当模型需要生成文本或回答问题时,首先会从一个庞大的文档集合中检索出相关的信息,这些检索到的信息随后会被用于指导生成过程,从而显著提高生成文本的质量和准确性。RAG 的整体结构可以用下图标识,系统接收一个用户 Query, 首先通过检索器(Retriever)从外部文档中检索出与给定 Query 相似的内容,然后将其与 Query 一同输入到 LLM ,LLM 给出最终答案:



RAG 的离线工作流程可以归纳成以下三步:

1️⃣文档读取和解析(Reader)

把各种格式的文档加载到系统中,可以借助开源工具 (如 MinerU) 来提高解析的准确率。

2️⃣分块和向量化(Transform and Vectorize)

对收集到的原始数据进行清洗、去重、分块等预处理工作,然后进行向量化。

3️⃣索引和存储(Indexing and Store)

利用向量数据库或其他高效的向量检索工具,将处理后的文本数据进行高效的存储和索引。



小结:

RAG 的工作流程可以归纳成以下三步:

1️⃣检索(Retrieval)

用户输入问题后,系统会基于该输入在知识库中检索相关内容。

2️⃣增强(Augmented)

检索到的文本内容会作为额外的上下文,与用户输入一起提供给大模型。

3️⃣生成(Generatation)

大模型结合检索到的信息和自身的预训练知识,生成最终的回答。

接下来我们将按照顺序,依次介绍 LazyLLM 中的文档管理、检索组件和生成组件。

2. 文档管理


RAG 的核心是从文档集合进行文档检索,文档集合中可以有各种各样的文档格式:可以是 DOCX,PDF,PPT 等富文本或者 Markdown 这样的纯文本,也可能是从某个 API 获取的内容(如通过搜索引擎检索得到的相关信息)等等。


由于集合内的文档格式各异,针对这些不同格式的文档,我们需要特定的解析器来提取其中有用的文本、图片、表格、音频和视频等内容。在 LazyLLM 中,这些用于提取特定内容的解析器被抽象为 Document 类,目前 LazyLLM 内置的 Document 可以支持 DOCX,PDF,PPT,EXCEL 等常见的富文本内容提取,您也可以自定义 Reader 读取特定格式的文档(在后续的教程中我们会进行详细介绍)。Document 的主要参数如下:


Parameters:

  • dataset_path (str) – 数据集目录的路径。此目录应包含要由文档模块管理的文档(注意:暂不支持指定单个文件)。

  • embed (Optional [Union [Callable, Dict [str, Callable]]], default: None ) – 用于生成文档 embedding 的对象。如果需要对文本生成多个 embedding,此处需要通过字典的方式指定多个 embedding 模型,key 标识 embedding 对应的名字,value 为对应的 embedding 模型。

  • manager (bool, default: False) – 指示是否为文档模块创建用户界面的标志。默认为 False。

  • launcher (optional, default: None) – 负责启动服务器模块的对象或函数。如果未提供,则使用 lazyllm.launchers 中的默认异步启动器 (sync=False)。

  • store_conf (optional, default: None) – 配置使用哪种存储后端和索引后端。

  • doc_fields (optional, default: None) – 配置需要存储和检索的字段继对应的类型(目前只有 Milvus 后端会用到)。


在此处我们仅介绍 Document 最基础的使用方法,embed、manager 等参数的使用,我们将在后续章节进行介绍。对于最基础的使用,我们只需要传入数据集目录的路径即可:


(代码 GitHub 链接:

https://github.com/LazyAGI/Tutorial/blob/7abc91dbb82a007a78731845dd8c360ac0cc1e75/rag/codes/chapter2/%E5%AE%9E%E6%88%981%EF%BC%9A%E6%9C%80%E5%9F%BA%E7%A1%80%E7%9A%84RAG.py#L19


# RAG 文档读取from lazyllm import Document# 传入绝对路径doc = Document("path/to/content/docs/")print(f"实际传入路径为:{}")# 传入相对路径doc = Document("/content/docs/")
复制代码


注意,您需要在此处传入绝对路径,或者是以当前目录为基础的相对路径,其他情况下需要您通过环境变量 LAZYLLM_DATA_PATH 指定您的文档所在目录再传入相对路径,效果如下图所示:




上述代码中我们通过 doc._manager._dataset_path 来访问最终传给 doc 的路径,可以看到上述两种方式的输出完全相同。

3. 检索组件


文档集合中的文档不一定都和用户要查询的内容相关,因此需要通过检索组件从文档中筛选出和用户查询相关的文档。LazyLLM 中执行检索功能的是 Retriever 组件, Retriever 组件可以创建一个用于文档查询和检索的检索模块。此构造函数初始化一个检索模块,该模块根据指定的相似度度量配置文档检索过程。主要参数如下:


Parameters:

  • doc (object) – 文档模块实例。该文档模块可以是单个实例,也可以是一个实例的列表。如果是单个实例,表示对单个 Document 进行检索,如果是实例的列表,则表示对多个 Document 进行检索。

  • group_name (str) – 在哪个 node group 上进行检索。

group_name 有三种内置切分策略,都是用 SentenceSplitter 切分,区别在于块大小不同:

◦ CoarseChunk: 块大小为 1024,重合长度为 100◦ MediumChunk: 块大小为 256,重合长度为 25◦ FineChunk: 块大小为 128,重合长度为 12

  • similarity (Optional [str], default: None ) – 用于设置文档检索的相似度函数。默认为 'dummy'。候选集包括 ["bm25", "bm25_chinese", "cosine"]。

  • similarity_cut_off (Union [float, Dict [str, float]], default: float ('-inf') ) – 当相似度低于指定值时丢弃该文档。在多 embedding 场景下,如果需要对不同的 embedding 指定不同的值,则需要使用字典的方式指定,key 表示指定的是哪个 embedding,value 表示相应的阈值。如果所有的 embedding 使用同一个阈值,则只指定一个数值即可。

  • index (str, default: 'default') – 用于文档检索的索引类型。目前仅支持 'default'。

  • topk (int, default: 6) – 表示取相似度最高的多少篇文档。

  • embed_keys (Optional [List [str]], default: None ) – 表示通过哪些 embedding 做检索,不指定表示用全部 embedding 进行检索。

  • target:目标组名,将结果转换到目标组。

  • output_format: 代表输出格式,默认为 None,可选值有 'content' 和 'dict',其中 content 对应输出格式为字符串,dict 对应字典。

  • join: 是否联合输出的 k 个节点,当输出格式为 content 时,如果设置该值为 True,则输出一个长字符串,如果设置为 False 则输出一个字符串列表,其中每个字符串对应每个节点的文本内容。当输出格式是 dict 时,不能联合输出,此时 join 默认为 False, 将输出一个字典,包括 'content、'embedding'、'metadata' 三个 key。

  • kwargs: 其他关键字参数。


下面这行代码声明检索组件需要在 doc 这个文档中的 Coarse chunk 节点组利用 bm25_chinese 相似度进行检索,最终返回相似度最高的 3 个节点。此处只简单介绍如何使用 Retriever 组件,相关算法原理及更多检索组件相关细节我们将在后续章节介绍。


(代码 GitHub 链接:

https://github.com/LazyAGI/Tutorial/blob/7abc91dbb82a007a78731845dd8c360ac0cc1e75/rag/codes/chapter2/%E5%AE%9E%E6%88%981%EF%BC%9A%E6%9C%80%E5%9F%BA%E7%A1%80%E7%9A%84RAG.py#L28


from lazyllm import Retriever# 传入绝对路径doc = Document("/path/to/content/docs/")# 使用Retriever组件,传入文档doc,节点组名称这里采用内置切分策略"CoarseChunk",相似度计算函数bm25_Chineseretriever = Retriever(doc, group_name=Document.CoarseChunk, similarity="bm25_chinese", topk=3)# 调用retriever组件,传入queryretriever_result = retriever("your query")      # 打印结果,用get_content()方法打印具体的内容print(retriever_result[0].get_content())
复制代码


在上面的代码中,我们 retriever_result 是一个 list,里面每个元素是一个 node(具体细节我们将在进阶 1 中介绍),我们调用 get_content () 方法可以打印具体的内容。

4. 生成组件


有了检索到的内容,结合我们提问的问题,将二者共同输入给生成组件,即可得我们想要的答案。这里的生成组件就是大模型,接下来我们将以线上大模型为例说明 lazyllm 是如何调用大模型的。

LazyLLM 通过 OnlineChatModule 统一调用线上大模型接口,不管您使用的 OpenAPI 接口还是 SenseNova 接口,或者是其他平台提供的接口,LazyLLM 均为您进行了规范的参数封装,您只需要根据自己的需求将平台和模型名称等参数传给对应的模块即可:


(代码 GitHub 链接:

https://github.com/LazyAGI/Tutorial/blob/7abc91dbb82a007a78731845dd8c360ac0cc1e75/rag/codes/chapter2/%E5%AE%9E%E6%88%981%EF%BC%9A%E6%9C%80%E5%9F%BA%E7%A1%80%E7%9A%84RAG.py#L42

​​​​​​​

llm_prompt = "你是一只小猫,每次回答完问题都要加上喵喵喵"llm = lazyllm.OnlineChatModule(source="sensenova", model="SenseChat-5-1202").prompt(llm_prompt)print(llm("早上好!"))# >>> 早上好呀!太阳公公出来啦~(伸个懒腰)要一起在窗台晒太阳吗?今天的早餐小鱼干分你一半喵~(蹭蹭你) 喵喵喵~
复制代码


仅用上述三行代码,就可以调用大模型。首先我们定义了一个 prompt,作为大模型的提示词,后续大模型的输出都会遵循这里给出的提示。


然后我们定义了要调用的大模型,通过 OnlineChatModule 传入平台 source 以及模型名称 model,通过.prompt 传入定义好的 prompt。


最后,调用定义好的大模型 llm,输入我们的问题就可以和大模型实现对话啦!

当然,您还可以将上述第 4 行代码替换成以下代码来实现一个对话窗口:


lazyllm.WebModule(llm, port=23466, history=[llm]).start().wait()
复制代码


这里我们通过 lazyllm.WebModule 启动了一个网页端,将地址和端口输入到浏览器就可以得到一个简单的对话系统啦~



RAG 知识库构建


RAG 在 LazyLLM 中的基本组件我们已经介绍完成了,下面我就可以用这几部分关键组件搭建完整的 RAG 工作流了。但是在此之前,我们首先需要选择一些文档作为 RAG 的语料库,下面我们将从 cmrc2018(https://huggingface.co/datasets/hfl/cmrc2018)原始数据集开始,为大家讲解如何基于此数据集构建我们的 RAG 知识库。在接下来的教程中,我们将介绍 RAG 改进和优化的各种方法,若无特殊说明,将始终使用此知识库。

1. 数据集简介


CMRC 2018(Chinese Machine Reading Comprehension 2018)[1] 数据集是一个中文阅读理解数据集,用于中文机器阅读理解的跨度提取数据集,以增加该领域的语言多样性。数据集由人类专家在维基百科段落上注释的近 20,000 个真实问题组成。

旨在推动中文机器阅读理解(MRC)任务的发展。其数据集的基本格式如下图所示:



对于每条数据,包括 id,context,question 以及 answers 四个字段,其中 id 是当前数据的编号,context 是一段文字性描述,涉及历史、新闻、小说等各领域,answer 包括两部分,一部分是 answer_start,标志答案从哪个 context 中的 token 开始,另一部分是 text,代表了针对 question 给出的答案,此答案由人类专家给出,上图中有两个答案,代表人类专家 1 和人类专家 2 分别给出,以此来保证答案的准确性。


首先我们要将此数据集下载到本地,这里我们采用 datasets 库进行下载(如果您没有安装 datasets 库,请先利用 pip install datasets 进行安装),代码如下:


(代码 GitHub 链接:

https://github.com/LazyAGI/Tutorial/blob/7abc91dbb82a007a78731845dd8c360ac0cc1e75/rag/codes/chapter2/%E5%AE%9E%E6%88%981%EF%BC%9A%E6%9C%80%E5%9F%BA%E7%A1%80%E7%9A%84RAG.py#L54

​​​​​​​

from datasets import load_datasetdataset = load_dataset('cmrc2018')  # 加载数据集# dataset = load_dataset('cmrc2018', cache_dir='path/to/datasets') # 指定下载路径print(dataset)
复制代码


上述代码会将数据集自动下载到.cache/huggingface/datasets 目录下,如果您希望指定下载路径,可以通过 cache_dir 参数来指定。下载成功后我们将看到如下格式的输出:



里面标着了当前 datasets 中包括 train、validation 以及 test 三部分数据。

2. 构建知识库


在这里,我们仅使用 test 数据集构建 RAG 的知识库,该数据集的其他部分将在后续章节微调模型时使用(到相应章节会说明原因)。


具体构建思路如下:考虑到每条数据中有 id,context,question 以及 answers 四个字段,我们仅使用 context 部分内容作为知识库,这样在后续评测 RAG 的效果时,我们就可以选择同一条数据当中 context 对应的 question 作为 query 输入,通过比较 RAG 中检索组件根据 question 召回的结果与 RAG 中生成组件与原本的 answers,就可以对 RAG 系统的好坏做出评价。


在后续的章节中我们会进行详细的介绍,在这里我们仅作为一个铺垫。本章您只需要明白 “我们将 text 数据集中的 context 部分构建 RAG 数据库” 即可。这里我们直接给出相应的代码:


(代码 GitHub 链接:

https://github.com/LazyAGI/Tutorial/blob/7abc91dbb82a007a78731845dd8c360ac0cc1e75/rag/codes/chapter2/%E5%AE%9E%E6%88%981%EF%BC%9A%E6%9C%80%E5%9F%BA%E7%A1%80%E7%9A%84RAG.py#L59

​​​​​​​

def create_KB(dataset):    '''基于测试集中的context字段创建一个知识库,每10条数据为一个txt,最后不足10条的也为一个txt'''    Context = []    for i in dataset:        Context.append(i['context'])    Context = list(set(Context))  # 去重后获得256个语料    # 计算需要的文件数    chunk_size = 10    total_files = (len(Context) + chunk_size - 1) // chunk_size  # 向上取整    # 创建文件夹data_kb保存知识库语料    os.makedirs("data_kb", exist_ok=True)     # 按 10 条数据一组写入多个文件    for i in range(total_files):        chunk = Context[i * chunk_size : (i + 1) * chunk_size]  # 获取当前 10 条数据        file_name = f"./data_kb/part_{i+1}.txt"  # 生成文件名        with open(file_name, "w", encoding="utf-8") as f:            f.write("\n".join(chunk))  # 以换行符分隔写入文件        # print(f"文件 {file_name} 写入完成!")  # 提示当前文件已写入
复制代码


上述代码中:

  • 第 2-3 行:这部分代码循环遍历 data 中的每个字典,提取每个字典中的 context 字段的值,并将其添加到 Context 列表中。最终,Context 将包含所有的 context 数据。

  • 第 6 行:通过使用 set (),该行代码去除了 Context 中的重复项,确保每个 context 只出现一次。然后,使用 list () 将去重后的 set 转换回列表。

  • 第 9-10 行:chunk_size 设置为 10,表示每个文件将包含最多 10 条 context 数据。为了计算需要生成多少个文件,total_files 通过将 Context 列表的长度除以 chunk_size 进行计算,且使用了向上取整的技巧 (len (Context) + chunk_size - 1) //chunk_size。这确保了即使 Context 的长度不是 10 的整数倍,最后一部分数据也会被单独写入一个文件。

  • 第 15-20 行:将 Context 列表按每 10 条数据一组进行拆分,并将每组数据写入一个独立的文本文件。具体操作如下:

    👉for i in range (total_files):循环遍历需要创建的文件数量。

    👉chunk = Context [i * chunk_size : (i + 1) * chunk_size]:从 Context 中获取当前批次的 10 条数据(即每个文件包含 10 条数据)。

    👉file_name = f"./data_kb/part_{i+1}.txt":为每个文件生成一个唯一的文件名,例如 part_1.txt, part_2.txt 等。

    👉with open (file_name, "w", encoding="utf-8") as f::以写模式打开(或创建)对应的文本文件,并确保使用 UTF-8 编码。

    👉f.write ("\n".join (chunk)):将当前批次的 10 条数据通过换行符 \n 拼接起来,并写入文件。


(代码 GitHub 链接:

https://github.com/LazyAGI/Tutorial/blob/7abc91dbb82a007a78731845dd8c360ac0cc1e75/rag/codes/chapter2/%E5%AE%9E%E6%88%981%EF%BC%9A%E6%9C%80%E5%9F%BA%E7%A1%80%E7%9A%84RAG.py#L82

​​​​​​​

# 调用create_KB()创建知识库create_KB(dataset['test'])# 展示其中一个txt文件中的内容with open('data_kb/part_1.txt') as f:    print(f.read())
复制代码


上述代码执行完成后,您的当前目录下将多出一个 data_kb 文件夹,里面包括若干个 txt 文件:



文件中的内容大致如下:



🚨请注意:上述 data_kb 文件夹的路径,在后续的 RAG 系统搭建中,若无特殊说明,我们将始终以此路径下的文件作为 RAG 的知识库。

3. 环境检查


检查你环境中的数据库(sqlite)是否支持多线程:​​​​​​​


from lazyllm.common.queue import sqlite3_check_threadsafetyprint(sqlite3_check_threadsafety())
复制代码


如果结果为 False,则你需要先重装 sqlite,使之支持多线程。以 macbook 为例:​​​​​​​


brew updatebrew install sqlitewhich sqlite3
复制代码


如果结果不是 homebrew 下的 sqlite,则你需要设置如下环境变量,并重装 python:​​​​​​​


brew uninstall pythonexport PATH="/opt/homebrew/opt/sqlite/bin:$PATH"export LDFLAGS="-L/opt/homebrew/opt/sqlite/lib"export CPPFLAGS="-I/opt/homebrew/opt/sqlite/include”brew install python
复制代码

实现基础的 RAG


我们已经介绍了 LazyLLM 中最常用的三个 RAG 组件,准备好了知识库,接下来就让我们实现最简单的 RAG 吧!


下面我们再来简单回顾下上文提到的 RAG 核心组件 Document,Retriever,大模型:

  • Document 组件:负责文档加载与管理,使用时只需指定文档地址即可实现加载和存储文档。

  • Retriever 组件:负责实现 RAG 系统的检索功能,使用时需要指定在哪个文档库进行检索,以何种方式进行检索以及返回多少条检索结果等。

  • 大模型(LLM):负责根据检索到的文档进行答复,简单情况下只需输入用户查询和检索组件检索到的文档即可。LazyLLM 提供了 TrainableModule 和 OnlineChatModule 分别支持本地模型和在线模型的统一调用,用户无需关注内部细节,可以自由切换不同模型。


将这三个组件的使用串联在一起,我们就得到了最简单的 RAG,代码如下:


(代码 GitHub 链接:

https://github.com/LazyAGI/Tutorial/blob/7abc91dbb82a007a78731845dd8c360ac0cc1e75/rag/codes/chapter2/%E5%AE%9E%E6%88%981%EF%BC%9A%E6%9C%80%E5%9F%BA%E7%A1%80%E7%9A%84RAG.py#L89

​​​​​​​

import lazyllm# 文档加载documents = lazyllm.Document(dataset_path="/content/docs")# 检索组件定义retriever = lazyllm.Retriever(doc=documents, group_name="CoarseChunk", similarity="bm25_chinese", topk=3) # 生成组件定义llm = lazyllm.OnlineChatModule(source="sensenova", model="SenseChat-5-1202")# prompt 设计prompt = 'You will act as an AI question-answering assistant and complete a dialogue task. In this task, you need to provide your answers based on the given context and questions.'llm.prompt(lazyllm.ChatPrompter(instruction=prompt, extra_keys=['context_str']))# 推理query = "为我介绍下玉山箭竹"    # 将Retriever组件召回的节点全部存储到列表doc_node_list中doc_node_list = retriever(query=query)# 将query和召回节点中的内容组成dict,作为大模型的输入res = llm({"query": query, "context_str": "".join([node.get_content() for node in doc_node_list])})print(f'With RAG Answer: {res}')
复制代码

 

上述代码思路梳理:

1️⃣我们首先按照上面的介绍分别定义了文档加载组件 document(第 4 行代码)、检索组件 retriever(第 7 行代码)以及生成组件(第 10 行代码)。

2️⃣然后设计了大模型的 prompt(第 13 行代码),所谓 prompt,就是指对大模型扮演角色 / 要执行任务的一个事先指定,然后我们通过 llm.prompt 方法将 prompt 和下文的附加信息 "context_str" 传给大模型)。里面使用了内置的 ChatPrompter 方法,其具体含义为:

  • ChatPrompter:负责提示词模板化,RAG 需要大模型基于提供的文档回答相应问题,因此在输入大模型时需要告诉大模型哪些是参考资料,哪个是问题。除此之外,在线模型往往需要将提示词按照规定的格式传给在线服务,ChatPrompter 可以帮助用户实现这个过程,而无需用户自行转换。

3️⃣接下来我们输入自己的 query(17 行),并调用 retriever 的得到检索结果(19 行)存储在列表 doc_mode_list 中。

4️⃣最后我们调用大模型 llm(21 行),这里传入了一个字典,字典包括两部分,一部分是我们提出的问题 query,另一部分是参考信息即 retriever 检索到的结果 content_str,这里我们从 doc_mode_list 取出各个检索节点,并通过.get_content 方法和 "".join 方法拼接为一个完整的内容。

 

我们对比一下在没有使用 RAG 直接调用大模型的情况下的结果:​​​​​​​

# 生成组件定义llm_without_rag = lazyllm.OnlineChatModule(source="sensenova", model="SenseChat-5-1202")query = "为我介绍下玉山箭竹"res = llm_without_rag(query)print(f'Without RAG Answer: {res}')
复制代码

 

参考文献:

[1] A Span-Extraction Dataset for Chinese Machine Reading Comprehension

附录

mac 安装 Python, Pip 和 Git

1. 先安装 xcode:



并且接受许可协议,然后安装 xcode 的命令行工具:​​​​​​​

sudo xcode-select -s /Applications/Xcode.app/Contents/Developer  # 确保路径正确sudo xcodebuild -license accept  # 接受许可证协议xcode-select --install  # 安装 Xcode 命令行工具
复制代码

2. 安装 homebrew,并并通过 homebrew 安装 python 和 pip:​​​​​​​

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zshrcsource ~/.zshrcbrew install pyenvpyenv install 3.10.0
复制代码

3. 安装 python3.10。注意不能安装 python3.13,因为我们依赖的 spacy 包不支持 python3.13:​​​​​​​

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrcecho 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrcecho 'eval "$(pyenv init --path)"' >> ~/.zshrcecho 'eval "$(pyenv init -)"' >> ~/.zshrcpyenv global 3.10.0python3 -m venv lazyllmsource lazyllm/bin/activate
复制代码


api key 链接


  • 日日新:

方法 1:https://console.sensecore.cn/help/docs/model-as-a-service/nova/

方法 2:https://console.sensecore.cn/aistudio/management/api-key

  • OpenAI:

https://platform.openai.com/api-keys

  • 智谱 AI:

https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys

  • Kimi:

https://platform.moonshot.cn/console/api-keys

  • 通义千问:

https://help.aliyun.com/zh/model-studio/obtain-api-key-app-id-and-workspace-id

  • 豆包:

https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey??apikey=%7B%7D

 

更多技术交流,欢迎移步 “LazyLLM” gzh!

发布于: 2025-07-31阅读数: 2
用户头像

用AI大模型,找商汤大装置。 2023-04-04 加入

还未添加个人简介

评论

发布
暂无评论
LazyLLM 教程 | 第 2 讲:10 分钟上手一个最小可用 RAG 系统_商汤万象开发者_InfoQ写作社区