Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clarify in docs how runtime parameter resolution works #4096

Merged
merged 7 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
## Breaking changes to the API

## Documentation changes
* Add clarifications in docs explaining how runtime parameter resolution works.

## Community contributions

Expand Down
3 changes: 2 additions & 1 deletion docs/source/configuration/advanced_configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,8 @@ Note that you can only use the resolver in `credentials.yml` and not in catalog
```

### How to change the merge strategy used by `OmegaConfigLoader`
By default, `OmegaConfigLoader` merges configuration [in different environments](configuration_basics.md#configuration-environments) in a destructive way. This means that whatever configuration resides in your overriding environment (`local` by default) takes precedence when the same top-level key is present in the base and overriding environment. Any configuration for that key **besides that given in the overriding environment** is discarded.
By default, `OmegaConfigLoader` merges configuration [in different environments](configuration_basics.md#configuration-environments) as well as runtime parameters in a destructive way. This means that whatever configuration resides in your overriding environment (`local` by default) takes precedence when the same top-level key is present in the base and overriding environment. Any configuration for that key **besides that given in the overriding environment** is discarded.
The same behaviour applies to runtime parameters overriding any configuration in the `base` environment.
merelcht marked this conversation as resolved.
Show resolved Hide resolved
You can change the merge strategy for each configuration type in your project's `src/<package_name>/settings.py`. The accepted merging strategies are `soft` and `destructive`.

```python
Expand Down
42 changes: 41 additions & 1 deletion docs/source/configuration/parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,47 @@ Each key-value pair is split on the first equals sign. The following example is
```bash
kedro run --params=param_key1=value1,param_key2=2.0
```
Values provided in the CLI take precedence and overwrite parameters specified in configuration files.
Values provided in the CLI take precedence and overwrite parameters specified in configuration files. By default, runtime parameters get merged destructively, meaning that any configuration for that key **besides that given in the runtime parameters** is discarded.
[This section describes how to change the merging strategy](advanced_configuration.md#how-to-change-the-merge-strategy-used-by-omegaconfigloader).

For example, if you have the following parameters in your `base` and `local` environments:

```yaml
# base/parameters.yml
model_options:
model_params:
learning_date: "2023-11-01"
training_date: "2023-11-01"
data_ratio: 14

data_options:
step_size: 123123
```

```yaml
# local/parameters.yml
features:
rate: 123
```

And you provide the following parameter at runtime:

```bash
kedro run --params="model_options.model_params.training_date=2011-11-11"
```

The final merged result will be:
```yaml
model_options:
model_params:
training_date: "2011-11-11"

data_options:
step_size: 123123

features:
rate: 123
```

* Parameter keys are _always_ treated as strings.
* Parameter values are converted to a float or an integer number if the corresponding conversion succeeds; otherwise, they are also treated as string.
Expand Down
83 changes: 83 additions & 0 deletions tests/config/test_omegaconf_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -1068,6 +1068,89 @@ def test_runtime_params_resolution(self, tmp_path):
# runtime params are resolved correctly in catalog
assert conf["catalog"]["companies"]["type"] == runtime_params["dataset"]["type"]

def test_runtime_params_resolution_with_soft_merge_base_env(self, tmp_path):
"""Test that runtime_params get softly merged with the base environment when soft merge is set
for parameter merge"""
base_params = tmp_path / _BASE_ENV / "parameters.yml"
prod_params = tmp_path / "prod" / "parameters.yml"
runtime_params = {
"aaa": {
"bbb": {
"abb": "2011-11-11",
}
}
}
param_config = {
"aaa": {
"bbb": {
"aba": "2023-11-01",
"abb": "2023-11-01",
"abc": 14,
}
},
"xyz": {"asdf": 123123},
}
prod_param_config = {"def": {"gg": 123}}
_write_yaml(base_params, param_config)
_write_yaml(prod_params, prod_param_config)
conf = OmegaConfigLoader(
tmp_path,
base_env=_BASE_ENV,
default_run_env="prod",
runtime_params=runtime_params,
merge_strategy={"parameters": "soft"},
)

expected_parameters = {
"aaa": {"bbb": {"aba": "2023-11-01", "abb": "2011-11-11", "abc": 14}},
"xyz": {"asdf": 123123},
"def": {"gg": 123},
}

# runtime parameters are resolved correctly across parameter files from different environments
assert conf["parameters"] == expected_parameters

def test_runtime_params_resolution_default_run_env(self, tmp_path):
"""Test that runtime_params overwrite merge with the default run environment"""
base_params = tmp_path / _BASE_ENV / "parameters.yml"
prod_params = tmp_path / "prod" / "parameters.yml"
runtime_params = {"data_shift": 3}
param_config = {
"model_options": {
"test_size": 0.2,
"random_state": 3,
"features": ["engines"],
}
}
prod_param_config = {
"model_options": {
"test_size": 0.2,
"random_state": 3,
"features": ["engines"],
},
"data_shift": 1,
}
_write_yaml(base_params, param_config)
_write_yaml(prod_params, prod_param_config)
conf = OmegaConfigLoader(
tmp_path,
base_env=_BASE_ENV,
default_run_env="prod",
runtime_params=runtime_params,
)

expected_parameters = {
"model_options": {
"test_size": 0.2,
"random_state": 3,
"features": ["engines"],
},
"data_shift": 3,
}

# runtime parameters are resolved correctly across parameter files from different environments
assert conf["parameters"] == expected_parameters

def test_runtime_params_missing_default(self, tmp_path):
base_params = tmp_path / _BASE_ENV / "parameters.yml"
runtime_params = {
Expand Down