Search code examples
fb-hydra

In hydra-python structured configs, how do you interpolate values?


I am using structured config (@dataclass-based) with hydra 1.1 and trying to interpolate some values. Specifically, I would like to set the working directory by substituting some of my config values.

I was able to do this consulting the documentation when using yaml:


run:
  dir: outputs
  name: try1

hydra:
  run:
    dir: ${run.dir}/${run.name}

How can I do this using structured configs?


Solution

  • Below is an example showing how to create a structured config that can be used to override Hydra's default output directory.

    # config.yaml
    defaults:
      - my_run_dir
      - _self_
    
    run:
      dir: outputs
      name: try1
    
    # my_app.py
    from dataclasses import dataclass
    import hydra
    from hydra.conf import RunDir
    from omegaconf import DictConfig, OmegaConf
    from hydra.core.config_store import ConfigStore
    
    cs = ConfigStore.instance()
    
    @dataclass
    class MyRunDir(RunDir):
        dir: str = "${run.dir}/${run.name}"
    
    cs.store(name="my_run_dir", node=MyRunDir, package="hydra.run")
    
    @hydra.main(config_path=".", config_name="config")
    def my_app(cfg: DictConfig) -> None:
        from hydra.core.hydra_config import HydraConfig
        assert HydraConfig.get().run.dir == "outputs/try1"
    
    if __name__ == "__main__":
        my_app()
    

    When this python file is run, the directory outputs/try1 is created.

    As an alternative to using the package="hydra.run" keyword argument to the cs.store method call, you could use an "@package" defaults list entry from config.yaml:

    # config.yaml
    defaults:
      - my_run_dir@hydra.run
    ...
    
    # my_app.py
    ...
    cs.store(name="my_run_dir", node=MyRunDir)  # omit the `package=` argument
    ...
    

    See the Hydra docs on Packages for more info on this.