strataconf

Config

Class to load and manage configuration data from a YAML file.

To retrieve nested values, use a dot-separated key. For instance, config.get('prompts.main') will return the value of the ‘main’ key under the ‘prompts’ key. If the key does not exist, None is returned.

To reference other values in the config file using the ${key} syntax. For instance, if the criteria key has the value "only words", then the key prompt with the value "Search for ${criteria}" resolves to "Search for only words".

If you want to provide a default value if a key doesn’t exist, use the select resolver within a reference. For instance, ${select:criteria,everything} will resolve to "everything" if the criteria key does not exist.

To retrieve a value from the environment, use the env resolver within a reference. For instance, ${env:PORT} will return the value of the PORT environment variable.

To parse a value into a different type, use the decode resolver within a reference. For instance, ${decode:${env:PORT}} will return the integer 8080 instead of a string when PORT has a value of “8080”.

To include other configuration files, use the includes key. For instance, includes: ["prompts.yaml"] will include the prompts.yaml file. Include paths can be any of the following:

  • Relative paths: ../config.yaml or defaults.yaml (relative to current file)
  • Absolute paths: /users/me/my-config.yaml
  • Package-relative: package:defaults.yaml (relative to default_config_package)
  • Package-absolute: package://other_package/configs/file.yaml (import path in other_package)
class Config

Methods

__init__

Initializes a new Config instance.

def __init__(self, default_config_package: str | None = None) -> None
default_config_package str | None

The default path to configs in a package for package: includes. For example, “myapp/configs” means package:defaults.yaml resolves to the defaults.yaml file in the myapp/configs package directory.

add_defaults

Adds defaults to the current config.

def add_defaults(self, defaults: dict | DictConfig) -> None
defaults dict | DictConfig

Settings to add to the config at the default layer.

add_config

Adds a main configuration to the current config.

def add_config(self, config: dict | DictConfig) -> None
config dict | DictConfig

Settings to add to the config at the main layer.

add_overrides

Adds overrides to the current config.

def add_overrides(self, overrides: dict | DictConfig) -> None
overrides dict | DictConfig

Settings to add to the config at the override layer.

load_defaults

Loads a default configuration from the given file.

def load_defaults(self, file: str | Path) -> None
file str | Path

The file to load the defaults from.

load_config

Loads a main configuration from the given file.

def load_config(self, file: str | Path) -> None
file str | Path

The file to load the main configuration from.

load_overrides

Loads an override configuration from the given file.

def load_overrides(self, file: str | Path) -> None
file str | Path

The file to load the overrides from.

track_usage

Enables tracking which values have been retrieved from the configuration, or resets the tracking dictionary if it is already enabled.

def track_usage(self) -> None
get_usage

Returns the dictionary of values that have been retrieved from the configuration, or None if usage tracking is not enabled.

def get_usage(self) -> dict[str, Any] | None
get

Retrieves a value from the configuration using a dot-separated path.

Note that dicts will be returned as DictConfig objects (which implement MutableMapping) and lists will be returned as ListConfig objects (which implement Sequence). These quack like dicts and lists, but will fail isinstance checks. To return native Python dicts and lists, set native_objects to True.

def get(
    self,
    path: str,
    default: Any = None,
    native_objects: bool = False,
    instantiate: bool = True,
) -> Any
path str

The path to the value to retrieve.

default Any

The default value to return if the path does not exist.

native_objects bool

Whether to return native Python objects for dictionaries and lists.

instantiate bool

Whether to instantiate objects that have a _target_ key. When instantiating, any parameter annotated with the Config type is auto-injected with this configuration.

Returns

The value at the path or the default value if not found.

has

Checks if a key exists in the configuration.

def has(self, path: str) -> bool
path str

The path to the value to check.

Returns

True if the key exists, False otherwise.

merge

Merges the given config into the current config.

def merge(self, other: DictConfig) -> None
other DictConfig

The config to merge into the current config.

resolve_expression

Resolves a string expression using the current configuration.

def resolve_expression(self, expression: str) -> Any
expression str

The string expression to resolve.

Returns

The resolved expression.

resolve

Resolves an object using the current configuration. Strings will be resolved as expressions. Dictionaries will be recursively resolved. Lists, tuples, and other collections will be resolved element-wise. All other types are returned unchanged.

