从字符串创建LangChain文档
常见问题场景
在LangChain开发中,需要将纯文本字符串转换为Document对象进行后续处理时,常会遇到AttributeError: 'tuple' object has no attribute 'page_content'
等错误。本文提供最新的解决方案和最佳实践。
问题描述
当尝试将字符串变量转换为LangChain的Document对象时,开发者常遇到以下问题:
- 官方文档中缺乏创建Document对象的明确指引
- 使用
Document(page_content="text")
创建后,在load_qa_chain
调用中出现类型错误 - 运行时报错:
AttributeError: 'tuple' object has no attribute 'page_content'
错误根本原因通常有两个:
- 过时的导入路径 - LangChain架构重构后旧导入方式失效
- 参数格式错误 -
input_documents
参数需要文档列表而非单个Document对象
最佳解决方案
方法1:使用langchain_core(推荐)
适用于LangChain v0.1.x+版本,这是目前最稳定且兼容性最好的方法:
# 导入最新路径的Document类
from langchain_core.documents import Document
# 创建Document对象
doc = Document(
page_content="这是你的文本内容",
metadata={"source": "自定义来源"}
)
# 关键步骤:传递文档列表而非单个对象
chain({"input_documents": [doc], "human_input": "你的查询问题"})
方法2:使用旧版路径(兼容方案)
如果使用的是LangChain 0.0.x版本可使用以下方案(不推荐新项目使用):
from langchain.docstore.document import Document
doc = Document(
page_content="文本内容",
metadata={"source": "local"}
)
# 同样需要包装为列表格式
chain({"input_documents": [doc], "human_input": query})
关键细节
- 参数格式要求:
input_documents
必须接收Document对象组成的列表,即使只有一个文档也需要使用[doc]
格式 - 数据结构规范:每个Document对象必须包含:
page_content
:字符串类型的文本内容metadata
:字典类型的元数据(至少需包含source
字段)
- 批量处理:多个文档应采用列表存储:
[doc1, doc2, doc3]
常见错误解析
错误1:AttributeError: 'tuple' object has no attribute 'page_content'
# 错误调用方式
chain({"input_documents": doc, ...}) # 直接传递Document对象
# 正确调用方式
chain({"input_documents": [doc], ...}) # 包装为列表
原因:input_documents
参数期望的是文档列表(Python list)而非单个Document
错误2:ImportError: cannot import name 'Document'
# LangChain v0.1.x+版本错误导入
from langchain.schema import Document # 已废弃路径
# 应修改为
from langchain_core.documents import Document
背景:LangChain在0.1版本后重构为模块化架构,拆分出三大组件:
langchain-core
:核心接口和文档模型langchain-community
:第三方集成langchain
:高层链式结构
高级用法
批量创建文档
当处理多段文本时,批量创建Document对象的方法:
from langchain_core.documents import Document
text_list = ["文本1", "文本2", "文本3"]
metadata_list = [
{"source": "来源1"},
{"source": "来源2"},
{"source": "来源3"}
]
# 确保内容和元数据数量匹配
documents = [
Document(page_content=text, metadata=meta)
for text, meta in zip(text_list, metadata_list)
]
chain({"input_documents": documents, ...})
使用文本分割器自动创建
对于长文本分割场景,更专业的处理方式:
from langchain.text_splitter import CharacterTextSplitter
from langchain_core.documents import Document
long_text = "这是一个非常长的文本..."
metadata = {"source": "长文档"}
# 初始化分割器
splitter = CharacterTextSplitter(
chunk_size=500,
chunk_overlap=50
)
# 自动分割并创建文档列表
documents = splitter.create_documents(
texts=[long_text],
metadatas=[metadata]
)
最佳实践建议
- 版本检查:使用
pip show langchain-core
确认安装版本,建议至少v0.1.11+ - 元数据规范:即使不使用追踪功能也应包含基本的源信息python
metadata={"source": "内部生成", "created_at": "2024-03-30"}
- 异常处理:添加类型验证避免运行时错误python
def validate_document(doc): if not isinstance(doc, Document): raise TypeError("输入必须是Document类型") if not isinstance(doc.page_content, str): raise ValueError("page_content必须是字符串")
注意兼容性变化
LangChain团队已宣布旧版路径(langchain.schema
)将在v0.2版本中彻底移除,新项目应始终使用langchain_core
导入路径以避免未来兼容性问题。