UNPKG

@bramato/openrouter-mock-generator

Version:

AI-powered mock data generator using OpenRouter API with JSON mode support

294 lines 13.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MockGeneratorService = void 0; const promises_1 = require("fs/promises"); const fs_1 = require("fs"); const pattern_analyzer_1 = require("../utils/pattern-analyzer"); const post_processing_orchestrator_1 = require("./post-processing-orchestrator"); const progress_manager_1 = require("../utils/progress-manager"); const json_analyzer_1 = require("./json-analyzer"); const MockDataAgent_1 = require("../agents/MockDataAgent"); class MockGeneratorService { constructor(config, enableImageProcessing) { const openRouterConfig = { apiKey: process.env.OPENROUTER_API_KEY || '', baseURL: 'https://openrouter.ai/api/v1', model: process.env.OPENROUTER_DEFAULT_MODEL || 'anthropic/claude-3.5-sonnet', }; const agentConfig = { name: 'mock-data-generator', type: 'mock-data', description: 'Professional mock data generator for testing and development', openRouter: config || openRouterConfig, temperature: 0.7, maxTokens: 4000, features: { jsonMode: true, imageGeneration: true, schemaValidation: true, batchProcessing: true, }, }; this.mockAgent = new MockDataAgent_1.MockDataAgent(agentConfig); this.progressManager = new progress_manager_1.ProgressManager(); this.jsonAnalyzer = new json_analyzer_1.JsonAnalyzer(config); // Configura il progress manager nell'agent this.mockAgent.setProgressManager(this.progressManager); // Auto-detect se abilitare il post-processing se non specificato const shouldEnableImageProcessing = enableImageProcessing ?? this.shouldEnableImageProcessing(); if (shouldEnableImageProcessing) { try { // Tenta di inizializzare il post-processor con la chiave HuggingFace const hfKey = this.getHuggingFaceApiKey(); this.postProcessor = new post_processing_orchestrator_1.PostProcessingOrchestrator(hfKey || undefined); console.log('🎨 AI image processing enabled'); } catch (error) { console.warn('⚠️ Image processing disabled: Failed to initialize post-processor'); } } else { console.log('📋 AI image processing disabled - using placeholder images'); } } shouldEnableImageProcessing() { try { // Controlla se c'è configurazione per image processing nel .env const hfKey = this.getHuggingFaceApiKey(); const hasStorageProvider = process.env.STORAGE_PROVIDER || this.getEnvValue('STORAGE_PROVIDER'); // Abilita se ha almeno una configurazione di image processing return !!(hfKey || hasStorageProvider); } catch { return false; } } getEnvValue(key) { try { const fs = require('fs'); const path = require('path'); const envPath = path.join(process.cwd(), '.env'); if (fs.existsSync(envPath)) { const envContent = fs.readFileSync(envPath, 'utf8'); const match = envContent.match(new RegExp(`${key}=(.+)`)); return match ? match[1].trim() : null; } } catch (error) { // Ignora errori } return null; } getHuggingFaceApiKey() { try { // Cerca nelle variabili d'ambiente if (process.env.HUGGINGFACE_API_KEY) { return process.env.HUGGINGFACE_API_KEY; } // Cerca nel file .env (sync per compatibilità con costruttore) const fs = require('fs'); const path = require('path'); const envPath = path.join(process.cwd(), '.env'); if (fs.existsSync(envPath)) { const envContent = fs.readFileSync(envPath, 'utf8'); const match = envContent.match(/HUGGINGFACE_API_KEY=(.+)/); return match ? match[1].trim() : null; } } catch (error) { // Ignora errori, il post-processing funzionerà comunque senza chiave API } return null; } async fileExists(filePath) { try { await (0, promises_1.access)(filePath, fs_1.constants.F_OK); return true; } catch { return false; } } calculateOptimalBatchSize(sampleItem) { return this.mockAgent.calculateOptimalBatchSize(sampleItem); } async generateSingleBatch(sampleItem, count, preferences, batchNumber, totalBatches) { return await this.mockAgent.generateMockItems(sampleItem, count, preferences, batchNumber, totalBatches); } async appendToJsonFile(filePath, newItems, isFirstBatch) { if (isFirstBatch) { const jsonContent = JSON.stringify(newItems, null, 2); await (0, promises_1.writeFile)(filePath, jsonContent, 'utf8'); } else { const existingContent = await (0, promises_1.readFile)(filePath, 'utf8'); const existingData = JSON.parse(existingContent); if (!Array.isArray(existingData)) { throw new Error('Output file does not contain a JSON array'); } const mergedData = [...existingData, ...newItems]; const jsonContent = JSON.stringify(mergedData, null, 2); await (0, promises_1.writeFile)(filePath, jsonContent, 'utf8'); } } async generateMockData(request) { try { // Clear output file at the beginning await (0, promises_1.writeFile)(request.outputFile, '[]', 'utf8'); const inputContent = await (0, promises_1.readFile)(request.inputFile, 'utf8'); const inputData = JSON.parse(inputContent); const analyses = pattern_analyzer_1.PatternAnalyzer.analyzeJsonStructure(inputData); if (analyses.length === 0) { return { success: false, generatedCount: 0, outputFile: request.outputFile, error: 'No arrays found in input file', }; } const targetAnalysis = request.arrayPath ? analyses.find(a => a.arrayPath === request.arrayPath) : pattern_analyzer_1.PatternAnalyzer.findLargestArray(analyses); if (!targetAnalysis) { return { success: false, generatedCount: 0, outputFile: request.outputFile, error: request.arrayPath ? `No array found at path: ${request.arrayPath}` : 'No suitable array found for mock generation', }; } const sampleItem = targetAnalysis.sampleItem; const optimalBatchSize = this.calculateOptimalBatchSize(sampleItem); const totalBatches = Math.ceil(request.count / optimalBatchSize); let generatedCount = 0; // Mostra informazioni sul modello AI in uso const currentModel = this.mockAgent.getCurrentModel(); console.log(`🤖 Modello AI: ${currentModel}`); if (totalBatches > 1) { console.log(`📦 Processamento in ${totalBatches} batch (dimensione ottimale: ${optimalBatchSize})`); } // Setup progress bars per il nuovo flusso const enableImageProcessing = this.postProcessor && request.enableImageProcessing !== false; if (enableImageProcessing) { this.progressManager.initMultiBar(); } const mockBar = enableImageProcessing ? this.progressManager.addBar('mock', { title: '🎲 Dati Mock', total: request.count, }) : this.progressManager.createMockGenerationBar(request.count); // Aggiungi progress bar per immagini se abilitato let imageBar = null; if (enableImageProcessing) { imageBar = this.progressManager.addBar('images', { title: '🖼️ Immagini AI', total: request.count, // Approssimiamo con il numero di elementi }); } for (let batch = 0; batch < totalBatches; batch++) { const remainingItems = request.count - generatedCount; const currentBatchSize = Math.min(optimalBatchSize, remainingItems); // STEP 1: Genera batch di dati mock const newItems = await this.generateSingleBatch(sampleItem, currentBatchSize, request.preferences, batch + 1, totalBatches); // STEP 2: Post-processing per immagini se abilitato let processedItems = newItems; if (enableImageProcessing && this.postProcessor) { try { processedItems = await this.processBatchImages(newItems, batch + 1, totalBatches); } catch (error) { console.warn(`⚠️ Image processing failed for batch ${batch + 1}:`, error); // Continua con i dati originali } } // STEP 3: Append dei dati processati al file finale await this.appendToJsonFile(request.outputFile, processedItems, batch === 0); generatedCount += processedItems.length; // Aggiorna progress bar if (enableImageProcessing) { this.progressManager.updateBar('mock', generatedCount, { status: `Batch ${batch + 1}/${totalBatches} processato`, }); } else { mockBar.update(generatedCount, { status: `Batch ${batch + 1}/${totalBatches} completato`, }); } // Dynamic delay based on batch size const delay = Math.max(500, currentBatchSize * 200); await new Promise(resolve => setTimeout(resolve, delay)); } // Completa la progress bar if (enableImageProcessing) { this.progressManager.completeBar('mock', '✅ Completato'); this.progressManager.stopAll(); } else { mockBar.stop(); } return { success: true, generatedCount, outputFile: request.outputFile, }; } catch (error) { return { success: false, generatedCount: 0, outputFile: request.outputFile, error: error instanceof Error ? error.message : 'Unknown error', }; } } /** * Processa le immagini di un singolo batch */ async processBatchImages(items, batchNumber, totalBatches) { if (!this.postProcessor || items.length === 0) { return items; } console.log(`\n🎨 Processing images for batch ${batchNumber}/${totalBatches} (${items.length} items)...`); // STEP 1: Analizza ogni item per generare descrizioni AI personalizzate const descriptions = await this.jsonAnalyzer.analyzeBatchForImageDescriptions(items, (current, total, item) => { console.log(` 📝 Analyzing item ${current}/${total} for image descriptions...`); }); console.log(` ✅ Generated ${descriptions.size} sets of image descriptions`); // STEP 2: Processa il batch attraverso il PostProcessingOrchestrator // con le descrizioni personalizzate try { // Setup progress callback per immagini const imageProgressCallback = (current, total, status) => { this.progressManager.updateBar('images', current, { status: status || `Batch ${batchNumber}/${totalBatches}`, }); }; // Configura il post-processor con callback personalizzati const originalOptions = this.postProcessor['options']; this.postProcessor['options'] = { ...originalOptions, onImageProgress: imageProgressCallback, customDescriptions: descriptions, // Passa le descrizioni personalizzate }; const result = await this.postProcessor.processData(items); if (result.success) { console.log(` ✅ Batch ${batchNumber} processed: ${result.processedImageCount} images`); return result.processedData; } else { console.warn(` ⚠️ Batch ${batchNumber} processing failed:`, result.errors); return items; // Fallback ai dati originali } } catch (error) { console.warn(` ❌ Batch ${batchNumber} processing error:`, error); return items; // Fallback ai dati originali } } } exports.MockGeneratorService = MockGeneratorService; //# sourceMappingURL=mock-generator.js.map