RAG进阶——初探llamaIndex的Document Summary Index

在这里插入图片描述
使用文档摘要索引增强大型语言模型问答系统
大型语言模型 (LLM) 的核心用例之一是利用自身数据进行问答。为了实现这一点,我们将 LLM 与一个能够在知识语料库上执行信息检索的“检索”模型配对,并使用 LLM 对检索到的文本进行响应合成。这种整体框架称为检索增强生成 (Retrieval-Augmented Generation)。

当今构建 LLM 驱动的问答系统的大多数用户倾向于执行以下某种操作:

获取源文档,并将每个文档分割成文本块
将文本块存储在向量数据库中
在查询时,通过嵌入相似性和/或关键词过滤器检索文本块
执行响应合成
出于多种原因,这种方法的检索性能有限。

现有方法的局限性
使用文本块进行嵌入检索存在一些限制:

文本块缺乏全局上下文。通常情况下,问题需要超出特定块中索引的内容之外的上下文。
需要仔细调整 top-k / 相似度得分阈值。 将值设置得太小,您将错过上下文。 将值设置得太大,成本/延迟可能会随着更多无关的上下文而增加。
嵌入并不总是为问题选择最相关的上下文。 嵌入本质上是在文本和上下文之间单独确定的。
添加关键词过滤器是一种增强检索结果的方法。 但这会带来一系列挑战。 我们需要充分确定每个文档的适当关键词,无论是手动操作还是通过 NLP 关键词提取/主题标记模型。 我们还需要从查询中充分推断适当的关键词。
文档摘要索引
[图表:LlamaIndex 的文档摘要索引]

我们在 LlamaIndex 中提出了一种新的索引,用于提取/索引每个文档的 非结构化文本摘要。 该索引可以帮助将检索性能提升到现有检索方法之外。 它可以比单个文本块索引更多信息,并且比关键词标签携带更多的语义含义。 它还允许更灵活的检索形式:我们可以同时进行 LLM 检索和基于嵌入的检索。

工作原理
在构建时,我们摄取每个文档,并使用 LLM 从每个文档中提取摘要。 我们还将文档分割成文本块(节点)。摘要和节点都存储在我们文档存储抽象中。 我们维护从摘要到源文档/节点的映射。

在查询时,我们使用以下方法根据其摘要检索与查询相关的文档:

基于 LLM 的检索: 我们向 LLM 提供一系列文档摘要,并要求 LLM 确定哪些文档是相关的 + 它们的相关性得分。
基于嵌入的检索: 我们基于摘要嵌入相似性(使用 top-k 截断)检索相关文档。
请注意,这种用于文档摘要的检索方法(即使使用基于嵌入的方法)也与基于文本块的基于嵌入的检索不同。 文档摘要索引的检索类会检索任何选定文档的 所有节点,而不是在节点级别返回相关块。
存储文档摘要也支持 基于 LLM 的检索。 我们可以先让 LLM 检查简洁的文档摘要,看看它是否与查询相关,而不是一开始就将整个文档馈送给 LLM。 这利用了比基于嵌入的查找更高级的 LLM 的推理能力,但避免了将整个文档馈送给 LLM 的成本/延迟。

额外见解
使用摘要进行文档检索可以被视为语义搜索和所有文档的蛮力摘要之间的“中间地带”。 我们根据给定查询的摘要相关性来查找文档,然后返回所有对应于检索到的文档的 节点。

我们为什么要这样做? 这种检索方法比文本块的 top-k 提供给用户更多的上下文,因为它可以在文档级别检索上下文。 但它也比主题建模更灵活/自动;无需再担心您的文本是否有正确的关键词标签!

文档摘要索引演示
本演示展示了对不同城市的维基百科文章进行的文档摘要索引。

文档摘要索引将从每个文档中提取摘要,并存储该摘要以及与文档相对应的所有节点。

检索可以通过LLM或嵌入(这是一个TODO)执行。我们首先根据它们的摘要选择与查询相关的文档。检索到的所有与所选文档对应的节点都将被检索。

如果您在Colab上打开此笔记本,可能需要安装LlamaIndex 🦙。

%pip install llama-index-llms-openai
!pip install llama-index
import os
import openai

os.environ["OPENAI_API_KEY"] = "sk-..."
openai.api_key = os.environ["OPENAI_API_KEY"]
import logging
import sys

logging.basicConfig(stream=sys.stdout, level=logging.WARNING)
logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))

# # Uncomment if you want to temporarily disable logger
# logger = logging.getLogger()
# logger.disabled = True
import nest_asyncio

nest_asyncio.apply()
from llama_index.core import SimpleDirectoryReader, get_response_synthesizer
from llama_index.core import DocumentSummaryIndex
from llama_index.llms.openai import OpenAI
from llama_index.core.node_parser import SentenceSplitter

加载数据集
加载不同城市的维基百科页面。

wiki_titles = ["Toronto", "Seattle", "Chicago", "Boston", "Houston"]
from pathlib import Path

import requests

for title in wiki_titles:
    response = requests.get(
        "https://en.wikipedia.org/w/api.php",
        params={
   
   
            "action": "query",
            "format": "json",
            "titles": title,
            "prop": "extracts",
            # 'exintro': True,
            "explaintext": True,
        },
    ).json()
    page = next(iter(response["query"]["pages"].values()))
    wiki_text = page["extract"]

    data_path = Path("data")
    if not data_path.exists():
        Path.mkdir(data_path)

    with open(data_path / f"{
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值