featrixsphere 0.2.1233__tar.gz → 0.2.1235__tar.gz

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 (19) hide show
  1. {featrixsphere-0.2.1233/featrixsphere.egg-info → featrixsphere-0.2.1235}/PKG-INFO +1 -1
  2. featrixsphere-0.2.1235/VERSION +1 -0
  3. {featrixsphere-0.2.1233 → featrixsphere-0.2.1235}/featrixsphere/__init__.py +1 -1
  4. {featrixsphere-0.2.1233 → featrixsphere-0.2.1235}/featrixsphere/client.py +86 -57
  5. {featrixsphere-0.2.1233 → featrixsphere-0.2.1235/featrixsphere.egg-info}/PKG-INFO +1 -1
  6. featrixsphere-0.2.1233/VERSION +0 -1
  7. {featrixsphere-0.2.1233 → featrixsphere-0.2.1235}/MANIFEST.in +0 -0
  8. {featrixsphere-0.2.1233 → featrixsphere-0.2.1235}/README.md +0 -0
  9. {featrixsphere-0.2.1233 → featrixsphere-0.2.1235}/featrixsphere/cli.py +0 -0
  10. {featrixsphere-0.2.1233 → featrixsphere-0.2.1235}/featrixsphere/test_client.py +0 -0
  11. {featrixsphere-0.2.1233 → featrixsphere-0.2.1235}/featrixsphere.egg-info/SOURCES.txt +0 -0
  12. {featrixsphere-0.2.1233 → featrixsphere-0.2.1235}/featrixsphere.egg-info/dependency_links.txt +0 -0
  13. {featrixsphere-0.2.1233 → featrixsphere-0.2.1235}/featrixsphere.egg-info/entry_points.txt +0 -0
  14. {featrixsphere-0.2.1233 → featrixsphere-0.2.1235}/featrixsphere.egg-info/not-zip-safe +0 -0
  15. {featrixsphere-0.2.1233 → featrixsphere-0.2.1235}/featrixsphere.egg-info/requires.txt +0 -0
  16. {featrixsphere-0.2.1233 → featrixsphere-0.2.1235}/featrixsphere.egg-info/top_level.txt +0 -0
  17. {featrixsphere-0.2.1233 → featrixsphere-0.2.1235}/requirements.txt +0 -0
  18. {featrixsphere-0.2.1233 → featrixsphere-0.2.1235}/setup.cfg +0 -0
  19. {featrixsphere-0.2.1233 → featrixsphere-0.2.1235}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: featrixsphere
3
- Version: 0.2.1233
3
+ Version: 0.2.1235
4
4
  Summary: Transform any CSV into a production-ready ML model in minutes, not months.
5
5
  Home-page: https://github.com/Featrix/sphere
6
6
  Author: Featrix
@@ -0,0 +1 @@
1
+ 0.2.1235
@@ -38,7 +38,7 @@ Example:
38
38
  ... labels=['Experiment A', 'Experiment B'])
39
39
  """
40
40
 
41
- __version__ = "0.2.1233"
41
+ __version__ = "0.2.1235"
42
42
  __author__ = "Featrix"
43
43
  __email__ = "support@featrix.com"
44
44
  __license__ = "MIT"
@@ -4194,19 +4194,34 @@ class FeatrixSphereClient:
4194
4194
  print(f"Training predictor on foundation model {foundation_model_id}...")
4195
4195
  print(f" Target: {target_column} ({target_column_type})")
4196
4196
 
4197
- # Validate that only one data source is provided
4198
- if input_filename and df is not None:
4199
- raise ValueError("Provide either input_filename or df, not both")
4197
+ # Get the compute cluster from the foundation model session
4198
+ # This ensures we upload files to the same node where the foundation model lives
4199
+ foundation_session = self.get_session_status(foundation_model_id)
4200
+ foundation_compute_cluster = self.get_last_server_metadata()
4201
+ foundation_compute_cluster = foundation_compute_cluster.get('compute_cluster') if foundation_compute_cluster else None
4202
+
4203
+ # Temporarily set compute cluster for file uploads if we found one
4204
+ original_compute_cluster = self.compute_cluster
4205
+ original_headers = self.session.headers.copy()
4206
+ if foundation_compute_cluster:
4207
+ self.set_compute_cluster(foundation_compute_cluster)
4208
+ if verbose:
4209
+ print(f" Using compute cluster: {foundation_compute_cluster}")
4200
4210
 
4201
- # If DataFrame provided, save to temp file and upload it
4202
- temp_file = None
4203
- if df is not None:
4204
- import pandas as pd
4205
- import tempfile
4206
- import os
4207
-
4208
- if not isinstance(df, pd.DataFrame):
4209
- raise ValueError("df must be a pandas DataFrame")
4211
+ try:
4212
+ # Validate that only one data source is provided
4213
+ if input_filename and df is not None:
4214
+ raise ValueError("Provide either input_filename or df, not both")
4215
+
4216
+ # If DataFrame provided, save to temp file and upload it
4217
+ temp_file = None
4218
+ if df is not None:
4219
+ import pandas as pd
4220
+ import tempfile
4221
+ import os
4222
+
4223
+ if not isinstance(df, pd.DataFrame):
4224
+ raise ValueError("df must be a pandas DataFrame")
4210
4225
 
4211
4226
  if verbose:
4212
4227
  print(f"📊 Using provided DataFrame ({len(df)} rows, {len(df.columns)} columns)")
@@ -4236,51 +4251,65 @@ class FeatrixSphereClient:
4236
4251
  except Exception:
4237
4252
  pass # Ignore cleanup errors
4238
4253
 
4239
- data = {
4240
- "foundation_model_id": foundation_model_id,
4241
- "target_column": target_column,
4242
- "target_column_type": target_column_type,
4243
- "epochs": epochs,
4244
- "optimize_for": optimize_for,
4245
- }
4246
-
4247
- if input_filename:
4248
- # If absolute path provided, upload the file first
4249
- from pathlib import Path
4250
- input_path = Path(input_filename)
4251
- if input_path.is_absolute():
4252
- # Upload the file first, then use the uploaded filename
4253
- if not input_path.exists():
4254
- raise FileNotFoundError(f"Input file not found: {input_filename}")
4255
-
4256
- if verbose:
4257
- print(f"📤 Uploading file from absolute path: {input_filename}")
4258
-
4259
- # Upload the file
4260
- uploaded_filename = self.upload_file(str(input_path))
4261
-
4262
- if verbose:
4263
- print(f"✅ File uploaded as: {uploaded_filename}")
4264
-
4265
- data["input_filename"] = uploaded_filename
4266
- else:
4267
- # Relative filename - assume it's already on the server
4268
- data["input_filename"] = input_filename
4269
- if name:
4270
- data["name"] = name
4271
- if session_name_prefix:
4272
- data["session_name_prefix"] = session_name_prefix
4273
- if rare_label_value:
4274
- data["rare_label_value"] = rare_label_value
4275
- if class_imbalance:
4276
- data["class_imbalance"] = class_imbalance
4277
- if webhooks:
4278
- data["webhooks"] = webhooks
4279
-
4280
- response_data = self._post_json("/compute/train_on_foundational_model", data)
4281
-
4282
- new_session_id = response_data.get('session_id')
4283
- print(f"✅ Predictor training session created: {new_session_id}")
4254
+ data = {
4255
+ "foundation_model_id": foundation_model_id,
4256
+ "target_column": target_column,
4257
+ "target_column_type": target_column_type,
4258
+ "epochs": epochs,
4259
+ "optimize_for": optimize_for,
4260
+ }
4261
+
4262
+ if input_filename:
4263
+ # If absolute path provided, upload the file first
4264
+ from pathlib import Path
4265
+ input_path = Path(input_filename)
4266
+ if input_path.is_absolute():
4267
+ # Upload the file first, then use the uploaded filename
4268
+ if not input_path.exists():
4269
+ raise FileNotFoundError(f"Input file not found: {input_filename}")
4270
+
4271
+ if verbose:
4272
+ print(f"📤 Uploading file from absolute path: {input_filename}")
4273
+
4274
+ # Upload the file
4275
+ uploaded_filename = self.upload_file(str(input_path))
4276
+
4277
+ if verbose:
4278
+ print(f"✅ File uploaded as: {uploaded_filename}")
4279
+
4280
+ data["input_filename"] = uploaded_filename
4281
+ else:
4282
+ # Relative filename - assume it's already on the server
4283
+ data["input_filename"] = input_filename
4284
+ if name:
4285
+ data["name"] = name
4286
+ if session_name_prefix:
4287
+ data["session_name_prefix"] = session_name_prefix
4288
+ if rare_label_value:
4289
+ data["rare_label_value"] = rare_label_value
4290
+ if class_imbalance:
4291
+ data["class_imbalance"] = class_imbalance
4292
+ if webhooks:
4293
+ data["webhooks"] = webhooks
4294
+
4295
+ response_data = self._post_json("/compute/train_on_foundational_model", data)
4296
+
4297
+ new_session_id = response_data.get('session_id')
4298
+ print(f"✅ Predictor training session created: {new_session_id}")
4299
+
4300
+ # Restore original compute cluster setting
4301
+ if original_compute_cluster != self.compute_cluster:
4302
+ if original_compute_cluster:
4303
+ self.set_compute_cluster(original_compute_cluster)
4304
+ else:
4305
+ self.session.headers = original_headers
4306
+ finally:
4307
+ # Ensure we restore headers even if there's an error
4308
+ if original_compute_cluster != self.compute_cluster:
4309
+ if original_compute_cluster:
4310
+ self.set_compute_cluster(original_compute_cluster)
4311
+ else:
4312
+ self.session.headers = original_headers
4284
4313
 
4285
4314
  if verbose:
4286
4315
  print(f"⏳ Waiting for training to complete...")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: featrixsphere
3
- Version: 0.2.1233
3
+ Version: 0.2.1235
4
4
  Summary: Transform any CSV into a production-ready ML model in minutes, not months.
5
5
  Home-page: https://github.com/Featrix/sphere
6
6
  Author: Featrix
@@ -1 +0,0 @@
1
- 0.2.1233