If you use `@root_validator` with pre=False (the default) you MUST specify `skip_on_failure=True`

今天使用遇到一个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个版本同时使用,但尽管如此,这也是一种解决方法,可以试试

参考资料:

pydantic.errors.PydanticUserError: If you use `@root_validator`...._pydantic.errors.pydanticusererror: a non-annotated-优快云博客

2  https://github.com/run-llama/llama_index/issues/11401

3如何在不同的Pydantic版本中使用LangChain_pydantic版本如何从v2降回v1-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值