今天使用遇到一个pydantic 包的错误
File "/home/ubuntu/anaconda3/envs/**/lib/python3.10/site-packages/langchain/schema.py", line 140, in ChatGeneration
def set_text(cls, values: Dict[str, Any]) -> Dict[str, Any]:
File "/home/ubuntu/anaconda3/envs/**/lib/python3.10/site-packages/pydantic/deprecated/class_validators.py", line 222, in root_validator
return root_validator()(*__args) # type: ignore
File "/home/ubuntu/anaconda3/envs/**/lib/python3.10/site-packages/pydantic/deprecated/class_validators.py", line 228, in root_validator
raise PydanticUserError(
pydantic.errors.PydanticUserError: If you use `@root_validator` with pre=False (the default) you MUST specify `skip_on_failure=True`. Note that `@root_validator` is deprecated and should be replaced with `@model_validator`.
环境,python 3.10,pydantic 版本2.1.0,按照参考资料1 的说法,降低版本至1.10.x,但是整个程序(不是上面那一行)又会报如下这个错误
ImportError: cannot import name 'BeforeValidator' from 'pydantic' (/home/ubuntu/anaconda3/envs/memory/**/lib/python3.10/site-packages/pydantic/__init__.cpython-310-x86_64-linux-gnu.so)
而这个包BeforeValidator 只有在2.0以上才会有,所以两个版本都不行,那就改其中一个源码吧
第一个错误是使用langchain,版本0.0.144
from langchain.llms import AzureOpenAI,OpenAIChat
此语句调用底层langchain/scheam.py, 如下的相关行
from abc import ABC, abstractmethod
from typing import Any, Dict, Generic, List, NamedTuple, Optional, TypeVar, Union
from pydantic import BaseModel, Extra, Field, root_validator
class Generation(BaseModel):
"""Output of a single generation."""
text: str
"""Generated text output."""
generation_info: Optional[Dict[str, Any]] = None
"""Raw generation info response from the provider"""
"""May include things like reason for finishing (e.g. in OpenAI)"""
# TODO: add log probs
class ChatGeneration(Generation):
"""Output of a single generation."""
text = ""
message: BaseMessage
@root_validator
def set_text(cls, values: Dict[str, Any]) -> Dict[str, Any]:
values["text"] = values["message"].content
return values
可以看到在类子类ChatGeneration中声明了一个装时器函数set_text,使用装饰器root_validator进行修饰的,而root_validator 在2.0版本以上已经属于deprecated,而且要求传参skip_on_failure=True才可以执行
root_validator的源码在**/pydantic/deprecated/class_validators.py里
def root_validator(
*__args,
pre: bool = False,
skip_on_failure: bool = False,
allow_reuse: bool = False,
) -> Any:
"""Decorate methods on a model indicating that they should be used to validate (and perhaps
modify) data either before or after standard model parsing/validation is performed.
Args:
pre (bool, optional): Whether this validator should be called before the standard
validators (else after). Defaults to False.
skip_on_failure (bool, optional): Whether to stop validation and return as soon as a
failure is encountered. Defaults to False.
allow_reuse (bool, optional): Whether to track and raise an error if another validator
refers to the decorated function. Defaults to False.
Returns:
Any: A decorator that can be used to decorate a function to be used as a root_validator.
"""
warn(
'Pydantic V1 style `@root_validator` validators are deprecated.'
' You should migrate to Pydantic V2 style `@model_validator` validators,'
' see the migration guide for more details',
DeprecationWarning,
stacklevel=2,
)
if __args:
# Ensure a nice error is raised if someone attempts to use the bare decorator
return root_validator()(*__args) # type: ignore
if allow_reuse is True: # pragma: no cover
warn(_ALLOW_REUSE_WARNING_MESSAGE, DeprecationWarning)
mode: Literal['before', 'after'] = 'before' if pre is True else 'after'
if pre is False and skip_on_failure is not True:
raise PydanticUserError(
'If you use `@root_validator` with pre=False (the default) you MUST specify `skip_on_failure=True`.'
' Note that `@root_validator` is deprecated and should be replaced with `@model_validator`.',
code='root-validator-pre-skip',
)
wrap = partial(_decorators_v1.make_v1_generic_root_validator, pre=pre)
可以看到源码root_validator有多个入参,也可以看到报错的真正原因:pre为False 且skip_on_failure 也是False,pre 默认为False,skip_on_failure默认也是False ,所以报错
那么修改其中1个参数skip_on_failure,更改为True,在ChatGeneration的修饰器 @root_validator添加参数,修改为 @root_validator(skip_on_failure=True)
然后运行,报如下错误:
File "/home/ubuntu/anaconda3/envs/**/lib/python3.10/site-packages/pydantic/_internal/_model_construction.py", line 98, in __new__
private_attributes = inspect_namespace(
File "/home/ubuntu/anaconda3/envs/**/lib/python3.10/site-packages/pydantic/_internal/_model_construction.py", line 337, in inspect_namespace
raise PydanticUserError(
pydantic.errors.PydanticUserError: Field 'text' defined on a base class was overridden by a non-annotated attribute. All field definitions, including overrides, require a type annotation.
这个ChatGeneration 有个元素是text,它也要有类型约束,那就添加类型约束,改为
text :str = ""
然后又报错:
name = Field(default="", const=True)
File "/home/ubuntu/anaconda3/envs/**/lib/python3.10/site-packages/pydantic/fields.py", line 741, in Field
raise PydanticUserError('`const` is removed, use `Literal` instead', code='removed-kwargs')
pydantic.errors.PydanticUserError: `const` is removed, use `Literal` instead
然后再修改const 为Literal ,不过后面也报了不少错误,原因是2.0在1。0版本上做了很大改动,所以不建议在2.0版本直接进行修改,看了参考资料2 和3后,具体的解决方法如下:
当pydantic 只需要1.0版本即可满足要求时,果断从2.x的版本降为1.0的版本
但如果1.0版本和2.0版本都需要使用时,则需要安装2.0以上的版本,同时在使用1.0版本的程序或者源码上,添加pydantic.v1,如原语句from pydantic import Extra, root_validator,则需要改为from pydantic.v1 import Extra, root_validator,不过这个工作量可能很大,比较容易出错,最好的办法是避免2个版本同时使用,但尽管如此,这也是一种解决方法,可以试试
参考资料: