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

使用Pydantic与typing.Protocol时遇架构生成错误,求解决

解决Pydantic与typing.Protocol联用的Schema生成错误

错误原因

Pydantic默认无法为typing.Protocol类型生成核心schema,因为Protocol是用于静态类型检查的结构契约,它定义的是对象需要满足的接口,而非可直接序列化/反序列化的具体类型。Pydantic无法自动推断这类抽象类型的序列化规则,因此抛出PydanticSchemaGenerationError。

解决方案

方案1:启用arbitrary_types_allowed(快速解决)

通过模型配置允许任意类型,让Pydantic跳过对Protocol字段的schema生成,转而依赖@runtime_checkable装饰器提供的运行时类型检查。

from typing import TypeVar, Protocol, Generic, runtime_checkable
from pydantic import BaseModel

D = TypeVar('D')


@runtime_checkable
class SupportsDimensionality(Protocol[D]):
    dimensionality: D


class ValueModel(BaseModel, Generic[D]):
    value: SupportsDimensionality[D]
    
    model_config = {"arbitrary_types_allowed": True}

注意:此方法的局限性是Pydantic不会自动处理value字段的序列化/反序列化,需要确保传入的对象本身可被序列化,或自行实现序列化逻辑。

方案2:为Protocol实现自定义Pydantic Schema(完全支持)

如果需要Pydantic完全支持Protocol的验证与序列化,可以实现__get_pydantic_core_schema__方法,手动定义schema规则。

from typing import TypeVar, Protocol, Generic, runtime_checkable, Any
from pydantic import BaseModel, GetCoreSchemaHandler
from pydantic_core import core_schema

D = TypeVar('D')


@runtime_checkable
class SupportsDimensionality(Protocol[D]):
    dimensionality: D

    @classmethod
    def __get_pydantic_core_schema__(cls, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:
        # 处理泛型参数D的schema
        d_schema = handler(D)
        # 验证规则:检查对象符合Protocol契约
        validate_rule = core_schema.is_instance_of(cls)
        # 序列化规则:提取dimensionality字段
        serialize_rule = core_schema.plain_serializer_function_ser_schema(
            lambda obj: {"dimensionality": obj.dimensionality}
        )
        # 支持从字典反序列化生成符合Protocol的对象
        deserialize_rule = core_schema.general_plain_validator_function(
            lambda value, info: type('TempDimensional', (), {"dimensionality": value['dimensionality']})() 
            if isinstance(value, dict) else value
        )
        
        return core_schema.union_schema(
            [validate_rule, deserialize_rule],
            serialization=serialize_rule
        )


class ValueModel(BaseModel, Generic[D]):
    value: SupportsDimensionality[D]

说明:这个方案让Pydantic完全理解Protocol的结构,既能验证输入是否符合契约,也能正确完成序列化/反序列化,但需要熟悉Pydantic Core的schema系统。

方案3:用具体Pydantic模型结合Protocol(推荐)

如果你的Protocol实现类本身是Pydantic模型,可以直接定义一个基础模型来实现Protocol契约,这样既满足静态类型检查,又能让Pydantic自动生成schema。

from typing import TypeVar, Protocol, Generic, runtime_checkable
from pydantic import BaseModel

D = TypeVar('D')


@runtime_checkable
class SupportsDimensionality(Protocol[D]):
    dimensionality: D


# 实现Protocol的具体Pydantic模型
class DimensionalBaseModel(BaseModel, Generic[D]):
    dimensionality: D


class ValueModel(BaseModel, Generic[D]):
    value: DimensionalBaseModel[D]

优势:这种方式完全贴合Pydantic的设计思路,无需额外配置,同时保留了Protocol带来的静态类型检查能力,是最常用的实践方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 04:35:33