基于 llama-index与Qwen大模型实现RAG

文章目录

LlamaIndex和Langchain都是比较成熟的RAG和Agent框架,这里基于llama实现RAG框架,大模型选用阿里的开源模型Qwen大模型。可以实现Qwen2.5 与外部数据(例如文档、网页等)的连接,利用 LlamaIndex 与 Qwen2.5 快速部署检索增强生成(RAG)技术。

llama-index

LlamaIndex(前身为 GPT Index)是一个强大的开源数据框架,主要用于构建基于大型语言模型(LLM)的应用程序。

核心功能

  • 数据连接器:能将 LLM 连接到多种数据源,像文档(PDF、Word、文本文件等)、API(Restful API、GraphQL API 等)、数据库(PostgreSQL、MySQL、MongoDB 等),以及 Notion、Slack、Google Docs 等平台。
  • 数据索引:提供多种索引结构来组织和存储外部数据,方便 LLM 快速访问和检索。如列表索引将数据存储为简单列表;向量存储索引利用向量嵌入将数据存于向量数据库,用于语义搜索;树索引把数据组织成树状结构,适用于分层导航;关键字表索引使用关键字索引数据,便于快速查找特定信息。
  • 查询接口:为用户提供了与 LLM 交互并查询索引数据的方式,支持基于关键字的查询、语义查询、基于模板的查询,还允许用户自定义查询逻辑。

工作流程

  • 数据摄取:能集成多种数据源,通过自动化的数据抓取与解析技术,将各类数据准确导入系统。
  • 索引创建:根据用户设定的规则与偏好,为数据定制索引策略,用户可依据数据性质、查询需求等灵活调整,以提高查询效率与数据检索准确性。
  • 查询执行:索引创建完成后,用户可通过用户界面或 API 接口发起数据查询请求,LlamaIndex 借助查询优化算法与索引结构,迅速响应并返回相关度高的结果集。

Qwen

通义千问(英文: Qwen ;读作: kùn)是由阿里巴巴通义千问团队开发的大规模语言和多模态系列模型。通义千问可以执行自然语言理解、文本生成、视觉理解、音频理解、工具调用、角色扮演、智能体等多种任务。语言和多模态模型均在大规模、多语言、多模态数据上进行预训练,并在高质量语料上后训练以与人类偏好对齐。

技术特点

  • 分组查询注意力机制:Qwen2 所有尺寸模型都使用了 GQA 机制,能让用户体验到推理加速和显存占用降低的优势。
  • 多语言能力:在中英文之外,模型训练数据中增加了 27 种语言相关的高质量数据,提升了模型的多语言能力,支持包括中文、英文、法文、西班牙文、葡萄牙文、德文等 29 种以上语言。
  • 上下文长度支持:Qwen2-72B-Instruct 能够完美处理 128k 上下文长度内的信息抽取任务,Qwen-72B 支持长达 32k 的上下文长度。
  • 字节对编码:采用字节对编码(Byte Pair Encoding,简称 BPE)的子词 tokenization 方法,词表有 151646 个 token,确保不存在未知词汇,所有文本都可以转换为 token 序列。

核心能力

  • 自然语言处理:可以执行自然语言理解、文本生成任务,能进行流畅的聊天、内容创造、信息抽取、文本摘要、翻译等。
  • 多模态处理:Qwen-VL 作为视觉语言模型,可实现视觉理解相关任务;Qwen-Audio 等可进行音频理解。
  • 代码与数学能力:Qwen2.5-Coder 在 40 多种编程语言中表现出色,在多编程语言代码修复基准 mdeval 中,Qwen2.5-Coder-32B-Instruct 取得了 75.2 分。Qwen2.5-Math 等模型具备数学问题求解能力。

RAG

RAG(Retrieval-Augmented Generation)即检索增强生成,是一种结合了信息检索和语言生成技术的方法,旨在提高语言模型在生成文本时的准确性、相关性和实用性。

核心原理

  • 检索模块:在生成文本之前,RAG 会根据输入的问题或主题,从一个大规模的语料库或知识图谱等数据源中检索相关的信息。这个检索过程通常基于关键词匹配、语义相似度计算等技术,以找到与当前任务最相关的文本片段或知识条目。
  • 生成模块:利用检索到的信息作为额外的上下文,输入到语言生成模型中,然后由语言生成模型根据这些信息和输入的提示来生成相应的文本。语言生成模型会结合自身的语言知识和检索到的外部信息,生成更准确、更有针对性的回答。

