SamuelWHS commited on
Commit
e387d27
·
verified ·
1 Parent(s): a6d731a

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +394 -1
index.html CHANGED
@@ -19,7 +19,7 @@
19
  </html>
20
  -->
21
 
22
- <!DOCTYPE html>
23
  <html lang="en">
24
  <head>
25
  <meta charset="utf-8" />
@@ -419,5 +419,398 @@
419
  console.log('🚀 Loading FalconsAI summarization model...');
420
  initModel();
421
  </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
422
  </body>
423
  </html>
 
19
  </html>
20
  -->
21
 
22
+ <!-- <!DOCTYPE html>
23
  <html lang="en">
24
  <head>
25
  <meta charset="utf-8" />
 
419
  console.log('🚀 Loading FalconsAI summarization model...');
420
  initModel();
421
  </script>
422
+ </body>
423
+ </html> -->
424
+
425
+
426
+ <!DOCTYPE html>
427
+ <html lang="en">
428
+ <head>
429
+ <meta charset="UTF-8">
430
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
431
+ <title>AI Text summarization · FalconsAI</title>
432
+ <!-- Font & clean reset -->
433
+ <link rel="preconnect" href="https://fonts.googleapis.com">
434
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
435
+ <link href="https://fonts.googleapis.com/css2?family=Inter:opsz,wght@14..32,400;14..32,500;14..32,600&display=swap" rel="stylesheet">
436
+ <style>
437
+ * {
438
+ margin: 0;
439
+ padding: 0;
440
+ box-sizing: border-box;
441
+ }
442
+
443
+ body {
444
+ background: #f6f8fc;
445
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
446
+ display: flex;
447
+ justify-content: center;
448
+ align-items: center;
449
+ min-height: 100vh;
450
+ margin: 0;
451
+ padding: 1.5rem;
452
+ }
453
+
454
+ .card {
455
+ max-width: 780px;
456
+ width: 100%;
457
+ background: #ffffff;
458
+ border-radius: 28px;
459
+ box-shadow: 0 20px 40px -12px rgba(0, 20, 40, 0.15);
460
+ padding: 2rem 2.25rem 2.5rem;
461
+ transition: all 0.2s ease;
462
+ }
463
+
464
+ /* header */
465
+ .app-header {
466
+ display: flex;
467
+ align-items: center;
468
+ justify-content: space-between;
469
+ margin-bottom: 1.75rem;
470
+ }
471
+
472
+ .app-header h1 {
473
+ font-size: 1.6rem;
474
+ font-weight: 600;
475
+ letter-spacing: -0.02em;
476
+ color: #0b1a33;
477
+ background: linear-gradient(145deg, #0b1a33 0%, #1d3a6f 100%);
478
+ -webkit-background-clip: text;
479
+ -webkit-text-fill-color: transparent;
480
+ background-clip: text;
481
+ }
482
+
483
+ .badge {
484
+ font-size: 0.75rem;
485
+ font-weight: 500;
486
+ background: #eef3fa;
487
+ color: #1f4977;
488
+ padding: 0.3rem 1rem;
489
+ border-radius: 40px;
490
+ letter-spacing: 0.01em;
491
+ white-space: nowrap;
492
+ border: 1px solid rgba(30, 80, 150, 0.08);
493
+ }
494
+
495
+ .badge i {
496
+ font-style: normal;
497
+ background: #d0def0;
498
+ padding: 0.1rem 0.5rem;
499
+ border-radius: 20px;
500
+ margin-left: 0.3rem;
501
+ color: #10345e;
502
+ font-weight: 600;
503
+ }
504
+
505
+ /* input / output sections */
506
+ .section {
507
+ margin-bottom: 1.5rem;
508
+ }
509
+
510
+ .section-label {
511
+ display: flex;
512
+ justify-content: space-between;
513
+ align-items: baseline;
514
+ margin-bottom: 0.4rem;
515
+ }
516
+
517
+ .section-label label {
518
+ font-weight: 500;
519
+ font-size: 0.9rem;
520
+ color: #1f3a5e;
521
+ letter-spacing: -0.01em;
522
+ }
523
+
524
+ .section-label .hint {
525
+ font-size: 0.7rem;
526
+ color: #6e7f96;
527
+ }
528
+
529
+ textarea {
530
+ width: 100%;
531
+ padding: 0.9rem 1.1rem;
532
+ font-family: 'Inter', monospace;
533
+ font-size: 0.95rem;
534
+ border: 1.5px solid #e2e9f2;
535
+ border-radius: 18px;
536
+ background: #fafcff;
537
+ resize: vertical;
538
+ transition: 0.15s ease;
539
+ color: #102133;
540
+ line-height: 1.5;
541
+ }
542
+
543
+ textarea:focus {
544
+ outline: none;
545
+ border-color: #3b7bc9;
546
+ box-shadow: 0 0 0 4px rgba(59, 123, 201, 0.12);
547
+ background: #ffffff;
548
+ }
549
+
550
+ textarea::placeholder {
551
+ color: #9aadc4;
552
+ font-weight: 400;
553
+ font-size: 0.9rem;
554
+ }
555
+
556
+ .output-box {
557
+ background: #fafcff;
558
+ border: 1.5px solid #e2e9f2;
559
+ border-radius: 18px;
560
+ padding: 0.9rem 1.1rem;
561
+ min-height: 5.5rem;
562
+ color: #102133;
563
+ font-size: 0.95rem;
564
+ line-height: 1.5;
565
+ word-wrap: break-word;
566
+ white-space: pre-wrap;
567
+ }
568
+
569
+ .output-box:empty::before {
570
+ content: "Summarized text will appear here";
571
+ color: #9aadc4;
572
+ font-weight: 400;
573
+ }
574
+
575
+ /* action row */
576
+ .actions {
577
+ display: flex;
578
+ gap: 0.75rem;
579
+ justify-content: flex-end;
580
+ margin-top: 0.25rem;
581
+ flex-wrap: wrap;
582
+ }
583
+
584
+ .btn {
585
+ font-family: 'Inter', sans-serif;
586
+ font-weight: 500;
587
+ font-size: 0.9rem;
588
+ padding: 0.6rem 1.8rem;
589
+ border-radius: 60px;
590
+ border: none;
591
+ background: #eef3fa;
592
+ color: #1f3a5e;
593
+ cursor: pointer;
594
+ transition: 0.15s ease;
595
+ box-shadow: 0 2px 4px rgba(0,0,0,0.02);
596
+ letter-spacing: 0.01em;
597
+ }
598
+
599
+ .btn-primary {
600
+ background: #0b1a33;
601
+ color: white;
602
+ box-shadow: 0 4px 8px -2px rgba(11, 26, 51, 0.2);
603
+ }
604
+
605
+ .btn-primary:hover {
606
+ background: #132f55;
607
+ transform: scale(1.01);
608
+ box-shadow: 0 6px 14px -4px rgba(11, 26, 51, 0.25);
609
+ }
610
+
611
+ .btn-secondary:hover {
612
+ background: #dfe8f3;
613
+ }
614
+
615
+ .btn:active {
616
+ transform: scale(0.97);
617
+ }
618
+
619
+ hr {
620
+ border: none;
621
+ border-top: 1px solid #e9eff6;
622
+ margin: 1.2rem 0 0.8rem;
623
+ }
624
+
625
+ .footer-credit {
626
+ font-size: 0.7rem;
627
+ color: #768aa3;
628
+ display: flex;
629
+ justify-content: space-between;
630
+ align-items: center;
631
+ margin-top: 0.5rem;
632
+ }
633
+
634
+ .footer-credit span:last-child {
635
+ background: #eef3fa;
636
+ padding: 0.2rem 0.8rem;
637
+ border-radius: 40px;
638
+ color: #1f4977;
639
+ }
640
+
641
+ /* mimic the image style: clean, airy */
642
+ .app-header h1::after {
643
+ content: "✨";
644
+ font-size: 1.2rem;
645
+ margin-left: 6px;
646
+ -webkit-text-fill-color: initial;
647
+ background: none;
648
+ }
649
+
650
+ /* small tweaks for mobile */
651
+ @media (max-width: 500px) {
652
+ .card { padding: 1.5rem; }
653
+ .app-header { flex-wrap: wrap; gap: 0.5rem; }
654
+ .badge { font-size: 0.65rem; padding: 0.2rem 0.8rem; }
655
+ .btn { padding: 0.5rem 1.2rem; font-size: 0.8rem; }
656
+ }
657
+ </style>
658
+ </head>
659
+ <body>
660
+ <div class="card">
661
+
662
+ <!-- header exactly as in image -->
663
+ <div class="app-header">
664
+ <h1>AI Text summarization</h1>
665
+ <div class="badge">
666
+ ⚡ FalconsAI <i>T5</i>
667
+ </div>
668
+ </div>
669
+
670
+ <!-- input section -->
671
+ <div class="section">
672
+ <div class="section-label">
673
+ <label for="inputText">Input text to summarize</label>
674
+ <span class="hint">paste document text</span>
675
+ </div>
676
+ <textarea id="inputText" rows="6" placeholder="Paste document text here..."></textarea>
677
+ </div>
678
+
679
+ <!-- output section -->
680
+ <div class="section">
681
+ <div class="section-label">
682
+ <label for="outputText">Summarized text</label>
683
+ <span class="hint">result</span>
684
+ </div>
685
+ <div id="outputText" class="output-box" aria-label="Summarized text"></div>
686
+ </div>
687
+
688
+ <!-- action buttons: Clear + Submit (matching image) -->
689
+ <div class="actions">
690
+ <button class="btn btn-secondary" id="clearBtn">Clear</button>
691
+ <button class="btn btn-primary" id="submitBtn">Submit</button>
692
+ </div>
693
+
694
+ <!-- subtle footer (like image description) -->
695
+ <hr>
696
+ <div class="footer-credit">
697
+ <span>Powered by FalconsAI T5 Sequence-to-Sequence model.</span>
698
+ <span>⚡</span>
699
+ </div>
700
+ </div>
701
+
702
+ <script>
703
+ (function() {
704
+ // --- DOM refs ---
705
+ const inputEl = document.getElementById('inputText');
706
+ const outputEl = document.getElementById('outputText');
707
+ const clearBtn = document.getElementById('clearBtn');
708
+ const submitBtn = document.getElementById('submitBtn');
709
+
710
+ // --- helper: update output (with optional status) ---
711
+ function setOutput(text) {
712
+ outputEl.textContent = text;
713
+ }
714
+
715
+ // --- Clear ---
716
+ clearBtn.addEventListener('click', function() {
717
+ inputEl.value = '';
718
+ setOutput(''); // clear summarized text
719
+ // placeholder-like empty state is handled by CSS :empty
720
+ });
721
+
722
+ // --- Submit: call gradio endpoint via fetch ---
723
+ // The gradio backend runs at the same origin (spaces) and exposes /api/predict or /run/predict
724
+ // With gradio 3.x/4.x default is /run/predict?
725
+ // We'll try both: first /run/predict (common) then fallback?
726
+ // But most spaces with gradio use /run/predict for the interface.
727
+ // If you have a custom path, adjust. We'll assume default gradio route.
728
+ async function callSummarize(text) {
729
+ // trim and validate
730
+ const trimmed = text.trim();
731
+ if (!trimmed) {
732
+ setOutput('Please enter document text to summarize.');
733
+ return;
734
+ }
735
+
736
+ // client-side token check: approximate word count < 5 → insufficient
737
+ const wordCount = trimmed.split(/\s+/).length;
738
+ if (wordCount < 5) {
739
+ setOutput('Insufficient text to summarize.');
740
+ return;
741
+ }
742
+
743
+ // Prepare payload for Gradio v3/v4:
744
+ // The endpoint is usually /run/predict or /api/predict
745
+ // We'll attempt /run/predict first.
746
+ const payload = {
747
+ data: [trimmed] // the interface has one input
748
+ };
749
+
750
+ try {
751
+ // For Gradio Spaces, the default endpoint is "/run/predict"
752
+ // (or "/api/predict" in newer versions). We'll try /run/predict.
753
+ const resp = await fetch('/run/predict', {
754
+ method: 'POST',
755
+ headers: {
756
+ 'Content-Type': 'application/json',
757
+ },
758
+ body: JSON.stringify(payload),
759
+ });
760
+
761
+ if (!resp.ok) {
762
+ // if 404, try /api/predict (gradio >= 4.0)
763
+ if (resp.status === 404) {
764
+ const resp2 = await fetch('/api/predict', {
765
+ method: 'POST',
766
+ headers: { 'Content-Type': 'application/json' },
767
+ body: JSON.stringify(payload),
768
+ });
769
+ if (!resp2.ok) throw new Error(`API error: ${resp2.status}`);
770
+ const json = await resp2.json();
771
+ // data is usually in json.data array
772
+ if (json && json.data && Array.isArray(json.data) && json.data.length > 0) {
773
+ setOutput(json.data[0]);
774
+ } else {
775
+ setOutput('Unexpected response format from server.');
776
+ }
777
+ return;
778
+ }
779
+ throw new Error(`Server error: ${resp.status}`);
780
+ }
781
+
782
+ const json = await resp.json();
783
+ // response structure: { data: [summary] } for gradio
784
+ if (json && json.data && Array.isArray(json.data) && json.data.length > 0) {
785
+ setOutput(json.data[0]);
786
+ } else {
787
+ setOutput('Unexpected response format.');
788
+ }
789
+ } catch (err) {
790
+ console.error('Summarization error:', err);
791
+ setOutput('Error connecting to summarization service. Please try again.');
792
+ }
793
+ }
794
+
795
+ submitBtn.addEventListener('click', function() {
796
+ const inputText = inputEl.value;
797
+ callSummarize(inputText);
798
+ });
799
+
800
+ // optional: press Enter (Ctrl+Enter) to submit
801
+ inputEl.addEventListener('keydown', function(e) {
802
+ if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
803
+ e.preventDefault();
804
+ submitBtn.click();
805
+ }
806
+ });
807
+
808
+ // on page load, maybe show a placeholder (empty) – but we want it empty.
809
+ // The CSS :empty pseudo-class will show placeholder text.
810
+ // ensure output is empty initially
811
+ setOutput('');
812
+ })();
813
+ </script>
814
+
815
  </body>
816
  </html>