leilaghomashchi commited on
Commit
f1ee021
·
verified ·
1 Parent(s): 9086f5c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +85 -80
app.py CHANGED
@@ -39,55 +39,41 @@ class AdvancedGroqAnonymizer:
39
  * درصدها (٪) و بازه‌های درصد → `percent-XX` (مثال بازه: `percent-05–percent-07`)
40
  * شاخص‌ها/علائم مالی (EPS, P/E, ARPU, NPL و…) باقی بمانند؛ فقط مقدارشان ناشناس شود (`EPS amount-01 ریال`, `P/E amount-02`)
41
 
42
- ## قواعد اندیس‌گذاری
43
- * برای هر نوع برچسب، از `-01` شروع و افزایشی تخصیص دهید (شمارنده‌های هر نوع از هم مستقل‌اند).
44
- * پایداری «درون همان قطعه»: یک موجودیت در یک قطعه همیشه همان شناسه را نگه دارد.
45
- * عدم نیاز به پایداری بین قطعات/پاراگراف‌های مستقل.
 
 
46
 
47
  ## چه چیزهایی حفظ می‌شود؟
48
- * تاریخ‌ها/ساعت‌ها (مثل 1404/04/29، 31 اردیبهشت 1404) دست‌نخورده.
49
- * عناوین شغلی/نقش‌ها (مدیرعامل، بازرس قانونی، …).
50
- * واحدها و اصطلاحات فنی (همت، میلیارد ریال، تُن، TEU، EPS، P/E، ARPU، NPL، …).
51
- * نام مکان‌ها/آدرس‌ها/محل برگزاری رویدادها اصولاً حفظ می‌شوند (مگر صریحاً سیاست دیگری داده شود).
52
- * ساختار جمله، روابط علّی/مقایسه‌ای، نتیجه‌گیری‌ها و لحن.
 
53
 
54
- ## قواعد جایگزینی
55
- 1. هر اسم خاص سازمانی/برندی/رسانه‌ای `company-XX` (بانک مرکزی، سامانه کدال، بیمه مرکزی، … نیز سازمان‌اند.)
56
- 2. هر نام شخص`person-XX` (عنوان شغلی حفظ شود).
57
- 3. هر عدد مستقل یا همراه واحد `amount-XX` + واحد.
58
- 4. هر درصد`percent-XX`؛ در بازه‌ها با خط تیره بدون فاصله.
59
- 5. اعداد چسبیده به واژه («5هزار») → بخش عددی ناشناس شود: `amount-01 هزار`.
60
- 6. مدل/سری محصول (مثل G10) معمولاً حفظ می‌شود؛ اگر سیاست پوشش کامل ارقام سری لازم بود: «Gamount-XX».
61
- 7. اگر درباره‌ی نوع برچسب مردد بودید، اولویت با `company-XX` (برای موجودیت‌های حقوقی) است.
62
 
63
- ## کنترل کیفیت (برای هر قطعه)
64
- * هر موجودیت در همان قطعه شناسه ثابت دارد.
65
- * نوع برچسب با ماهیت موجودیت سازگار است (شخص≠شرکت).
66
- * همه‌ی اعداد و درصدها پوشانده و واحدها حفظ شده‌اند.
67
- * تاریخ/ساعت حفظ شده است.
68
- * اندیس‌ها از 01 شروع و پیوسته‌اند (به‌تفکیک نوع).
69
- * هیچ توضیح یا کروشه اضافه به متن ناشناس‌شده افزوده نشده است.
70
 
71
- ## قالب خروجی
72
- برای هر ورودی، **صرفاً متن ناشناس‌شده** را برگردان. هیچ توضیح، سربرگ، یا نشانه‌گذاری اضافه ننوی��. زبان و علائم نگارشی اصلی را حفظ کن.
73
 
