ins-pricing 0.5.0__py3-none-any.whl → 0.5.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. ins_pricing/cli/BayesOpt_entry.py +15 -5
  2. ins_pricing/cli/BayesOpt_incremental.py +43 -10
  3. ins_pricing/cli/Explain_Run.py +16 -5
  4. ins_pricing/cli/Explain_entry.py +29 -8
  5. ins_pricing/cli/Pricing_Run.py +16 -5
  6. ins_pricing/cli/bayesopt_entry_runner.py +45 -12
  7. ins_pricing/cli/utils/bootstrap.py +23 -0
  8. ins_pricing/cli/utils/cli_config.py +34 -15
  9. ins_pricing/cli/utils/import_resolver.py +14 -14
  10. ins_pricing/cli/utils/notebook_utils.py +120 -106
  11. ins_pricing/cli/watchdog_run.py +15 -5
  12. ins_pricing/frontend/app.py +132 -61
  13. ins_pricing/frontend/config_builder.py +33 -0
  14. ins_pricing/frontend/example_config.json +11 -0
  15. ins_pricing/frontend/runner.py +340 -388
  16. ins_pricing/modelling/README.md +1 -1
  17. ins_pricing/modelling/__init__.py +10 -10
  18. ins_pricing/modelling/bayesopt/README.md +29 -11
  19. ins_pricing/modelling/bayesopt/config_components.py +12 -0
  20. ins_pricing/modelling/bayesopt/config_preprocess.py +50 -13
  21. ins_pricing/modelling/bayesopt/core.py +47 -19
  22. ins_pricing/modelling/bayesopt/model_plotting_mixin.py +20 -14
  23. ins_pricing/modelling/bayesopt/models/model_ft_components.py +349 -342
  24. ins_pricing/modelling/bayesopt/models/model_ft_trainer.py +11 -5
  25. ins_pricing/modelling/bayesopt/models/model_gnn.py +20 -14
  26. ins_pricing/modelling/bayesopt/models/model_resn.py +9 -3
  27. ins_pricing/modelling/bayesopt/trainers/trainer_base.py +62 -50
  28. ins_pricing/modelling/bayesopt/trainers/trainer_ft.py +61 -53
  29. ins_pricing/modelling/bayesopt/trainers/trainer_glm.py +9 -3
  30. ins_pricing/modelling/bayesopt/trainers/trainer_gnn.py +40 -32
  31. ins_pricing/modelling/bayesopt/trainers/trainer_resn.py +36 -24
  32. ins_pricing/modelling/bayesopt/trainers/trainer_xgb.py +240 -37
  33. ins_pricing/modelling/bayesopt/utils/distributed_utils.py +193 -186
  34. ins_pricing/modelling/bayesopt/utils/torch_trainer_mixin.py +23 -10
  35. ins_pricing/pricing/factors.py +67 -56
  36. ins_pricing/setup.py +1 -1
  37. ins_pricing/utils/__init__.py +7 -6
  38. ins_pricing/utils/device.py +45 -24
  39. ins_pricing/utils/logging.py +34 -1
  40. ins_pricing/utils/profiling.py +8 -4
  41. {ins_pricing-0.5.0.dist-info → ins_pricing-0.5.3.dist-info}/METADATA +182 -182
  42. {ins_pricing-0.5.0.dist-info → ins_pricing-0.5.3.dist-info}/RECORD +44 -43
  43. {ins_pricing-0.5.0.dist-info → ins_pricing-0.5.3.dist-info}/WHEEL +0 -0
  44. {ins_pricing-0.5.0.dist-info → ins_pricing-0.5.3.dist-info}/top_level.txt +0 -0
@@ -11,11 +11,21 @@ import json
11
11
  import os
12
12
  import sys
13
13
 
