01 问题情景
最近在做Langchain的开发,可能是因为我更新了依赖库的版本,在执行下面这部分代码的时候出现了该异常:
# 出现该异常的代码(仅保留核心逻辑)
from langchain.output_parsers import PydanticOutputParser
from pydantic import BaseModel
class Data(BaseModel):
...
def my_func(...):
...
# 创建了一个输出解析器 此行是报错的位置
parser = PydanticOutputParser(pydantic_object=Data)
...
02 分析问题
报错的内容是:
...
pydantic.v1.error_wrappers.ValidationError: 1 validation error for PydanticOutputParser
pydantic_object
subclass of BaseModel expected (type=type_error.subclass; expected_class=BaseModel)
该信息提示,预期传入的是BaseModel
类的子类,说我没有传对类型。
可是我传递的Data
分明是继承了BaseModel
类的子类,不应该呀。
03 阅读源码
于是我开始去源码中寻找答案:
# 源码节选
from langchain_core.pydantic_v1 import BaseModel
class PydanticOutputParser(JsonOutputParser):
"""Parse an output using a pydantic model."""
pydantic_object: Type[BaseModel]
...
从Type[BaseModel]
来看,我的传递方式确实没有写错,问题出在源码中导包的部分
源码写法:from langchain_core.pydantic_v1 import BaseModel
我的写法:from pydantic import BaseModel
恍然大悟!
原来是版本不兼容惹得祸,为了证实这一点,我在命令行使用pip list
命令查看pydantic
的版本,发现版本是2.x.x
,而源码中导入的是1.x.x
,版本是不兼容的!
04 解决方案
4.1 方案1 - 指定版本安装
这也是网上很多人给出的解决方案,即在requirements.txt
中指定pydantic==1.10.3
。
但我并不太推荐,因为我的项目其他地方也用到了pydantic,那边依赖的是2.x
的版本,这一换就全换了。
而且使用老旧的版本心里总觉得有点不舒服。
4.2 (通用)方案2 - 指定v1版本
在不替换原有的2.x
版本的情况下 ,pydantic为我们提供了兼容的选项,只需要在我们自己的项目中采用如下方式导包即可:
# 原来的导包方式
from pydantic import BaseModel
# 改成下面这种导包方式
from pydantic.v1 import BaseModel
4.3 (推荐)方案3 - 参考源码
在我的项目中,完全可以看源码中的导包方式,我只需要复制粘贴就可以了,这种方式最为稳妥。
# 将我的导包方式改成和源码一致
from langchain_core.pydantic_v1 import BaseModel
(完)