74
- ## مثال‌های کوتاه
75
- **مثال 1:**
76
- ورودی: «بانک پاسارگاد با شناسایی سود خالص 155 هزار میلیارد ریالی…»
77
- خروجی: «company-01 با شناسایی سود خالص amount-01 هزار میلیارد ریالی…»
78
-
79
- **مثال 2:**
80
- ورودی: «مهدی اخوان بهابادی، مدیرعامل همراه اول، گفت سود خالص 7101 میلیارد تومان شد و EPS به 936 ریال رسید.»
81
- خروجی: «person-01، مدیرعامل company-01، گفت سود خالص amount-01 میلیارد تومان شد و EPS به amount-02 ریال رسید.»
82
-
83
- **مثال 3:**
84
- ورودی: «هزینه لجستیکی بوعلی حدود 100 میلیون دلار بود؛ 40٪ خوراک از خط لوله و 60٪ معادل 1 تا 1.5 میلیون تن.»
85
- خروجی: «هزینه لجستیکی company-01 حدود amount-01 میلیون دلار بود؛ percent-01 خوراک از خط لوله و percent-02 معادل amount-02 تا amount-03 میلیون تن.»
86
-
87
- ## نکات لبه‌ای
88
- * بازه‌های عددی/درصدی: `amount-01–amount-02` / `percent-01–percent-02`.
89
- * اعداد سریالی سند/ثبت/شماره ملی/شماره ثبت: عدد → `amount-XX`، عنوان/واژه‌ها حفظ.
90
- * اگر یک نام هم‌زمان برند محصول و شرکت است، در متن مالی/حاکمیتی آن را شرکت فرض کنید (`company-XX`).
91
 
92
  فقط متن ناشناس‌شده را برگردان، بدون هیچ توضیح اضافی."""
93
 
@@ -162,7 +148,7 @@ class AdvancedGroqAnonymizer:
162
  "statistics": analysis["statistics"],
163
  "detailed_analysis": analysis["detailed_analysis"],
164
  "usage": response.get("usage", {}),
165
- "quality_check": self._quality_check(content)
166
  }
167
 
168
  except Exception as e:
@@ -230,46 +216,54 @@ class AdvancedGroqAnonymizer:
230
  "detailed_analysis": detailed_analysis
231
  }
232
 
233
- def _quality_check(self, text: str) -> Dict[str, Any]:
234
- """بررسی کیفیت ناشناس‌سازی"""
235
  import re
236
 
237
- # بررسی شروع اندیس‌ها از 01
238
- company_indices = [int(x) for x in re.findall(r'company-(\d+)', text)]
239
- person_indices = [int(x) for x in re.findall(r'person-(\d+)', text)]
240
- amount_indices = [int(x) for x in re.findall(r'amount-(\d+)', text)]
241
- percent_indices = [int(x) for x in re.findall(r'percent-(\d+)', text)]
242
-
243
- issues = []
244
 
245
- # بررسی شروع از 01
246
- for entity_type, indices in [
247
- ("company", company_indices),
248
- ("person", person_indices),
249
- ("amount", amount_indices),
250
- ("percent", percent_indices)
251
- ]:
252
- if indices and min(indices) != 1:
253
- issues.append(f"اندیس {entity_type} از 01 شروع نشده")
254
 
255
- # بررسی پیوستگی اندیس‌ها
256
  for entity_type, indices in [
257
- ("company", company_indices),
258
- ("person", person_indices),
259
- ("amount", amount_indices),
260
- ("percent", percent_indices)
 
261
  ]:
262
  if indices:
263
- unique_indices = sorted(list(set(indices)))
 
 
 
 
 
264
  expected = list(range(1, len(unique_indices) + 1))
265
  if unique_indices != expected:
266
- issues.append(f"اندیس‌های {entity_type} پیوسته نیستند")
 
 
 
 
 
 
267
 
268
  return {
269
- "passed": len(issues) == 0,
270
- "issues": issues,
271
- "total_checks": 8,
272
- "passed_checks": 8 - len(issues)
 
 
 
 
 
273
  }
274
 
275
  def create_advanced_interface():
@@ -513,7 +507,7 @@ def create_advanced_interface():
513
  quality = result.get("quality_check", {})
514
  quality_md = "✅ **کنترل کیفیت:**\n\n"
515
 
516
- if quality.get("passed", False):
517
  quality_md += '<span class="quality-badge quality-pass">✅ تمام بررسی‌ها موفق</span>\n\n'
518
  else:
519
  quality_md += '<span class="quality-badge quality-fail">❌ مشکلاتی یافت شد</span>\n\n'
@@ -523,7 +517,12 @@ def create_advanced_interface():
523
  for issue in issues:
524
  quality_md += f"• {issue}\n"
525
 
526
- quality_md += f"\n**نتیجه:** {quality.get('passed_checks', 0)}/{quality.get('total_checks', 0)} بررسی موفق"
 
 
 
 
 
527
 
528
  # موجودیت‌های شناسایی شده
529
  entities = result.get("entities", {})
@@ -587,7 +586,7 @@ def create_advanced_interface():
587
 
588
  def clear_all():
589
  """پاک کردن تمام فیلدها"""
590
- return "", "", "", "", "", "", gr.Textbox(visible=False)
591
 
592
  # اتصال رویدادها
593
  anonymize_btn.click(
@@ -610,17 +609,17 @@ def create_advanced_interface():
610
  # مثال‌های پیشرفته
611
  gr.Examples(
612
  examples=[
 
613
  ["بانک پاسارگاد با شناسایی سود خالص 155 هزار میلیارد ریالی در ردۀ دوم سودآورترین بانک‌های کشور قرار گرفت."],
614
  ["مهدی اخوان بهابادی، مدیرعامل همراه اول، اعلام کرد درآمد عملیاتی شرکت با رشد 37 درصدی به 70 هزار و 677 میلیارد تومان رسیده است."],
615
  ["هزینه لجستیکی بوعلی حدود 100 میلیون دلار بود؛ 40٪ خوراک از خط لوله و 60٪ معادل 1 تا 1.5 میلیون تن در سال."],
616
- ["مجمع عمومی در تاریخ 1404/04/29 ساعت 10:00 در هتل بزرگ نخل کنگان برگزار شد و علی محمدی، رئیس هیئت مدیره، گزارش عملکرد ار��ئه داد."],
617
  ["گروه دتا با سود خالص 45.3 میلیارد تومان و EPS برابر 2850 ریال، رشد 15.7 درصدی نسبت به مدت مشابه سال قبل داشته است."]
618
  ],
619
  inputs=input_text,
620
  label="📚 مثال‌های پیشرفته آزمایشی"
621
  )
622
 
623
- # راهنمای کامل
624
  with gr.Accordion("📖 راهنمای کامل استفاده", open=False):
625
  gr.Markdown("""