14
- if __package__ in {None, ""}:
15
- if importlib.util.find_spec("ins_pricing") is None:
16
- repo_root = Path(__file__).resolve().parents[2]
17
- if str(repo_root) not in sys.path:
18
- sys.path.insert(0, str(repo_root))
14
+ def _ensure_repo_root() -> None:
15
+ if __package__ not in {None, ""}:
16
+ return
17
+ if importlib.util.find_spec("ins_pricing") is not None:
18
+ return
19
+ bootstrap_path = Path(__file__).resolve().parents[1] / "utils" / "bootstrap.py"
20
+ spec = importlib.util.spec_from_file_location("ins_pricing.cli.utils.bootstrap", bootstrap_path)
21
+ if spec is None or spec.loader is None:
22
+ return
23
+ module = importlib.util.module_from_spec(spec)
24
+ spec.loader.exec_module(module)
25
+ module.ensure_repo_root()
26
+
27
+
28
+ _ensure_repo_root()
19
29
 
20
30
  def _apply_env_from_config(argv: list[str]) -> None:
21
31
  if "--config-json" not in argv:
@@ -20,11 +20,22 @@ from pathlib import Path
20
20
  import importlib.util
21
21
  import sys
22
22
 
23
- if __package__ in {None, ""}:
24
- if importlib.util.find_spec("ins_pricing") is None:
25
- repo_root = Path(__file__).resolve().parents[2]
26
- if str(repo_root) not in sys.path:
27
- sys.path.insert(0, str(repo_root))
23
+
24
+ def _ensure_repo_root() -> None:
25
+ if __package__ not in {None, ""}:
26
+ return
27
+ if importlib.util.find_spec("ins_pricing") is not None:
28
+ return
29
+ bootstrap_path = Path(__file__).resolve().parents[1] / "utils" / "bootstrap.py"
30
+ spec = importlib.util.spec_from_file_location("ins_pricing.cli.utils.bootstrap", bootstrap_path)
31
+ if spec is None or spec.loader is None:
32
+ return
33
+ module = importlib.util.module_from_spec(spec)
34
+ spec.loader.exec_module(module)
35
+ module.ensure_repo_root()
36
+
37
+
38
+ _ensure_repo_root()
28
39
 
29
40
  import argparse
30
41
  import json
@@ -422,9 +433,20 @@ class IncrementalUpdateRunner:
422
433
  self.prediction_cache_dir = runtime_cfg["prediction_cache_dir"]
423
434
  self.prediction_cache_format = runtime_cfg["prediction_cache_format"]
424
435
  self.plot_path_style = runtime_cfg["plot_path_style"]
425
- self.xgb_max_depth_max = runtime_cfg["xgb_max_depth_max"]
426
- self.xgb_n_estimators_max = runtime_cfg["xgb_n_estimators_max"]
427
- self.optuna_storage = runtime_cfg["optuna_storage"]
436
+ self.xgb_max_depth_max = runtime_cfg["xgb_max_depth_max"]
437
+ self.xgb_n_estimators_max = runtime_cfg["xgb_n_estimators_max"]
438
+ self.xgb_gpu_id = runtime_cfg["xgb_gpu_id"]
439
+ self.xgb_cleanup_per_fold = runtime_cfg["xgb_cleanup_per_fold"]
440
+ self.xgb_cleanup_synchronize = runtime_cfg["xgb_cleanup_synchronize"]
441
+ self.xgb_use_dmatrix = runtime_cfg["xgb_use_dmatrix"]
442
+ self.ft_cleanup_per_fold = runtime_cfg["ft_cleanup_per_fold"]
443
+ self.ft_cleanup_synchronize = runtime_cfg["ft_cleanup_synchronize"]
444
+ self.resn_cleanup_per_fold = runtime_cfg["resn_cleanup_per_fold"]
445
+ self.resn_cleanup_synchronize = runtime_cfg["resn_cleanup_synchronize"]
446
+ self.gnn_cleanup_per_fold = runtime_cfg["gnn_cleanup_per_fold"]
447
+ self.gnn_cleanup_synchronize = runtime_cfg["gnn_cleanup_synchronize"]
448
+ self.optuna_cleanup_synchronize = runtime_cfg["optuna_cleanup_synchronize"]
449
+ self.optuna_storage = runtime_cfg["optuna_storage"]
428
450
  self.optuna_study_prefix = runtime_cfg["optuna_study_prefix"]
