Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>HuroAI Ollama Playground</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<script src="https://kit.fontawesome.com/a076d05399.js" crossorigin="anonymous"></script> | |
<style> | |
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); | |
body { | |
font-family: 'Inter', sans-serif; | |
background-color: #f5f7fa; | |
} | |
.message-user { | |
background-color: #e3f2fd; | |
border-radius: 18px 18px 0 18px; | |
} | |
.message-ai { | |
background-color: #ffffff; | |
border-radius: 18px 18px 18px 0; | |
box-shadow: 0 1px 2px rgba(0,0,0,0.1); | |
} | |
.model-card { | |
transition: all 0.2s ease; | |
} | |
.model-card:hover { | |
transform: translateY(-2px); | |
box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1); | |
} | |
.model-card.selected { | |
border-color: #3b82f6; | |
background-color: #f0f7ff; | |
} | |
.typing-indicator span { | |
display: inline-block; | |
width: 8px; | |
height: 8px; | |
border-radius: 50%; | |
background-color: #9ca3af; | |
margin: 0 2px; | |
} | |
.typing-indicator span:nth-child(1) { | |
animation: bounce 1s infinite; | |
} | |
.typing-indicator span:nth-child(2) { | |
animation: bounce 1s infinite 0.2s; | |
} | |
.typing-indicator span:nth-child(3) { | |
animation: bounce 1s infinite 0.4s; | |
} | |
@keyframes bounce { | |
0%, 100% { transform: translateY(0); } | |
50% { transform: translateY(-5px); } | |
} | |
#chat-container { | |
scrollbar-width: thin; | |
scrollbar-color: #cbd5e0 #f1f5f9; | |
} | |
#chat-container::-webkit-scrollbar { | |
width: 6px; | |
} | |
#chat-container::-webkit-scrollbar-track { | |
background: #f1f5f9; | |
} | |
#chat-container::-webkit-scrollbar-thumb { | |
background-color: #cbd5e0; | |
border-radius: 3px; | |
} | |
</style> | |
</head> | |
<body class="min-h-screen flex flex-col"> | |
<header class="bg-white shadow-sm py-4"> | |
<div class="container mx-auto px-4 flex justify-between items-center"> | |
<div class="flex items-center space-x-2"> | |
<div class="w-8 h-8 bg-blue-500 rounded-full flex items-center justify-center"> | |
<i class="fas fa-robot text-white"></i> | |
</div> | |
<h1 class="text-xl font-bold text-gray-800">HuroAI Ollama Playground</h1> | |
</div> | |
<div class="flex items-center space-x-4"> | |
<a href="#" class="text-gray-600 hover:text-blue-500"> | |
<i class="fas fa-cog"></i> | |
</a> | |
<a href="#" class="text-gray-600 hover:text-blue-500"> | |
<i class="fas fa-question-circle"></i> | |
</a> | |
</div> | |
</div> | |
</header> | |
<main class="flex-1 container mx-auto px-4 py-6 flex flex-col lg:flex-row gap-6"> | |
<!-- Model Selection Sidebar --> | |
<aside class="w-full lg:w-64 flex-shrink-0"> | |
<div class="bg-white rounded-xl shadow-sm p-4 sticky top-6"> | |
<h2 class="font-semibold text-gray-700 mb-4">Available Models</h2> | |
<div class="space-y-3"> | |
<div class="model-card p-3 border rounded-lg cursor-pointer transition selected" data-model="huroai/phoenixcoder"> | |
<div class="flex items-center space-x-3"> | |
<div class="w-10 h-10 bg-purple-100 rounded-full flex items-center justify-center"> | |
<i class="fas fa-code text-purple-600"></i> | |
</div> | |
<div> | |
<h3 class="font-medium text-gray-800">PhoenixCoder</h3> | |
<p class="text-xs text-gray-500">Specialized in coding</p> | |
</div> | |
</div> | |
</div> | |
<div class="model-card p-3 border rounded-lg cursor-pointer transition" data-model="huroai/beehuroai"> | |
<div class="flex items-center space-x-3"> | |
<div class="w-10 h-10 bg-yellow-100 rounded-full flex items-center justify-center"> | |
<i class="fas fa-comment-dots text-yellow-600"></i> | |
</div> | |
<div> | |
<h3 class="font-medium text-gray-800">BeeHuroAI</h3> | |
<p class="text-xs text-gray-500">General assistant</p> | |
</div> | |
</div> | |
</div> | |
<div class="model-card p-3 border rounded-lg cursor-pointer transition" data-model="huroai/beehuroai-vision"> | |
<div class="flex items-center space-x-3"> | |
<div class="w-10 h-10 bg-green-100 rounded-full flex items-center justify-center"> | |
<i class="fas fa-eye text-green-600"></i> | |
</div> | |
<div> | |
<h3 class="font-medium text-gray-800">BeeHuroAI Vision</h3> | |
<p class="text-xs text-gray-500">Multimodal capabilities</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="mt-6 pt-4 border-t border-gray-100"> | |
<h3 class="text-sm font-medium text-gray-700 mb-2">Model Settings</h3> | |
<div class="space-y-3"> | |
<div> | |
<label class="block text-xs text-gray-500 mb-1">Temperature</label> | |
<input type="range" min="0" max="1" step="0.1" value="0.7" class="w-full"> | |
</div> | |
<div> | |
<label class="block text-xs text-gray-500 mb-1">Max Tokens</label> | |
<input type="number" value="2048" class="w-full px-2 py-1 text-sm border rounded"> | |
</div> | |
</div> | |
</div> | |
</div> | |
</aside> | |
<!-- Chat Interface --> | |
<div class="flex-1 flex flex-col bg-white rounded-xl shadow-sm overflow-hidden"> | |
<!-- Chat Header --> | |
<div class="border-b border-gray-100 p-4 flex items-center justify-between"> | |
<div> | |
<h2 class="font-semibold text-gray-800">Chat with PhoenixCoder</h2> | |
<p class="text-xs text-gray-500">Model is ready</p> | |
</div> | |
<div class="flex space-x-2"> | |
<button class="p-2 text-gray-500 hover:text-blue-500 hover:bg-gray-50 rounded-full"> | |
<i class="fas fa-redo"></i> | |
</button> | |
<button class="p-2 text-gray-500 hover:text-blue-500 hover:bg-gray-50 rounded-full"> | |
<i class="fas fa-trash-alt"></i> | |
</button> | |
</div> | |
</div> | |
<!-- Chat Messages --> | |
<div id="chat-container" class="flex-1 p-4 overflow-y-auto space-y-4"> | |
<div class="flex justify-start"> | |
<div class="message-ai p-4 max-w-[85%]"> | |
<div class="flex items-center space-x-2 mb-1"> | |
<div class="w-6 h-6 bg-blue-100 rounded-full flex items-center justify-center"> | |
<i class="fas fa-robot text-blue-500 text-xs"></i> | |
</div> | |
<span class="text-xs font-medium text-gray-700">PhoenixCoder</span> | |
</div> | |
<p class="text-gray-800">Hello! I'm PhoenixCoder, your AI coding assistant. I can help with code generation, debugging, and explanations. What would you like to work on today?</p> | |
</div> | |
</div> | |
<div class="flex justify-end"> | |
<div class="message-user p-4 max-w-[85%]"> | |
<div class="flex items-center space-x-2 mb-1 justify-end"> | |
<span class="text-xs font-medium text-gray-700">You</span> | |
<div class="w-6 h-6 bg-blue-500 rounded-full flex items-center justify-center"> | |
<i class="fas fa-user text-white text-xs"></i> | |
</div> | |
</div> | |
<p class="text-gray-800">Can you help me write a Python function to calculate Fibonacci numbers?</p> | |
</div> | |
</div> | |
<div class="flex justify-start"> | |
<div class="message-ai p-4 max-w-[85%]"> | |
<div class="flex items-center space-x-2 mb-1"> | |
<div class="w-6 h-6 bg-blue-100 rounded-full flex items-center justify-center"> | |
<i class="fas fa-robot text-blue-500 text-xs"></i> | |
</div> | |
<span class="text-xs font-medium text-gray-700">PhoenixCoder</span> | |
</div> | |
<div class="text-gray-800"> | |
<p>Certainly! Here's a Python function to calculate Fibonacci numbers recursively:</p> | |
<pre class="bg-gray-100 p-3 rounded mt-2 overflow-x-auto"><code class="text-sm">def fibonacci(n): | |
if n <= 1: | |
return n | |
else: | |
return fibonacci(n-1) + fibonacci(n-2)</code></pre> | |
<p class="mt-2">Would you like me to explain how it works or provide an iterative version?</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Input Area --> | |
<div class="border-t border-gray-100 p-4"> | |
<div class="flex items-end space-x-2"> | |
<div class="flex-1 relative"> | |
<textarea id="message-input" rows="1" placeholder="Type your message..." class="w-full px-4 py-3 pr-12 border rounded-lg resize-none focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" style="min-height: 50px;"></textarea> | |
<div class="absolute right-2 bottom-3 flex space-x-1"> | |
<button class="p-1 text-gray-400 hover:text-blue-500"> | |
<i class="fas fa-paperclip"></i> | |
</button> | |
<button class="p-1 text-gray-400 hover:text-blue-500"> | |
<i class="fas fa-image"></i> | |
</button> | |
</div> | |
</div> | |
<button id="send-button" class="bg-blue-500 hover:bg-blue-600 text-white p-3 rounded-lg transition"> | |
<i class="fas fa-paper-plane"></i> | |
</button> | |
</div> | |
<div class="mt-2 text-xs text-gray-500 flex justify-between"> | |
<div> | |
<span id="char-count">0</span>/1000 | |
</div> | |
<div> | |
<button class="text-blue-500 hover:underline">Shift + Enter for new line</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
</main> | |
<footer class="bg-white border-t py-4"> | |
<div class="container mx-auto px-4 text-center text-sm text-gray-500"> | |
<p>Powered by Ollama • Models by HuroAI • <a href="#" class="text-blue-500 hover:underline">Terms</a> • <a href="#" class="text-blue-500 hover:underline">Privacy</a></p> | |
</div> | |
</footer> | |
<script> | |
document.addEventListener('DOMContentLoaded', function() { | |
// Model selection | |
const modelCards = document.querySelectorAll('.model-card'); | |
modelCards.forEach(card => { | |
card.addEventListener('click', function() { | |
modelCards.forEach(c => c.classList.remove('selected')); | |
this.classList.add('selected'); | |
const modelName = this.getAttribute('data-model'); | |
document.querySelector('.chat-header h2').textContent = `Chat with ${modelName.split('/')[1]}`; | |
// In a real implementation, you would switch the active model here | |
console.log(`Switched to model: ${modelName}`); | |
}); | |
}); | |
// Message input handling | |
const messageInput = document.getElementById('message-input'); | |
const sendButton = document.getElementById('send-button'); | |
const chatContainer = document.getElementById('chat-container'); | |
const charCount = document.getElementById('char-count'); | |
messageInput.addEventListener('input', function() { | |
charCount.textContent = this.value.length; | |
}); | |
function sendMessage() { | |
const message = messageInput.value.trim(); | |
if (message === '') return; | |
// Add user message to chat | |
const userMessageHtml = ` | |
<div class="flex justify-end"> | |
<div class="message-user p-4 max-w-[85%]"> | |
<div class="flex items-center space-x-2 mb-1 justify-end"> | |
<span class="text-xs font-medium text-gray-700">You</span> | |
<div class="w-6 h-6 bg-blue-500 rounded-full flex items-center justify-center"> | |
<i class="fas fa-user text-white text-xs"></i> | |
</div> | |
</div> | |
<p class="text-gray-800">${message}</p> | |
</div> | |
</div> | |
`; | |
chatContainer.insertAdjacentHTML('beforeend', userMessageHtml); | |
// Clear input | |
messageInput.value = ''; | |
charCount.textContent = '0'; | |
// Add typing indicator | |
const typingIndicator = ` | |
<div class="flex justify-start"> | |
<div class="message-ai p-4 max-w-[85%]"> | |
<div class="flex items-center space-x-2 mb-1"> | |
<div class="w-6 h-6 bg-blue-100 rounded-full flex items-center justify-center"> | |
<i class="fas fa-robot text-blue-500 text-xs"></i> | |
</div> | |
<span class="text-xs font-medium text-gray-700">${document.querySelector('.selected h3').textContent}</span> | |
</div> | |
<div class="typing-indicator"> | |
<span></span> | |
<span></span> | |
<span></span> | |
</div> | |
</div> | |
</div> | |
`; | |
chatContainer.insertAdjacentHTML('beforeend', typingIndicator); | |
chatContainer.scrollTop = chatContainer.scrollHeight; | |
// Simulate AI response after delay | |
setTimeout(() => { | |
// Remove typing indicator | |
const typingIndicators = document.querySelectorAll('.typing-indicator'); | |
typingIndicators[typingIndicators.length - 1].parentNode.parentNode.remove(); | |
// Add AI response | |
const selectedModel = document.querySelector('.selected').getAttribute('data-model'); | |
let responseText = ''; | |
if (selectedModel === 'huroai/phoenixcoder') { | |
responseText = `I'm PhoenixCoder, your coding assistant. I can help you with programming questions. For your message: "${message}", I would typically provide a code solution or explanation. In a real implementation, this would connect to the Ollama API.`; | |
} else if (selectedModel === 'huroai/beehuroai') { | |
responseText = `As BeeHuroAI, I can assist with general knowledge questions. You asked: "${message}". In a production environment, this would query the Ollama model for a detailed response.`; | |
} else if (selectedModel === 'huroai/beehuroai-vision') { | |
responseText = `BeeHuroAI Vision can process both text and images. You sent: "${message}". If you included an image, I could analyze it. This is a demo - in reality, it would use Ollama's multimodal capabilities.`; | |
} | |
const aiMessageHtml = ` | |
<div class="flex justify-start"> | |
<div class="message-ai p-4 max-w-[85%]"> | |
<div class="flex items-center space-x-2 mb-1"> | |
<div class="w-6 h-6 bg-blue-100 rounded-full flex items-center justify-center"> | |
<i class="fas fa-robot text-blue-500 text-xs"></i> | |
</div> | |
<span class="text-xs font-medium text-gray-700">${document.querySelector('.selected h3').textContent}</span> | |
</div> | |
<p class="text-gray-800">${responseText}</p> | |
</div> | |
</div> | |
`; | |
chatContainer.insertAdjacentHTML('beforeend', aiMessageHtml); | |
chatContainer.scrollTop = chatContainer.scrollHeight; | |
}, 1500); | |
} | |
sendButton.addEventListener('click', sendMessage); | |
messageInput.addEventListener('keydown', function(e) { | |
if (e.key === 'Enter' && !e.shiftKey) { | |
e.preventDefault(); | |
sendMessage(); | |
} | |
}); | |
// Auto-resize textarea | |
messageInput.addEventListener('input', function() { | |
this.style.height = 'auto'; | |
this.style.height = (this.scrollHeight) + 'px'; | |
}); | |
}); | |
</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=tommytracx/t" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |