// ================================================================ // frontend/src/api/services/training.ts // ================================================================ /** * Training Service - Complete backend alignment * * Backend API structure (3-tier architecture): * - ATOMIC: training_jobs.py, models.py * - OPERATIONS: training_operations.py * * Last Updated: 2025-10-05 * Status: ✅ Complete - Zero drift with backend */ import { apiClient } from '../client/apiClient'; import type { TrainingJobRequest, TrainingJobResponse, TrainingJobStatus, SingleProductTrainingRequest, ActiveModelResponse, ModelMetricsResponse, TrainedModelResponse, TenantStatistics, ModelPerformanceResponse, ModelsQueryParams, PaginatedResponse, } from '../types/training'; class TrainingService { private readonly baseUrl = '/tenants'; // =================================================================== // OPERATIONS: Training Job Creation // Backend: services/training/app/api/training_operations.py // =================================================================== /** * Create a new training job * POST /tenants/{tenant_id}/training/jobs */ async createTrainingJob( tenantId: string, request: TrainingJobRequest ): Promise { return apiClient.post( `${this.baseUrl}/${tenantId}/training/jobs`, request ); } /** * Train a single product * POST /tenants/{tenant_id}/training/products/{inventory_product_id} */ async trainSingleProduct( tenantId: string, inventoryProductId: string, request: SingleProductTrainingRequest ): Promise { return apiClient.post( `${this.baseUrl}/${tenantId}/training/products/${inventoryProductId}`, request ); } // =================================================================== // ATOMIC: Training Job Status // Backend: services/training/app/api/training_jobs.py // =================================================================== /** * Get training job status * GET /tenants/{tenant_id}/training/jobs/{job_id}/status */ async getTrainingJobStatus( tenantId: string, jobId: string ): Promise { return apiClient.get( `${this.baseUrl}/${tenantId}/training/jobs/${jobId}/status` ); } /** * Get training statistics * GET /tenants/{tenant_id}/training/statistics */ async getTenantStatistics(tenantId: string): Promise { return apiClient.get( `${this.baseUrl}/${tenantId}/training/statistics` ); } // =================================================================== // ATOMIC: Model Management // Backend: services/training/app/api/models.py // =================================================================== /** * Get active model for a product * GET /tenants/{tenant_id}/training/models/{inventory_product_id}/active */ async getActiveModel( tenantId: string, inventoryProductId: string ): Promise { return apiClient.get( `${this.baseUrl}/${tenantId}/training/models/${inventoryProductId}/active` ); } /** * Get model metrics * GET /tenants/{tenant_id}/training/models/{model_id}/metrics */ async getModelMetrics( tenantId: string, modelId: string ): Promise { return apiClient.get( `${this.baseUrl}/${tenantId}/training/models/${modelId}/metrics` ); } /** * List models with optional filters * GET /tenants/{tenant_id}/training/models */ async getModels( tenantId: string, queryParams?: ModelsQueryParams ): Promise> { const params = new URLSearchParams(); if (queryParams?.status) params.append('status', queryParams.status); if (queryParams?.model_type) params.append('model_type', queryParams.model_type); if (queryParams?.limit) params.append('limit', queryParams.limit.toString()); if (queryParams?.offset) params.append('offset', queryParams.offset.toString()); const queryString = params.toString() ? `?${params.toString()}` : ''; return apiClient.get>( `${this.baseUrl}/${tenantId}/training/models${queryString}` ); } /** * Get model performance metrics * Note: This endpoint might be deprecated - check backend for actual implementation */ async getModelPerformance( tenantId: string, modelId: string ): Promise { return apiClient.get( `${this.baseUrl}/${tenantId}/training/models/${modelId}/performance` ); } /** * Delete all tenant models (Admin only) * DELETE /models/tenant/{tenant_id} */ async deleteAllTenantModels(tenantId: string): Promise<{ message: string }> { return apiClient.delete<{ message: string }>(`/models/tenant/${tenantId}`); } // =================================================================== // WebSocket Support // =================================================================== /** * Get WebSocket URL for real-time training updates */ getTrainingWebSocketUrl(tenantId: string, jobId: string): string { const baseWsUrl = apiClient.getAxiosInstance().defaults.baseURL?.replace(/^http/, 'ws'); return `${baseWsUrl}/ws/tenants/${tenantId}/training/jobs/${jobId}/live`; } /** * Helper method to construct WebSocket connection */ createWebSocketConnection( tenantId: string, jobId: string, token?: string ): WebSocket { const wsUrl = this.getTrainingWebSocketUrl(tenantId, jobId); const urlWithToken = token ? `${wsUrl}?token=${token}` : wsUrl; return new WebSocket(urlWithToken); } } // Create and export singleton instance export const trainingService = new TrainingService(); export default trainingService;