429
451
  self.best_params_files = runtime_cfg["best_params_files"]
430
452
  self.reuse_best_params = runtime_cfg["reuse_best_params"]
@@ -593,8 +615,19 @@ class IncrementalUpdateRunner:
593
615
  use_ft_ddp=self.cfg.get("use_ft_ddp", False),
594
616
  use_gnn_ddp=self.cfg.get("use_gnn_ddp", False),
595
617
  output_dir=str(self.output_root) if self.output_root else None,
596
- xgb_max_depth_max=self.xgb_max_depth_max,
597
- xgb_n_estimators_max=self.xgb_n_estimators_max,
618
+ xgb_max_depth_max=self.xgb_max_depth_max,
619
+ xgb_n_estimators_max=self.xgb_n_estimators_max,
620
+ xgb_gpu_id=self.xgb_gpu_id,
621
+ xgb_cleanup_per_fold=self.xgb_cleanup_per_fold,
622
+ xgb_cleanup_synchronize=self.xgb_cleanup_synchronize,
623
+ xgb_use_dmatrix=self.xgb_use_dmatrix,
624
+ ft_cleanup_per_fold=self.ft_cleanup_per_fold,
625
+ ft_cleanup_synchronize=self.ft_cleanup_synchronize,
626
+ resn_cleanup_per_fold=self.resn_cleanup_per_fold,
627
+ resn_cleanup_synchronize=self.resn_cleanup_synchronize,
628
+ gnn_cleanup_per_fold=self.gnn_cleanup_per_fold,
629
+ gnn_cleanup_synchronize=self.gnn_cleanup_synchronize,
630
+ optuna_cleanup_synchronize=self.optuna_cleanup_synchronize,
598
631
  resn_weight_decay=self.cfg.get("resn_weight_decay"),
599
632
  final_ensemble=bool(self.cfg.get("final_ensemble", False)),
600
633
  final_ensemble_k=int(self.cfg.get("final_ensemble_k", 3)),
@@ -5,11 +5,22 @@ from typing import Optional
5
5
  import importlib.util
6
6
  import sys
7
7
 
8
- if __package__ in {None, ""}:
9
- if importlib.util.find_spec("ins_pricing") is None:
10
- repo_root = Path(__file__).resolve().parents[2]
11
- if str(repo_root) not in sys.path:
12
- sys.path.insert(0, str(repo_root))
8
+
9
+ def _ensure_repo_root() -> None:
10
+ if __package__ not in {None, ""}:
11
+ return
12
+ if importlib.util.find_spec("ins_pricing") is not None:
13
+ return
14
+ bootstrap_path = Path(__file__).resolve().parents[1] / "utils" / "bootstrap.py"
15
+ spec = importlib.util.spec_from_file_location("ins_pricing.cli.utils.bootstrap", bootstrap_path)
16
+ if spec is None or spec.loader is None:
17
+ return
18
+ module = importlib.util.module_from_spec(spec)
19
+ spec.loader.exec_module(module)
20
+ module.ensure_repo_root()
21
+
22
+
23
+ _ensure_repo_root()
13
24
 
14
25
  try:
15
26
  from ins_pricing.cli.utils.notebook_utils import run_from_config, run_from_config_cli # type: ignore
@@ -6,11 +6,21 @@ from pathlib import Path
6
6
  import importlib.util
7
7
  import sys
8
8
 
9
- if __package__ in {None, ""}:
10
- if importlib.util.find_spec("ins_pricing") is None:
11
- repo_root = Path(__file__).resolve().parents[2]
12
- if str(repo_root) not in sys.path:
13
- sys.path.insert(0, str(repo_root))
9
+ def _ensure_repo_root() -> None:
10
+ if __package__ not in {None, ""}:
11
+ return
12
+ if importlib.util.find_spec("ins_pricing") is not None:
13
+ return
14
+ bootstrap_path = Path(__file__).resolve().parents[1] / "utils" / "bootstrap.py"
15
+ spec = importlib.util.spec_from_file_location("ins_pricing.cli.utils.bootstrap", bootstrap_path)
16
+ if spec is None or spec.loader is None:
17
+ return
18
+ module = importlib.util.module_from_spec(spec)
19
+ spec.loader.exec_module(module)
20
+ module.ensure_repo_root()
21
+
22
+
23
+ _ensure_repo_root()
14
24
 
15
25
  import argparse
16
26
  import json
@@ -460,9 +470,20 @@ def explain_from_config(args: argparse.Namespace) -> None:
460
470
  "epochs": int(runtime_cfg["epochs"]),
461
471
  "use_gpu": bool(cfg.get("use_gpu", True)),
462
472
  "output_dir": output_dir,
463
- "xgb_max_depth_max": runtime_cfg["xgb_max_depth_max"],
464
- "xgb_n_estimators_max": runtime_cfg["xgb_n_estimators_max"],
465
- "resn_weight_decay": cfg.get("resn_weight_decay"),
473
+ "xgb_max_depth_max": runtime_cfg["xgb_max_depth_max"],
474
+ "xgb_n_estimators_max": runtime_cfg["xgb_n_estimators_max"],
475
+ "xgb_gpu_id": runtime_cfg["xgb_gpu_id"],
476
+ "xgb_cleanup_per_fold": runtime_cfg["xgb_cleanup_per_fold"],
477
+ "xgb_cleanup_synchronize": runtime_cfg["xgb_cleanup_synchronize"],
478
+ "xgb_use_dmatrix": runtime_cfg["xgb_use_dmatrix"],
479
+ "ft_cleanup_per_fold": runtime_cfg["ft_cleanup_per_fold"],
480
+ "ft_cleanup_synchronize": runtime_cfg["ft_cleanup_synchronize"],
481
+ "resn_cleanup_per_fold": runtime_cfg["resn_cleanup_per_fold"],
482
+ "resn_cleanup_synchronize": runtime_cfg["resn_cleanup_synchronize"],
483
+ "gnn_cleanup_per_fold": runtime_cfg["gnn_cleanup_per_fold"],
484
+ "gnn_cleanup_synchronize": runtime_cfg["gnn_cleanup_synchronize"],
485
+ "optuna_cleanup_synchronize": runtime_cfg["optuna_cleanup_synchronize"],
486
+ "resn_weight_decay": cfg.get("resn_weight_decay"),
466
487
  "final_ensemble": bool(cfg.get("final_ensemble", False)),
467
488
  "final_ensemble_k": int(cfg.get("final_ensemble_k", 3)),
468
489
  "final_refit": bool(cfg.get("final_refit", True)),
@@ -5,11 +5,22 @@ from typing import Optional
5
5
  import importlib.util
6
6
  import sys
7
7
 
8
- if __package__ in {None, ""}:
9
- if importlib.util.find_spec("ins_pricing") is None:
10
- repo_root = Path(__file__).resolve().parents[2]
11
- if str(repo_root) not in sys.path:
12
- sys.path.insert(0, str(repo_root))
8
+
9
+ def _ensure_repo_root() -> None:
10
+ if __package__ not in {None, ""}:
11
+ return
12
+ if importlib.util.find_spec("ins_pricing") is not None:
13
+ return
14
+ bootstrap_path = Path(__file__).resolve().parents[1] / "utils" / "bootstrap.py"
15
+ spec = importlib.util.spec_from_file_location("ins_pricing.cli.utils.bootstrap", bootstrap_path)
16
+ if spec is None or spec.loader is None:
17
+ return
18
+ module = importlib.util.module_from_spec(spec)
19
+ spec.loader.exec_module(module)
20
+ module.ensure_repo_root()
21
+
22
+
23
+ _ensure_repo_root()
13
24
 
14
25
  try:
15
26
  from ins_pricing.cli.utils.notebook_utils import run_from_config, run_from_config_cli # type: ignore
