rahul-02 commited on
Commit
522a147
·
verified ·
1 Parent(s): 942df2a

flask-files

Browse files
Files changed (5) hide show
  1. Dockerfile +21 -0
  2. README.md +25 -11
  3. app.py +65 -0
  4. requirements.txt +3 -0
  5. templates/index.html +142 -0
Dockerfile ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 1. Use an official Python image
2
+ FROM python:3.9-slim
3
+
4
+ # 2. Set the working directory inside the container
5
+ WORKDIR /app
6
+
7
+ # 3. Copy only the requirements first (better for speed)
8
+ COPY requirements.txt .
9
+
10
+ # 4. Install the libraries
11
+ RUN pip install --no-cache-dir -r requirements.txt
12
+
13
+ # 5. Copy the rest of your code (app.py and templates folder)
14
+ COPY . .
15
+
16
+ # 6. Tell Hugging Face to use port 7860
17
+ ENV PORT=7860
18
+ EXPOSE 7860
19
+
20
+ # 7. Start the Flask app
21
+ CMD ["python", "app.py"]
README.md CHANGED
@@ -1,11 +1,25 @@
1
- ---
2
- title: Text Summarizer AI
3
- emoji: 🐠
4
- colorFrom: yellow
5
- colorTo: yellow
6
- sdk: docker
7
- pinned: false
8
- license: apache-2.0
9
- ---
10
-
11
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: AI Text Summarizer
3
+ emoji: 📝
4
+ colorFrom: blue
5
+ colorTo: purple
6
+ sdk: docker
7
+ app_port: 7860
8
+ pinned: false
9
+ ---
10
+ # AI Text Summarizer (Bart-Large)
11
+ An intelligent, web-based application that leverages Transformer-based Deep Learning to transform long, complex articles into concise, meaningful summaries. This project uses the facebook/bart-large-cnn model to provide high-quality, abstractive summarization.
12
+
13
+ ### Overview :-
14
+ Reading through massive blocks of text is time-consuming. This tool aims to solve the "Information Overload" problem by providing a user-friendly interface where users can paste up to 1024 words and receive a human-like summary in seconds.
15
+
16
+ Unlike basic extractive summarizers that just copy sentences, this app uses Abstractive Summarization, meaning the AI understands the context and "rewrites" the summary in its own words.
17
+
18
+ ### Key Features :-
19
+ Deep Learning Backend: Powered by the 1.6GB BART-Large model for superior accuracy.
20
+
21
+ Intelligent Post-Processing: Custom Python logic to handle sentence capitalization and proper noun preservation (e.g., keeping "James Webb" capitalized).
22
+
23
+ Dynamic Summary Length: Forced minimum word counts to ensure summaries are detailed and informative rather than just one-liners.
24
+
25
+ Modern Web UI: A clean, responsive interface built with Flask and CSS.
app.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from flask import Flask, render_template, request, jsonify
3
+ from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
4
+
5
+ app = Flask(__name__)
6
+
7
+ MODEL_NAME = "facebook/bart-large-cnn"
8
+
9
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
10
+ model = AutoModelForSeq2SeqLM.from_pretrained(MODEL_NAME)
11
+
12
+ @app.route('/')
13
+ def index():
14
+ return render_template('index.html')
15
+
16
+ @app.route('/summarize', methods=['POST'])
17
+ def summarize():
18
+ try:
19
+ data = request.get_json()
20
+ text = data.get('text', '').strip()
21
+
22
+ if not text or len(text.split()) < 15:
23
+ return jsonify({'error': 'Text too short.'}), 400
24
+
25
+ inputs = tokenizer(text, return_tensors="pt", max_length=1024, truncation=True)
26
+
27
+ summary_ids = model.generate(
28
+ inputs["input_ids"],
29
+ max_length=300,
30
+ min_length=150,
31
+ length_penalty=2.5,
32
+ num_beams=5,
33
+ no_repeat_ngram_size=3,
34
+ early_stopping=False
35
+ )
36
+
37
+ summary = tokenizer.decode(summary_ids[0], skip_special_tokens=True)
38
+
39
+ # --- SAFE CLEANING LOGIC ---
40
+ # 1. Fix punctuation spacing
41
+ summary = summary.replace(" .", ".").replace(" ,", ",").replace(" !", "!").replace(" ?", "?")
42
+
43
+ # 2. Capitalize ONLY the first letter of each sentence
44
+ # This prevents "James Webb" from becoming "James webb"
45
+ parts = summary.split(". ")
46
+ cleaned_sentences = []
47
+ for p in parts:
48
+ p = p.strip()
49
+ if p:
50
+ # Upcase only index 0, keep everything else exactly as the AI wrote it
51
+ sentence = p[0].upper() + p[1:]
52
+ cleaned_sentences.append(sentence)
53
+
54
+ summary = ". ".join(cleaned_sentences)
55
+
56
+ if summary and not summary.endswith('.'):
57
+ summary += '.'
58
+
59
+ return jsonify({'summary': summary})
60
+
61
+ except Exception as e:
62
+ return jsonify({'error': str(e)}), 500
63
+
64
+ if __name__ == '__main__':
65
+ app.run(host='0.0.0.0', port=7860)
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ flask
2
+ transformers
3
+ torch --index-url https://download.pytorch.org/whl/cpu
templates/index.html ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>SummAI | Professional Text Summarizer</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
9
+ </head>
10
+ <body class="bg-gray-50 text-gray-900 font-sans leading-normal tracking-normal">
11
+
12
+ <nav class="bg-white shadow-sm border-b border-gray-200 py-4 px-6">
13
+ <div class="max-w-7xl mx-auto flex justify-between items-center">
14
+ <div class="flex items-center space-x-2">
15
+ <i class="fa-solid font-bold text-indigo-600 text-2xl"></i>
16
+ <span class="text-xl font-extrabold tracking-tight text-gray-800">Summ<span class="text-indigo-600">AI</span></span>
17
+ </div>
18
+ <div class="hidden md:flex space-x-6 text-sm font-medium text-gray-500">
19
+ <span class="hover:text-indigo-600 cursor-pointer">Abstractive AI</span>
20
+ <span class="hover:text-indigo-600 cursor-pointer">BART Model</span>
21
+ </div>
22
+ </div>
23
+ </nav>
24
+
25
+ <main class="max-w-6xl mx-auto py-12 px-4 sm:px-6 lg:px-8">
26
+ <div class="text-center mb-12">
27
+ <h1 class="text-4xl font-extrabold text-gray-900 sm:text-5xl">
28
+ Summarize content in <span class="text-indigo-600">seconds.</span>
29
+ </h1>
30
+ <p class="mt-4 text-lg text-gray-600 max-w-2xl mx-auto">
31
+ Paste long articles, research papers, or reports and let our AI provide a professional-grade summary instantly.
32
+ </p>
33
+ </div>
34
+
35
+ <div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
36
+
37
+ <div class="bg-white rounded-2xl shadow-xl p-6 border border-gray-100">
38
+ <div class="flex items-center justify-between mb-4">
39
+ <h3 class="text-lg font-bold text-gray-800">Original Text</h3>
40
+ <span id="charCount" class="text-xs text-gray-400 font-medium">0 words</span>
41
+ </div>
42
+ <textarea id="inputText"
43
+ class="w-full h-80 p-4 bg-gray-50 border border-gray-200 rounded-xl focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition resize-none placeholder-gray-400"
44
+ placeholder="Paste your text here (minimum 20 words for best results)..."></textarea>
45
+
46
+ <button id="sumBtn" onclick="summarize()"
47
+ class="mt-6 w-full bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-4 rounded-xl transition-all duration-200 flex items-center justify-center space-x-2 shadow-lg shadow-indigo-200">
48
+ <i class="fa-solid fa-wand-sparkles"></i>
49
+ <span>Generate Summary</span>
50
+ </button>
51
+ </div>
52
+
53
+ <div class="bg-white rounded-2xl shadow-xl p-6 border border-gray-100 flex flex-col">
54
+ <div class="flex items-center justify-between mb-4">
55
+ <h3 class="text-lg font-bold text-gray-800">AI Summary</h3>
56
+ <button onclick="copyToClipboard()" class="text-indigo-600 hover:text-indigo-800 text-sm font-semibold flex items-center space-x-1">
57
+ <i class="fa-regular fa-copy"></i>
58
+ <span>Copy</span>
59
+ </button>
60
+ </div>
61
+
62
+ <div id="outputBox" class="flex-grow w-full h-80 p-4 bg-indigo-50/30 border-2 border-dashed border-indigo-100 rounded-xl overflow-y-auto">
63
+ <p id="outputPlaceholder" class="text-gray-400 italic">Your summary will appear here after processing...</p>
64
+ <p id="outputText" class="text-gray-700 hidden leading-relaxed"></p>
65
+ </div>
66
+
67
+ <div id="statusMessage" class="mt-4 text-sm text-gray-500 flex items-center space-x-2 opacity-0 transition-opacity">
68
+ <i class="fa-solid fa-circle-notch fa-spin text-indigo-600"></i>
69
+ <span>AI is thinking...</span>
70
+ </div>
71
+ </div>
72
+ </div>
73
+ </main>
74
+
75
+ <footer class="mt-12 py-8 text-center text-gray-400 text-sm border-t border-gray-100">
76
+ &copy; 2026 SummAI. Powered by Hugging Face Transformers.
77
+ </footer>
78
+
79
+ <script>
80
+ // Word counter logic
81
+ document.getElementById('inputText').addEventListener('input', function() {
82
+ const words = this.value.trim().split(/\s+/).filter(x => x.length > 0).length;
83
+ document.getElementById('charCount').innerText = `${words} words`;
84
+ });
85
+
86
+ async function summarize() {
87
+ const inputText = document.getElementById('inputText').value;
88
+ const outputText = document.getElementById('outputText');
89
+ const outputPlaceholder = document.getElementById('outputPlaceholder');
90
+ const statusMessage = document.getElementById('statusMessage');
91
+ const btn = document.getElementById('sumBtn');
92
+
93
+ if (inputText.split(/\s+/).length < 20) {
94
+ alert("Please enter at least 20 words for a meaningful summary.");
95
+ return;
96
+ }
97
+
98
+ // Start Loading State
99
+ btn.disabled = true;
100
+ btn.classList.add('opacity-50', 'cursor-not-allowed');
101
+ statusMessage.classList.add('opacity-100');
102
+ outputPlaceholder.innerText = "Analyzing text and generating summary...";
103
+ outputText.classList.add('hidden');
104
+
105
+ try {
106
+ const response = await fetch('/summarize', {
107
+ method: 'POST',
108
+ headers: { 'Content-Type': 'application/json' },
109
+ body: JSON.stringify({ text: inputText })
110
+ });
111
+
112
+ const data = await response.json();
113
+
114
+ if (response.ok) {
115
+ outputText.innerText = data.summary;
116
+ outputText.classList.remove('hidden');
117
+ outputPlaceholder.classList.add('hidden');
118
+ } else {
119
+ alert(data.error || "An error occurred");
120
+ outputPlaceholder.innerText = "Summary failed. Please try again.";
121
+ }
122
+ } catch (error) {
123
+ console.error("Error:", error);
124
+ alert("Failed to connect to the server.");
125
+ } finally {
126
+ // End Loading State
127
+ btn.disabled = false;
128
+ btn.classList.remove('opacity-50', 'cursor-not-allowed');
129
+ statusMessage.classList.remove('opacity-100');
130
+ }
131
+ }
132
+
133
+ function copyToClipboard() {
134
+ const text = document.getElementById('outputText').innerText;
135
+ if (!text) return;
136
+ navigator.clipboard.writeText(text).then(() => {
137
+ alert("Summary copied to clipboard!");
138
+ });
139
+ }
140
+ </script>
141
+ </body>
142
+ </html>