Skip to main content
Reactor allows YAML files for configuration. The configuration schema is completely up to you: you define whatever parameters your model needs. Reactor loads the YAML, merges any CLI overrides, and passes the result to your model’s constructor as a DictConfig object.

Quick Start

# Run with config from @model decorator
reactor run

# Run with a specific config file
reactor run -c configs/my_config.yaml

# Override a single value from CLI
reactor run --model.fps=60

# Combine: load config file + override specific values
reactor run -c configs/base.yaml --model.num_steps=10 --model.use_cache=false
Throughout this page, we omit the --runtime argument for brevity. In practice, you will typically run reactor run --runtime http ... for local development. See Model Instancing for details on running your model.

How Configuration Flows to Your Model

Configuration passes through several stages before reaching your model:
  1. The CLI reads the config field from the @model decorator (or uses the -c flag if provided)
  2. The YAML file is loaded
  3. Any --model.* CLI overrides are merged on top
  4. The final DictConfig is passed to your model’s __init__
EDITOR: Add diagram showing configuration flow from @model decorator and CLI flags through OmegaConf merge to the model constructor.

Configuration Files (YAML)

Configuration files are standard YAML files. They can contain any structure your model expects:
# configs/default.yaml

# Basic parameters
fps: 30
height: 480
width: 832
seed: 1

# Nested configuration
model_kwargs:
  local_attn_size: 12
  timestep_shift: 5.0
  sink_size: 3

# Lists
denoising_step_list:
  - 1000
  - 750
  - 500
  - 250

# Paths (relative to working directory)
generator_ckpt: models/longlive_base.pt
lora_ckpt: models/lora.pt
The YAML file is parsed by OmegaConf, which supports advanced features like:
  • Variable interpolation: output_path: ${model_name}/outputs
  • Environment variables: api_key: ${oc.env:API_KEY}

Specifying a Config File

In the @model Decorator

Set a default config file in your decorator:
@model(name="my-model", config="configs/default.yaml")
class MyVideoModel(VideoModel):
    ...
When you run reactor run without the -c flag, the runtime loads this file. If no config field is specified in the decorator, the model receives an empty configuration.

With the -c Flag

Use -c or --config to specify a config file explicitly:
reactor run -c configs/high_quality.yaml
reactor run --config configs/experimental.yaml
When you specify -c, it takes precedence over the config field in the @model decorator. This lets you switch between configurations without modifying your code:
# Use the fast config for development
reactor run -c configs/fast.yaml

# Use the high-quality config for production
reactor run -c configs/high_quality.yaml

CLI Overrides with --model.*

You can override any configuration value from the command line using the --model. prefix:
reactor run --model.fps=60 --model.seed=42
For nested values, use dot notation:
reactor run --model.model_kwargs.timestep_shift=3.0
Overrides are merged on top of the configuration file, so you can load a base config and tweak specific values:
reactor run -c configs/base.yaml --model.num_steps=20 --model.use_cache=true

Type Handling

OmegaConf automatically infers types from the values you provide:
CLI ValueInterpreted Type
--model.fps=30int
--model.scale=1.5float
--model.enabled=truebool
--model.enabled=falsebool
--model.name=my-modelstr
--model.path=/tmp/outstr
For strings that look like numbers or booleans, quote them:
reactor run --model.version="1.0"  # string, not float

Configuration Priority

When multiple sources provide configuration, they are merged in this order (later sources override earlier ones):
  1. @model decorator config field: Base configuration from the file specified in the decorator
  2. -c flag: Replaces the decorator config entirely if provided
  3. --model.* overrides: Applied on top of whichever config file was loaded

Example Scenarios

Scenario 1: Decorator config only
reactor run
# Loads: @model(config="configs/default.yaml") -> configs/default.yaml
Scenario 2: -c flag overrides decorator
reactor run -c configs/fast.yaml
# Loads: configs/fast.yaml (ignores decorator's config field)
Scenario 3: CLI overrides on top of file
reactor run -c configs/base.yaml --model.fps=60
# Loads: configs/base.yaml, then overrides fps=60
Scenario 4: CLI overrides with no config file
reactor run --model.fps=60 --model.seed=42
# Creates config from CLI overrides only: {fps: 60, seed: 42}
This last scenario is useful for simple models that only need a few parameters.

Accessing Configuration in Your Model

Your model’s __init__ method receives the merged configuration as a DictConfig. There are two approaches: typed parsing (recommended) or direct access. Define a dataclass that describes your expected configuration schema. This gives you autocompletion, type checking, and validation in one place:
from dataclasses import dataclass, field
from typing import Optional, List
from omegaconf import DictConfig, OmegaConf
from reactor_runtime import VideoModel

@dataclass
class ModelConfig:
    """Configuration schema for MyVideoModel."""
    fps: int = 30
    height: int = 480
    width: int = 832
    seed: Optional[int] = None
    num_steps: int = 5
    use_cache: bool = True
    denoising_steps: List[int] = field(default_factory=lambda: [1000, 750, 500, 250])

class MyVideoModel(VideoModel):
    def __init__(self, config: DictConfig):
        # Parse DictConfig into typed dataclass
        self.cfg: ModelConfig = OmegaConf.structured(ModelConfig)
        self.cfg = OmegaConf.merge(self.cfg, config)

        # Now you have full type safety and IDE autocompletion
        self._fps = self.cfg.fps           # int, guaranteed
        self._height = self.cfg.height     # int, guaranteed
        self._seed = self.cfg.seed         # Optional[int]
You can also use Pydantic for more advanced validation:
from pydantic import BaseModel, Field
from omegaconf import DictConfig, OmegaConf

