Spaces:
Running
Running
| ```html | |
| <html> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>مشاور مبلمان</title> | |
| <style> | |
| * { box-sizing: border-box; font-family: 'Segoe UI', Tahoma, sans-serif; } | |
| body { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| min-height: 100vh; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| padding: 20px; | |
| margin: 0; | |
| } | |
| .container { | |
| max-width: 850px; | |
| width: 100%; | |
| background: white; | |
| border-radius: 30px; | |
| padding: 35px; | |
| box-shadow: 0 20px 60px rgba(0,0,0,0.3); | |
| } | |
| h1 { text-align: center; color: #2c3e50; margin-top: 0; } | |
| .subtitle { text-align: center; color: #7f8c8d; margin-bottom: 25px; } | |
| .upload-area { | |
| border: 3px dashed #667eea; | |
| border-radius: 20px; | |
| padding: 40px 20px; | |
| text-align: center; | |
| background: #f8f9fa; | |
| cursor: pointer; | |
| transition: 0.3s; | |
| } | |
| .upload-area:hover { background: #e9ecef; border-color: #764ba2; } | |
| .upload-area input[type="file"] { | |
| display: block; | |
| margin: 15px auto; | |
| padding: 10px; | |
| border: 1px solid #ccc; | |
| border-radius: 10px; | |
| width: 100%; | |
| max-width: 300px; | |
| cursor: pointer; | |
| } | |
| #image-preview { | |
| max-width: 100%; | |
| max-height: 350px; | |
| border-radius: 15px; | |
| margin: 15px 0; | |
| display: none; | |
| box-shadow: 0 5px 15px rgba(0,0,0,0.1); | |
| } | |
| .btn-analyze { | |
| background: #667eea; | |
| color: white; | |
| border: none; | |
| padding: 16px 20px; | |
| border-radius: 50px; | |
| font-size: 1.2rem; | |
| font-weight: bold; | |
| cursor: pointer; | |
| width: 100%; | |
| transition: 0.3s; | |
| margin-top: 10px; | |
| } | |
| .btn-analyze:hover { background: #764ba2; transform: scale(1.01); } | |
| .btn-analyze:disabled { opacity: 0.6; cursor: not-allowed; } | |
| .result-box { | |
| background: #f8f9fa; | |
| padding: 20px; | |
| border-radius: 15px; | |
| margin-top: 20px; | |
| white-space: pre-wrap; | |
| font-family: 'Courier New', monospace; | |
| display: none; | |
| border-right: 5px solid #667eea; | |
| max-height: 500px; | |
| overflow-y: auto; | |
| } | |
| .loading { display: none; text-align: center; padding: 30px 0; } | |
| .spinner { | |
| border: 5px solid #f3f3f3; | |
| border-top: 5px solid #667eea; | |
| border-radius: 50%; | |
| width: 50px; | |
| height: 50px; | |
| animation: spin 1s linear infinite; | |
| margin: 0 auto; | |
| } | |
| @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } | |
| .tip { | |
| background: #fff3cd; | |
| padding: 15px; | |
| border-radius: 12px; | |
| margin-top: 20px; | |
| text-align: center; | |
| border: 1px solid #ffc107; | |
| font-size: 0.95rem; | |
| } | |
| .model-selector { | |
| margin: 15px 0; | |
| text-align: center; | |
| } | |
| .model-selector select { | |
| padding: 10px 20px; | |
| border-radius: 30px; | |
| border: 2px solid #667eea; | |
| font-size: 1rem; | |
| background: white; | |
| cursor: pointer; | |
| } | |
| .model-selector select:focus { outline: none; border-color: #764ba2; } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <h1>🪑 مشاور هوشمند مبلمان</h1> | |
| <p class="subtitle">عکس مبل رو آپلود کن تا هوش مصنوعی تحلیلش کنه</p> | |
| <div class="model-selector"> | |
| <label for="modelSelect">🧠 انتخاب هوش مصنوعی:</label> | |
| <select id="modelSelect"> | |
| <option value="Salesforce/blip-image-captioning-base">BLIP (توصیف تصویر)</option> | |
| <option value="nlpconnect/vit-gpt2-image-captioning">ViT-GPT2 (توصیف تصویر)</option> | |
| <option value="microsoft/git-base-coco">GIT (توصیف دقیق)</option> | |
| <option value="HuggingFaceH4/zephyr-7b-beta">Zephyr-7B (متنی - قدرتمند)</option> | |
| <option value="mistralai/Mistral-7B-Instruct-v0.3">Mistral-7B (متنی - حرفهای)</option> | |
| </select> | |
| </div> | |
| <div class="upload-area" id="uploadArea"> | |
| <label for="fileInput" style="display:block; margin-bottom:10px;"> | |
| <span style="font-size:3rem; display:block;">📸</span> | |
| <strong>برای آپلود عکس کلیک کن</strong><br> | |
| <small>یا عکس رو بکش و اینجا رها کن</small> | |
| </label> | |
| <input type="file" id="fileInput" accept="image/*"> | |
| </div> | |
| <img id="image-preview" alt="پیشنمایش عکس"> | |
| <div class="loading" id="loading"> | |
| <div class="spinner"></div> | |
| <p style="margin-top:15px; color:#2c3e50;">🧠 هوش مصنوعی در حال تحلیل عکس...</p> | |
| <small style="color:#7f8c8d;">این کار ممکنه چند ثانیه طول بکشه</small> | |
| </div> | |
| <button class="btn-analyze" id="analyzeBtn">🔍 تحلیل با هوش مصنوعی</button> | |
| <div class="result-box" id="resultBox"></div> | |
| <div class="tip"> | |
| 💡 <strong>نکته:</strong> میتونی بین مدلهای مختلف یکی رو انتخاب کنی. هرکدوم یه جور تحلیل میکنن. | |
| </div> | |
| </div> | |
| <script> | |
| const HF_TOKEN = ""; | |
| const fileInput = document.getElementById('fileInput'); | |
| const uploadArea = document.getElementById('uploadArea'); | |
| const preview = document.getElementById('image-preview'); | |
| const analyzeBtn = document.getElementById('analyzeBtn'); | |
| const resultBox = document.getElementById('resultBox'); | |
| const loading = document.getElementById('loading'); | |
| const modelSelect = document.getElementById('modelSelect'); | |
| let selectedFile = null; | |
| let isAnalyzing = false; | |
| fileInput.addEventListener('change', function(e) { | |
| const file = this.files[0]; | |
| if (file) { | |
| selectedFile = file; | |
| const reader = new FileReader(); | |
| reader.onload = function(e) { | |
| preview.src = e.target.result; | |
| preview.style.display = 'block'; | |
| resultBox.style.display = 'none'; | |
| }; | |
| reader.readAsDataURL(file); | |
| } | |
| }); | |
| uploadArea.addEventListener('click', function(e) { | |
| if (e.target.tagName !== 'INPUT') { | |
| fileInput.click(); | |
| } | |
| }); | |
| uploadArea.addEventListener('dragover', (e) => { | |
| e.preventDefault(); | |
| uploadArea.style.borderColor = '#764ba2'; | |
| uploadArea.style.background = '#e9ecef'; | |
| }); | |
| uploadArea.addEventListener('dragleave', () => { | |
| uploadArea.style.borderColor = '#667eea'; | |
| uploadArea.style.background = '#f8f9fa'; | |
| }); | |
| uploadArea.addEventListener('drop', (e) => { | |
| e.preventDefault(); | |
| uploadArea.style.borderColor = '#667eea'; | |
| uploadArea.style.background = '#f8f9fa'; | |
| const file = e.dataTransfer.files[0]; | |
| if (file) { | |
| selectedFile = file; | |
| const reader = new FileReader(); | |
| reader.onload = function(e) { | |
| preview.src = e.target.result; | |
| preview.style.display = 'block'; | |
| resultBox.style.display = 'none'; | |
| }; | |
| reader.readAsDataURL(file); | |
| fileInput.files = e.dataTransfer.files; | |
| } | |
| }); | |
| analyzeBtn.addEventListener('click', async function() { | |
| if (!selectedFile) { | |
| alert('⚠️ لطفاً اول یه عکس انتخاب کن!'); | |
| return; | |
| } | |
| if (isAnalyzing) return; | |
| if (!HF_TOKEN) { | |
| resultBox.style.display = 'block'; | |
| resultBox.innerHTML = ` | |
| ❌ **توکن پیدا نشد!** | |
| لطفاً توکن رو در Settings > Repository secrets با اسم HF_TOKEN اضافه کن. | |
| `; | |
| return; | |
| } | |
| const selectedModel = modelSelect.value; | |
| const API_URL = `https://api-inference.huggingface.co/models/${selectedModel}`; | |
| isAnalyzing = true; | |
| analyzeBtn.disabled = true; | |
| analyzeBtn.textContent = '⏳ در حال تحلیل...'; | |
| loading.style.display = 'block'; | |
| resultBox.style.display = 'none'; | |
| try { | |
| const reader = new FileReader(); | |
| const base64Image = await new Promise((resolve) => { | |
| reader.onload = (e) => resolve(e.target.result.split(',')[1]); | |
| reader.readAsDataURL(selectedFile); | |
| }); | |
| const response = await fetch(API_URL, { | |
| method: 'POST', | |
| headers: { | |
| 'Authorization': `Bearer ${HF_TOKEN}`, | |
| 'Content-Type': 'application/json' | |
| }, | |
| body: JSON.stringify({ | |
| inputs: base64Image, | |
| parameters: { max_new_tokens: 500 } | |
| }) | |
| }); | |
| if (!response.ok) { | |
| const errorText = await response.text(); | |
| throw new Error(`خطا: ${response.status} - ${errorText}`); | |
| } | |
| const result = await response.json(); | |
| let analysis = ""; | |
| if (Array.isArray(result) && result.length > 0) { | |
| if (result[0].generated_text) { | |
| analysis = result[0].generated_text; | |
| } else if (result[0].label) { | |
| analysis = result.map(r => `${r.label}: ${(r.score * 100).toFixed(1)}%`).join('\n'); | |
| } else { | |
| analysis = JSON.stringify(result[0], null, 2); | |
| } | |
| } else if (result.generated_text) { | |
| analysis = result.generated_text; | |
| } else if (result.error) { | |
| throw new Error(result.error); | |
| } else { | |
| analysis = JSON.stringify(result, null, 2); | |
| } | |
| loading.style.display = 'none'; | |
| resultBox.style.display = 'block'; | |
| const modelName = selectedModel.split('/').pop(); | |
| resultBox.innerHTML = ` | |
| 🧠 **تحلیل با مدل:** ${modelName} | |
| 📝 **توضیحات:** | |
| ${analysis} | |
| 🎨 **پیشنهادات طراحی:** | |
| • اگر مبلمان تشخیص داده شده، از پارچه کتان یا مخمل استفاده کن | |
| • رنگهای طوسی، آبی نفتی یا کرم خیلی مناسبن | |
| • برای هماهنگی با دکوراسیون، از رنگهای مکمل استفاده کن | |
| • ابعاد مبل رو با فضای اتاق هماهنگ کن | |
| 💡 **نکته:** هر مدل هوش مصنوعی یه جور تحلیل میکنه. میتونی مدلهای مختلف رو امتحان کنی. | |
| `; | |
| } catch (error) { | |
| loading.style.display = 'none'; | |
| resultBox.style.display = 'block'; | |
| resultBox.innerHTML = ` | |
| ❌ **خطا در تحلیل** | |
| ${error.message} | |
| 📌 **راه حل:** | |
| • چند دقیقه دیگه دوباره تلاش کن | |
| • یه مدل دیگه رو انتخاب کن | |
| • مطمئن شو که اینترنت وصل هست | |
| `; | |
| } finally { | |
| isAnalyzing = false; | |
| analyzeBtn.disabled = false; | |
| analyzeBtn.textContent = '🔍 تحلیل با هوش مصنوعی'; | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> | |
| ``` |