Skip to content
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
6 changes: 2 additions & 4 deletions modules/ui/BaseTopBarView.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,8 @@ def __load_current_config(self, filename):
with open(filename, "r") as f:
loaded_dict = json.load(f)
default_config = TrainConfig.default_values()
if is_built_in_preset:
# always assume built-in configs are saved in the most recent version
loaded_dict["__version"] = default_config.config_version
loaded_config = default_config.from_dict(loaded_dict).to_unpacked_config()
# built-in configs are always saved in the most recent version, so migration can be skipped
loaded_config = default_config.from_dict(loaded_dict, migrate=not is_built_in_preset).to_unpacked_config()

with suppress(FileNotFoundError), open("secrets.json", "r") as f:
secrets_dict=json.load(f)
Expand Down
6 changes: 6 additions & 0 deletions modules/util/args/TrainArgs.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@


class TrainArgs(BaseArgs):
preset_path: str
config_path: str
secrets_path: str
config_values: list[str]

def __init__(self, data: list[(str, Any, type, bool)]):
super().__init__(data)
Expand All @@ -17,8 +19,10 @@ def parse_args() -> 'TrainArgs':

# @formatter:off

parser.add_argument("--preset-path", type=str, required=False, dest="preset_path", help="The path to a built-in preset file, applied before --config-path. When set, config migration is skipped for both files, so both the preset and the config must be in the current format.")
parser.add_argument("--config-path", type=str, required=True, dest="config_path", help="The path to the config file")
parser.add_argument("--secrets-path", type=str, required=False, dest="secrets_path", help="The path to the secrets file")
parser.add_argument("--config-value", type=str, required=False, dest="config_values", action="append", help="Override a single config value, as KEY=VALUE. Applied after --preset-path and --config-path. KEY may use dot notation to reach nested config objects (e.g. ema.decay). Can be passed multiple times.")
parser.add_argument("--callback-path", type=str, required=False, dest="callback_path", help="The path to the callback pickle file")
parser.add_argument("--command-path", type=str, required=False, dest="command_path", help="The path to the command pickle file")

Expand All @@ -33,8 +37,10 @@ def default_values() -> 'TrainArgs':
data = []

# name, default value, data type, nullable
data.append(("preset_path", None, str, True))
data.append(("config_path", None, str, True))
data.append(("secrets_path", None, str, True))
data.append(("config_values", None, list[str], True))
data.append(("callback_path", None, str, True))
data.append(("command_path", None, str, True))

Expand Down
23 changes: 12 additions & 11 deletions modules/util/config/BaseConfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,19 +63,20 @@ def to_dict(self) -> dict:

return data

def from_dict(self, data: dict) -> 'BaseConfig':
version = 0
if '__version' in data:
version = data['__version']
def from_dict(self, data: dict, migrate: bool = True) -> 'BaseConfig':
if migrate:
version = 0
if '__version' in data:
version = data['__version']

while version in self.config_migrations:
data = self.config_migrations[version](data)
version += 1
while version in self.config_migrations:
data = self.config_migrations[version](data)
version += 1

for name in self.types:
try:
if issubclass_safe(self.types[name], BaseConfig):
getattr(self, name).from_dict(data[name])
getattr(self, name).from_dict(data[name], migrate=migrate)
elif self.types[name] is list or get_origin(self.types[name]) is list:
if len(get_args(self.types[name])) > 0 and issubclass_safe(get_args(self.types[name])[0], BaseConfig):
list_type = get_args(self.types[name])[0]
Expand All @@ -85,9 +86,9 @@ def from_dict(self, data: dict) -> 'BaseConfig':
value = []
for i in range(len(data[name])):
if i < len(old_value) and i < len(data[name]):
value.append(old_value[i].from_dict(data[name][i]))
value.append(old_value[i].from_dict(data[name][i], migrate=migrate))
else:
value.append(list_type.default_values().from_dict(data[name][i]))
value.append(list_type.default_values().from_dict(data[name][i], migrate=migrate))
else:
value = None
setattr(self, name, value)
Expand All @@ -98,7 +99,7 @@ def from_dict(self, data: dict) -> 'BaseConfig':
dict_type = get_args(self.types[name])[1]
value = {}
for dict_key, dict_value in data[name].items():
value[dict_key] = dict_type.default_values().from_dict(dict_value)
value[dict_key] = dict_type.default_values().from_dict(dict_value, migrate=migrate)
setattr(self, name, value)
else:
setattr(self, name, data[name])
Expand Down
17 changes: 16 additions & 1 deletion scripts/train.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,23 @@ def main():
commands = TrainCommands()

train_config = TrainConfig.default_values()

if args.preset_path is not None:
with open(args.preset_path, "r") as f:
train_config.from_dict(json.load(f), migrate=False)

with open(args.config_path, "r") as f:
train_config.from_dict(json.load(f))
train_config.from_dict(json.load(f), migrate=args.preset_path is None)

for config_value in args.config_values or []:
key, _, value = config_value.partition("=")
*parent_keys, leaf_key = key.split(".")
target = train_config
for parent_key in parent_keys:
target = getattr(target, parent_key)
if target.types[leaf_key] is bool:
value = value.lower() in ("true", "1", "yes")
target.from_dict({leaf_key: value}, migrate=False)

try:
with open("secrets.json" if args.secrets_path is None else args.secrets_path, "r") as f:
Expand Down