626
  ## 🎯 ویژگی‌های سیستم پیشرفته:
@@ -645,15 +644,21 @@ def create_advanced_interface():
645
  - بررسی پیوستگی اندیس‌ها
646
  - تضمین ثبات شناسه‌ها در یک متن
647
  - حفظ واحدها و شاخص‌های مالی
 
648
 
649
  ### 💡 نکات مهم:
650
  - هر نوع موجودیت شماره‌گذاری مستقل دارد
651
  - در بازه‌های عددی: amount-01–amount-02
652
  - برای درصدها: percent-01–percent-02
653
  - اعداد چسبیده: "5هزار" → "amount-01 هزار"
 
 
 
 
 
654
  """)
655
-
656
- return interface
657
 
658
  # اجرای برنامه
659
  if __name__ == "__main__":
 
39
  * درصدها (٪) و بازه‌های درصد → `percent-XX` (مثال بازه: `percent-05–percent-07`)
40
  * شاخص‌ها/علائم مالی (EPS, P/E, ARPU, NPL و…) باقی بمانند؛ فقط مقدارشان ناشناس شود (`EPS amount-01 ریال`, `P/E amount-02`)
41
 
42
+ ## قواعد اندیس‌گذاری **CRITICAL**
43
+ * **MUST START FROM 01**: هر نوع برچسب از -01 شروع شود: company-01, person-01, amount-01, percent-01
44
+ * **MUST BE SEQUENTIAL**: اندیس‌ها باید پیوسته باشند: company-01, company-02, company-03 (نه company-01, company-13)
45
+ * **SEPARATE COUNTERS**: شمارنده‌های هر نوع از هم مستقل‌اند
46
+ * **CONSISTENCY**: یک موجودیت در متن همیشه همان شناسه را داشته باشد
47
+ * **NO GAPS**: هیچ خلاء در شماره‌گذاری نباشد
48
 
49
  ## چه چیزهایی حفظ می‌شود؟
50
+ * تاریخ‌ها/ساعت‌ها (مثل 1404/04/29، 30 آذر 1403) دست‌نخورده
51
+ * عناوین شغلی/نقش‌ها (مدیرعامل، بازرس قانونی)
52
+ * واحدها و اصطلاحات فنی (میلیارد تومان، درصد، زیان، درآمد، حمل، پردازش)
53
+ * شاخص‌های مالی (EPS, P/E) - فقط مقدار ناشناس شود
54
+ * کلمات عمومی فارسی و ساختار جمله
55
+ * نام مکان‌ها (در صورت عدم حساسیت)
56
 
57
+ ## قواعد جایگزینی **STRICT**
58
+ 1. شرکت آسان پادرو → company-01
59
+ 2. سرزمین هوشمند پادcompany-02
60
+ 3. بانک پاسارگادcompany-03
61
+ 4. هر عدد (6، 30، 97، 60) amount-01, amount-02, amount-03, amount-04 (به ترتیب ظهور)
62
+ 5. هر درصد (97 درصد، 60 درصد) → percent-01, percent-02
63
+ 6. کلمات انگلیسی اضافی یا غیرضروری نباید اضافه شود
64
+ 7. کلمات فارسی مانند "مقایسه" نباید به "comparison" تبدیل شود
65
 
66
+ ## مثال دقیق برای متن نمونه:
67
+ ورودی: «شرکت آسان پادرو منتهی به 30 آذر 1403 نشان می‌دهد این شرکت سال مالی جاری بیش از 6 میلیارد تومان زیان... سرزمین هوشمند پاد (زیرمجموعه بانک پاسارگاد)»
 
 
 
 
 
68
 
69
+ خروجی صحیح: «company-01 منتهی به 30 آذر 1403 نشان می‌دهد این شرکت سال مالی جاری بیش از amount-01 میلیارد تومان زیان... company-02 (زیرمجموعه company-03)»
 
70
 
71
+ ## کنترل کیفیت نهایی
72
+ - company-01, company-02, company-03 (پیوسته و بدون گپ)
73
+ - amount-01, amount-02, amount-03, amount-04 (پیوسته و بدون گپ)
74
+ - percent-01, percent-02 (پیوسته و بدون گپ)
75
+ - هیچ کلمه انگلیسی اضافی نباشد
76
+ - ساختار و معنای فارسی حفظ شود
 
 
 
 
 
 
 
 
 
 
 
77
 
78
  فقط متن ناشناس‌شده را برگردان، بدون هیچ توضیح اضافی."""
