// src/api/services/TrainingService.ts import { apiClient } from '../base/apiClient'; import { ApiResponse } from '../types/api'; export interface TrainingJobStatus { job_id: string; tenant_id: string; status: 'queued' | 'running' | 'completed' | 'failed' | 'cancelled'; progress: number; current_step?: string; started_at: string; completed_at?: string; duration_seconds?: number; models_trained?: Record; metrics?: Record; error_message?: string; } export interface TrainingRequest { force_retrain?: boolean; products?: string[]; training_days?: number; } export interface TrainedModel { id: string; product_name: string; model_type: string; model_version: string; mape?: number; rmse?: number; mae?: number; r2_score?: number; training_samples?: number; features_used?: string[]; is_active: boolean; created_at: string; last_used_at?: string; } export interface TrainingJobProgress { id: string; status: 'queued' | 'running' | 'completed' | 'failed' | 'cancelled'; progress: number; current_step?: string; total_steps?: number; step_details?: string; estimated_completion?: string; logs?: string[]; } export interface ModelMetrics { mape: number; rmse: number; mae: number; r2_score: number; training_samples: number; validation_samples: number; features_used: string[]; } export interface TrainingConfiguration { include_weather: boolean; include_traffic: boolean; min_data_points: number; forecast_horizon_days: number; cross_validation_folds: number; hyperparameter_tuning: boolean; products?: string[]; } export class TrainingService { /** * Start new training job */ async startTraining(tenantId: string, config: TrainingConfiguration): Promise { const response = await apiClient.post( `/api/v1/tenants/${tenantId}/training/jobs`, config ); return response.data!; } /** * Get training job status */ async getTrainingStatus(tenantId: string, jobId: string): Promise { const response = await apiClient.get>( `/api/v1/tenants/${tenantId}/training/jobs/${jobId}` ); return response.data!; } /** * Get all training jobs */ async getTrainingHistory(tenantId: string, params?: { page?: number; limit?: number; status?: string; }): Promise<{ jobs: TrainingJobStatus[]; total: number; page: number; pages: number; }> { const response = await apiClient.get>('/api/v1/training/jobs', { params }); return response.data!; } /** * Cancel training job */ async cancelTraining(tenantId: string, jobId: string): Promise { await apiClient.post(`/api/v1/tenants/${tenantId}/training/jobs/${jobId}/cancel`); } /** * Get trained models */ async getModels(tenantId: string, params?: { productName?: string; active?: boolean; page?: number; limit?: number; }): Promise<{ models: TrainedModel[]; total: number; page: number; pages: number; }> { const response = await apiClient.get>(`/api/v1/tenants/${tenantId}/training/models`, { params }); return response.data!; } /** * Get specific model details */ async getModel(tenantId: string, modelId: string): Promise { const response = await apiClient.get>( `/api/v1/training/models/${modelId}` ); return response.data!; } /** * Get model metrics */ async getModelMetrics(tenantId: string, modelId: string): Promise { const response = await apiClient.get>( `/api/v1/tenants/${tenantId}/training/models/${modelId}/metrics` ); return response.data!; } /** * Activate/deactivate model */ async toggleModelStatus(tenantId: string, modelId: string, active: boolean): Promise { const response = await apiClient.patch>( `/api/v1/tenants/${tenantId}/training/models/${modelId}`, { is_active: active } ); return response.data!; } /** * Delete model */ async deleteModel(tenantId: string, modelId: string): Promise { await apiClient.delete(`/api/v1/training/models/${modelId}`); } /** * Train specific product */ async trainProduct(tenantId: string, productName: string, config?: Partial): Promise { const response = await apiClient.post>( `/api/v1/tenants/${tenantId}/training/products/train`, { product_name: productName, ...config, } ); return response.data!; } /** * Get training statistics */ async getTrainingStats(tenantId: string): Promise<{ total_models: number; active_models: number; avg_accuracy: number; last_training_date: string | null; products_trained: number; training_time_avg_minutes: number; }> { const response = await apiClient.get>(`/api/v1/tenants/${tenantId}/training/stats`); return response.data!; } /** * Validate training data */ async validateTrainingData(tenantId: string, products?: string[]): Promise<{ valid: boolean; errors: string[]; warnings: string[]; product_data_points: Record; recommendation: string; }> { const response = await apiClient.post>(`/api/v1/tenants/${tenantId}/training/validate`, { products, }); return response.data!; } /** * Get training recommendations */ async getTrainingRecommendations(tenantId: string): Promise<{ should_retrain: boolean; reasons: string[]; recommended_products: string[]; optimal_config: TrainingConfiguration; }> { const response = await apiClient.get>(`/api/v1/tenants/${tenantId}/training/recommendations`); return response.data!; } /** * Get training logs */ async getTrainingLogs(tenantId: string, jobId: string): Promise { const response = await apiClient.get>(`/api/v1/tenants/${tenantId}/training/jobs/${jobId}/logs`); return response.data!; } /** * Export model */ async exportModel(tenantId: string, modelId: string, format: 'pickle' | 'onnx' = 'pickle'): Promise { const response = await apiClient.get(`/api/v1/tenants/${tenantId}/training/models/${modelId}/export`, { params: { format }, responseType: 'blob', }); return response as unknown as Blob; } } export const trainingService = new TrainingService();