Spaces:
Running
Running
Download index.html from SamuelWHS/TextSummarizer: direct link, hf CLI and curl.
- Browser
- Download file 13.3 kB
-
https://huggingface.co/spaces/SamuelWHS/TextSummarizer/resolve/main/index.html
- Command line
-
hf download hf://spaces/SamuelWHS/TextSummarizer/index.html
-
curl -L -o index.html https://huggingface.co/spaces/SamuelWHS/TextSummarizer/resolve/main/index.html
13.3 kB
| <!-- <!doctype html> | |
| <html> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <meta name="viewport" content="width=device-width" /> | |
| <title>My static Space</title> | |
| <link rel="stylesheet" href="style.css" /> | |
| </head> | |
| <body> | |
| <div class="card"> | |
| <h1>Welcome to your static Space!</h1> | |
| <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p> | |
| <p> | |
| Also don't forget to check the | |
| <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>. | |
| </p> | |
| </div> | |
| </body> | |
| </html> --> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| <title>AI Text Summarization</title> | |
| <style> | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| body { | |
| font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif; | |
| background: #f5f5f5; | |
| min-height: 100vh; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| padding: 20px; | |
| } | |
| .card { | |
| background: white; | |
| border-radius: 8px; | |
| padding: 32px 40px; | |
| max-width: 680px; | |
| width: 100%; | |
| box-shadow: 0 1px 3px rgba(0,0,0,0.08); | |
| border: 1px solid #e8e8e8; | |
| } | |
| h1 { | |
| color: #1a1a1a; | |
| font-size: 1.6rem; | |
| font-weight: 600; | |
| margin-bottom: 4px; | |
| letter-spacing: -0.3px; | |
| } | |
| .subtitle { | |
| color: #666; | |
| font-size: 0.9rem; | |
| margin-bottom: 24px; | |
| padding-bottom: 16px; | |
| border-bottom: 1px solid #eee; | |
| font-weight: 400; | |
| } | |
| .model-status { | |
| margin: -8px 0 20px 0; | |
| padding: 8px 0; | |
| font-size: 0.85rem; | |
| color: #2d7a3a; | |
| font-weight: 400; | |
| } | |
| .model-status.loading { | |
| color: #b45309; | |
| } | |
| .model-status.error { | |
| color: #b91c1c; | |
| } | |
| .input-group { | |
| margin-bottom: 16px; | |
| } | |
| .input-group label { | |
| display: block; | |
| font-weight: 500; | |
| color: #333; | |
| margin-bottom: 6px; | |
| font-size: 0.9rem; | |
| } | |
| textarea { | |
| width: 100%; | |
| padding: 10px 12px; | |
| border: 1px solid #d0d0d0; | |
| border-radius: 4px; | |
| font-size: 14px; | |
| font-family: inherit; | |
| resize: vertical; | |
| transition: border-color 0.2s; | |
| min-height: 120px; | |
| background: white; | |
| color: #333; | |
| line-height: 1.5; | |
| } | |
| textarea:focus { | |
| outline: none; | |
| border-color: #4a6cf7; | |
| } | |
| textarea::placeholder { | |
| color: #999; | |
| } | |
| .output-group { | |
| margin-bottom: 16px; | |
| } | |
| .output-group label { | |
| display: block; | |
| font-weight: 500; | |
| color: #333; | |
| margin-bottom: 6px; | |
| font-size: 0.9rem; | |
| } | |
| #outputText { | |
| background: #fafafa; | |
| padding: 10px 12px; | |
| border-radius: 4px; | |
| min-height: 80px; | |
| border: 1px solid #e8e8e8; | |
| color: #333; | |
| white-space: pre-wrap; | |
| word-wrap: break-word; | |
| font-size: 14px; | |
| line-height: 1.5; | |
| } | |
| #outputText .placeholder { | |
| color: #999; | |
| } | |
| #outputText.error { | |
| color: #b91c1c; | |
| } | |
| #outputText.loading { | |
| color: #4a6cf7; | |
| } | |
| .button-group { | |
| display: flex; | |
| gap: 10px; | |
| margin-top: 4px; | |
| } | |
| button { | |
| padding: 8px 24px; | |
| border-radius: 4px; | |
| font-size: 14px; | |
| font-weight: 500; | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| border: 1px solid transparent; | |
| background: transparent; | |
| } | |
| .submit-btn { | |
| background: #4a6cf7; | |
| color: white; | |
| border-color: #4a6cf7; | |
| order: 2; | |
| margin-left: auto; | |
| } | |
| .submit-btn:hover:not(:disabled) { | |
| background: #3b5de7; | |
| border-color: #3b5de7; | |
| } | |
| .submit-btn:disabled { | |
| background: #a0aec0; | |
| border-color: #a0aec0; | |
| cursor: not-allowed; | |
| } | |
| .clear-btn { | |
| color: #4a5568; | |
| border-color: #d0d0d0; | |
| background: white; | |
| order: 1; | |
| } | |
| .clear-btn:hover:not(:disabled) { | |
| background: #f7fafc; | |
| border-color: #a0aec0; | |
| } | |
| .clear-btn:disabled { | |
| opacity: 0.5; | |
| cursor: not-allowed; | |
| } | |
| .token-info { | |
| margin-top: 8px; | |
| font-size: 0.8rem; | |
| color: #999; | |
| text-align: right; | |
| } | |
| @media (max-width: 600px) { | |
| .card { | |
| padding: 20px; | |
| } | |
| h1 { | |
| font-size: 1.3rem; | |
| } | |
| .button-group { | |
| flex-wrap: wrap; | |
| } | |
| .submit-btn { | |
| flex: 1; | |
| } | |
| .clear-btn { | |
| flex: 0.4; | |
| min-width: 80px; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="card"> | |
| <h1>AI Text summarization</h1> | |
| <div class="subtitle">Powered by FalconsAI T5 Sequence-to-Sequence model.</div> | |
| <!-- Model status - styled to blend in, not stand out --> | |
| <div id="modelStatus" class="model-status loading">β³ Loading model...</div> | |
| <div class="input-group"> | |
| <label for="inputText">Input text to summarize:</label> | |
| <textarea | |
| id="inputText" | |
| rows="6" | |
| placeholder="Paste document text here..." | |
| ></textarea> | |
| </div> | |
| <div class="output-group"> | |
| <label for="outputText">Summarized text:</label> | |
| <div id="outputText"><span class="placeholder">Your summary will appear here...</span></div> | |
| <div id="tokenInfo" class="token-info"></div> | |
| </div> | |
| <div class="button-group"> | |
| <button id="clearButton" class="clear-btn" disabled>Clear</button> | |
| <button id="summarizeButton" class="submit-btn" disabled>Submit</button> | |
| </div> | |
| </div> | |
| <!-- Use the official @huggingface/transformers import map --> | |
| <script type="importmap"> | |
| { | |
| "imports": { | |
| "@huggingface/transformers": "https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.0.0/dist/transformers.min.js" | |
| } | |
| } | |
| </script> | |
| <script type="module"> | |
| import { pipeline } from '@huggingface/transformers'; | |
| // DOM elements | |
| const inputText = document.getElementById('inputText'); | |
| const outputText = document.getElementById('outputText'); | |
| const tokenInfo = document.getElementById('tokenInfo'); | |
| const summarizeBtn = document.getElementById('summarizeButton'); | |
| const clearBtn = document.getElementById('clearButton'); | |
| const modelStatus = document.getElementById('modelStatus'); | |
| // Initialize the summarization pipeline | |
| let summarizer = null; | |
| let isModelReady = false; | |
| async function initModel() { | |
| try { | |
| modelStatus.textContent = 'β³ Loading model...'; | |
| modelStatus.className = 'model-status loading'; | |
| summarizeBtn.disabled = true; | |
| clearBtn.disabled = true; | |
| summarizer = await pipeline( | |
| 'summarization', | |
| 'onnx-community/text_summarization-ONNX' | |
| ); | |
| isModelReady = true; | |
| modelStatus.textContent = 'β Model loaded successfully! Ready to summarize.'; | |
| modelStatus.className = 'model-status'; | |
| summarizeBtn.disabled = false; | |
| clearBtn.disabled = false; | |
| console.log('β FalconsAI summarization model loaded successfully!'); | |
| } catch (error) { | |
| console.error('Failed to load model:', error); | |
| modelStatus.textContent = 'β Failed to load model. Please refresh the page.'; | |
| modelStatus.className = 'model-status error'; | |
| summarizeBtn.disabled = true; | |
| clearBtn.disabled = true; | |
| outputText.textContent = 'Failed to load the summarization model. Please refresh the page.'; | |
| outputText.className = 'error'; | |
| } | |
| } | |
| // Main summarize function - MATCHES PYTHON APP.PY DEFAULTS | |
| async function summarize() { | |
| if (!isModelReady || !summarizer) { | |
| outputText.textContent = 'Model is still loading. Please wait...'; | |
| outputText.className = 'error'; | |
| return; | |
| } | |
| const text = inputText.value.trim(); | |
| // Check if input is empty or only whitespace | |
| if (!text) { | |
| outputText.textContent = 'Please enter document text to summarize.'; | |
| outputText.className = 'error'; | |
| tokenInfo.textContent = ''; | |
| return; | |
| } | |
| // Approximate token count using words | |
| const inputTokens = text.split(/\s+/).length; | |
| // Check if word count is less than 5 | |
| if (inputTokens < 5) { | |
| outputText.textContent = 'Insufficient text to summarize.'; | |
| outputText.className = 'error'; | |
| tokenInfo.textContent = `Input tokens: ${inputTokens}`; | |
| return; | |
| } | |
| // Show loading state | |
| outputText.textContent = 'Summarizing...'; | |
| outputText.className = 'loading'; | |
| summarizeBtn.disabled = true; | |
| tokenInfo.textContent = ''; | |
| try { | |
| // Proceed with summarization - MATCH PYTHON DEFAULTS | |
| const result = await summarizer(text, { | |
| truncation: true, | |
| max_length: 200, // Python default: 200 | |
| min_length: 50, // Python default: 50 | |
| do_sample: false, // Python default: False | |
| num_beams: 4, // Python default: 4 beams | |
| early_stopping: true | |
| }); | |
| // Get summary text | |
| const summaryText = result[0].summary_text; | |
| // Calculate output tokens (approximate using word count) | |
| const outputTokens = summaryText.split(/\s+/).length; | |
| // Debug print statement (visible in browser console) | |
| console.log(`Input tokens: ${inputTokens}, Output tokens: ${outputTokens}`); | |
| // Update UI | |
| outputText.textContent = summaryText; | |
| outputText.className = ''; | |
| tokenInfo.textContent = `Input tokens: ${inputTokens} | Output tokens: ${outputTokens}`; | |
| } catch (error) { | |
| console.error('Summarization error:', error); | |
| outputText.textContent = `An error occurred: ${error.message || 'Unknown error'}`; | |
| outputText.className = 'error'; | |
| } finally { | |
| summarizeBtn.disabled = false; | |
| } | |
| } | |
| // Clear function | |
| function clearAll() { | |
| inputText.value = ''; | |
| outputText.innerHTML = '<span class="placeholder">Your summary will appear here...</span>'; | |
| outputText.className = ''; | |
| tokenInfo.textContent = ''; | |
| } | |
| // Event listeners | |
| summarizeBtn.addEventListener('click', summarize); | |
| clearBtn.addEventListener('click', clearAll); | |
| // Allow Ctrl+Enter to summarize (same as your Python version) | |
| inputText.addEventListener('keydown', (e) => { | |
| if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) { | |
| e.preventDefault(); | |
| summarize(); | |
| } | |
| }); | |
| // Initialize the model when the page loads | |
| console.log('π Loading FalconsAI summarization model...'); | |
| initModel(); | |
| </script> | |
| </body> | |
| </html> |