Files
bakery-ia/frontend/src/api/services/trainingService.ts

254 lines
6.6 KiB
TypeScript
Raw Normal View History

2025-07-22 17:01:12 +02:00
// src/api/services/TrainingService.ts
import { apiClient } from '../base/apiClient';
import {
2025-07-23 10:02:48 +02:00
ApiResponse
2025-07-22 17:01:12 +02:00
} from '../types/api';
2025-07-23 10:02:48 +02:00
export interface TrainingJobStatus {
2025-07-25 21:56:53 +02:00
job_id: string;
2025-07-23 10:02:48 +02:00
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<string, any>;
metrics?: Record<string, any>;
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;
}
2025-07-22 17:01:12 +02:00
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
*/
2025-07-26 18:46:52 +02:00
async startTraining(tenantId: string, config: TrainingConfiguration): Promise<TrainingJobStatus> {
2025-07-25 21:56:53 +02:00
const response = await apiClient.post<TrainingJobStatus>(
2025-07-26 18:46:52 +02:00
`/api/v1/tenants/${tenantId}/training/jobs`,
2025-07-22 17:01:12 +02:00
config
);
return response.data!;
}
/**
* Get training job status
*/
2025-07-26 18:46:52 +02:00
async getTrainingStatus(tenantId: string, jobId: string): Promise<TrainingJobProgress> {
2025-07-22 17:01:12 +02:00
const response = await apiClient.get<ApiResponse<TrainingJobProgress>>(
2025-07-26 18:46:52 +02:00
`/api/v1/tenants/${tenantId}/training/jobs/${jobId}`
2025-07-22 17:01:12 +02:00
);
return response.data!;
}
/**
* Get all training jobs
*/
2025-07-26 18:46:52 +02:00
async getTrainingHistory(tenantId: string, params?: {
2025-07-22 17:01:12 +02:00
page?: number;
limit?: number;
status?: string;
}): Promise<{
jobs: TrainingJobStatus[];
total: number;
page: number;
pages: number;
}> {
2025-07-23 07:26:04 +02:00
const response = await apiClient.get<ApiResponse<any>>('/api/v1/training/jobs', { params });
2025-07-22 17:01:12 +02:00
return response.data!;
}
/**
* Cancel training job
*/
2025-07-26 18:46:52 +02:00
async cancelTraining(tenantId: string, jobId: string): Promise<void> {
await apiClient.post(`/api/v1/tenants/${tenantId}/training/jobs/${jobId}/cancel`);
2025-07-22 17:01:12 +02:00
}
/**
* Get trained models
*/
2025-07-26 18:46:52 +02:00
async getModels(tenantId: string, params?: {
2025-07-22 17:01:12 +02:00
productName?: string;
active?: boolean;
page?: number;
limit?: number;
}): Promise<{
models: TrainedModel[];
total: number;
page: number;
pages: number;
}> {
2025-07-26 18:46:52 +02:00
const response = await apiClient.get<ApiResponse<any>>(`/api/v1/tenants/${tenantId}/training/models`, { params });
2025-07-22 17:01:12 +02:00
return response.data!;
}
/**
* Get specific model details
*/
2025-07-26 18:46:52 +02:00
async getModel(tenantId: string, modelId: string): Promise<TrainedModel> {
2025-07-22 17:01:12 +02:00
const response = await apiClient.get<ApiResponse<TrainedModel>>(
2025-07-23 07:26:04 +02:00
`/api/v1/training/models/${modelId}`
2025-07-22 17:01:12 +02:00
);
return response.data!;
}
/**
* Get model metrics
*/
2025-07-26 18:46:52 +02:00
async getModelMetrics(tenantId: string, modelId: string): Promise<ModelMetrics> {
2025-07-22 17:01:12 +02:00
const response = await apiClient.get<ApiResponse<ModelMetrics>>(
2025-07-26 18:46:52 +02:00
`/api/v1/tenants/${tenantId}/training/models/${modelId}/metrics`
2025-07-22 17:01:12 +02:00
);
return response.data!;
}
/**
* Activate/deactivate model
*/
2025-07-26 18:46:52 +02:00
async toggleModelStatus(tenantId: string, modelId: string, active: boolean): Promise<TrainedModel> {
2025-07-22 17:01:12 +02:00
const response = await apiClient.patch<ApiResponse<TrainedModel>>(
2025-07-26 18:46:52 +02:00
`/api/v1/tenants/${tenantId}/training/models/${modelId}`,
2025-07-22 17:01:12 +02:00
{ is_active: active }
);
return response.data!;
}
/**
* Delete model
*/
2025-07-26 18:46:52 +02:00
async deleteModel(tenantId: string, modelId: string): Promise<void> {
2025-07-23 07:26:04 +02:00
await apiClient.delete(`/api/v1/training/models/${modelId}`);
2025-07-22 17:01:12 +02:00
}
/**
* Train specific product
*/
2025-07-26 18:46:52 +02:00
async trainProduct(tenantId: string, productName: string, config?: Partial<TrainingConfiguration>): Promise<TrainingJobStatus> {
2025-07-22 17:01:12 +02:00
const response = await apiClient.post<ApiResponse<TrainingJobStatus>>(
2025-07-26 18:46:52 +02:00
`/api/v1/tenants/${tenantId}/training/products/train`,
2025-07-22 17:01:12 +02:00
{
product_name: productName,
...config,
}
);
return response.data!;
}
/**
* Get training statistics
*/
2025-07-26 18:46:52 +02:00
async getTrainingStats(tenantId: string): Promise<{
2025-07-22 17:01:12 +02:00
total_models: number;
active_models: number;
avg_accuracy: number;
last_training_date: string | null;
products_trained: number;
training_time_avg_minutes: number;
}> {
2025-07-26 18:46:52 +02:00
const response = await apiClient.get<ApiResponse<any>>(`/api/v1/tenants/${tenantId}/training/stats`);
2025-07-22 17:01:12 +02:00
return response.data!;
}
/**
* Validate training data
*/
2025-07-26 18:46:52 +02:00
async validateTrainingData(tenantId: string, products?: string[]): Promise<{
2025-07-22 17:01:12 +02:00
valid: boolean;
errors: string[];
warnings: string[];
product_data_points: Record<string, number>;
recommendation: string;
}> {
2025-07-26 18:46:52 +02:00
const response = await apiClient.post<ApiResponse<any>>(`/api/v1/tenants/${tenantId}/training/validate`, {
2025-07-22 17:01:12 +02:00
products,
});
return response.data!;
}
/**
* Get training recommendations
*/
2025-07-26 18:46:52 +02:00
async getTrainingRecommendations(tenantId: string): Promise<{
2025-07-22 17:01:12 +02:00
should_retrain: boolean;
reasons: string[];
recommended_products: string[];
optimal_config: TrainingConfiguration;
}> {
2025-07-26 18:46:52 +02:00
const response = await apiClient.get<ApiResponse<any>>(`/api/v1/tenants/${tenantId}/training/recommendations`);
2025-07-22 17:01:12 +02:00
return response.data!;
}
/**
* Get training logs
*/
2025-07-26 18:46:52 +02:00
async getTrainingLogs(tenantId: string, jobId: string): Promise<string[]> {
const response = await apiClient.get<ApiResponse<string[]>>(`/api/v1/tenants/${tenantId}/training/jobs/${jobId}/logs`);
2025-07-22 17:01:12 +02:00
return response.data!;
}
/**
* Export model
*/
2025-07-26 18:46:52 +02:00
async exportModel(tenantId: string, modelId: string, format: 'pickle' | 'onnx' = 'pickle'): Promise<Blob> {
const response = await apiClient.get(`/api/v1/tenants/${tenantId}/training/models/${modelId}/export`, {
2025-07-22 17:01:12 +02:00
params: { format },
responseType: 'blob',
});
return response as unknown as Blob;
}
}
export const trainingService = new TrainingService();