class ModelConfig(BaseModel):
    """Configuration schema with Pydantic validation."""
    fps: int = Field(default=30, ge=1, le=120, description="Frames per second")
    height: int = Field(default=480, ge=64, description="Output height in pixels")
    width: int = Field(default=832, ge=64, description="Output width in pixels")
    num_steps: int = Field(default=5, ge=1, le=100, description="Denoising steps")
    cfg_scale: float = Field(default=7.5, ge=1.0, le=20.0, description="Guidance scale")

class MyVideoModel(VideoModel):
    def __init__(self, config: DictConfig):
        # Convert DictConfig to dict, then validate with Pydantic
        raw_dict = OmegaConf.to_container(config, resolve=True)
        self.cfg = ModelConfig(**raw_dict)

        # Full validation happens automatically
        self._fps = self.cfg.fps
        self._num_steps = self.cfg.num_steps

Alternative: Direct Access with .get()

For simpler models or rapid prototyping, you can access values directly:
class MyVideoModel(VideoModel):
    def __init__(self, config: DictConfig):
        # Safe access with defaults using .get()
        self._fps = config.get("fps", 30)
        self._seed = config.get("seed", None)

        # Dot-access (raises ConfigAttributeError if missing)
        self._height = config.height
        self._width = config.width

        # Access nested values
        self._timestep_shift = config.model_kwargs.timestep_shift

        # Check if a key exists
        if "lora_ckpt" in config:
            self._load_lora(config.lora_ckpt)

DictConfig Tips

The DictConfig object from OmegaConf behaves like a dictionary but also supports:
# Dot-access (attribute style)
config.fps  # Same as config["fps"]

# Safe access with defaults
config.get("missing_key", "default_value")

# Check existence
"fps" in config  # True/False

# Convert to plain dict if needed
plain_dict = OmegaConf.to_container(config, resolve=True)

# Convert to YAML string (for logging)
from omegaconf import OmegaConf
print(OmegaConf.to_yaml(config))
Use the typed dataclass or Pydantic approach for any model you plan to maintain long-term. It provides IDE autocompletion, catches typos at startup, documents your configuration schema in code, and makes refactoring safer. The direct .get() approach is fine for quick experiments but becomes error-prone as your config grows.

Inspecting Available Configuration Options

Use --config-help to see all available parameters in a config file and their current values:
reactor run -c configs/default.yaml --config-help
Output:
Model configuration options from: configs/default.yaml
============================================================

Available parameters (override with --model.<key>=<value>):

  --model.fps=30
      Type: int, Default: 30

  --model.height=480
      Type: int, Default: 480

  --model.model_kwargs.timestep_shift=5.0
      Type: float, Default: 5.0

  ...
============================================================
This helps you discover what options are available and how to override them.

Best Practices

Use a Base Config in the @model Decorator

Always specify a default configuration in your decorator so reactor run works out of the box:
@model(name="my-model", config="configs/default.yaml")
class MyVideoModel(VideoModel):
    ...

Create Multiple Config Variants

Keep different configurations for different use cases:
configs/
├── default.yaml      # Balanced defaults
├── fast.yaml         # Lower quality, faster inference
├── high_quality.yaml # Higher quality, slower inference
└── debug.yaml        # Verbose logging, small batches

Use CLI Overrides for Experiments

Do not create a new config file for every experiment. Use CLI overrides:
# Quick iteration on a parameter
reactor run -c configs/base.yaml --model.num_steps=5
reactor run -c configs/base.yaml --model.num_steps=10
reactor run -c configs/base.yaml --model.num_steps=20

Document Your YAML Files

Add comments to your YAML files for users who edit them directly:
# Number of denoising steps. Higher = better quality, slower.
# Recommended: 4-8 for real-time, 20+ for offline rendering.
num_steps: 5

# Classifier-free guidance scale. Higher = more prompt adherence.
# Range: 1.0 (no guidance) to 15.0 (strong guidance)
cfg_scale: 7.5

Fail Fast with Clear Errors

If not using Pydantic validation, check required fields and constraints early:
def __init__(self, config: DictConfig):
    if "model_path" not in config:
        raise ValueError(
            "Config missing required 'model_path'. "
            "Add it to your config file or pass --model.model_path=<path>"
        )

    self._num_steps = config.get("num_steps", 5)
    if self._num_steps < 1:
        raise ValueError(f"num_steps must be >= 1, got {self._num_steps}")
With Pydantic, this validation happens automatically when you instantiate the config model.

Common Issues

Config File Not Found

Error loading config file 'configs/default.yaml': [Errno 2] No such file or directory
Solution: Paths in the @model decorator are relative to the model file’s directory. Make sure the config file exists at the specified path.

Unknown Configuration Key

If your model crashes because of an unexpected key, it means the YAML file contains parameters the model does not use. Either:
  1. Remove unused keys from the YAML file
  2. Use config.get() with defaults instead of direct access

Type Mismatch

ValueError: expected int, got str
Solution: YAML infers types automatically. If a value like version: 1.0 is being read as float when you need a string, quote it: version: "1.0"

CLI Reference

ArgumentDescription
-c, --configPath to YAML config file. Overrides the @model decorator’s config field
--config-helpShow all config options from the specified config file and exit
--model.<key>=<value>Override a specific config value. Can be repeated

Environment Variables in Config

OmegaConf supports environment variable interpolation:
# configs/production.yaml
api_key: ${oc.env:MY_API_KEY}
output_dir: ${oc.env:OUTPUT_DIR,/tmp/output} # with default