| |
| |
| |
| |
|
|
| const axios = require('axios'); |
| const crypto = require('crypto'); |
|
|
| class AIService { |
| constructor() { |
| |
| this.hfApiKey = process.env.HF_API_KEY; |
| |
| |
| this.models = { |
| |
| fast: process.env.AI_MODEL_FAST || 'Qwen/Qwen2.5-7B-Instruct', |
| |
| precise: process.env.AI_MODEL_PRECISE || 'deepseek-ai/DeepSeek-R1', |
| |
| fallback: 'Qwen/Qwen2.5-7B-Instruct' |
| }; |
| |
| |
| this.apiUrl = 'https://router.huggingface.co/v1/chat/completions'; |
| |
| |
| this.cache = new Map(); |
| this.cacheTTL = 3600000; |
| |
| |
| this.modelStats = { |
| fast: { calls: 0, avgTime: 0 }, |
| precise: { calls: 0, avgTime: 0 } |
| }; |
| |
| console.log(`๐ค AI Service initialized with models: |
| - Fast Model: ${this.models.fast} |
| - Precise Model: ${this.models.precise}`); |
| } |
| |
| |
| |
| |
| selectModel(taskType) { |
| |
| |
| return this.models.fast; |
| } |
| |
| |
| |
| |
| getCacheKey(prompt, type, model) { |
| return crypto.createHash('md5').update(`${type}:${prompt}:${model}`).digest('hex'); |
| } |
| |
| |
| |
| |
| async callHuggingFace(prompt, temperature = 0.7, model = null) { |
| if (!this.hfApiKey) { |
| console.warn('โ ๏ธ HF_API_KEY not configured, using fallback responses'); |
| return null; |
| } |
| |
| const selectedModel = model || this.models.fast; |
| const startTime = Date.now(); |
| |
| try { |
| const response = await axios.post( |
| this.apiUrl, |
| { |
| model: selectedModel, |
| messages: [ |
| { |
| role: 'system', |
| content: `You are an expert e-commerce and web design assistant for MGZon platform. |
| |
| Platform capabilities: |
| - Products: digital, projects, services |
| - Pages: custom pages with HTML/CSS/JS |
| - Shortcodes: products, product, contact-form, store-info, categories, testimonials, social-links |
| - Themes: custom colors, fonts, layouts, full templates |
| - Store sections: hero, featured, products, categories, testimonials, faq, contact, html, products_grid |
| |
| Respond with valid JSON when requested. Be concise, professional, and ensure output matches MGZon format.` |
| }, |
| { |
| role: 'user', |
| content: prompt |
| } |
| ], |
| temperature: temperature, |
| max_tokens: 4096, |
| top_p: 0.95 |
| }, |
| { |
| headers: { |
| 'Authorization': `Bearer ${this.hfApiKey}`, |
| 'Content-Type': 'application/json' |
| }, |
| timeout: 30000 |
| } |
| ); |
| |
| const content = response.data?.choices?.[0]?.message?.content; |
| if (!content) { |
| throw new Error('Empty response from Hugging Face'); |
| } |
| |
| |
| const modelType = selectedModel === this.models.precise ? 'precise' : 'fast'; |
| const timeTaken = Date.now() - startTime; |
| this.modelStats[modelType].calls++; |
| this.modelStats[modelType].avgTime = |
| (this.modelStats[modelType].avgTime * (this.modelStats[modelType].calls - 1) + timeTaken) / |
| this.modelStats[modelType].calls; |
| |
| return content; |
| |
| } catch (error) { |
| console.error(`Hugging Face API error (${selectedModel}):`, error.response?.data || error.message); |
| return null; |
| } |
| } |
| |
| |
| |
| |
| async callAI(prompt, temperature = 0.7, taskType = 'general') { |
| |
| const primaryModel = this.models.fast; |
| const cacheKey = this.getCacheKey(prompt, taskType, primaryModel); |
| const cached = this.cache.get(cacheKey); |
| |
| if (cached && (Date.now() - cached.timestamp) < this.cacheTTL) { |
| return cached.result; |
| } |
| |
| console.log(`๐ค Trying primary model: ${primaryModel}`); |
| let result = await this.callHuggingFace(prompt, temperature, primaryModel); |
| |
| |
| if (!result) { |
| const fallbackModel = this.models.precise; |
| console.log(`โ ๏ธ Primary model failed, trying fallback: ${fallbackModel}`); |
| result = await this.callHuggingFace(prompt, temperature, fallbackModel); |
| } |
| |
| |
| if (!result) { |
| console.log(`โ ๏ธ Both models failed, using final fallback: ${this.models.fallback}`); |
| result = await this.callHuggingFace(prompt, temperature, this.models.fallback); |
| } |
| |
| if (result) { |
| this.cache.set(cacheKey, { result, timestamp: Date.now() }); |
| return result; |
| } |
| |
| return null; |
| } |
| |
| |
| |
| |
| async generatePageLayout(description, storeType = 'general') { |
| const prompt = ` |
| You are an expert e-commerce web designer for MGZon platform. Generate a complete store page layout. |
| |
| User description: "${description}" |
| Store type: ${storeType} |
| |
| Available section types: hero, products, featured, categories, testimonials, faq, contact, html, products_grid |
| |
| Generate a JSON object with this exact structure: |
| { |
| "name": "Suggested page name (max 50 chars)", |
| "sections": [ |
| { |
| "type": "section_type", |
| "title": "Section title (if applicable)", |
| "order": 1, |
| "enabled": true, |
| "limit": 6, |
| "layout": "grid", |
| "columns": 4, |
| "content": {} |
| } |
| ], |
| "theme": { |
| "primaryColor": "#hex", |
| "secondaryColor": "#hex", |
| "accentColor": "#hex", |
| "fontFamily": "Inter, sans-serif", |
| "layout": "full-width", |
| "backgroundType": "default", |
| "borderRadius": 16, |
| "animationType": "lift" |
| }, |
| "seo": { |
| "title": "Suggested SEO title (50-60 chars)", |
| "description": "Suggested meta description (150-160 chars)", |
| "keywords": ["keyword1", "keyword2", "keyword3"] |
| } |
| } |
| |
| Return ONLY valid JSON, no explanation. Ensure all colors are valid hex codes. |
| `; |
| |
| try { |
| const response = await this.callAI(prompt, 0.8, 'layout'); |
| |
| if (!response) { |
| return this.getFallbackLayout(description, storeType); |
| } |
| |
| const cleanResponse = response |
| .replace(/```json\n?/g, '') |
| .replace(/```\n?/g, '') |
| .replace(/`/g, '') |
| .trim(); |
| |
| const layout = JSON.parse(cleanResponse); |
| |
| |
| layout.sections = layout.sections.map((s, i) => ({ |
| ...s, |
| order: s.order || i + 1, |
| enabled: s.enabled !== false |
| })); |
| |
| return { |
| success: true, |
| layout: layout, |
| modelUsed: this.modelStats.fast.calls > this.modelStats.precise.calls ? this.models.fast : this.models.precise, |
| modelStats: this.modelStats |
| }; |
| } catch (error) { |
| console.error('AI layout generation error:', error); |
| return { |
| success: false, |
| error: error.message, |
| fallback: this.getFallbackLayout(description, storeType) |
| }; |
| } |
| } |
| |
| |
| |
| |
| getFallbackLayout(description, storeType) { |
| const layouts = { |
| fashion: { |
| name: 'Fashion Store', |
| sections: [ |
| { type: 'hero', order: 1, enabled: true, content: { title: 'New Collection', subtitle: 'Discover the latest trends', buttonText: 'Shop Now', buttonLink: '#products' } }, |
| { type: 'featured', order: 2, enabled: true, title: 'Featured Products', limit: 6, layout: 'grid' }, |
| { type: 'categories', order: 3, enabled: true, title: 'Shop by Category', layout: 'grid' }, |
| { type: 'products', order: 4, enabled: true, title: 'All Products', limit: 12, layout: 'grid', columns: 4 }, |
| { type: 'testimonials', order: 5, enabled: true, title: 'What Our Customers Say', limit: 4 }, |
| { type: 'contact', order: 6, enabled: true, title: 'Get in Touch' } |
| ], |
| theme: { |
| primaryColor: '#ec4899', |
| secondaryColor: '#8b5cf6', |
| accentColor: '#f43f5e', |
| fontFamily: 'Poppins, sans-serif', |
| layout: 'full-width', |
| backgroundType: 'gradient', |
| backgroundValue: 'linear-gradient(135deg, #fdf2f8 0%, #fce7f3 100%)', |
| borderRadius: 20, |
| animationType: 'lift' |
| }, |
| seo: { |
| title: 'Fashion Store | Latest Trends & Styles', |
| description: 'Discover the latest fashion trends. Shop our collection of clothing, accessories, and more. Free shipping on orders over $50.', |
| keywords: ['fashion', 'clothing', 'trends', 'style', 'shop', 'online store'] |
| } |
| }, |
| electronics: { |
| name: 'Tech Store', |
| sections: [ |
| { type: 'hero', order: 1, enabled: true, content: { title: 'Latest Technology', subtitle: 'Cutting-edge gadgets at best prices', buttonText: 'Shop Now', buttonLink: '#products' } }, |
| { type: 'categories', order: 2, enabled: true, title: 'Shop by Category', layout: 'grid' }, |
| { type: 'featured', order: 3, enabled: true, title: 'Best Sellers', limit: 6, sort: 'popular' }, |
| { type: 'products', order: 4, enabled: true, title: 'All Products', limit: 12, layout: 'grid', columns: 4 }, |
| { type: 'faq', order: 5, enabled: true, title: 'Frequently Asked Questions' }, |
| { type: 'contact', order: 6, enabled: true, title: 'Support' } |
| ], |
| theme: { |
| primaryColor: '#06b6d4', |
| secondaryColor: '#3b82f6', |
| accentColor: '#10b981', |
| fontFamily: 'Inter, sans-serif', |
| layout: 'full-width', |
| backgroundType: 'grid', |
| borderRadius: 12, |
| animationType: 'scale' |
| }, |
| seo: { |
| title: 'Tech Store | Electronics & Gadgets', |
| description: 'Shop the latest electronics, gadgets, and tech accessories. Best prices and fast shipping. 30-day return policy.', |
| keywords: ['electronics', 'gadgets', 'technology', 'tech', 'shop', 'online store'] |
| } |
| }, |
| food: { |
| name: 'Food & Restaurant', |
| sections: [ |
| { type: 'hero', order: 1, enabled: true, content: { title: 'Delicious Food', subtitle: 'Order online for delivery', buttonText: 'Order Now', buttonLink: '#products' } }, |
| { type: 'featured', order: 2, enabled: true, title: 'Popular Dishes', limit: 6, type: 'service' }, |
| { type: 'categories', order: 3, enabled: true, title: 'Menu Categories', layout: 'grid' }, |
| { type: 'products', order: 4, enabled: true, title: 'Full Menu', limit: 12, layout: 'grid', columns: 3, type: 'service' }, |
| { type: 'testimonials', order: 5, enabled: true, title: 'Customer Reviews', limit: 3 }, |
| { type: 'contact', order: 6, enabled: true, title: 'Contact Us' } |
| ], |
| theme: { |
| primaryColor: '#f59e0b', |
| secondaryColor: '#ef4444', |
| accentColor: '#22c55e', |
| fontFamily: 'Playfair Display, serif', |
| layout: 'full-width', |
| backgroundType: 'dots', |
| borderRadius: 24, |
| animationType: 'lift' |
| }, |
| seo: { |
| title: 'Food & Restaurant | Order Online', |
| description: 'Delicious food delivered to your door. Browse our menu and order online for fast delivery. Fresh ingredients, great taste.', |
| keywords: ['food', 'restaurant', 'delivery', 'order online', 'menu', 'catering'] |
| } |
| }, |
| art: { |
| name: 'Art Gallery', |
| sections: [ |
| { type: 'hero', order: 1, enabled: true, content: { title: 'Art Gallery', subtitle: 'Discover unique artworks', buttonText: 'Browse Art', buttonLink: '#products' } }, |
| { type: 'featured', order: 2, enabled: true, title: 'Featured Artworks', limit: 6 }, |
| { type: 'categories', order: 3, enabled: true, title: 'Categories', layout: 'grid' }, |
| { type: 'products', order: 4, enabled: true, title: 'All Artworks', limit: 12, layout: 'masonry', columns: 3 }, |
| { type: 'testimonials', order: 5, enabled: true, title: 'Collector Reviews', limit: 4 } |
| ], |
| theme: { |
| primaryColor: '#a855f7', |
| secondaryColor: '#ec4899', |
| accentColor: '#06b6d4', |
| fontFamily: 'Poppins, sans-serif', |
| layout: 'boxed', |
| backgroundType: 'cross', |
| borderRadius: 16, |
| animationType: 'glow' |
| }, |
| seo: { |
| title: 'Art Gallery | Original Artworks', |
| description: 'Discover unique original artworks from talented artists. Paintings, sculptures, digital art. Worldwide shipping.', |
| keywords: ['art', 'gallery', 'artwork', 'painting', 'sculpture', 'artist'] |
| } |
| }, |
| general: { |
| name: 'My Store', |
| sections: [ |
| { type: 'hero', order: 1, enabled: true, content: { title: 'Welcome to My Store', subtitle: 'Quality products at great prices', buttonText: 'Shop Now', buttonLink: '#products' } }, |
| { type: 'featured', order: 2, enabled: true, title: 'Featured Products', limit: 6 }, |
| { type: 'categories', order: 3, enabled: true, title: 'Categories', layout: 'grid' }, |
| { type: 'products', order: 4, enabled: true, title: 'All Products', limit: 12, layout: 'grid', columns: 4 }, |
| { type: 'testimonials', order: 5, enabled: true, title: 'What Our Customers Say', limit: 3 }, |
| { type: 'faq', order: 6, enabled: true, title: 'Frequently Asked Questions' }, |
| { type: 'contact', order: 7, enabled: true, title: 'Contact Us' } |
| ], |
| theme: { |
| primaryColor: '#3b82f6', |
| secondaryColor: '#8b5cf6', |
| accentColor: '#f59e0b', |
| fontFamily: 'Inter, sans-serif', |
| layout: 'full-width', |
| backgroundType: 'default', |
| borderRadius: 16, |
| animationType: 'lift' |
| }, |
| seo: { |
| title: 'My Store | Quality Products', |
| description: 'Shop our collection of quality products. Best prices, fast shipping, and excellent customer service.', |
| keywords: ['store', 'shop', 'products', 'online store', 'ecommerce'] |
| } |
| } |
| }; |
| |
| return { |
| success: false, |
| fallback: true, |
| layout: layouts[storeType] || layouts.general, |
| message: 'Using fallback layout (AI service unavailable)' |
| }; |
| } |
| |
| |
| |
| |
| async generateCompleteTemplate(description, style = 'modern') { |
| const prompt = ` |
| Generate a complete store template for MGZon platform. |
| |
| Description: "${description}" |
| Style preference: ${style} (modern/minimal/elegant/bold) |
| |
| Return a JSON object with: |
| { |
| "name": "Template name", |
| "description": "Template description", |
| "category": "fashion|electronics|food|art|general", |
| "sections": [array of sections], |
| "theme": { theme settings }, |
| "seo": { seo settings }, |
| "shortcodes": ["[products limit=\"6\"]", "[contact-form]"] |
| } |
| |
| Ensure the template is fully compatible with MGZon platform's store system. |
| Return ONLY valid JSON. |
| `; |
| |
| try { |
| const response = await this.callAI(prompt, 0.85, 'template'); |
| |
| if (!response) { |
| return this.getFallbackTemplate(description, style); |
| } |
| |
| const cleanResponse = response |
| .replace(/```json\n?/g, '') |
| .replace(/```\n?/g, '') |
| .replace(/`/g, '') |
| .trim(); |
| |
| const template = JSON.parse(cleanResponse); |
| |
| return { |
| success: true, |
| template: template, |
| modelUsed: this.models.precise, |
| modelStats: this.modelStats |
| }; |
| } catch (error) { |
| console.error('AI template generation error:', error); |
| return this.getFallbackTemplate(description, style); |
| } |
| } |
| |
| getFallbackTemplate(description, style) { |
| return { |
| success: false, |
| fallback: true, |
| template: { |
| name: `${style.charAt(0).toUpperCase() + style.slice(1)} Store`, |
| description: description || `A beautiful ${style} store template`, |
| category: 'general', |
| sections: [ |
| { type: 'hero', order: 1, content: { title: 'Welcome', buttonText: 'Shop Now' } }, |
| { type: 'products', order: 2, title: 'Products', limit: 12 } |
| ], |
| theme: { |
| primaryColor: '#3b82f6', |
| secondaryColor: '#8b5cf6', |
| fontFamily: 'Inter, sans-serif' |
| }, |
| shortcodes: ['[products limit="6"]', '[contact-form]'] |
| }, |
| message: 'Using fallback template (AI service unavailable)' |
| }; |
| } |
| |
| |
| |
| |
| |
| |
| async generateShortcode(description) { |
| const prompt = ` |
| Based on this description: "${description}" |
| |
| Generate an appropriate shortcode from these available shortcodes: |
| - [products] - products grid (parameters: limit, type, layout, sort, columns, category) |
| - [product] - single product (parameters: id, layout) |
| - [contact-form] - contact form (parameters: title, fields) |
| - [testimonials] - customer reviews (parameters: limit, autoplay) |
| - [categories] - categories (parameters: layout, showCount) |
| - [search-form] - search box (parameters: placeholder, showFilters) |
| - [store-info] - store info (parameters: field) |
| - [cart-count] - cart count |
| - [social-links] - social links (parameters: layout) |
| |
| Return ONLY the shortcode, no explanation. |
| Example: [products limit="6" type="digital" layout="grid" sort="popular"] |
| `; |
| |
| try { |
| const response = await this.callAI(prompt, 0.5, 'shortcode'); |
| |
| if (!response) { |
| return { |
| success: false, |
| fallback: '[products limit="6"]', |
| message: 'AI service unavailable, using fallback' |
| }; |
| } |
| |
| const cleanShortcode = response |
| .trim() |
| .replace(/`/g, '') |
| .replace(/^\[/, '[') |
| .replace(/\]$/, ']'); |
| |
| return { |
| success: true, |
| shortcode: cleanShortcode, |
| modelUsed: this.modelStats.fast.calls > this.modelStats.precise.calls ? this.models.fast : this.models.precise, |
| modelStats: this.modelStats |
| }; |
| } catch (error) { |
| return { |
| success: false, |
| error: error.message, |
| fallback: '[products limit="6"]' |
| }; |
| } |
| } |
| |
| suggestDesign(storeType) { |
| const suggestions = { |
| fashion: { |
| primaryColor: '#ec4899', |
| secondaryColor: '#8b5cf6', |
| accentColor: '#f43f5e', |
| fontFamily: 'Poppins, sans-serif', |
| headingFont: 'Poppins, sans-serif', |
| backgroundType: 'gradient', |
| backgroundValue: 'linear-gradient(135deg, #fdf2f8 0%, #fce7f3 100%)', |
| borderRadius: 20, |
| animationType: 'lift' |
| }, |
| electronics: { |
| primaryColor: '#06b6d4', |
| secondaryColor: '#3b82f6', |
| accentColor: '#10b981', |
| fontFamily: 'Inter, sans-serif', |
| headingFont: 'Inter, sans-serif', |
| backgroundType: 'grid', |
| borderRadius: 12, |
| animationType: 'scale' |
| }, |
| food: { |
| primaryColor: '#f59e0b', |
| secondaryColor: '#ef4444', |
| accentColor: '#22c55e', |
| fontFamily: 'Playfair Display, serif', |
| headingFont: 'Playfair Display, serif', |
| backgroundType: 'dots', |
| borderRadius: 24, |
| animationType: 'lift' |
| }, |
| art: { |
| primaryColor: '#a855f7', |
| secondaryColor: '#ec4899', |
| accentColor: '#06b6d4', |
| fontFamily: 'Poppins, sans-serif', |
| headingFont: 'Poppins, sans-serif', |
| backgroundType: 'cross', |
| borderRadius: 16, |
| animationType: 'glow' |
| }, |
| general: { |
| primaryColor: '#3b82f6', |
| secondaryColor: '#8b5cf6', |
| accentColor: '#f59e0b', |
| fontFamily: 'Inter, sans-serif', |
| headingFont: 'Inter, sans-serif', |
| backgroundType: 'default', |
| borderRadius: 16, |
| animationType: 'lift' |
| } |
| }; |
| |
| return suggestions[storeType] || suggestions.general; |
| } |
| |
| async enhanceProductDescription(title, currentDescription, tags = []) { |
| const prompt = ` |
| Improve this product description: |
| |
| Title: ${title} |
| Current: ${currentDescription || 'No description'} |
| Tags: ${tags.join(', ')} |
| |
| Write an engaging, SEO-friendly description (150-200 words) with benefits, keywords, and call to action. |
| Return ONLY the description, no explanation. |
| `; |
| |
| try { |
| const response = await this.callAI(prompt, 0.7, 'description_enhance'); |
| |
| if (!response) { |
| return { |
| success: false, |
| description: currentDescription || `${title} - High quality product. Shop now!` |
| }; |
| } |
| |
| return { |
| success: true, |
| description: response.trim(), |
| modelUsed: this.modelStats.fast.calls > this.modelStats.precise.calls ? this.models.fast : this.models.precise |
| }; |
| } catch (error) { |
| return { |
| success: false, |
| description: currentDescription, |
| error: error.message |
| }; |
| } |
| } |
| |
| async suggestKeywords(title, category, storeType) { |
| const prompt = ` |
| Suggest 10 SEO keywords for: |
| Title: ${title} |
| Category: ${category} |
| Store Type: ${storeType} |
| |
| Return ONLY comma-separated keywords, no explanation. |
| `; |
| |
| try { |
| const response = await this.callAI(prompt, 0.3, 'keyword'); |
| |
| if (!response) { |
| return { |
| success: false, |
| keywords: [title, category, storeType, 'online store', 'buy online'] |
| }; |
| } |
| |
| const keywords = response |
| .trim() |
| .split(',') |
| .map(k => k.trim()) |
| .filter(k => k.length > 0); |
| |
| return { |
| success: true, |
| keywords: keywords.slice(0, 10), |
| modelUsed: this.modelStats.fast.calls > this.modelStats.precise.calls ? this.models.fast : this.models.precise |
| }; |
| } catch (error) { |
| return { |
| success: false, |
| keywords: [title, category, storeType, 'online store', 'buy online'] |
| }; |
| } |
| } |
| |
| async generateStoreDescription(storeName, industry, products) { |
| const prompt = ` |
| Write a store description for: |
| Store Name: ${storeName} |
| Industry: ${industry} |
| Products: ${products.join(', ')} |
| |
| Write 100-150 words, welcoming, unique, with call to action. |
| Return ONLY the description. |
| `; |
| |
| try { |
| const response = await this.callAI(prompt, 0.6, 'general'); |
| |
| if (!response) { |
| return { |
| success: false, |
| description: `Welcome to ${storeName}! We offer high-quality ${industry} products. Shop now!` |
| }; |
| } |
| |
| return { |
| success: true, |
| description: response.trim(), |
| modelUsed: this.modelStats.fast.calls > this.modelStats.precise.calls ? this.models.fast : this.models.precise |
| }; |
| } catch (error) { |
| return { |
| success: false, |
| description: `Welcome to ${storeName}! We offer high-quality ${industry} products. Shop now!` |
| }; |
| } |
| } |
| |
| clearCache() { |
| this.cache.clear(); |
| console.log('๐๏ธ AI cache cleared'); |
| console.log('๐ Model stats:', this.modelStats); |
| } |
| |
| async testConnection() { |
| try { |
| const testPrompt = "Say 'API works' and nothing else."; |
| const response = await this.callHuggingFace(testPrompt, 0.1, this.models.fast); |
| |
| if (response && response.includes('API works')) { |
| console.log('โ
Hugging Face API connection successful'); |
| return true; |
| } |
| console.log('โ ๏ธ Hugging Face API test failed'); |
| return false; |
| } catch (error) { |
| console.error('โ Hugging Face API connection failed:', error.message); |
| return false; |
| } |
| } |
| } |
|
|
| module.exports = new AIService(); |