citoreh commited on
Commit
6d782c3
·
verified ·
1 Parent(s): 4922b1f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +114 -191
app.py CHANGED
@@ -1,6 +1,4 @@
1
  import gradio as gr
2
- import torch
3
- from transformers import AutoTokenizer, AutoModelForSeq2SeqLM, pipeline
4
  import re
5
  import warnings
6
  import io
@@ -9,33 +7,10 @@ from bs4 import BeautifulSoup
9
  from urllib.parse import urlparse
10
  warnings.filterwarnings("ignore")
11
 
12
- class PersianSummarizer:
13
  def __init__(self):
14
- # Using mT5 which is more stable and supports Persian well
15
- self.model_name = "google/mt5-small"
16
- self.tokenizer = None
17
- self.model = None
18
- self.load_model()
19
-
20
- def load_model(self):
21
- """Load the multilingual T5 model for Persian summarization"""
22
- try:
23
- print("Loading mT5 model for Persian summarization...")
24
- self.tokenizer = AutoTokenizer.from_pretrained(self.model_name)
25
- self.model = AutoModelForSeq2SeqLM.from_pretrained(self.model_name)
26
- print("mT5 model loaded successfully!")
27
- except Exception as e:
28
- print(f"Error loading model: {e}")
29
- # Fallback to pipeline approach
30
- try:
31
- from transformers import pipeline
32
- self.pipeline = pipeline("summarization", model="facebook/bart-large-cnn")
33
- self.model = None
34
- print("Fallback pipeline loaded!")
35
- except Exception as e2:
36
- print(f"All models failed: {e2}")
37
- self.model = None
38
- self.pipeline = None
39
 
40
  def preprocess_persian_text(self, text):
41
  """Clean and preprocess Persian text"""
@@ -47,8 +22,76 @@ class PersianSummarizer:
47
 
48
  return text
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  def summarize_text(self, text, max_length=150, min_length=50):
51
- """Summarize Persian text keeping output in Persian"""
52
  if not text or len(text.strip()) < 50:
53
  return "❌ متن ورودی کوتاه است. لطفاً متن طولانی‌تری وارد کنید."
54
 
@@ -60,50 +103,18 @@ class PersianSummarizer:
60
  if len(clean_text) < 100:
61
  return "❌ متن پس از پردازش کوتاه است. متن بلندتری وارد کنید."
62
 
63
- if self.model is None:
64
- # Use fallback methods
65
- if hasattr(self, 'pipeline') and self.pipeline:
66
- # Try with pipeline but post-process to stay Persian
67
- result = self.pipeline(clean_text, max_length=max_length, min_length=min_length)
68
- return self.ensure_persian_output(result[0]['summary_text'], clean_text)
69
- else:
70
- # Pure extractive method
71
- return self.extractive_summary(clean_text, max_length)
72
-
73
- # Use mT5 with Persian-specific prompting
74
- # Add Persian instruction to encourage Persian output
75
- persian_prompt = f"خلاصه کنید: {clean_text}"
76
-
77
- # Tokenize with proper settings
78
- inputs = self.tokenizer(
79
- persian_prompt,
80
- max_length=512, # Reduced for stability
81
- padding=True,
82
- truncation=True,
83
- return_tensors="pt"
84
- )
85
-
86
- # Generate summary
87
- with torch.no_grad():
88
- summary_ids = self.model.generate(
89
- inputs["input_ids"],
90
- attention_mask=inputs.get("attention_mask"),
91
- max_length=max_length,
92
- min_length=min_length,
93
- num_beams=2, # Reduced for speed
94
- length_penalty=1.0,
95
- repetition_penalty=1.1,
96
- early_stopping=True,
97
- do_sample=False
98
- )
99
 
100
- # Decode and clean
101
- summary = self.tokenizer.decode(summary_ids[0], skip_special_tokens=True)
 
 
102
 
103
- # Clean up the summary and ensure it's Persian
104
- summary = self.clean_persian_summary(summary, clean_text)
105
 
106
- return summary
 
107
 
108
  # File processing functions
109
  def extract_text_from_file(file_path):
@@ -266,84 +277,10 @@ def process_url_input(url):
266
  content = persian_summarizer.preprocess_persian_text(content)
267
  return content, message
268
  else:
