ins-pricing 0.4.5__py3-none-any.whl → 0.5.1__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 (93) hide show
  1. ins_pricing/README.md +48 -22
  2. ins_pricing/__init__.py +142 -90
  3. ins_pricing/cli/BayesOpt_entry.py +58 -46
  4. ins_pricing/cli/BayesOpt_incremental.py +77 -110
  5. ins_pricing/cli/Explain_Run.py +42 -23
  6. ins_pricing/cli/Explain_entry.py +551 -577
  7. ins_pricing/cli/Pricing_Run.py +42 -23
  8. ins_pricing/cli/bayesopt_entry_runner.py +51 -16
  9. ins_pricing/cli/utils/bootstrap.py +23 -0
  10. ins_pricing/cli/utils/cli_common.py +256 -256
  11. ins_pricing/cli/utils/cli_config.py +379 -360
  12. ins_pricing/cli/utils/import_resolver.py +375 -358
  13. ins_pricing/cli/utils/notebook_utils.py +256 -242
  14. ins_pricing/cli/watchdog_run.py +216 -198
  15. ins_pricing/frontend/__init__.py +10 -10
  16. ins_pricing/frontend/app.py +132 -61
  17. ins_pricing/frontend/config_builder.py +33 -0
  18. ins_pricing/frontend/example_config.json +11 -0
  19. ins_pricing/frontend/example_workflows.py +1 -1
  20. ins_pricing/frontend/runner.py +340 -388
  21. ins_pricing/governance/__init__.py +20 -20
  22. ins_pricing/governance/release.py +159 -159
  23. ins_pricing/modelling/README.md +1 -1
  24. ins_pricing/modelling/__init__.py +147 -92
  25. ins_pricing/modelling/{core/bayesopt → bayesopt}/README.md +31 -13
  26. ins_pricing/modelling/{core/bayesopt → bayesopt}/__init__.py +64 -102
  27. ins_pricing/modelling/{core/bayesopt → bayesopt}/config_components.py +12 -0
  28. ins_pricing/modelling/{core/bayesopt → bayesopt}/config_preprocess.py +589 -552
  29. ins_pricing/modelling/{core/bayesopt → bayesopt}/core.py +987 -958
  30. ins_pricing/modelling/{core/bayesopt → bayesopt}/model_explain_mixin.py +296 -296
  31. ins_pricing/modelling/{core/bayesopt → bayesopt}/model_plotting_mixin.py +488 -548
  32. ins_pricing/modelling/{core/bayesopt → bayesopt}/models/__init__.py +27 -27
  33. ins_pricing/modelling/{core/bayesopt → bayesopt}/models/model_ft_components.py +349 -342
  34. ins_pricing/modelling/{core/bayesopt → bayesopt}/models/model_ft_trainer.py +921 -913
  35. ins_pricing/modelling/{core/bayesopt → bayesopt}/models/model_gnn.py +794 -785
  36. ins_pricing/modelling/{core/bayesopt → bayesopt}/models/model_resn.py +454 -446
  37. ins_pricing/modelling/bayesopt/trainers/__init__.py +19 -0
  38. ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_base.py +1294 -1282
  39. ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_ft.py +64 -56
  40. ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_glm.py +203 -198
  41. ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_gnn.py +333 -325
  42. ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_resn.py +279 -267
  43. ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_xgb.py +515 -313
  44. ins_pricing/modelling/bayesopt/utils/__init__.py +67 -0
  45. ins_pricing/modelling/bayesopt/utils/constants.py +21 -0
  46. ins_pricing/modelling/{core/bayesopt → bayesopt}/utils/distributed_utils.py +193 -186
  47. ins_pricing/modelling/bayesopt/utils/io_utils.py +7 -0
  48. ins_pricing/modelling/bayesopt/utils/losses.py +27 -0
  49. ins_pricing/modelling/bayesopt/utils/metrics_and_devices.py +17 -0
  50. ins_pricing/modelling/{core/bayesopt → bayesopt}/utils/torch_trainer_mixin.py +636 -623
  51. ins_pricing/modelling/{core/evaluation.py → evaluation.py} +113 -104
  52. ins_pricing/modelling/explain/__init__.py +55 -55
  53. ins_pricing/modelling/explain/metrics.py +27 -174
  54. ins_pricing/modelling/explain/permutation.py +237 -237
  55. ins_pricing/modelling/plotting/__init__.py +40 -36
  56. ins_pricing/modelling/plotting/compat.py +228 -0
  57. ins_pricing/modelling/plotting/curves.py +572 -572
  58. ins_pricing/modelling/plotting/diagnostics.py +163 -163
  59. ins_pricing/modelling/plotting/geo.py +362 -362
  60. ins_pricing/modelling/plotting/importance.py +121 -121
  61. ins_pricing/pricing/__init__.py +27 -27
  62. ins_pricing/pricing/factors.py +67 -56
  63. ins_pricing/production/__init__.py +35 -25
  64. ins_pricing/production/{predict.py → inference.py} +140 -57
  65. ins_pricing/production/monitoring.py +8 -21
  66. ins_pricing/reporting/__init__.py +11 -11
  67. ins_pricing/setup.py +1 -1
  68. ins_pricing/tests/production/test_inference.py +90 -0
  69. ins_pricing/utils/__init__.py +112 -78
  70. ins_pricing/utils/device.py +258 -237
  71. ins_pricing/utils/features.py +53 -0
  72. ins_pricing/utils/io.py +72 -0
  73. ins_pricing/utils/logging.py +34 -1
  74. ins_pricing/{modelling/core/bayesopt/utils → utils}/losses.py +125 -129
  75. ins_pricing/utils/metrics.py +158 -24
  76. ins_pricing/utils/numerics.py +76 -0
  77. ins_pricing/utils/paths.py +9 -1
  78. ins_pricing/utils/profiling.py +8 -4
  79. {ins_pricing-0.4.5.dist-info → ins_pricing-0.5.1.dist-info}/METADATA +1 -1
  80. ins_pricing-0.5.1.dist-info/RECORD +132 -0
  81. ins_pricing/modelling/core/BayesOpt.py +0 -146
  82. ins_pricing/modelling/core/__init__.py +0 -1
  83. ins_pricing/modelling/core/bayesopt/trainers/__init__.py +0 -19
  84. ins_pricing/modelling/core/bayesopt/utils/__init__.py +0 -86
  85. ins_pricing/modelling/core/bayesopt/utils/constants.py +0 -183
  86. ins_pricing/modelling/core/bayesopt/utils/io_utils.py +0 -126
  87. ins_pricing/modelling/core/bayesopt/utils/metrics_and_devices.py +0 -555
  88. ins_pricing/modelling/core/bayesopt/utils.py +0 -105
  89. ins_pricing/modelling/core/bayesopt/utils_backup.py +0 -1503
  90. ins_pricing/tests/production/test_predict.py +0 -233
  91. ins_pricing-0.4.5.dist-info/RECORD +0 -130
  92. {ins_pricing-0.4.5.dist-info → ins_pricing-0.5.1.dist-info}/WHEEL +0 -0
  93. {ins_pricing-0.4.5.dist-info → ins_pricing-0.5.1.dist-info}/top_level.txt +0 -0
@@ -1,376 +1,393 @@
1
- """Unified import resolver for CLI modules.
2
-
3
- This module provides a single source of truth for all import fallback chains,
4
- eliminating the need for nested try/except blocks in multiple CLI files.
5
-
6
- Usage:
7
- from ins_pricing.cli.utils.import_resolver import resolve_imports
8
- imports = resolve_imports()
9
- ropt = imports.bayesopt
10
- PLOT_MODEL_LABELS = imports.PLOT_MODEL_LABELS
11
- """
12
-
13
- from __future__ import annotations
14
-
1
+ """Unified import resolver for CLI modules.
2
+
3
+ This module provides a single source of truth for all import fallback chains,
4
+ eliminating the need for nested try/except blocks in multiple CLI files.
5
+
6
+ Usage:
7
+ from ins_pricing.cli.utils.import_resolver import resolve_imports
8
+ imports = resolve_imports()
9
+ ropt = imports.bayesopt
10
+ PLOT_MODEL_LABELS = imports.PLOT_MODEL_LABELS
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
15
  import importlib
16
16
  import os
17
17
  import sys
18
- from dataclasses import dataclass, field
19
- from pathlib import Path
18
+ from dataclasses import dataclass, field
19
+ from pathlib import Path
20
20
  from typing import Any, Callable, Dict, List, Optional, Tuple, Type
21
21
 
22
-
23
- @dataclass
24
- class ResolvedImports:
25
- """Container for resolved imports from the bayesopt ecosystem."""
26
-
27
- # Core bayesopt module
28
- bayesopt: Any = None
29
-
30
- # CLI common utilities
31
- PLOT_MODEL_LABELS: Dict[str, Tuple[str, str]] = field(default_factory=dict)
32
- PYTORCH_TRAINERS: List[str] = field(default_factory=list)
33
- build_model_names: Optional[Callable] = None
34
- dedupe_preserve_order: Optional[Callable] = None
35
- load_dataset: Optional[Callable] = None
36
- parse_model_pairs: Optional[Callable] = None
37
- resolve_data_path: Optional[Callable] = None
38
- resolve_path: Optional[Callable] = None
39
- fingerprint_file: Optional[Callable] = None
40
- coerce_dataset_types: Optional[Callable] = None
41
- split_train_test: Optional[Callable] = None
42
-
43
- # CLI config utilities
44
- add_config_json_arg: Optional[Callable] = None
45
- add_output_dir_arg: Optional[Callable] = None
46
- resolve_and_load_config: Optional[Callable] = None
47
- resolve_data_config: Optional[Callable] = None
48
- resolve_report_config: Optional[Callable] = None
49
- resolve_split_config: Optional[Callable] = None
50
- resolve_runtime_config: Optional[Callable] = None
51
- resolve_output_dirs: Optional[Callable] = None
52
-
53
- # Evaluation utilities
54
- bootstrap_ci: Optional[Callable] = None
55
- calibrate_predictions: Optional[Callable] = None
56
- metrics_report: Optional[Callable] = None
57
- select_threshold: Optional[Callable] = None
58
-
59
- # Governance and reporting
60
- ModelArtifact: Optional[Type] = None
61
- ModelRegistry: Optional[Type] = None
62
- drift_psi_report: Optional[Callable] = None
63
- group_metrics: Optional[Callable] = None
64
- ReportPayload: Optional[Type] = None
65
- write_report: Optional[Callable] = None
66
-
67
- # Logging
68
- configure_run_logging: Optional[Callable] = None
69
-
70
- # Plotting
71
- plot_loss_curve: Optional[Callable] = None
72
-
73
-
74
- def _debug_imports_enabled() -> bool:
75
- value = os.environ.get("BAYESOPT_DEBUG_IMPORTS")
76
- if value is None:
77
- return False
78
- return str(value).strip().lower() in {"1", "true", "yes", "y", "on"}
79
-
80
-
81
- def _try_import(module_path: str, attr_name: Optional[str] = None) -> Optional[Any]:
82
- """Attempt to import a module or attribute, returning None on failure."""
83
- try:
84
- module = importlib.import_module(module_path)
85
- if attr_name:
86
- result = getattr(module, attr_name, None)
87
- else:
88
- result = module
89
- if _debug_imports_enabled():
90
- origin = getattr(module, "__file__", None)
91
- origin = origin or getattr(module, "__path__", None)
92
- print(
93
- f"[BAYESOPT_DEBUG_IMPORTS] imported {module_path}"
94
- f"{'::' + attr_name if attr_name else ''} from {origin}",
95
- file=sys.stderr,
96
- flush=True,
97
- )
98
- return result
99
- except Exception as exc:
100
- if _debug_imports_enabled():
101
- print(
102
- f"[BAYESOPT_DEBUG_IMPORTS] failed import {module_path}"
103
- f"{'::' + attr_name if attr_name else ''}: {exc.__class__.__name__}: {exc}",
104
- file=sys.stderr,
105
- flush=True,
106
- )
107
- return None
108
-
109
-
110
- def _try_import_from_paths(
111
- paths: List[str],
112
- attr_name: Optional[str] = None
113
- ) -> Optional[Any]:
114
- """Try importing from multiple module paths, return first success."""
115
- for path in paths:
116
- result = _try_import(path, attr_name)
117
- if result is not None:
118
- return result
119
- return None
120
-
121
-
22
+ from ins_pricing.cli.utils.bootstrap import ensure_repo_root
23
+
24
+
25
+ @dataclass
26
+ class ResolvedImports:
27
+ """Container for resolved imports from the bayesopt ecosystem."""
28
+
29
+ # Core bayesopt module
30
+ bayesopt: Any = None
31
+
32
+ # CLI common utilities
33
+ PLOT_MODEL_LABELS: Dict[str, Tuple[str, str]] = field(default_factory=dict)
34
+ PYTORCH_TRAINERS: List[str] = field(default_factory=list)
35
+ build_model_names: Optional[Callable] = None
36
+ dedupe_preserve_order: Optional[Callable] = None
37
+ load_dataset: Optional[Callable] = None
38
+ parse_model_pairs: Optional[Callable] = None
39
+ resolve_data_path: Optional[Callable] = None
40
+ resolve_path: Optional[Callable] = None
41
+ fingerprint_file: Optional[Callable] = None
42
+ coerce_dataset_types: Optional[Callable] = None
43
+ split_train_test: Optional[Callable] = None
44
+
45
+ # CLI config utilities
46
+ add_config_json_arg: Optional[Callable] = None
47
+ add_output_dir_arg: Optional[Callable] = None
48
+ resolve_and_load_config: Optional[Callable] = None
49
+ resolve_data_config: Optional[Callable] = None
50
+ resolve_report_config: Optional[Callable] = None
51
+ resolve_explain_save_root: Optional[Callable] = None
52
+ resolve_explain_save_dir: Optional[Callable] = None
53
+ resolve_explain_output_overrides: Optional[Callable] = None
54
+ resolve_model_path_value: Optional[Callable] = None
55
+ resolve_split_config: Optional[Callable] = None
56
+ resolve_runtime_config: Optional[Callable] = None
57
+ resolve_output_dirs: Optional[Callable] = None
58
+
59
+ # Evaluation utilities
60
+ bootstrap_ci: Optional[Callable] = None
61
+ calibrate_predictions: Optional[Callable] = None
62
+ metrics_report: Optional[Callable] = None
63
+ select_threshold: Optional[Callable] = None
64
+
65
+ # Governance and reporting
66
+ ModelArtifact: Optional[Type] = None
67
+ ModelRegistry: Optional[Type] = None
68
+ drift_psi_report: Optional[Callable] = None
69
+ group_metrics: Optional[Callable] = None
70
+ ReportPayload: Optional[Type] = None
71
+ write_report: Optional[Callable] = None
72
+
73
+ # Logging
74
+ configure_run_logging: Optional[Callable] = None
75
+
76
+ # Plotting
77
+ plot_loss_curve: Optional[Callable] = None
78
+
79
+
80
+ def _debug_imports_enabled() -> bool:
81
+ value = os.environ.get("BAYESOPT_DEBUG_IMPORTS")
82
+ if value is None:
83
+ return False
84
+ return str(value).strip().lower() in {"1", "true", "yes", "y", "on"}
85
+
86
+
87
+ def _try_import(module_path: str, attr_name: Optional[str] = None) -> Optional[Any]:
88
+ """Attempt to import a module or attribute, returning None on failure."""
89
+ try:
90
+ module = importlib.import_module(module_path)
91
+ if attr_name:
92
+ result = getattr(module, attr_name, None)
93
+ else:
94
+ result = module
95
+ if _debug_imports_enabled():
96
+ origin = getattr(module, "__file__", None)
97
+ origin = origin or getattr(module, "__path__", None)
98
+ print(
99
+ f"[BAYESOPT_DEBUG_IMPORTS] imported {module_path}"
100
+ f"{'::' + attr_name if attr_name else ''} from {origin}",
101
+ file=sys.stderr,
102
+ flush=True,
103
+ )
104
+ return result
105
+ except Exception as exc:
106
+ if _debug_imports_enabled():
107
+ print(
108
+ f"[BAYESOPT_DEBUG_IMPORTS] failed import {module_path}"
109
+ f"{'::' + attr_name if attr_name else ''}: {exc.__class__.__name__}: {exc}",
110
+ file=sys.stderr,
111
+ flush=True,
112
+ )
113
+ return None
114
+
115
+
116
+ def _try_import_from_paths(
117
+ paths: List[str],
118
+ attr_name: Optional[str] = None
119
+ ) -> Optional[Any]:
120
+ """Try importing from multiple module paths, return first success."""
121
+ for path in paths:
122
+ result = _try_import(path, attr_name)
123
+ if result is not None:
124
+ return result
125
+ return None
126
+
127
+
122
128
  def _resolve_bayesopt() -> Optional[Any]:
123
129
  """Resolve the bayesopt module from multiple possible locations."""
124
130
  paths = [
125
- "ins_pricing.modelling.core.bayesopt",
131
+ "ins_pricing.modelling.bayesopt",
126
132
  "bayesopt",
127
133
  "BayesOpt",
128
134
  ]
129
- return _try_import_from_paths(paths)
130
-
131
-
132
- def _resolve_cli_common() -> Dict[str, Any]:
133
- """Resolve CLI common utilities."""
134
- paths = [
135
- "ins_pricing.cli.utils.cli_common",
136
- "cli.utils.cli_common",
137
- "utils.cli_common",
138
- ]
139
-
140
- attrs = [
141
- "PLOT_MODEL_LABELS",
142
- "PYTORCH_TRAINERS",
143
- "build_model_names",
144
- "dedupe_preserve_order",
145
- "load_dataset",
146
- "parse_model_pairs",
147
- "resolve_data_path",
148
- "resolve_path",
149
- "fingerprint_file",
150
- "coerce_dataset_types",
151
- "split_train_test",
152
- ]
153
-
154
- results = {}
155
- for path in paths:
156
- module = _try_import(path)
157
- if module is not None:
158
- for attr in attrs:
159
- if attr not in results or results[attr] is None:
160
- results[attr] = getattr(module, attr, None)
161
- # If we got most attributes, break
162
- if sum(1 for v in results.values() if v is not None) >= len(attrs) // 2:
163
- break
164
-
165
- return results
166
-
167
-
168
- def _resolve_cli_config() -> Dict[str, Any]:
169
- """Resolve CLI config utilities."""
170
- paths = [
171
- "ins_pricing.cli.utils.cli_config",
172
- "cli.utils.cli_config",
173
- "utils.cli_config",
174
- ]
175
-
176
- attrs = [
177
- "add_config_json_arg",
178
- "add_output_dir_arg",
179
- "resolve_and_load_config",
180
- "resolve_data_config",
181
- "resolve_report_config",
182
- "resolve_split_config",
183
- "resolve_runtime_config",
184
- "resolve_output_dirs",
185
- ]
186
-
187
- results = {}
188
- for path in paths:
189
- module = _try_import(path)
190
- if module is not None:
191
- for attr in attrs:
192
- if attr not in results or results[attr] is None:
193
- results[attr] = getattr(module, attr, None)
194
- if sum(1 for v in results.values() if v is not None) >= len(attrs) // 2:
195
- break
196
-
197
- return results
198
-
199
-
135
+ return _try_import_from_paths(paths)
136
+
137
+
138
+ def _resolve_cli_common() -> Dict[str, Any]:
139
+ """Resolve CLI common utilities."""
140
+ paths = [
141
+ "ins_pricing.cli.utils.cli_common",
142
+ "cli.utils.cli_common",
143
+ "utils.cli_common",
144
+ ]
145
+
146
+ attrs = [
147
+ "PLOT_MODEL_LABELS",
148
+ "PYTORCH_TRAINERS",
149
+ "build_model_names",
150
+ "dedupe_preserve_order",
151
+ "load_dataset",
152
+ "parse_model_pairs",
153
+ "resolve_data_path",
154
+ "resolve_path",
155
+ "fingerprint_file",
156
+ "coerce_dataset_types",
157
+ "split_train_test",
158
+ ]
159
+
160
+ results = {}
161
+ for path in paths:
162
+ module = _try_import(path)
163
+ if module is not None:
164
+ for attr in attrs:
165
+ if attr not in results or results[attr] is None:
166
+ results[attr] = getattr(module, attr, None)
167
+ # If we got most attributes, break
168
+ if sum(1 for v in results.values() if v is not None) >= len(attrs) // 2:
169
+ break
170
+
171
+ return results
172
+
173
+
174
+ def _resolve_cli_config() -> Dict[str, Any]:
175
+ """Resolve CLI config utilities."""
176
+ paths = [
177
+ "ins_pricing.cli.utils.cli_config",
178
+ "cli.utils.cli_config",
179
+ "utils.cli_config",
180
+ ]
181
+
182
+ attrs = [
183
+ "add_config_json_arg",
184
+ "add_output_dir_arg",
185
+ "resolve_and_load_config",
186
+ "resolve_data_config",
187
+ "resolve_report_config",
188
+ "resolve_explain_save_root",
189
+ "resolve_explain_save_dir",
190
+ "resolve_explain_output_overrides",
191
+ "resolve_model_path_value",
192
+ "resolve_split_config",
193
+ "resolve_runtime_config",
194
+ "resolve_output_dirs",
195
+ ]
196
+
197
+ results = {}
198
+ for path in paths:
199
+ module = _try_import(path)
200
+ if module is not None:
201
+ for attr in attrs:
202
+ if attr not in results or results[attr] is None:
203
+ results[attr] = getattr(module, attr, None)
204
+ if sum(1 for v in results.values() if v is not None) >= len(attrs) // 2:
205
+ break
206
+
207
+ return results
208
+
209
+
200
210
  def _resolve_evaluation() -> Dict[str, Any]:
201
211
  """Resolve evaluation utilities."""
202
212
  paths = [
203
- "ins_pricing.modelling.core.evaluation",
213
+ "ins_pricing.modelling.evaluation",
204
214
  "evaluation",
205
215
  ]
206
-
207
- results = {}
208
- for path in paths:
209
- module = _try_import(path)
210
- if module is not None:
211
- results["bootstrap_ci"] = getattr(module, "bootstrap_ci", None)
212
- results["calibrate_predictions"] = getattr(module, "calibrate_predictions", None)
213
- results["metrics_report"] = getattr(module, "metrics_report", None)
214
- results["select_threshold"] = getattr(module, "select_threshold", None)
215
- if any(v is not None for v in results.values()):
216
- break
217
-
218
- return results
219
-
220
-
221
- def _resolve_governance() -> Dict[str, Any]:
222
- """Resolve governance and reporting utilities."""
223
- results = {}
224
-
225
- # ModelRegistry and ModelArtifact
226
- registry_paths = [
227
- "ins_pricing.governance.registry",
228
- ]
229
- for path in registry_paths:
230
- module = _try_import(path)
231
- if module is not None:
232
- results["ModelArtifact"] = getattr(module, "ModelArtifact", None)
233
- results["ModelRegistry"] = getattr(module, "ModelRegistry", None)
234
- break
235
-
236
- # PSI report
237
- psi_paths = [
238
- "ins_pricing.production",
239
- ]
240
- for path in psi_paths:
241
- module = _try_import(path)
242
- if module is not None:
243
- results["drift_psi_report"] = getattr(module, "psi_report", None)
244
- break
245
-
246
- # Group metrics
247
- monitoring_paths = [
248
- "ins_pricing.production.monitoring",
249
- ]
250
- for path in monitoring_paths:
251
- module = _try_import(path)
252
- if module is not None:
253
- results["group_metrics"] = getattr(module, "group_metrics", None)
254
- break
255
-
256
- # Report builder
257
- report_paths = [
258
- "ins_pricing.reporting.report_builder",
259
- ]
260
- for path in report_paths:
261
- module = _try_import(path)
262
- if module is not None:
263
- results["ReportPayload"] = getattr(module, "ReportPayload", None)
264
- results["write_report"] = getattr(module, "write_report", None)
265
- break
266
-
267
- return results
268
-
269
-
270
- def _resolve_logging() -> Dict[str, Any]:
271
- """Resolve logging utilities."""
272
- paths = [
273
- "ins_pricing.cli.utils.run_logging",
274
- "cli.utils.run_logging",
275
- "utils.run_logging",
276
- ]
277
-
278
- results = {}
279
- for path in paths:
280
- module = _try_import(path)
281
- if module is not None:
282
- results["configure_run_logging"] = getattr(module, "configure_run_logging", None)
283
- break
284
-
285
- return results
286
-
287
-
288
- def _resolve_plotting() -> Dict[str, Any]:
289
- """Resolve plotting utilities."""
290
- paths = [
291
- "ins_pricing.modelling.plotting.diagnostics",
292
- "ins_pricing.plotting.diagnostics",
293
- ]
294
-
295
- results = {}
296
- for path in paths:
297
- module = _try_import(path)
298
- if module is not None:
299
- results["plot_loss_curve"] = getattr(module, "plot_loss_curve", None)
300
- break
301
-
302
- return results
303
-
304
-
305
- def resolve_imports() -> ResolvedImports:
306
- """Resolve all imports from the bayesopt ecosystem.
307
-
308
- This function attempts to import modules from multiple possible locations,
309
- handling the various ways the package might be installed or run.
310
-
311
- Returns:
312
- ResolvedImports object containing all resolved imports.
313
- """
314
- imports = ResolvedImports()
315
-
316
- # Resolve bayesopt core
317
- imports.bayesopt = _resolve_bayesopt()
318
-
319
- # Resolve CLI common utilities
320
- cli_common = _resolve_cli_common()
321
- imports.PLOT_MODEL_LABELS = cli_common.get("PLOT_MODEL_LABELS", {})
322
- imports.PYTORCH_TRAINERS = cli_common.get("PYTORCH_TRAINERS", [])
323
- imports.build_model_names = cli_common.get("build_model_names")
324
- imports.dedupe_preserve_order = cli_common.get("dedupe_preserve_order")
325
- imports.load_dataset = cli_common.get("load_dataset")
326
- imports.parse_model_pairs = cli_common.get("parse_model_pairs")
327
- imports.resolve_data_path = cli_common.get("resolve_data_path")
328
- imports.resolve_path = cli_common.get("resolve_path")
329
- imports.fingerprint_file = cli_common.get("fingerprint_file")
330
- imports.coerce_dataset_types = cli_common.get("coerce_dataset_types")
331
- imports.split_train_test = cli_common.get("split_train_test")
332
-
333
- # Resolve CLI config utilities
334
- cli_config = _resolve_cli_config()
335
- imports.add_config_json_arg = cli_config.get("add_config_json_arg")
336
- imports.add_output_dir_arg = cli_config.get("add_output_dir_arg")
337
- imports.resolve_and_load_config = cli_config.get("resolve_and_load_config")
338
- imports.resolve_data_config = cli_config.get("resolve_data_config")
339
- imports.resolve_report_config = cli_config.get("resolve_report_config")
340
- imports.resolve_split_config = cli_config.get("resolve_split_config")
341
- imports.resolve_runtime_config = cli_config.get("resolve_runtime_config")
342
- imports.resolve_output_dirs = cli_config.get("resolve_output_dirs")
343
-
344
- # Resolve evaluation utilities
345
- evaluation = _resolve_evaluation()
346
- imports.bootstrap_ci = evaluation.get("bootstrap_ci")
347
- imports.calibrate_predictions = evaluation.get("calibrate_predictions")
348
- imports.metrics_report = evaluation.get("metrics_report")
349
- imports.select_threshold = evaluation.get("select_threshold")
350
-
351
- # Resolve governance and reporting
352
- governance = _resolve_governance()
353
- imports.ModelArtifact = governance.get("ModelArtifact")
354
- imports.ModelRegistry = governance.get("ModelRegistry")
355
- imports.drift_psi_report = governance.get("drift_psi_report")
356
- imports.group_metrics = governance.get("group_metrics")
357
- imports.ReportPayload = governance.get("ReportPayload")
358
- imports.write_report = governance.get("write_report")
359
-
360
- # Resolve logging
361
- logging_utils = _resolve_logging()
362
- imports.configure_run_logging = logging_utils.get("configure_run_logging")
363
-
364
- # Resolve plotting
365
- plotting = _resolve_plotting()
366
- imports.plot_loss_curve = plotting.get("plot_loss_curve")
367
-
368
- return imports
369
-
370
-
371
- # Convenience function for backward compatibility
216
+
217
+ results = {}
218
+ for path in paths:
219
+ module = _try_import(path)
220
+ if module is not None:
221
+ results["bootstrap_ci"] = getattr(module, "bootstrap_ci", None)
222
+ results["calibrate_predictions"] = getattr(module, "calibrate_predictions", None)
223
+ results["metrics_report"] = getattr(module, "metrics_report", None)
224
+ results["select_threshold"] = getattr(module, "select_threshold", None)
225
+ if any(v is not None for v in results.values()):
226
+ break
227
+
228
+ return results
229
+
230
+
231
+ def _resolve_governance() -> Dict[str, Any]:
232
+ """Resolve governance and reporting utilities."""
233
+ results = {}
234
+
235
+ # ModelRegistry and ModelArtifact
236
+ registry_paths = [
237
+ "ins_pricing.governance.registry",
238
+ ]
239
+ for path in registry_paths:
240
+ module = _try_import(path)
241
+ if module is not None:
242
+ results["ModelArtifact"] = getattr(module, "ModelArtifact", None)
243
+ results["ModelRegistry"] = getattr(module, "ModelRegistry", None)
244
+ break
245
+
246
+ # PSI report
247
+ psi_paths = [
248
+ "ins_pricing.production",
249
+ ]
250
+ for path in psi_paths:
251
+ module = _try_import(path)
252
+ if module is not None:
253
+ results["drift_psi_report"] = getattr(module, "psi_report", None)
254
+ break
255
+
256
+ # Group metrics
257
+ monitoring_paths = [
258
+ "ins_pricing.production.monitoring",
259
+ ]
260
+ for path in monitoring_paths:
261
+ module = _try_import(path)
262
+ if module is not None:
263
+ results["group_metrics"] = getattr(module, "group_metrics", None)
264
+ break
265
+
266
+ # Report builder
267
+ report_paths = [
268
+ "ins_pricing.reporting.report_builder",
269
+ ]
270
+ for path in report_paths:
271
+ module = _try_import(path)
272
+ if module is not None:
273
+ results["ReportPayload"] = getattr(module, "ReportPayload", None)
274
+ results["write_report"] = getattr(module, "write_report", None)
275
+ break
276
+
277
+ return results
278
+
279
+
280
+ def _resolve_logging() -> Dict[str, Any]:
281
+ """Resolve logging utilities."""
282
+ paths = [
283
+ "ins_pricing.cli.utils.run_logging",
284
+ "cli.utils.run_logging",
285
+ "utils.run_logging",
286
+ ]
287
+
288
+ results = {}
289
+ for path in paths:
290
+ module = _try_import(path)
291
+ if module is not None:
292
+ results["configure_run_logging"] = getattr(module, "configure_run_logging", None)
293
+ break
294
+
295
+ return results
296
+
297
+
298
+ def _resolve_plotting() -> Dict[str, Any]:
299
+ """Resolve plotting utilities."""
300
+ paths = [
301
+ "ins_pricing.modelling.plotting.diagnostics",
302
+ "ins_pricing.plotting.diagnostics",
303
+ ]
304
+
305
+ results = {}
306
+ for path in paths:
307
+ module = _try_import(path)
308
+ if module is not None:
309
+ results["plot_loss_curve"] = getattr(module, "plot_loss_curve", None)
310
+ break
311
+
312
+ return results
313
+
314
+
315
+ def resolve_imports() -> ResolvedImports:
316
+ """Resolve all imports from the bayesopt ecosystem.
317
+
318
+ This function attempts to import modules from multiple possible locations,
319
+ handling the various ways the package might be installed or run.
320
+
321
+ Returns:
322
+ ResolvedImports object containing all resolved imports.
323
+ """
324
+ imports = ResolvedImports()
325
+
326
+ # Resolve bayesopt core
327
+ imports.bayesopt = _resolve_bayesopt()
328
+
329
+ # Resolve CLI common utilities
330
+ cli_common = _resolve_cli_common()
331
+ imports.PLOT_MODEL_LABELS = cli_common.get("PLOT_MODEL_LABELS", {})
332
+ imports.PYTORCH_TRAINERS = cli_common.get("PYTORCH_TRAINERS", [])
333
+ imports.build_model_names = cli_common.get("build_model_names")
334
+ imports.dedupe_preserve_order = cli_common.get("dedupe_preserve_order")
335
+ imports.load_dataset = cli_common.get("load_dataset")
336
+ imports.parse_model_pairs = cli_common.get("parse_model_pairs")
337
+ imports.resolve_data_path = cli_common.get("resolve_data_path")
338
+ imports.resolve_path = cli_common.get("resolve_path")
339
+ imports.fingerprint_file = cli_common.get("fingerprint_file")
340
+ imports.coerce_dataset_types = cli_common.get("coerce_dataset_types")
341
+ imports.split_train_test = cli_common.get("split_train_test")
342
+
343
+ # Resolve CLI config utilities
344
+ cli_config = _resolve_cli_config()
345
+ imports.add_config_json_arg = cli_config.get("add_config_json_arg")
346
+ imports.add_output_dir_arg = cli_config.get("add_output_dir_arg")
347
+ imports.resolve_and_load_config = cli_config.get("resolve_and_load_config")
348
+ imports.resolve_data_config = cli_config.get("resolve_data_config")
349
+ imports.resolve_report_config = cli_config.get("resolve_report_config")
350
+ imports.resolve_explain_save_root = cli_config.get("resolve_explain_save_root")
351
+ imports.resolve_explain_save_dir = cli_config.get("resolve_explain_save_dir")
352
+ imports.resolve_explain_output_overrides = cli_config.get("resolve_explain_output_overrides")
353
+ imports.resolve_model_path_value = cli_config.get("resolve_model_path_value")
354
+ imports.resolve_split_config = cli_config.get("resolve_split_config")
355
+ imports.resolve_runtime_config = cli_config.get("resolve_runtime_config")
356
+ imports.resolve_output_dirs = cli_config.get("resolve_output_dirs")
357
+
358
+ # Resolve evaluation utilities
359
+ evaluation = _resolve_evaluation()
360
+ imports.bootstrap_ci = evaluation.get("bootstrap_ci")
361
+ imports.calibrate_predictions = evaluation.get("calibrate_predictions")
362
+ imports.metrics_report = evaluation.get("metrics_report")
363
+ imports.select_threshold = evaluation.get("select_threshold")
364
+
365
+ # Resolve governance and reporting
366
+ governance = _resolve_governance()
367
+ imports.ModelArtifact = governance.get("ModelArtifact")
368
+ imports.ModelRegistry = governance.get("ModelRegistry")
369
+ imports.drift_psi_report = governance.get("drift_psi_report")
370
+ imports.group_metrics = governance.get("group_metrics")
371
+ imports.ReportPayload = governance.get("ReportPayload")
372
+ imports.write_report = governance.get("write_report")
373
+
374
+ # Resolve logging
375
+ logging_utils = _resolve_logging()
376
+ imports.configure_run_logging = logging_utils.get("configure_run_logging")
377
+
378
+ # Resolve plotting
379
+ plotting = _resolve_plotting()
380
+ imports.plot_loss_curve = plotting.get("plot_loss_curve")
381
+
382
+ return imports
383
+
384
+
385
+ # Convenience function for backward compatibility
372
386
  def setup_sys_path() -> None:
373
387
  """Ensure the repository root is in sys.path for imports."""
374
- repo_root = Path(__file__).resolve().parents[3]
375
- if str(repo_root) not in sys.path:
376
- sys.path.insert(0, str(repo_root))
388
+ try:
389
+ if importlib.util.find_spec("ins_pricing") is not None:
390
+ return
391
+ except Exception:
392
+ pass
393
+ ensure_repo_root()