检索增强生成(RAG)实践:基于LlamaIndex和Qwen1.5搭建智能问答系统

技术
检索增强生成(RAG)实践:基于LlamaIndex和Qwen1.5搭建智能问答系统
  • 什么是 RAG

LLM 会产生误导性的 “幻觉 ”,依赖的信息可能过时 ,处理特定知识时效率不高,缺乏专业领域 的深度洞察,同时在推理能力上也有所欠缺。

正是在这样的背景下,检索增强生成技术(Retrieval-Augmented Generation,RAG)应时而生,成为 AI 时代的一大趋势。RAG 通过在语言模型生成答案之前,先从广泛的文档数据库中检索相关信息,然后利用这些信息来引导生成过程,极大地提升了内容的准确性和相关性。RAG 有效地缓解了幻觉问题 ,提高了知识更新的速度 ,并增强了内容生成的可追溯性 ,使得大型语言模型在实际应用中变得更加实用和可信

一个典型的 RAG 的例子:

picture.image

这里面主要包括包括三个基本步骤:

  1. 索引 — 将文档库分割成较短的 Chunk,并通过编码器构建向量索引。
  2. 检索 — 根据问题和 chunks 的相似度检索相关文档片段。
  3. 生成 — 以检索到的上下文为条件,生成问题的回答。
1.通义千问Qwen 1.5

1.1 简介

  • 官方链接:

Qwen1.5 版本年前开源了包括 0.5B、1.8B、4B、7B、14B 和 72B 在内的六种大小的基础和聊天模型,同时,也开源了量化模型。不仅提供了 Int4 和 Int8 的 GPTQ 模型,还有 AWQ 模型,以及 GGUF 量化模型。为了提升开发者体验,Qwen1.5 的代码合并到 Hugging Face Transformers 中,开发者现在可以直接使用 transformers>=4.37.0 而无需 trust_remote_code。

与之前的版本相比,Qwen1.5 显著提升了聊天模型与人类偏好的一致性,并且改善了它们的多语言能力。所有模型提供了统一的上下文长度支持,支持 32K 上下文。还有,基础语言模型的质量也有所小幅改进

Qwen1.5 全系列统一具备强大的链接外部系统能力(agent/RAG/Tool-use/Code-interpreter)

正因为 Qwen1.5 作为中文 LLM 率先合入了 Transformers,我们也可以使用 LLaMaIndex 的原生 HuggingFaceLLM 来加载模型。

当前基础模型已经稳定训练了大规模高质量且多样化的数据,覆盖多语言(当前以中文和英文为主),总量高达3万亿token。在相关基准评测中,Qwen系列模型拿出非常有竞争力的表现,显著超出同规模模型并紧追一系列最强的闭源模型。此外,我们利用SFT和RLHF技术实现对齐,从基座模型训练得到对话模型。Qwen-Chat具备聊天、文字创作、摘要、信息抽取、翻译等能力,同时还具备一定的代码生成和简单数学推理的能力。在此基础上,我们针对LLM对接外部系统等方面针对性地做了优化,当前具备较强的工具调用能力,以及最近备受关注的Code Interpreter的能力和扮演Agent的能力。我们将各个大小模型的特点列到了下表。

模型开源日期最大上下文长度System Prompt强化预训练token数微调(Q-Lora)最小GPU用量生成2048个token的最小显存占用工具调用
Qwen-1.8B23.11.3032K2.2T5.8GB2.9GB
Qwen-7B23.08.0332K2.4T11.5GB8.2GB
Qwen-14B23.09.258K3.0T18.7GB13.0GB
Qwen-72B23.11.3032K3.0T61.4GB48.9GB

Qwen系列模型相比同规模模型均实现了效果的显著提升。我们评测的数据集包括MMLU、C-Eval、 GSM8K、 MATH、HumanEval、MBPP、BBH等数据集,考察的能力包括自然语言理解、知识、数学计算和推理、代码生成、逻辑推理等。Qwen-72B在所有任务上均超越了LLaMA2-70B的性能,同时在10项任务中的7项任务中超越GPT-3.5.

