首页 > 教程攻略 > ai资讯 >LlamaIndex中的Document和Node

LlamaIndex中的Document和Node

来源:互联网 时间:2026-07-16 11:38:29

在 LlamaIndex 中,有两个核心概念贯穿始终:

Document

Node

。简单来说,Document 是一个通用的数据容器,可以装下任何来源的信息——PDF、API 返回、数据库查询结果等等。你可以手动创建 Document,也可以借助 LlamaIndex 提供的各种 Reader 自动搞定。默认情况下,每个 Document 会存储文本本身,外加两个关键属性:

  • metadata

    :一个字典,用来存放各种注释信息。
  • relationships

    :也是一个字典,记录与其他 Document 或 Node 的关系。

那么 Node 呢?它是 Document 的“切块”。和 Document 一样,它也拥有 metadata 和 relationships,但地位更特殊——Node 是 LlamaIndex 中的一等公民。你可以直接定义 Node 及其所有属性,也可以借助 NodeParser 将 Document 自动切分成 Node。默认情况下,从同一个 Document 切出来的 Node 都会继承该 Document 的 metadata(比如那个 Document 的文件名会自动传给每个 Node)。

Document

所有 Reader 默认都会通过 load_data() 方法返回 Document 对象。比如:

from llama_index.core import SimpleDirectoryReader

documents = SimpleDirectoryReader("./data").load_data()

当然,你也可以手动创建 Document:

from llama_index.core import Document

text_list = [text1, text2, ...]
documents = [Document(text=t) for t in text_list]

想快速验证原型?直接用默认示例文本:

document = Document.example()

Document 元数据

Document 有一个很重要的属性叫

metadata

,它像个标签笔记本,存着文件名、文件类别之类信息。从 Document 创建的 Node 会继承这个元数据,后续生成嵌入向量和调用 LLM 时也会用到。需要注意:有些向量数据库要求 metadata 字典的键必须是字符串,值必须是 str、float 或 int。

那么怎么设置 metadata 呢?有几种常见方式:

1. 在构造函数中直接指定:

document = Document(
    text="text",
    metadata={"filename": "", "category": ""},
)

2. 创建后再赋值:

document.metadata = {"filename": ""}

3. 使用 SimpleDirectoryReader 的 file_metadata 钩子自动设置文件名:

from llama_index.core import SimpleDirectoryReader

filename_fn = lambda filename: {"file_name": filename}

# 运行钩子自动设置每个 Document 的 metadata
documents = SimpleDirectoryReader(
    "./data", file_metadata=filename_fn
).load_data()

Document ID

每个 Document 都有一个 doc_id 属性,用于唯一标识。当你在 Document 基础上构建索引后,如果后续内容更新,可以根据 doc_id 刷新对应的索引。使用 SimpleDirectoryReader 时,可以设置 filename_as_id=True,这样 doc_id 就是文件的全路径:

from llama_index.core import SimpleDirectoryReader

documents = SimpleDirectoryReader("./data", filename_as_id=True).load_data()
print([x.doc_id for x in documents])

当然,也可以手动设置成其他值:

document.doc_id = "My new document id!"

高级元数据管理

默认情况下,所有 metadata 都会同时参与嵌入向量的生成和 LLM 的答案生成。但有时你可能不希望 LLM 读到某些元数据(比如文件名本身对语义没什么帮助),而文件名在生成嵌入向量时又很有用(可能包含重要信息)。这时候可以指定 LLM 不读取的元数据键,比如:

LLM 只能看到 category 元数据和文件内容了。

同样,你也可以定制在生成嵌入向量阶段要屏蔽的元数据键:

现在我们已经知道元数据和文本内容都会发送给嵌入模型和 LLM,那么它们是以什么格式组织的呢?通过 Document 的以下三个属性可以了解:

这些属性都可以更改,以上只是默认值。

Node

Node 是 LlamaIndex 中的一等公民,代表 Document 的“块”(文本块、图像等)。和 Document 类似,它也包含元数据以及与其他 Node 或索引结构的关系信息。

你可以通过 NodeParser 将 Document 解析为 Node:

from llama_index.core.node_parser import SentenceSplitter

parser = SentenceSplitter()
nodes = parser.get_nodes_from_documents(documents)

也可以直接定义 Node 及其所有属性:

from llama_index.core.schema import TextNode, NodeRelationship, RelatedNodeInfo

node1 = TextNode(text="", id_="")
node2 = TextNode(text="", id_="")
# 设置关系
node1.relationships[NodeRelationship.NEXT] = RelatedNodeInfo(
    node_id=node2.node_id
)
node2.relationships[NodeRelationship.PREVIOUS] = RelatedNodeInfo(
    node_id=node1.node_id
)
nodes = [node1, node2]

RelatedNodeInfo 还可以携带额外的 metadata 信息:

node2.relationships[NodeRelationship.PARENT] = RelatedNodeInfo(
    node_id=node1.node_id, metadata={"key": "val"}
)

每个 Node 都有一个 node_id 属性,如果不指定会自动生成。这个 ID 用途很多:更新存储中的 Node、定义 Node 之间的关系(通过 IndexNode)等等。

print(node.node_id)
node.node_id = "My new node_id!"