关键优势

  • 提高信息准确性:传统的语言模型可能会生成一些与事实不符或缺乏依据的内容。RAG 通过引入外部准确的信息源,能够显著提高生成内容的准确性和可靠性,使其更符合实际情况。
  • 增强上下文理解:检索到的相关信息为语言模型提供了更丰富的上下文,帮助模型更好地理解问题的背景和意图,从而生成更连贯、更有针对性的回答,提升了模型对复杂问题的处理能力。
  • 提升知识覆盖范围:可以接入各种领域的专业知识数据库、文档库等,大大扩展了语言模型的知识覆盖范围,使其能够在更多领域提供有价值的信息和回答,而不仅仅局限于模型自身训练数据中所包含的知识。
  • 减少幻觉现象:语言模型在生成文本时有时会出现 "幻觉",即生成一些看似合理但实际上不存在或与事实不符的内容。RAG 通过引入外部真实信息作为参考,能够有效减少这种幻觉现象的发生,使生成结果更加可信。

工作流程

知识准备阶段
  • source docs(源文档):代表原始的文档集合,这些文档是系统的知识来源,包含了各种信息。
  • Knowledge Preparation(知识准备):对源文档进行处理,将其分割成较小的 "indexed chunks(索引块)",这些索引块后续会被建立索引,以便于快速检索。
查询处理阶段
  • user query(用户查询):用户输入的问题或查询指令。
  • query elaboration(查询细化):对用户查询进行进一步的处理和理解,可能包括解析、扩展等操作,使其更适合后续处理。
  • embedding(嵌入):将细化后的查询转换为向量表示(嵌入),这是为了在向量空间中进行相似性计算。
检索与重排阶段
  • retrieved chunks(检索到的块):根据查询嵌入,从索引块中检索出与之相关的文档块。
  • re-ranking(重排):对检索到的文档块进行重新排序,通常是基于它们与查询的相关性,选出最相关的文档块。
语言模型调用阶段
  • system prompt(系统提示):是一种预定义的提示,为语言模型提供一些通用的指导或背景信息。
  • context prompt(上下文提示):由重排后的相关文档块构成,为语言模型提供具体的上下文信息。
  • full LLM prompt(完整的大语言模型提示):将系统提示和上下文提示结合起来,形成最终输入给大语言模型(LLM)的提示。
  • LLM call(大语言模型调用):使用完整的提示调用大语言模型。
  • LLM response(大语言模型响应):大语言模型根据输入提示生成的回答,作为最终反馈给用户的结果。

实现

环境准备

使用conda创建环境以及pip安装环境

建议使用 Python 3.10 或以上版本, PyTorch 2.3 ,transformers>=4.37.0 版本

shell 复制代码
# create rag env
conda create -n rag python=3.10
conda activate rag

# install torch
pip install torch
pip install transformers -U

# install qwen
pip install accelerate
pip install tiktoken
pip install einops
pip install transformers_stream_generator==0.0.4
pip install scipy

# install llama-index
pip install llama-index
pip install llama-index-llms-huggingface
pip install llama-index-readers-web
pip install ipywidgets
代码实现

设置参数

现在可以设置语言模型和向量模型。Qwen2.5-Instruct支持包括英语和中文在内的多种语言对话。您可以使用 bge-base-en-v1.5 模型来检索英文文档,下载 bge-base-zh-v1.5 模型以检索中文文档。根据计算资源可以选择 bge-largebge-small 作为向量模型,或调整上下文窗口大小或文本块大小。Qwen2.5模型系列支持最大32K上下文窗口大小(7B 、14B 、32B 及 72B可扩展支持 128K 上下文,但需要额外配置)

python 复制代码
import torch
from llama_index.core import Settings
from llama_index.core.node_parser import SentenceSplitter
from llama_index.llms.huggingface import HuggingFaceLLM
from llama_index.embeddings.huggingface import HuggingFaceEmbedding

# Set prompt template for generation (optional)
from llama_index.core import PromptTemplate

def completion_to_prompt(completion):
   return f"<|im_start|>system\n<|im_end|>\n<|im_start|>user\n{completion}<|im_end|>\n<|im_start|>assistant\n"

def messages_to_prompt(messages):
    prompt = ""
    for message in messages:
        if message.role == "system":
            prompt += f"<|im_start|>system\n{message.content}<|im_end|>\n"
        elif message.role == "user":
            prompt += f"<|im_start|>user\n{message.content}<|im_end|>\n"
        elif message.role == "assistant":
            prompt += f"<|im_start|>assistant\n{message.content}<|im_end|>\n"

    if not prompt.startswith("<|im_start|>system"):
        prompt = "<|im_start|>system\n" + prompt

    prompt = prompt + "<|im_start|>assistant\n"

    return prompt

# Set Qwen2.5 as the language model and set generation config
Settings.llm = HuggingFaceLLM(
    model_name="Qwen/Qwen2.5-7B-Instruct",
    tokenizer_name="Qwen/Qwen2.5-7B-Instruct",
    context_window=30000,
    max_new_tokens=2000,
    generate_kwargs={"temperature": 0.7, "top_k": 50, "top_p": 0.95},
    messages_to_prompt=messages_to_prompt,
    completion_to_prompt=completion_to_prompt,
    device_map="auto",
)

# Set embedding model
Settings.embed_model = HuggingFaceEmbedding(
    model_name = "BAAI/bge-base-en-v1.5"
)

