RAPTOR:树结构的索引和检索系统的递归抽象处理-CSDN博客
原文地址:implementing-advanced-rag-in-langchain-using-raptor
2024 年 3 月 24 日
RAPTOR 简介
递归抽象处理树组织检索(RAPTOR)是种全新而强大的索引和检索技术,它全面适用于LLM。该方法采用自下而上的策略,通过聚类和汇总文本片段(块)来构建一个分层的树状结构。
RAPTOR 论文介绍了一种创新的文档索引和检索策略:
- 首先,将一组初始文档(单个文档的文本块或者完整文档)视为树的“叶子”。
- 这些叶子被嵌入并表示为向量,然后通过聚类算法进行分组。
- 接着,这些聚类被提炼为更高层次(更抽象)的信息,这些信息跨越相似的文档进行整合。
- 整个过程递归进行,形成了一棵从原始文档(叶子)到更抽象摘要的“树”。
假设我们有来自于庞大手册的8个文档块,我们并不只是简单地对这些块进行嵌入并直接进行检索,而是首先将它们转换成向量形式,接着对这些高维向量进行降维处理。这样做是因为生成包含所有维度的簇会带来极高的计算成本,例如,在使用OpenAI的嵌入模型时,维度高达1536,而在使用常见的开源小型嵌入模型时,维度为384。
完成降维后,我们应用聚类算法对这些低维向量进行分组。接下来,我们收集每个聚类中的所有文档块,并对每个聚类的上下文进行总结。这样生成的摘要不仅反映了嵌入和聚类的结果,而且我们还重复这一过程,直到达到模型的令牌限制(即上下文窗口的大小)。
简而言之,RAPTOR方法的核心思想可以概括为:
- 聚类并总结相似的文档块。
- 将相关信息从相关文档中提取到摘要中。
- 为那些只需要少量上下文就能回答的问题提供支持。
LLM 应用技术栈
- Langchain
- llm :zephyr-7b-beta.Q4_K_M.gguf
- 嵌入模型 — thenlper/gte-small
- clustering 算法: GMM (Gaussian Mixture Model)
代码实现
安装所需的库
!pip install -U langchain umap-learn scikit-learn langchain_community tiktoken langchain-openai langchainhub chromadb
!CMAKE_ARGS="-DLLAMA_CUBLAS=on" FORCE_CMAKE=1 pip install -qU llama-cpp-python
import locale
def getpreferredencoding(do_setlocale = True):
return "UTF-8"
locale.getpreferredencoding = getpreferredencoding
获取 Zephyr 模型参数文件
!wget "https://huggingface.co/TheBloke/zephyr-7B-beta-GGUF/resolve/main/zephyr-7b-beta.Q4_K_M.gguf"
实例化 LLM
from langchain_community.llms import LlamaCpp
from langchain_core.callbacks import CallbackManager, StreamingStdOutCallbackHandler
from langchain_core.prompts import PromptTemplate
# 放置在 GPU 上的层数,其余的将在 CPU 上进行,-1表示将所有层移至GPU。
n_gpu_layers = - 1
# 介于 1 和 n_ctx 之间,考虑 GPU 中的 VRAM 量。
n_batch = 512
# 回调支持 token-wise 流式处理
callback_manager = CallbackManager([StreamingStdOutCallbackHandler()])
model = LlamaCpp(
model_path="/content/zephyr-7b-beta.Q4_K_M.gguf",
n_gpu_layers=n_gpu_layers,
n_batch=n_batch,
temperature=0.75,
max_tokens=1000,
top_p=1,
n_ctx=35000,
callback_manager=callback_manager,
verbose=True, # Verbose is required to pass to the callback manager
)
实例化嵌入模型
from langchain.vectorstores import Chroma
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores.utils import DistanceStrategy
EMBEDDING_MODEL_NAME = "thenlper/gte-small"
embd = HuggingFaceEmbeddings(
model_name=EMBEDDING_MODEL_NAME,
multi_process=True,
model_kwargs={"device": "cuda"},
encode_kwargs={"normalize_embeddings": True}, # set True for cosine similarity
)
加载数据
使用LangChain的LCEL文档作为输入数据
import matplotlib.pyplot as plt
import tiktoken
from bs4 import BeautifulSoup as Soup
from langchain_community.document_loaders.recursive_url_loader import RecursiveUrlLoader
# 用于统计每个文本中 Token 数量的辅助函数
def num_tokens_from_string(string: str, encoding_name: str) -> int:
"""返回文本字符串中的令牌数量"""
encoding = tiktoken.get_encoding(encoding_name)
num_tokens = len(encoding.encode(string))
return num_tokens
# LCEL 文档
url = "https://python.langchain.com/docs/expression_language/"
loader = RecursiveUrlLoader(
url=url, max_depth=20, extractor=lambda x: Soup(x, "html.parser").text
)
docs = loader.load()
# LCEL w/ PydanticOutputParser (主要 LCEL 文档之外)
url = "https://python.langchain.com/docs/modules/model_io/output_parsers/quick_start"
loader = RecursiveUrlLoader(
url=url, max_depth=1, extractor=lambda x: Soup(x, "html.parser&