Download templates/admin.html from bshk57/Chatbot: direct link, hf CLI and curl.
- Browser
- Download file 14.6 kB
-
https://huggingface.co/spaces/bshk57/Chatbot/resolve/main/templates/admin.html
- Command line
-
hf download hf://spaces/bshk57/Chatbot/templates/admin.html
-
curl -L -o admin.html https://huggingface.co/spaces/bshk57/Chatbot/resolve/main/templates/admin.html
14.6 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Admin Dashboard - SASTRA Chatbot</title> | |
| <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"> | |
| <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}"> | |
| </head> | |
| <body> | |
| <!-- Admin Header --> | |
| <nav class="navbar navbar-expand-lg navbar-dark bg-dark"> | |
| <div class="container"> | |
| <a class="navbar-brand" href="/"> | |
| <i class="fas fa-university me-2"></i>SASTRA Admin | |
| </a> | |
| <div class="navbar-nav ms-auto"> | |
| <a href="/" class="nav-link"> | |
| <i class="fas fa-robot me-1"></i>Chat | |
| </a> | |
| <a href="/logout" class="nav-link"> | |
| <i class="fas fa-sign-out-alt me-1"></i>Logout | |
| </a> | |
| </div> | |
| </div> | |
| </nav> | |
| <div class="container mt-4"> | |
| <div class="row"> | |
| <div class="col-md-12"> | |
| <h2 class="mb-4"> | |
| <i class="fas fa-tachometer-alt me-2"></i>Admin Dashboard | |
| </h2> | |
| </div> | |
| </div> | |
| <!-- Retraining Section --> | |
| <div class="row mb-4"> | |
| <div class="col-md-12"> | |
| <div class="card"> | |
| <div class="card-header bg-warning text-dark"> | |
| <h5 class="mb-0"> | |
| <i class="fas fa-retweet me-2"></i>Model Retraining | |
| </h5> | |
| </div> | |
| <div class="card-body"> | |
| <div class="alert alert-info"> | |
| <i class="fas fa-info-circle me-2"></i> | |
| Upload a new Excel file with keyword-response pairs to update the chatbot's knowledge. | |
| </div> | |
| <form id="retrainForm"> | |
| <div class="mb-3"> | |
| <label for="trainingFile" class="form-label">Upload Training Data (Excel)</label> | |
| <input class="form-control" type="file" id="trainingFile" accept=".xlsx"> | |
| <div class="form-text"> | |
| Excel file should have columns: "keyword" and "response" | |
| </div> | |
| </div> | |
| <div class="d-flex gap-2"> | |
| <button type="submit" class="btn btn-warning" id="retrainBtn"> | |
| <i class="fas fa-sync me-2"></i>Retrain Model | |
| </button> | |
| <a href="/api/download_logs" class="btn btn-outline-primary"> | |
| <i class="fas fa-download me-2"></i>Download Logs | |
| </a> | |
| </div> | |
| </form> | |
| <div id="retrainResult" class="mt-3"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Analytics Section --> | |
| <div class="row"> | |
| <div class="col-md-12"> | |
| <div class="card"> | |
| <div class="card-header bg-success text-white"> | |
| <h5 class="mb-0"> | |
| <i class="fas fa-chart-bar me-2"></i>Analytics Dashboard | |
| </h5> | |
| </div> | |
| <div class="card-body"> | |
| <div class="d-flex justify-content-between mb-3"> | |
| <button class="btn btn-outline-success" onclick="refreshAnalytics()"> | |
| <i class="fas fa-redo me-2"></i>Refresh Analytics | |
| </button> | |
| <span class="text-muted">Last updated: <span id="lastUpdate">Never</span></span> | |
| </div> | |
| <!-- Analytics Cards --> | |
| <div class="row" id="analyticsCards"> | |
| <div class="col-md-3 mb-3"> | |
| <div class="card text-center h-100"> | |
| <div class="card-body"> | |
| <h1 class="display-4 text-primary" id="totalQueries">0</h1> | |
| <p class="card-text">Total Queries</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="col-md-9 mb-3"> | |
| <div class="card h-100"> | |
| <div class="card-header"> | |
| <h6 class="mb-0">Language Distribution</h6> | |
| </div> | |
| <div class="card-body"> | |
| <div class="table-responsive"> | |
| <table class="table table-sm" id="langTable"> | |
| <tbody> | |
| <!-- Filled by JavaScript --> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Response Types & Top Questions --> | |
| <div class="row mt-3"> | |
| <div class="col-md-6 mb-3"> | |
| <div class="card h-100"> | |
| <div class="card-header"> | |
| <h6 class="mb-0">Response Types</h6> | |
| </div> | |
| <div class="card-body"> | |
| <div class="table-responsive"> | |
| <table class="table table-sm" id="responseTypeTable"> | |
| <tbody> | |
| <!-- Filled by JavaScript --> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="col-md-6 mb-3"> | |
| <div class="card h-100"> | |
| <div class="card-header"> | |
| <h6 class="mb-0">Recent Questions</h6> | |
| </div> | |
| <div class="card-body"> | |
| <ul class="list-group list-group-flush" id="topQuestions"> | |
| <!-- Filled by JavaScript --> | |
| </ul> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Bootstrap JS --> | |
| <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script> | |
| <!-- Admin JavaScript --> | |
| <script> | |
| document.getElementById('retrainForm').addEventListener('submit', async function(e) { | |
| e.preventDefault(); | |
| const fileInput = document.getElementById('trainingFile'); | |
| const retrainBtn = document.getElementById('retrainBtn'); | |
| const resultDiv = document.getElementById('retrainResult'); | |
| if (!fileInput.files.length) { | |
| resultDiv.innerHTML = ` | |
| <div class="alert alert-warning"> | |
| <i class="fas fa-exclamation-triangle me-2"></i> | |
| Please select an Excel file to upload. | |
| </div> | |
| `; | |
| return; | |
| } | |
| const formData = new FormData(); | |
| formData.append('file', fileInput.files[0]); | |
| retrainBtn.disabled = true; | |
| retrainBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Retraining...'; | |
| try { | |
| const response = await fetch('/api/retrain', { | |
| method: 'POST', | |
| body: formData | |
| }); | |
| const data = await response.json(); | |
| if (response.ok) { | |
| resultDiv.innerHTML = ` | |
| <div class="alert alert-success"> | |
| <i class="fas fa-check-circle me-2"></i> | |
| ${data.message} | |
| </div> | |
| `; | |
| // Refresh analytics after retraining | |
| refreshAnalytics(); | |
| } else { | |
| resultDiv.innerHTML = ` | |
| <div class="alert alert-danger"> | |
| <i class="fas fa-times-circle me-2"></i> | |
| Error: ${data.error || 'Failed to retrain'} | |
| </div> | |
| `; | |
| } | |
| } catch (error) { | |
| resultDiv.innerHTML = ` | |
| <div class="alert alert-danger"> | |
| <i class="fas fa-times-circle me-2"></i> | |
| Network error: ${error.message} | |
| </div> | |
| `; | |
| } finally { | |
| retrainBtn.disabled = false; | |
| retrainBtn.innerHTML = '<i class="fas fa-sync me-2"></i>Retrain Model'; | |
| } | |
| }); | |
| async function refreshAnalytics() { | |
| try { | |
| const response = await fetch('/api/analytics'); | |
| const data = await response.json(); | |
| if (response.ok) { | |
| // Update last update time | |
| const now = new Date(); | |
| document.getElementById('lastUpdate').textContent = now.toLocaleTimeString(); | |
| // Update total queries | |
| document.getElementById('totalQueries').textContent = data.total_queries || 0; | |
| // Update language distribution | |
| const langTable = document.getElementById('langTable'); | |
| langTable.innerHTML = ''; | |
| if (data.language_distribution) { | |
| for (const [lang, count] of Object.entries(data.language_distribution)) { | |
| const row = document.createElement('tr'); | |
| row.innerHTML = ` | |
| <td>${getLanguageName(lang)}</td> | |
| <td>${count}</td> | |
| <td> | |
| <div class="progress" style="height: 10px;"> | |
| <div class="progress-bar" style="width: ${(count / data.total_queries * 100) || 0}%"></div> | |
| </div> | |
| </td> | |
| `; | |
| langTable.appendChild(row); | |
| } | |
| } | |
| // Update response types | |
| const responseTable = document.getElementById('responseTypeTable'); | |
| responseTable.innerHTML = ''; | |
| if (data.response_types) { | |
| for (const [type, count] of Object.entries(data.response_types)) { | |
| const row = document.createElement('tr'); | |
| const badgeColor = getResponseTypeColor(type); | |
| row.innerHTML = ` | |
| <td><span class="badge ${badgeColor}">${type.toUpperCase()}</span></td> | |
| <td>${count}</td> | |
| `; | |
| responseTable.appendChild(row); | |
| } | |
| } | |
| // Update top questions | |
| const topQuestions = document.getElementById('topQuestions'); | |
| topQuestions.innerHTML = ''; | |
| if (data.top_questions && data.top_questions.length > 0) { | |
| data.top_questions.forEach(question => { | |
| const li = document.createElement('li'); | |
| li.className = 'list-group-item'; | |
| li.textContent = question.length > 50 ? question.substring(0, 50) + '...' : question; | |
| topQuestions.appendChild(li); | |
| }); | |
| } | |
| } | |
| } catch (error) { | |
| console.error('Error refreshing analytics:', error); | |
| } | |
| } | |
| function getLanguageName(code) { | |
| const languages = { | |
| 'en': 'English', | |
| 'ta': 'Tamil', | |
| 'te': 'Telugu', | |
| 'kn': 'Kannada', | |
| 'hi': 'Hindi', | |
| 'unknown': 'Unknown' | |
| }; | |
| return languages[code] || code; | |
| } | |
| function getResponseTypeColor(type) { | |
| const colors = { | |
| 'keyword': 'bg-warning', | |
| 'rag': 'bg-info', | |
| 'llm': 'bg-primary', | |
| 'error': 'bg-danger' | |
| }; | |
| return colors[type] || 'bg-secondary'; | |
| } | |
| // Load analytics on page load | |
| document.addEventListener('DOMContentLoaded', refreshAnalytics); | |
| </script> | |
| </body> | |
| </html> |