Source: services/learning.service.js

/**
 * Learning service
 * 
 * Handles learning system operations including datasets, samples, and training
 */

import axios from 'axios';
import { config } from '../config/index.js';
import { logger } from '../utils/logger.js';

// Initialize HTTP client for learning API
const learningApiClient = axios.create({
  baseURL: `${config.MODEL_API.URL}/learning`,
  timeout: config.MODEL_API.TIMEOUT,
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': config.MODEL_API.KEY,
  },
});

export const learningService = {
  /**
   * List datasets
   */
  listDatasets: async (filters = {}) => {
    try {
      const response = await learningApiClient.get('/datasets', { params: filters });
      return response.data;
    } catch (error) {
      logger.error('Failed to list datasets:', error);
      throw new Error(`Learning API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Get dataset details
   */
  getDatasetDetails: async (datasetId) => {
    try {
      const response = await learningApiClient.get(`/datasets/${datasetId}`);
      return response.data;
    } catch (error) {
      if (error.response?.status === 404) {
        return null;
      }
      logger.error(`Failed to get dataset details for ${datasetId}:`, error);
      throw new Error(`Learning API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Create a new dataset
   */
  createDataset: async (name, description, type, initialSamples, metadata = {}) => {
    try {
      const response = await learningApiClient.post('/datasets', {
        name,
        description,
        type,
        initialSamples,
        metadata
      });
      return response.data;
    } catch (error) {
      logger.error('Failed to create dataset:', error);
      throw new Error(`Learning API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Update a dataset
   */
  updateDataset: async (datasetId, updates) => {
    try {
      const response = await learningApiClient.put(`/datasets/${datasetId}`, updates);
      return response.data;
    } catch (error) {
      if (error.response?.status === 404) {
        return null;
      }
      logger.error(`Failed to update dataset ${datasetId}:`, error);
      throw new Error(`Learning API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Delete a dataset
   */
  deleteDataset: async (datasetId) => {
    try {
      await learningApiClient.delete(`/datasets/${datasetId}`);
      return true;
    } catch (error) {
      if (error.response?.status === 404) {
        return false;
      }
      logger.error(`Failed to delete dataset ${datasetId}:`, error);
      throw new Error(`Learning API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * List samples in a dataset
   */
  listSamples: async (datasetId, filters = {}) => {
    try {
      const response = await learningApiClient.get(`/datasets/${datasetId}/samples`, { params: filters });
      return response.data;
    } catch (error) {
      if (error.response?.status === 404) {
        return null;
      }
      logger.error(`Failed to list samples for dataset ${datasetId}:`, error);
      throw new Error(`Learning API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Get a specific sample
   */
  getSample: async (datasetId, sampleId) => {
    try {
      const response = await learningApiClient.get(`/datasets/${datasetId}/samples/${sampleId}`);
      return response.data;
    } catch (error) {
      if (error.response?.status === 404) {
        return null;
      }
      logger.error(`Failed to get sample ${sampleId} from dataset ${datasetId}:`, error);
      throw new Error(`Learning API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Add samples to a dataset
   */
  addSamples: async (datasetId, samples) => {
    try {
      const response = await learningApiClient.post(`/datasets/${datasetId}/samples`, { samples });
      return response.data;
    } catch (error) {
      if (error.response?.status === 404) {
        return null;
      }
      logger.error(`Failed to add samples to dataset ${datasetId}:`, error);
      throw new Error(`Learning API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Update a sample
   */
  updateSample: async (datasetId, sampleId, updates) => {
    try {
      const response = await learningApiClient.put(`/datasets/${datasetId}/samples/${sampleId}`, updates);
      return response.data;
    } catch (error) {
      if (error.response?.status === 404) {
        return null;
      }
      logger.error(`Failed to update sample ${sampleId} in dataset ${datasetId}:`, error);
      throw new Error(`Learning API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Delete a sample
   */
  deleteSample: async (datasetId, sampleId) => {
    try {
      await learningApiClient.delete(`/datasets/${datasetId}/samples/${sampleId}`);
      return true;
    } catch (error) {
      if (error.response?.status === 404) {
        return false;
      }
      logger.error(`Failed to delete sample ${sampleId} from dataset ${datasetId}:`, error);
      throw new Error(`Learning API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Submit feedback for model outputs
   */
  submitFeedback: async (modelId, input, output, rating, comments = '', metadata = {}) => {
    try {
      const response = await learningApiClient.post('/feedback', {
        modelId,
        input,
        output,
        rating,
        comments,
        metadata,
        timestamp: new Date().toISOString()
      });
      return response.data;
    } catch (error) {
      logger.error('Failed to submit feedback:', error);
      throw new Error(`Learning API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * List feedback entries
   */
  listFeedback: async (filters = {}) => {
    try {
      const response = await learningApiClient.get('/feedback', { params: filters });
      return response.data;
    } catch (error) {
      logger.error('Failed to list feedback:', error);
      throw new Error(`Learning API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Get feedback details
   */
  getFeedbackDetails: async (feedbackId) => {
    try {
      const response = await learningApiClient.get(`/feedback/${feedbackId}`);
      return response.data;
    } catch (error) {
      if (error.response?.status === 404) {
        return null;
      }
      logger.error(`Failed to get feedback details for ${feedbackId}:`, error);
      throw new Error(`Learning API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Start a training job
   */
  startTrainingJob: async (modelId, datasets, hyperparameters = {}, options = {}) => {
    try {
      const response = await learningApiClient.post('/training', {
        modelId,
        datasets,
        hyperparameters,
        options,
        timestamp: new Date().toISOString()
      });
      return response.data;
    } catch (error) {
      logger.error('Failed to start training job:', error);
      throw new Error(`Learning API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * List training jobs
   */
  listTrainingJobs: async (filters = {}) => {
    try {
      const response = await learningApiClient.get('/training', { params: filters });
      return response.data;
    } catch (error) {
      logger.error('Failed to list training jobs:', error);
      throw new Error(`Learning API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Get training job status
   */
  getTrainingJobStatus: async (jobId) => {
    try {
      const response = await learningApiClient.get(`/training/${jobId}`);
      return response.data;
    } catch (error) {
      if (error.response?.status === 404) {
        return null;
      }
      logger.error(`Failed to get training job status for ${jobId}:`, error);
      throw new Error(`Learning API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Cancel a training job
   */
  cancelTrainingJob: async (jobId) => {
    try {
      const response = await learningApiClient.delete(`/training/${jobId}`);
      return response.data;
    } catch (error) {
      if (error.response?.status === 404) {
        return null;
      }
      logger.error(`Failed to cancel training job ${jobId}:`, error);
      throw new Error(`Learning API error: ${error.response?.data?.message || error.message}`);
    }
  }
};

export default learningService;