@@ -15,11 +15,22 @@ from pathlib import Path
15
15
  import importlib.util
16
16
  import sys
17
17
 
18
- if __package__ in {None, ""}:
19
- if importlib.util.find_spec("ins_pricing") is None:
20
- repo_root = Path(__file__).resolve().parents[2]
21
- if str(repo_root) not in sys.path:
22
- sys.path.insert(0, str(repo_root))
18
+
19
+ def _ensure_repo_root() -> None:
20
+ if __package__ not in {None, ""}:
21
+ return
22
+ if importlib.util.find_spec("ins_pricing") is not None:
23
+ return
24
+ bootstrap_path = Path(__file__).resolve().parents[1] / "utils" / "bootstrap.py"
25
+ spec = importlib.util.spec_from_file_location("ins_pricing.cli.utils.bootstrap", bootstrap_path)
26
+ if spec is None or spec.loader is None:
27
+ return
28
+ module = importlib.util.module_from_spec(spec)
29
+ spec.loader.exec_module(module)
30
+ module.ensure_repo_root()
31
+
32
+
33
+ _ensure_repo_root()
23
34
 
24
35
  import argparse
25
36
  import hashlib
@@ -1114,10 +1125,21 @@ def train_from_config(args: argparse.Namespace) -> None:
1114
1125
  output_override=args.output_dir,
1115
1126
  )
1116
1127
  output_dir = output_cfg["output_dir"]
1117
- reuse_best_params = bool(
1118
- args.reuse_best_params or runtime_cfg["reuse_best_params"])
1119
- xgb_max_depth_max = runtime_cfg["xgb_max_depth_max"]
1120
- xgb_n_estimators_max = runtime_cfg["xgb_n_estimators_max"]
1128
+ reuse_best_params = bool(
1129
+ args.reuse_best_params or runtime_cfg["reuse_best_params"])
1130
+ xgb_max_depth_max = runtime_cfg["xgb_max_depth_max"]
1131
+ xgb_n_estimators_max = runtime_cfg["xgb_n_estimators_max"]
1132
+ xgb_gpu_id = runtime_cfg["xgb_gpu_id"]
1133
+ xgb_cleanup_per_fold = runtime_cfg["xgb_cleanup_per_fold"]
1134
+ xgb_cleanup_synchronize = runtime_cfg["xgb_cleanup_synchronize"]
1135
+ xgb_use_dmatrix = runtime_cfg["xgb_use_dmatrix"]
1136
+ ft_cleanup_per_fold = runtime_cfg["ft_cleanup_per_fold"]
1137
+ ft_cleanup_synchronize = runtime_cfg["ft_cleanup_synchronize"]
1138
+ resn_cleanup_per_fold = runtime_cfg["resn_cleanup_per_fold"]
1139
+ resn_cleanup_synchronize = runtime_cfg["resn_cleanup_synchronize"]
1140
+ gnn_cleanup_per_fold = runtime_cfg["gnn_cleanup_per_fold"]
1141
+ gnn_cleanup_synchronize = runtime_cfg["gnn_cleanup_synchronize"]
1142
+ optuna_cleanup_synchronize = runtime_cfg["optuna_cleanup_synchronize"]
1121
1143
  optuna_storage = runtime_cfg["optuna_storage"]
1122
1144
  optuna_study_prefix = runtime_cfg["optuna_study_prefix"]
1123
1145
  best_params_files = runtime_cfg["best_params_files"]
@@ -1249,9 +1271,20 @@ def train_from_config(args: argparse.Namespace) -> None:
1249
1271
  "use_ft_ddp": use_ft_ddp,
1250
1272
  "use_gnn_ddp": use_gnn_ddp,
1251
1273
  "output_dir": output_dir,
