citoreh commited on
Commit
dbd9e8d
·
verified ·
1 Parent(s): 6c73e86

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +331 -0
app.py ADDED
@@ -0,0 +1,331 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import re
3
+ from typing import Dict, List
4
+
5
+ class PersianVowelizer:
6
+ """
7
+ A rule-based Persian vowel mark (diacritic) system.
8
+ This is a simplified version - for production use, consider using
9
+ pre-trained models like BERT-based Persian vocalization models.
10
+ """
11
+
12
+ def __init__(self):
13
+ # Persian vowel marks (diacritics)
14
+ self.vowel_marks = {
15
+ 'fatha': '\u064E', # َ (a)
16
+ 'kasra': '\u0650', # ِ (e/i)
17
+ 'damma': '\u064F', # ُ (o/u)
18
+ 'sukun': '\u0652', # ْ (silence)
19
+ 'shadda': '\u0651', # ّ (doubling)
20
+ 'tanwin_fath': '\u064B', # ً
21
+ 'tanwin_kasr': '\u064D', # ٍ
22
+ 'tanwin_damm': '\u064C', # ٌ
23
+ }
24
+
25
+ # Common Persian words with their vocalized forms
26
+ self.common_words = {
27
+ 'سلام': 'سَلام',
28
+ 'خوب': 'خوب',
29
+ 'بد': 'بَد',
30
+ 'خانه': 'خانِه',
31
+ 'مدرسه': 'مَدرِسِه',
32
+ 'کتاب': 'کِتاب',
33
+ 'آب': 'آب',
34
+ 'نان': 'نان',
35
+ 'دوست': 'دوست',
36
+ 'عشق': 'عِشق',
37
+ 'زندگی': 'زِندِگی',
38
+ 'کار': 'کار',
39
+ 'خواهر': 'خواهَر',
40
+ 'برادر': 'بَرادَر',
41
+ 'مادر': 'مادَر',
42
+ 'پدر': 'پِدَر',
43
+ 'فرد': 'فَرد',
44
+ 'شب': 'شَب',
45
+ 'روز': 'روز',
46
+ 'صبح': 'صُبح',
47
+ 'عصر': 'عَصر',
48
+ 'شام': 'شام',
49
+ 'درس': 'دَرس',
50
+ 'استاد': 'اُستاد',
51
+ 'دانشجو': 'دانِشجو',
52
+ 'دانشگاه': 'دانِشگاه',
53
+ 'شهر': 'شَهر',
54
+ 'روستا': 'روستا',
55
+ 'کشور': 'کِشوَر',
56
+ 'ایران': 'ایران',
57
+ 'فارسی': 'فارسی',
58
+ 'زبان': 'زَبان',
59
+ 'کلام': 'کَلام',
60
+ 'سخن': 'سُخن',
61
+ 'گفتن': 'گُفتَن',
62
+ 'رفتن': 'رَفتَن',
63
+ 'آمدن': 'آمَدَن',
64
+ 'خوردن': 'خوردَن',
65
+ 'نوشتن': 'نِویسیدَن',
66
+ 'خواندن': 'خواندَن',
67
+ 'دیدن': 'دیدَن',
68
+ 'شنیدن': 'شِنیدَن',
69
+ 'فهمیدن': 'فَهمیدَن',
70
+ 'دانستن': 'دانِستَن',
71
+ 'بودن': 'بودَن',
72
+ 'کردن': 'کَردَن',
73
+ 'داشتن': 'داشتَن',
74
+ 'گذاشتن': 'گُذاشتَن',
75
+ 'نشستن': 'نِشَستَن',
76
+ 'ایستادن': 'ایستادَن',
77
+ 'خوابیدن': 'خوابیدَن',
78
+ 'بیدار': 'بیدار',
79
+ 'خسته': 'خَستِه',
80
+ 'شاد': 'شاد',
81
+ 'غمگین': 'غَمگین',
82
+ 'خوشحال': 'خوشحال',
83
+ 'عاشق': 'عاشِق',
84
+ 'دوستدار': 'دوستدار',
85
+ 'محبت': 'مُحِبَّت',
86
+ 'عشق': 'عِشق',
87
+ 'نفرت': 'نَفرَت',
88
+ 'ترس': 'تَرس',
89
+ 'امید': 'اُمید',
90
+ 'آرزو': 'آرِزو',
91
+ 'خواب': 'خواب',
92
+ 'رویا': 'رؤیا'
93
+ }
94
+
95
+ # Pattern-based rules for common Persian structures
96
+ self.patterns = [
97
+ # Past tense patterns
98
+ (r'(\w+)ید', r'\1ید'), # -id ending
99
+ (r'(\w+)د', r'\1َد'), # -ad ending for past tense
100
+
101
+ # Present tense patterns
102
+ (r'می(\w+)', r'می\1'), # mi- prefix
103
+ (r'(\w+)م', r'\1َم'), # -am ending
104
+ (r'(\w+)ی', r'\1ی'), # -i ending
105
+ (r'(\w+)د', r'\1َد'), # -ad ending
106
+ (r'(\w+)یم', r'\1یم'), # -im ending
107
+ (r'(\w+)ید', r'\1ید'), # -id ending
108
+ (r'(\w+)ند', r'\1َند'), # -and ending
109
+ ]
110
+
111
+ def add_vowel_marks(self, text: str) -> str:
112
+ """
113
+ Add vowel marks to Persian text using dictionary lookup and pattern matching.
114
+ """
115
+ if not text.strip():
116
+ return text
117
+
118
+ # Split text into words while preserving spaces and punctuation
119
+ words = re.findall(r'\S+|\s+', text)
120
+ vocalized_words = []
121
+
122
+ for word in words:
123
+ if word.isspace() or not re.search(r'[\u0600-\u06FF]', word):
124
+ # Skip whitespace and non-Persian characters
125
+ vocalized_words.append(word)
126
+ continue
127
+
128
+ # Clean word for lookup (remove punctuation)
129
+ clean_word = re.sub(r'[^\u0600-\u06FF]', '', word)
130
+
131
+ # Try dictionary lookup first
132
+ if clean_word in self.common_words:
133
+ # Replace the Persian part with vocalized version
134
+ vocalized_word = word.replace(clean_word, self.common_words[clean_word])
135
+ vocalized_words.append(vocalized_word)
136
+ else:
137
+ # Apply pattern-based rules
138
+ vocalized_word = word
139
+ for pattern, replacement in self.patterns:
140
+ vocalized_word = re.sub(pattern, replacement, vocalized_word)
141
+
142
+ # Add basic vowel marks based on common patterns
143
+ vocalized_word = self._apply_basic_rules(vocalized_word)
144
+ vocalized_words.append(vocalized_word)
145
+
146
+ return ''.join(vocalized_words)
147
+
148
+ def _apply_basic_rules(self, word: str) -> str:
149
+ """
150
+ Apply basic vowel marking rules to Persian words.
151
+ """
152
+ # This is a simplified approach - real vocalization needs more sophisticated rules
153
+ result = word
154
+
155
+ # Add fatha to common consonant patterns
156
+ result = re.sub(r'([بپتثجچحخدذرزژسشصضطظعغفقکگلمنوهی])([بپتثجچحخدذرزژسشصضطظعغفقکگلمنوهی])',
157
+ r'\1َ\2', result)
158
+
159
+ return result
160
+
161
+ def vocalize_persian_text(text: str) -> str:
162
+ """
163
+ Main function to add vowel marks to Persian text.
164
+ """
165
+ if not text.strip():
166
+ return "لطفاً متنی وارد کنید."
167
+
168
+ vowelizer = PersianVowelizer()
169
+ vocalized_text = vowelizer.add_vowel_marks(text)
170
+ return vocalized_text
171
+
172
+ # Custom CSS for RTL support and Persian fonts
173
+ custom_css = """
174
+ .rtl-text {
175
+ direction: rtl !important;
176
+ text-align: right !important;
177
+ font-family: 'Vazir', 'Tahoma', 'Arial Unicode MS', sans-serif !important;
178
+ font-size: 16px !important;
179
+ line-height: 1.6 !important;
180
+ }
181
+
182
+ .rtl-text textarea {
183
+ direction: rtl !important;
184
+ text-align: right !important;
185
+ font-family: 'Vazir', 'Tahoma', 'Arial Unicode MS', sans-serif !important;
186
+ font-size: 16px !important;
187
+ }
188
+
189
+ .rtl-text .output-text {
190
+ direction: rtl !important;
191
+ text-align: right !important;
192
+ font-family: 'Vazir', 'Tahoma', 'Arial Unicode MS', sans-serif !important;
193
+ font-size: 18px !important;
194
+ background-color: #f8f9fa !important;
195
+ padding: 15px !important;
196
+ border-radius: 8px !important;
197
+ border: 1px solid #dee2e6 !important;
198
+ min-height: 100px !important;
199
+ }
200
+
201
+ /* Import Persian fonts */
202
+ @import url('https://cdn.jsdelivr.net/gh/rastikerdar/vazir-font@v30.1.0/dist/font-face.css');
203
+
204
+ .gradio-container {
205
+ max-width: 900px !important;
206
+ margin: auto !important;
207
+ }
208
+
209
+ .title-text {
210
+ text-align: center !important;
211
+ color: #2c3e50 !important;
212
+ margin-bottom: 20px !important;
213
+ }
214
+
215
+ .description-text {
216
+ text-align: center !important;
217
+ color: #7f8c8d !important;
218
+ margin-bottom: 30px !important;
219
+ }
220
+ """
221
+
222
+ # Sample Persian texts for examples
223
+ sample_texts = [
224
+ "سلام دوست عزیز چطوری؟",
225
+ "من دانشجوی دانشگاه تهران هستم",
226
+ "فردا به کتابخانه خواهم رفت",
227
+ "مادرم برای من غذای خوشمزه درست کرد",
228
+ "زبان فارسی زیبا و شیرین است"
229
+ ]
230
+
231
+ # Create Gradio interface
232
+ with gr.Blocks(css=custom_css, title="Persian Vowel Marks Generator") as demo:
233
+ gr.HTML("""
234
+ <div class="title-text">
235
+ <h1>🎯 افزودن اعراب به متن فارسی</h1>
236
+ </div>
237
+ <div class="description-text">
238
+ <p>این ابزار به شما کمک می‌کند تا اعراب (حرکات) را به متن فارسی اضافه کنید</p>
239
+ <p>Add vowel marks (diacritics) to Persian text</p>
240
+ </div>
241
+ """)
242
+
243
+ with gr.Row():
244
+ with gr.Column(scale=1):
245
+ input_text = gr.Textbox(
246
+ label="📝 متن فارسی (Persian Text Input)",
247
+ placeholder="متن فارسی خود را اینجا وارد کنید...",
248
+ lines=5,
249
+ rtl=True,
250
+ elem_classes=["rtl-text"]
251
+ )
252
+
253
+ with gr.Row():
254
+ submit_btn = gr.Button("🎯 افزودن اعراب", variant="primary", size="lg")
255
+ clear_btn = gr.Button("🗑️ پاک کردن", variant="secondary")
256
+
257
+ with gr.Column(scale=1):
258
+ output_text = gr.Textbox(
259
+ label="✨ متن با اعراب (Text with Vowel Marks)",
260
+ lines=5,
261
+ rtl=True,
262
+ elem_classes=["rtl-text"],
263
+ interactive=False
264
+ )
265
+
266
+ # Examples section
267
+ gr.HTML("<h3 style='text-align: center; margin-top: 30px;'>🔸 نمونه متن‌ها (Sample Texts)</h3>")
268
+
269
+ examples = gr.Examples(
270
+ examples=sample_texts,
271
+ inputs=input_text,
272
+ outputs=output_text,
273
+ fn=vocalize_persian_text,
274
+ cache_examples=False,
275
+ label="نمونه‌های آماده"
276
+ )
277
+
278
+ # Information section
279
+ with gr.Accordion("📚 راهنما و اطلاعات (Guide & Information)", open=False):
280
+ gr.HTML("""
281
+ <div style="direction: rtl; text-align: right; font-family: Vazir, Tahoma;">
282
+ <h4>🔹 نحوه استفاده:</h4>
283
+ <ul>
284
+ <li>متن فارسی خود را در کادر بالا وارد کنید</li>
285
+ <li>روی دکمه "افزودن اعراب" کلیک کنید</li>
286
+ <li>نتیجه در کادر سمت راست نمایش داده می‌شود</li>
287
+ </ul>
288
+
289
+ <h4>🔹 ویژگی‌ها:</h4>
290
+ <ul>
291
+ <li>پشتیبانی از متن راست به چپ</li>
292
+ <li>استفاده از فونت فارسی مناسب</li>
293
+ <li>افزودن اعراب بر اساس کلمات رایج</li>
294
+ <li>پشتیبانی از الگوهای گرامری فارسی</li>
295
+ </ul>
296
+
297
+ <h4>🔹 نکات مهم:</h4>
298
+ <ul>
299
+ <li>این سیستم بر اساس قوانین و واژگان رایج کار می‌کند</li>
300
+ <li>برای دقت بیشتر، از مدل‌های یادگیری ماشین پیشرفته استفاده کنید</li>
301
+ <li>اعراب اضافه شده ممکن است نیاز به ویرایش دستی داشته باشد</li>
302
+ </ul>
303
+ </div>
304
+ """)
305
+
306
+ # Event handlers
307
+ submit_btn.click(
308
+ fn=vocalize_persian_text,
309
+ inputs=input_text,
310
+ outputs=output_text
311
+ )
312
+
313
+ clear_btn.click(
314
+ fn=lambda: ("", ""),
315
+ outputs=[input_text, output_text]
316
+ )
317
+
318
+ input_text.submit(
319
+ fn=vocalize_persian_text,
320
+ inputs=input_text,
321
+ outputs=output_text
322
+ )
323
+
324
+ # Launch configuration
325
+ if __name__ == "__main__":
326
+ demo.launch(
327
+ server_name="0.0.0.0",
328
+ server_port=7860,
329
+ share=True,
330
+ debug=True
331
+ )