citoreh commited on
Commit
16f05bf
·
verified ·
1 Parent(s): 63c81e2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +105 -125
app.py CHANGED
@@ -1,39 +1,12 @@
1
  import gradio as gr
2
- import torch
3
- from transformers import pipeline, AutoTokenizer, AutoModelForSeq2SeqLM, MT5Tokenizer
4
  import re
5
  import warnings
6
  warnings.filterwarnings("ignore")
7
 
8
- class PersianSummarizer:
9
  def __init__(self):
10
- self.model_name = "nafisehNik/mt5-persian-summary"
11
- self.tokenizer = None
12
- self.model = None
13
- self.load_model()
14
-
15
- def load_model(self):
16
- """Load the Persian-specific summarization model"""
17
- try:
18
- print("Loading Persian summarization model...")
19
- # Using Persian-specific MT5 model
20
- self.tokenizer = MT5Tokenizer.from_pretrained(self.model_name)
21
- self.model = AutoModelForSeq2SeqLM.from_pretrained(self.model_name)
22
- print("Persian MT5 model loaded successfully!")
23
- except Exception as e:
24
- print(f"Error loading Persian model: {e}")
25
- print("Falling back to multilingual model...")
26
- try:
27
- # Fallback to mT5 base model
28
- self.model_name = "google/mt5-small"
29
- self.tokenizer = MT5Tokenizer.from_pretrained(self.model_name)
30
- self.model = AutoModelForSeq2SeqLM.from_pretrained(self.model_name)
31
- print("Fallback model loaded!")
32
- except Exception as e2:
33
- print(f"Fallback failed: {e2}")
34
- # Last resort - simple extractive summarization
35
- self.model = None
36
- self.tokenizer = None
37
 
38
  def preprocess_persian_text(self, text):
39
  """Clean and preprocess Persian text"""
@@ -45,8 +18,76 @@ class PersianSummarizer:
45
 
46
  return text
47
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  def summarize_text(self, text, max_length=150, min_length=50):
49
- """Summarize Persian text using Persian-specific model"""
50
  if not text or len(text.strip()) < 50:
51
  return "❌ متن ورودی کوتاه است. لطفاً متن طولانی‌تری وارد کنید."
52
 
@@ -58,83 +99,21 @@ class PersianSummarizer:
58
  if len(clean_text) < 100:
59
  return "❌ متن پس از پردازش کوتاه است. متن بلندتری وارد کنید."
60
 
61
- if self.model is None or self.tokenizer is None:
62
- # Fallback to extractive summarization
63
- return self.extractive_summary(clean_text, max_length)
64
 
65
- # Persian-specific summarization using MT5
66
- input_ids = self.tokenizer(
67
- clean_text,
68
- max_length=1000,
69
- padding="max_length",
70
- truncation=True,
71
- return_attention_mask=True,
72
- add_special_tokens=True,
73
- return_tensors="pt"
74
- )
75
 
76
- # Generate summary
77
- with torch.no_grad():
78
- generated_ids = self.model.generate(
79
- input_ids=input_ids["input_ids"],
80
- attention_mask=input_ids["attention_mask"],
81
- num_beams=3,
82
- max_length=max_length,
83
- min_length=min_length,
84
- repetition_penalty=1.2,
85
- length_penalty=1.0,
86
- early_stopping=True,
87
- use_cache=True,
88
- do_sample=False
89
- )
90
-
91
- # Decode the summary
92
- summary = self.tokenizer.decode(
93
- generated_ids[0],
94
- skip_special_tokens=True,
95
- clean_up_tokenization_spaces=True
96
- )
97
-
98
- # Clean the output
99
- summary = self.clean_output(summary)
100
-
101
- return summary if summary else "❌ نتوانستم خلاصه مناسبی تولید کنم. لطفاً متن دیگری امتحان کنید."
102
 
103
  except Exception as e:
