Combining Statically-Defined and Dynamically-Generated Configurations#

hydra-zen provides a decorator, hydrated_dataclass(), which is similar to dataclasses.dataclass(). It can be used to dynamically auto-populate configuration parameters, à la builds(). However, it also enables users to define a config such that its attributes are statically available to various tools, like type-checkers and IDEs.

E.g. in the following codeblock, we will use @hydrated_dataclass to create a frozen (i.e. immutable) config, which is designed to partially configure the class torch.optim.Adam. Here, static tooling can “see” the types associated with the configured fields, and flag bad inputs in our code. That this config is immutable is also salient to static analysis.

from hydra_zen import hydrated_dataclass

from torch.optim import Adam  # type: ignore

@hydrated_dataclass(target=Adam, zen_partial=True, frozen=True)
class BuildsAdam:
    lr: float = 0.01
    momentum: float = 0.9

# static type-checker flags as invalid (invalid type)
BuildsAdam(lr="a string")  # type: ignore

conf = BuildsAdam()
# static type-checker flags as invalid (mutating "frozen" dataclass)
conf.lr = 10.0  # type: ignore
>>> from hydra_zen import instantiate
>>> instantiate(BuildsAdam)
functools.partial(<class Adam>, lr=0.01, momentum=0.9)

Note that we did not need to specify Hydra-specific fields like _target_: the decorator handled this for us. Furthermore, we also benefit from the additional runtime validation capabilities that builds() provides; e.g. the following code will raise an error during the creation of BuildsAdam because the field name momentum was misspelled.

# @hydrated_dataclass will catch the misspelled parameter name
# and will raise a TypeError

@hydrated_dataclass(target=Adam)
class BuildsAdam:
    momtum: float = 0.9  # <- typo causes TypeError upon constructing config

This means that our config is validated upon construction: we will identify this error before we launch our Hydra job.

Note that the @hydrated_dataclass decorator uses a recently proposed mechanism for enabling static tools to “recognize” third-party dataclass decorators like this one. Presently, the above static inspection is only supported by pyright, but other type-checkers will likely add support for this soon.