isa-model 0.3.91__py3-none-any.whl → 0.4.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 (228) hide show
  1. isa_model/client.py +1166 -584
  2. isa_model/core/cache/redis_cache.py +410 -0
  3. isa_model/core/config/config_manager.py +282 -12
  4. isa_model/core/config.py +91 -1
  5. isa_model/core/database/__init__.py +1 -0
  6. isa_model/core/database/direct_db_client.py +114 -0
  7. isa_model/core/database/migration_manager.py +563 -0
  8. isa_model/core/database/migrations.py +297 -0
  9. isa_model/core/database/supabase_client.py +258 -0
  10. isa_model/core/dependencies.py +316 -0
  11. isa_model/core/discovery/__init__.py +19 -0
  12. isa_model/core/discovery/consul_discovery.py +190 -0
  13. isa_model/core/logging/__init__.py +54 -0
  14. isa_model/core/logging/influx_logger.py +523 -0
  15. isa_model/core/logging/loki_logger.py +160 -0
  16. isa_model/core/models/__init__.py +46 -0
  17. isa_model/core/models/config_models.py +625 -0
  18. isa_model/core/models/deployment_billing_tracker.py +430 -0
  19. isa_model/core/models/model_billing_tracker.py +60 -88
  20. isa_model/core/models/model_manager.py +66 -25
  21. isa_model/core/models/model_metadata.py +690 -0
  22. isa_model/core/models/model_repo.py +217 -55
  23. isa_model/core/models/model_statistics_tracker.py +234 -0
  24. isa_model/core/models/model_storage.py +0 -1
  25. isa_model/core/models/model_version_manager.py +959 -0
  26. isa_model/core/models/system_models.py +857 -0
  27. isa_model/core/pricing_manager.py +2 -249
  28. isa_model/core/repositories/__init__.py +9 -0
  29. isa_model/core/repositories/config_repository.py +912 -0
  30. isa_model/core/resilience/circuit_breaker.py +366 -0
  31. isa_model/core/security/secrets.py +358 -0
  32. isa_model/core/services/__init__.py +2 -4
  33. isa_model/core/services/intelligent_model_selector.py +479 -370
  34. isa_model/core/storage/hf_storage.py +2 -2
  35. isa_model/core/types.py +8 -0
  36. isa_model/deployment/__init__.py +5 -48
  37. isa_model/deployment/core/__init__.py +2 -31
  38. isa_model/deployment/core/deployment_manager.py +1278 -368
  39. isa_model/deployment/local/__init__.py +31 -0
  40. isa_model/deployment/local/config.py +248 -0
  41. isa_model/deployment/local/gpu_gateway.py +607 -0
  42. isa_model/deployment/local/health_checker.py +428 -0
  43. isa_model/deployment/local/provider.py +586 -0
  44. isa_model/deployment/local/tensorrt_service.py +621 -0
  45. isa_model/deployment/local/transformers_service.py +644 -0
  46. isa_model/deployment/local/vllm_service.py +527 -0
  47. isa_model/deployment/modal/__init__.py +8 -0
  48. isa_model/deployment/modal/config.py +136 -0
  49. isa_model/deployment/modal/deployer.py +894 -0
  50. isa_model/deployment/modal/services/__init__.py +3 -0
  51. isa_model/deployment/modal/services/audio/__init__.py +1 -0
  52. isa_model/deployment/modal/services/audio/isa_audio_chatTTS_service.py +520 -0
  53. isa_model/deployment/modal/services/audio/isa_audio_openvoice_service.py +758 -0
  54. isa_model/deployment/modal/services/audio/isa_audio_service_v2.py +1044 -0
  55. isa_model/deployment/modal/services/embedding/__init__.py +1 -0
  56. isa_model/deployment/modal/services/embedding/isa_embed_rerank_service.py +296 -0
  57. isa_model/deployment/modal/services/llm/__init__.py +1 -0
  58. isa_model/deployment/modal/services/llm/isa_llm_service.py +424 -0
  59. isa_model/deployment/modal/services/video/__init__.py +1 -0
  60. isa_model/deployment/modal/services/video/isa_video_hunyuan_service.py +423 -0
  61. isa_model/deployment/modal/services/vision/__init__.py +1 -0
  62. isa_model/deployment/modal/services/vision/isa_vision_ocr_service.py +519 -0
  63. isa_model/deployment/modal/services/vision/isa_vision_qwen25_service.py +709 -0
  64. isa_model/deployment/modal/services/vision/isa_vision_table_service.py +676 -0
  65. isa_model/deployment/modal/services/vision/isa_vision_ui_service.py +833 -0
  66. isa_model/deployment/modal/services/vision/isa_vision_ui_service_optimized.py +660 -0
  67. isa_model/deployment/models/org-org-acme-corp-tenant-a-service-llm-20250825-225822/tenant-a-service_modal_service.py +48 -0
  68. isa_model/deployment/models/org-test-org-123-prefix-test-service-llm-20250825-225822/prefix-test-service_modal_service.py +48 -0
  69. isa_model/deployment/models/test-llm-service-llm-20250825-204442/test-llm-service_modal_service.py +48 -0
  70. isa_model/deployment/models/test-monitoring-gpt2-llm-20250825-212906/test-monitoring-gpt2_modal_service.py +48 -0
  71. isa_model/deployment/models/test-monitoring-gpt2-llm-20250825-213009/test-monitoring-gpt2_modal_service.py +48 -0
  72. isa_model/deployment/storage/__init__.py +5 -0
  73. isa_model/deployment/storage/deployment_repository.py +824 -0
  74. isa_model/deployment/triton/__init__.py +10 -0
  75. isa_model/deployment/triton/config.py +196 -0
  76. isa_model/deployment/triton/configs/__init__.py +1 -0
  77. isa_model/deployment/triton/provider.py +512 -0
  78. isa_model/deployment/triton/scripts/__init__.py +1 -0
  79. isa_model/deployment/triton/templates/__init__.py +1 -0
  80. isa_model/inference/__init__.py +47 -1
  81. isa_model/inference/ai_factory.py +179 -16
  82. isa_model/inference/legacy_services/__init__.py +21 -0
  83. isa_model/inference/legacy_services/model_evaluation.py +637 -0
  84. isa_model/inference/legacy_services/model_service.py +573 -0
  85. isa_model/inference/legacy_services/model_serving.py +717 -0
  86. isa_model/inference/legacy_services/model_training.py +561 -0
  87. isa_model/inference/models/__init__.py +21 -0
  88. isa_model/inference/models/inference_config.py +551 -0
  89. isa_model/inference/models/inference_record.py +675 -0
  90. isa_model/inference/models/performance_models.py +714 -0
  91. isa_model/inference/repositories/__init__.py +9 -0
  92. isa_model/inference/repositories/inference_repository.py +828 -0
  93. isa_model/inference/services/audio/__init__.py +21 -0
  94. isa_model/inference/services/audio/base_realtime_service.py +225 -0
  95. isa_model/inference/services/audio/base_stt_service.py +184 -11
  96. isa_model/inference/services/audio/isa_tts_service.py +0 -0
  97. isa_model/inference/services/audio/openai_realtime_service.py +320 -124
  98. isa_model/inference/services/audio/openai_stt_service.py +53 -11
  99. isa_model/inference/services/base_service.py +17 -1
  100. isa_model/inference/services/custom_model_manager.py +277 -0
  101. isa_model/inference/services/embedding/__init__.py +13 -0
  102. isa_model/inference/services/embedding/base_embed_service.py +111 -8
  103. isa_model/inference/services/embedding/isa_embed_service.py +305 -0
  104. isa_model/inference/services/embedding/ollama_embed_service.py +15 -3
  105. isa_model/inference/services/embedding/openai_embed_service.py +2 -4
  106. isa_model/inference/services/embedding/resilient_embed_service.py +285 -0
  107. isa_model/inference/services/embedding/tests/test_embedding.py +222 -0
  108. isa_model/inference/services/img/__init__.py +2 -2
  109. isa_model/inference/services/img/base_image_gen_service.py +24 -7
  110. isa_model/inference/services/img/replicate_image_gen_service.py +84 -422
  111. isa_model/inference/services/img/services/replicate_face_swap.py +193 -0
  112. isa_model/inference/services/img/services/replicate_flux.py +226 -0
  113. isa_model/inference/services/img/services/replicate_flux_kontext.py +219 -0
  114. isa_model/inference/services/img/services/replicate_sticker_maker.py +249 -0
  115. isa_model/inference/services/img/tests/test_img_client.py +297 -0
  116. isa_model/inference/services/llm/__init__.py +10 -2
  117. isa_model/inference/services/llm/base_llm_service.py +361 -26
  118. isa_model/inference/services/llm/cerebras_llm_service.py +628 -0
  119. isa_model/inference/services/llm/helpers/llm_adapter.py +71 -12
  120. isa_model/inference/services/llm/helpers/llm_prompts.py +342 -0
  121. isa_model/inference/services/llm/helpers/llm_utils.py +321 -23
  122. isa_model/inference/services/llm/huggingface_llm_service.py +581 -0
  123. isa_model/inference/services/llm/local_llm_service.py +747 -0
  124. isa_model/inference/services/llm/ollama_llm_service.py +11 -3
  125. isa_model/inference/services/llm/openai_llm_service.py +670 -56
  126. isa_model/inference/services/llm/yyds_llm_service.py +10 -3
  127. isa_model/inference/services/vision/__init__.py +27 -6
  128. isa_model/inference/services/vision/base_vision_service.py +118 -185
  129. isa_model/inference/services/vision/blip_vision_service.py +359 -0
  130. isa_model/inference/services/vision/helpers/image_utils.py +19 -10
  131. isa_model/inference/services/vision/isa_vision_service.py +634 -0
  132. isa_model/inference/services/vision/openai_vision_service.py +19 -10
  133. isa_model/inference/services/vision/tests/test_ocr_client.py +284 -0
  134. isa_model/inference/services/vision/vgg16_vision_service.py +257 -0
  135. isa_model/serving/api/cache_manager.py +245 -0
  136. isa_model/serving/api/dependencies/__init__.py +1 -0
  137. isa_model/serving/api/dependencies/auth.py +194 -0
  138. isa_model/serving/api/dependencies/database.py +139 -0
  139. isa_model/serving/api/error_handlers.py +284 -0
  140. isa_model/serving/api/fastapi_server.py +240 -18
  141. isa_model/serving/api/middleware/auth.py +317 -0
  142. isa_model/serving/api/middleware/security.py +268 -0
  143. isa_model/serving/api/middleware/tenant_context.py +414 -0
  144. isa_model/serving/api/routes/analytics.py +489 -0
  145. isa_model/serving/api/routes/config.py +645 -0
  146. isa_model/serving/api/routes/deployment_billing.py +315 -0
  147. isa_model/serving/api/routes/deployments.py +475 -0
  148. isa_model/serving/api/routes/gpu_gateway.py +440 -0
  149. isa_model/serving/api/routes/health.py +32 -12
  150. isa_model/serving/api/routes/inference_monitoring.py +486 -0
  151. isa_model/serving/api/routes/local_deployments.py +448 -0
  152. isa_model/serving/api/routes/logs.py +430 -0
  153. isa_model/serving/api/routes/settings.py +582 -0
  154. isa_model/serving/api/routes/tenants.py +575 -0
  155. isa_model/serving/api/routes/unified.py +992 -171
  156. isa_model/serving/api/routes/webhooks.py +479 -0
  157. isa_model/serving/api/startup.py +318 -0
  158. isa_model/serving/modal_proxy_server.py +249 -0
  159. isa_model/utils/gpu_utils.py +311 -0
  160. {isa_model-0.3.91.dist-info → isa_model-0.4.3.dist-info}/METADATA +76 -22
  161. isa_model-0.4.3.dist-info/RECORD +193 -0
  162. isa_model/deployment/cloud/__init__.py +0 -9
  163. isa_model/deployment/cloud/modal/__init__.py +0 -10
  164. isa_model/deployment/cloud/modal/isa_vision_doc_service.py +0 -766
  165. isa_model/deployment/cloud/modal/isa_vision_table_service.py +0 -532
  166. isa_model/deployment/cloud/modal/isa_vision_ui_service.py +0 -406
  167. isa_model/deployment/cloud/modal/register_models.py +0 -321
  168. isa_model/deployment/core/deployment_config.py +0 -356
  169. isa_model/deployment/core/isa_deployment_service.py +0 -401
  170. isa_model/deployment/gpu_int8_ds8/app/server.py +0 -66
  171. isa_model/deployment/gpu_int8_ds8/scripts/test_client.py +0 -43
  172. isa_model/deployment/gpu_int8_ds8/scripts/test_client_os.py +0 -35
  173. isa_model/deployment/runtime/deployed_service.py +0 -338
  174. isa_model/deployment/services/__init__.py +0 -9
  175. isa_model/deployment/services/auto_deploy_vision_service.py +0 -538
  176. isa_model/deployment/services/model_service.py +0 -332
  177. isa_model/deployment/services/service_monitor.py +0 -356
  178. isa_model/deployment/services/service_registry.py +0 -527
  179. isa_model/eval/__init__.py +0 -92
  180. isa_model/eval/benchmarks.py +0 -469
  181. isa_model/eval/config/__init__.py +0 -10
  182. isa_model/eval/config/evaluation_config.py +0 -108
  183. isa_model/eval/evaluators/__init__.py +0 -18
  184. isa_model/eval/evaluators/base_evaluator.py +0 -503
  185. isa_model/eval/evaluators/llm_evaluator.py +0 -472
  186. isa_model/eval/factory.py +0 -531
  187. isa_model/eval/infrastructure/__init__.py +0 -24
  188. isa_model/eval/infrastructure/experiment_tracker.py +0 -466
  189. isa_model/eval/metrics.py +0 -798
  190. isa_model/inference/adapter/unified_api.py +0 -248
  191. isa_model/inference/services/helpers/stacked_config.py +0 -148
  192. isa_model/inference/services/img/flux_professional_service.py +0 -603
  193. isa_model/inference/services/img/helpers/base_stacked_service.py +0 -274
  194. isa_model/inference/services/others/table_transformer_service.py +0 -61
  195. isa_model/inference/services/vision/doc_analysis_service.py +0 -640
  196. isa_model/inference/services/vision/helpers/base_stacked_service.py +0 -274
  197. isa_model/inference/services/vision/ui_analysis_service.py +0 -823
  198. isa_model/scripts/inference_tracker.py +0 -283
  199. isa_model/scripts/mlflow_manager.py +0 -379
  200. isa_model/scripts/model_registry.py +0 -465
  201. isa_model/scripts/register_models.py +0 -370
  202. isa_model/scripts/register_models_with_embeddings.py +0 -510
  203. isa_model/scripts/start_mlflow.py +0 -95
  204. isa_model/scripts/training_tracker.py +0 -257
  205. isa_model/training/__init__.py +0 -74
  206. isa_model/training/annotation/annotation_schema.py +0 -47
  207. isa_model/training/annotation/processors/annotation_processor.py +0 -126
  208. isa_model/training/annotation/storage/dataset_manager.py +0 -131
  209. isa_model/training/annotation/storage/dataset_schema.py +0 -44
  210. isa_model/training/annotation/tests/test_annotation_flow.py +0 -109
  211. isa_model/training/annotation/tests/test_minio copy.py +0 -113
  212. isa_model/training/annotation/tests/test_minio_upload.py +0 -43
  213. isa_model/training/annotation/views/annotation_controller.py +0 -158
  214. isa_model/training/cloud/__init__.py +0 -22
  215. isa_model/training/cloud/job_orchestrator.py +0 -402
  216. isa_model/training/cloud/runpod_trainer.py +0 -454
  217. isa_model/training/cloud/storage_manager.py +0 -482
  218. isa_model/training/core/__init__.py +0 -23
  219. isa_model/training/core/config.py +0 -181
  220. isa_model/training/core/dataset.py +0 -222
  221. isa_model/training/core/trainer.py +0 -720
  222. isa_model/training/core/utils.py +0 -213
  223. isa_model/training/factory.py +0 -424
  224. isa_model-0.3.91.dist-info/RECORD +0 -138
  225. /isa_model/{core/storage/minio_storage.py → deployment/modal/services/audio/isa_audio_fish_service.py} +0 -0
  226. /isa_model/deployment/{services → modal/services/vision}/simple_auto_deploy_vision_service.py +0 -0
  227. {isa_model-0.3.91.dist-info → isa_model-0.4.3.dist-info}/WHEEL +0 -0
  228. {isa_model-0.3.91.dist-info → isa_model-0.4.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,561 @@
1
+ """
2
+ Model Training Service - Step 1 of Model Pipeline
3
+ Handles ML model training using existing model processors
4
+ """
5
+
6
+ import pandas as pd
7
+ from typing import Dict, List, Any, Optional
8
+ import logging
9
+ from dataclasses import dataclass, field
10
+ from datetime import datetime
11
+
12
+ # Lazy import to avoid mutex locks from ML libraries
13
+ def _get_ml_processor():
14
+ from tools.services.data_analytics_service.processors.data_processors.model import MLProcessor
15
+ return MLProcessor
16
+
17
+ def _get_time_series_processor():
18
+ from tools.services.data_analytics_service.processors.data_processors.model import TimeSeriesProcessor
19
+ return TimeSeriesProcessor
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+ @dataclass
24
+ class TrainingConfig:
25
+ """Configuration for model training"""
26
+ algorithm: str
27
+ problem_type: Optional[str] = None # auto-detect if None
28
+ hyperparameters: Dict[str, Any] = field(default_factory=dict)
29
+ cross_validation: bool = True
30
+ cv_folds: int = 5
31
+ test_size: float = 0.2
32
+ preprocessing_options: Dict[str, Any] = field(default_factory=dict)
33
+ feature_selection: bool = False
34
+ feature_selection_method: str = "auto"
35
+
36
+ @dataclass
37
+ class TrainingResult:
38
+ """Result of model training step"""
39
+ success: bool
40
+ model_info: Optional[Dict[str, Any]] = None
41
+ training_metrics: Dict[str, Any] = field(default_factory=dict)
42
+ model_metadata: Dict[str, Any] = field(default_factory=dict)
43
+ performance_metrics: Dict[str, Any] = field(default_factory=dict)
44
+ warnings: List[str] = field(default_factory=list)
45
+ errors: List[str] = field(default_factory=list)
46
+
47
+ class ModelTrainingService:
48
+ """
49
+ Model Training Service - Step 1 of Model Pipeline
50
+
51
+ Handles:
52
+ - ML model training using various algorithms
53
+ - Problem type detection and algorithm recommendation
54
+ - Hyperparameter tuning
55
+ - Cross-validation and model selection
56
+ """
57
+
58
+ def __init__(self):
59
+ self.execution_stats = {
60
+ 'total_training_operations': 0,
61
+ 'successful_training_operations': 0,
62
+ 'failed_training_operations': 0,
63
+ 'models_trained': 0,
64
+ 'average_training_time': 0.0
65
+ }
66
+
67
+ # Track trained models
68
+ self.trained_models = {}
69
+
70
+ logger.info("Model Training Service initialized")
71
+
72
+ def train_model(self,
73
+ data: pd.DataFrame,
74
+ target_column: str,
75
+ training_config: TrainingConfig) -> TrainingResult:
76
+ """
77
+ Train a machine learning model
78
+
79
+ Args:
80
+ data: Training dataset
81
+ target_column: Target variable column name
82
+ training_config: Training configuration
83
+
84
+ Returns:
85
+ TrainingResult with model information and metrics
86
+ """
87
+ start_time = datetime.now()
88
+
89
+ try:
90
+ logger.info(f"Starting model training: {training_config.algorithm}")
91
+
92
+ # Initialize result
93
+ result = TrainingResult(
94
+ success=False,
95
+ model_metadata={
96
+ 'start_time': start_time,
97
+ 'target_column': target_column,
98
+ 'algorithm': training_config.algorithm,
99
+ 'data_shape': data.shape
100
+ }
101
+ )
102
+
103
+ # Validate inputs
104
+ validation_result = self._validate_training_inputs(data, target_column, training_config)
105
+ if not validation_result['valid']:
106
+ result.errors.extend(validation_result['errors'])
107
+ return self._finalize_training_result(result, start_time)
108
+
109
+ # Select appropriate processor based on algorithm/problem type
110
+ processor_result = self._get_model_processor(data, target_column, training_config)
111
+ if not processor_result['success']:
112
+ result.errors.extend(processor_result['errors'])
113
+ return self._finalize_training_result(result, start_time)
114
+
115
+ processor = processor_result['processor']
116
+ detected_problem_type = processor_result['problem_type']
117
+
118
+ # Execute training
119
+ training_result = self._execute_training(
120
+ processor, data, target_column, training_config, detected_problem_type
121
+ )
122
+
123
+ if not training_result['success']:
124
+ result.errors.extend(training_result['errors'])
125
+ return self._finalize_training_result(result, start_time)
126
+
127
+ # Store model information
128
+ model_id = training_result['model_id']
129
+ self.trained_models[model_id] = {
130
+ 'processor': processor,
131
+ 'model_instance': training_result.get('model_instance'),
132
+ 'training_config': training_config,
133
+ 'target_column': target_column,
134
+ 'problem_type': detected_problem_type,
135
+ 'created_at': start_time
136
+ }
137
+
138
+ # Success
139
+ result.success = True
140
+ result.model_info = {
141
+ 'model_id': model_id,
142
+ 'algorithm': training_config.algorithm,
143
+ 'problem_type': detected_problem_type
144
+ }
145
+ result.training_metrics = training_result.get('training_metrics', {})
146
+ result.model_metadata.update(training_result.get('metadata', {}))
147
+
148
+ return self._finalize_training_result(result, start_time)
149
+
150
+ except Exception as e:
151
+ logger.error(f"Model training failed: {e}")
152
+ result.errors.append(f"Training error: {str(e)}")
153
+ return self._finalize_training_result(result, start_time)
154
+
155
+ def train_multiple_models(self,
156
+ data: pd.DataFrame,
157
+ target_column: str,
158
+ algorithm_configs: List[TrainingConfig]) -> Dict[str, TrainingResult]:
159
+ """Train multiple models for comparison"""
160
+ results = {}
161
+
162
+ for i, config in enumerate(algorithm_configs):
163
+ algorithm_name = config.algorithm
164
+ logger.info(f"Training model {i+1}/{len(algorithm_configs)}: {algorithm_name}")
165
+
166
+ try:
167
+ result = self.train_model(data, target_column, config)
168
+ results[algorithm_name] = result
169
+ except Exception as e:
170
+ logger.error(f"Failed to train {algorithm_name}: {e}")
171
+ results[algorithm_name] = TrainingResult(
172
+ success=False,
173
+ errors=[str(e)]
174
+ )
175
+
176
+ return results
177
+
178
+ def get_algorithm_recommendations(self,
179
+ data: pd.DataFrame,
180
+ target_column: str) -> Dict[str, Any]:
181
+ """Get ML algorithm recommendations for the dataset"""
182
+ try:
183
+ # Use MLProcessor for comprehensive analysis
184
+ MLProcessor = _get_ml_processor()
185
+ MLProcessor = _get_ml_processor()
186
+ processor = MLProcessor(csv_processor=None, file_path=None)
187
+ processor.df = data
188
+
189
+ # Get ML analysis and recommendations
190
+ analysis = processor.get_ml_analysis(target_column)
191
+
192
+ if 'error' in analysis:
193
+ return {'success': False, 'error': analysis['error']}
194
+
195
+ return {
196
+ 'success': True,
197
+ 'problem_analysis': analysis.get('problem_analysis', {}),
198
+ 'algorithm_recommendations': analysis.get('algorithm_recommendations', {}),
199
+ 'preprocessing_recommendations': analysis.get('preprocessing_recommendations', {}),
200
+ 'data_preparation_needs': analysis.get('data_preparation', {})
201
+ }
202
+
203
+ except Exception as e:
204
+ logger.error(f"Algorithm recommendation failed: {e}")
205
+ return {'success': False, 'error': str(e)}
206
+
207
+ def tune_hyperparameters(self,
208
+ data: pd.DataFrame,
209
+ target_column: str,
210
+ algorithm: str,
211
+ param_grid: Optional[Dict[str, Any]] = None,
212
+ search_type: str = "grid",
213
+ cv_folds: int = 5) -> TrainingResult:
214
+ """Perform hyperparameter tuning for a specific algorithm"""
215
+ start_time = datetime.now()
216
+
217
+ try:
218
+ # Create processor
219
+ MLProcessor = _get_ml_processor()
220
+ processor = MLProcessor(csv_processor=None, file_path=None)
221
+ processor.df = data
222
+
223
+ # Perform hyperparameter tuning
224
+ tuning_result = processor.hyperparameter_tuning(
225
+ target_column=target_column,
226
+ algorithm=algorithm,
227
+ param_grid=param_grid,
228
+ search_type=search_type,
229
+ cv_folds=cv_folds
230
+ )
231
+
232
+ if 'error' in tuning_result:
233
+ return TrainingResult(
234
+ success=False,
235
+ errors=[tuning_result['error']]
236
+ )
237
+
238
+ # Store tuned model
239
+ model_id = tuning_result['model_id']
240
+ self.trained_models[model_id] = {
241
+ 'processor': processor,
242
+ 'model_instance': processor.models.get(model_id),
243
+ 'training_config': TrainingConfig(
244
+ algorithm=algorithm,
245
+ hyperparameters=tuning_result['best_parameters']
246
+ ),
247
+ 'target_column': target_column,
248
+ 'problem_type': 'auto_detected',
249
+ 'created_at': start_time,
250
+ 'is_tuned': True
251
+ }
252
+
253
+ result = TrainingResult(
254
+ success=True,
255
+ model_info={
256
+ 'model_id': model_id,
257
+ 'algorithm': algorithm,
258
+ 'is_hyperparameter_tuned': True
259
+ },
260
+ training_metrics=tuning_result,
261
+ model_metadata={
262
+ 'tuning_method': search_type,
263
+ 'cv_folds': cv_folds,
264
+ 'best_parameters': tuning_result['best_parameters'],
265
+ 'best_score': tuning_result['best_score']
266
+ }
267
+ )
268
+
269
+ return self._finalize_training_result(result, start_time)
270
+
271
+ except Exception as e:
272
+ logger.error(f"Hyperparameter tuning failed: {e}")
273
+ return TrainingResult(
274
+ success=False,
275
+ errors=[str(e)]
276
+ )
277
+
278
+ def _validate_training_inputs(self,
279
+ data: pd.DataFrame,
280
+ target_column: str,
281
+ config: TrainingConfig) -> Dict[str, Any]:
282
+ """Validate training inputs"""
283
+ errors = []
284
+
285
+ # Check data
286
+ if data.empty:
287
+ errors.append("Training data is empty")
288
+
289
+ # Check target column
290
+ if target_column not in data.columns:
291
+ errors.append(f"Target column '{target_column}' not found in data")
292
+
293
+ # Check algorithm
294
+ supported_algorithms = [
295
+ 'logistic_regression', 'linear_regression', 'ridge', 'lasso',
296
+ 'random_forest_classifier', 'random_forest_regressor',
297
+ 'decision_tree_classifier', 'decision_tree_regressor',
298
+ 'svm_classifier', 'svm_regressor', 'knn_classifier', 'knn_regressor',
299
+ 'naive_bayes', 'xgboost_classifier', 'xgboost_regressor', 'prophet'
300
+ ]
301
+
302
+ if config.algorithm.lower() not in supported_algorithms:
303
+ errors.append(f"Unsupported algorithm: {config.algorithm}")
304
+
305
+ # Check test size
306
+ if not 0 < config.test_size < 1:
307
+ errors.append("Test size must be between 0 and 1")
308
+
309
+ return {
310
+ 'valid': len(errors) == 0,
311
+ 'errors': errors
312
+ }
313
+
314
+ def _get_model_processor(self,
315
+ data: pd.DataFrame,
316
+ target_column: str,
317
+ config: TrainingConfig) -> Dict[str, Any]:
318
+ """Get appropriate model processor based on algorithm and problem type"""
319
+ try:
320
+ algorithm = config.algorithm.lower()
321
+
322
+ # Check if it's a time series problem
323
+ if algorithm == 'prophet' or 'ds' in data.columns:
324
+ try:
325
+ TimeSeriesProcessor = _get_time_series_processor()
326
+ processor = TimeSeriesProcessor(csv_processor=None, file_path=None)
327
+ except Exception:
328
+ # Use MLProcessor for time series if TimeSeriesProcessor not available
329
+ MLProcessor = _get_ml_processor()
330
+ processor = MLProcessor(csv_processor=None, file_path=None)
331
+ processor.df = data
332
+ return {
333
+ 'success': True,
334
+ 'processor': processor,
335
+ 'problem_type': 'time_series'
336
+ }
337
+ processor.df = data
338
+ return {
339
+ 'success': True,
340
+ 'processor': processor,
341
+ 'problem_type': 'time_series'
342
+ }
343
+
344
+ # MLProcessor causes mutex locks due to complex dependency chains
345
+ # Use lightweight DataFrameMLProcessor instead
346
+ class DataFrameMLProcessor:
347
+ """Lightweight ML processor that works directly with DataFrames"""
348
+ def __init__(self, dataframe):
349
+ self.df = dataframe
350
+
351
+ def train_model(self, target_column, algorithm, test_size=0.2, **hyperparameters):
352
+ """Train model using sklearn directly"""
353
+ try:
354
+ from sklearn.model_selection import train_test_split
355
+ from sklearn.metrics import accuracy_score, r2_score, mean_squared_error
356
+ from sklearn.linear_model import LogisticRegression, LinearRegression
357
+ from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor
358
+ from sklearn.tree import DecisionTreeClassifier, DecisionTreeRegressor
359
+ import time
360
+
361
+ start_time = time.time()
362
+
363
+ # Prepare data
364
+ X = self.df.drop(columns=[target_column])
365
+ y = self.df[target_column]
366
+
367
+ # Select numeric features only
368
+ numeric_features = X.select_dtypes(include=['int64', 'float64']).columns
369
+ X = X[numeric_features]
370
+
371
+ if len(X.columns) == 0:
372
+ return {'error': 'No numeric features available for training'}
373
+
374
+ # Split data
375
+ X_train, X_test, y_train, y_test = train_test_split(
376
+ X, y, test_size=test_size, random_state=42
377
+ )
378
+
379
+ # Detect problem type
380
+ if y.dtype in ['int64', 'float64'] and y.nunique() > 10:
381
+ problem_type = 'regression'
382
+ else:
383
+ problem_type = 'classification'
384
+
385
+ # Select and train model
386
+ if problem_type == 'classification':
387
+ if algorithm.lower() in ['logistic_regression', 'logistic']:
388
+ model = LogisticRegression(random_state=42, max_iter=1000, **hyperparameters)
389
+ elif algorithm.lower() in ['random_forest', 'rf']:
390
+ model = RandomForestClassifier(random_state=42, n_estimators=100, **hyperparameters)
391
+ elif algorithm.lower() in ['decision_tree', 'tree']:
392
+ model = DecisionTreeClassifier(random_state=42, **hyperparameters)
393
+ else:
394
+ model = LogisticRegression(random_state=42, max_iter=1000)
395
+ else: # regression
396
+ if algorithm.lower() in ['linear_regression', 'linear']:
397
+ model = LinearRegression(**hyperparameters)
398
+ elif algorithm.lower() in ['random_forest', 'rf']:
399
+ model = RandomForestRegressor(random_state=42, n_estimators=100, **hyperparameters)
400
+ elif algorithm.lower() in ['decision_tree', 'tree']:
401
+ model = DecisionTreeRegressor(random_state=42, **hyperparameters)
402
+ else:
403
+ model = LinearRegression()
404
+
405
+ # Train
406
+ model.fit(X_train, y_train)
407
+
408
+ # Evaluate
409
+ y_pred = model.predict(X_test)
410
+ if problem_type == 'classification':
411
+ score = accuracy_score(y_test, y_pred)
412
+ metrics = {
413
+ 'accuracy': float(score),
414
+ 'test_samples': len(y_test)
415
+ }
416
+ else:
417
+ r2 = r2_score(y_test, y_pred)
418
+ mse = mean_squared_error(y_test, y_pred)
419
+ metrics = {
420
+ 'r2_score': float(r2),
421
+ 'mse': float(mse),
422
+ 'test_samples': len(y_test)
423
+ }
424
+
425
+ training_time = time.time() - start_time
426
+
427
+ # Generate model ID
428
+ from datetime import datetime
429
+ model_id = f'{algorithm}_{int(datetime.now().timestamp())}'
430
+
431
+ return {
432
+ 'model_id': model_id,
433
+ 'model_instance': model,
434
+ 'problem_type': problem_type,
435
+ 'metrics': metrics,
436
+ 'features_used': list(X.columns),
437
+ 'n_samples': len(X),
438
+ 'train_size': len(X_train),
439
+ 'test_size': len(X_test),
440
+ 'training_time_seconds': training_time,
441
+ 'algorithm': algorithm
442
+ }
443
+
444
+ except Exception as e:
445
+ return {'error': f'Model training failed: {str(e)}'}
446
+
447
+ processor = DataFrameMLProcessor(data)
448
+
449
+ return {
450
+ 'success': True,
451
+ 'processor': processor,
452
+ 'problem_type': 'classification' # Will be detected during training
453
+ }
454
+
455
+ except Exception as e:
456
+ return {
457
+ 'success': False,
458
+ 'errors': [f"Processor initialization failed: {str(e)}"]
459
+ }
460
+
461
+ def _execute_training(self,
462
+ processor,
463
+ data: pd.DataFrame,
464
+ target_column: str,
465
+ config: TrainingConfig,
466
+ problem_type: str) -> Dict[str, Any]:
467
+ """Execute the actual model training"""
468
+ try:
469
+ if hasattr(processor, 'train_model'):
470
+ # Use processor's train_model method
471
+ training_result = processor.train_model(
472
+ target_column=target_column,
473
+ algorithm=config.algorithm,
474
+ test_size=config.test_size,
475
+ **config.hyperparameters
476
+ )
477
+
478
+ if 'error' in training_result:
479
+ return {
480
+ 'success': False,
481
+ 'errors': [training_result['error']]
482
+ }
483
+
484
+ return {
485
+ 'success': True,
486
+ 'model_id': training_result['model_id'],
487
+ 'training_metrics': training_result,
488
+ 'metadata': {
489
+ 'algorithm': config.algorithm,
490
+ 'problem_type': problem_type,
491
+ 'training_time': training_result.get('training_time_seconds', 0)
492
+ }
493
+ }
494
+ else:
495
+ return {
496
+ 'success': False,
497
+ 'errors': [f"Processor does not support training method"]
498
+ }
499
+
500
+ except Exception as e:
501
+ return {
502
+ 'success': False,
503
+ 'errors': [f"Training execution failed: {str(e)}"]
504
+ }
505
+
506
+ def _finalize_training_result(self,
507
+ result: TrainingResult,
508
+ start_time: datetime) -> TrainingResult:
509
+ """Finalize training result with timing and stats"""
510
+ end_time = datetime.now()
511
+ duration = (end_time - start_time).total_seconds()
512
+
513
+ # Update performance metrics
514
+ result.performance_metrics['training_duration_seconds'] = duration
515
+ result.performance_metrics['end_time'] = end_time
516
+ result.model_metadata['end_time'] = end_time
517
+ result.model_metadata['duration_seconds'] = duration
518
+
519
+ # Update execution stats
520
+ self.execution_stats['total_training_operations'] += 1
521
+ if result.success:
522
+ self.execution_stats['successful_training_operations'] += 1
523
+ self.execution_stats['models_trained'] += 1
524
+ else:
525
+ self.execution_stats['failed_training_operations'] += 1
526
+
527
+ # Update average duration
528
+ total = self.execution_stats['total_training_operations']
529
+ old_avg = self.execution_stats['average_training_time']
530
+ self.execution_stats['average_training_time'] = (old_avg * (total - 1) + duration) / total
531
+
532
+ logger.info(f"Training completed: success={result.success}, duration={duration:.2f}s")
533
+ return result
534
+
535
+ def get_trained_model(self, model_id: str) -> Optional[Dict[str, Any]]:
536
+ """Get information about a trained model"""
537
+ return self.trained_models.get(model_id)
538
+
539
+ def list_trained_models(self) -> List[Dict[str, Any]]:
540
+ """List all trained models"""
541
+ models_info = []
542
+ for model_id, model_data in self.trained_models.items():
543
+ models_info.append({
544
+ 'model_id': model_id,
545
+ 'algorithm': model_data.get('training_config').algorithm,
546
+ 'problem_type': model_data.get('problem_type'),
547
+ 'target_column': model_data.get('target_column'),
548
+ 'created_at': model_data.get('created_at'),
549
+ 'is_tuned': model_data.get('is_tuned', False)
550
+ })
551
+ return models_info
552
+
553
+ def get_execution_stats(self) -> Dict[str, Any]:
554
+ """Get service execution statistics"""
555
+ return {
556
+ **self.execution_stats,
557
+ 'success_rate': (
558
+ self.execution_stats['successful_training_operations'] /
559
+ max(1, self.execution_stats['total_training_operations'])
560
+ )
561
+ }
@@ -0,0 +1,21 @@
1
+ """
2
+ Inference Models
3
+
4
+ Data models for inference operations following the ISA Model architecture pattern.
5
+ """
6
+
7
+ from .inference_record import InferenceRequest, UsageStatistics, ModelUsageSnapshot
8
+ from .inference_config import InferenceConfig, ProviderConfig, ModelConfig
9
+ from .performance_models import PerformanceMetrics, LatencyProfile, ThroughputProfile
10
+
11
+ __all__ = [
12
+ "InferenceRequest",
13
+ "UsageStatistics",
14
+ "ModelUsageSnapshot",
15
+ "InferenceConfig",
16
+ "ProviderConfig",
17
+ "ModelConfig",
18
+ "PerformanceMetrics",
19
+ "LatencyProfile",
20
+ "ThroughputProfile"
21
+ ]