Load config with _base_ inheritance, then apply CLI overrides.
(args: argparse.Namespace)
| 378 | |
| 379 | |
| 380 | def load_config(args: argparse.Namespace) -> dict: |
| 381 | """Load config with _base_ inheritance, then apply CLI overrides.""" |
| 382 | from skillopt.config import load_config as _load, flatten_config, is_structured |
| 383 | |
| 384 | cfg = _load(args.config, overrides=args.cfg_options) |
| 385 | structured = is_structured(cfg) |
| 386 | |
| 387 | # Apply legacy --key value overrides |
| 388 | cli = {k: v for k, v in vars(args).items() |
| 389 | if v is not None and k not in ("config", "cfg_options")} |
| 390 | if cli: |
| 391 | if structured: |
| 392 | from skillopt.config import apply_overrides |
| 393 | mapped = [] |
| 394 | for k, v in cli.items(): |
| 395 | dotted = _LEGACY_TO_STRUCTURED.get(k) |
| 396 | if dotted: |
| 397 | mapped.append(f"{dotted}={v}") |
| 398 | else: |
| 399 | mapped.append(f"env.{k}={v}") |
| 400 | apply_overrides(cfg, mapped) |
| 401 | else: |
| 402 | cfg.update(cli) |
| 403 | |
| 404 | # Flatten structured config → flat dict for trainer/adapter |
| 405 | flat = flatten_config(cfg) if structured else cfg |
| 406 | |
| 407 | for new_key, old_key in ( |
| 408 | ("azure_openai_endpoint", "azure_endpoint"), |
| 409 | ("azure_openai_api_version", "azure_api_version"), |
| 410 | ("azure_openai_api_key", "azure_api_key"), |
| 411 | ): |
| 412 | if flat.get(new_key) in (None, "") and flat.get(old_key) not in (None, ""): |
| 413 | flat[new_key] = flat[old_key] |
| 414 | |
| 415 | explicit_backend = getattr(args, "backend", None) |
| 416 | if explicit_backend is None: |
| 417 | for option in args.cfg_options or []: |
| 418 | key = str(option).split("=", 1)[0].strip() |
| 419 | if key == "model.backend": |
| 420 | explicit_backend = str(option).split("=", 1)[1].strip() |
| 421 | break |
| 422 | |
| 423 | backend = normalize_backend_name(flat.get("model_backend") or flat.get("target_backend") or "azure_openai") |
| 424 | |
| 425 | def _has_model_override(dotted_key: str, legacy_key: str) -> bool: |
| 426 | if getattr(args, legacy_key, None) is not None: |
| 427 | return True |
| 428 | for option in args.cfg_options or []: |
| 429 | key = str(option).split("=", 1)[0].strip() |
| 430 | if key == dotted_key: |
| 431 | return True |
| 432 | return False |
| 433 | |
| 434 | if explicit_backend is not None: |
| 435 | backend = normalize_backend_name(explicit_backend) |
| 436 | flat["model_backend"] = backend |
| 437 | if backend in {"claude", "claude_chat"}: |
no test coverage detected