Source: services/model.service.js

/**
 * Model service
 * 
 * Handles model registry operations and model inference
 */

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

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

export const modelService = {
  /**
   * List available models
   */
  listModels: async (filters = {}) => {
    try {
      const response = await modelApiClient.get('/models', { params: filters });
      return response.data;
    } catch (error) {
      logger.error('Failed to list models:', error);
      throw new Error(`Model API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Get details for a specific model
   */
  getModelDetails: async (modelId) => {
    try {
      const response = await modelApiClient.get(`/models/${modelId}`);
      return response.data;
    } catch (error) {
      if (error.response?.status === 404) {
        return null;
      }
      logger.error(`Failed to get model details for ${modelId}:`, error);
      throw new Error(`Model API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * List versions for a specific model
   */
  listModelVersions: async (modelId, filters = {}) => {
    try {
      const response = await modelApiClient.get(`/models/${modelId}/versions`, { params: filters });
      return response.data;
    } catch (error) {
      if (error.response?.status === 404) {
        return null;
      }
      logger.error(`Failed to list versions for model ${modelId}:`, error);
      throw new Error(`Model API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Get details for a specific model version
   */
  getModelVersionDetails: async (modelId, versionId) => {
    try {
      const response = await modelApiClient.get(`/models/${modelId}/versions/${versionId}`);
      return response.data;
    } catch (error) {
      if (error.response?.status === 404) {
        return null;
      }
      logger.error(`Failed to get version details for ${modelId}/${versionId}:`, error);
      throw new Error(`Model API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Make a prediction using a model
   */
  predict: async (modelId, inputs, options = {}) => {
    try {
      const response = await modelApiClient.post(`/models/${modelId}/predict`, {
        inputs,
        options
      });
      return response.data;
    } catch (error) {
      logger.error(`Prediction failed for model ${modelId}:`, error);
      throw new Error(`Model API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Analyze data using a model
   */
  analyze: async (modelId, data, options = {}) => {
    try {
      const response = await modelApiClient.post(`/models/${modelId}/analyze`, {
        data,
        options
      });
      return response.data;
    } catch (error) {
      logger.error(`Analysis failed for model ${modelId}:`, error);
      throw new Error(`Model API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Generate content using a model
   */
  generate: async (modelId, prompt, options = {}) => {
    try {
      const response = await modelApiClient.post(`/models/${modelId}/generate`, {
        prompt,
        options
      });
      return response.data;
    } catch (error) {
      logger.error(`Generation failed for model ${modelId}:`, error);
      throw new Error(`Model API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Create embeddings using a model
   */
  createEmbeddings: async (modelId, texts, options = {}) => {
    try {
      const response = await modelApiClient.post(`/models/${modelId}/embed`, {
        texts,
        options
      });
      return response.data;
    } catch (error) {
      logger.error(`Embedding failed for model ${modelId}:`, error);
      throw new Error(`Model API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Process batch of inputs
   */
  processBatch: async (modelId, operation, batch, options = {}) => {
    try {
      const response = await modelApiClient.post(`/models/${modelId}/batch`, {
        operation,
        batch,
        options
      });
      return response.data;
    } catch (error) {
      logger.error(`Batch processing failed for model ${modelId}:`, error);
      throw new Error(`Model API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Start a fine-tuning job
   */
  startFineTune: async (modelId, trainingData, hyperparameters = {}, options = {}) => {
    try {
      const response = await modelApiClient.post(`/models/${modelId}/fine-tune`, {
        trainingData,
        hyperparameters,
        options
      });
      return response.data;
    } catch (error) {
      logger.error(`Fine-tuning failed for model ${modelId}:`, error);
      throw new Error(`Model API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Get fine-tune job status
   */
  getFineTuneStatus: async (modelId, jobId) => {
    try {
      const response = await modelApiClient.get(`/models/${modelId}/fine-tune/${jobId}`);
      return response.data;
    } catch (error) {
      if (error.response?.status === 404) {
        return null;
      }
      logger.error(`Failed to get fine-tune status for ${modelId}/${jobId}:`, error);
      throw new Error(`Model API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Register a new model
   */
  registerModel: async (name, description, type, initialVersion, metadata = {}) => {
    try {
      const response = await modelApiClient.post('/models', {
        name,
        description,
        type,
        initialVersion,
        metadata
      });
      return response.data;
    } catch (error) {
      logger.error('Failed to register model:', error);
      throw new Error(`Model API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Update an existing model
   */
  updateModel: async (modelId, updates) => {
    try {
      const response = await modelApiClient.put(`/models/${modelId}`, updates);
      return response.data;
    } catch (error) {
      if (error.response?.status === 404) {
        return null;
      }
      logger.error(`Failed to update model ${modelId}:`, error);
      throw new Error(`Model API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Delete a model
   */
  deleteModel: async (modelId) => {
    try {
      await modelApiClient.delete(`/models/${modelId}`);
      return true;
    } catch (error) {
      if (error.response?.status === 404) {
        return false;
      }
      logger.error(`Failed to delete model ${modelId}:`, error);
      throw new Error(`Model API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Create a new model version
   */
  createModelVersion: async (modelId, version, artifacts, metadata = {}) => {
    try {
      const response = await modelApiClient.post(`/models/${modelId}/versions`, {
        version,
        artifacts,
        metadata
      });
      return response.data;
    } catch (error) {
      logger.error(`Failed to create version for model ${modelId}:`, error);
      throw new Error(`Model API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Update a model version
   */
  updateModelVersion: async (modelId, versionId, updates) => {
    try {
      const response = await modelApiClient.put(`/models/${modelId}/versions/${versionId}`, updates);
      return response.data;
    } catch (error) {
      if (error.response?.status === 404) {
        return null;
      }
      logger.error(`Failed to update version ${versionId} for model ${modelId}:`, error);
      throw new Error(`Model API error: ${error.response?.data?.message || error.message}`);
    }
  },
  
  /**
   * Delete a model version
   */
  deleteModelVersion: async (modelId, versionId) => {
    try {
      await modelApiClient.delete(`/models/${modelId}/versions/${versionId}`);
      return true;
    } catch (error) {
      if (error.response?.status === 404) {
        return false;
      }
      logger.error(`Failed to delete version ${versionId} for model ${modelId}:`, error);
      throw new Error(`Model API error: ${error.response?.data?.message || error.message}`);
    }
  }
};

export default modelService;