L1G4-InternLM + LlamaIndex RAG 实践
1. RAG技术
1.1 RAG技术概述
解决的问题:
- 生成幻觉:不知道的东西乱说
- 过时知识:大模型的训练是一次性的而不是实时的,不能及时获取最新的知识
- 缺乏透明和可追溯的推理过程:大模型给出的答案可能是对的,但我们不知道是怎么得到的。即不知道信息的来源。
1.2 RAG工作原理
- 索引(Indexing):将外部知识源(文档、网页等)分割成小块(称为文档块),编码成向量,并存储在向量数据库中。
- 检索(Retrieval):接收到用户的问题后,将问题也编码成向量,并在向量数据库中找到与之最相关的文档块(top-k chunks)。
- 生成(Generation):将检索到的文档块与原始问题一起作为提示(prompt)输入到LLM中,生成最终的回答。
例子:
给 ChatGPT 抛出了一个关于最近被广泛讨论的新闻的问题。鉴于 ChatGPT 对培训前数据的依赖,它最初缺乏提供最新动态的能力。RAG 通过从外部数据库获取和整合知识来弥合这种信息差距。在这种情况下,它收集与用户查询相关的新闻文章。这些文章,结合最初的问题,形成了一个全面的提示,授权 LLMs 生成一个充分知情的答案。
1.3 向量数据库
嵌入模型(Embedding Model)是机器学习中的一种模型,主要用于将数据(通常是高维度的数据,如文本、图像、语音等)映射到一个低维的连续向量空间中。这个向量空间中的每个点(即嵌入向量)代表了原始数据的特征,嵌入模型的目标是使得在这个低维空间中的相似数据点之间的距离尽可能小,而不同数据点之间的距离尽可能大。
在自然语言处理(NLP)中,嵌入模型通常用于将单词、句子或文档转换为向量,这样可以让计算机更容易地理解和操作这些文本数据,比如计算数据之间的相似性。
在向量表示中:
- 通常采用贴近语料源的嵌入模型。
- 现在通常使用基于大模型的嵌入模型。
1.4 RAG发展进程
【参考文章】深度解读RAG技术发展历程:从基础Naive RAG 到高级Advanced,再到模块化Modular RAG的全面升级
RAG 发展经历了三个阶段:Naive RAG、 Advanced RAG 和 Modular RAG,下面对三种 RAG 详细阐述。
1.4.1 Naive RAG
Naive RAG 遵循传统过程 Indexing-Retrieval-Generation,也被称为 “Retrieve-Read” 框架。
-
索引(Indexing)
索引首先清理和提取各种格式的原始数据,如 PDF、 HTML、 Word 和 Markdown,然后将其转换为统一的纯文本格式。为了适应语言模型的上下文限制,文本被分割成更小的、可消化的块(chunk)。然后使用嵌入模型将块编码成向量表示,并存储在向量数据库中。这一步对于在随后的检索阶段实现高效的相似性搜索至关重要。知识库分割成 chunks,并将 chunks 向量化至向量库中。
-
检索(Retrieval)
在收到用户查询(Query)后,RAG 系统采用与索引阶段相同的编码模型将查询转换为向量表示,然后计算索引语料库中查询向量与块向量的相似性得分。该系统优先级和检索最高 k (Top-K)块,显示最大的相似性查询。这些块随后被用作 prompt 中的扩展上下文。Query 向量化,匹配向量空间中相近的 chunks。
-
生成(Generation)
提出的查询(Query)和选定的文档(Chunks)被合成为一个连贯的提示,大语言模型负责生成回复。该模型的答复方法可能因具体任务的标准而异,允许它或者利用其固有的参数知识,或者限制其对所提供文件中所包含的信息的答复。在正在进行的对话中,任何现有的对话历史都可以整合到提示中,使模型能够有效地进行多轮对话交互。
-
Native RAG 存在的问题:
检索问题
:检索阶段经常存在准确率和召回率冲突的问题,最终导致召回不一致或不相关的 chunks,以及关键信息的缺失。生成困难
:在产生响应时,模型可能面临幻觉的问题,即它产生的内容不依据检索到的上下文。这个阶段也可能受到输出不相关,毒性或偏倚的影响,从而影响响应的质量和可靠性。增强障碍
:将检索到的信息与不同的任务整合在一起,有时会产生不连贯或不连贯的输出。当从多个来源检索相似的信息时,该过程也可能遇到冗余,导致重复响应。面对复杂的问题,基于原始查询的单一检索可能不足以获得足够的上下文信息。过度依赖
:生成模型可能过度依赖增强的信息,导致输出只是回应检索到的内容,而不添加有见地或合成的信息。
1.4.2 Advanced RAG
Advanced RAG 提高检索质量,采用了检索前和检索后策略(pre-retrieval and post-retrieval strategies)。
预检索过程(Pre-retrieval process)
-
1. 优化索引结构和原始查询优化索引:
-
目标是提高被索引内容的质量
-
涉及到策略如:
-
增强数据粒度
-
数据粒度的概念:数据粒度指的是数据的细化程度。粒度越细,表示数据包含的细节越多,分析结果也越精确;粒度越粗,数据包含的细节越少,分析结果则更为概括。
漫画中,老板的“粗略”、“明细”描述的就是数据的粒度,越明细的数据包含的信息越多,同时也越难解读,所以一般根据需求不同会挑选不同粒度的数据来分析。
在RAG中,对长文本做向量化时:
- 最粗粒度:直接由整篇文章得到一个向量。缺点是长文本往往涵盖多个主题或观点,整体向量难以准确捕捉细节语义,导致语义信息被稀释,无法充分体现文本的核心内容,也会丢失可能与问题相关的段落信息。
- 更细粒度的方法:将文章切分成几个部分,每个部分得到一个向量。切分得越细,数据粒度就越大。优点是将文本分块后,得到的文本片段具有更精细的粒度,能够更准确地匹配用户的查询意图,提升检索结果的相关性和准确度。
-
实施方法:RAG分块策略:主流方法(递归、jina-seg)+前沿推荐(Meta-chunking、Late chunking、SLM-SFT)
-
-
优化索引结构
-
添加元数据
-
对齐优化
-
混合检索等
-
-
- 2. 查询优化:目标是使用户的原始问题更清晰,更适合于检索任务。常见的方法包括:查询重写查询转换,查询扩展等。
后检索过程(Post-Retrieval Process)
-
将检索到相关的上下文有效地集成到查询中是至关重要的。
-
检索后处理的主要方法包括
重新排序块(rerank chunks)
和上下文压缩(context compressing)
。检索后的工作集中在选择关键信息、强调关键部分和缩短待处理的上下文。
1.4.3 Modular RAG
Modular RAG 引入多个特定功能模块和替换现有模块, 总体上展示了更大的灵活性。其过程并不局限于顺序检索和生成,包括迭代和自适应检索等方法。
Modular RAG 并不局限在“检索”-“阅读”的框架,利用大模型自身的"反思"能力等,构建起RAG的新的范式。简单点说,上面两种方法都是一个单一的流水线模式,检索结束之后交给模型,然后模型输出结果。但是在论文中的Modular RAG方法中,递归的调用了LLM的能力,例如利用模型来反思、评估第一次输出,然后再输出新的结果。或者让模型自己决定什么时候调用检索工具。这其实有点像实现一个RAG Agent。论文表示这种模块化的 RAG 范式正逐渐成为 RAG 领域的趋势。
-
new Modules
模块化 RAG 框架引入了额外的专门组件,以增强检索和处理能力。
- Search 模块适应特定的场景,使用 LLM 生成的代码和查询语言,可以直接搜索各种数据源,如搜索引擎、数据库和知识图表。
- RAG-Fusion 通过采用多查询策略解决传统搜索的局限性,该策略将用户查询扩展到不同的视角,利用并行向量搜索和智能重新排序来发现显性和变革性的知识边缘。
- Memory 模块利用 LLM 的内存来指导检索,创建一个无界内存池,通过迭代自我提升,使文本与数据分布更紧密地对齐。
- Routing 模块通过不同的数据源,为查询选择最佳路径,无论是涉及摘要、特定的数据库搜索,还是合并不同的信息流。
- Predict 模块旨在通过直接通过 LLM 生成上下文来减少冗余和噪声,确保相关性和准确性。
- Task Adapter 模块将 RAG 适配到各种下游任务,为 zero-shot 输入自动提示进行检索,为 few-shot 查询生成创建特定于任务的检索器。
-
new Patterns
通过允许模块替换或重新配置来解决特定的问题,模块 RAG 提供了显著的适应能力。这超出了 Naive 和 Advanced RAG 的固定结构,其特点是拥有属性简单的 “Retrieve” 和“ Read”机制。此外,模块化 RAG 通过整合新的模块或调整现有模块之间的交互流来扩展这种灵活性,增强其在不同任务之间的适用性。
1.5 RAG常见优化方法
1.6 RAG vs 微调
RAG和微调处于一种类似于博弈的状态。
长尾知识问题:长尾知识问题的表现是指,由于知识很冷门,数据样本数量少,如果用于训练,模型学习到的特征往往不够充分,导致模型难以对这些罕见类别的知识进行准确的识别。
RAG的局限补充:大模型输出更多取决于其本身的性能,RAG不能打破同一系列的大模型的参数量差异带来的能力差距。
FIne-tuning可能会导致过拟合的原因:用于微调的数据量不够大。
Fine-tuning很难解决长尾知识问题。
1.7 LLM优化方法比较
纵轴:对外部知识的需求程度,也可以理解为实时性能力。
横轴:模型适配度,即模型对于某个专业领域的能力。
- 提示词工程:实时性和模型适配度都低。
- RAG:实时性强,模型适配度弱。
- 微调:实时性弱,模型适配度高。
- All of the above:即将各种方法综合起来,就可以做到实时性和适配度都强。
1.8 评估框架和基准测试
【参考文章】RAG领域的一篇综述:Retrieval-Augmented Generation for Large Language Models: A Survey
【参考文章】喂饭!RAG for LLM: A Survey论文导读
RGB评价框架下RAG的两个评价指标(Evaluation Targets):
- 检索质量(Retrieval Quality):检索到的内容与需求匹配程度。
- 生成质量(Generation Quality)
RGB评价框架下RAG的四个评估维度(Evaluation Aspects):
- 噪声鲁棒性
- 负面拒绝
- 信息整合
- 反面鲁棒性
1.9 RAG总结
RAG常用技术栈:
- Langchain
- LlamaIndex
2. LlamaIndex
2.1 概述
LlamaIndex是一个开源的索引和搜索库,提供高效、可扩展的文本索引和检索功能。
它并不是专为RAG设计的工具,但它提供RAG需要的各种东西。
它的用途:
- 问答知识库
- 结构型提取
- 对话
- 语义式搜索
- 智能体
2.2 用于RAG的优势
下面提到的数据索引和检索和支持多种模型都是它的优势和擅长的地方。
2.3 RAG流程模块化
这里的一些流程可以用于毕设
3. LlamaIndex+InternLM API 实践
3.1 环境准备
3.1.1 安装 Llamaindex
安装 Llamaindex和相关的包
conda activate llamaindex
pip install llama-index==0.11.20
pip install llama-index-llms-replicate==0.3.0
pip install llama-index-llms-openai-like==0.2.0
pip install llama-index-embeddings-huggingface==0.3.1
pip install llama-index-embeddings-instructor==0.2.1
pip install torch==2.5.0 torchvision==0.20.0 torchaudio==2.5.0 --index-url https://download.pytorch.org/whl/cu121
3.1.2 下载 Sentence Transformer 模型
源词向量模型 Sentence Transformer:(我们也可以选用别的开源词向量模型来进行 Embedding,目前选用这个模型是相对轻量、支持中文且效果较好的,同学们可以自由尝试别的开源词向量模型) 运行以下指令,新建一个python文件
cd ~
mkdir llamaindex_demo
mkdir model
cd ~/llamaindex_demo
touch download_hf.py
打开download_hf.py
贴入以下代码
import os# 设置环境变量
os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'# 下载模型
os.system('huggingface-cli download --resume-download sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 --local-dir /root/model/sentence-transformer')
然后,在 /root/llamaindex_demo 目录下执行该脚本即可自动开始下载:
cd /root/llamaindex_demo
conda activate llamaindex
python download_hf.py
更多关于镜像使用可以移步至 HF Mirror 查看。
[!tip]
也可以从modelscope下载
https://modelscope.cn/models/Ceceliachenen/paraphrase-multilingual-MiniLM-L12-v2/summary
git lfs installcd /root/model/git clone https://www.modelscope.cn/Ceceliachenen/paraphrase-multilingual-MiniLM-L12-v2.gitmv paraphrase-multilingual-MiniLM-L12-v2 sentence-transformer
3.1.3 下载 NLTK 相关资源
我们在使用开源词向量模型构建开源词向量的时候,需要用到第三方库 nltk
的一些资源。正常情况下,其会自动从互联网上下载,但可能由于网络原因会导致下载中断,此处我们可以从国内仓库镜像地址下载相关资源,保存到服务器上。 我们用以下命令下载 nltk 资源并解压到服务器上:
cd /root
git clone https://gitee.com/yzy0612/nltk_data.git --branch gh-pages
cd nltk_data
mv packages/* ./
cd tokenizers
unzip punkt.zip
cd ../taggers
unzip averaged_perceptron_tagger.zip
之后使用时服务器即会自动使用已有资源,无需再次下载
3.2 不使用 LlamaIndex RAG(仅API)
使用api来访问internlm2.5-latest模型
首先在.bashrc
文件中export api_key = "your api key"
,然后source .bashrc
运行以下指令,新建一个python文件
cd ~/llamaindex_demo
touch test_internlm.py
打开test_internlm.py 贴入以下代码
from openai import OpenAI
import osbase_url = "https://internlm-chat.intern-ai.org.cn/puyu/api/v1/"
api_key = os.getenv("api_key") # 访问环境变量中的api_key
model="internlm2.5-latest"# base_url = "https://api.siliconflow.cn/v1"
# api_key = "sk-请填写准确的 token!"
# model="internlm/internlm2_5-7b-chat"client = OpenAI(api_key=api_key , base_url=base_url,
)'''
completion 的字面意思是"完成"或"补全"
在 AI 语言模型中,这个术语表示模型在给定提示(prompt)的基础上,生成或"完成"剩余的内容
completions: 文本补全
chat.completions: 对话补全
'''
chat_rsp = client.chat.completions.create(model=model,messages=[{"role": "user", "content": "xtuner是什么?"}],
)for choice in chat_rsp.choices:print(choice.message.content)
之后运行
conda activate llamaindex
cd ~/llamaindex_demo/
python test_internlm.py
结果为:
回答的效果并不好,并不是我们想要的xtuner。
chat_rsp
的结果如下:
会返回:
- choices:模型的答案(一个list)
- created:时间戳
- id:对话id
- model:对话模型
3.3 使用 API+LlamaIndex
首先将外部知识库下载到data
目录下:
mkdir data
cd data
git clone https://github.com/InternLM/xtuner.git # 我们提的问题是xtuner相关的,所以将xtuner的仓库下载到本地。
mv xtuner/README_zh-CN.md ./
运行以下指令,新建一个python文件
cd ~/llamaindex_demo
touch llamaindex_RAG.py
打开llamaindex_RAG.py
贴入以下代码,这就是调用llamaindex库做rag的示例代码:
import os
os.environ['NLTK_DATA'] = '/root/nltk_data'from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.core.settings import Settings
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.legacy.callbacks import CallbackManager
from llama_index.llms.openai_like import OpenAILike# Create an instance of CallbackManager
callback_manager = CallbackManager()api_base_url = "https://internlm-chat.intern-ai.org.cn/puyu/api/v1/"
model = "internlm2.5-latest"
# api_key = "请填写 API Key"
api_key = os.getenv("api_key") # 这里要先在.bashrc中export api_key# api_base_url = "https://api.siliconflow.cn/v1"
# model = "internlm/internlm2_5-7b-chat"
# api_key = "请填写 API Key"llm = OpenAILike(model=model, api_base=api_base_url, api_key=api_key, is_chat_model=True,callback_manager=callback_manager)#初始化一个HuggingFaceEmbedding对象,用于将文本转换为向量表示
embed_model = HuggingFaceEmbedding(
#指定了一个预训练的sentence-transformer模型的路径
#可以看到,这里给我们一个使用说明,即只需要将embedding模型下载到本地(hugging face格式),然后使用llamaindex的api直接指定路径即可。其实在这个模型的hugging face主页上,只有如何通过transformer库或者其自研的库来调用这个模型的方法。
# 访问llamaindex文档查看更多HuggingFaceEmbedding的用法:https://docs.llamaindex.ai/en/stable/examples/embeddings/huggingface/#huggingfaceembeddingmodel_name="/root/model/sentence-transformer"
)
#将创建的嵌入模型赋值给全局设置的embed_model属性,
#这样在后续的索引构建过程中就会使用这个模型。
Settings.embed_model = embed_model#初始化llm
Settings.llm = llm#从指定目录读取所有文档,并加载数据到内存中
documents = SimpleDirectoryReader("/root/llamaindex_demo/data").load_data()
#创建一个VectorStoreIndex,并使用之前加载的文档来构建索引。
# 此索引将文档转换为向量,并存储这些向量以便于快速检索。
index = VectorStoreIndex.from_documents(documents)
# 创建一个查询引擎,这个引擎可以接收查询并返回相关文档的响应。
query_engine = index.as_query_engine()
response = query_engine.query("xtuner是什么?")print(response)
之后运行:
conda activate llamaindex
cd ~/llamaindex_demo/
python llamaindex_RAG.py
结果如下:
借助RAG技术后,就能获得我们想要的答案了。
3.4 LlamaIndex web
通过streamlit
库来构建图形化的大模型对话界面。
运行之前首先安装依赖
pip install streamlit==1.39.0
运行以下指令,新建一个python文件
cd ~/llamaindex_demo
touch app.py
打开app.py
贴入以下代码
import streamlit as st
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.legacy.callbacks import CallbackManager
from llama_index.llms.openai_like import OpenAILike
import os# Create an instance of CallbackManager
callback_manager = CallbackManager()api_base_url = "https://internlm-chat.intern-ai.org.cn/puyu/api/v1/"
model = "internlm2.5-latest"
# api_key = "请填写 API Key"
api_key = os.getenv("api_key") # 这里要先在.bashrc中export api_key# api_base_url = "https://api.siliconflow.cn/v1"
# model = "internlm/internlm2_5-7b-chat"
# api_key = "请填写 API Key"llm =OpenAILike(model=model, api_base=api_base_url, api_key=api_key, is_chat_model=True,callback_manager=callback_manager)st.set_page_config(page_title="llama_index_demo", page_icon="🦜🔗")
st.title("llama_index_demo")# 初始化模型
@st.cache_resource
def init_models():embed_model = HuggingFaceEmbedding(model_name="/root/model/sentence-transformer")Settings.embed_model = embed_model#用初始化llmSettings.llm = llmdocuments = SimpleDirectoryReader("/root/llamaindex_demo/data").load_data()index = VectorStoreIndex.from_documents(documents)query_engine = index.as_query_engine()return query_engine# 检查是否需要初始化模型
if 'query_engine' not in st.session_state:st.session_state['query_engine'] = init_models()def greet2(question):response = st.session_state['query_engine'].query(question)return response# Store LLM generated responses
if "messages" not in st.session_state.keys():st.session_state.messages = [{"role": "assistant", "content": "你好,我是你的助手,有什么我可以帮助你的吗?"}] # Display or clear chat messages
for message in st.session_state.messages:with st.chat_message(message["role"]):st.write(message["content"])def clear_chat_history():st.session_state.messages = [{"role": "assistant", "content": "你好,我是你的助手,有什么我可以帮助你的吗?"}]st.sidebar.button('Clear Chat History', on_click=clear_chat_history)# Function for generating LLaMA2 response
def generate_llama_index_response(prompt_input):return greet2(prompt_input)# User-provided prompt
if prompt := st.chat_input():st.session_state.messages.append({"role": "user", "content": prompt})with st.chat_message("user"):st.write(prompt)# Gegenerate_llama_index_response last message is not from assistant
if st.session_state.messages[-1]["role"] != "assistant":with st.chat_message("assistant"):with st.spinner("Thinking..."):response = generate_llama_index_response(prompt)placeholder = st.empty()placeholder.markdown(response)message = {"role": "assistant", "content": response}st.session_state.messages.append(message)
之后运行
streamlit run app.py
streamlit
库默认使用8501号端口,要在vscode终端中配置端口映射:
提问,回答成功:
4. LlamaIndex+本地部署InternLM实践
4.1 环境准备
进入开发机后,创建新的 conda 环境,命名为 llamaindex2
,在命令行模式下运行:
conda create -n llamaindex2 python=3.10 -y
运行 conda
命令,激活 llamaindex2
:
conda activate llamaindex2
然后安装 python 相关基础依赖包:
pip install einops==0.7.0 protobuf==5.26.1
pip install llama-index==0.10.38 llama-index-llms-huggingface==0.2.0 "transformers[torch]==4.41.1" "huggingface_hub[inference]==0.23.1" huggingface_hub==0.23.1 sentence-transformers==2.7.0 sentencepiece==0.2.0
pip install llama-index-embeddings-huggingface==0.2.0 llama-index-embeddings-instructor==0.1.3
在这一步请确定llama-index-embeddings-huggingface安装成功,如果存在not found错误,请重新安装
pip install llama-index-embeddings-huggingface==0.2.0
确保 huggingface_hub==0.23.1
最后再安装 Pytorch:
conda install pytorch==2.0.1 torchvision==0.15.2 torchaudio==2.0.2 pytorch-cuda=11.7 -c pytorch -c nvidia
安装完成后,验证 Pytorch 是否正确安装并使用了指定的 CUDA 版本:
import torch
print(torch.__version__) # 应输出类似 '2.0.1'
print(torch.version.cuda) # 应输出 '11.7'
print(torch.cuda.is_available())# 应输出 True
随后安装Sentence-Transformer和NLTK,与3.1.2和3.1.3一致。
4.2 用LlamaIndex调用Hugging face LLM
运行以下指令,把 InternLM2 1.8B
软连接出来
cd ~/model
ln -s /root/share/new_models/Shanghai_AI_Laboratory/internlm2-chat-1_8b/ ./
运行以下指令,新建一个 python 文件
cd ~/llamaindex_demo
touch llamaindex_internlm.py
打开 llamaindex_internlm.py 贴入以下代码
from llama_index.llms.huggingface import HuggingFaceLLM
from llama_index.core.llms import ChatMessage
llm = HuggingFaceLLM(model_name="/root/model/internlm2-chat-1_8b",tokenizer_name="/root/model/internlm2-chat-1_8b",model_kwargs={"trust_remote_code":True},tokenizer_kwargs={"trust_remote_code":True}
)rsp = llm.chat(messages=[ChatMessage(content="xtuner是什么?")])
print(rsp)
之后运行
conda activate llamaindex2
cd ~/llamaindex_demo/
python llamaindex_internlm.py
结果为:
4.3 LlamaIndex RAG
在3.3小节中已经下载好了xtuner的相关文件,安装在/root/llamaindex_demo/data
中
运行以下指令,新建一个 python 文件
cd ~/llamaindex_demo
touch llamaindex_RAG2.py
打开llamaindex_RAG2.py
贴入以下代码
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settingsfrom llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.huggingface import HuggingFaceLLM#初始化一个HuggingFaceEmbedding对象,用于将文本转换为向量表示
embed_model = HuggingFaceEmbedding(
#指定了一个预训练的sentence-transformer模型的路径model_name="/root/model/sentence-transformer"
)
#将创建的嵌入模型赋值给全局设置的embed_model属性,
#这样在后续的索引构建过程中就会使用这个模型。
Settings.embed_model = embed_modelllm = HuggingFaceLLM(model_name="/root/model/internlm2-chat-1_8b",tokenizer_name="/root/model/internlm2-chat-1_8b",model_kwargs={"trust_remote_code":True},tokenizer_kwargs={"trust_remote_code":True}
)
#设置全局的llm属性,这样在索引查询时会使用这个模型。
Settings.llm = llm#从指定目录读取所有文档,并加载数据到内存中
documents = SimpleDirectoryReader("/root/llamaindex_demo/data").load_data()
#创建一个VectorStoreIndex,并使用之前加载的文档来构建索引。
# 此索引将文档转换为向量,并存储这些向量以便于快速检索。
index = VectorStoreIndex.from_documents(documents)
# 创建一个查询引擎,这个引擎可以接收查询并返回相关文档的响应。
query_engine = index.as_query_engine()
response = query_engine.query("xtuner是什么?")print(response)
之后运行
conda activate llamaindex2
cd ~/llamaindex_demo/
python llamaindex_RAG2.py
结果为:
4.4 LlamaIndex web
运行之前首先安装依赖
pip install streamlit==1.36.0
运行以下指令,新建一个 python 文件
cd ~/llamaindex_demo
touch app2.py
打开app2.py
贴入以下代码
import streamlit as st
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.huggingface import HuggingFaceLLMst.set_page_config(page_title="llama_index_demo", page_icon="🦜🔗")
st.title("llama_index_demo")# 初始化模型
@st.cache_resource
def init_models():embed_model = HuggingFaceEmbedding(model_name="/root/model/sentence-transformer")Settings.embed_model = embed_modelllm = HuggingFaceLLM(model_name="/root/model/internlm2-chat-1_8b",tokenizer_name="/root/model/internlm2-chat-1_8b",model_kwargs={"trust_remote_code": True},tokenizer_kwargs={"trust_remote_code": True})Settings.llm = llmdocuments = SimpleDirectoryReader("/root/llamaindex_demo/data").load_data()index = VectorStoreIndex.from_documents(documents)query_engine = index.as_query_engine()return query_engine# 检查是否需要初始化模型
if 'query_engine' not in st.session_state:st.session_state['query_engine'] = init_models()def greet2(question):response = st.session_state['query_engine'].query(question)return response# Store LLM generated responses
if "messages" not in st.session_state.keys():st.session_state.messages = [{"role": "assistant", "content": "你好,我是你的助手,有什么我可以帮助你的吗?"}]# Display or clear chat messages
for message in st.session_state.messages:with st.chat_message(message["role"]):st.write(message["content"])def clear_chat_history():st.session_state.messages = [{"role": "assistant", "content": "你好,我是你的助手,有什么我可以帮助你的吗?"}]st.sidebar.button('Clear Chat History', on_click=clear_chat_history)# Function for generating LLaMA2 response
def generate_llama_index_response(prompt_input):return greet2(prompt_input)# User-provided prompt
if prompt := st.chat_input():st.session_state.messages.append({"role": "user", "content": prompt})with st.chat_message("user"):st.write(prompt)# Gegenerate_llama_index_response last message is not from assistant
if st.session_state.messages[-1]["role"] != "assistant":with st.chat_message("assistant"):with st.spinner("Thinking..."):response = generate_llama_index_response(prompt)placeholder = st.empty()placeholder.markdown(response)message = {"role": "assistant", "content": response}st.session_state.messages.append(message)
之后运行
streamlit run app2.py
5. 补充
5.1 llamaindex的HuggingFaceEmedding的用法
在示例代码中,我们是这样调用嵌入模型的
#初始化一个HuggingFaceEmbedding对象,用于将文本转换为向量表示
embed_model = HuggingFaceEmbedding(
#指定了一个预训练的sentence-transformer模型的路径model_name="/root/model/sentence-transformer"
)
#将创建的嵌入模型赋值给全局设置的embed_model属性,
#这样在后续的索引构建过程中就会使用这个模型。
Settings.embed_model = embed_model
可以看到,这里给我们一个使用说明,即只需要将embedding模型下载到本地(hugging face格式),然后使用llamaindex的api直接指定路径即可。
访问llamaindex文档查看更多HuggingFaceEmbedding的用法: