要把一篇方法学 PDF 变成可引用答案,不能把整本塞进提示词。LlamaIndex 用 Document 装一份来源全文,用 Node(通常是 TextNode)装切出来的块。切分后 元数据(metadata)会从 Document 拷到每个 Node;引用能回到 doc_id / 页码,靠的就是这层对象,不是靠模型「记得文件名」。
段末注释:Document 是
TextNode的子类,表示一份来源容器;Node 是索引与召回的原子块。二者都走get_content(),不是只用.text。

1. 一句话定位
| 维度 | 内容 |
|---|---|
| 角色 | 知识层的数据单元:来源容器 vs 可索引块 |
| 输入 → 输出 | 原始字符串 / 文件内容 → Document →(经 NodeParser)list[TextNode] |
| 典型调用入口 | Document(text=..., metadata=...)、parser.get_nodes_from_documents()、node.get_content() |
| 与 LangChain / LangGraph | 近邻是 LangChain Document(page_content);LangGraph 不管切块,节点里拿到的应是已切好的 Node |
出现背景:早期教程把「一段 str」直接 embedding。私有库一上规模,引用、增量更新、父子块都需要稳定 ID 与关系边,于是 Document / Node 成为一等公民。Document 在实现上就是带「整份来源」语义的 TextNode。
2. 前置依赖与环境
1 | pip install -U llama-index-core |
- Python 3.10+
- 版本锚点:
llama-index-core0.14.x(与概述相同) - 本篇不调 LLM / Embedding;同步 API 即可。后续入库才需要 Ollama。
3. 实现逻辑
一次「手写 Document → 切成 Node」的步骤:
1 | 1. 构造 Document(text, metadata, doc_id) |
字段级变形(方法学片段):
1 | Document( |
4. 原理说明
主轴是:同一份 text + metadata,在不同 MetadataMode 下拼出不同字符串,再被切块继承。
1 | 1. 写入 Document.text 与 Document.metadata(扁平 dict:str/int/float) |
对象挂在步骤上:
Document(数据类,llama_index.core.Document)出现在步骤 1。功能:一份来源的容器。最小字段:text: str 非空才有检索意义;metadata: dict 默认 {}。
get_content(metadata_mode)(方法)出现在步骤 3~5。功能:按模式拼「metadata 字符串 + 正文」。默认模板:metadata_template="{key}: {value}",text_template="{metadata_str}\n\n{content}"。
TextNode(数据类,llama_index.core.schema.TextNode)出现在步骤 6。功能:可索引块。关键字段:text、id_(属性 node_id)、metadata、relationships、start_char_idx / end_char_idx。
NodeRelationship(枚举)出现在步骤 7~8。常用:SOURCE(溯源)、PREVIOUS / NEXT(邻块)、PARENT / CHILD(层级切分)。
砍掉 excluded_llm_metadata_keys 时:内部路径、绝对文件名会进生成提示,模型可能把路径当证据。
5. 最小可运行示例
1 | pip install -U llama-index-core |
1 | from llama_index.core import Document |
预期形态:LLM 输出含 species / section 不含 file_name;EMBED 三者都在;至少一个 Node 的 SOURCE.node_id 为 paper_001。
6. 重要配置参数
| 参数(API 名) | 类型 / 默认值 | 功能说明 | 作用与影响 | 参考起点 / 常用范围 | 配置指导 |
|---|---|---|---|---|---|
text |
str,必填 | 来源正文,构造器传入 | 空串可构造但检索无意义 | 非空 | 保持原文,不要先摘要再入库 |
metadata |
dict,{} |
扁平注解,会注入 embed/LLM 文本并传到子 Node | 嵌套 dict / 列表多数向量库不收 | species、page、int/str |
只要扁平标量 |
doc_id / id_ |
str,默认 UUID | 来源级稳定 ID,增量刷新对齐键 | 改 ID 等于新文档,旧向量成孤儿 | 路径或 pmid:123 |
filename_as_id 或显式赋值 |
excluded_llm_metadata_keys |
list[str],[] |
从 LLM 所见文本里拿掉这些键 | 不填则路径/内部 ID 污染生成 | file_name、file_path |
引用仍可从 node.metadata 读 |
excluded_embed_metadata_keys |
list[str],[] |
从 embedding 文本里拿掉这些键 | 拿掉过多会丢过滤信号;拿掉过少会让路径主导向量 | 少排除 | 默认让物种、章节进向量 |
metadata_template |
str,"{key}: {value}" |
每个键值如何格式化进文本 | 改格式会改变 embedding,重建索引才一致 | 保持默认 | 改了必须全量重嵌 |
text_template |
str,"{metadata_str}\n\n{content}" |
metadata 串与正文如何拼接 | 同上,属于嵌入契约 | 保持默认 | 与 template 成对冻结 |
7. 适用 / 不适用
| 维度 | 适用 | 不适用 |
|---|---|---|
| 任务形态 | 私有文档要引用、要按 metadata 过滤 | 一次性 prompt 里塞三句话,不必起 Document |
| 集成约束 | 向量库要求扁平 metadata | 需要深层 JSON 当 payload——先拍平再入库 |
| 工程阶段 | 任何要审计 source_nodes 的 RAG |
只调 Chat 模型、无私有库 |
出现环、审批、会话恢复时:仍用这些 Node 当检索结果,控制流交给 LangGraph。
8. 易踩坑
- 把
.text当成模型真正吃到的字符串:embed/LLM 走get_content(),含 metadata。调试必须按MetadataMode打印。 doc_id每次 UUID:同一文件重建索引无法 upsert,重复块堆积。- metadata 塞嵌套对象:Qdrant / pgvector 一类后端写入失败或被静默丢掉。
小结
- Document 装来源,TextNode 装块;切分默认继承 metadata 并挂 SOURCE。
- 引用看
metadata与relationships;模型看到的字符串看get_content(MetadataMode)。 doc_id是增量更新的对齐键,不要每次随机。- 切分剂量(chunk_size)在 NodeParser 专篇拧;本篇只固定数据契约。