269
- return "", message if summary else "❌ نتوانستم خلاصه مناسبی تولید کنم. لطفاً متن دیگری امتحان کنید."
270
-
271
- except Exception as e:
272
- print(f"Error in summarization: {e}")
273
- # Always fallback to extractive
274
- return self.extractive_summary(clean_text, max_length)
275
-
276
- def ensure_persian_output(self, text, original_text):
277
- """Ensure output stays in Persian"""
278
- # If the output seems to be English, use extractive method instead
279
- english_ratio = len(re.findall(r'[a-zA-Z]', text)) / max(len(text), 1)
280
- if english_ratio > 0.3: # If more than 30% English characters
281
- return self.extractive_summary(original_text, 150)
282
- return text
283
-
284
- def clean_persian_summary(self, summary, original_text):
285
- """Clean and ensure Persian summary quality"""
286
- # Remove the prompt prefix if it exists
287
- summary = re.sub(r'^خلاصه کنید:?\s*', '', summary)
288
-
289
- # Remove excessive English characters
290
- summary = re.sub(r'[a-zA-Z]{3,}', '', summary)
291
-
292
- # Check if summary is mostly Persian
293
- persian_chars = len(re.findall(r'[\u0600-\u06FF]', summary))
294
- total_chars = len(re.sub(r'\s', '', summary))
295
-
296
- if total_chars == 0 or persian_chars / total_chars < 0.5:
297
- # If not enough Persian content, use extractive method
298
- return self.extractive_summary(original_text, 150)
299
-
300
- # Clean whitespace
301
- summary = re.sub(r'\s+', ' ', summary.strip())
302
-
303
- return summary
304
-
305
- def extractive_summary(self, text, max_length):
306
- """Simple extractive summarization fallback that keeps Persian"""
307
- sentences = re.split(r'[.!?؟]', text)
308
- sentences = [s.strip() for s in sentences if len(s.strip()) > 20]
309
-
310
- if len(sentences) <= 2:
311
- return text[:max_length] + ("..." if len(text) > max_length else "")
312
-
313
- # Score sentences by position and length
314
- scored_sentences = []
315
- for i, sentence in enumerate(sentences):
316
- # Give higher scores to earlier sentences and longer sentences
317
- position_score = 1.0 - (i / len(sentences)) * 0.5
318
- length_score = min(len(sentence) / 100, 1.0)
319
- total_score = position_score + length_score
320
- scored_sentences.append((sentence, total_score))
321
-
322
- # Sort by score and take top sentences
323
- scored_sentences.sort(key=lambda x: x[1], reverse=True)
324
-
325
- # Select sentences until we reach desired length
326
- summary_sentences = []
327
- current_length = 0
328
-
329
- for sentence, score in scored_sentences:
330
- if current_length + len(sentence) < max_length:
331
- summary_sentences.append(sentence)
332
- current_length += len(sentence)
333
- else:
334
- break
335
-
336
- # Maintain original order
337
- original_order = []
338
- for sentence in sentences:
339
- if sentence in summary_sentences:
340
- original_order.append(sentence)
341
-
342
- summary = ". ".join(original_order)
343
- return summary[:max_length] + ("..." if len(summary) > max_length else "")
344
 
345
  # Initialize the summarizer
346
- persian_summarizer = PersianSummarizer()
347
 
348
  def summarize_persian_text(text, summary_length):
349
  """Main function to handle summarization requests"""
@@ -359,21 +296,21 @@ def summarize_persian_text(text, summary_length):
359
  # Sample Persian texts for demonstration