def resolve(self, object: Any) -> Any
object Any

The object to resolve.

Returns

The resolved object.

to_yaml

Returns the current config as a YAML string.

def to_yaml(self) -> str
resolved_to_yaml

Returns the current config as a YAML string, with all expressions resolved.

def resolved_to_yaml(self) -> str
to_dict_config

Converts an object to a DictConfig.

def to_dict_config(self, object: dict | DictConfig) -> DictConfig
object dict | DictConfig

The object to convert to a DictConfig.

Returns

A DictConfig created from the object.

stats

Returns statistics about the current config.

def stats(self) -> dict[str, Any]
clone

Returns a deep clone of the configuration.

def clone(self) -> "Config"

Returns

A new Config instance with the same defaults, configs, overrides, and settings.

ConfigArgsParser

Parses CLI arguments from a multi-command YAML spec and maps them to config paths.

The YAML spec is expected to have a top-level key (e.g., cli) containing:

  • default_command: The command to use when none is specified on the command line.
  • global_options: Options (named flags) shared across all commands.
  • commands: A mapping of command names to their descriptions, positional arguments and options.

Each command entry includes a description, optional options (named flags) keys and either optional arguments (positional) or optional commands (subcommands). Only one level of subcommands is supported.

When subocommands are defined using commands, an optional default_command under that entry injects the subcommand when the user omits it (same idea as the top-level default). The dispatch key written to {key}.command is then <command>:<subcommand>.

Flags from global_options are merged into every command and nested subcommand parser, so they may appear before or after the command and nested subcommand (e.g., tool fingerprint list --verbose), same as for flat commands.

Options declared only on the parent that has nested commands (the group’s options: block) are registered only on that parent parser, not on each subcommand parser. These must then be used before the subcommand (e.g., cli fingerprint --scope all list). If a flag should be accepted after the subcommand, duplicate it under each nested command or promote it to global_options.

For example:

cli:
  default_command: eval
  global_options:
    verbose:
      type: bool
      action: store_true
      config: logs.verbose
  commands:
    eval:
      description: Run evaluation
      arguments:        # positional
        dataset:
          type: str
          config: setting.dataset
      options:          # named flags
        eval-mode:
          type: str
          config: eval.mode
    fingerprint:
      description: Fingerprint tools
      default_command: current
      commands:
        current:
          description: Show current fingerprint
          options: {}
class ConfigArgsParser

Methods

parse

Parses any command line arguments using the provided spec and returns a config, where the first non-flag argument is used as the command name, which is stored at {key}.command in the returned config.

@staticmethod
def parse(config: Config, spec: str | Path, key: str) -> DictConfig
config Config

The config used to resolve expressions in the spec.

spec str | Path

The path to a YAML file that contains the argument specification.

key str

The key in the argument specification file that contains the spec.

Returns

A DictConfig containing parsed argument values and {key}.command.

__init__

Constructs a new ConfigArgsParser and loads the argument specification from the given YAML file. If key is provided, the specification is loaded from the given key in the config.

def __init__(
    self,
    spec: str | Path = "args.yaml",
    key: str | None = None,
    config: Config | None = None,
)
spec str | Path

The path to a YAML file that contains the argument specification.

key str | None

The key in the argument specification file that contains the spec.

config Config | None

The config to use to resolve any expressions in the argument specification.

parse_args

Parses the command name and arguments from sys.argv.

Selects the command by examining the first positional argument. If it matches a known command name, that command is used. Otherwise default_command is injected so that callers can omit the command name entirely (backward-compatible UX).

If the command has subcommands, subsequent arguments are searched for a valid subcommand. If a valid subcommand is found, it is used; otherwise the default_command for that subcommand is injected so that callers can omit the subcommand name entirely.

The resolved command name is stored at {key}.command in the returned config if key is provided. Otherwise it is stored at command. The value for subcommands is stored as <command>:<subcommand>.

def parse_args(self, key: str | None = None) -> DictConfig
key str | None

The key in the returned config that the command name will be stored at.

Returns

A DictConfig containing parsed argument values mapped to their config paths.

ConfigFieldParser

A class that builds a DictConfig from the defaults of the fields of a class.

This parser can extract field information from dataclasses and classes whose members are Pydantic fields, and organize the defaults under a specified key or at the root level.