1252
- "xgb_max_depth_max": xgb_max_depth_max,
1253
- "xgb_n_estimators_max": xgb_n_estimators_max,
1254
- "resn_weight_decay": cfg.get("resn_weight_decay"),
1274
+ "xgb_max_depth_max": xgb_max_depth_max,
1275
+ "xgb_n_estimators_max": xgb_n_estimators_max,
1276
+ "xgb_gpu_id": xgb_gpu_id,
1277
+ "xgb_cleanup_per_fold": xgb_cleanup_per_fold,
1278
+ "xgb_cleanup_synchronize": xgb_cleanup_synchronize,
1279
+ "xgb_use_dmatrix": xgb_use_dmatrix,
1280
+ "ft_cleanup_per_fold": ft_cleanup_per_fold,
1281
+ "ft_cleanup_synchronize": ft_cleanup_synchronize,
1282
+ "resn_cleanup_per_fold": resn_cleanup_per_fold,
1283
+ "resn_cleanup_synchronize": resn_cleanup_synchronize,
1284
+ "gnn_cleanup_per_fold": gnn_cleanup_per_fold,
1285
+ "gnn_cleanup_synchronize": gnn_cleanup_synchronize,
1286
+ "optuna_cleanup_synchronize": optuna_cleanup_synchronize,
1287
+ "resn_weight_decay": cfg.get("resn_weight_decay"),
1255
1288
  "final_ensemble": bool(cfg.get("final_ensemble", False)),
1256
1289
  "final_ensemble_k": int(cfg.get("final_ensemble_k", 3)),
1257
1290
  "final_refit": bool(cfg.get("final_refit", True)),