ModelMMLUC-EvalGSM8KMATHHumanEvalMBPPBBHCMMLU
5-shot5-shot8-shot4-shot0-shot3-shot3-shot5-shot
LLaMA2-7B46.832.516.73.312.820.838.231.8
LLaMA2-13B55.041.429.65.018.930.345.638.4
LLaMA2-34B62.6-42.26.222.633.044.1-
ChatGLM2-6B47.951.732.46.5--33.7-
InternLM-7B51.053.431.26.310.414.037.051.8
InternLM-20B62.158.852.67.925.635.652.559.0
Baichuan2-7B54.756.324.65.618.324.241.657.1
Baichuan2-13B59.559.052.810.117.130.249.062.0
Yi-34B76.381.867.915.926.238.266.482.6
XVERSE-65B70.868.660.3-26.3---
Qwen-1.8B45.356.132.32.315.214.222.352.1
Qwen-7B58.263.551.711.629.931.645.062.2
Qwen-14B66.372.161.324.832.340.853.471.0
Qwen-72B77.483.378.935.235.452.267.783.6

1.2 推理性能

测算了BF16、Int8和Int4模型在生成2048个token时的平均推理速度(tokens/s)和显存使用。结果如下所示:

Model SizeQuantizationSpeed (Tokens/s)GPU Memory Usage
1.8BBF1654.094.23GB
Int855.563.48GB
Int471.072.91GB
7BBF1640.9316.99GB
Int837.4711.20GB
Int450.098.21GB
14BBF1632.2230.15GB
Int829.2818.81GB
Int438.7213.01GB
72BBF168.48144.69GB (2xA100)
Int89.0581.27GB (2xA100)
Int411.3248.86GB
72B + vLLMBF1617.602xA100

1.3 训练需要配置

下面记录7B和14B模型在单GPU使用LoRA(LoRA (emb)指的是embedding和输出层参与训练,而LoRA则不优化这部分参数)和QLoRA时处理不同长度输入的显存占用和训练速度的情况。本次评测运行于单张A100-SXM4-80G GPU,使用CUDA 11.8和Pytorch 2.0,并使用了flash attention 2。我们统一使用batch size为1,gradient accumulation为8的训练配置,记录输入长度分别为256、512、1024、2048、4096和8192的显存占用(GB)和训练速度(s/iter)。我们还使用2张A100测了Qwen-7B的全参数微调。受限于显存大小,我们仅测试了256、512和1024token的性能。

对于 Qwen-7B,我们额外测试了多机微调的性能。我们在两台服务器上运行评测,每台服务器包含两张A100-SXM4-80G GPU,其余配置与Qwen-7B的其他评测相同。多机微调的结果在表中以 LoRA (multinode) 标示。对于 Qwen-72B,我们测试了两种方案:1)使用4个 A100-SXM4-80G GPUs,通过 Lora + DeepSpeed ZeRO 3 微调和2)使用单张A100-SXM4-80G GPU,通过 QLora (int4) 微调。请注意,使用 LoRA (emb) 微调和不带 DeepSpeed ZeRO 3 的 LoRA 微调在4个A100-SXM4-80G GPUs 上都会出现OOM(你可以通过将--deepspeed finetune/ds_config_zero3.json参数传给finetune/finetune_lora_ds.sh来打开 DeepSpeed ZeRO 3 配置)。

具体数值如下所示:

Model SizeMethod#Nodes#GPUs per nodeSequence Length
256512102420484096
1.8BLoRA116.7G / 1.0s/it
LoRA (emb)1113.7G / 1.0s/it14.0G / 1.0s/it
Q-LoRA115.8G / 1.4s/it6.0G / 1.4s/it
Full-parameter1143.5G / 2.1s/it43.5G / 2.2s/it
7BLoRA1120.1G / 1.2s/it
LoRA (emb)1133.7G / 1.4s/it34.1G / 1.6s/it
Q-LoRA1111.5G / 3.0s/it11.5G / 3.0s/it
Full-parameter12139.2G / 4.0s/it148.0G / 4.0s/it
LoRA (multinode)2274.7G / 2.09s/it77.6G / 3.16s/it
14BLoRA1134.6G / 1.6s/it
LoRA (emb)1151.2 / 1.7s/it51.1G / 2.6s/it
Q-LoRA1118.7G / 5.3s/it18.4G / 6.3s/it
72BLoRA + Deepspeed Zero314215.4G / 17.6s/it
Q-LoRA1161.4G / 27.4s/it61.4G / 31.5s/it
  1. LLaMaIndex =============

