langchain_core.documents.Document
是 LangChain 框架中的核心类,用于封装文本内容及其相关元数据,是构建基于大型语言模型(LLM)应用的基础组件。它在文档加载、文本分割、向量存储和问答系统等场景中扮演重要角色。本文将从定义、属性、创建方法、应用场景、示例代码和注意事项等方面,详细讲解 Document
类的功能与使用方法。
一、定义与作用
1. 什么是 Document
类?
Document
类是 LangChain 框架中用于表示文档的标准化数据结构,继承自 BaseMedia
类。它设计用于存储一段文本内容(page_content
)及其相关元数据(metadata
),便于在 LLM 应用中进行文档管理、处理和检索。
-
核心功能:
- 封装文本内容和元数据,提供统一的文档表示。
- 支持 LangChain 生态系统中的模块化操作,如文档加载、分割、嵌入和检索。
- 适用于上下文感知、问答系统、检索增强生成(RAG)等场景。
-
设计目标:
- 提供简单、灵活的接口,适应多种数据源(如 PDF、网页、数据库)。
- 确保与 LangChain 的其他组件(如链、代理、向量存储)无缝集成。
2. 为什么需要 Document
类?
在 LLM 应用中,原始文本数据往往需要附加上下文信息(如来源、作者、时间戳),以便在检索、过滤或生成答案时使用。Document
类通过将文本和元数据统一封装,简化了这些操作,降低了开发复杂度。
二、核心属性
Document
类的属性清晰定义,支持文本和元数据的灵活存储。以下是其主要属性的详细说明:
属性名称 | 描述 | 类型/约束 | 是否必需 | 版本新增 |
---|---|---|---|---|
page_content | 文档的主要文本内容,必须提供 | str | 必需 | - |
metadata | 可选的字典,存储与文档相关的元数据,如来源、作者、时间等 | dict | 可选 | - |
id | 可选的唯一标识符,建议使用 UUID,格式不强制 | str | None | 可选 |
type | 固定为“Document”,用于内部类型检查和序列化 | Literal['Document'] | 自动设置 | - |
属性详解:
-
page_content
:- 存储文档的核心文本内容,是与 LLM 交互的主要数据。
- 必须是字符串类型,不能为空。
- 示例:一段文章的正文、网页的段落内容等。
-
metadata
:- 一个字典,用于存储任意键值对,表示文档的附加信息。
- 常见元数据包括:
source
:文档来源(如 URL 或文件路径)。author
:文档作者。timestamp
:创建或修改时间。
- 元数据在检索和过滤时非常有用,例如仅检索特定来源的文档。
-
id
:- 从 LangChain 版本 0.2.11 开始引入,用于为文档提供唯一标识。
- 建议使用 UUID(如
uuid.uuid4()
),但格式不强制。 - 在管理大型文档集合或向量存储时,
id
有助于跟踪和区分文档。
-
type
:- 固定值为“Document”,由类自动设置。
- 用于 LangChain 内部的类型检查和序列化,确保对象的一致性。
三、创建 Document
实例
创建 Document
实例非常简单,可以通过构造函数传递 page_content
和可选的 metadata
参数。以下是几种常见方式:
1. 基本创建
from langchain_core.documents import Document
# 创建一个简单的 Document 对象
document = Document(
page_content="这是一个示例文档,介绍 LangChain 的功能。",
metadata={"source": "example.com", "author": "张三", "date": "2025-05-18"}
)
2. 使用位置参数
page_content
支持作为位置参数传递,简化代码:
document = Document(
"这是一个简短的文档。",
metadata={"source": "local_file.txt"}
)
3. 带 id
的创建
如果需要唯一标识符,可以手动指定 id
:
import uuid
document = Document(
page_content="带 ID 的文档示例。",
metadata={"source": "database"},
id=str(uuid.uuid4())
)
4. 动态生成多个 Document
在实际应用中,文档通常成批生成,例如从文件或网页加载:
documents = [
Document(
page_content=f"文档 {i} 的内容",
metadata={"index": i, "source": f"file_{i}.txt"}
) for i in range(3)
]
四、常见用途与应用场景
Document
类在 LangChain 的多个模块中广泛应用,以下是其主要场景及实际用途:
1. 文档加载
- 场景:从外部数据源(如 PDF、网页、CSV、数据库)加载内容时,加载器会将数据转换为
Document
对象。 - 示例:使用
HNLoader
加载 Hacker News 评论:from langchain_community.document_loaders import HNLoader loader = HNLoader("https://news.ycombinator.com/item?id=34422627") documents = loader.load() # documents 是 Document 对象的列表,每个对象包含评论内容和元数据
- 作用:将原始数据标准化为
Document
,便于后续处理。
2. 文本分割
- 场景:将长文档分割成小块,以便嵌入向量空间或输入 LLM。
- 示例:使用
CharacterTextSplitter
进行分割:from langchain.text_splitter import CharacterTextSplitter long_document = Document( page_content="这是一篇很长的文章..." * 100, metadata={"source": "article.txt"} ) splitter = CharacterTextSplitter(chunk_size=100, chunk_overlap=20) split_documents = splitter.split_documents([long_document]) # split_documents 是多个小 Document 对象的列表
- 作用:每个小块保留原始元数据,适合 RAG 或上下文管理。
3. 向量存储与检索增强生成 (RAG)
- 场景:在 RAG 系统中,
Document
对象被嵌入到向量空间,用于相似性搜索。 - 示例:使用 Chroma 向量存储:
from langchain.vectorstores import Chroma from langchain.embeddings import OpenAIEmbeddings documents = [ Document(page_content="Python 是一种编程语言", metadata={"topic": "programming"}), Document(page_content="LangChain 是一个 LLM 框架", metadata={"topic": "AI"}) ] vectorstore = Chroma.from_documents(documents, OpenAIEmbeddings()) results = vectorstore.similarity_search("编程语言", k=1) # results 返回匹配的 Document 对象
- 作用:
Document
提供文本和元数据,支持高效检索。
4. 问答系统
- 场景:在 QA 链中,
Document
提供上下文,帮助 LLM 生成准确答案。 - 示例:构建一个简单的 QA 系统:
from langchain.chains import RetrievalQA from langchain.llms import OpenAI # 假设已有 vectorstore 和 documents qa_chain = RetrievalQA.from_chain_type( llm=OpenAI(), retriever=vectorstore.as_retriever() ) answer = qa_chain.run("LangChain 是什么?") print(answer)
- 作用:
Document
作为上下文来源,确保答案基于相关文档。
5. 记忆与上下文管理
- 场景:在对话系统中,
Document
可以存储历史对话或参考资料,作为记忆输入。 - 示例:将对话历史保存为
Document
:conversation_doc = Document( page_content="用户:LangChain 是什么?\nAI:LangChain 是一个 LLM 框架。", metadata={"session_id": "123", "timestamp": "2025-05-18"} )
五、示例代码:完整工作流
以下是一个结合文档加载、分割和检索的完整示例,展示 Document
类的实际应用:
from langchain_core.documents import Document
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
# 1. 创建 Document 对象
documents = [
Document(
page_content="LangChain 是一个用于构建 LLM 应用的框架,支持文档加载、分割和检索。",
metadata={"source": "langchain_docs", "category": "AI"}
),
Document(
page_content="Python 是一种简单易学的编程语言,广泛用于数据科学。",
metadata={"source": "python_docs", "category": "programming"}
)
]
# 2. 文本分割
splitter = CharacterTextSplitter(chunk_size=50, chunk_overlap=10)
split_docs = splitter.split_documents(documents)
# 3. 创建向量存储
vectorstore = Chroma.from_documents(split_docs, OpenAIEmbeddings())
# 4. 检索相关文档
query = "LLM 框架是什么?"
results = vectorstore.similarity_search(query, k=1)
for doc in results:
print(f"内容: {doc.page_content}")
print(f"元数据: {doc.metadata}")
输出示例:
内容: LangChain 是一个用于构建 LLM 应用的框架
元数据: {'source': 'langchain_docs', 'category': 'AI'}
六、注意事项与最佳实践
-
元数据设计:
- 保持元数据结构一致,例如统一
source
或category
的格式,便于检索和过滤。 - 避免在元数据中存储过大或无关的信息,以减少内存占用。
- 保持元数据结构一致,例如统一
-
使用
id
的建议:- 对于大型文档集合,建议为每个
Document
设置唯一id
(如 UUID),以便在数据库或向量存储中跟踪。 - 示例:
id=str(uuid.uuid4())
。
- 对于大型文档集合,建议为每个
-
版本兼容性:
- 在 LangChain 早期版本(如 v0.1),
Document
可能位于langchain.schema
模块,升级到新版本时注意导入路径:from langchain_core.documents import Document # 新版本
- 在 LangChain 早期版本(如 v0.1),
-
性能优化:
- 在处理大量文档时,使用批量操作(如
Chroma.from_documents
)而不是逐个处理。 - 合理设置文本分割的
chunk_size
和chunk_overlap
,以平衡检索精度和性能。
- 在处理大量文档时,使用批量操作(如
-
错误处理:
- 确保
page_content
不为空,否则会抛出异常。 - 检查元数据的键值类型,避免序列化问题(例如不可序列化的对象)。
- 确保
七、总结
langchain_core.documents.Document
类是 LangChain 框架中用于管理文档的核心工具,通过封装文本内容和元数据,支持文档加载、分割、嵌入和检索等功能。它在 RAG、问答系统和上下文管理等场景中至关重要,具有简单、灵活和高扩展性的特点。
通过理解 Document
类的属性、创建方法和应用场景,开发者可以更高效地构建 LLM 应用。无论是处理单个文档还是管理大规模文档集合,Document
都提供了可靠的基础支持。
参考资源: