isa-model 0.4.0__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.
- isa_model/client.py +466 -43
- isa_model/core/cache/redis_cache.py +12 -3
- isa_model/core/config/config_manager.py +230 -3
- isa_model/core/config.py +90 -0
- isa_model/core/database/direct_db_client.py +114 -0
- isa_model/core/database/migration_manager.py +563 -0
- isa_model/core/database/migrations.py +21 -1
- isa_model/core/database/supabase_client.py +154 -19
- isa_model/core/dependencies.py +316 -0
- isa_model/core/discovery/__init__.py +19 -0
- isa_model/core/discovery/consul_discovery.py +190 -0
- isa_model/core/logging/__init__.py +54 -0
- isa_model/core/logging/influx_logger.py +523 -0
- isa_model/core/logging/loki_logger.py +160 -0
- isa_model/core/models/__init__.py +27 -18
- isa_model/core/models/config_models.py +625 -0
- isa_model/core/models/deployment_billing_tracker.py +430 -0
- isa_model/core/models/model_manager.py +40 -17
- isa_model/core/models/model_metadata.py +690 -0
- isa_model/core/models/model_repo.py +174 -18
- isa_model/core/models/system_models.py +857 -0
- isa_model/core/repositories/__init__.py +9 -0
- isa_model/core/repositories/config_repository.py +912 -0
- isa_model/core/services/intelligent_model_selector.py +399 -21
- isa_model/core/storage/hf_storage.py +1 -1
- isa_model/core/types.py +1 -0
- isa_model/deployment/__init__.py +5 -48
- isa_model/deployment/core/__init__.py +2 -31
- isa_model/deployment/core/deployment_manager.py +1278 -370
- isa_model/deployment/local/__init__.py +31 -0
- isa_model/deployment/local/config.py +248 -0
- isa_model/deployment/local/gpu_gateway.py +607 -0
- isa_model/deployment/local/health_checker.py +428 -0
- isa_model/deployment/local/provider.py +586 -0
- isa_model/deployment/local/tensorrt_service.py +621 -0
- isa_model/deployment/local/transformers_service.py +644 -0
- isa_model/deployment/local/vllm_service.py +527 -0
- isa_model/deployment/modal/__init__.py +8 -0
- isa_model/deployment/modal/config.py +136 -0
- isa_model/deployment/{services/auto_hf_modal_deployer.py → modal/deployer.py} +1 -1
- isa_model/deployment/modal/services/__init__.py +3 -0
- isa_model/deployment/modal/services/audio/__init__.py +1 -0
- isa_model/deployment/modal/services/embedding/__init__.py +1 -0
- isa_model/deployment/modal/services/llm/__init__.py +1 -0
- isa_model/deployment/modal/services/llm/isa_llm_service.py +424 -0
- isa_model/deployment/modal/services/video/__init__.py +1 -0
- isa_model/deployment/modal/services/vision/__init__.py +1 -0
- isa_model/deployment/models/org-org-acme-corp-tenant-a-service-llm-20250825-225822/tenant-a-service_modal_service.py +48 -0
- isa_model/deployment/models/org-test-org-123-prefix-test-service-llm-20250825-225822/prefix-test-service_modal_service.py +48 -0
- isa_model/deployment/models/test-llm-service-llm-20250825-204442/test-llm-service_modal_service.py +48 -0
- isa_model/deployment/models/test-monitoring-gpt2-llm-20250825-212906/test-monitoring-gpt2_modal_service.py +48 -0
- isa_model/deployment/models/test-monitoring-gpt2-llm-20250825-213009/test-monitoring-gpt2_modal_service.py +48 -0
- isa_model/deployment/storage/__init__.py +5 -0
- isa_model/deployment/storage/deployment_repository.py +824 -0
- isa_model/deployment/triton/__init__.py +10 -0
- isa_model/deployment/triton/config.py +196 -0
- isa_model/deployment/triton/configs/__init__.py +1 -0
- isa_model/deployment/triton/provider.py +512 -0
- isa_model/deployment/triton/scripts/__init__.py +1 -0
- isa_model/deployment/triton/templates/__init__.py +1 -0
- isa_model/inference/__init__.py +47 -1
- isa_model/inference/ai_factory.py +137 -10
- isa_model/inference/legacy_services/__init__.py +21 -0
- isa_model/inference/legacy_services/model_evaluation.py +637 -0
- isa_model/inference/legacy_services/model_service.py +573 -0
- isa_model/inference/legacy_services/model_serving.py +717 -0
- isa_model/inference/legacy_services/model_training.py +561 -0
- isa_model/inference/models/__init__.py +21 -0
- isa_model/inference/models/inference_config.py +551 -0
- isa_model/inference/models/inference_record.py +675 -0
- isa_model/inference/models/performance_models.py +714 -0
- isa_model/inference/repositories/__init__.py +9 -0
- isa_model/inference/repositories/inference_repository.py +828 -0
- isa_model/inference/services/audio/base_stt_service.py +184 -11
- isa_model/inference/services/audio/openai_stt_service.py +22 -6
- isa_model/inference/services/custom_model_manager.py +277 -0
- isa_model/inference/services/embedding/ollama_embed_service.py +15 -3
- isa_model/inference/services/embedding/resilient_embed_service.py +285 -0
- isa_model/inference/services/llm/__init__.py +10 -2
- isa_model/inference/services/llm/base_llm_service.py +335 -24
- isa_model/inference/services/llm/cerebras_llm_service.py +628 -0
- isa_model/inference/services/llm/helpers/llm_adapter.py +9 -4
- isa_model/inference/services/llm/helpers/llm_prompts.py +342 -0
- isa_model/inference/services/llm/helpers/llm_utils.py +321 -23
- isa_model/inference/services/llm/huggingface_llm_service.py +581 -0
- isa_model/inference/services/llm/local_llm_service.py +747 -0
- isa_model/inference/services/llm/ollama_llm_service.py +9 -2
- isa_model/inference/services/llm/openai_llm_service.py +33 -16
- isa_model/inference/services/llm/yyds_llm_service.py +8 -2
- isa_model/inference/services/vision/__init__.py +22 -1
- isa_model/inference/services/vision/blip_vision_service.py +359 -0
- isa_model/inference/services/vision/helpers/image_utils.py +8 -5
- isa_model/inference/services/vision/isa_vision_service.py +65 -4
- isa_model/inference/services/vision/openai_vision_service.py +19 -10
- isa_model/inference/services/vision/vgg16_vision_service.py +257 -0
- isa_model/serving/api/cache_manager.py +245 -0
- isa_model/serving/api/dependencies/__init__.py +1 -0
- isa_model/serving/api/dependencies/auth.py +194 -0
- isa_model/serving/api/dependencies/database.py +139 -0
- isa_model/serving/api/error_handlers.py +284 -0
- isa_model/serving/api/fastapi_server.py +172 -22
- isa_model/serving/api/middleware/auth.py +8 -2
- isa_model/serving/api/middleware/security.py +23 -33
- isa_model/serving/api/middleware/tenant_context.py +414 -0
- isa_model/serving/api/routes/analytics.py +4 -1
- isa_model/serving/api/routes/config.py +645 -0
- isa_model/serving/api/routes/deployment_billing.py +315 -0
- isa_model/serving/api/routes/deployments.py +138 -2
- isa_model/serving/api/routes/gpu_gateway.py +440 -0
- isa_model/serving/api/routes/health.py +32 -12
- isa_model/serving/api/routes/inference_monitoring.py +486 -0
- isa_model/serving/api/routes/local_deployments.py +448 -0
- isa_model/serving/api/routes/tenants.py +575 -0
- isa_model/serving/api/routes/unified.py +680 -18
- isa_model/serving/api/routes/webhooks.py +479 -0
- isa_model/serving/api/startup.py +68 -54
- isa_model/utils/gpu_utils.py +311 -0
- {isa_model-0.4.0.dist-info → isa_model-0.4.3.dist-info}/METADATA +66 -24
- isa_model-0.4.3.dist-info/RECORD +193 -0
- isa_model/core/storage/minio_storage.py +0 -0
- isa_model/deployment/cloud/__init__.py +0 -9
- isa_model/deployment/cloud/modal/__init__.py +0 -10
- isa_model/deployment/core/deployment_config.py +0 -356
- isa_model/deployment/core/isa_deployment_service.py +0 -401
- isa_model/deployment/gpu_int8_ds8/app/server.py +0 -66
- isa_model/deployment/gpu_int8_ds8/scripts/test_client.py +0 -43
- isa_model/deployment/gpu_int8_ds8/scripts/test_client_os.py +0 -35
- isa_model/deployment/runtime/deployed_service.py +0 -338
- isa_model/deployment/services/__init__.py +0 -9
- isa_model/deployment/services/auto_deploy_vision_service.py +0 -538
- isa_model/deployment/services/model_service.py +0 -332
- isa_model/deployment/services/service_monitor.py +0 -356
- isa_model/deployment/services/service_registry.py +0 -527
- isa_model/eval/__init__.py +0 -92
- isa_model/eval/benchmarks/__init__.py +0 -27
- isa_model/eval/benchmarks/multimodal_datasets.py +0 -460
- isa_model/eval/benchmarks.py +0 -701
- isa_model/eval/config/__init__.py +0 -10
- isa_model/eval/config/evaluation_config.py +0 -108
- isa_model/eval/evaluators/__init__.py +0 -24
- isa_model/eval/evaluators/audio_evaluator.py +0 -727
- isa_model/eval/evaluators/base_evaluator.py +0 -503
- isa_model/eval/evaluators/embedding_evaluator.py +0 -742
- isa_model/eval/evaluators/llm_evaluator.py +0 -472
- isa_model/eval/evaluators/vision_evaluator.py +0 -564
- isa_model/eval/example_evaluation.py +0 -395
- isa_model/eval/factory.py +0 -798
- isa_model/eval/infrastructure/__init__.py +0 -24
- isa_model/eval/infrastructure/experiment_tracker.py +0 -466
- isa_model/eval/isa_benchmarks.py +0 -700
- isa_model/eval/isa_integration.py +0 -582
- isa_model/eval/metrics.py +0 -951
- isa_model/eval/tests/unit/test_basic.py +0 -396
- isa_model/serving/api/routes/evaluations.py +0 -579
- isa_model/training/__init__.py +0 -168
- isa_model/training/annotation/annotation_schema.py +0 -47
- isa_model/training/annotation/processors/annotation_processor.py +0 -126
- isa_model/training/annotation/storage/dataset_manager.py +0 -131
- isa_model/training/annotation/storage/dataset_schema.py +0 -44
- isa_model/training/annotation/tests/test_annotation_flow.py +0 -109
- isa_model/training/annotation/tests/test_minio copy.py +0 -113
- isa_model/training/annotation/tests/test_minio_upload.py +0 -43
- isa_model/training/annotation/views/annotation_controller.py +0 -158
- isa_model/training/cloud/__init__.py +0 -22
- isa_model/training/cloud/job_orchestrator.py +0 -402
- isa_model/training/cloud/runpod_trainer.py +0 -454
- isa_model/training/cloud/storage_manager.py +0 -482
- isa_model/training/core/__init__.py +0 -26
- isa_model/training/core/config.py +0 -181
- isa_model/training/core/dataset.py +0 -222
- isa_model/training/core/trainer.py +0 -720
- isa_model/training/core/utils.py +0 -213
- isa_model/training/examples/intelligent_training_example.py +0 -281
- isa_model/training/factory.py +0 -424
- isa_model/training/intelligent/__init__.py +0 -25
- isa_model/training/intelligent/decision_engine.py +0 -643
- isa_model/training/intelligent/intelligent_factory.py +0 -888
- isa_model/training/intelligent/knowledge_base.py +0 -751
- isa_model/training/intelligent/resource_optimizer.py +0 -839
- isa_model/training/intelligent/task_classifier.py +0 -576
- isa_model/training/storage/__init__.py +0 -24
- isa_model/training/storage/core_integration.py +0 -439
- isa_model/training/storage/training_repository.py +0 -552
- isa_model/training/storage/training_storage.py +0 -628
- isa_model-0.4.0.dist-info/RECORD +0 -182
- /isa_model/deployment/{cloud/modal → modal/services/audio}/isa_audio_chatTTS_service.py +0 -0
- /isa_model/deployment/{cloud/modal → modal/services/audio}/isa_audio_fish_service.py +0 -0
- /isa_model/deployment/{cloud/modal → modal/services/audio}/isa_audio_openvoice_service.py +0 -0
- /isa_model/deployment/{cloud/modal → modal/services/audio}/isa_audio_service_v2.py +0 -0
- /isa_model/deployment/{cloud/modal → modal/services/embedding}/isa_embed_rerank_service.py +0 -0
- /isa_model/deployment/{cloud/modal → modal/services/video}/isa_video_hunyuan_service.py +0 -0
- /isa_model/deployment/{cloud/modal → modal/services/vision}/isa_vision_ocr_service.py +0 -0
- /isa_model/deployment/{cloud/modal → modal/services/vision}/isa_vision_qwen25_service.py +0 -0
- /isa_model/deployment/{cloud/modal → modal/services/vision}/isa_vision_table_service.py +0 -0
- /isa_model/deployment/{cloud/modal → modal/services/vision}/isa_vision_ui_service.py +0 -0
- /isa_model/deployment/{cloud/modal → modal/services/vision}/isa_vision_ui_service_optimized.py +0 -0
- /isa_model/deployment/{services → modal/services/vision}/simple_auto_deploy_vision_service.py +0 -0
- {isa_model-0.4.0.dist-info → isa_model-0.4.3.dist-info}/WHEEL +0 -0
- {isa_model-0.4.0.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
|
+
]
|