Spaces:
Sleeping
Sleeping
| <html> | |
| <head> | |
| <title>Batch Prediction - Amazon Review Sentiment Analysis</title> | |
| <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> | |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet"> | |
| <style> | |
| :root { | |
| --color-teal: #5BA082; | |
| --color-lime: #9DC25C; | |
| --color-orange: #D18B5C; | |
| --color-pink: #D29BB5; | |
| --color-beige: #BFB5A0; | |
| --color-rose: #D5658D; | |
| --color-sage: #A3A899; | |
| --color-charcoal: #5B5958; | |
| --color-mint: #A8DCC1; | |
| --color-seafoam: #8EC4B3; | |
| } | |
| body { | |
| background: linear-gradient(135deg, var(--color-teal) 0%, var(--color-sage) 30%, var(--color-beige) 70%); | |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
| min-height: 100vh; | |
| } | |
| .main-container { | |
| display: flex; | |
| justify-content: center; | |
| align-items: flex-start; | |
| min-height: 100vh; | |
| padding: 20px; | |
| } | |
| .prediction-card { | |
| background: rgba(255,255,255,0.95); | |
| border-radius: 24px; | |
| padding: 40px; | |
| width: 100%; | |
| max-width: 950px; | |
| box-shadow: 0 20px 50px rgba(0,0,0,0.1); | |
| } | |
| .main-title { font-size: 2.5rem; font-weight: 700; color: var(--color-teal); } | |
| .subtitle { color: var(--color-charcoal); font-size: 1.2rem; } | |
| .upload-zone { | |
| border: 2px dashed var(--color-sage); | |
| border-radius: 20px; | |
| padding: 40px; | |
| text-align: center; | |
| margin-bottom: 20px; | |
| } | |
| .upload-zone:hover { border-color: var(--color-teal); background: rgba(91,160,130,0.05); } | |
| .file-name { | |
| font-weight: 700; | |
| color: var(--color-teal); | |
| margin-top: 12px; | |
| display: inline-block; | |
| } | |
| .submit-btn { | |
| background: var(--color-teal); border: none; color: white; | |
| padding: 16px; border-radius: 50px; font-size: 1.2rem; | |
| font-weight: 700; width: 100%; | |
| } | |
| .confidence-bar { height: 8px; border-radius: 4px; overflow: hidden; margin-top: 5px; } | |
| .confidence-fill { height: 100%; } | |
| .confidence-fill.positive { background: linear-gradient(90deg,var(--color-mint),var(--color-teal)); } | |
| .confidence-fill.negative { background: linear-gradient(90deg,var(--color-rose),var(--color-pink)); } | |
| .confidence-fill.neutral { background: linear-gradient(90deg,var(--color-sage),var(--color-beige)); } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="main-container"> | |
| <div class="prediction-card"> | |
| <div class="text-center mb-4"> | |
| <h1 class="main-title">TranSenti</h1> | |
| <p class="subtitle">Upload multiple reviews for sentiment analysis</p> | |
| </div> | |
| <!-- Error / Success Messages --> | |
| {% if error %} | |
| <div class="alert alert-danger" id="errorMessage"> | |
| <i class="fas fa-exclamation-circle"></i> {{ error }} | |
| </div> | |
| {% endif %} | |
| <div class="alert alert-danger" id="errorMessage" style="display:none;"> | |
| <i class="fas fa-exclamation-circle"></i> Invalid file format. Please upload a .csv file. | |
| </div> | |
| {% if results %} | |
| <div class="alert alert-success"> | |
| <i class="fas fa-check-circle"></i> File processed successfully! | |
| </div> | |
| {% endif %} | |
| <!-- Upload Form --> | |
| <form method="POST" enctype="multipart/form-data" id="uploadForm"> | |
| <div class="upload-zone" id="uploadZone"> | |
| <i class="fas fa-cloud-upload-alt fa-3x text-success"></i> | |
| <p class="mt-2">Drop your CSV file here or click to browse</p> | |
| <input type="file" name="csvfile" class="file-input" accept=".csv" required id="fileInput" style="display:none;"> | |
| <label for="fileInput" class="btn btn-outline-success mt-2">Choose File</label> | |
| <div class="file-name" id="fileName" style="display:none;"></div> | |
| </div> | |
| <button type="submit" class="submit-btn"> | |
| <i class="fas fa-brain"></i> Analyze Sentiment | |
| </button> | |
| </form> | |
| <!-- Results Table --> | |
| {% if results %} | |
| <div class="mt-5"> | |
| <h4 class="text-center mb-4" style="color: var(--color-teal); font-weight:700;">Prediction Results</h4> | |
| <div class="table-responsive"> | |
| <table class="table table-bordered table-hover align-middle"> | |
| <thead class="table-success"> | |
| <tr> | |
| <th>Review</th> | |
| <th>Sentiment</th> | |
| <th>Confidence</th> | |
| <th>Model Used</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| {% for r in results %} | |
| <tr> | |
| <td>{{ r.text }}</td> | |
| <td> | |
| {% if r.sentiment.lower().startswith("positive") %} | |
| <span class="badge bg-success">{{ r.sentiment }}</span> | |
| {% elif r.sentiment.lower().startswith("negative") %} | |
| <span class="badge bg-danger">{{ r.sentiment }}</span> | |
| {% else %} | |
| <span class="badge bg-secondary">{{ r.sentiment }}</span> | |
| {% endif %} | |
| </td> | |
| <td> | |
| <span>{{ r.confidence }}%</span> | |
| <div class="confidence-bar"> | |
| <div class="confidence-fill {{ r.sentiment.lower() }}" style="width: {{ r.confidence }}%"></div> | |
| </div> | |
| </td> | |
| <td> | |
| <i class="fas fa-robot text-muted"></i> {{ r.chosen_model }} | |
| </td> | |
| </tr> | |
| {% endfor %} | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| {% endif %} | |
| <!-- Back Button --> | |
| <div class="text-center mt-4"> | |
| <a href="{{ url_for('single_review') }}" class="btn btn-outline-secondary"> | |
| <i class="fas fa-arrow-left"></i> Back to Single Prediction | |
| </a> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| const fileInput = document.getElementById("fileInput"); | |
| const fileName = document.getElementById("fileName"); | |
| const errorMessage = document.getElementById("errorMessage"); | |
| fileInput.addEventListener("change", () => { | |
| const file = fileInput.files[0]; | |
| if (file && file.name.endsWith(".csv")) { | |
| fileName.textContent = file.name; | |
| fileName.style.display = "block"; | |
| errorMessage.style.display = "none"; | |
| } else { | |
| fileInput.value = ""; | |
| fileName.style.display = "none"; | |
| errorMessage.style.display = "block"; | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> | |