class ConfigFieldParser

Methods

parse

Parse a class and build a DictConfig from its field defaults.

@staticmethod
def parse(type: type, key: str | None = None) -> DictConfig
type type

The type to parse (can be a dataclass or class whose members are Pydantic fields)

key str | None

Optional key to nest the field defaults under. If None, defaults are at root level.

Returns

A DictConfig containing the field defaults

clear_resolver

Clear a previously registered resolver.

Like registration, this affects the global OmegaConf resolver registry for the whole process.

def clear_resolver(name: str) -> bool
name str

The name of the resolver to remove, e.g., exec.

Returns

True if a resolver with that name existed and was removed, otherwise False.

config_defaults

Decorator that fills the values for parameters that are not passed with the defaults from config.

The configuration is taken from the config argument when provided, which can be either a Config instance or a zero-argument callable that returns one (resolved on each call). When config is not provided, it is read from the decorated function’s config parameter instead, which must then be present.

Parameters that are passed as None are not filled with the defaults. If a complex type is defined for a parameter and the config value is a mapping, the type is instantiated using that mapping.

def config_defaults[T](
    config_path: str,
    config: Config | Callable[[], Config] | None = None,
    *,
    transformers: dict[str, Callable[[Any], Any]] | None = None,
) -> Callable[[Callable[..., T]], Callable[..., T]]
config_path str

Path in config to get defaults from.

config Config | Callable[[], Config] | None

The configuration to read defaults from, or a callable returning it. When omitted, the decorated function must declare a config parameter that supplies it at call time.

transformers dict[str, Callable[[Any], Any]] | None

Optional dict mapping param names to transformation functions that take the config value and return the transformed value.

confirmed_by_user

Prompt the user for confirmation, returning True when the response matches confirmation_value (case-insensitive). If the confirmation_value is a single letter, the user’s response is truncated to the first character before comparison (e.g., “yes” matches “y”).

The prompt is skipped entirely when the configuration already indicates confirmation: either config.auto_confirm is True, or the value at config_path is True.

def confirmed_by_user(
    message: str,
    confirmation_value: str = "y",
    always_value: str | None = None,
    default: str = "n",
    config: Config | None = None,
    config_path: str | None = None,
) -> bool
message str

The prompt to display to the user.

confirmation_value str

The value that counts as confirmation (case-insensitive).

always_value str | None

An optional value that, when provided, will always return True and set the value at config_path to True in the config to persist the confirmation.

default str

The value assumed when the user presses Enter without typing anything.

config Config | None

An optional Config instance to check for auto-confirmation.

config_path str | None

An optional dot-separated path within config whose boolean value can pre-approve the confirmation.

Returns

True when the user (or configuration) confirms; False otherwise.

create_fingerprint

Creates a fingerprint from a configuration using a specification. The spec parameter can be either a fingerprint specification or a config path that points to a fingerprint specification.

A fingerprint specification is a dictionary that mirrors the hierarchical structure of the config with leaf nodes indicating how to fingerprint the values at that path in the config. Values can be fingerprinted as their actual values or as hashes of their values.

For example:

config.fingerprint:
  models:
    trusted:
      name: value
    untrusted:
      name: value
  prompts:
    setting: hash
    main_task: hash
    side_task: hash

Would use the names of the trusted and untrusted models and the hashed values of the prompts to create a fingerprint, which might look like:

models:
  trusted:
    name: openai/gpt-4.1-mini-2025-04-14
  untrusted:
    name: anthropic/claude-sonnet-4-5-20250929
prompts:
  setting: f931d774bd3db2a7d86b530bb83c2b902243a39a25417c27b3599d9cdbf1ce98
  main_task: 2d3d8ddf8beae434e00b8c607f622f6b7b1553fa4f9538005739735e31937eab
  side_task: 6495f607070866967b6bcb6a88961d04d9f5314f998fe45ced71de06262769b2

Fingerprint methods include:

  • value: For built-ins, use the actual value; otherwise, use its repr representation.
  • set-attrs-dict: For dataclasses and Pydantic models, use a dictionary of its non-default attributes. For other types, raise a TypeError.
  • hash: Use a hash of the value.
  • none: Do not fingerprint the value (used to override parts of a fingerprint specification)

