mimi111222 commited on
Commit
5926754
Β·
verified Β·
1 Parent(s): bad2faf

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +599 -0
  2. requirements.txt +6 -3
app.py ADDED
@@ -0,0 +1,599 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from transformers import pipeline
3
+ from nltk.tokenize import sent_tokenize
4
+ import base64
5
+ import torch
6
+ import nltk
7
+ import os
8
+ import tempfile
9
+
10
+
11
+ @st.cache_resource
12
+ def init_nltk():
13
+ # βœ… Use a writable temp directory, not /app
14
+ nltk_data_dir = os.path.join(tempfile.gettempdir(), "nltk_data")
15
+ os.makedirs(nltk_data_dir, exist_ok=True)
16
+
17
+ # βœ… Register this directory for nltk
18
+ if nltk_data_dir not in nltk.data.path:
19
+ nltk.data.path.insert(0, nltk_data_dir)
20
+
21
+ # βœ… Download only required packages
22
+ for pkg in ["punkt"]:
23
+ try:
24
+ nltk.data.find(f"tokenizers/{pkg}")
25
+ except LookupError:
26
+ nltk.download(pkg, download_dir=nltk_data_dir, quiet=True)
27
+
28
+ return True
29
+
30
+ # βœ… Run it once at startup
31
+ init_nltk()
32
+
33
+
34
+
35
+ # Device detection
36
+ DEVICE = 0 if torch.cuda.is_available() else -1
37
+
38
+ # Lazy model loading
39
+ def get_summarizer():
40
+ if 'summarizer' not in st.session_state:
41
+ with st.spinner("🧠 Loading AI Brain..."):
42
+ st.session_state.summarizer = pipeline("summarization", model="sshleifer/distilbart-cnn-12-6", device=DEVICE)
43
+ return st.session_state.summarizer
44
+
45
+ def get_qa():
46
+ if 'qa' not in st.session_state:
47
+ with st.spinner("🧠 Loading AI Brain..."):
48
+ st.session_state.qa = pipeline("question-answering", model="distilbert-base-uncased-distilled-squad", device=DEVICE)
49
+ return st.session_state.qa
50
+
51
+ def get_classifier():
52
+ if 'classifier' not in st.session_state:
53
+ with st.spinner("🧠 Loading AI Brain..."):
54
+ st.session_state.classifier = pipeline("zero-shot-classification", model="typeform/distilbert-base-uncased-mnli", device=DEVICE)
55
+ return st.session_state.classifier
56
+
57
+ @st.cache_resource
58
+ def load_translator(model_name):
59
+ return pipeline("translation", model=model_name, device=DEVICE)
60
+
61
+ def truncate_text(text, max_words=400):
62
+ words = text.split()
63
+ return (" ".join(words[:max_words]), len(words) > max_words)
64
+
65
+ # ULTRA PREMIUM CSS - Glassmorphism + Animations - FIXED HEADER
66
+ st.markdown("""
67
+ <style>
68
+ @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700;900&display=swap');
69
+ * {
70
+ font-family: 'Poppins', sans-serif;
71
+ }
72
+ .stApp {
73
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 25%, #f093fb 50%, #4facfe 75%, #00f2fe 100%);
74
+ background-size: 400% 400%;
75
+ animation: gradientShift 15s ease infinite;
76
+ }
77
+ @keyframes gradientShift {
78
+ 0% { background-position: 0% 50%; }
79
+ 50% { background-position: 100% 50%; }
80
+ 100% { background-position: 0% 50%; }
81
+ }
82
+ /* NEW HEADER - Simple and Visible */
83
+ .hero-header {
84
+ background: linear-gradient(135deg, #1e1e3f 0%, #2d2d5f 100%);
85
+ padding: 3rem 2rem;
86
+ border-radius: 25px;
87
+ margin-bottom: 2rem;
88
+ text-align: center;
89
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
90
+ border: 2px solid #667eea;
91
+ }
92
+
93
+ .hero-title {
94
+ font-size: 3.5rem;
95
+ font-weight: 900;
96
+ color: #ffffff;
97
+ margin: 0 0 1rem 0;
98
+ text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.5);
99
+ }
100
+
101
+ .hero-subtitle {
102
+ font-size: 1.3rem;
103
+ color: #ffffff;
104
+ margin: 0;
105
+ font-weight: 400;
106
+ opacity: 0.95;
107
+ }
108
+ /* Premium Tabs */
109
+ .stTabs [data-baseweb="tab-list"] {
110
+ gap: 12px;
111
+ background: rgba(255, 255, 255, 0.1);
112
+ padding: 12px;
113
+ border-radius: 20px;
114
+ backdrop-filter: blur(10px);
115
+ border: 1px solid rgba(255, 255, 255, 0.2);
116
+ }
117
+ .stTabs [data-baseweb="tab"] {
118
+ background: rgba(255, 255, 255, 0.15);
119
+ border-radius: 15px;
120
+ color: white;
121
+ font-weight: 600;
122
+ font-size: 1.1rem;
123
+ padding: 12px 24px;
124
+ border: 1px solid rgba(255, 255, 255, 0.25);
125
+ transition: all 0.3s ease;
126
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
127
+ }
128
+ .stTabs [data-baseweb="tab"]:hover {
129
+ background: rgba(255, 255, 255, 0.25);
130
+ transform: translateY(-2px);
131
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
132
+ }
133
+ .stTabs [aria-selected="true"] {
134
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
135
+ border-color: rgba(255, 255, 255, 0.4);
136
+ box-shadow: 0 8px 24px rgba(102, 126, 234, 0.4);
137
+ }
138
+ /* Premium Buttons */
139
+ .stButton > button {
140
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
141
+ color: white;
142
+ font-weight: 700;
143
+ font-size: 1.1rem;
144
+ padding: 16px 40px;
145
+ border-radius: 16px;
146
+ border: none;
147
+ box-shadow: 0 8px 24px rgba(102, 126, 234, 0.4);
148
+ transition: all 0.3s ease;
149
+ width: 100%;
150
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
151
+ }
152
+ .stButton > button:hover {
153
+ transform: translateY(-3px);
154
+ box-shadow: 0 12px 36px rgba(102, 126, 234, 0.6);
155
+ background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
156
+ }
157
+ /* Input Fields */
158
+ .stTextArea textarea, .stTextInput input {
159
+ background: rgba(255, 255, 255, 0.2) !important;
160
+ backdrop-filter: blur(10px);
161
+ border: 2px solid rgba(255, 255, 255, 0.3) !important;
162
+ border-radius: 16px !important;
163
+ color: white !important;
164
+ font-size: 1rem !important;
165
+ padding: 16px !important;
166
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
167
+ }
168
+ .stTextArea textarea::placeholder, .stTextInput input::placeholder {
169
+ color: rgba(255, 255, 255, 0.7) !important;
170
+ }
171
+ .stTextArea textarea:focus, .stTextInput input:focus {
172
+ border-color: rgba(255, 255, 255, 0.6) !important;
173
+ box-shadow: 0 0 20px rgba(255, 255, 255, 0.3) !important;
174
+ background: rgba(255, 255, 255, 0.25) !important;
175
+ }
176
+ /* Result Cards */
177
+ .result-card {
178
+ background: rgba(255, 255, 255, 0.95);
179
+ color: #1a1a1a;
180
+ padding: 2rem;
181
+ border-radius: 20px;
182
+ margin: 1rem 0;
183
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
184
+ animation: fadeIn 0.5s ease;
185
+ border-left: 5px solid #667eea;
186
+ }
187
+ .result-card p {
188
+ word-break: break-word;
189
+ overflow-wrap: break-word;
190
+ max-height: 300px;
191
+ overflow-y: auto;
192
+ }
193
+ @keyframes fadeIn {
194
+ from { opacity: 0; transform: translateY(20px); }
195
+ to { opacity: 1; transform: translateY(0); }
196
+ }
197
+ /* Stats Badge */
198
+ .stats-badge {
199
+ display: inline-block;
200
+ background: rgba(255, 255, 255, 0.25);
201
+ backdrop-filter: blur(10px);
202
+ padding: 8px 20px;
203
+ border-radius: 20px;
204
+ color: white;
205
+ font-weight: 600;
206
+ border: 1px solid rgba(255, 255, 255, 0.3);
207
+ margin: 5px;
208
+ text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
209
+ }
210
+ /* Success/Error Messages */
211
+ .stSuccess {
212
+ background: rgba(72, 187, 120, 0.25) !important;
213
+ backdrop-filter: blur(10px);
214
+ border-left: 4px solid #48bb78 !important;
215
+ border-radius: 12px !important;
216
+ color: white !important;
217
+ }
218
+ .stError {
219
+ background: rgba(245, 101, 101, 0.25) !important;
220
+ backdrop-filter: blur(10px);
221
+ border-left: 4px solid #f56565 !important;
222
+ border-radius: 12px !important;
223
+ color: white !important;
224
+ }
225
+ .stInfo {
226
+ background: rgba(66, 153, 225, 0.25) !important;
227
+ backdrop-filter: blur(10px);
228
+ border-left: 4px solid #4299e1 !important;
229
+ border-radius: 12px !important;
230
+ color: white !important;
231
+ }
232
+ /* Sidebar */
233
+ .css-1d391kg, [data-testid="stSidebar"] {
234
+ background: rgba(20, 20, 40, 0.9);
235
+ backdrop-filter: blur(20px);
236
+ border-right: 1px solid rgba(255, 255, 255, 0.2);
237
+ }
238
+ /* Ensure text wraps properly */
239
+ .stTabs h3 {
240
+ word-break: break-word;
241
+ overflow-wrap: anywhere;
242
+ white-space: normal;
243
+ max-width: 100%;
244
+ margin: 0;
245
+ padding: 0.5rem 0;
246
+ color: white;
247
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
248
+ }
249
+ .css-1d391kg h2, [data-testid="stSidebar"] h2 {
250
+ color: white;
251
+ font-weight: 700;
252
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
253
+ }
254
+ .css-1d391kg p, [data-testid="stSidebar"] p {
255
+ color: rgba(255, 255, 255, 0.9);
256
+ }
257
+ /* Spinner */
258
+ .stSpinner > div {
259
+ border-top-color: white !important;
260
+ }
261
+ /* Selectbox */
262
+ .stSelectbox > div > div {
263
+ background: rgba(255, 255, 255, 0.2) !important;
264
+ backdrop-filter: blur(10px);
265
+ border-radius: 12px !important;
266
+ color: white !important;
267
+ border: 2px solid rgba(255, 255, 255, 0.3) !important;
268
+ }
269
+ .stSelectbox label {
270
+ color: white !important;
271
+ font-weight: 600 !important;
272
+ text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
273
+ }
274
+ /* Footer */
275
+ .premium-footer {
276
+ text-align: center;
277
+ padding: 2rem;
278
+ margin-top: 3rem;
279
+ background: rgba(20, 20, 40, 0.85);
280
+ backdrop-filter: blur(15px);
281
+ border-radius: 20px;
282
+ border: 2px solid rgba(255, 255, 255, 0.3);
283
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
284
+ }
285
+ .premium-footer p {
286
+ color: rgba(255, 255, 255, 0.9);
287
+ margin: 0.5rem 0;
288
+ text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
289
+ }
290
+ /* Hide Streamlit Branding */
291
+ #MainMenu {visibility: hidden;}
292
+ footer {visibility: hidden;}
293
+ header {visibility: hidden;}
294
+
295
+ /* Custom scrollbar */
296
+ ::-webkit-scrollbar {
297
+ width: 10px;
298
+ }
299
+ ::-webkit-scrollbar-track {
300
+ background: rgba(255, 255, 255, 0.1);
301
+ }
302
+ ::-webkit-scrollbar-thumb {
303
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
304
+ border-radius: 5px;
305
+ }
306
+ ::-webkit-scrollbar-thumb:hover {
307
+ background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
308
+ }
309
+ </style>
310
+ """, unsafe_allow_html=True)
311
+
312
+ # New Simple Header
313
+ st.markdown("""
314
+ <div class="hero-header">
315
+ <div class="hero-title">🧠 AI Study Helper Pro</div>
316
+ <div class="hero-subtitle">⚑ Supercharge Your Learning with Advanced AI Technology</div>
317
+ </div>
318
+ """, unsafe_allow_html=True)
319
+
320
+ # Sidebar
321
+ with st.sidebar:
322
+ st.markdown("### 🎯 Dashboard")
323
+ st.markdown("---")
324
+
325
+ # Stats
326
+ col1, col2 = st.columns(2)
327
+ with col1:
328
+ st.markdown('<div class="stats-badge">πŸ“Š 247 Processed</div>', unsafe_allow_html=True)
329
+ with col2:
330
+ st.markdown('<div class="stats-badge">⚑ 2.3s Avg</div>', unsafe_allow_html=True)
331
+
332
+ st.markdown("---")
333
+ st.markdown("### ✨ Features")
334
+ features = [
335
+ "πŸ“ AI Summarization",
336
+ "πŸ’¬ Smart Q&A",
337
+ "🎯 Quiz Generator",
338
+ "🌍 Multi-Language",
339
+ "πŸ”‘ Keyword Extraction",
340
+ "πŸ’¨ Lightning Fast"
341
+ ]
342
+ for feat in features:
343
+ st.markdown(f"**{feat}**")
344
+
345
+ st.markdown("---")
346
+ st.markdown("### πŸ‘©β€πŸ’» Developer")
347
+ st.markdown("**Umaima Qureshi**")
348
+ st.markdown("[GitHub](https://github.com/Umaima122)")
349
+
350
+ # Session state
351
+ for key in ["summary", "quiz", "translation", "keywords"]:
352
+ if key not in st.session_state:
353
+ st.session_state[key] = "" if key not in ["quiz", "keywords"] else []
354
+
355
+ # Tabs
356
+ tab1, tab2, tab3, tab4, tab5, tab6 = st.tabs([
357
+ "πŸ“ Summarize", "πŸ’¬ Q&A", "🎯 Quiz", "🌍 Translate", "πŸ”‘ Keywords", "πŸ“₯ Download"
358
+ ])
359
+
360
+ # SUMMARIZE TAB
361
+ with tab1:
362
+ st.markdown("### πŸ“ Intelligent Summarization")
363
+
364
+ text = st.text_area("✍️ Your notes or textbook:", value="", height=250, key="sum_txt",
365
+ placeholder="Paste your content here and watch AI magic happen...")
366
+
367
+ col1, col2, col3 = st.columns([1, 1, 1])
368
+ with col2:
369
+ if st.button("✨ Generate Summary", key="sum_btn"):
370
+ if not text.strip():
371
+ st.error("⚠️ Please provide text to summarize")
372
+ else:
373
+ trunc, was_trunc = truncate_text(text, 400)
374
+ if was_trunc:
375
+ st.info("πŸ“Š Text optimized to 400 words")
376
+
377
+ if len(trunc.split()) < 20:
378
+ st.error("⚠️ Need at least 20 words")
379
+ else:
380
+ with st.spinner("🧠 AI is thinking..."):
381
+ try:
382
+ summarizer = get_summarizer()
383
+ result = summarizer(trunc, max_length=130, min_length=30, do_sample=False, truncation=True)
384
+ summary = result[0]['summary_text']
385
+
386
+ st.markdown(f"""
387
+ <div class="result-card">
388
+ <h4 style="color: #667eea; margin-bottom: 1rem;">πŸ“„ AI-Generated Summary</h4>
389
+ <p style="font-size: 1.1rem; line-height: 1.8; color: #2d3748;">{summary}</p>
390
+ <div style="margin-top: 1rem; padding-top: 1rem; border-top: 1px solid #e2e8f0;">
391
+ <span class="stats-badge" style="background: #667eea; color: white;">
392
+ {len(summary.split())} words
393
+ </span>
394
+ <span class="stats-badge" style="background: #48bb78; color: white;">
395
+ βœ“ Completed
396
+ </span>
397
+ </div>
398
+ </div>
399
+ """, unsafe_allow_html=True)
400
+ st.session_state["summary"] = summary
401
+ except Exception as e:
402
+ st.error(f"❌ Error: {str(e)}")
403
+
404
+ # Q&A TAB
405
+ with tab2:
406
+ st.markdown("### πŸ’¬ Intelligent Q&A System")
407
+
408
+ context = st.text_area("πŸ“š Context (Your notes):", value="", height=200, key="qa_ctx",
409
+ placeholder="Paste your study material here...")
410
+ question = st.text_input("❓ Ask your question:", key="qa_q",
411
+ placeholder="What would you like to know?")
412
+
413
+ col1, col2, col3 = st.columns([1, 1, 1])
414
+ with col2:
415
+ if st.button("πŸ” Get Answer", key="qa_btn"):
416
+ if not context.strip() or not question.strip():
417
+ st.error("⚠️ Please provide both context and question")
418
+ else:
419
+ trunc_ctx, _ = truncate_text(context, 400)
420
+ with st.spinner("πŸ€” Analyzing..."):
421
+ try:
422
+ qa_model = get_qa()
423
+ answer = qa_model(question=question, context=trunc_ctx)['answer']
424
+
425
+ st.markdown(f"""
426
+ <div class="result-card">
427
+ <h4 style="color: #667eea; margin-bottom: 1rem;">πŸ’‘ AI Answer</h4>
428
+ <p style="font-size: 1.2rem; line-height: 1.8; color: #2d3748; font-weight: 500;">{answer}</p>
429
+ <div style="margin-top: 1rem; padding-top: 1rem; border-top: 1px solid #e2e8f0;">
430
+ <span class="stats-badge" style="background: #48bb78; color: white;">
431
+ βœ“ Answer Found
432
+ </span>
433
+ </div>
434
+ </div>
435
+ """, unsafe_allow_html=True)
436
+ except Exception as e:
437
+ st.error(f"❌ Error: {str(e)}")
438
+
439
+ # QUIZ TAB
440
+ with tab3:
441
+ st.markdown("### 🎯 AI Quiz Generator")
442
+
443
+ quiz_ctx = st.text_area("πŸ“– Study material:", value="", height=200, key="quiz_ctx",
444
+ placeholder="Paste content for quiz generation...")
445
+
446
+ col1, col2, col3 = st.columns([1, 1, 1])
447
+ with col2:
448
+ if st.button("πŸš€ Generate Quiz", key="quiz_btn"):
449
+ if not quiz_ctx.strip():
450
+ st.error("⚠️ Please provide text")
451
+ else:
452
+ trunc_quiz, _ = truncate_text(quiz_ctx, 200)
453
+ with st.spinner("🎲 Creating questions..."):
454
+ sentences = sent_tokenize(trunc_quiz)[:5]
455
+ questions = [f"What is the main concept in: '{s[:70]}...'?" for s in sentences]
456
+
457
+ st.markdown('<div class="result-card">', unsafe_allow_html=True)
458
+ st.markdown("<h4 style='color: #667eea;'>πŸ“ Generated Quiz Questions</h4>", unsafe_allow_html=True)
459
+ for i, q in enumerate(questions, 1):
460
+ st.markdown(f"""
461
+ <div style='background: #f7fafc; padding: 1rem; margin: 0.5rem 0; border-radius: 12px; border-left: 4px solid #667eea;'>
462
+ <strong style='color: #667eea;'>Question {i}:</strong> {q}
463
+ </div>
464
+ """, unsafe_allow_html=True)
465
+ st.markdown('</div>', unsafe_allow_html=True)
466
+ st.session_state["quiz"] = questions
467
+
468
+ # TRANSLATE TAB
469
+ with tab4:
470
+ st.markdown("### 🌍 AI Translation")
471
+
472
+ trans_text = st.text_area("✍️ Text to translate:", height=200, key="trans_txt",
473
+ placeholder="Enter text to translate...")
474
+
475
+ col1, col2 = st.columns(2)
476
+ with col1:
477
+ lang = st.selectbox("🎯 Target language:", ["French", "German", "Spanish", "Italian", "Hindi"])
478
+
479
+ with col2:
480
+ st.write("")
481
+ st.write("")
482
+ if st.button("🌐 Translate Now", key="trans_btn"):
483
+ if not trans_text.strip():
484
+ st.error("⚠️ Please provide text")
485
+ else:
486
+ model_map = {
487
+ "French": "Helsinki-NLP/opus-mt-en-fr",
488
+ "German": "Helsinki-NLP/opus-mt-en-de",
489
+ "Spanish": "Helsinki-NLP/opus-mt-en-es",
490
+ "Italian": "Helsinki-NLP/opus-mt-en-it",
491
+ "Hindi": "Helsinki-NLP/opus-mt-en-hi"
492
+ }
493
+
494
+ trunc_trans, _ = truncate_text(trans_text, 200)
495
+ with st.spinner(f"🌍 Translating to {lang}..."):
496
+ try:
497
+ translator = load_translator(model_map[lang])
498
+ translation = translator(trunc_trans, max_length=256)[0]['translation_text']
499
+
500
+ st.markdown(f"""
501
+ <div class="result-card">
502
+ <h4 style="color: #667eea; margin-bottom: 1rem;">🌐 Translation ({lang})</h4>
503
+ <p style="font-size: 1.2rem; line-height: 1.8; color: #2d3748;">{translation}</p>
504
+ <div style="margin-top: 1rem; padding-top: 1rem; border-top: 1px solid #e2e8f0;">
505
+ <span class="stats-badge" style="background: #48bb78; color: white;">
506
+ βœ“ Translated
507
+ </span>
508
+ </div>
509
+ </div>
510
+ """, unsafe_allow_html=True)
511
+ st.session_state["translation"] = translation
512
+ except Exception as e:
513
+ st.error(f"❌ Error: {str(e)}")
514
+
515
+ # KEYWORDS TAB
516
+ with tab5:
517
+ st.markdown("### πŸ”‘ AI Keyword Extraction")
518
+
519
+ keyword_input = st.text_area("πŸ“ Text for analysis:", value="", height=200, key="kw_txt",
520
+ placeholder="Paste text to extract key concepts...")
521
+
522
+ col1, col2, col3 = st.columns([1, 1, 1])
523
+ with col2:
524
+ if st.button("πŸ” Extract Keywords", key="kw_btn"):
525
+ if not keyword_input.strip():
526
+ st.error("⚠️ Please provide text")
527
+ else:
528
+ trunc_kw, _ = truncate_text(keyword_input, 200)
529
+ with st.spinner("πŸ”Ž Analyzing concepts..."):
530
+ try:
531
+ classifier = get_classifier()
532
+ labels = ["technology", "science", "education", "health", "business", "finance", "medical"]
533
+ result = classifier(trunc_kw, labels)
534
+ keywords = [lbl for lbl, score in zip(result['labels'], result['scores']) if score > 0.3][:5]
535
+
536
+ if keywords:
537
+ st.markdown('<div class="result-card">', unsafe_allow_html=True)
538
+ st.markdown("<h4 style='color: #667eea;'>🎯 Extracted Keywords</h4>", unsafe_allow_html=True)
539
+ kw_html = " ".join([
540
+ f"<span style='display: inline-block; background: linear-gradient(135deg, #667eea, #764ba2); color: white; padding: 12px 24px; border-radius: 25px; margin: 8px; font-size: 1rem; font-weight: 600; box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);'>{kw}</span>"
541
+ for kw in keywords
542
+ ])
543
+ st.markdown(kw_html, unsafe_allow_html=True)
544
+ st.markdown('</div>', unsafe_allow_html=True)
545
+ st.session_state["keywords"] = keywords
546
+ else:
547
+ st.info("ℹ️ No strong keywords found")
548
+ except Exception as e:
549
+ st.error(f"❌ Error: {str(e)}")
550
+
551
+ # DOWNLOAD TAB
552
+ with tab6:
553
+ st.markdown("### πŸ“₯ Download Results")
554
+
555
+ def download_link(text, filename, emoji):
556
+ b64 = base64.b64encode(text.encode()).decode()
557
+ return f"""
558
+ <a href="data:file/txt;base64,{b64}" download="{filename}"
559
+ style="display: inline-block; background: linear-gradient(135deg, #667eea, #764ba2);
560
+ color: white; padding: 16px 32px; border-radius: 16px; text-decoration: none;
561
+ font-weight: 700; font-size: 1.1rem; margin: 10px; box-shadow: 0 8px 24px rgba(102, 126, 234, 0.3);
562
+ transition: all 0.3s ease;">
563
+ {emoji} Download {filename}
564
+ </a>
565
+ """
566
+
567
+ col1, col2 = st.columns(2)
568
+
569
+ with col1:
570
+ if st.session_state["summary"]:
571
+ st.markdown(download_link(st.session_state["summary"], "summary.txt", "πŸ“„"), unsafe_allow_html=True)
572
+ if st.session_state["quiz"]:
573
+ st.markdown(download_link("\n".join(st.session_state["quiz"]), "quiz.txt", "🎯"), unsafe_allow_html=True)
574
+
575
+ with col2:
576
+ if st.session_state["translation"]:
577
+ st.markdown(download_link(st.session_state["translation"], "translation.txt", "🌍"), unsafe_allow_html=True)
578
+ if st.session_state["keywords"]:
579
+ st.markdown(download_link(", ".join(st.session_state["keywords"]), "keywords.txt", "πŸ”‘"), unsafe_allow_html=True)
580
+
581
+ if not any([st.session_state["summary"], st.session_state["quiz"],
582
+ st.session_state["translation"], st.session_state["keywords"]]):
583
+ st.info("ℹ️ Generate content in other tabs to enable downloads")
584
+
585
+ # Premium Footer
586
+ st.markdown("""
587
+ <div class="premium-footer">
588
+ <p style="font-size: 1.2rem; font-weight: 600;">Built with ❀️ by <span style="background: linear-gradient(135deg, #ffffff, #e0e7ff); -webkit-background-clip: text; -webkit-text-fill-color: transparent; font-weight: 700;">Umaima Qureshi</span></p>
589
+ <p style="font-size: 0.9rem;">Β© 2025 AI Study Helper Pro. All Rights Reserved.</p>
590
+ <p style="margin-top: 1rem;">
591
+ <a href="https://github.com/Umaima122" target="_blank"
592
+ style="color: white; text-decoration: none; padding: 8px 20px; background: rgba(255, 255, 255, 0.15);
593
+ border-radius: 20px; backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.3);
594
+ transition: all 0.3s ease;">
595
+ πŸ”— GitHub
596
+ </a>
597
+ </p>
598
+ </div>
599
+ """, unsafe_allow_html=True)
requirements.txt CHANGED
@@ -1,3 +1,6 @@
1
- altair
2
- pandas
3
- streamlit
 
 
 
 
1
+ streamlit==1.31.0
2
+ transformers==4.36.0
3
+ torch==2.1.0
4
+ nltk==3.8.1
5
+ PyPDF2==3.0.1
6
+ sentencepiece==0.1.99