贴心小梗概

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

环境准备

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

1.开发环境搭建

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

📌手动配置

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

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

python -m venv lazyllm-venv
source 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 lazyllm
lazyllm install standard

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

pip3 install lazyllm
lazyllm 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_Chinese
    retriever = Retriever(doc, group_name=Document.CoarseChunk, similarity="bm25_chinese", topk=3)
    # 调用retriever组件,传入query
    retriever_result = retriever("your query")      
    # 打印结果,用get_content()方法打印具体的内容
    print(retriever_result[0].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_dataset
    dataset = 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 = 10total_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_threadsafety
    print(sqlite3_check_threadsafety())

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

      brew update
      brew install sqlite
      which sqlite3

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

      brew uninstall python
      export 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)"' >> ~/.zshrc
      source ~/.zshrc
      brew install pyenv
      pyenv install 3.10.0

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

      echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
      echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
      echo 'eval "$(pyenv init --path)"' >> ~/.zshrc
      echo 'eval "$(pyenv init -)"' >> ~/.zshrc
      pyenv global 3.10.0
      python3 -m venv lazyllm
      source 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!

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

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

      相关文章

      android9-PMS-常见问题及分析步骤

      以下是基于 Android 9 的 Package Manager Service (PMS) 常见问题及分析步骤&#xff0c;结合系统原理与优化实践整理&#xff1a; &#x1f527; 一、开机性能问题 现象 开机时间随应用增多显著延长&#xff0c;卡在“正在启动应用”阶段。 分析步骤 ① 确认扫描阶段耗时adb…

      生成模型实战 | GLOW详解与实现

      生成模型实战 | GLOW详解与实现0. 前言1. 归一化流模型1.1 归一化流与变换公式1.2 RealNVP 的通道翻转2. GLOW 架构2.1 ActNorm2.2 可逆 11 卷积2.3 仿射耦合层2.4 多尺度架构3. 使用 PyTorch 实现 GLOW3.1 数据处理3.2 模型构建3.3 模型训练0. 前言 GLOW (Generative Flow) 是…

      行业案例:杰和科技为智慧教育构建数字化硬件底座

      清晨8点10分&#xff0c;深圳某学生踏入校园&#xff0c;智慧门闸识别身份&#xff0c;并同步发给家长&#xff1b;走廊里的“智慧班牌”向他们展示今日的课表&#xff1b;课堂上&#xff0c;教室前方的多媒体播放器里&#xff0c;老师引导学生学习“居民楼消防隐患”知识&…

      Redis与MySQL数据同步:从“双写一致性”到实战方案

      Redis与MySQL数据同步&#xff1a;从“双写一致性”到实战方案 在分布式系统中&#xff0c;Redis作为高性能缓存被广泛使用——它能将热点数据从MySQL中“搬运”到内存&#xff0c;大幅降低数据库压力、提升接口响应速度。但随之而来的核心问题是&#xff1a;当MySQL数据更新时…

      Java源码构建智能名片小程序

      在移动互联网时代&#xff0c;纸质名片的局限性日益凸显——信息更新不便、客户管理困难、营销效果难以追踪。智能电子名片小程序以其便捷、高效、智能的特点&#xff0c;正成为商务人士的"数字营销门户"。而基于Java技术栈开发的智能名片系统&#xff0c;凭借其稳定…

      如何在短时间内显著提升3D效果图渲染速度?

      在建筑设计、游戏开发、影视制作等行业&#xff0c;3D效果图的渲染速度是项目进度与效率的关键瓶颈。面对复杂场景时&#xff0c;漫长的渲染等待尤为突出。要在保证质量的前提下大幅缩短渲染时间&#xff0c;以下优化策略至关重要&#xff1a; 1. 升级硬件配置&#xff1a;渲染…

      配置daemon.json使得 Docker 容器能够使用服务器GPU【验证成功】

      &#x1f947; 版权: 本文由【墨理学AI】原创首发、各位读者大大、敬请查阅、感谢三连 文章目录&#x1f50d;你遇到的错误&#xff1a;&#x1f50d; 根本原因✅ 解决方案&#xff1a;正确安装 NVIDIA Container Toolkit✅ 第一步&#xff1a;卸载旧版本&#xff08;如果存在&…

      Linux 系统进程管理与计划任务详解

      Linux 系统进程管理与计划任务详解 一、程序与进程的基本概念 程序&#xff1a;保存在外部存储介质中的可执行机器代码和数据的静态集合。进程&#xff1a;在CPU及内存中处于动态执行状态的计算机程序。关系&#xff1a;每个程序启动后&#xff0c;可创建一个或多个进程。 二、…

      【图像处理】直方图均衡化c++实现

      直方图均衡化是一种通过调整图像像素灰度值分布&#xff0c;来增强图像对比度的经典数字图像处理技术。其核心在于将原始图像的灰度直方图从集中的某个区间“拉伸”或“均衡”到更广泛的区间&#xff0c;让图像的明暗细节更清晰&#xff0c;关键在于利用累积分布函数实现灰度值…

      Web前端实战:Vue工程化+ElementPlus

      1.Vue工程化 1.1介绍 模块化&#xff1a;将js和css等&#xff0c;做成一个个可复用模块组件化&#xff1a;我们将UI组件&#xff0c;css样式&#xff0c;js行为封装成一个个的组件&#xff0c;便于管理规范化&#xff1a;我们提供一套标准的规范的目录接口和编码规范&#xff0…

      ECMAScript2021(ES12)新特性

      概述 ECMAScript2021于2021年6月正式发布&#xff0c; 本文会介绍ECMAScript2021(ES12)&#xff0c;即ECMAScript的第12个版本的新特性。 以下摘自官网&#xff1a;ecma-262 ECMAScript 2021, the 12th edition, introduced the replaceAll method for Strings; Promise.any,…

      Tlias 案例-整体布局(前端)

      开发流程前端开发和后端开发是一样的&#xff0c;都需要阅读接口文档。 准备工作&#xff1a; 1&#xff1a;导入项目中准备的基础过程到 VsCode。2&#xff1a;启动前端项目&#xff0c;访问该项目3&#xff1a;熟悉一下基本的布局<script setup></script><tem…

      三十二、【Linux网站服务器】搭建httpd服务器演示虚拟主机配置、网页重定向功能

      httpd服务器功能演示一、虚拟主机配置虚拟主机技术全景虚拟主机目录规范1. 基于端口的虚拟主机&#xff08;8080/8081&#xff09;2. 基于IP的虚拟主机&#xff08;192.168.1.100/192.168.1.101&#xff09;3. 基于域名的虚拟主机&#xff08;site1.com/site2.com&#xff09;二…

      串行化:MYSQL事务隔离级别中的终极防护

      在现代应用程序中&#xff0c;数据的一致性和可靠性至关重要。想象一下&#xff0c;如果在一个银行系统中&#xff0c;两个用户同时试图转账到同一个账户&#xff0c;最终的数据结果可能会出乎意料。为了避免这种情况&#xff0c;MYSQL提供了不同的事务隔离级别&#xff0c;其中…

      RAG:检索增强生成的范式演进、技术突破与前沿挑战

      1 核心定义与原始论文 RAG&#xff08;Retrieval-Augmented Generation&#xff09;由Facebook AI Research团队于2020年提出&#xff0c;核心思想是将参数化记忆&#xff08;预训练语言模型&#xff09;与非参数化记忆&#xff08;外部知识库检索&#xff09;结合&#xff0c…

      2024年蓝桥杯Scratch10月图形化stema选拔赛真题——旋转的图形

      旋转的图形编程实现旋转的图形。具体要求1&#xff09;点击绿旗&#xff0c;在舞台上出现滑杆形式的变量 r&#xff0c;取值范围为-1、0、1&#xff0c;默认值为 0&#xff0c;如图所示&#xff1b;2&#xff09;1秒后&#xff0c;在舞台上绘制出一个红色正方形&#xff08;边长…

      【音视频】WebRTC 开发环境搭建-Web端

      一、开发环境搭建 1.1 安装vscode 下载VSCode&#xff1a;https://code.visualstudio.com/&#xff0c;下载后主要用于开发Web前端页面&#xff0c;编写前端代码 安装完成后下载Live Server插件&#xff0c;用于本地开发&#xff0c;实时加载前端页面 1.1.1 前端代码测试 下…

      力扣54:螺旋矩阵

      力扣54:螺旋矩阵题目思路代码题目 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 思路 思路很简单创建一个二维数组然后按照箭头所示的顺序一层一层的给二维数组相应的位置赋值即可。难点是我们是一层一层的赋值…

      【CSS】设置表格表头固定

      1.设置thead样式在thead元素中增加样式&#xff1a;position: sticky;top: 0;2.设置table样式在table元素中增加样式&#xff1a;border-collapse: separate; /* 分离边框模式 */ border-spacing: 0;3.设置表头伪元素样式增加样式&#xff1a;th::after {content: ;position: a…

      Baumer工业相机堡盟工业相机如何通过YoloV8深度学习模型实现标签条码一维码的检测(C#代码,UI界面版)

      Baumer工业相机堡盟工业相机如何通过YoloV8深度学习模型实现标签条码一维码的检测&#xff08;C#代码&#xff0c;UI界面版&#xff09;&#xff09;工业相机使用YoloV8模型实现标签条码一维码的检测工业相机通过YoloV8模型实现标签条码的检测的技术背景在相机SDK中获取图像转换…