定义和自定义文档#
定义文档#
文档可以通过数据加载器自动创建,也可以手动构建。
默认情况下,我们所有的数据加载器(包括 LlamaHub 上提供的数据加载器)都通过 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
对象是我们的 TextNode
对象的子类,所有这些设置和细节也适用于 TextNode
对象类。
元数据#
文档还提供了包含有用元数据的机会。通过使用每个文档上的 metadata
字典,可以包含附加信息来帮助响应并跟踪查询响应的来源。此信息可以是任何内容,例如文件名或类别。如果您正在与向量数据库集成,请记住某些向量数据库要求键必须是字符串,并且值必须是平面的(可以是 str
、float
或 int
)。
在每个文档的 metadata
字典中设置的任何信息都将显示在从该文档创建的每个源节点的 metadata
中。此外,此信息也包含在节点中,使索引能够在查询和响应中使用它。默认情况下,元数据会被注入文本中,用于嵌入和大型语言模型调用。
有几种设置此字典的方法
- 在文档构造函数中
document = Document(
text="text",
metadata={"filename": "<doc_file_name>", "category": "<category>"},
)
- 创建文档后
document.metadata = {"filename": "<doc_file_name>"}
- 使用
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_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!"
注意:ID 也可以通过 Document 对象上的 node_id
或 id_
属性设置,类似于 TextNode
对象。
高级 - 元数据自定义#
上面提到的一个关键细节是,默认情况下,您设置的任何元数据都包含在嵌入生成和大型语言模型 (LLM) 中。
自定义大型语言模型 (LLM) 元数据文本#
通常,一个文档可能有很多元数据键,但在响应合成过程中,您可能不希望所有这些元数据都对大型语言模型 (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) 或嵌入模型时会注入到每个文档/节点的实际文本中。默认情况下,此元数据的格式由三个属性控制
Document.metadata_seperator
-> 默认值 ="\n"
连接元数据的所有键/值字段时,此字段控制每个键/值对之间的分隔符。
Document.metadata_template
-> 默认值 ="{key}: {value}"
此属性控制元数据中的每个键/值对的格式。需要包含 key
和 value
两个字符串键变量。
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) 本身执行元数据提取的初始示例。