本文是基于MarshalW/jupyterlab-demos/blob/main/proto-embedding-reranker.ipynb 笔记的说明。
笔记的大部分内容,都可以执行在 4GB 显存的 nvidia 设备上(有关配置见 在 4GB 显存下运行 LLM 基础开发环境 )。
本文的目的是,通过 JupyterLab 笔记,最简明的介绍基于 LlamaIndex 使用嵌入(Embedding)和重排(Rerank),对大文档中的知识点进行检索和查询的方法。
另外,给出了初步结论:目前至少需要 Qwen2:7B 以上的模型,才能达到基本可用的效果。
低显存设备可用于学习,但因为模型偏小,准确率很低。
基本思路
- 大模型在不断提升上下文长度,可以将更大的文档一次性加入提示词上下文
- 但是 RAG 依然有存在的价值,原因是:
- 云端模型在对话过程中将消费大量 token,费用昂贵
- 本地模型上下文长度受硬件限制很难大幅提高
- 很多场景的数据量还是会超过最大上下文长度限制
- 最基本的 RAG 一般涉及4个步骤
- 加载数据,比如通过文件系统加载本地的 txt 文件
- 加载的文本文档,切分为一定长度的片段
- 切分方式,基于字符长度,基于自然语言断句,或者基于语义等
- 索引阶段
- 通过嵌入模型,将文档分片用向量(嵌入)表示
- 不同的模型,生成的嵌入是不同的,好的嵌入模型,召回率更高
- 嵌入保存在向量数据库中,笔记中使用 Qdrant
- 创建索引很耗时,会将相关数据存储,供后续阶段读取
- 检索阶段
- 将用户的查询文字,和索引中的向量做运算,文本内容一般使用余弦相似度算法
- 运算结果取
top_k,就是取前多少个相邻向量 - 运算结果通常与语义相似性紧密相关
- 但是,基于词向量的运算,可能无法完全捕捉到所有语义细节
- 查询阶段
- 将检索到的向量的原文,加入到提示词上下文
- 提示词将包括:检索到的文本+用户输入的提示词
- 将合成的提示词传给 LLM,让 LLM 组织文字形成最终的回答
- 加载数据,比如通过文件系统加载本地的 txt 文件
- rerank 是对 RAG 的检索阶段的改进
- 余弦相似度算法的
top_k,可能存在更准确的文本片段排在后面 - rerank 模型基于查询提示词的语义,对
top_k结果重新排序,并取其中的top_n - rerank 适用的场景
- 必须取大量的向量才能涵盖到需要的文本片段,即
top_k很大,比如 1000 - 如果直接将这些片段合成为提示词,会造成
- 性能下降
- 干扰 LLM 正确的回答
- 超出提示词上下文最大值
- 在上述情况下,rerank 能提升大模型回答的准确率,并显著提高响应速度
- 必须取大量的向量才能涵盖到需要的文本片段,即
- 余弦相似度算法的
对显存的要求
笔记代码中使用的模型,最多占用 2.5GB 左右显存:
Qwen2:1.5b: 1508MBquentinz/bge-large-zh-v1.5: 1080MB
reranker,可以不使用 GPU 加载,
BAAI/bge-reranker-base: 需要大约 1.5GB 系统内存
配置使用上述模型,准确率很低,但是可以跑通代码。
实现效果
完整代码笔记见 MarshalW/jupyterlab-demos/blob/main/proto-embedding-reranker.ipynb
演示视频:
实现步骤说明
基本步骤按照笔记 MarshalW/jupyterlab-demos/blob/main/proto-embedding-reranker.ipynb 即可。
有一些需要配置的,下面说明一下。
Ollama 加载多个模型
Ollama 默认只加载一个模型,如果再加载其他模型,则会替换掉当前模型。这样做的目的是节省显存。
为了能同时加载 LLM(比如 Qwen2:1.5b) 模型和嵌入模型(比如 bge-large-zh-v1.5), 需要编辑 llm-proto .env 文件:
OLLAMA_FLASH_ATTENTION=1
OLLAMA_NUM_PARALLEL=4
OLLAMA_MAX_LOADED_MODELS=2 # 可同时加载2个模型
# jubyterlab
JUPYTER_TOKEN="password"
Ollama 下载嵌入模型
# 进入 ollama 容器
docker exec -it llms bash
# 拉取模型
ollama pull quentinz/bge-large-zh-v1.5
reranker 模型的下载和加载
Ollama 没有可支持的 reranker 模型,只能自行加载加载。
bge-reranker-base 下载地址。
在 JupyterLab 的命令行中运行:
# 安装git lfs支持
apt-get update && apt-get install git-lfs -y
mkdir /models
cd /models
# 下载 - 可能需要代理
git clone https://huggingface.co/BAAI/bge-reranker-base
按照绝对路径加载模型:
rerank = SentenceTransformerRerank(
model="/models/bge-reranker-base", top_n=5,
device='cpu',
)
reranker 模型在 GPU 加载
如果显存足够大,可以考虑 reranker 模型也通过 GPU 加载,在笔记中为了适配低显存,用的 CPU 加载, 注视掉 device='cpu',,默认情况下是 GPU 加载。:
rerank = SentenceTransformerRerank(
model="/models/bge-reranker-base", top_n=5,
# device='cpu',
)
总结
- 通过笔记可以掌握 RAG 的基本做法,嵌入检索和查询
- 执行效果很依赖模型质量,一般越大的模型准确率越高
- reranker 可以通过 LLM 执行,LlamaIndex 分装了 LLMRerank
- 笔记最后的部分 - 基于更大的本地模型
- 展示了
Qwen2:7b等更大尺寸模型的效果,准确率较高 - 这部分加载模型的显存至少要 7GB
- 展示了