360
  sample_texts = {
361
  "خبر سیاسی": """
362
- مجلس شورای اسلامی ایران در جلسه علنی روز گذشته لایحه بودجه سال آینده را بررسی کرد. نمایندگان مجلس در این جلسه به بحث و بررسی جزئیات بودجه پرداختند و پیشنهادات مختلفی برای بهبود آن ارائه دادند. وزیر اقتصاد نیز در این جلسه حضور یافت و به سوالات نمایندگان پاسخ داد. بر اساس این لایحه، بودجه عمومی کشور نسبت به سال جاری افزایش قابل توجهی خواهد داشت. همچنین اعتبارات ویژه‌ای برای توسعه زیرساخت‌های کشور در نظر گرفته شده است.
363
  """,
364
 
365
  "مقاله علمی": """
366
- هوش مصنوعی در دهه‌های اخیر به یکی از مهم‌ترین فناوری‌های نوین تبدیل شده است. این فناوری کاربردهای گسترده‌ای در زمینه‌های مختلف نظیر پزشکی، آموزش، حمل و نقل و صنعت دارد. یادگیری ماشین که بخش مهمی از هوش مصنوعی محسوب می‌شود، امکان تحلیل داده‌های پیچیده و الگویابی را فراهم می‌کند. شبکه‌های عصبی مصنوعی نیز با الهام از مغز انسان طراحی شده‌اند و قابلیت‌های شگفت‌انگیزی در تشخیص الگو و پردازش تصویر دارند. با این حال، چالش‌هایی نظیر اخلاق در هوش مصنوعی و حفظ حریم خصوصی همچنان وجود دارد.
367
  """,
368
 
369
  "متن ادبی": """
370
- در باغ گل‌های سرخ، پیرمردی با موهای سفید نشسته بود و به آسمان آبی نگاه می‌کرد. نسیم ملایم صبحگاهی برگ‌های درختان را به رقص درآورده بود. صدای آب نهری که از دور می‌آمد، آرامش خاصی به فضا می‌بخشید. پیرمرد در دل خود به یاد روزهای جوانی‌اش بود، زمانی که این باغ را با دستان خود کاشته بود. اکنون پس از سال‌ها، میوه زحماتش را می‌دید. گل‌های رنگارنگ، درختان سایه‌دار و آرامش این مکان، همه نشان از عشق و دلبستگی او به این باغ داشت.
371
  """
372
  }
373
 
374
  # Create Gradio interface
375
  with gr.Blocks(
376
- title="خلاصه‌ساز متن فارسی",
377
  theme=gr.themes.Soft(),
378
  css="""
379
  .persian-text {
@@ -392,8 +329,8 @@ with gr.Blocks(
392
  gr.HTML("""
393
  <div class="main-header">
394
  <h1>🤖 خلاصه‌ساز هوشمند متن فارسی</h1>
395
- <p><strong>Persian Text Summarization Tool</strong></p>
396
- <p>این ابزار با استفاده از هوش مصنوعی، متن‌ها، فایل‌ها و وب‌سایت‌ها را خلاصه می‌کند</p>
397
  <p>📁 فایل‌های TXT, DOCX, PDF | 🌐 وب‌سایت‌ها و مقالات آنلاین</p>
398
  </div>
399
  """)
@@ -402,13 +339,14 @@ with gr.Blocks(
402
  with gr.Column(scale=2):
403
  gr.Markdown("## 📝 متن ورودی")
404
 
405
- # Model status
406
- model_status = gr.HTML(
407
- f"""<div style="padding: 10px; background-color: #e8f5e8; border-radius: 5px; margin-bottom: 10px;">
408
- <strong>🤖 مدل فعال:</strong> mT5-small (پشتیبانی از فارسی)<br>
409
- <strong>📊 وضعیت:</strong> {'آماده برای خلاصه‌سازی فارسی' if persian_summarizer.model else 'حالت استخراجی (fallback)'}
410
- </div>"""
411
- )
 
412
 
413
  # File upload section
414
  with gr.Accordion("📁 آپلود فایل متنی", open=False):
@@ -479,45 +417,30 @@ with gr.Blocks(
479
  ### نحوه استفاده:
480
  1. **متن خود را وارد کنید**: متن فارسی خود را در قسمت "متن ورودی" بنویسید یا کپی کنید
481
  2. **یا فایل آپلود کنید**: فایل متنی (.txt, .docx, .pdf) خود را آپلود کنید
482
- 3. **یا از وب‌سایت استخراج کنید**: آدرس وبسایت مورد نظر را وارد کنید
483
- 4. **نمونه متن انتخاب کنید**: می‌توانید از نمونه متن‌های آماده استفاده کنید
484
- 5. **طول خلاصه را تعیین کنید**: کوتاه، متوسط یا بلند
485
- 6. **دکمه خلاصه‌سازی را بزنید**: منتظر بمانید تا خلاصه تولید شود
486
-
487
- ### ویژگی‌ها:
488
- - ✅ پشتیبانی کامل از زبان فارسی با mT5
489
- - ✅ خروجی کاملاً فارسی (بدون ترجمه به انگلیسی)
490
  - ✅ آپلود فایل‌های متنی (TXT, DOCX, PDF)
491
- - ✅ استخراج محتوا از وب‌سایت‌ها
492
- - ✅ سه سطح طول خلاصه
493
- - ✅ نمونه متن‌های آماده
494
- - ✅ نمایش آمار متن
495
- - ✅ رابط کاربری فارسی
496
- - سیستم fallback پیشرفته
497
-
498
- ### منابع ورودی پشتیبانی شده:
499
- - **متن مستقیم**: کپی و پیست متن
500
- - **فایل‌ها**: TXT, DOCX, PDF
501
- - **وب‌سایت‌ها**: خبرگاری‌ها، وبلاگ‌ها، مقالات آنلاین
502
-
503
- ### فرمت‌های فایل:
504
  - **TXT**: فایل‌های متن ساده (UTF-8, CP1256)
505
  - **DOCX**: اسناد Microsoft Word
506
  - **PDF**: اسناد PDF (نیاز به PyPDF2)
507
 
508
- ### وب‌سایت‌های پشتیبانی شده:
509
- - **خبرگاری‌ها**: BBC Persian, Radio Farda, ایسنا و...
510
- - **وبلاگ‌ها**: وردپرس، بلاگر و...
511
- - **مقالات**: مجلات آنلاین، سایت‌های آموزشی
512
- - **ویکی‌پدیا**: صفحات فارسی و انگلیسی
513
-
514
  ### نکات:
515
  - متن ورودی باید حداقل 100 کاراکتر باشد
516
- - کیفیت خلاصه با متن‌های طولانیتر بهتر است
517
- - از mT5 برای حفظ زبان فارسی استفاده می‌کند
518
- - خلاصه تولیدی همیشه به زبان فارسی است
519
- - برای وبسایت‌ها، محتوای اصلی مقاله استخراج می‌شود
520
- - فایل‌ها و وب‌سایت‌های بزرگ زمان بیشتری نیاز دارند
521
  """)