@@ -0,0 +1,23 @@
1
+ """Bootstrap helpers for running CLI modules as scripts."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import sys
6
+ from pathlib import Path
7
+ from typing import Optional
8
+
9
+
10
+ def _find_repo_root(start: Optional[Path] = None) -> Path:
11
+ anchor = (start or Path(__file__)).resolve()
12
+ for parent in [anchor] + list(anchor.parents):
13
+ if (parent / "ins_pricing").is_dir():
14
+ return parent
15
+ return anchor.parent
16
+
17
+
18
+ def ensure_repo_root(repo_root: Optional[Path] = None) -> Path:
19
+ """Ensure the repository root (parent of ins_pricing/) is on sys.path."""
20
+ root = _find_repo_root(repo_root)
21
+ if str(root) not in sys.path:
22
+ sys.path.insert(0, str(root))
23
+ return root
@@ -339,21 +339,40 @@ def resolve_split_config(cfg: Dict[str, Any]) -> Dict[str, Any]:
339
339
  }
340
340
 
341
341
 
342
- def resolve_runtime_config(cfg: Dict[str, Any]) -> Dict[str, Any]:
343
- return {
344
- "save_preprocess": bool(cfg.get("save_preprocess", False)),
345
- "preprocess_artifact_path": cfg.get("preprocess_artifact_path"),
346
- "rand_seed": cfg.get("rand_seed", 13),
347
- "epochs": cfg.get("epochs", 50),
348
- "plot_path_style": cfg.get("plot_path_style"),
349
- "reuse_best_params": bool(cfg.get("reuse_best_params", False)),
350
- "xgb_max_depth_max": int(cfg.get("xgb_max_depth_max", 25)),
351
- "xgb_n_estimators_max": int(cfg.get("xgb_n_estimators_max", 500)),
352
- "optuna_storage": cfg.get("optuna_storage"),
353
- "optuna_study_prefix": cfg.get("optuna_study_prefix"),
354
- "best_params_files": cfg.get("best_params_files"),
355
- "bo_sample_limit": cfg.get("bo_sample_limit"),
356
- "cache_predictions": bool(cfg.get("cache_predictions", False)),
342
+ def resolve_runtime_config(cfg: Dict[str, Any]) -> Dict[str, Any]:
343
+ xgb_gpu_id = cfg.get("xgb_gpu_id")
344
+ if isinstance(xgb_gpu_id, str) and xgb_gpu_id.strip() == "":
345
+ xgb_gpu_id = None
346
+ if xgb_gpu_id is not None:
347
+ try:
348
+ xgb_gpu_id = int(xgb_gpu_id)
349
+ except (TypeError, ValueError):
350
+ xgb_gpu_id = None
351
+ return {
352
+ "save_preprocess": bool(cfg.get("save_preprocess", False)),
353
+ "preprocess_artifact_path": cfg.get("preprocess_artifact_path"),
354
+ "rand_seed": cfg.get("rand_seed", 13),
355
+ "epochs": cfg.get("epochs", 50),
356
+ "plot_path_style": cfg.get("plot_path_style"),
357
+ "reuse_best_params": bool(cfg.get("reuse_best_params", False)),
358
+ "xgb_max_depth_max": int(cfg.get("xgb_max_depth_max", 25)),
359
+ "xgb_n_estimators_max": int(cfg.get("xgb_n_estimators_max", 500)),
360
+ "xgb_gpu_id": xgb_gpu_id,
361
+ "xgb_cleanup_per_fold": bool(cfg.get("xgb_cleanup_per_fold", False)),
362
+ "xgb_cleanup_synchronize": bool(cfg.get("xgb_cleanup_synchronize", False)),
363
+ "xgb_use_dmatrix": bool(cfg.get("xgb_use_dmatrix", True)),
364
+ "ft_cleanup_per_fold": bool(cfg.get("ft_cleanup_per_fold", False)),
365
+ "ft_cleanup_synchronize": bool(cfg.get("ft_cleanup_synchronize", False)),
366
+ "resn_cleanup_per_fold": bool(cfg.get("resn_cleanup_per_fold", False)),
367
+ "resn_cleanup_synchronize": bool(cfg.get("resn_cleanup_synchronize", False)),
368
+ "gnn_cleanup_per_fold": bool(cfg.get("gnn_cleanup_per_fold", False)),
369
+ "gnn_cleanup_synchronize": bool(cfg.get("gnn_cleanup_synchronize", False)),
370
+ "optuna_cleanup_synchronize": bool(cfg.get("optuna_cleanup_synchronize", False)),
371
+ "optuna_storage": cfg.get("optuna_storage"),
372
+ "optuna_study_prefix": cfg.get("optuna_study_prefix"),
373
+ "best_params_files": cfg.get("best_params_files"),
374
+ "bo_sample_limit": cfg.get("bo_sample_limit"),
375
+ "cache_predictions": bool(cfg.get("cache_predictions", False)),
357
376
  "prediction_cache_dir": cfg.get("prediction_cache_dir"),
358
377
  "prediction_cache_format": cfg.get("prediction_cache_format", "parquet"),
359
378
  "ddp_min_rows": cfg.get("ddp_min_rows", 50000),
@@ -12,12 +12,14 @@ Usage:
12
12
 
13
13
  from __future__ import annotations
14
14
 
15
- import importlib
16
- import os
17
- import sys
15
+ import importlib
16
+ import os
17
+ import sys
18
18
  from dataclasses import dataclass, field
19
19
  from pathlib import Path
20
- from typing import Any, Callable, Dict, List, Optional, Tuple, Type
20
+ from typing import Any, Callable, Dict, List, Optional, Tuple, Type
21
+
22
+ from ins_pricing.cli.utils.bootstrap import ensure_repo_root
21
23
 
22
24
 
23
25
  @dataclass
@@ -381,13 +383,11 @@ def resolve_imports() -> ResolvedImports:
381
383
 
382
384
 
383
385
  # Convenience function for backward compatibility
384
- def setup_sys_path() -> None:
385
- """Ensure the repository root is in sys.path for imports."""
386
- try:
387
- if importlib.util.find_spec("ins_pricing") is not None:
388
- return
389
- except Exception:
390
- pass
391
- repo_root = Path(__file__).resolve().parents[3]
392
- if str(repo_root) not in sys.path:
393
- sys.path.insert(0, str(repo_root))
386
+ def setup_sys_path() -> None:
387
+ """Ensure the repository root is in sys.path for imports."""
388
+ try:
389
+ if importlib.util.find_spec("ins_pricing") is not None:
390
+ return
391
+ except Exception:
392
+ pass
393
+ ensure_repo_root()