Skip to content

从字符串创建LangChain文档

常见问题场景

在LangChain开发中,需要将纯文本字符串转换为Document对象进行后续处理时,常会遇到AttributeError: 'tuple' object has no attribute 'page_content'等错误。本文提供最新的解决方案和最佳实践。

问题描述

当尝试将字符串变量转换为LangChain的Document对象时,开发者常遇到以下问题:

  1. 官方文档中缺乏创建Document对象的明确指引
  2. 使用Document(page_content="text")创建后,在load_qa_chain调用中出现类型错误
  3. 运行时报错:AttributeError: 'tuple' object has no attribute 'page_content'

错误根本原因通常有两个:

  1. 过时的导入路径 - LangChain架构重构后旧导入方式失效
  2. 参数格式错误 - input_documents参数需要文档列表而非单个Document对象

最佳解决方案

方法1:使用langchain_core(推荐)

适用于LangChain v0.1.x+版本,这是目前最稳定且兼容性最好的方法:

python
# 导入最新路径的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版本可使用以下方案(不推荐新项目使用):

python
from langchain.docstore.document import Document

doc = Document(
    page_content="文本内容", 
    metadata={"source": "local"}
)

# 同样需要包装为列表格式
chain({"input_documents": [doc], "human_input": query})

关键细节

  1. 参数格式要求input_documents必须接收Document对象组成的列表,即使只有一个文档也需要使用[doc]格式
  2. 数据结构规范:每个Document对象必须包含:
    • page_content:字符串类型的文本内容
    • metadata:字典类型的元数据(至少需包含source字段)
  3. 批量处理:多个文档应采用列表存储:[doc1, doc2, doc3]

常见错误解析

错误1:AttributeError: 'tuple' object has no attribute 'page_content'

python
# 错误调用方式
chain({"input_documents": doc, ...})  # 直接传递Document对象

# 正确调用方式
chain({"input_documents": [doc], ...})  # 包装为列表

原因input_documents参数期望的是文档列表(Python list)而非单个Document

错误2:ImportError: cannot import name 'Document'

python
# LangChain v0.1.x+版本错误导入
from langchain.schema import Document  # 已废弃路径

# 应修改为
from langchain_core.documents import Document

背景:LangChain在0.1版本后重构为模块化架构,拆分出三大组件:

  • langchain-core:核心接口和文档模型
  • langchain-community:第三方集成
  • langchain:高层链式结构

高级用法

批量创建文档

当处理多段文本时,批量创建Document对象的方法:

python
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, ...})

使用文本分割器自动创建

对于长文本分割场景,更专业的处理方式:

python
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]
)

最佳实践建议

  1. 版本检查:使用pip show langchain-core确认安装版本,建议至少v0.1.11+
  2. 元数据规范:即使不使用追踪功能也应包含基本的源信息
    python
    metadata={"source": "内部生成", "created_at": "2024-03-30"}
  3. 异常处理:添加类型验证避免运行时错误
    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导入路径以避免未来兼容性问题。