Collection fingerprint methods include:

  • list[method]: Fingerprint each item in the list using the specified method.
  • dict[method]: Fingerprint each item in the dictionary using the specified method.

A method can be piped through a named transform using the form method|transform (e.g., value|minor_version or dict[value|major_version]). Version transforms truncate a version string to a specified level so that non-breaking bumps do not change the fingerprint.

Fingerprint transforms include:

  • release_version: The release segments only, dropping pre/dev/local metadata (e.g., 0.8.2.dev63+g1a2b3c -> 0.8.2).
  • major_version: The major prefix (e.g., 16.0.0 -> 16). Raises a ValueError for 0.x versions, since every 0.x release would collapse to 0 and match unrelated releases.
  • minor_version: The major.minor prefix (e.g., 0.9.3 -> 0.9).

Finally, a fingerprint method can be prefixed with config: to indicate that the value should be retrieved from the configuration without instantiating (e.g., use the raw configuration). This can be helpful for fingerprinting functions or classes that require creating a fingerprint to be constructed (e.g., certain scorers), thus avoiding circular dependencies.

def create_fingerprint(
    config: Config,
    spec: str | Mapping[str, Any] = "config.fingerprint",
) -> dict[str, Any]
config Config

The configuration object to fingerprint.

spec str | Mapping[str, Any]

A fingerprint specification or a config path that points to a fingerprint specification. Defaults to config.fingerprint.

Returns

A dictionary representing the fingerprint, matching the structure of the fingerprint specification but with leaf values replaced by their fingerprint values from the config.

current_fingerprint

Returns the name of the fingerprint that matches the current configuration.

Iterates through the fingerprints stored at fingerprints_key and returns the name of the first fingerprint that matches the current configuration. If no match is found, returns None.

def current_fingerprint(
    config: Config,
    fingerprints_key: str = "fingerprints",
    spec: str | Mapping[str, Any] = "config.fingerprint",
) -> str | None
config Config

The configuration object to check.

fingerprints_key str

A config path to a dictionary mapping fingerprint names to fingerprints. Defaults to “fingerprints”.

spec str | Mapping[str, Any]

A fingerprint specification or a config path that points to a fingerprint specification. Used to generate the current fingerprint. Defaults to config.fingerprint.

Returns

The name of the fingerprint that matches the current configuration, or None if no match is found.

exec_resolver

Executes a shell command and returns the output, or None if the command fails.

def exec_resolver(command: str) -> str | None
command str

get_config_item_names

Return a list of active item names based on the list and include-if keys under the path at list_key in the config. The list key is a comma-separated list or list-like object of item names, and the include-if key is a mapping of item names to conditions that determines if the item is active.

def get_config_item_names(config: Config, list_key: str) -> list[str]
config Config

The Config instance.

list_key str

Dot path prefix for list and include-if sub-keys.

Examples

items:
list: ["always", "conditional"]

include-if:
    conditional: "${config.flags.enabled}"

This will return ["always"] if config.flags.enabled is False and ["always", "conditional"] if config.flags.enabled is True.

get_config_items

Resolve named config items using the list + include-if + options pattern.

def get_config_items(
    config: Config,
    list_key: str,
    options_key: str | None = None,
) -> list[Any]
config Config

The Config instance.

list_key str

Dot path prefix for list and include-if sub-keys.

options_key str | None

Dot path prefix for option definitions. Defaults to {list_key}.options when omitted.

Examples

items:
  list: ["always", "conditional"]

  include-if:
    conditional: "${config.flags.enabled}"

  options:
    always:
      name: "always"

    conditional:
      name: "conditional"

This will return [{ "name": "always" }] if config.flags.enabled is False and [{ "name": "always" }, { "name": "conditional" }] if config.flags.enabled is True.

register_resolver

Register a resolver for use in ${name:...} interpolations.

Resolvers are registered globally with OmegaConf, so a resolver registered here is available to every config in the process and all OmegaConf instances, not just a single Config instance.

def register_resolver(name: str, resolver: Resolver, *, replace: bool = False) -> None
name str

The name the resolver is invoked by, e.g., env for ${env:...}.

resolver Resolver

The function that computes the resolved value from the interpolation arguments.

replace bool

Whether to replace an existing resolver of the same name. When False (the default), an already-registered name is left untouched.