2.1 简介

LlamaIndex 是一个基于 LLM 的应用程序的数据框架,受益于上下文增强。 这种 LLM 系统被称为 RAG 系统,代表 “检索增强生成”。LlamaIndex 提供了必要的抽象,可以更轻松地摄取、构建和访问私有或特定领域的数据,以便将这些数据安全可靠地注入 LLM 中,以实现更准确的文本生成。

picture.image

  • 官方链接

首先,它有助于“摄取”数据,这意味着将数据从原始来源获取到系统中。其次,它有助于“结构化”数据,这意味着以语言模型易于理解的方式组织数据。第三,它有助于“检索”,这意味着在需要时查找和获取正确的数据。最后,它简化了“集成”,使您更容易将数据与各种应用程序框架融合在一起。

  • LllamaIndex 以专用索引的形式提供独特的数据结构:
  • 向量存储索引:最常用,允许您回答对大型数据集的查询。
  • 树索引:对于总结文档集合很有用。
  • 列表索引:对于合成一个结合了多个数据源信息的答案很有用。
  • 关键字表索引:用于将查询路由到不同的数据源。
  • 结构化存储索引:对于结构化数据(例如 SQL 查询)很有用。
  • 知识图谱索引:对于构建知识图谱很有用。

LlamaIndex 有用性的核心是其有助于构建 LLM 应用程序的功能和工具。在这里,我们详细讨论它们:

  • 数据连接器

LlamaIndex 提供数据连接器,可以提取您现有的数据源和格式。无论是 API、PDF、文档还是 SQL 数据库,LlamaIndex 都可以与它们无缝集成,为您的 LLM 准备数据。

  • 数据结构

使用 LLM 的主要挑战之一是以易于使用的方式构建数据。LlamaIndex 提供了在索引或图表中构建数据的工具。

  • 高级检索/查询界面

LlamaIndex 不仅仅是摄取和构建数据。它还为您的数据提供高级检索或查询界面。只需输入任何 LLM 输入提示,LlamaIndex 将返回检索到的上下文和知识增强输出。

  • 与其他框架集成

LlamaIndex 允许与您的外部应用程序框架轻松集成。您可以将它与 LangChain、Flask、Docker、ChatGPT 以及您的项目可能需要的任何其他工具一起使用。

  • 高级和低级 API

无论您的熟练程度如何,LlamaIndex 都能满足您的需求。初学者用户会喜欢高级 API,它允许使用 LlamaIndex 以仅五行代码来摄取和查询他们的数据。另一方面,高级用户可以根据需要利用较低级别的 API 自定义和扩展任何模块(数据连接器、索引、检索器、查询引擎、重新排名模块)。

2.2 快速使用

  • 使用 pip 安装 LlamaIndex 非常简单:

        
          
pip install llama-index  

      
  • 如何构建向量存储索引并查询它的简单示例:

        
          
import os  
os.environ["OPENAI_API_KEY"] = 'YOUR_OPENAI_API_KEY'  
   
from llama_index import GPTVectorStoreIndex, SimpleDirectoryReader  
documents = SimpleDirectoryReader('data').load_data()  
index = GPTVectorStoreIndex.from_documents(documents)  
   
#o query:  
query_engine = index.as_query_engine()  
query_engine.query("<question_text>?")  
   
#By default, data is stored in-memory. To persist to disk (under ./storage):  
index.storage_context.persist()  
   
#To reload from disk:  
from llama_index import StorageContext, load_index  
   
_from_storage  
#rebuild storage context  
storage_context = StorageContext.from_defaults(persist_dir='./storage')  
#load index  
index = load_index_from_storage(storage_context)  

      

LlamaIndex 不仅仅是一个数据框架;它是更大的工具和资源生态系统的一部分: LlamaHub:数据加载器的社区库。 LlamaLab:使用 LlamaIndex 的尖端 AGI 项目平台。

