Spaces:
Runtime error
Runtime error
| /** | |
| * A/B Test Predictor - JavaScript/Node.js API Examples | |
| */ | |
| // ============================================================================ | |
| // Option 1: Using Fetch API (Browser/Node.js) | |
| // ============================================================================ | |
| async function predictABTest(controlImagePath, variantImagePath, categories) { | |
| const apiUrl = 'http://localhost:7860/api/predict'; // Change to your deployment URL | |
| // Read and encode images to base64 | |
| const fs = require('fs').promises; | |
| const controlImage = await fs.readFile(controlImagePath); | |
| const variantImage = await fs.readFile(variantImagePath); | |
| const controlB64 = `data:image/jpeg;base64,${controlImage.toString('base64')}`; | |
| const variantB64 = `data:image/jpeg;base64,${variantImage.toString('base64')}`; | |
| // Prepare request payload | |
| const payload = { | |
| data: [ | |
| controlB64, | |
| variantB64, | |
| categories.businessModel, | |
| categories.customerType, | |
| categories.conversionType, | |
| categories.industry, | |
| categories.pageType | |
| ] | |
| }; | |
| // Send POST request | |
| const response = await fetch(apiUrl, { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json' | |
| }, | |
| body: JSON.stringify(payload) | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`API request failed: ${response.status} ${response.statusText}`); | |
| } | |
| const result = await response.json(); | |
| return result.data[0]; // Gradio wraps response in 'data' array | |
| } | |
| // Example usage | |
| (async () => { | |
| try { | |
| const result = await predictABTest( | |
| 'control.jpg', | |
| 'variant.jpg', | |
| { | |
| businessModel: 'SaaS', | |
| customerType: 'B2B', | |
| conversionType: 'High-Intent Lead Gen', | |
| industry: 'B2B Software & Tech', | |
| pageType: 'Awareness & Discovery' | |
| } | |
| ); | |
| console.log('Prediction Results:'); | |
| console.log(JSON.stringify(result, null, 2)); | |
| console.log('\nWin Probability:', result.predictionResults.probability); | |
| console.log('Model Confidence:', result.predictionResults.modelConfidence + '%'); | |
| } catch (error) { | |
| console.error('Error:', error.message); | |
| } | |
| })(); | |
| // ============================================================================ | |
| // Option 2: Using Axios (More Robust) | |
| // ============================================================================ | |
| const axios = require('axios'); | |
| const fs = require('fs').promises; | |
| class ABTestPredictorClient { | |
| constructor(apiUrl = 'http://localhost:7860') { | |
| this.apiUrl = apiUrl; | |
| this.endpoint = `${apiUrl}/api/predict`; | |
| } | |
| async encodeImage(imagePath) { | |
| const imageBuffer = await fs.readFile(imagePath); | |
| return `data:image/jpeg;base64,${imageBuffer.toString('base64')}`; | |
| } | |
| async predict(controlImagePath, variantImagePath, categories) { | |
| try { | |
| // Encode images | |
| const controlB64 = await this.encodeImage(controlImagePath); | |
| const variantB64 = await this.encodeImage(variantImagePath); | |
| // Validate categories | |
| this.validateCategories(categories); | |
| // Prepare payload | |
| const payload = { | |
| data: [ | |
| controlB64, | |
| variantB64, | |
| categories.businessModel, | |
| categories.customerType, | |
| categories.conversionType, | |
| categories.industry, | |
| categories.pageType | |
| ] | |
| }; | |
| // Make API call | |
| const response = await axios.post(this.endpoint, payload, { | |
| headers: { | |
| 'Content-Type': 'application/json' | |
| }, | |
| timeout: 30000 // 30 second timeout | |
| }); | |
| return { | |
| success: true, | |
| data: response.data.data[0] | |
| }; | |
| } catch (error) { | |
| return { | |
| success: false, | |
| error: error.message, | |
| details: error.response?.data | |
| }; | |
| } | |
| } | |
| validateCategories(categories) { | |
| const validCategories = { | |
| businessModel: ['E-Commerce', 'Lead Generation', 'Other*', 'SaaS'], | |
| customerType: ['B2B', 'B2C', 'Both', 'Other*'], | |
| conversionType: [ | |
| 'Direct Purchase', | |
| 'High-Intent Lead Gen', | |
| 'Info/Content Lead Gen', | |
| 'Location Search', | |
| 'Non-Profit/Community', | |
| 'Other Conversion' | |
| ], | |
| industry: [ | |
| 'Automotive & Transportation', | |
| 'B2B Services', | |
| 'B2B Software & Tech', | |
| 'Consumer Services', | |
| 'Consumer Software & Apps', | |
| 'Education', | |
| 'Finance, Insurance & Real Estate', | |
| 'Food, Hospitality & Travel', | |
| 'Health & Wellness', | |
| 'Industrial & Manufacturing', | |
| 'Media & Entertainment', | |
| 'Non-Profit & Government', | |
| 'Other', | |
| 'Retail & E-commerce' | |
| ], | |
| pageType: [ | |
| 'Awareness & Discovery', | |
| 'Consideration & Evaluation', | |
| 'Conversion', | |
| 'Internal & Navigation', | |
| 'Post-Conversion & Other' | |
| ] | |
| }; | |
| // Validate each category | |
| for (const [key, value] of Object.entries(categories)) { | |
| if (!validCategories[key]?.includes(value)) { | |
| throw new Error(`Invalid ${key}: ${value}`); | |
| } | |
| } | |
| return true; | |
| } | |
| async batchPredict(testCases) { | |
| const results = []; | |
| for (let i = 0; i < testCases.length; i++) { | |
| console.log(`Processing test ${i + 1}/${testCases.length}...`); | |
| const testCase = testCases[i]; | |
| const result = await this.predict( | |
| testCase.controlImage, | |
| testCase.variantImage, | |
| testCase.categories | |
| ); | |
| results.push({ | |
| testId: i + 1, | |
| input: testCase, | |
| result: result | |
| }); | |
| // Rate limiting | |
| await new Promise(resolve => setTimeout(resolve, 1000)); | |
| } | |
| return results; | |
| } | |
| } | |
| // Example usage | |
| (async () => { | |
| const client = new ABTestPredictorClient('http://localhost:7860'); | |
| // Single prediction | |
| const result = await client.predict( | |
| 'control.jpg', | |
| 'variant.jpg', | |
| { | |
| businessModel: 'SaaS', | |
| customerType: 'B2B', | |
| conversionType: 'High-Intent Lead Gen', | |
| industry: 'B2B Software & Tech', | |
| pageType: 'Awareness & Discovery' | |
| } | |
| ); | |
| if (result.success) { | |
| console.log('Prediction successful!'); | |
| console.log('Win Probability:', result.data.predictionResults.probability); | |
| console.log('Confidence:', result.data.predictionResults.modelConfidence + '%'); | |
| } else { | |
| console.error('Prediction failed:', result.error); | |
| } | |
| // Batch predictions | |
| const testCases = [ | |
| { | |
| controlImage: 'test1_control.jpg', | |
| variantImage: 'test1_variant.jpg', | |
| categories: { | |
| businessModel: 'SaaS', | |
| customerType: 'B2B', | |
| conversionType: 'High-Intent Lead Gen', | |
| industry: 'B2B Software & Tech', | |
| pageType: 'Awareness & Discovery' | |
| } | |
| }, | |
| // Add more test cases... | |
| ]; | |
| const batchResults = await client.batchPredict(testCases); | |
| console.log('Batch results:', JSON.stringify(batchResults, null, 2)); | |
| })(); | |
| // ============================================================================ | |
| // Option 3: Browser Example (Using File Input) | |
| // ============================================================================ | |
| // HTML: | |
| // <input type="file" id="controlImage" accept="image/*"> | |
| // <input type="file" id="variantImage" accept="image/*"> | |
| // <button onclick="predictFromBrowser()">Predict</button> | |
| // <div id="results"></div> | |
| async function predictFromBrowser() { | |
| const controlFile = document.getElementById('controlImage').files[0]; | |
| const variantFile = document.getElementById('variantImage').files[0]; | |
| if (!controlFile || !variantFile) { | |
| alert('Please select both images'); | |
| return; | |
| } | |
| // Convert files to base64 | |
| const controlB64 = await fileToBase64(controlFile); | |
| const variantB64 = await fileToBase64(variantFile); | |
| // Prepare payload | |
| const payload = { | |
| data: [ | |
| controlB64, | |
| variantB64, | |
| 'SaaS', | |
| 'B2B', | |
| 'High-Intent Lead Gen', | |
| 'B2B Software & Tech', | |
| 'Awareness & Discovery' | |
| ] | |
| }; | |
| try { | |
| const response = await fetch('http://localhost:7860/api/predict', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json' | |
| }, | |
| body: JSON.stringify(payload) | |
| }); | |
| const result = await response.json(); | |
| displayResults(result.data[0]); | |
| } catch (error) { | |
| alert('Error: ' + error.message); | |
| } | |
| } | |
| function fileToBase64(file) { | |
| return new Promise((resolve, reject) => { | |
| const reader = new FileReader(); | |
| reader.onload = () => resolve(reader.result); | |
| reader.onerror = reject; | |
| reader.readAsDataURL(file); | |
| }); | |
| } | |
| function displayResults(data) { | |
| const resultsDiv = document.getElementById('results'); | |
| resultsDiv.innerHTML = ` | |
| <h3>Prediction Results</h3> | |
| <p>Win Probability: ${data.predictionResults.probability}</p> | |
| <p>Model Confidence: ${data.predictionResults.modelConfidence}%</p> | |
| <p>Training Samples: ${data.predictionResults.trainingDataSamples}</p> | |
| <p>Total Predictions: ${data.predictionResults.totalPredictions}</p> | |
| `; | |
| } | |
| // ============================================================================ | |
| // Option 4: Express.js Server Example | |
| // ============================================================================ | |
| const express = require('express'); | |
| const multer = require('multer'); | |
| const upload = multer({ dest: 'uploads/' }); | |
| const app = express(); | |
| const client = new ABTestPredictorClient('http://localhost:7860'); | |
| app.post('/predict', upload.fields([ | |
| { name: 'control', maxCount: 1 }, | |
| { name: 'variant', maxCount: 1 } | |
| ]), async (req, res) => { | |
| try { | |
| const controlPath = req.files['control'][0].path; | |
| const variantPath = req.files['variant'][0].path; | |
| const categories = { | |
| businessModel: req.body.businessModel, | |
| customerType: req.body.customerType, | |
| conversionType: req.body.conversionType, | |
| industry: req.body.industry, | |
| pageType: req.body.pageType | |
| }; | |
| const result = await client.predict(controlPath, variantPath, categories); | |
| // Clean up uploaded files | |
| const fs = require('fs'); | |
| fs.unlinkSync(controlPath); | |
| fs.unlinkSync(variantPath); | |
| res.json(result); | |
| } catch (error) { | |
| res.status(500).json({ | |
| success: false, | |
| error: error.message | |
| }); | |
| } | |
| }); | |
| app.listen(3000, () => { | |
| console.log('Proxy server running on port 3000'); | |
| }); | |