Hub Python Library documentation
Strict Dataclasses
Strict Dataclasses
Gói huggingface_hub cung cấp tiện ích để tạo strict dataclasses. Đây là các phiên bản nâng cao của dataclass chuẩn của Python với các tính năng xác thực bổ sung. Strict dataclasses đảm bảo rằng các trường được xác thực cả trong quá trình khởi tạo và gán giá trị, khiến chúng trở nên lý tưởng cho các kịch bản mà tính toàn vẹn của dữ liệu là yếu tố then chốt.
Tổng quan
Strict dataclasses được tạo bằng decorator @strict. Chúng mở rộng chức năng của các dataclass thông thường bằng cách:
- Xác thực kiểu trường dựa trên gợi ý kiểu
- Hỗ trợ trình xác thực tùy chỉnh cho các kiểm tra bổ sung
- Tùy chọn cho phép các đối số từ khóa tùy ý trong bộ khởi tạo
- Xác thực các trường cả khi khởi tạo và trong quá trình gán
Lợi ích
- Tính toàn vẹn dữ liệu: Đảm bảo các trường luôn chứa dữ liệu hợp lệ
- Dễ sử dụng: Tích hợp liền mạch với module
dataclasscủa Python - Tính linh hoạt: Hỗ trợ các trình xác thực tùy chỉnh cho logic xác thực phức tạp
- Nhẹ: Không yêu cầu các phụ thuộc bổ sung như Pydantic, attrs hoặc các thư viện tương tự
Cách sử dụng
Ví dụ cơ bản
from dataclasses import dataclass
from huggingface_hub.dataclasses import strict, as_validated_field
# Custom validator to ensure a value is positive
@as_validated_field
def positive_int(value: int):
if not value > 0:
raise ValueError(f"Value must be positive, got {value}")
@strict
@dataclass
class Config:
model_type: str
hidden_size: int = positive_int(default=16)
vocab_size: int = 32 # Default value
# Methods named `validate_xxx` are treated as class-wise validators
def validate_big_enough_vocab(self):
if self.vocab_size < self.hidden_size:
raise ValueError(f"vocab_size ({self.vocab_size}) must be greater than hidden_size ({self.hidden_size})")Các trường được xác thực trong quá trình khởi tạo:
config = Config(model_type="bert", hidden_size=24) # Valid
config = Config(model_type="bert", hidden_size=-1) # Raises StrictDataclassFieldValidationErrorSự nhất quán giữa các trường cũng được xác thực trong quá trình khởi tạo (xác thực theo lớp):
# `vocab_size` too small compared to `hidden_size`
config = Config(model_type="bert", hidden_size=32, vocab_size=16) # Raises StrictDataclassClassValidationErrorCác trường cũng được xác thực trong quá trình gán:
config.hidden_size = 512 # Valid
config.hidden_size = -1 # Raises StrictDataclassFieldValidationErrorĐể chạy lại xác thực cho toàn bộ lớp sau khi gán, bạn phải gọi .validate một cách tường minh:
config.validate() # Runs all class validatorsTrình xác thực tùy chỉnh
Bạn có thể gắn nhiều bộ xác thực tùy chỉnh vào các trường bằng cách sử dụng validated_field. Một bộ xác thực là một hàm có thể gọi nhận một đối số duy nhất và ném ngoại lệ nếu giá trị không hợp lệ.
from dataclasses import dataclass
from huggingface_hub.dataclasses import strict, validated_field
def multiple_of_64(value: int):
if value % 64 != 0:
raise ValueError(f"Value must be a multiple of 64, got {value}")
@strict
@dataclass
class Config:
hidden_size: int = validated_field(validator=[positive_int, multiple_of_64])Trong ví dụ này, cả hai bộ xác thực đều được áp dụng cho trường hidden_size.
Các đối số từ khóa bổ sung
Mặc định, strict dataclasses chỉ chấp nhận các trường được định nghĩa trong lớp. Bạn có thể cho phép các đối số từ khóa bổ sung bằng cách đặt accept_kwargs=True trong bộ trang trí @strict.
from dataclasses import dataclass
from huggingface_hub.dataclasses import strict
@strict(accept_kwargs=True)
@dataclass
class ConfigWithKwargs:
model_type: str
vocab_size: int = 16
config = ConfigWithKwargs(model_type="bert", vocab_size=30000, extra_field="extra_value")
print(config) # ConfigWithKwargs(model_type='bert', vocab_size=30000, *extra_field='extra_value')Các đối số từ khóa bổ sung xuất hiện trong biểu diễn chuỗi của dataclass nhưng được thêm tiền tố * để nhấn mạnh rằng chúng không được kiểm tra.
Tích hợp với Type Hints
Strict dataclasses tuân thủ các type hints và tự động kiểm tra chúng. Ví dụ:
from typing import List
from dataclasses import dataclass
from huggingface_hub.dataclasses import strict
@strict
@dataclass
class Config:
layers: List[int]
config = Config(layers=[64, 128]) # Valid
config = Config(layers="not_a_list") # Raises StrictDataclassFieldValidationErrorCác kiểu được hỗ trợ bao gồm:
- Bất kỳ
- Union
- Tùy chọn
- Literal
- Danh sách
- Dict
- Tuple
- Đặt
Và bất kỳ sự kết hợp nào của các kiểu này. Nếu bạn cần xác thực kiểu phức tạp hơn, bạn có thể thực hiện thông qua một bộ xác thực tùy chỉnh.
Trình xác thực lớp
Các phương thức có tên validate_xxx được coi là bộ xác thực lớp. Các phương thức này chỉ được phép nhận self làm đối số. Bộ xác thực lớp được chạy một lần trong quá trình khởi tạo, ngay sau __post_init__. Bạn có thể định nghĩa bao nhiêu bộ xác thực như vậy cũng được—chúng sẽ được thực thi tuần tự theo thứ tự xuất hiện.
Lưu ý rằng các bộ xác thực lớp (class validators) không được tự động chạy lại khi một trường được cập nhật sau khi khởi tạo. Để xác thực lại đối tượng thủ công, bạn cần gọi obj.validate().
from dataclasses import dataclass
from huggingface_hub.dataclasses import strict
@strict
@dataclass
class Config:
foo: str
foo_length: int
upper_case: bool = False
def validate_foo_length(self):
if len(self.foo) != self.foo_length:
raise ValueError(f"foo must be {self.foo_length} characters long, got {len(self.foo)}")
def validate_foo_casing(self):
if self.upper_case and self.foo.upper() != self.foo:
raise ValueError(f"foo must be uppercase, got {self.foo}")
config = Config(foo="bar", foo_length=3) # ok
config.upper_case = True
config.validate() # Raises StrictDataclassClassValidationError
Config(foo="abcd", foo_length=3) # Raises StrictDataclassFieldValidationError
Config(foo="Bar", foo_length=3, upper_case=True) # Raises StrictDataclassFieldValidationErrorPhương thức
.validate()là một tên được dành riêng cho các dataclass nghiêm ngặt. Để ngăn chặn các hành vi không mong muốn, một lỗiStrictDataclassDefinitionErrorsẽ được ném ra nếu lớp của bạn đã định nghĩa phương thức này.
Tham khảo API
@strict
Trình trang trí @strict tăng cường cho một dataclass với tính năng xác thực nghiêm ngặt.
huggingface_hub.dataclasses.strict
< source >( accept_kwargs: bool = False )
Trình trang trí để thêm xác thực nghiêm ngặt vào một dataclass.
Trình trang trí này phải được sử dụng phía trên @dataclass để đảm bảo các IDE và công cụ kiểm tra kiểu tĩnh nhận diện lớp đó là một dataclass.
Có thể được sử dụng có hoặc không có đối số:
@strict@strict(accept_kwargs=True)
Ví dụ:
>>> from dataclasses import dataclass
>>> from huggingface_hub.dataclasses import as_validated_field, strict, validated_field
>>> @as_validated_field
>>> def positive_int(value: int):
... if not value >= 0:
... raise ValueError(f"Value must be positive, got {value}")
>>> @strict(accept_kwargs=True)
... @dataclass
... class User:
... name: str
... age: int = positive_int(default=10)
# Initialize
>>> User(name="John")
User(name='John', age=10)
# Extra kwargs are accepted
>>> User(name="John", age=30, lastname="Doe")
User(name='John', age=30, *lastname='Doe')
# Invalid type => raises
>>> User(name="John", age="30")
huggingface_hub.errors.StrictDataclassFieldValidationError: Validation error for field 'age':
TypeError: Field 'age' expected int, got str (value: '30')
# Invalid value => raises
>>> User(name="John", age=-1)
huggingface_hub.errors.StrictDataclassFieldValidationError: Validation error for field 'age':
ValueError: Value must be positive, got -1validate_typed_dict
Phương thức để xác minh rằng một từ điển tuân thủ các kiểu được định nghĩa trong lớp TypedDict.
Đây là tương đương của việc xác thực dataclass nhưng dành cho TypedDict. Vì typed dict không bao giờ được khởi tạo (chỉ được sử dụng bởi trình kiểm tra kiểu tĩnh), bước xác thực phải được gọi thủ công.
huggingface_hub.dataclasses.validate_typed_dict
< source >( schema: typedata: dict )
Kiểm tra xem một từ điển có tuân thủ các kiểu được định nghĩa trong lớp TypedDict hay không.
Bên trong, typed dict được chuyển đổi thành một dataclass nghiêm ngặt và được xác thực bằng decorator @strict.
Ví dụ:
>>> from typing import Annotated, TypedDict
>>> from huggingface_hub.dataclasses import validate_typed_dict
>>> def positive_int(value: int):
... if not value >= 0:
... raise ValueError(f"Value must be positive, got {value}")
>>> class User(TypedDict):
... name: str
... age: Annotated[int, positive_int]
>>> # Valid data
>>> validate_typed_dict(User, {"name": "John", "age": 30})
>>> # Invalid type for age
>>> validate_typed_dict(User, {"name": "John", "age": "30"})
huggingface_hub.errors.StrictDataclassFieldValidationError: Validation error for field 'age':
TypeError: Field 'age' expected int, got str (value: '30')
>>> # Invalid value for age
>>> validate_typed_dict(User, {"name": "John", "age": -1})
huggingface_hub.errors.StrictDataclassFieldValidationError: Validation error for field 'age':
ValueError: Value must be positive, got -1as_validated_field
Decorator để tạo một validated_field. Được khuyến nghị cho các trường có một validator duy nhất để tránh mã lặp lại.
huggingface_hub.dataclasses.as_validated_field
< source >( validator: Callable )
Trang trí một hàm validator như một validated_field (tức là một trường dataclass có validator tùy chỉnh).
validated_field
Tạo một trường dataclass với xác thực tùy chỉnh.
huggingface_hub.dataclasses.validated_field
< source >( validator: list[collections.abc.Callable[[typing.Any], None]] | collections.abc.Callable[[typing.Any], None]default: typing.Any = <dataclasses._MISSING_TYPE object at 0x7f9675fda620>default_factory: typing.Any = <dataclasses._MISSING_TYPE object at 0x7f9675fda620>init: bool = Truerepr: bool = Truehash: bool | None = Nonecompare: bool = Truemetadata: dict | None = None**kwargs: typing.Any )
Tạo một trường dataclass với bộ xác thực tùy chỉnh.
Có ích khi áp dụng nhiều kiểm tra cho một trường. Nếu chỉ áp dụng một quy tắc, hãy xem trang trí as_validated_field.
Lỗi
Ngoại lệ cơ bản cho các dataclass nghiêm ngặt.
Lỗi ngoại lệ được ném ra khi một dataclass nghiêm ngặt được định nghĩa không chính xác.
lớp huggingface_hub.errors.StrictDataclassFieldValidationError
< source >( field: strcause: Exception )
Ngoại lệ được ném ra khi một dataclass nghiêm ngặt không vượt qua kiểm tra xác thực cho một trường nhất định.
Tại sao không dùng pydantic? (hay attrs? hay marshmallow_dataclass?)
- Xem thảo luận tại https://github.com/huggingface/transformers/issues/36329 về việc thêm Pydantic làm một dependency. Đây sẽ là một bổ sung nặng và đòi hỏi logic cẩn thận để hỗ trợ cả v1 và v2.
- Chúng ta không cần hầu hết các tính năng của Pydantic, đặc biệt là những tính năng liên quan đến chuyển đổi kiểu tự động, jsonschema, chuỗi hóa, alias, v.v.
- Chúng ta không cần khả năng khởi tạo một lớp từ một từ điển.
- Chúng ta không muốn thay đổi dữ liệu. Trong
@strict, “validation” có nghĩa là “kiểm tra xem một giá trị có hợp lệ hay không.” Trong Pydantic, “validation” có nghĩa là “chuyển đổi kiểu một giá trị, có thể làm thay đổi nó, rồi sau đó kiểm tra xem nó có hợp lệ hay không.” - Chúng ta không cần kiểm tra cực kỳ nhanh.
@strictkhông được thiết kế cho các tải nặng mà hiệu suất là yếu tố then chốt. Các trường hợp sử dụng phổ biến bao gồm kiểm tra cấu hình mô hình (được thực hiện một lần và không đáng kể so với việc chạy mô hình). Điều này cho phép chúng ta giữ mã ở mức tối giản.