3.GTE 文本向量

3.1 简介

  • 模型链接:

文本表示是自然语言处理 (NLP) 领域的核心问题, 其在很多 NLP、信息检索的下游任务中发挥着非常重要的作用。近几年, 随着深度学习的发展,尤其是预训练语言模型的出现极大的推动了文本表示技术的效果, 基于预训练语言模型的文本表示模型在学术研究数据、工业实际应用中都明显优于传统的基于统计模型或者浅层神经网络的文本表示模型。这里, 我们主要关注基于预训练语言模型的文本表示。

文本表示示例, 输入一个句子, 输入一个固定维度的连续向量:

  • 输入: 吃完海鲜可以喝牛奶吗?
  • 输出: [0.27162,-0.66159,0.33031,0.24121,0.46122,...]

文本的向量表示通常可以用于文本聚类、文本相似度计算、文本向量召回等下游任务中。

picture.image

基于监督数据训练的文本表示模型通常采用 Dual Encoder 框架, 如下图所示。在 Dual Encoder 框架中, Query 和 Document 文本通过预训练语言模型编码后, 通常采用预训练语言模型 [CLS] 位置的向量作为最终的文本向量表示。基于标注数据的标签, 通过计算 query-document 之间的 cosine 距离度量两者之间的相关性。

  • GTE-zh 模型使用 retromae 初始化训练模型,之后利用两阶段训练方法训练模型:
  • 第一阶段利用大规模弱弱监督文本对数据训练模型,
  • 第二阶段利用高质量精标文本对数据以及挖掘的难负样本数据训练模型。

具体训练方法请参考论文 Towards General Text Embeddings with Multi-stage Contrastive Learning。

  • 使用方式:直接推理,对给定文本计算其对应的文本向量表示,向量维度 768
  • 使用范围:本模型可以使用在通用领域的文本向量表示及其下游应用场景, 包括双句文本相似度计算、query & 多 doc 候选的相似度排序

在 ModelScope 框架上,提供输入文本 (默认最长文本长度为 128),即可以通过简单的 Pipeline 调用来使用 GTE 文本向量表示模型。ModelScope 封装了统一的接口对外提供单句向量表示、双句文本相似度、多候选相似度计算功能

3.2 代码示例


        
          
from modelscope.models import Model  
from modelscope.pipelines import pipeline  
from modelscope.utils.constant import Tasks  
  
model_id = "iic/nlp\_gte\_sentence-embedding\_chinese-base"  
pipeline_se = pipeline(Tasks.sentence_embedding,  
                       model=model_id,  
                       sequence_length=512  
                       ) # sequence\_length 代表最大文本长度,默认值为128  
  
#当输入包含“soure\_sentence”与“sentences\_to\_compare”时,会输出source\_sentence中首个句子与sentences\_to\_compare中每个句子的向量表示,以及source\_sentence中首个句子与sentences\_to\_compare中每个句子的相似度。  
inputs = {  
        "source\_sentence": ["吃完海鲜可以喝牛奶吗?"],  
        "sentences\_to\_compare": [  
            "不可以,早晨喝牛奶不科学",  
            "吃了海鲜后是不能再喝牛奶的,因为牛奶中含得有维生素C,如果海鲜喝牛奶一起服用会对人体造成一定的伤害",  
            "吃海鲜是不能同时喝牛奶吃水果,这个至少间隔6小时以上才可以。",  
            "吃海鲜是不可以吃柠檬的因为其中的维生素C会和海鲜中的矿物质形成砷"  
        ]  
    }  
  
