Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>AI Image Generator Chatbot</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
<style> | |
@keyframes pulse { | |
0%, 100% { opacity: 1; } | |
50% { opacity: 0.5; } | |
} | |
.animate-pulse { | |
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; | |
} | |
.chat-container { | |
height: calc(100vh - 180px); | |
} | |
@media (max-width: 768px) { | |
.chat-container { | |
height: calc(100vh - 150px); | |
} | |
} | |
.gradient-bg { | |
background: linear-gradient(135deg, #6e8efb, #a777e3); | |
} | |
</style> | |
</head> | |
<body class="bg-gray-100"> | |
<div class="min-h-screen flex flex-col"> | |
<!-- Header --> | |
<header class="gradient-bg text-white p-4 shadow-lg"> | |
<div class="container mx-auto flex justify-between items-center"> | |
<h1 class="text-2xl font-bold flex items-center"> | |
<i class="fas fa-robot mr-2"></i> AI Image Generator | |
</h1> | |
<div class="flex items-center space-x-4"> | |
<button id="clear-chat" class="bg-white text-purple-700 px-3 py-1 rounded-full text-sm font-semibold hover:bg-purple-100 transition"> | |
<i class="fas fa-trash-alt mr-1"></i> Clear Chat | |
</button> | |
<button id="info-btn" class="bg-white text-purple-700 px-3 py-1 rounded-full text-sm font-semibold hover:bg-purple-100 transition"> | |
<i class="fas fa-info-circle mr-1"></i> Info | |
</button> | |
</div> | |
</div> | |
</header> | |
<!-- Main Content --> | |
<main class="flex-grow container mx-auto p-4 max-w-6xl"> | |
<div class="bg-white rounded-xl shadow-lg overflow-hidden"> | |
<!-- Chat Container --> | |
<div id="chat-container" class="chat-container overflow-y-auto p-4 space-y-4"> | |
<!-- Welcome Message --> | |
<div class="flex justify-start"> | |
<div class="flex-shrink-0 h-10 w-10 rounded-full bg-purple-500 flex items-center justify-center text-white"> | |
<i class="fas fa-robot"></i> | |
</div> | |
<div class="ml-3 max-w-xs md:max-w-md lg:max-w-2xl"> | |
<div class="bg-gray-100 p-3 rounded-lg rounded-tl-none"> | |
<p class="text-gray-800">Hello! I'm your AI assistant powered by Gemini. Ask me anything and I'll do my best to help. For example: "Explain quantum computing in simple terms"</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Input Area --> | |
<div class="border-t border-gray-200 p-4 bg-gray-50"> | |
<div class="flex items-center space-x-2"> | |
<input | |
id="user-input" | |
type="text" | |
placeholder="Describe the image you want to generate..." | |
class="flex-grow px-4 py-2 rounded-full border border-gray-300 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent" | |
> | |
<button | |
id="send-btn" | |
class="gradient-bg text-white p-2 rounded-full w-10 h-10 flex items-center justify-center hover:opacity-90 transition" | |
> | |
<i class="fas fa-paper-plane"></i> | |
</button> | |
</div> | |
<div class="mt-2 text-right text-xs text-gray-500"> | |
<div id="status" class="italic"></div> | |
</div> | |
</div> | |
</div> | |
</main> | |
<!-- Footer --> | |
<footer class="bg-gray-800 text-white p-4 text-center text-sm"> | |
<p>AI Image Generator Chatbot © 2023 | Powered by OpenAI API</p> | |
</footer> | |
</div> | |
<!-- Info Modal --> | |
<div id="info-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden z-50"> | |
<div class="bg-white rounded-lg p-6 max-w-md w-full mx-4"> | |
<div class="flex justify-between items-center mb-4"> | |
<h2 class="text-xl font-bold text-gray-800">About This Chatbot</h2> | |
<button id="close-modal" class="text-gray-500 hover:text-gray-700"> | |
<i class="fas fa-times"></i> | |
</button> | |
</div> | |
<div class="space-y-3 text-gray-700"> | |
<p>This AI chatbot can generate images based on your text descriptions using advanced machine learning models.</p> | |
<p><strong>Tips:</strong></p> | |
<ul class="list-disc pl-5 space-y-1"> | |
<li>Be as descriptive as possible for better results</li> | |
<li>Include details about style, colors, and composition</li> | |
<li>Try different variations of your prompt</li> | |
<li>High quality option produces better images but takes longer</li> | |
</ul> | |
<p class="pt-2 text-sm text-gray-500">Note: Generated images are AI-created and may not always be perfect.</p> | |
</div> | |
</div> | |
</div> | |
<script> | |
document.addEventListener('DOMContentLoaded', function() { | |
const chatContainer = document.getElementById('chat-container'); | |
const userInput = document.getElementById('user-input'); | |
const sendBtn = document.getElementById('send-btn'); | |
const clearChatBtn = document.getElementById('clear-chat'); | |
const infoBtn = document.getElementById('info-btn'); | |
const infoModal = document.getElementById('info-modal'); | |
const closeModal = document.getElementById('close-modal'); | |
const statusElement = document.getElementById('status'); | |
const highQualityCheckbox = document.getElementById('high-quality'); | |
const API_URL = 'https://openrouter.ai/api/v1/chat/completions'; | |
let API_KEY = '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'; | |
// Event Listeners | |
sendBtn.addEventListener('click', () => { | |
if (!API_KEY) { | |
requestAPIKey(); | |
return; | |
} | |
sendMessage(); | |
}); | |
userInput.addEventListener('keypress', function(e) { | |
if (e.key === 'Enter') sendMessage(); | |
}); | |
clearChatBtn.addEventListener('click', clearChat); | |
infoBtn.addEventListener('click', () => infoModal.classList.remove('hidden')); | |
closeModal.addEventListener('click', () => infoModal.classList.add('hidden')); | |
// Close modal when clicking outside | |
infoModal.addEventListener('click', (e) => { | |
if (e.target === infoModal) infoModal.classList.add('hidden'); | |
}); | |
async function sendMessage() { | |
const prompt = userInput.value.trim(); | |
if (!prompt) return; | |
// Add user message to chat | |
addMessage(prompt, 'user'); | |
userInput.value = ''; | |
statusElement.textContent = 'Generating image...'; | |
// Add loading indicator | |
const loadingId = addLoadingIndicator(); | |
try { | |
const response = await generateImage(prompt); | |
if (response.choices && response.choices.length > 0) { | |
const messageContent = response.choices[0].message.content; | |
addMessage(messageContent, 'bot'); | |
} else { | |
addMessage("Sorry, I couldn't generate a response for that. Please try a different prompt.", 'bot'); | |
} | |
} catch (error) { | |
console.error('Error:', error); | |
if (error.message.includes('content policy')) { | |
addMessage("Sorry, I couldn't generate that image because it may violate content policies. Please try a different description.", 'bot'); | |
} else { | |
addMessage("Sorry, I encountered an error while generating your image. Please try again.", 'bot'); | |
} | |
} finally { | |
// Remove loading indicator | |
removeLoadingIndicator(loadingId); | |
statusElement.textContent = ''; | |
} | |
} | |
function addMessage(text, sender) { | |
const messageDiv = document.createElement('div'); | |
messageDiv.className = `flex ${sender === 'user' ? 'justify-end' : 'justify-start'}`; | |
const avatar = sender === 'user' ? | |
`<div class="flex-shrink-0 h-10 w-10 rounded-full bg-blue-500 flex items-center justify-center text-white"> | |
<i class="fas fa-user"></i> | |
</div>` : | |
`<div class="flex-shrink-0 h-10 w-10 rounded-full bg-purple-500 flex items-center justify-center text-white"> | |
<i class="fas fa-robot"></i> | |
</div>`; | |
const messageContent = sender === 'user' ? | |
`<div class="mr-3 max-w-xs md:max-w-md lg:max-w-2xl"> | |
<div class="bg-blue-100 p-3 rounded-lg rounded-tr-none"> | |
<p class="text-gray-800">${text}</p> | |
</div> | |
</div>` : | |
`<div class="ml-3 max-w-xs md:max-w-md lg:max-w-2xl"> | |
<div class="bg-gray-100 p-3 rounded-lg rounded-tl-none"> | |
<p class="text-gray-800">${text}</p> | |
</div> | |
</div>`; | |
messageDiv.innerHTML = sender === 'user' ? | |
`${messageContent}${avatar}` : | |
`${avatar}${messageContent}`; | |
chatContainer.appendChild(messageDiv); | |
chatContainer.scrollTop = chatContainer.scrollHeight; | |
} | |
function addLoadingIndicator() { | |
const id = 'loading-' + Date.now(); | |
const loadingDiv = document.createElement('div'); | |
loadingDiv.className = 'flex justify-start'; | |
loadingDiv.id = id; | |
loadingDiv.innerHTML = ` | |
<div class="flex-shrink-0 h-10 w-10 rounded-full bg-purple-500 flex items-center justify-center text-white"> | |
<i class="fas fa-robot"></i> | |
</div> | |
<div class="ml-3 max-w-xs md:max-w-md lg:max-w-2xl"> | |
<div class="bg-gray-100 p-3 rounded-lg rounded-tl-none"> | |
<div class="flex space-x-2"> | |
<div class="w-3 h-3 rounded-full bg-purple-400 animate-pulse"></div> | |
<div class="w-3 h-3 rounded-full bg-purple-400 animate-pulse delay-100"></div> | |
<div class="w-3 h-3 rounded-full bg-purple-400 animate-pulse delay-200"></div> | |
</div> | |
</div> | |
</div> | |
`; | |
chatContainer.appendChild(loadingDiv); | |
chatContainer.scrollTop = chatContainer.scrollHeight; | |
return id; | |
} | |
function removeLoadingIndicator(id) { | |
const element = document.getElementById(id); | |
if (element) { | |
element.remove(); | |
} | |
} | |
function requestAPIKey() { | |
const key = prompt('Please enter your OpenAI API key:'); | |
if (key) { | |
API_KEY = key.trim(); | |
localStorage.setItem('openai_api_key', API_KEY); | |
} else { | |
addMessage("API key is required to generate images. Please refresh the page and enter your key when prompted.", 'bot'); | |
} | |
} | |
async function generateImage(prompt) { | |
const response = await fetch(API_URL, { | |
method: 'POST', | |
headers: { | |
"Authorization": `Bearer ${API_KEY}`, | |
"Content-Type": "application/json", | |
"HTTP-Referer": window.location.href, | |
"X-Title": "AI Image Generator" | |
}, | |
body: JSON.stringify({ | |
"model": "google/gemini-2.0-flash-exp:free", | |
"messages": [ | |
{ | |
"role": "user", | |
"content": [ | |
{ | |
"type": "text", | |
"text": prompt | |
} | |
] | |
} | |
] | |
}) | |
}); | |
if (!response.ok) { | |
const errorData = await response.json(); | |
let errorMessage = `API request failed with status ${response.status}`; | |
if (errorData.error && errorData.error.message) { | |
errorMessage = errorData.error.message; | |
} | |
throw new Error(errorMessage); | |
} | |
const data = await response.json(); | |
return data; | |
} | |
function clearChat() { | |
// Keep only the welcome message | |
while (chatContainer.children.length > 1) { | |
chatContainer.removeChild(chatContainer.lastChild); | |
} | |
} | |
}); | |
</script> | |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=miiann/ai-image-prompt-gen" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |