在自然语言处理(NLP)领域,高效处理和组织文本数据是构建强大应用的关键。LlamaIndex 框架为我们提供了便捷的工具,尤其是其中的 Document 和 Node 类型,它们在数据处理和检索方面发挥着重要作用。本文将深入探讨 LlamaIndex 框架中 Document 和 Node 类型的相关知识,帮助你更好地理解和运用这一强大的工具。
一、Document 类型:通用数据容器
1.1 定义与用途
在 LlamaIndex 中,Document 类型的对象可以看作是一个通用的不同来源的数据容器。它能够容纳来自文档、数据库或者企业级应用系统中的数据。通过 Document 对象,我们可以方便地将各种数据源整合到一起,为后续的处理和分析提供统一的接口。
1.2 创建 Document 对象
我们可以使用以下代码创建一个简单的 Document 对象:
python
from llama_index.core.schema import Document
import pprint
doc = Document(text="RAG 是一种常见的大模型应用范式,它通过检索 - 排序 - 生成的方式生成文本",
metadata={'title': 'RAG 模型介绍', 'author': 'llamaindex'})
pprint.pprint(doc.dict())
在上述代码中,我们创建了一个包含文本内容和元数据的 Document 对象,并使用 doc.dict()
方法将其内部数据转换为字典对象进行打印。元数据是数据的描述信息,它可以帮助我们更好地理解和管理数据。在这个例子中,元数据包含了文档的标题和作者信息。
1.3 元数据的深入理解
元数据在 Document 对象中扮演着重要的角色,它可以被理解为描述数据的数据。元数据的类型是字典类型,由多个 key/value 组成,我们可以在其中放入任何需要的信息。此外,Document 对象生成的 Node 对象会自动携带 Document 对象的元数据,并且元数据会在生成向量或者响应时和文本内容一起被输入,用于帮助模型更好地控制输出。
以下是一个更复杂的 Document 对象创建示例,展示了如何自定义元数据的处理方式:
python
from llama_index.core.schema import Document, MetadataMode
doc4 = Document(
text='百度是一家中国的搜索引擎公司',
metadata={
"file_name": "test.txt",
"category": "technology",
"author": "random person"
},
excluded_llm_metadata_keys=['file_name'],
excluded_embed_metadata_keys=['filename', 'author'],
metadata_separator=" | ",
metadata_template="{key} =>{value}",
text_template="Metadata:{metadata_str}\n-----\nContent:{content}"
)
print("\n全部元数据:\n", doc4.get_content(metadata_mode=MetadataMode.ALL))
在这个例子中,我们定义了多个参数来控制元数据的处理。excluded_llm_metadata_keys
表示在发送给大模型时需要排除的元数据 key,excluded_embed_metadata_keys
表示在发送给嵌入模型时需要排除的元数据 key。metadata_separator
用于定义连接元数据多个 key/value 对的分隔符,metadata_template
用于定义元数据每个 key/value 对的转换格式,text_template
用于定义组合元数据与文本内容的格式。
1.4 不同方式创建 Document 对象
除了直接使用文本创建 Document 对象外,我们还可以利用数据连接器加载数据生成 Document 对象。例如,使用 SimpleDirectoryReader
从某个目录中加载一个或多个文档到 Document 对象中:
python
from llama_index.core import SimpleDirectoryReader
docs3 = SimpleDirectoryReader('../../data/source_files').load_data()
print(len(docs3))
在上述代码中,我们使用 SimpleDirectoryReader
加载指定目录下的所有文档,并将其转换为 Document 对象。打印结果显示了生成的 Document 对象的数量。需要注意的是,加载一个 PDF 文档时,默认生成的数量对应 PDF 的页数;加载目录下所有文档时,生成的 Document 数量则和文档数量保持一致。
二、Node 类型:Document 对象的分割块
2.1 定义与特点
Node 类型的对象可以想象成对应的 Document 对象分割后的一个块。在 LlamaIndex 中,Node 类型来自 basenode
基类,有 4 种 Node 类型,分别是 text、image、document 和 index 索引 Node。其中,text 类型是最基本的 Node 类型,它保存了文本内容。
2.2 Node 对象的生成
2.2.1 直接生成
我们可以直接使用文本生成 Node 对象,示例代码如下:
python
from llama_index.core.schema import TextNode
texts = 'xxx'
node = TextNode(text=texts)
2.2.2 用 Document 生成
大多数 Node 对象是用 Document 对象通过各种数据分割器生成的。以下是一个使用 TokenTextSplitter
构造简单数据分割器并生成 Node 对象的示例:
python
from llama_index.core import SimpleDirectoryReader
from llama_index.text_splitter import TokenTextSplitter
# 加载文档
docs = SimpleDirectoryReader('../../data/source_files').load_data()
# 构造数据分割器
parser = TokenTextSplitter(chunk_size=100, chunk_overlap=0, separator="\n")
nodes = parser.get_nodes_from_documents(docs)
在上述代码中,我们首先使用 SimpleDirectoryReader
加载文档,然后使用 TokenTextSplitter
构造数据分割器,最后通过 get_nodes_from_documents
方法将 Document 对象分割成多个 Node 对象。
2.3 元数据抽取器生成元数据
元数据抽取器通常会借助大模型或自定义算法来生成 Node 对象中与内容相关的额外信息,将其作为元数据。这些元数据可以提供原始内容以外的更丰富的语义或参考信息,提高检索与生成的能力。常见的元数据抽取器包括摘要抽取器、问答抽取器和标题抽取器。
2.3.1 摘要抽取器
python
from llama_index.core.extractors import SummaryExtractor
from llama_index.llms import Ollama
from llama_index.core import SimpleDirectoryReader
llm = Ollama(model="qwen:14b")
docs = SimpleDirectoryReader(input_files=['../../data/yy.txt']).load_data()
summaryextractor = SummaryExtractor(llm=llm, show_progress=False,
prompt_template="请生成以下内容的中文摘要:{context_str}\n摘要:",
metadata=MetadataMode.NONE)
section_summary = summaryextractor.extract(docs)
在上述代码中,我们使用 SummaryExtractor
从文档中抽取摘要信息。首先,我们初始化了一个大语言模型 llm
,然后使用 SimpleDirectoryReader
加载文档,接着创建了 SummaryExtractor
对象,并调用 extract
方法抽取摘要。
2.3.2 问答抽取器
问答抽取器可以从给定的 Node 对象中生成其内容可以回答的问题列表(假设性问题),其使用方式与摘要抽取器类似,只需将 SummaryExtractor
替换为 QuestionAnsweredExtractor
即可。
2.3.3 标题抽取器
标题抽取器用于给输入的 Node 对象的内容生成标题,同样可以通过创建 TitleExtractor
对象并调用 extract
方法来实现。
三、IndexNode 类型:特殊的 Node 类型
3.1 定义与特点
IndexNode 类型是一种在 textnode 类型的基础上扩展的 Node 类型,除了具备 textnode 类型的基本属性外,还可以带有指向其他 Node 类型或者对象的引用。它主要通过 index_id
属性保存其他对象的 id,通过 obj
属性保存其他对象的引用指向。
3.2 主要作用
IndexNode 的主要作用是在检索器检索出 IndexNode 对象时,根据其 index_id
属性或者 obj
属性进行递归操作。例如,根据摘要 Node 找到完整的内容 Node,根据一级 Node 找到二级检索需要的检索器或者查询引擎。
总结
本文详细介绍了 LlamaIndex 框架中 Document 和 Node 类型的相关知识,包括它们的定义、创建方式、元数据处理以及不同类型的 Node 对象的特点和用途。通过深入理解这些内容,你可以更好地利用 LlamaIndex 框架进行文本数据的处理和检索,为构建强大的自然语言处理应用打下坚实的基础。希望本文对你有所帮助,如果你在使用过程中遇到任何问题,欢迎在评论区留言讨论。