result = pipeline_se(input=inputs)  
print (result)  
'''  
{'text\_embedding': array([[ 1.6415151e-04, 2.2334497e-02, -2.4202393e-02, ...,  
 2.7710509e-02, 2.5980933e-02, -3.1285528e-02],  
 [-9.9107623e-03, 1.3627578e-03, -2.1072682e-02, ...,  
 2.6786461e-02, 3.5029035e-03, -1.5877936e-02],  
 [ 1.9877627e-03, 2.2191243e-02, -2.7656069e-02, ...,  
 2.2540951e-02, 2.1780970e-02, -3.0861111e-02],  
 [ 3.8688166e-05, 1.3409532e-02, -2.9691193e-02, ...,  
 2.9900728e-02, 2.1570563e-02, -2.0719109e-02],  
 [ 1.4484422e-03, 8.5943500e-03, -1.6661938e-02, ...,  
 2.0832840e-02, 2.3828523e-02, -1.1581291e-02]], dtype=float32), 'scores': [0.8859604597091675, 0.9830712080001831, 0.966042160987854, 0.891857922077179]}  
'''  
  
  
#当输入仅含有soure\_sentence时,会输出source\_sentence中每个句子的向量表示。  
inputs2 = {  
        "source\_sentence": [  
            "不可以,早晨喝牛奶不科学",  
            "吃了海鲜后是不能再喝牛奶的,因为牛奶中含得有维生素C,如果海鲜喝牛奶一起服用会对人体造成一定的伤害",  
            "吃海鲜是不能同时喝牛奶吃水果,这个至少间隔6小时以上才可以。",  
            "吃海鲜是不可以吃柠檬的因为其中的维生素C会和海鲜中的矿物质形成砷"  
        ]  
}  
result = pipeline_se(input=inputs2)  
print (result)  
'''  
{'text\_embedding': array([[-9.9107623e-03, 1.3627578e-03, -2.1072682e-02, ...,  
 2.6786461e-02, 3.5029035e-03, -1.5877936e-02],  
 [ 1.9877627e-03, 2.2191243e-02, -2.7656069e-02, ...,  
 2.2540951e-02, 2.1780970e-02, -3.0861111e-02],  
 [ 3.8688166e-05, 1.3409532e-02, -2.9691193e-02, ...,  
 2.9900728e-02, 2.1570563e-02, -2.0719109e-02],  
 [ 1.4484422e-03, 8.5943500e-03, -1.6661938e-02, ...,  
 2.0832840e-02, 2.3828523e-02, -1.1581291e-02]], dtype=float32), 'scores': []}  
'''  
  

      

默认向量维度 768, scores 中的 score 计算两个向量之间的内成积距离得到

  • 训练示例代码

        
          
#需在GPU环境运行  
#加载数据集过程可能由于网络原因失败,请尝试重新运行代码  
from modelscope.metainfo import Trainers                                                                                                                                                                
from modelscope.msdatasets import MsDataset  
from modelscope.trainers import build_trainer  
import tempfile  
import os  
  
tmp_dir = tempfile.TemporaryDirectory().name  
if not os.path.exists(tmp_dir):  
    os.makedirs(tmp_dir)  
  
#load dataset  
ds = MsDataset.load('dureader-retrieval-ranking', 'zyznull')  
train_ds = ds['train'].to_hf_dataset()  
dev_ds = ds['dev'].to_hf_dataset()  
model_id = 'iic/nlp\_gte\_sentence-embedding\_chinese-base'  
def cfg\_modify\_fn(cfg):  
    cfg.task = 'sentence-embedding'  
    cfg['preprocessor'] = {'type': 'sentence-embedding','max\_length': 256}  
    cfg['dataset'] = {  
        'train': {  
            'type': 'bert',  
            'query\_sequence': 'query',  
            'pos\_sequence': 'positive\_passages',  
            'neg\_sequence': 'negative\_passages',  
            'text\_fileds': ['text'],  
            'qid\_field': 'query\_id'  
        },  
        'val': {  
            'type': 'bert',  
            'query\_sequence': 'query',  
            'pos\_sequence': 'positive\_passages',  
            'neg\_sequence': 'negative\_passages',  
            'text\_fileds': ['text'],  
            'qid\_field': 'query\_id'  
        },  
    }  
    cfg['train']['neg\_samples'] = 4  
    cfg['evaluation']['dataloader']['batch\_size\_per\_gpu'] = 30  
    cfg.train.max_epochs = 1  
    cfg.train.train_batch_size = 4  
    return cfg   
kwargs = dict(  
    model=model_id,  
    train_dataset=train_ds,  
    work_dir=tmp_dir,  
    eval_dataset=dev_ds,  
    cfg_modify_fn=cfg_modify_fn)  
