Spaces:
Runtime error
Runtime error
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>BioGPT HoC Inference</title> | |
| <!-- Load Tailwind CSS --> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <!-- Include Inter font --> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet"> | |
| <style> | |
| body { | |
| font-family: 'Inter', sans-serif; | |
| } | |
| .hallmark-badge { | |
| display: inline-block; | |
| padding: 0.3rem 0.6rem; | |
| margin: 0.2rem; | |
| border-radius: 0.5rem; /* Rounded corners */ | |
| font-size: 0.8rem; | |
| line-height: 1rem; | |
| font-weight: 500; | |
| cursor: default; | |
| transition: background-color 0.2s ease-in-out; | |
| border: 1px solid transparent; | |
| } | |
| /* Color definitions (same as before) */ | |
| .hallmark-color-0 { background-color: #EFF6FF; color: #1E40AF; border-color: #BEE3F8; } /* Blue */ | |
| .hallmark-color-1 { background-color: #ECFDF5; color: #065F46; border-color: #A7F3D0; } /* Green */ | |
| .hallmark-color-2 { background-color: #FFFBEB; color: #92400E; border-color: #FDE68A; } /* Yellow */ | |
| .hallmark-color-3 { background-color: #FEF2F2; color: #991B1B; border-color: #FECACA; } /* Red */ | |
| .hallmark-color-4 { background-color: #F5F3FF; color: #5B21B6; border-color: #DDD6FE; } /* Purple */ | |
| .hallmark-color-5 { background-color: #FDF2F8; color: #9D174D; border-color: #FBCFE8; } /* Pink */ | |
| .hallmark-color-6 { background-color: #EEF2FF; color: #3730A3; border-color: #C7D2FE; } /* Indigo */ | |
| .hallmark-color-7 { background-color: #F0FDFA; color: #134E4A; border-color: #99F6E4; } /* Teal */ | |
| .hallmark-color-8 { background-color: #FFF7ED; color: #9A3412; border-color: #FED7AA; } /* Orange */ | |
| .hallmark-color-9 { background-color: #F9FAFB; color: #374151; border-color: #E5E7EB; } /* Gray */ | |
| /* Loading Spinner */ | |
| .spinner { | |
| border: 4px solid rgba(0, 0, 0, 0.1); | |
| width: 36px; | |
| height: 36px; | |
| border-radius: 50%; | |
| border-left-color: #4f46e5; /* Indigo */ | |
| animation: spin 1s ease infinite; | |
| margin: 20px auto; | |
| } | |
| @keyframes spin { | |
| 0% { transform: rotate(0deg); } | |
| 100% { transform: rotate(360deg); } | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-100 min-h-screen flex flex-col items-center justify-center p-4 sm:p-6"> | |
| <div class="bg-white p-6 sm:p-8 rounded-lg shadow-xl w-full max-w-2xl space-y-6"> | |
| <!-- Header --> | |
| <div class="text-center border-b pb-4"> | |
| <h1 class="text-2xl sm:text-3xl font-bold text-gray-800 mb-1">BioGPT HoC Inference</h1> | |
| <h2 class="text-md sm:text-lg font-semibold text-blue-700 mb-2">~27M Parameter Finetuned SLM</h2> | |
| <p class="text-sm text-gray-600 max-w-2xl mx-auto"> | |
| Enter a biomedical abstract below to predict Hallmarks of Cancer labels using the finetuned model. | |
| </p> | |
| </div> | |
| <!-- Input Area --> | |
| <div> | |
| <label for="abstract-input" class="block text-sm font-medium text-gray-700 mb-1">Enter Abstract Text:</label> | |
| <textarea id="abstract-input" rows="8" class="w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition duration-150 ease-in-out shadow-sm" placeholder="Paste or type abstract here..."></textarea> | |
| </div> | |
| <!-- Predict Button --> | |
| <div class="text-center"> | |
| <button id="predict-button" class="bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2.5 px-8 rounded-lg transition duration-150 ease-in-out shadow-md hover:shadow-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed"> | |
| Predict Hallmarks | |
| </button> | |
| </div> | |
| <!-- Results Area --> | |
| <div id="results-area" class="space-y-3 hidden"> | |
| <div class="border border-green-200 p-4 rounded-lg bg-green-50 shadow-sm min-h-[80px]"> | |
| <h3 class="text-md font-semibold text-green-800 mb-2">Predicted Hallmarks:</h3> | |
| <div id="loading-indicator" class="hidden text-center"> | |
| <div class="spinner"></div> | |
| <p class="text-sm text-gray-600">Predicting...</p> | |
| </div> | |
| <div id="error-message" class="hidden text-center text-red-600 font-medium"> | |
| An error occurred. Please try again. | |
| </div> | |
| <div id="prediction-output"> | |
| <!-- Badges will be inserted here --> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // --- Hallmark Colors (for consistent styling) --- | |
| const hallmarkList = [ // Ensure this matches the list in app.py | |
| "activating invasion and metastasis", "avoiding immune destruction", | |
| "cellular energetics", "enabling replicative immortality", | |
| "evading growth suppressors", "genomic instability and mutation", | |
| "inducing angiogenesis", "resisting cell death", | |
| "sustaining proliferative signaling", "tumor promoting inflammation", | |
| ]; | |
| const hallmarkColors = {}; | |
| hallmarkList.forEach((hallmark, index) => { | |
| hallmarkColors[hallmark] = `hallmark-color-${index % 10}`; | |
| }); | |
| // --- DOM Elements --- | |
| const abstractInput = document.getElementById('abstract-input'); | |
| const predictButton = document.getElementById('predict-button'); | |
| const resultsArea = document.getElementById('results-area'); | |
| const loadingIndicator = document.getElementById('loading-indicator'); | |
| const errorMessage = document.getElementById('error-message'); | |
| const predictionOutput = document.getElementById('prediction-output'); | |
| // --- Event Listener --- | |
| predictButton.addEventListener('click', handlePrediction); | |
| // --- Prediction Logic --- | |
| async function handlePrediction() { | |
| const abstractText = abstractInput.value.trim(); | |
| if (!abstractText) { | |
| alert("Please enter some abstract text."); | |
| return; | |
| } | |
| // --- UI Updates: Start loading --- | |
| predictButton.disabled = true; | |
| resultsArea.classList.remove('hidden'); | |
| predictionOutput.innerHTML = ''; // Clear previous results | |
| errorMessage.classList.add('hidden'); | |
| loadingIndicator.classList.remove('hidden'); | |
| try { | |
| // --- Call the backend API --- | |
| const response = await fetch('/predict', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify({ abstract: abstractText }), | |
| }); | |
| // --- Handle Response --- | |
| loadingIndicator.classList.add('hidden'); // Hide loading indicator | |
| if (!response.ok) { | |
| const errorData = await response.json(); | |
| throw new Error(errorData.error || `HTTP error! status: ${response.status}`); | |
| } | |
| const data = await response.json(); | |
| displayPredictions(data.predictions); | |
| } catch (error) { | |
| console.error('Prediction failed:', error); | |
| loadingIndicator.classList.add('hidden'); | |
| errorMessage.textContent = `Prediction failed: ${error.message}`; | |
| errorMessage.classList.remove('hidden'); | |
| } finally { | |
| predictButton.disabled = false; // Re-enable button | |
| } | |
| } | |
| // --- Display Logic --- | |
| function displayPredictions(predictions) { | |
| predictionOutput.innerHTML = ''; // Clear previous just in case | |
| errorMessage.classList.add('hidden'); | |
| if (predictions && predictions.length > 0) { | |
| predictions.forEach(label => { | |
| const badge = document.createElement('span'); | |
| badge.textContent = label; | |
| const colorClass = hallmarkColors[label] || 'hallmark-color-9'; // Default color | |
| badge.className = `hallmark-badge ${colorClass}`; | |
| predictionOutput.appendChild(badge); | |
| }); | |
| } else { | |
| predictionOutput.innerHTML = '<span class="text-gray-500 italic text-sm">No specific hallmarks predicted for this abstract.</span>'; | |
| } | |
| } | |
| </script> | |
| </body> | |
| </html> | |