79
 
 
148
  "statistics": analysis["statistics"],
149
  "detailed_analysis": analysis["detailed_analysis"],
150
  "usage": response.get("usage", {}),
151
+ "quality_check": self._validate_anonymized_text(content)
152
  }
153
 
154
  except Exception as e:
 
216
  "detailed_analysis": detailed_analysis
217
  }
218
 
219
+ def _validate_anonymized_text(self, text: str) -> Dict[str, Any]:
220
+ """اعتبارسنجی پیشرفته متن ناشناس‌شده"""
221
  import re
222
 
223
+ # استخراج همه موجودیت‌ها
224
+ companies = re.findall(r'company-(\d+)', text)
225
+ persons = re.findall(r'person-(\d+)', text)
226
+ amounts = re.findall(r'amount-(\d+)', text)
227
+ percents = re.findall(r'percent-(\d+)', text)
228
+ groups = re.findall(r'group-(\d+)', text)
 
229
 
230
+ validation_issues = []
 
 
 
 
 
 
 
 
231
 
232
+ # بررسی هر نوع موجودیت
233
  for entity_type, indices in [
234
+ ("company", companies),
235
+ ("person", persons),
236
+ ("amount", amounts),
237
+ ("percent", percents),
238
+ ("group", groups)
239
  ]:
240
  if indices:
241
+ unique_indices = sorted(list(set([int(x) for x in indices])))
242
+ # بررسی شروع از 1
243
+ if unique_indices[0] != 1:
244
+ validation_issues.append(f"اندیس {entity_type} از 01 شروع نشده (شروع: {unique_indices[0]:02d})")
245
+
246
+ # بررسی پیوستگی
247
  expected = list(range(1, len(unique_indices) + 1))
248
  if unique_indices != expected:
249
+ validation_issues.append(f"اندیس‌های {entity_type} پیوسته نیستند: {[f'{x:02d}' for x in unique_indices]}")
250
+
251
+ # بررسی کلمات انگلیسی غیرضروری
252
+ english_words = re.findall(r'\b[a-zA-Z]+\b', text)
253
+ unwanted_english = [word for word in english_words if word.lower() not in ['eps', 'p/e', 'arpu', 'npl', 'roe', 'roa']]
254
+ if unwanted_english:
255
+ validation_issues.append(f"کلمات انگلیسی غیرضروری: {unwanted_english}")
256
 
257
  return {
258
+ "is_valid": len(validation_issues) == 0,
259
+ "issues": validation_issues,
260
+ "entity_counts": {
261
+ "company": len(set(companies)),
262
+ "person": len(set(persons)),
263
+ "amount": len(set(amounts)),
264
+ "percent": len(set(percents)),
265
+ "group": len(set(groups))
266
+ }
267
  }
268
 
269
  def create_advanced_interface():
 
507
  quality = result.get("quality_check", {})
508
  quality_md = "✅ **کنترل کیفیت:**\n\n"