trainer = build_trainer(name=Trainers.nlp_sentence_embedding_trainer, default_args=kwargs)  
trainer.train()  
  

      

3.3 模型效果评估

  • 中文多任务向量评测榜单C-MTEB结果如下:
Model SizeMethod#Nodes#GPUs per nodeSequence Length
256512102420484096
1.8BLoRA116.7G / 1.0s/it
LoRA (emb)1113.7G / 1.0s/it14.0G / 1.0s/it
Q-LoRA115.8G / 1.4s/it6.0G / 1.4s/it
Full-parameter1143.5G / 2.1s/it43.5G / 2.2s/it
7BLoRA1120.1G / 1.2s/it
LoRA (emb)1133.7G / 1.4s/it34.1G / 1.6s/it
Q-LoRA1111.5G / 3.0s/it11.5G / 3.0s/it
Full-parameter12139.2G / 4.0s/it148.0G / 4.0s/it
LoRA (multinode)2274.7G / 2.09s/it77.6G / 3.16s/it
14BLoRA1134.6G / 1.6s/it
LoRA (emb)1151.2 / 1.7s/it51.1G / 2.6s/it
Q-LoRA1118.7G / 5.3s/it18.4G / 6.3s/it
72BLoRA + Deepspeed Zero314215.4G / 17.6s/it
Q-LoRA1161.4G / 27.4s/it61.4G / 31.5s/it
  • 英文多任务向量评测榜单MTEB结果如下:
Model NameModel Size (GB)DimensionSequence LengthAverage (56)Clustering (11)Pair Classification (3)Reranking (4)Retrieval (15)STS (10)Summarization (1)Classification (12)
gte-large0.67102451263.1346.8485.0059.1352.2283.3531.6673.33
gte-base0.2276851262.3946.284.5758.6151.1482.331.1773.01
e5-large-v21.34102451262.2544.4986.0356.6150.5682.0530.1975.24
e5-base-v20.4476851261.543.8085.7355.9150.2981.0530.2873.84
gte-small0.0738451261.3644.8983.5457.749.4682.0730.4272.31
text-embedding-ada-002-1536819260.9945.984.8956.3249.2580.9730.870.93
e5-small-v20.1338451259.9339.9284.6754.3249.0480.3931.1672.94
sentence-t5-xxl9.7376851259.5143.7285.0656.4242.2482.6330.0873.42
all-mpnet-base-v20.4476851457.7843.6983.0459.3643.8180.2827.4965.07
sgpt-bloom-7b1-msmarco28.274096204857.5938.9381.955.6548.2277.7433.666.19
all-MiniLM-L12-v20.1338451256.5341.8182.4158.4442.6979.827.963.21
all-MiniLM-L6-v20.0938451256.2642.3582.3758.0441.9578.930.8163.05
contriever-base-msmarco0.4476851256.0041.182.5453.1441.8876.5130.3666.68
sentence-t5-base0.2276851255.2740.2185.1853.0933.6381.1431.3969.81
4.魔搭社区最佳实践

4.1 逐步解析

  • 环境配置与安装
  1. python 3.10 及以上版本
  2. pytorch 1.12 及以上版本,推荐 2.0 及以上版本
  3. 建议使用 CUDA 11.4 及以上本文主要演示的模型推理代码可在魔搭社区免费实例 PAI-DSW 的配置下运行(显存 24G) :
  • 第一步:点击模型右侧 Notebook 快速开发按钮,选择 GPU 环境

picture.image

  • 第二步:新建 Notebook

picture.image

安装依赖库1


        
          
!pip install llama-index llama-index-llms-huggingface ipywidgets  
!pip install transformers -U  
import logging  
import sys  
  
logging.basicConfig(stream=sys.stdout, level=logging.INFO)  
logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))  
  
  
from IPython.display import Markdown, display  
import torch  
from llama_index.llms.huggingface import HuggingFaceLLM  
from llama_index.core.prompts import PromptTemplate  
from modelscope import snapshot_download  
from llama_index.core.base.embeddings.base import BaseEmbedding, Embedding  
from abc import ABC  
from typing import Any, List, Optional, Dict, cast  
from llama_index.core import (  
    VectorStoreIndex,  
    ServiceContext,  
    set_global_service_context,  
    SimpleDirectoryReader,  
)  

      
  • 加载大语言模型

