You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

跨环境反序列化LangChain Document报错KeyError: '__fields_set__'求助

问题描述

我有一个结构简单的字典:

{"string1" : ['langchain_core.documents.base.Document', 'langchain_core.documents.base.Document' ...],
"string2"  : ['langchain_core.documents.base.Document', 'langchain_core.documents.base.Document' ...],
}

我在Databricks环境中对其进行pickle序列化,之后尝试在本地Docker容器环境中反序列化。目的是利用Databricks更强的计算资源预先处理文档,提升应用运行速度,避免用户等待文档转换为LangChain文档列表。

该操作曾稳定运行数月,但近期执行对应代码行时触发报错:

KeyError: '__fields_set__'
Traceback:
File "/usr/local/lib/python3.9/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 589, in _run_script
    exec(code, module.__dict__)
File "/src/frontend/pages/Chat.py", line 217, in <module>
    parsed_documents_dict_temp = pickle.load(open(file_path, "rb"))
File "/usr/local/lib/python3.9/site-packages/pydantic/v1/main.py", line 417, in __setstate__
    object_setattr(self, '__fields_set__', state['__fields_set__'])

经排查:

  • 已确认两个环境均运行Python 3.9.19,pickle.format_version均为4.0,排除版本不一致问题
  • Databricks环境内可正常反序列化,排除文件损坏问题

报错源于PyDantic,但我并未用PyDantic创建字典,猜测是PyDantic误判状态导致无法反序列化,尝试dill库也出现相同报错,求解决思路。

解决思路

1. 对齐LangChain及PyDantic版本

LangChain的Document类底层依赖PyDantic,两个环境的LangChain、PyDantic版本差异是核心诱因:

  • 执行pip freeze | grep -E "langchain-core|pydantic"分别获取Databricks和Docker环境的版本号,强制Docker环境安装与Databricks完全一致的版本
  • 注意区分PyDantic v1和v2,报错栈显示使用的是v1,需确保两边均为PyDantic v1.x系列

2. 自定义序列化/反序列化逻辑,绕过PyDantic状态问题

不直接pickle整个Document对象,而是提取其核心数据后序列化,反序列化时再重建Document:

序列化(Databricks端):

import pickle
from langchain_core.documents import Document

def serialize_docs(doc_dict):
    serialized = {}
    for key, docs in doc_dict.items():
        serialized[key] = [{"page_content": doc.page_content, "metadata": doc.metadata} for doc in docs]
    with open("docs_serialized.pkl", "wb") as f:
        pickle.dump(serialized, f)

反序列化(Docker端):

import pickle
from langchain_core.documents import Document

def deserialize_docs(file_path):
    with open(file_path, "rb") as f:
        serialized = pickle.load(f)
    doc_dict = {}
    for key, data_list in serialized.items():
        doc_dict[key] = [Document(page_content=data["page_content"], metadata=data["metadata"]) for data in data_list]
    return doc_dict

# 调用示例
parsed_documents_dict_temp = deserialize_docs(file_path)

这种方式只序列化纯Python字典,完全避开PyDantic对象的序列化兼容性问题,稳定性更高。

3. 替换pickle为更兼容的序列化方式

如果不想修改序列化逻辑,可尝试使用cloudpickle替代pickle/dill:

  • Databricks端安装cloudpickle,用cloudpickle.dump()序列化
  • Docker端安装同版本cloudpickle,用cloudpickle.load()反序列化
    cloudpickle对复杂对象的跨环境兼容性比原生pickle更好,能处理更多类结构差异场景

内容的提问来源于stack exchange,提问作者Rasputin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 03:23:14