522
 
523
  # Event handlers
 
1
  import gradio as gr
 
 
2
  import re
3
  import warnings
4
  import io
 
7
  from urllib.parse import urlparse
8
  warnings.filterwarnings("ignore")
9
 
10
+ class LightweightPersianSummarizer:
11
  def __init__(self):
12
+ """Lightweight Persian summarizer using extractive methods"""
13
+ print("Initializing lightweight Persian summarizer...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
  def preprocess_persian_text(self, text):
16
  """Clean and preprocess Persian text"""
 
22
 
23
  return text
24
 
25
+ def score_sentence(self, sentence, position, total_sentences):
26
+ """Score sentences for importance"""
27
+ # Position score (earlier sentences are more important)
28
+ position_score = 1.0 - (position / total_sentences) * 0.3
29
+
30
+ # Length score (moderate length sentences are preferred)
31
+ length = len(sentence.strip())
32
+ if length < 20:
33
+ length_score = 0.1
34
+ elif length > 200:
35
+ length_score = 0.7
36
+ else:
37
+ length_score = 1.0
38
+
39
+ # Keyword density score (sentences with more Persian content)
40
+ persian_chars = len(re.findall(r'[\u0600-\u06FF]', sentence))
41
+ total_chars = len(sentence.replace(' ', ''))
42
+ persian_ratio = persian_chars / max(total_chars, 1)
43
+
44
+ # Combined score
45
+ final_score = (position_score * 0.4) + (length_score * 0.3) + (persian_ratio * 0.3)
46
+
47
+ return final_score
48
+
49
+ def extractive_summary(self, text, target_length):
50
+ """Advanced extractive summarization for Persian text"""
51
+ # Split into sentences
52
+ sentences = re.split(r'[.!?؟]', text)
53
+ sentences = [s.strip() for s in sentences if len(s.strip()) > 15]
54
+
55
+ if len(sentences) <= 2:
56
+ return text[:target_length] + ("..." if len(text) > target_length else "")
57
+
58
+ # Score all sentences
59
+ scored_sentences = []
60
+ for i, sentence in enumerate(sentences):
61
+ score = self.score_sentence(sentence, i, len(sentences))
62
+ scored_sentences.append((sentence, score, i))
63
+
64
+ # Sort by score (highest first)
65
+ scored_sentences.sort(key=lambda x: x[1], reverse=True)
66
+
67
+ # Select sentences up to target length
68
+ selected_sentences = []
69
+ current_length = 0
70
+
71
+ for sentence, score, original_index in scored_sentences:
72
+ sentence_length = len(sentence)
73
+ if current_length + sentence_length <= target_length:
74
+ selected_sentences.append((sentence, original_index))
75
+ current_length += sentence_length
76
+ elif len(selected_sentences) == 0: # At least include one sentence
77
+ # Truncate the sentence if needed
78
+ truncated = sentence[:target_length-10] + "..."
79
+ selected_sentences.append((truncated, original_index))
80
+ break
81
+
82
+ # Sort selected sentences by original order
83
+ selected_sentences.sort(key=lambda x: x[1])
84
+
85
+ # Join sentences
86
+ summary = ". ".join([sent[0] for sent in selected_sentences])
87
+
88
+ # Final cleanup
89
+ summary = re.sub(r'\s+', ' ', summary.strip())
90
+
91
+ return summary
92
+
93
  def summarize_text(self, text, max_length=150, min_length=50):
94
+ """Main summarization function"""
95
  if not text or len(text.strip()) < 50:
96
  return "❌ متن ورودی کوتاه است. لطفاً متن طولانی‌تری وارد کنید."
97
 
 
103
  if len(clean_text) < 100:
104
  return "❌ متن پس از پردازش کوتاه است. متن بلندتری وارد کنید."
105
 
106
+ # Use extractive summarization
107
+ summary = self.extractive_summary(clean_text, max_length)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
 
109
+ # Ensure minimum length
110
+ if len(summary) < min_length and len(clean_text) > min_length:
111
+ # Try with higher target length
112
+ summary = self.extractive_summary(clean_text, min(max_length + 50, len(clean_text)))
113
 
114
+ return summary if summary else "❌ نتوانستم خلاصه مناسبی تولید کنم."
 
115
 
116
+ except Exception as e:
117
+ return f"❌ خطا در خلاصه‌سازی: {str(e)}"
118
 
119
  # File processing functions
120
  def extract_text_from_file(file_path):
 
277
  content = persian_summarizer.preprocess_persian_text(content)
278
  return content, message
279
  else:
280
+ return "", message
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
281
 
282
  # Initialize the summarizer
283
+ persian_summarizer = LightweightPersianSummarizer()
284
 
285
  def summarize_persian_text(text, summary_length):
286
  """Main function to handle summarization requests"""
 
296
  # Sample Persian texts for demonstration
297
  sample_texts = {
298
  "خبر سیاسی": """
299
+ مجلس شورای اسلامی ایران در جلسه علنی روز گذشته لایحه بودجه سال آینده را بررسی کرد. نمایندگان مجلس در این جلسه به بحث و بررسی جزئیات بودجه پرداختند و پیشنهادات مختلفی برای بهبود آن ارائه دادند. وزیر اقتصاد نیز در این جلسه حضور یافت و به سوالات نمایندگان پاسخ داد. بر اساس این لایحه، بودجه عمومی کشور نسبت به سال جاری افزایش قابل توجهی خواهد داشت. همچنین اعتبارات ویژه‌ای برای توسعه زیرساخت‌های کشور در نظر گرفته شده است. نمایندگان بر لزوم شفافیت در هزینه‌کرد بودجه تأکید کردند و خواستار نظارت دقیق‌تر بر اجرای برنامه‌های توسعه‌ای شدند.
300
  """,
301
 
302
  "مقاله علمی": """
303
+ هوش مصنوعی در دهه‌های اخیر به یکی از مهم‌ترین فناوری‌های نوین تبدیل شده است. این فناوری کاربردهای گسترده‌ای در زمینه‌های مختلف نظیر پزشکی، آموزش، حمل و نقل و صنعت دارد. یادگیری ماشین که بخش مهمی از هوش مصنوعی محسوب می‌شود، امکان تحلیل داده‌های پیچیده و الگویابی را فراهم می‌کند. شبکه‌های عصبی مصنوعی نیز با الهام از مغز انسان طراحی شده‌اند و قابلیت‌های شگفت‌انگیزی در تشخیص الگو و پردازش تصویر دارند. با این حال، چالش‌هایی نظیر اخلاق در هوش مصنوعی و حفظ حریم خصوصی همچنان وجود دارد. محققان بر لزوم توسعه هوش مصنوعی مسئولانه تأکید می‌کنند تا از مزایای این فناوری استفاده کرده و از مضرات احتمالی آن جلوگیری شود.
304
  """,
305
 
306
  "متن ادبی": """
307
+ در باغ گل‌های سرخ، پیرمردی با موهای سفید نشسته بود و به آسمان آبی نگاه می‌کرد. نسیم ملایم صبحگاهی برگ‌های درختان را به رقص درآورده بود. صدای آب نهری که از دور می‌آمد، آرامش خاصی به فضا می‌بخشید. پیرمرد در دل خود به یاد روزهای جوانی‌اش بود، زمانی که این باغ را با دستان خود کاشته بود. اکنون پس از سال‌ها، میوه زحماتش را می‌دید. گل‌های رنگارنگ، درختان سایه‌دار و آرامش این مکان، همه نشان از عشق و دلبستگی او به این باغ داشت. او لبخندی بر لب داشت، لبخندی که حاکی از رضایت و آرامش درونی بود. این باغ نه تنها مکانی برای استراحت، بلکه خانه‌ای برای خاطرات شیرین او بود.
308
  """
309
  }
310
 
311
  # Create Gradio interface
312
  with gr.Blocks(
313
+ title="خلاصه‌ساز متن فارسی - نسخه سبک",
314
  theme=gr.themes.Soft(),
315
  css="""
316
  .persian-text {
 
329
  gr.HTML("""
330
  <div class="main-header">
331
  <h1>🤖 خلاصه‌ساز هوشمند متن فارسی</h1>
332
+ <p><strong>Persian Text Summarization Tool - Lightweight Version</strong></p>
333
+ <p>این ابزار با روش استخراجی پیشرفته، متن‌ها، فایل‌ها و وب‌سایت‌ها را خلاصه می‌کند</p>
334
  <p>📁 فایل‌های TXT, DOCX, PDF | 🌐 وب‌سایت‌ها و مقالات آنلاین</p>
335
  </div>
336
  """)
 
339
  with gr.Column(scale=2):
340
  gr.Markdown("## 📝 متن ورودی")
341
 
342
+ # Method info
343
+ gr.HTML("""
344
+ <div style="padding: 10px; background-color: #e3f2fd; border-radius: 5px; margin-bottom: 10px;">
345
+ <strong> روش:</strong> خلاصه‌سازی استخراجی پیشرفته<br>
346
+ <strong> مزیت:</strong> سریع، پایدار و کاملاً فارسی<br>
347
+ <strong>🎯 کیفیت:</strong> بالا برای متن‌های فارسی
348
+ </div>
349
+ """)
350
 
351
  # File upload section
352
  with gr.Accordion("📁 آپلود فایل متنی", open=False):
 
417
  ### نحوه استفاده:
418
  1. **متن خود را وارد کنید**: متن فارسی خود را در قسمت "متن ورودی" بنویسید یا کپی کنید
419
  2. **یا فایل آپلود کنید**: فایل متنی (.txt, .docx, .pdf) خود را آپلود کنید
420
+ 3. **نمونه متن انتخاب کنید**: میتوانید از نمونه متن‌های آماده استفاده کنید
421
+ 4. **طول خلاصه را تعیین کنید**: کوتاه، متوسط یا بلند
422
+ 5. **دکمه خلاصه‌سازی را بزنید**: منتظر بمانید تا خلاصه تولید شود
423
+
424
+ ### ویژگی‌های نسخه سبک:
425
+ - ✅ سریع و پایدار (بدون نیاز به مدل‌های سنگین)
426
+ - ✅ کاملاً فارسی (هیچ ترجمه‌ای انجام نمی‌شود)
 
427
  - ✅ آپلود فایل‌های متنی (TXT, DOCX, PDF)
428
+ - ✅ کیفیت بالا برای متن‌های فارسی
429
+ - ✅ مناسب برای همه سرورها
430
+ - ✅ روش استخراجی هوشمند
431
+ - ✅ امتیازدهی پیشرفته به جملات
432
+
433
+ ### فرمت‌های فایل پشتیبانی شده:
 
 
 
 
 
 
 
434
  - **TXT**: فایل‌های متن ساده (UTF-8, CP1256)
435
  - **DOCX**: اسناد Microsoft Word
436
  - **PDF**: اسناد PDF (نیاز به PyPDF2)
437
 
 
 
 
 
 
 
438
  ### نکات:
439
  - متن ورودی باید حداقل 100 کاراکتر باشد
440
+ - جملات ابتدایی و میانی متن امتیاز بیشتری دریافت می‌کنند
441
+ - این نسخه برای استقرار آسان طراحی شده است
442
+ - هیچ وابستگی پیچیدهای ندارد
443
+ - فایل‌های بزرگ ممکن است زمان بیشتری برای پردازش نیاز داشته باشند
 
444
  """)
445
 
446
  # Event handlers