因为 Qwen 本次支持了 Transformers,使用 HuggingFaceLLM 加载模型,模型为(Qwen1.5-4B-Chat)1


        
          
#Model names   
qwen2_4B_CHAT = "qwen/Qwen1.5-4B-Chat"  
  
selected_model = snapshot_download(qwen2_4B_CHAT)  
  
SYSTEM_PROMPT = """You are a helpful AI assistant.  
"""  
  
query_wrapper_prompt = PromptTemplate(  
    "[INST]<<SYS>>\n" + SYSTEM_PROMPT + "<</SYS>>\n\n{query_str}[/INST] "  
)  
  
llm = HuggingFaceLLM(  
    context_window=4096,  
    max_new_tokens=2048,  
    generate_kwargs={"temperature": 0.0, "do_sample": False},  
    query_wrapper_prompt=query_wrapper_prompt,  
    tokenizer_name=selected_model,  
    model_name=selected_model,  
    device_map="auto",  
    # change these settings below depending on your GPU  
    model_kwargs={"torch_dtype": torch.float16},  
)  

      
  • 加载数据:导入测试数据

        
          
!mkdir -p 'data/xianjiaoda/'  
!wget 'https://modelscope.oss-cn-beijing.aliyuncs.com/resource/rag/xianjiaoda.md' -O 'data/xianjiaoda/xianjiaoda.md'  
documents = SimpleDirectoryReader("/mnt/workspace/data/xianjiaoda/").load_data()  
documents  

      
  • 构建 Embedding 类

加载 GTE 模型,使用 GTE 模型构造 Embedding 类


        
          
embedding_model = "iic/nlp_gte_sentence-embedding_chinese-base"  
class ModelScopeEmbeddings4LlamaIndex(BaseEmbedding, ABC):  
    embed: Any = None  
    model_id: str = "iic/nlp_gte_sentence-embedding_chinese-base"  
  
    def __init__(  
            self,  
            model_id: str,  
            **kwargs: Any,  
    ) -> None:  
        super().__init__(**kwargs)  
        try:  
            from modelscope.models import Model  
            from modelscope.pipelines import pipeline  
            from modelscope.utils.constant import Tasks  
            # 使用modelscope的embedding模型(包含下载)  
            self.embed = pipeline(Tasks.sentence_embedding, model=self.model_id)  
  
        except ImportError as e:  
            raise ValueError(  
                "Could not import some python packages." "Please install it with `pip install modelscope`."  
            ) from e  
  
    def _get_query_embedding(self, query: str) -> List[float]:  
        text = query.replace("\n", " ")  
        inputs = {"source_sentence": [text]}  
        return self.embed(input=inputs)['text_embedding'][0].tolist()  
  
    def _get_text_embedding(self, text: str) -> List[float]:  
        text = text.replace("\n", " ")  
        inputs = {"source_sentence": [text]}  
        return self.embed(input=inputs)['text_embedding'][0].tolist()  
  
    def _get_text_embeddings(self, texts: List[str]) -> List[List[float]]:  
        texts = list(map(lambda x: x.replace("\n", " "), texts))  
        inputs = {"source_sentence": texts}  
        return self.embed(input=inputs)['text_embedding'].tolist()  
  
    async def _aget_query_embedding(self, query: str) -> List[float]:  
        return self._get_query_embedding(query)  
  

      
  • 建设索引

加载数据后,基于文档对象列表(或节点列表),建设他们的 index,就可以方便的检索他们。1


        
          
embeddings = ModelScopeEmbeddings4LlamaIndex(model_id=embedding_model)  
service_context = ServiceContext.from_defaults(embed_model=embeddings, llm=llm)  
set_global_service_context(service_context)  
  
index = VectorStoreIndex.from_documents(documents)  

      
  • 查询和问答

搭建基于本地知识库的问答引擎1


        
          
  
query_engine = index.as_query_engine()  
response = query_engine.query("西安交大是由哪几个学校合并的?")  
print(response)  

      

4.2 完整代码

0
0
0
0
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论