Skip to content
LlamaIndex 文档版本 跟随上游 源快照 c59de43b 更新于 2026-10-15

定义 Document

Documents 既可以由数据加载器自动创建,也可以手工构造。

默认情况下,我们所有的数据加载器都通过 load_data 函数返回 Document 对象。

from llama_index.core import SimpleDirectoryReader

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

你也可以选择手工构造文档。LlamaIndex 暴露了 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 对象的多种方式。由于 Document 是 TextNode 的子类,这里讲的所有设置与细节同样适用于 TextNode 类。

元数据

Document 还允许你带上有用的元数据。借助每个文档上的 metadata 字典,可以附加额外信息,用来为回答提供参考、并追踪查询结果的来源。这些信息可以是任意内容,比如文件名或类别。如果你要对接向量数据库,请注意:有些向量库要求 key 必须是字符串、value 必须是扁平值(str、float 或 int)。

你在每个文档 metadata 字典里设置的信息,都会出现在由该文档创建的每个源节点的 metadata 中。此外这些信息会被纳入节点本身,使索引能够在查询与回答时利用它们。默认情况下,元数据会被注入到文本中,同时用于嵌入和 LLM 调用。

有几种方式可以设置这个字典:

  1. 在文档构造函数里设置:
document = Document(
    text="text",
    metadata={"filename": "<doc_file_name>", "category": "<category>"},
)
  1. 文档创建之后再设置:
document.metadata = {"filename": "<doc_file_name>"}
  1. 用 SimpleDirectoryReader 和 file_metadata 钩子自动设置文件名。该钩子会在每个文档上运行,用以设置 metadata 字段:
from llama_index.core import SimpleDirectoryReader

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

# automatically sets the metadata of each document according to filename_fn
documents = SimpleDirectoryReader(
    "./data", file_metadata=filename_fn
).load_data()

定制 id

正如文档管理一节所述,doc_id 用于在索引中高效地刷新文档。使用 SimpleDirectoryReader 时,你可以自动把每个文档的 doc 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!

document.doc_id = "My new document id!"

注意:与 TextNode 对象类似,文档上的 ID 也可以通过 node_id 或 id_ 属性来设置。

进阶 —— 元数据定制

上文提到的一个关键是:默认情况下,你设置的任何元数据都会被纳入嵌入生成与 LLM 输入。

定制 LLM 可见的元数据文本

通常一个文档会有许多元数据 key,但你未必希望它们在响应合成时全部对 LLM 可见。以上面的例子来说,我们可能不想让 LLM 读到文档的 file_name;但 file_name 又可能包含有助于生成更好嵌入的信息。这样做的主要好处是:为检索偏向嵌入,同时不改变 LLM 最终读到的内容。

可以像这样把它排除掉:

document.excluded_llm_metadata_keys = ["file_name"]

随后,我们可以用 get_content() 函数并指定 MetadataMode.LLM,来验证 LLM 实际读到了什么:

from llama_index.core.schema import MetadataMode

print(document.get_content(metadata_mode=MetadataMode.LLM))

定制嵌入可见的元数据文本

与定制 LLM 可见的元数据类似,我们也可以定制嵌入模型可见的元数据。这里可以专门排除某些对嵌入模型可见的元数据,以防某些文本影响(偏向)嵌入。

document.excluded_embed_metadata_keys = ["file_name"]

随后,我们可以用 get_content() 函数并指定 MetadataMode.EMBED,来验证嵌入模型实际读到了什么:

from llama_index.core.schema import MetadataMode

print(document.get_content(metadata_mode=MetadataMode.EMBED))

定制元数据格式

你现在已经知道,元数据会被注入每个文档/节点的实际文本,再送给 LLM 或嵌入模型。默认情况下,这段元数据的格式由三个属性控制:

  1. Document.metadata_seperator -> 默认 = "\n"

在拼接你元数据里的所有键值字段时,该属性控制每一对键值之间的分隔符。

  1. Document.metadata_template -> 默认 = "{key}: {value}"

该属性控制元数据中每一对键值的呈现格式。两个字符串变量 key 与 value 是必需的。

  1. Document.text_template -> 默认 = {metadata_str}\n\n{content}

当你的元数据已用 metadata_seperator 与 metadata_template 转成字符串后,该模板决定「元数据与文档/节点正文拼接时」的样子。metadata 与 content 这两个字符串键是必需的。

总结

了解这些之后,我们来写一个把这套能力都用上的小例子:

from llama_index.core import Document
from llama_index.core.schema import MetadataMode

document = Document(
    text="This is a super-customized document",
    metadata={
        "file_name": "super_secret_document.txt",
        "category": "finance",
        "author": "LlamaIndex",
    },
    excluded_llm_metadata_keys=["file_name"],
    metadata_seperator="::",
    metadata_template="{key}=>{value}",
    text_template="Metadata: {metadata_str}\n-----\nContent: {content}",
)

print(
    "The LLM sees this: \n",
    document.get_content(metadata_mode=MetadataMode.LLM),
)
print(
    "The Embedding model sees this: \n",
    document.get_content(metadata_mode=MetadataMode.EMBED),
)

进阶 —— 自动元数据抽取

我们已有关于直接用 LLM 完成元数据抽取的初步示例。

BytesRouter 是社区翻译站点,所有译文仅供参考,一切以官方英文原文为准。