509
 
510
+ if quality.get("is_valid", False):
511
  quality_md += '<span class="quality-badge quality-pass">✅ تمام بررسی‌ها موفق</span>\n\n'
512
  else:
513
  quality_md += '<span class="quality-badge quality-fail">❌ مشکلاتی یافت شد</span>\n\n'
 
517
  for issue in issues:
518
  quality_md += f"• {issue}\n"
519
 
520
+ entity_counts = quality.get("entity_counts", {})
521
+ if entity_counts:
522
+ quality_md += f"\n**تعداد موجودیت‌های منحصربه‌فرد:**\n"
523
+ for entity_type, count in entity_counts.items():
524
+ if count > 0:
525
+ quality_md += f"• {entity_type}: {count}\n"
526
 
527
  # موجودیت‌های شناسایی شده
528
  entities = result.get("entities", {})
 
586
 
587
  def clear_all():
588
  """پاک کردن تمام فیلدها"""
589
+ return "", "", "", "", "", "", "", gr.Textbox(visible=False)
590
 
591
  # اتصال رویدادها
592
  anonymize_btn.click(
 
609
  # مثال‌های پیشرفته
610
  gr.Examples(
611
  examples=[
612
+ ["صورت‌های مالی حسابرسی شده شرکت آسان پادرو منتهی به 30 آذر 1403 نشان می‌دهد این شرکت سال مالی جاری بیش از 6 میلیارد تومان زیان خالص شناسایی کرده است. پادرو سال مالی 1403 حدود 30 میلیارد تومان درآمد عملیاتی کسب کرد که این رقم در مقایسه با سال 1402 رشد تقریباً دوبرابری دارد. 97 درصد درآمد پادرو از «پردازش حمل» است که مربوط به مشتریان متقاضی خدمات پستی بوده و بیش از 60 درصد درآمد آن از سرزمین هوشمند پاد (زیرمجموعه بانک پاسارگاد) و بابت حمل مرسوله کارت‌های بانکی است."],
613
  ["بانک پاسارگاد با شناسایی سود خالص 155 هزار میلیارد ریالی در ردۀ دوم سودآورترین بانک‌های کشور قرار گرفت."],
614
  ["مهدی اخوان بهابادی، مدیرعامل همراه اول، اعلام کرد درآمد عملیاتی شرکت با رشد 37 درصدی به 70 هزار و 677 میلیارد تومان رسیده است."],
615
  ["هزینه لجستیکی بوعلی حدود 100 میلیون دلار بود؛ 40٪ خوراک از خط لوله و 60٪ معادل 1 تا 1.5 میلیون تن در سال."],
 
616
  ["گروه دتا با سود خالص 45.3 میلیارد تومان و EPS برابر 2850 ریال، رشد 15.7 درصدی نسبت به مدت مشابه سال قبل داشته است."]
617
  ],
618
  inputs=input_text,
619
  label="📚 مثال‌های پیشرفته آزمایشی"
620
  )
621
 
622
+ # راهنمای کامل
623
  with gr.Accordion("📖 راهنمای کامل استفاده", open=False):
624
  gr.Markdown("""
625
  ## 🎯 ویژگی‌های سیستم پیشرفته:
 
644
  - بررسی پیوستگی اندیس‌ها
645
  - تضمین ثبات شناسه‌ها در یک متن
646
  - حفظ واحدها و شاخص‌های مالی
647
+ - شناسایی کلمات انگلیسی غیرضروری
648
 
649
  ### 💡 نکات مهم:
650
  - هر نوع موجودیت شماره‌گذاری مستقل دارد
651
  - در بازه‌های عددی: amount-01–amount-02
652
  - برای درصدها: percent-01–percent-02
653
  - اعداد چسبیده: "5هزار" → "amount-01 هزار"
654
+
655
+ ### 🔧 مثال صحیح برای متن شما:
656
+ **ورودی:** صورت‌های مالی حسابرسی شده شرکت آسان پادرو منتهی به 30 آذر 1403 نشان می‌دهد این شرکت سال مالی جاری بیش از 6 میلیارد تومان زیان خالص شناسایی کرده است...
657
+
658
+ **خروجی مطلوب:** صورت‌های مالی حسابرسی شده company-01 منتهی به 30 آذر 1403 نشان می‌دهد این شرکت سال مالی جاری بیش از amount-01 میلیارد تومان زیان خالص شناسایی کرده است...
659
  """)
660
+
661
+ return interface
662
 
663
  # اجرای برنامه
664
  if __name__ == "__main__":