元数据提取使用模式(Metadata Extraction Usage Pattern)
概念解释
你可以使用 LLM(大型语言模型)来自动提取元数据,通过我们的元数据提取器模块实现。
我们的元数据提取器模块包括以下“特征提取器”:
- SummaryExtractor - 自动提取一组节点的摘要
- QuestionsAnsweredExtractor - 提取每个节点可以回答的一组问题
- TitleExtractor - 提取每个节点的标题
- EntityExtractor - 提取每个节点内容中提到的实体(例如地点、人物、事物的名称)
然后,你可以将元数据提取器与我们的节点解析器链接起来:
使用模式
定义元数据提取器
from llama_index.core.extractors import (
TitleExtractor,
QuestionsAnsweredExtractor,
)
from llama_index.core.node_parser import TokenTextSplitter
text_splitter = TokenTextSplitter(
separator=" ", chunk_size=512, chunk_overlap=128
)
title_extractor = TitleExtractor(nodes=5)
qa_extractor = QuestionsAnsweredExtractor(questions=3)
运行元数据提取器
假设文档已经定义,提取节点:
from llama_index.core.ingestion import IngestionPipeline
pipeline = IngestionPipeline(
transformations=[text_splitter, title_extractor, qa_extractor]
)
nodes = pipeline.run(
documents=documents,
in_place=True,
show_progress=True,
)
或者插入到索引中:
from llama_index.core import VectorStoreIndex
index = VectorStoreIndex.from_documents(
documents, transformations=[text_splitter, title_extractor, qa_extractor]
)
自动元数据提取以改善检索和合成
在本教程中,我们展示了如何执行自动元数据提取以获得更好的检索结果。我们使用两个提取器:一个 QuestionsAnsweredExtractor
,它从一段文本中生成问答对,以及一个 SummaryExtractor
,它不仅在当前文本中提取摘要,还在相邻文本中提取摘要。
我们展示了这允许“块梦境”——每个单独的块可以有更多的“整体”细节,从而在给定检索结果的情况下提高答案质量。
我们的数据来源取自 Eugene Yan 的流行文章《LLM Patterns》:https://eugeneyan.com/writing/llm-patterns/
设置
如果你在 colab 上打开这个 Notebook,你可能需要安装 LlamaIndex 🦙。
%pip install llama-index-llms-openai
%pip install llama-index-readers-web
!pip install llama-index
import nest_asyncio
nest_asyncio.apply()
import os
import openai
# OPTIONAL: setup W&B callback handling for tracing
from llama_index.core import set_global_handler
set_global_handler("wandb", run_args={"project": "llamaindex"})
os.environ["OPENAI_API_KEY"] = "sk-..."
openai.api_key = os.environ["OPENAI_API_KEY"]
定义元数据提取器
这里我们定义元数据提取器。我们定义两个变体:
metadata_extractor_1
只包含QuestionsAnsweredExtractor
metadata_extractor_2
包含QuestionsAnsweredExtractor
和SummaryExtractor
from llama_index.llms.openai import OpenAI
from llama_index.core.schema import MetadataMode
llm = OpenAI(temperature=0.1, model="gpt-3.5-turbo", max_tokens=512)
我们还展示了如何实例化 SummaryExtractor
和 QuestionsAnsweredExtractor
。
from llama_index.core.node_parser import TokenTextSplitter
from llama_index.core.extractors import (
SummaryExtractor,
QuestionsAnsweredExtractor,
)
node_parser = TokenTextSplitter(
separator=" ", chunk_size=256, chunk_overlap=128
)
extractors_1 = [
QuestionsAnsweredExtractor(
questions=3, llm=llm, metadata_mode=MetadataMode.EMBED
),
]
extractors_2 = [
SummaryExtractor(summaries=["prev", "self", "next"], llm=llm),
QuestionsAnsweredExtractor(
questions=3, llm=llm, metadata_mode=MetadataMode.EMBED
),
]
加载数据,运行提取器
我们使用 LlamaHub 的 SimpleWebPageReader
加载 Eugene 的文章(https://eugeneyan.com/writing/llm-patterns/)。
然后我们运行提取器。
from llama_index.core import SimpleDirectoryReader
# load in blog
from llama_index.readers.web import SimpleWebPageReader
reader = SimpleWebPageReader(html_to_text=True)
docs = reader.load_data(urls=["https://eugeneyan.com/writing/llm-patterns/"])
print(docs[0].get_content())
orig_nodes = node_parser.get_nodes_from_documents(docs)
# take just the first 8 nodes for testing
nodes = orig_nodes[20:28]
print(nodes[3].get_content(metadata_mode="all"))
运行元数据提取器:
from llama_index.core.ingestion import IngestionPipeline
# process nodes with metadata extractors
pipeline = IngestionPipeline(transformations=[node_parser, *extractors_1])
nodes_1 = pipeline.run(nodes=nodes, in_place=False, show_progress=True)
Parsing documents into nodes: 0%| | 0/8 [00:00<?, ?it/s]
Extracting questions: 0%| | 0/8 [00:00<?, ?it/s]
print(nodes_1[3].get_content(metadata_mode="all"))
第二次运行摘要和元数据提取器:
# process nodes with metadata extractor
pipeline = IngestionPipeline(transformations=[node_parser, *extractors_2])
nodes_2 = pipeline.run(nodes=nodes, in_place=False, show_progress=True)
Parsing documents into nodes: 0%| | 0/8 [00:00<?, ?it/s]
Extracting summaries: 0%| | 0/8 [00:00<?, ?it/s]
Extracting questions: 0%| | 0/8 [00:00<?, ?it/s]
可视化一些示例数据
print(nodes_2[3].get_content(metadata_mode="all"))
print(nodes_2[1].get_content(metadata_mode="all"))
设置 RAG 查询引擎,比较结果!
我们在三种节点变体之上设置 3 个索引/查询引擎。
from llama_index.core import VectorStoreIndex
from llama_index.core.response.notebook_utils import (
display_source_node,
display_response,
)
# try out different query engines
index0 = VectorStoreIndex(orig_nodes)
index1 = VectorStoreIndex(orig_nodes[:20] + nodes_1 + orig_nodes[28:])
index2 = VectorStoreIndex(orig_nodes[:20] + nodes_2 + orig_nodes[28:])
query_engine0 = index0.as_query_engine(similarity_top_k=1)
query_engine1 = index1.as_query_engine(similarity_top_k=1)
query_engine2 = index2.as_query_engine(similarity_top_k=1)
尝试一些问题
在这个问题中,我们看到朴素的响应 response0
只提到了 BLEU 和 ROUGE,并且缺乏关于其他指标的上下文。
而 response2
在其上下文中包含了所有指标。
query_str = (
"Can you describe metrics for evaluating text generation quality, compare"
" them, and tell me about their downsides"
)
response0 = query_engine0.query(query_str)
response1 = query_engine1.query(query_str)
response2 = query_engine2.query(query_str)
display_response(
response0, source_length=1000, show_source=True, show_source_metadata=True
)
print(response0.source_nodes[0].node.get_content())
display_response(
response1, source_length=1000, show_source=True, show_source_metadata=True
)
display_response(
response2, source_length=1000, show_source=True, show_source_metadata=True
)
在下一个问题中,我们询问 BERTScore/MoverScore。
响应相似。但 response2
比 response0
提供了稍微更多的细节,因为它在元数据中包含了更多关于 MoverScore 的信息。
query_str = (
"Can you give a high-level overview of BERTScore/MoverScore + formulas if"
" available?"
)
response0 = query_engine0.query(query_str)
response1 = query_engine1.query(query_str)
response2 = query_engine2.query(query_str)
display_response(
response0, source_length=1000, show_source=True, show_source_metadata=True
)
display_response(
response1, source_length=1000, show_source=True, show_source_metadata=True
)
display_response(
response2, source_length=1000, show_source=True, show_source_metadata=True
)
response1.source_nodes[0].node.metadata
通过这些详细的解释和示例,希望你能更好地理解和使用 LlamaIndex 中的元数据提取功能。