# Set the size of the text chunk for retrieval
Settings.transformations = [SentenceSplitter(chunk_size=1024)]

构建索引

可以从文档构建索引

python 复制代码
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader

documents = SimpleDirectoryReader("./document").load_data()
index = VectorStoreIndex.from_documents(
    documents,
    embed_model=Settings.embed_model,
    transformations=Settings.transformations
)

也可以从一系列网站的内容构建索引

python 复制代码
from llama_index.readers.web import SimpleWebPageReader
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader

documents = SimpleWebPageReader(html_to_text=True).load_data(
    ["web_address_1","web_address_2",...]
)
index = VectorStoreIndex.from_documents(
    documents,
    embed_model=Settings.embed_model,
    transformations=Settings.transformations
)

保存索引与加载索引

python 复制代码
index.storage_context.persist(persist_dir="save")

# save index
storage_context = StorageContext.from_defaults(persist_dir="save")

# load index
index = load_index_from_storage(storage_context)

检索增强rag

可以输入查询,Qwen2.5 将基于索引文档的内容提供答案。

python 复制代码
query_engine = index.as_query_engine()
your_query = "<your query here>"
print(query_engine.query(your_query).response)

总的代码如下:

python 复制代码
import os
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"

import torch
from llama_index.core import Settings
from llama_index.core.node_parser import SentenceSplitter
from llama_index.llms.huggingface import HuggingFaceLLM
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.core import StorageContext, load_index_from_storage

# Set prompt template for generation (optional)
from llama_index.core import PromptTemplate

def completion_to_prompt(completion):
   return f"<|im_start|>system\n<|im_end|>\n<|im_start|>user\n{completion}<|im_end|>\n<|im_start|>assistant\n"


def messages_to_prompt(messages):
    prompt = ""
    for message in messages:
        if message.role == "system":
            prompt += f"<|im_start|>system\n{message.content}<|im_end|>\n"
        elif message.role == "user":
            prompt += f"<|im_start|>user\n{message.content}<|im_end|>\n"
        elif message.role == "assistant":
            prompt += f"<|im_start|>assistant\n{message.content}<|im_end|>\n"

    if not prompt.startswith("<|im_start|>system"):
        prompt = "<|im_start|>system\n" + prompt

    prompt = prompt + "<|im_start|>assistant\n"
    return prompt

# Set Qwen2.5 as the language model and set generation config
device = "cuda:2"
Settings.llm = HuggingFaceLLM(
    model_name="Qwen/Qwen2.5-7B-Instruct",
    tokenizer_name="Qwen/Qwen2.5-7B-Instruct",
    context_window=30000,
    max_new_tokens=2000,
    generate_kwargs={"temperature": 0.7, "top_k": 50, "top_p": 0.95},
    messages_to_prompt=messages_to_prompt,
    completion_to_prompt=completion_to_prompt,
    device_map=device)

# Set embedding model
Settings.embed_model = HuggingFaceEmbedding(model_name = "BAAI/bge-small-zh-v1.5")

# Set the size of the text chunk for retrieval
Settings.transformations = [SentenceSplitter(chunk_size=1024)]

print('----build index----')
# Build index
documents = SimpleDirectoryReader("./document").load_data()
index = VectorStoreIndex.from_documents(
    documents,
    embed_model=Settings.embed_model,
    transformations=Settings.transformations)

print('----save index----')
# save index
index.storage_context.persist(persist_dir="./save")

## load index
#index = load_index_from_storage(storage_context)

query_engine = index.as_query_engine()
while True:
    your_query = input()
    print(query_engine.query(your_query).response)

参考

相关推荐
一 铭9 小时前
dify实现分析-rag-关键词索引的实现
人工智能·语言模型·大模型·llm
百家方案10 小时前
DeepSeek赋能智慧城市:多场景应用,打造感知-决策-执行的闭环解决方案架构
人工智能·ai·大模型·deepseek
m0_6219660118 小时前
一键部署开源DeepSeek并集成到钉钉
开源·大模型·钉钉
shandianchengzi18 小时前
【笔记】LLM|Ubuntu22服务器极简本地部署DeepSeek+联网使用方式
服务器·llm·api·本地部署·deepseek
陈敬雷-充电了么-CEO兼CTO1 天前
DeepSeek核心算法解析:如何打造比肩ChatGPT的国产大模型
人工智能·神经网络·自然语言处理·chatgpt·大模型·aigc·deepseek
♢.*2 天前
析言GBI:用自然语言交互重构企业数据分析范式
人工智能·数据分析·大模型·交互·bi·阿里
cpuCode2 天前
BERT 大模型
人工智能·深度学习·ai·自然语言处理·大模型·llm·bert
风起晨曦2 天前
LLaMa Factory 安装
llama
运维开发王义杰2 天前
AI: Unsloth + Llama 3 微调实践,基于Colab
人工智能·llama
风起晨曦2 天前
(LLaMa Factory)大模型训练方法--预训练(Qwen2-0.5B)
llama