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> |