churnkit 0.76.0a2__py3-none-any.whl → 0.76.1a1__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.
- {churnkit-0.76.0a2.data → churnkit-0.76.1a1.data}/data/share/churnkit/exploration_notebooks/01_data_discovery.ipynb +5 -3
- {churnkit-0.76.0a2.dist-info → churnkit-0.76.1a1.dist-info}/METADATA +1 -1
- {churnkit-0.76.0a2.dist-info → churnkit-0.76.1a1.dist-info}/RECORD +28 -28
- customer_retention/__init__.py +1 -1
- customer_retention/analysis/notebook_progress.py +10 -1
- customer_retention/core/config/experiments.py +60 -0
- customer_retention/integrations/databricks_init.py +46 -3
- {churnkit-0.76.0a2.data → churnkit-0.76.1a1.data}/data/share/churnkit/exploration_notebooks/00_start_here.ipynb +0 -0
- {churnkit-0.76.0a2.data → churnkit-0.76.1a1.data}/data/share/churnkit/exploration_notebooks/01a_a_temporal_text_deep_dive.ipynb +0 -0
- {churnkit-0.76.0a2.data → churnkit-0.76.1a1.data}/data/share/churnkit/exploration_notebooks/01a_temporal_deep_dive.ipynb +0 -0
- {churnkit-0.76.0a2.data → churnkit-0.76.1a1.data}/data/share/churnkit/exploration_notebooks/01b_temporal_quality.ipynb +0 -0
- {churnkit-0.76.0a2.data → churnkit-0.76.1a1.data}/data/share/churnkit/exploration_notebooks/01c_temporal_patterns.ipynb +0 -0
- {churnkit-0.76.0a2.data → churnkit-0.76.1a1.data}/data/share/churnkit/exploration_notebooks/01d_event_aggregation.ipynb +0 -0
- {churnkit-0.76.0a2.data → churnkit-0.76.1a1.data}/data/share/churnkit/exploration_notebooks/02_column_deep_dive.ipynb +0 -0
- {churnkit-0.76.0a2.data → churnkit-0.76.1a1.data}/data/share/churnkit/exploration_notebooks/02a_text_columns_deep_dive.ipynb +0 -0
- {churnkit-0.76.0a2.data → churnkit-0.76.1a1.data}/data/share/churnkit/exploration_notebooks/03_quality_assessment.ipynb +0 -0
- {churnkit-0.76.0a2.data → churnkit-0.76.1a1.data}/data/share/churnkit/exploration_notebooks/04_relationship_analysis.ipynb +0 -0
- {churnkit-0.76.0a2.data → churnkit-0.76.1a1.data}/data/share/churnkit/exploration_notebooks/05_multi_dataset.ipynb +0 -0
- {churnkit-0.76.0a2.data → churnkit-0.76.1a1.data}/data/share/churnkit/exploration_notebooks/06_feature_opportunities.ipynb +0 -0
- {churnkit-0.76.0a2.data → churnkit-0.76.1a1.data}/data/share/churnkit/exploration_notebooks/07_modeling_readiness.ipynb +0 -0
- {churnkit-0.76.0a2.data → churnkit-0.76.1a1.data}/data/share/churnkit/exploration_notebooks/08_baseline_experiments.ipynb +0 -0
- {churnkit-0.76.0a2.data → churnkit-0.76.1a1.data}/data/share/churnkit/exploration_notebooks/09_business_alignment.ipynb +0 -0
- {churnkit-0.76.0a2.data → churnkit-0.76.1a1.data}/data/share/churnkit/exploration_notebooks/10_spec_generation.ipynb +0 -0
- {churnkit-0.76.0a2.data → churnkit-0.76.1a1.data}/data/share/churnkit/exploration_notebooks/11_scoring_validation.ipynb +0 -0
- {churnkit-0.76.0a2.data → churnkit-0.76.1a1.data}/data/share/churnkit/exploration_notebooks/12_view_documentation.ipynb +0 -0
- {churnkit-0.76.0a2.dist-info → churnkit-0.76.1a1.dist-info}/WHEEL +0 -0
- {churnkit-0.76.0a2.dist-info → churnkit-0.76.1a1.dist-info}/entry_points.txt +0 -0
- {churnkit-0.76.0a2.dist-info → churnkit-0.76.1a1.dist-info}/licenses/LICENSE +0 -0
|
@@ -137,10 +137,12 @@
|
|
|
137
137
|
"# =============================================================================\n",
|
|
138
138
|
"\n",
|
|
139
139
|
"# DATA_PATH: Path to your data file (CSV, Parquet, or Delta)\n",
|
|
140
|
-
"DATA_PATH = \"../tests/fixtures/
|
|
140
|
+
"DATA_PATH = \"../tests/fixtures/customer_emails.csv\"\n",
|
|
141
|
+
"# or databricks /Volumes/churnkit/landing/datasets/customer_emails.csv\n",
|
|
142
|
+
"\n",
|
|
141
143
|
"\n",
|
|
142
144
|
"# TARGET_COLUMN: Your prediction target (set to None for auto-detection)\n",
|
|
143
|
-
"TARGET_COLUMN = \
|
|
145
|
+
"TARGET_COLUMN = None\n",
|
|
144
146
|
"\n",
|
|
145
147
|
"# ENTITY_COLUMN: Customer/user ID column (set to None for auto-detection)\n",
|
|
146
148
|
"ENTITY_COLUMN = None\n",
|
|
@@ -169,7 +171,7 @@
|
|
|
169
171
|
"#\n",
|
|
170
172
|
"# EVENT-LEVEL (multiple rows per customer):\n",
|
|
171
173
|
"# DATA_PATH = \"../tests/fixtures/customer_transactions.csv\"\n",
|
|
172
|
-
"DATA_PATH = \"../tests/fixtures/customer_emails.csv\"\n",
|
|
174
|
+
"# DATA_PATH = \"../tests/fixtures/customer_emails.csv\"\n",
|
|
173
175
|
"# =============================================================================\n",
|
|
174
176
|
"\n",
|
|
175
177
|
"# OUTPUT_DIR: All outputs go here (gitignored)\n",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: churnkit
|
|
3
|
-
Version: 0.76.
|
|
3
|
+
Version: 0.76.1a1
|
|
4
4
|
Summary: Structured ML framework for customer churn prediction -- from exploration notebooks to production pipelines, locally or on Databricks.
|
|
5
5
|
Project-URL: Homepage, https://github.com/aladjov/CR
|
|
6
6
|
Project-URL: Documentation, https://github.com/aladjov/CR/wiki
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
customer_retention/__init__.py,sha256=
|
|
1
|
+
customer_retention/__init__.py,sha256=fNqb1iL6Q95kXsIVQBbVJtV_NmNSWBtgbGZxRy7vuYM,1406
|
|
2
2
|
customer_retention/cli.py,sha256=Wdl540cZgu_9mV-hWmTV9jD3S8QTDR8Ik-5hQXYCvmg,2466
|
|
3
3
|
customer_retention/analysis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
customer_retention/analysis/jupyter_save_hook.py,sha256=iiNFIL83yOPX8BGUjCE6Pt5Kc8X-2adtE1_NZTMUaZQ,947
|
|
5
5
|
customer_retention/analysis/notebook_html_exporter.py,sha256=AMOTcD6nZncM4MPdVS1Kn4WF2YoaOoODMI2X48oEZ24,4491
|
|
6
|
-
customer_retention/analysis/notebook_progress.py,sha256=
|
|
6
|
+
customer_retention/analysis/notebook_progress.py,sha256=Tm98ihaFQMXRAlEHTH89T23gLNZardzrCMC4svcoAUw,2463
|
|
7
7
|
customer_retention/analysis/plotly_preprocessor.py,sha256=Bdd_9-AmfmJdrmm030wzgpLflbiszp9KhXPbw_F5Id0,5300
|
|
8
8
|
customer_retention/analysis/auto_explorer/__init__.py,sha256=0isViyt62QvDkYc2oxOhsDQ9RNMqBq1ihvwEZgoLb_s,1572
|
|
9
9
|
customer_retention/analysis/auto_explorer/exploration_manager.py,sha256=60ObVRhYwAWqHnLrkeJ6_oQjPvXOl4gkLutE66_k8uc,18028
|
|
@@ -84,7 +84,7 @@ customer_retention/core/components/components/transformer.py,sha256=saEO6cRzKitU
|
|
|
84
84
|
customer_retention/core/components/components/validator.py,sha256=5IbUqPYhsvZBTRx0X3MKV2dvZrgTcI19MM9c5_9t2CU,1405
|
|
85
85
|
customer_retention/core/config/__init__.py,sha256=VXNmwSFG3wY6Budh82WRj26X07WCQKgl-M9sVwx8eds,1587
|
|
86
86
|
customer_retention/core/config/column_config.py,sha256=rmMJFV4wK66q-DDQAJXe0EuXdrWd_6bg8s81NQQ54_A,3051
|
|
87
|
-
customer_retention/core/config/experiments.py,sha256=
|
|
87
|
+
customer_retention/core/config/experiments.py,sha256=PQJwO1l8NjS9k_F6qOu0u0fTFcf_k--e6NIUMFBK1p4,4703
|
|
88
88
|
customer_retention/core/config/pipeline_config.py,sha256=jriAcP-_UAlVTT_vVlWUPF97ieIguqlE5hrl9Ny0UiI,3675
|
|
89
89
|
customer_retention/core/config/source_config.py,sha256=NnZUytq4NVvRVmp1ZtoFO_SiaIvSoJwkhw5WXy4Wi_c,2534
|
|
90
90
|
customer_retention/core/utils/__init__.py,sha256=9b8SwZGiLP-glYwzcp-1aWCeTGIploAPokwITbUCneA,971
|
|
@@ -131,7 +131,7 @@ customer_retention/generators/spec_generator/generic_generator.py,sha256=I_glnOO
|
|
|
131
131
|
customer_retention/generators/spec_generator/mlflow_pipeline_generator.py,sha256=LME87sjzP_MjOMA3NTxqRfOhCroUJAb40BAnSH4-I74,29866
|
|
132
132
|
customer_retention/generators/spec_generator/pipeline_spec.py,sha256=c8v1SWgTdeGmNs96l1hOS0qx1B1ua0iwPhw1I5w9OIo,10705
|
|
133
133
|
customer_retention/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
134
|
-
customer_retention/integrations/databricks_init.py,sha256=
|
|
134
|
+
customer_retention/integrations/databricks_init.py,sha256=xQgCBhzx0DoGGGeocYX9Iu3H2dEl--bvA36T7_uF6TM,6526
|
|
135
135
|
customer_retention/integrations/adapters/__init__.py,sha256=Fgdp0ESROTUHnOb2RN9Ubo0A4BdfoenOGuUz61lHz8g,583
|
|
136
136
|
customer_retention/integrations/adapters/base.py,sha256=z6dVAowDKGogKsYGR7VMcLkS6VhcB9h4zgN1tilNYRg,254
|
|
137
137
|
customer_retention/integrations/adapters/factory.py,sha256=CMsqOeDozADbWnk8fzktZvAyL1FEmUjDMvfDCpLDVaU,1202
|
|
@@ -277,27 +277,27 @@ customer_retention/transforms/artifact_store.py,sha256=FYLpDcv2N6-dUTX5RPEIK3aCW
|
|
|
277
277
|
customer_retention/transforms/executor.py,sha256=oML5dCidxbW_q6YUkAwWcutYP6bIFB6IdD3BvemK45A,6304
|
|
278
278
|
customer_retention/transforms/fitted.py,sha256=3pNvnae-P3t3bKMeZz1Bl0xww-feapIYdoeTY6aUtI8,3278
|
|
279
279
|
customer_retention/transforms/ops.py,sha256=Xg2g9UOOudq_y9Hf3oWsjpqw3dEoykQR5pDSoyW8GX0,4294
|
|
280
|
-
churnkit-0.76.
|
|
281
|
-
churnkit-0.76.
|
|
282
|
-
churnkit-0.76.
|
|
283
|
-
churnkit-0.76.
|
|
284
|
-
churnkit-0.76.
|
|
285
|
-
churnkit-0.76.
|
|
286
|
-
churnkit-0.76.
|
|
287
|
-
churnkit-0.76.
|
|
288
|
-
churnkit-0.76.
|
|
289
|
-
churnkit-0.76.
|
|
290
|
-
churnkit-0.76.
|
|
291
|
-
churnkit-0.76.
|
|
292
|
-
churnkit-0.76.
|
|
293
|
-
churnkit-0.76.
|
|
294
|
-
churnkit-0.76.
|
|
295
|
-
churnkit-0.76.
|
|
296
|
-
churnkit-0.76.
|
|
297
|
-
churnkit-0.76.
|
|
298
|
-
churnkit-0.76.
|
|
299
|
-
churnkit-0.76.
|
|
300
|
-
churnkit-0.76.
|
|
301
|
-
churnkit-0.76.
|
|
302
|
-
churnkit-0.76.
|
|
303
|
-
churnkit-0.76.
|
|
280
|
+
churnkit-0.76.1a1.data/data/share/churnkit/exploration_notebooks/00_start_here.ipynb,sha256=zCyhftEd3v9fc0Ta6wvA6b-9LcoGzRi8bS1tMZ3iu9w,21911
|
|
281
|
+
churnkit-0.76.1a1.data/data/share/churnkit/exploration_notebooks/01_data_discovery.ipynb,sha256=EDhWyKM2stHtWg2bS8HdRMItZ6WtokWRyZ90_MjTPFQ,46500
|
|
282
|
+
churnkit-0.76.1a1.data/data/share/churnkit/exploration_notebooks/01a_a_temporal_text_deep_dive.ipynb,sha256=uai8T3iJSqOrabBQnVi8Z0k8zZGVgs_VVQWRHyXN8QU,33690
|
|
283
|
+
churnkit-0.76.1a1.data/data/share/churnkit/exploration_notebooks/01a_temporal_deep_dive.ipynb,sha256=fC1ASNtvI8X1lAe-Lzcw3oX2cptDC-ymPeEtKKWhg20,67326
|
|
284
|
+
churnkit-0.76.1a1.data/data/share/churnkit/exploration_notebooks/01b_temporal_quality.ipynb,sha256=RU5hxgrTVMZs1ytChVv1t49WpTO0Oj6B_Fu8g0xS0To,23039
|
|
285
|
+
churnkit-0.76.1a1.data/data/share/churnkit/exploration_notebooks/01c_temporal_patterns.ipynb,sha256=ZGYfztP6JhOEwPmTYdC0l7w579fKXcNEJXq-PnCLc2I,153167
|
|
286
|
+
churnkit-0.76.1a1.data/data/share/churnkit/exploration_notebooks/01d_event_aggregation.ipynb,sha256=-FT3SoBU0fhaZxGeTo-_UQl6riCrtoJaFnUg31opk64,63244
|
|
287
|
+
churnkit-0.76.1a1.data/data/share/churnkit/exploration_notebooks/02_column_deep_dive.ipynb,sha256=mbP2LQWsXDyTsWg0bhrCBHEfHsEer_XOXRYV9f8JxAk,60250
|
|
288
|
+
churnkit-0.76.1a1.data/data/share/churnkit/exploration_notebooks/02a_text_columns_deep_dive.ipynb,sha256=M9YN8yAjjuC6ZaUlc-rVqVLEkWd7Rc_GNILHS9qO3PU,29704
|
|
289
|
+
churnkit-0.76.1a1.data/data/share/churnkit/exploration_notebooks/03_quality_assessment.ipynb,sha256=H49LLmn1PHbcbAvSQfteESRGk125QwkPI5qbLk3yZgc,68595
|
|
290
|
+
churnkit-0.76.1a1.data/data/share/churnkit/exploration_notebooks/04_relationship_analysis.ipynb,sha256=Rr-B4-xg0ILuAIgztlZkiGJdTzLuNjOqBFxO8W4o9iU,78624
|
|
291
|
+
churnkit-0.76.1a1.data/data/share/churnkit/exploration_notebooks/05_multi_dataset.ipynb,sha256=bBxkuZyTl1yZg4kMXO87WRjgZMhj_6hwLGX6m3XC270,62664
|
|
292
|
+
churnkit-0.76.1a1.data/data/share/churnkit/exploration_notebooks/06_feature_opportunities.ipynb,sha256=cBJF5o4z3Z-dustQ4CVklnfTcQ8saG97tlgswWK9uWE,67409
|
|
293
|
+
churnkit-0.76.1a1.data/data/share/churnkit/exploration_notebooks/07_modeling_readiness.ipynb,sha256=IiA04fyb-l097Glp3MtR03vPjQsZlS1Icg-hjEHa_Dg,28376
|
|
294
|
+
churnkit-0.76.1a1.data/data/share/churnkit/exploration_notebooks/08_baseline_experiments.ipynb,sha256=KmjhnDf1JdpEiIcdfQ-ZFo_at6t9JRC30B6NmmvMBmg,34226
|
|
295
|
+
churnkit-0.76.1a1.data/data/share/churnkit/exploration_notebooks/09_business_alignment.ipynb,sha256=tMNfGM7AH50N1ONzHhGW2HZLpQwraIxVzOiVnI-10X8,17214
|
|
296
|
+
churnkit-0.76.1a1.data/data/share/churnkit/exploration_notebooks/10_spec_generation.ipynb,sha256=KeUdfL9Mvdi6023XpnfZ6oLEDNZaWiIHUfsAWig24mE,42847
|
|
297
|
+
churnkit-0.76.1a1.data/data/share/churnkit/exploration_notebooks/11_scoring_validation.ipynb,sha256=5fi3eHMm03ZKZgdFAXMgydtZ3qX2TtR3L9bZS2MpWPE,49937
|
|
298
|
+
churnkit-0.76.1a1.data/data/share/churnkit/exploration_notebooks/12_view_documentation.ipynb,sha256=aQF7CG8HxckqUKOKqnmZgMkSvfVzyO2LlYPrymLYjBY,4405
|
|
299
|
+
churnkit-0.76.1a1.dist-info/METADATA,sha256=CkjX1u5qlqFbTuNbtFC93u25moHVAf2TaxYJwFAMWZY,13005
|
|
300
|
+
churnkit-0.76.1a1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
301
|
+
churnkit-0.76.1a1.dist-info/entry_points.txt,sha256=swQFVe-jjgQSBJQNO2Ulkz2F5odaE-TsnlTor3HQBjw,70
|
|
302
|
+
churnkit-0.76.1a1.dist-info/licenses/LICENSE,sha256=Bud8Oj25tnpoIuXCWW0xcSfmGPeEZAAHrDRoKdSYtZY,11344
|
|
303
|
+
churnkit-0.76.1a1.dist-info/RECORD,,
|
customer_retention/__init__.py
CHANGED
|
@@ -5,7 +5,16 @@ from pathlib import Path
|
|
|
5
5
|
from typing import Optional
|
|
6
6
|
|
|
7
7
|
from customer_retention.core.compat import is_databricks
|
|
8
|
-
from customer_retention.core.config.experiments import get_notebook_experiments_dir
|
|
8
|
+
from customer_retention.core.config.experiments import get_notebook_experiments_dir, reload_config
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _ensure_databricks_config_loaded() -> None:
|
|
12
|
+
if not is_databricks():
|
|
13
|
+
return
|
|
14
|
+
reload_config()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
_ensure_databricks_config_loaded()
|
|
9
18
|
|
|
10
19
|
|
|
11
20
|
def track_and_export_previous(current_notebook: str) -> None:
|
|
@@ -1,7 +1,49 @@
|
|
|
1
|
+
import json
|
|
1
2
|
import os
|
|
2
3
|
from pathlib import Path
|
|
3
4
|
from typing import Optional
|
|
4
5
|
|
|
6
|
+
_DATABRICKS_CONFIG_FILENAME = ".churnkit_config.json"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _workspace_config_path(workspace_path: str) -> Path:
|
|
10
|
+
return Path(f"/Workspace/{workspace_path}") / _DATABRICKS_CONFIG_FILENAME
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _read_config_file(path: Path) -> dict | None:
|
|
14
|
+
try:
|
|
15
|
+
return json.loads(path.read_text()) if path.exists() else None
|
|
16
|
+
except (json.JSONDecodeError, OSError):
|
|
17
|
+
return None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _load_persisted_databricks_config() -> dict | None:
|
|
21
|
+
if not os.environ.get("DATABRICKS_RUNTIME_VERSION"):
|
|
22
|
+
return None
|
|
23
|
+
workspace_path = os.environ.get("CR_WORKSPACE_PATH")
|
|
24
|
+
if workspace_path:
|
|
25
|
+
return _read_config_file(_workspace_config_path(workspace_path))
|
|
26
|
+
cwd = Path.cwd()
|
|
27
|
+
for _ in range(5):
|
|
28
|
+
result = _read_config_file(cwd / _DATABRICKS_CONFIG_FILENAME)
|
|
29
|
+
if result:
|
|
30
|
+
return result
|
|
31
|
+
if cwd.parent == cwd:
|
|
32
|
+
break
|
|
33
|
+
cwd = cwd.parent
|
|
34
|
+
return None
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def persist_databricks_config(experiments_dir: str, catalog: str, schema: str, workspace_path: str | None = None) -> None:
|
|
38
|
+
if not workspace_path:
|
|
39
|
+
return
|
|
40
|
+
try:
|
|
41
|
+
_workspace_config_path(workspace_path).write_text(json.dumps({
|
|
42
|
+
"experiments_dir": experiments_dir, "catalog": catalog, "schema": schema,
|
|
43
|
+
}))
|
|
44
|
+
except OSError:
|
|
45
|
+
pass
|
|
46
|
+
|
|
5
47
|
|
|
6
48
|
def _find_project_root() -> Path:
|
|
7
49
|
path = Path(__file__).parent
|
|
@@ -17,6 +59,9 @@ def get_experiments_dir(default: Optional[str] = None) -> Path:
|
|
|
17
59
|
return Path(os.environ["CR_EXPERIMENTS_DIR"])
|
|
18
60
|
if default:
|
|
19
61
|
return Path(default)
|
|
62
|
+
persisted = _load_persisted_databricks_config()
|
|
63
|
+
if persisted and "experiments_dir" in persisted:
|
|
64
|
+
return Path(persisted["experiments_dir"])
|
|
20
65
|
return _find_project_root() / "experiments"
|
|
21
66
|
|
|
22
67
|
|
|
@@ -64,6 +109,21 @@ WORKSPACE_PATH = get_workspace_path()
|
|
|
64
109
|
EXPERIMENT_NAME = get_experiment_name()
|
|
65
110
|
|
|
66
111
|
|
|
112
|
+
def reload_config() -> None:
|
|
113
|
+
global EXPERIMENTS_DIR, FINDINGS_DIR, DATA_DIR, MLRUNS_DIR, FEATURE_STORE_DIR
|
|
114
|
+
global OUTPUT_DIR, CATALOG, SCHEMA, WORKSPACE_PATH, EXPERIMENT_NAME
|
|
115
|
+
EXPERIMENTS_DIR = get_experiments_dir()
|
|
116
|
+
FINDINGS_DIR = get_findings_dir()
|
|
117
|
+
DATA_DIR = get_data_dir()
|
|
118
|
+
MLRUNS_DIR = get_mlruns_dir()
|
|
119
|
+
FEATURE_STORE_DIR = get_feature_store_dir()
|
|
120
|
+
OUTPUT_DIR = FINDINGS_DIR
|
|
121
|
+
CATALOG = get_catalog()
|
|
122
|
+
SCHEMA = get_schema()
|
|
123
|
+
WORKSPACE_PATH = get_workspace_path()
|
|
124
|
+
EXPERIMENT_NAME = get_experiment_name()
|
|
125
|
+
|
|
126
|
+
|
|
67
127
|
def setup_experiments_structure(experiments_dir: Optional[Path] = None) -> None:
|
|
68
128
|
base = experiments_dir or get_experiments_dir()
|
|
69
129
|
directories = [
|
|
@@ -22,7 +22,7 @@ class DatabricksInitResult:
|
|
|
22
22
|
"CR_CATALOG": self.catalog,
|
|
23
23
|
"CR_SCHEMA": self.schema,
|
|
24
24
|
"CR_EXPERIMENT_NAME": self.experiment_name,
|
|
25
|
-
"CR_EXPERIMENTS_DIR": f"/
|
|
25
|
+
"CR_EXPERIMENTS_DIR": f"/Volumes/{self.catalog}/{self.schema}/experiments",
|
|
26
26
|
}
|
|
27
27
|
if self.workspace_path:
|
|
28
28
|
env_vars["CR_WORKSPACE_PATH"] = self.workspace_path
|
|
@@ -38,10 +38,16 @@ def databricks_init(
|
|
|
38
38
|
model_name: str = "customer_retention",
|
|
39
39
|
) -> DatabricksInitResult:
|
|
40
40
|
_validate_databricks_environment()
|
|
41
|
+
if workspace_path:
|
|
42
|
+
workspace_path = _normalize_workspace_path(workspace_path)
|
|
43
|
+
_ensure_workspace_directory(workspace_path)
|
|
41
44
|
_set_environment_variables(catalog, schema, workspace_path)
|
|
45
|
+
_persist_config(catalog, schema, workspace_path)
|
|
42
46
|
resolved_experiment_name = experiment_name or _resolve_experiment_name_from_notebook_path()
|
|
43
47
|
resolved_experiment_name = _make_absolute_experiment_path(resolved_experiment_name, workspace_path)
|
|
44
48
|
_set_experiment_name_env_var(resolved_experiment_name)
|
|
49
|
+
_reload_config_constants()
|
|
50
|
+
_setup_experiment_directories()
|
|
45
51
|
_configure_mlflow_experiment(resolved_experiment_name)
|
|
46
52
|
notebooks_copied: list[str] = []
|
|
47
53
|
if copy_notebooks and workspace_path:
|
|
@@ -69,15 +75,36 @@ def _validate_databricks_environment() -> None:
|
|
|
69
75
|
def _set_environment_variables(catalog: str, schema: str, workspace_path: str | None) -> None:
|
|
70
76
|
os.environ["CR_CATALOG"] = catalog
|
|
71
77
|
os.environ["CR_SCHEMA"] = schema
|
|
78
|
+
os.environ["CR_EXPERIMENTS_DIR"] = f"/Volumes/{catalog}/{schema}/experiments"
|
|
72
79
|
if workspace_path:
|
|
73
80
|
os.environ["CR_WORKSPACE_PATH"] = workspace_path
|
|
74
|
-
os.environ["CR_EXPERIMENTS_DIR"] = f"/Workspace/{workspace_path}/experiments"
|
|
75
81
|
|
|
76
82
|
|
|
77
83
|
def _set_experiment_name_env_var(experiment_name: str) -> None:
|
|
78
84
|
os.environ["CR_EXPERIMENT_NAME"] = experiment_name
|
|
79
85
|
|
|
80
86
|
|
|
87
|
+
def _persist_config(catalog: str, schema: str, workspace_path: str | None) -> None:
|
|
88
|
+
from customer_retention.core.config.experiments import persist_databricks_config
|
|
89
|
+
|
|
90
|
+
persist_databricks_config(f"/Volumes/{catalog}/{schema}/experiments", catalog, schema, workspace_path)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _reload_config_constants() -> None:
|
|
94
|
+
from customer_retention.core.config.experiments import reload_config
|
|
95
|
+
|
|
96
|
+
reload_config()
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _setup_experiment_directories() -> None:
|
|
100
|
+
from customer_retention.core.config.experiments import setup_experiments_structure
|
|
101
|
+
|
|
102
|
+
try:
|
|
103
|
+
setup_experiments_structure()
|
|
104
|
+
except OSError:
|
|
105
|
+
pass
|
|
106
|
+
|
|
107
|
+
|
|
81
108
|
def _resolve_experiment_name_from_notebook_path() -> str:
|
|
82
109
|
try:
|
|
83
110
|
dbutils = _get_dbutils()
|
|
@@ -98,6 +125,12 @@ def _get_dbutils() -> Any | None:
|
|
|
98
125
|
return None
|
|
99
126
|
|
|
100
127
|
|
|
128
|
+
def _normalize_workspace_path(workspace_path: str) -> str:
|
|
129
|
+
if workspace_path.startswith("/Workspace/"):
|
|
130
|
+
return workspace_path[len("/Workspace/"):]
|
|
131
|
+
return workspace_path
|
|
132
|
+
|
|
133
|
+
|
|
101
134
|
def _make_absolute_experiment_path(experiment_name: str, workspace_path: str | None) -> str:
|
|
102
135
|
if experiment_name.startswith("/"):
|
|
103
136
|
return experiment_name
|
|
@@ -118,6 +151,13 @@ def _configure_mlflow_experiment(experiment_name: str) -> None:
|
|
|
118
151
|
pass
|
|
119
152
|
|
|
120
153
|
|
|
154
|
+
def _ensure_workspace_directory(workspace_path: str) -> None:
|
|
155
|
+
try:
|
|
156
|
+
Path(f"/Workspace/{workspace_path}").mkdir(parents=True, exist_ok=True)
|
|
157
|
+
except OSError:
|
|
158
|
+
pass
|
|
159
|
+
|
|
160
|
+
|
|
121
161
|
def _copy_exploration_notebooks(workspace_path: str) -> list[str]:
|
|
122
162
|
from customer_retention.generators.notebook_generator.project_init import ProjectInitializer
|
|
123
163
|
|
|
@@ -139,11 +179,14 @@ def _copy_exploration_notebooks(workspace_path: str) -> list[str]:
|
|
|
139
179
|
|
|
140
180
|
|
|
141
181
|
def _display_init_summary(result: DatabricksInitResult) -> None:
|
|
142
|
-
|
|
182
|
+
from customer_retention import __version__
|
|
183
|
+
|
|
184
|
+
print(f"ChurnKit v{__version__} Databricks Initialization Complete")
|
|
143
185
|
print("=" * 45)
|
|
144
186
|
print(f" Catalog: {result.catalog}")
|
|
145
187
|
print(f" Schema: {result.schema}")
|
|
146
188
|
print(f" Experiment: {result.experiment_name}")
|
|
189
|
+
print(f" Experiments Dir: /Volumes/{result.catalog}/{result.schema}/experiments")
|
|
147
190
|
print(f" Workspace Path: {result.workspace_path or '(not set)'}")
|
|
148
191
|
print(f" Model Name: {result.model_name}")
|
|
149
192
|
if result.notebooks_copied:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|