104
- print(f"Error in summarization: {e}")
105
- # Fallback to extractive method
106
- return self.extractive_summary(clean_text, max_length)
107
-
108
- def extractive_summary(self, text, max_length):
109
- """Simple extractive summarization fallback"""
110
- sentences = re.split(r'[.!?؟]', text)
111
- sentences = [s.strip() for s in sentences if len(s.strip()) > 20]
112
-
113
- if len(sentences) <= 2:
114
- return text[:max_length] + "..."
115
-
116
- # Take first, middle, and last sentences for a simple summary
117
- summary_sentences = []
118
- if len(sentences) >= 3:
119
- summary_sentences = [sentences[0], sentences[len(sentences)//2], sentences[-1]]
120
- else:
121
- summary_sentences = sentences
122
-
123
- summary = ". ".join(summary_sentences)
124
- return summary[:max_length] + ("..." if len(summary) > max_length else "")
125
-
126
- def clean_output(self, text):
127
- """Clean the generated summary"""
128
- # Remove any potential English artifacts
129
- text = re.sub(r'[a-zA-Z]+', '', text)
130
- # Remove extra spaces
131
- text = re.sub(r'\s+', ' ', text.strip())
132
- # Ensure proper Persian punctuation
133
- text = text.replace('.', '.')
134
- return text
135
 
136
  # Initialize the summarizer
137
- persian_summarizer = PersianSummarizer()
138
 
139
  def summarize_persian_text(text, summary_length):
140
  """Main function to handle summarization requests"""
@@ -150,21 +129,21 @@ def summarize_persian_text(text, summary_length):
150
  # Sample Persian texts for demonstration
151
  sample_texts = {
152
  "خبر سیاسی": """
153
- مجلس شورای اسلامی ایران در جلسه علنی روز گذشته لایحه بودجه سال آینده را بررسی کرد. نمایندگان مجلس در این جلسه به بحث و بررسی جزئیات بودجه پرداختند و پیشنهادات مختلفی برای بهبود آن ارائه دادند. وزیر اقتصاد نیز در این جلسه حضور یافت و به سوالات نمایندگان پاسخ داد. بر اساس این لایحه، بودجه عمومی کشور نسبت به سال جاری افزایش قابل توجهی خواهد داشت. همچنین اعتبارات ویژه‌ای برای توسعه زیرساخت‌های کشور در نظر گرفته شده است.
154
  """,
155
 
156
  "مقاله علمی": """
157
- هوش مصنوعی در دهه‌های اخیر به یکی از مهم‌ترین فناوری‌های نوین تبدیل شده است. این فناوری کاربردهای گسترده‌ای در زمینه‌های مختلف نظیر پزشکی، آموزش، حمل و نقل و صنعت دارد. یادگیری ماشین که بخش مهمی از هوش مصنوعی محسوب می‌شود، امکان تحلیل داده‌های پیچیده و الگویابی را فراهم می‌کند. شبکه‌های عصبی مصنوعی نیز با الهام از مغز انسان طراحی شده‌اند و قابلیت‌های شگفت‌انگیزی در تشخیص الگو و پردازش تصویر دارند. با این حال، چالش‌هایی نظیر اخلاق در هوش مصنوعی و حفظ حریم خصوصی همچنان وجود دارد.
158
  """,
159
 
160
  "متن ادبی": """
161
- در باغ گل‌های سرخ، پیرمردی با موهای سفید نشسته بود و به آسمان آبی نگاه می‌کرد. نسیم ملایم صبحگاهی برگ‌های درختان را به رقص درآورده بود. صدای آب نهری که از دور می‌آمد، آرامش خاصی به فضا می‌بخشید. پیرمرد در دل خود به یاد روزهای جوانی‌اش بود، زمانی که این باغ را با دستان خود کاشته بود. اکنون پس از سال‌ها، میوه زحماتش را می‌دید. گل‌های رنگارنگ، درختان سایه‌دار و آرامش این مکان، همه نشان از عشق و دلبستگی او به این باغ داشت.
162
  """
163
  }
164
 
165
  # Create Gradio interface
166
  with gr.Blocks(
167
- title="خلاصه‌ساز متن فارسی",
168
  theme=gr.themes.Soft(),
169
  css="""
170
  .persian-text {
@@ -183,8 +162,8 @@ with gr.Blocks(
183
  gr.HTML("""
184
  <div class="main-header">
185
  <h1>🤖 خلاصه‌ساز هوشمند متن فارسی</h1>
186
- <p><strong>Persian Text Summarization Tool</strong></p>
187
- <p>این ابزار با استفاده از هوش مصنوعی، متن‌های فارسی را خلاصه می‌کند</p>
188
  </div>
189
  """)
190
 
@@ -192,13 +171,14 @@ with gr.Blocks(
192
  with gr.Column(scale=2):
193
  gr.Markdown("## 📝 متن ورودی")
194
 
195
- # Model status
196
- model_status = gr.HTML(
197
- f"""<div style="padding: 10px; background-color: #e8f5e8; border-radius: 5px; margin-bottom: 10px;">
198
- <strong>🤖 مدل فعال:</strong> {persian_summarizer.model_name}<br>
199
- <strong>📊 وضعیت:</strong> {'آماده برای خلاصه‌سازی فارسی' if persian_summarizer.model else 'حالت استخراجی (fallback)'}
200
- </div>"""
201
- )
 
202
 
203
  # Sample text selector
204
  sample_selector = gr.Dropdown(
@@ -252,19 +232,19 @@ with gr.Blocks(
252
  3. **طول خلاصه را تعیین کنید**: کوتاه، متوسط یا بلند
253
  4. **دکمه خلاصه‌سازی را بزنید**: منتظر بمانید تا خلاصه تولید شود
254
 
255
- ### ویژگی‌ها:
256
- - ✅ پشتیبانی کامل از زبان فارسی با مدل تخصصی
257
- - ✅ خروجی کاملاً فارسی (بدون ترجمه)
258
- - ✅ سه سطح طول خلاصه
259
- - ✅ نمونه متن‌های آماده
260
- - ✅ نمایش آمار متن
261
- - ✅ رابط کاربری فارسی
262
 
263
  ### نکات:
264
  - متن ورودی باید حداقل 100 کاراکتر باشد
265
- - کیفیت خلاصه با متن‌های طولانی‌تر بهتر است
266
- - این ابزار از مدل MT5 فارسی استفاده می‌کند
267
- - خلاصه تولیدی کاملاً به زبان فارسی است
268
  """)
269
 
270
  # Event handlers
 
1
  import gradio as gr
 
 
2
  import re
3
  import warnings
4
  warnings.filterwarnings("ignore")
5
 
6
+ class LightweightPersianSummarizer:
7
  def __init__(self):
8
+ """Lightweight Persian summarizer using extractive methods"""
9
+ print("Initializing lightweight Persian summarizer...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  def preprocess_persian_text(self, text):
12
  """Clean and preprocess Persian text"""
 
18
 
19
  return text
20
 
21
+ def score_sentence(self, sentence, position, total_sentences):
22
+ """Score sentences for importance"""
23
+ # Position score (earlier sentences are more important)
24
+ position_score = 1.0 - (position / total_sentences) * 0.3
25
+
26
+ # Length score (moderate length sentences are preferred)
27
+ length = len(sentence.strip())
28
+ if length < 20:
29
+ length_score = 0.1
30
+ elif length > 200:
31
+ length_score = 0.7
32
+ else:
33
+ length_score = 1.0
34
+
35
+ # Keyword density score (sentences with more Persian content)
36
+ persian_chars = len(re.findall(r'[\u0600-\u06FF]', sentence))
37
+ total_chars = len(sentence.replace(' ', ''))
38
+ persian_ratio = persian_chars / max(total_chars, 1)
39
+
40
+ # Combined score
41
+ final_score = (position_score * 0.4) + (length_score * 0.3) + (persian_ratio * 0.3)
42
+
43
+ return final_score
44
+
45
+ def extractive_summary(self, text, target_length):
46
+ """Advanced extractive summarization for Persian text"""
47
+ # Split into sentences
48
+ sentences = re.split(r'[.!?؟]', text)
49
+ sentences = [s.strip() for s in sentences if len(s.strip()) > 15]
50
+
51
+ if len(sentences) <= 2:
52
+ return text[:target_length] + ("..." if len(text) > target_length else "")
53
+
54
+ # Score all sentences
55
+ scored_sentences = []
56
+ for i, sentence in enumerate(sentences):
57
+ score = self.score_sentence(sentence, i, len(sentences))
58
+ scored_sentences.append((sentence, score, i))
59
+
60
+ # Sort by score (highest first)
61
+ scored_sentences.sort(key=lambda x: x[1], reverse=True)
62
+
63
+ # Select sentences up to target length
64
+ selected_sentences = []
65
+ current_length = 0
66
+
67
+ for sentence, score, original_index in scored_sentences:
68
+ sentence_length = len(sentence)
69
+ if current_length + sentence_length <= target_length:
70
+ selected_sentences.append((sentence, original_index))
71
+ current_length += sentence_length
72
+ elif len(selected_sentences) == 0: # At least include one sentence
73
+ # Truncate the sentence if needed
74
+ truncated = sentence[:target_length-10] + "..."
75
+ selected_sentences.append((truncated, original_index))
76
+ break
77
+
78
+ # Sort selected sentences by original order
79
+ selected_sentences.sort(key=lambda x: x[1])
80
+
81
+ # Join sentences
82
+ summary = ". ".join([sent[0] for sent in selected_sentences])
83
+
84
+ # Final cleanup
85
+ summary = re.sub(r'\s+', ' ', summary.strip())
86
+
87
+ return summary
88
+
89
  def summarize_text(self, text, max_length=150, min_length=50):
90
+ """Main summarization function"""
91
  if not text or len(text.strip()) < 50:
92
  return "❌ متن ورودی کوتاه است. لطفاً متن طولانی‌تری وارد کنید."
93
 
 
99
  if len(clean_text) < 100:
100
  return "❌ متن پس از پردازش کوتاه است. متن بلندتری وارد کنید."
101
 
102
+ # Use extractive summarization
103
+ summary = self.extractive_summary(clean_text, max_length)
 
104
 
105
+ # Ensure minimum length
106
+ if len(summary) < min_length and len(clean_text) > min_length:
107
+ # Try with higher target length
108
+ summary = self.extractive_summary(clean_text, min(max_length + 50, len(clean_text)))
 
 
 
 
 
 
109
 
110
+ return summary if summary else "❌ نتوانستم خلاصه مناسبی تولید کنم."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
 
112
  except Exception as e:
113
+ return f" خطا در خلاصه‌سازی: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
 
115
  # Initialize the summarizer
116
+ persian_summarizer = LightweightPersianSummarizer()
117
 
118
  def summarize_persian_text(text, summary_length):
119
  """Main function to handle summarization requests"""
 
129
  # Sample Persian texts for demonstration
130
  sample_texts = {
131
  "خبر سیاسی": """
132
+ مجلس شورای اسلامی ایران در جلسه علنی روز گذشته لایحه بودجه سال آینده را بررسی کرد. نمایندگان مجلس در این جلسه به بحث و بررسی جزئیات بودجه پرداختند و پیشنهادات مختلفی برای بهبود آن ارائه دادند. وزیر اقتصاد نیز در این جلسه حضور یافت و به سوالات نمایندگان پاسخ داد. بر اساس این لایحه، بودجه عمومی کشور نسبت به سال جاری افزایش قابل توجهی خواهد داشت. همچنین اعتبارات ویژه‌ای برای توسعه زیرساخت‌های کشور در نظر گرفته شده است. نمایندگان بر لزوم شفافیت در هزینه‌کرد بودجه تأکید کردند و خواستار نظارت دقیق‌تر بر اجرای برنامه‌های توسعه‌ای شدند.
133
  """,
134
 
135
  "مقاله علمی": """
136
+ هوش مصنوعی در دهه‌های اخیر به یکی از مهم‌ترین فناوری‌های نوین تبدیل شده است. این فناوری کاربردهای گسترده‌ای در زمینه‌های مختلف نظیر پزشکی، آموزش، حمل و نقل و صنعت دارد. یادگیری ماشین که بخش مهمی از هوش مصنوعی محسوب می‌شود، امکان تحلیل داده‌های پیچیده و الگویابی را فراهم می‌کند. شبکه‌های عصبی مصنوعی نیز با الهام از مغز انسان طراحی شده‌اند و قابلیت‌های شگفت‌انگیزی در تشخیص الگو و پردازش تصویر دارند. با این حال، چالش‌هایی نظیر اخلاق در هوش مصنوعی و حفظ حریم خصوصی همچنان وجود دارد. محققان بر لزوم توسعه هوش مصنوعی مسئولانه تأکید می‌کنند تا از مزایای این فناوری استفاده کرده و از مضرات احتمالی آن جلوگیری شود.
137
  """,
138
 
139
  "متن ادبی": """
140
+ در باغ گل‌های سرخ، پیرمردی با موهای سفید نشسته بود و به آسمان آبی نگاه می‌کرد. نسیم ملایم صبحگاهی برگ‌های درختان را به رقص درآورده بود. صدای آب نهری که از دور می‌آمد، آرامش خاصی به فضا می‌بخشید. پیرمرد در دل خود به یاد روزهای جوانی‌اش بود، زمانی که این باغ را با دستان خود کاشته بود. اکنون پس از سال‌ها، میوه زحماتش را می‌دید. گل‌های رنگارنگ، درختان سایه‌دار و آرامش این مکان، همه نشان از عشق و دلبستگی او به این باغ داشت. او لبخندی بر لب داشت، لبخندی که حاکی از رضایت و آرامش درونی بود. این باغ نه تنها مکانی برای استراحت، بلکه خانه‌ای برای خاطرات شیرین او بود.
141
  """
142
  }
143
 
144
  # Create Gradio interface
145
  with gr.Blocks(
146
+ title="خلاصه‌ساز متن فارسی - نسخه سبک",
147
  theme=gr.themes.Soft(),
148
  css="""
149
  .persian-text {
 
162
  gr.HTML("""
163
  <div class="main-header">
164
  <h1>🤖 خلاصه‌ساز هوشمند متن فارسی</h1>
165
+ <p><strong>Persian Text Summarization Tool - Lightweight Version</strong></p>
166
+ <p>این ابزار با روش استخراجی پیشرفته، متن‌های فارسی را خلاصه می‌کند</p>
167
  </div>
168
  """)
169
 
 
171
  with gr.Column(scale=2):
172
  gr.Markdown("## 📝 متن ورودی")
173
 
174
+ # Method info
175
+ gr.HTML("""
176
+ <div style="padding: 10px; background-color: #e3f2fd; border-radius: 5px; margin-bottom: 10px;">
177
+ <strong>⚡ روش:</strong> خلاصه‌سازی استخراجی پیشرفته<br>
178
+ <strong>✅ مزیت:</strong> سریع، پایدار و کاملاً فارسی<br>
179
+ <strong>🎯 کیفیت:</strong> بالا برای متن‌های فارسی
180
+ </div>
181
+ """)
182
 
183
  # Sample text selector
184
  sample_selector = gr.Dropdown(
 
232
  3. **طول خلاصه را تعیین کنید**: کوتاه، متوسط یا بلند
233
  4. **دکمه خلاصه‌سازی را بزنید**: منتظر بمانید تا خلاصه تولید شود
234
 
235
+ ### ویژگی‌های نسخه سبک:
236
+ - ✅ سریع و پایدار (بدون نیاز به مدل‌های سنگین)
237
+ - ✅ کاملاً فارسی (هیچ ترجمه‌ای انجام نمی‌شود)
238
+ - ✅ کیفیت بالا برای متن‌های فارسی
239
+ - ✅ مناسب برای همه سرورها
240
+ - ✅ روش استخراجی هوشمند
241
+ - ✅ امتیازدهی پیشرفته به جملات
242
 
243
  ### نکات:
244
  - متن ورودی باید حداقل 100 کاراکتر باشد
245
+ - جملات ابتدایی و میانی متن امتیاز بیشتری دریافت می‌کنند
246
+ - این نسخه برای استقرار آسان طراحی شده است
247
+ - هیچ وابستگی پیچیده‌ای ندارد
248
  """)
249
 
250
  # Event handlers