leilaghomashchi commited on
Commit
778cdc6
·
verified ·
1 Parent(s): d2d8070

Upload huggingface_setup (2).py

Browse files
Files changed (1) hide show
  1. huggingface_setup (2).py +550 -0
huggingface_setup (2).py ADDED
@@ -0,0 +1,550 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # =====================================
2
+ # فایل: app.py (کد اصلی برای HF Spaces)
3
+ # =====================================
4
+
5
+ import requests
6
+ import json
7
+ import gradio as gr
8
+ from typing import Dict, Any
9
+ import os
10
+ from dataclasses import dataclass
11
+
12
+ @dataclass
13
+ class GroqConfig:
14
+ """تنظیمات Groq API"""
15
+ api_key: str
16
+ base_url: str = "https://api.groq.com/openai/v1"
17
+ model: str = "llama-3.1-8b-instant"
18
+ max_tokens: int = 1000
19
+ temperature: float = 0.1
20
+
21
+ class GroqAnonymizer:
22
+ """سیستم ناشناس‌سازی با استفاده از Groq"""
23
+
24
+ def __init__(self, api_key: str = None):
25
+ # در HF Spaces از متغیر محیطی کلید را بخوان
26
+ if api_key is None:
27
+ api_key = os.getenv("GROQ_API_KEY")
28
+ if not api_key:
29
+ raise ValueError("کلید API در متغیرهای محیطی یافت نشد. لطفاً GROQ_API_KEY را تنظیم کنید.")
30
+
31
+ self.config = GroqConfig(api_key=api_key)
32
+ self.system_prompt = self._create_system_prompt()
33
+
34
+ def _create_system_prompt(self) -> str:
35
+ """ایجاد دستورالعمل سیستمی برای Groq"""
36
+ return """شما یک سیستم ناشناس‌سازی متن فارسی هستید.
37
+
38
+ وظیفه: تشخیص و جایگزینی موجودیت‌های حساس:
39
+
40
+ 1. نام شرکت‌ها → company-01, company-02, ...
41
+ 2. نام افراد → person-01, person-02, ...
42
+ 3. مبالغ و اعداد → amount-01, amount-02, ...
43
+ 4. درصدها → percent-01, percent-02, ...
44
+
45
+ نکات:
46
+ - همان موجودیت = همان شماره
47
+ - پیشوندها (دکتر، آقا) را حفظ کنید
48
+ - فقط متن ناشناس‌سازی شده را برگردانید، بدون JSON یا توضیح اضافی
49
+
50
+ مثال:
51
+ ورودی: احمد رضایی مدیرعامل شرکت پارس 100 میلیون تومان درآمد دارد
52
+ خروجی: person-01 مدیرعامل company-01 amount-01 درآمد دارد"""
53
+
54
+ def _make_api_request(self, text: str) -> Dict[str, Any]:
55
+ """ارسال درخواست به Groq API"""
56
+ headers = {
57
+ "Authorization": f"Bearer {self.config.api_key}",
58
+ "Content-Type": "application/json"
59
+ }
60
+
61
+ payload = {
62
+ "messages": [
63
+ {
64
+ "role": "system",
65
+ "content": self.system_prompt
66
+ },
67
+ {
68
+ "role": "user",
69
+ "content": text
70
+ }
71
+ ],
72
+ "model": self.config.model,
73
+ "temperature": self.config.temperature,
74
+ "max_tokens": self.config.max_tokens
75
+ }
76
+
77
+ try:
78
+ print(f"DEBUG: Sending request to {self.config.base_url}/chat/completions")
79
+ print(f"DEBUG: Model: {self.config.model}")
80
+ print(f"DEBUG: Text length: {len(text)}")
81
+
82
+ response = requests.post(
83
+ f"{self.config.base_url}/chat/completions",
84
+ headers=headers,
85
+ json=payload,
86
+ timeout=30
87
+ )
88
+
89
+ print(f"DEBUG: Response status: {response.status_code}")
90
+
91
+ if response.status_code != 200:
92
+ print(f"DEBUG: Error response: {response.text}")
93
+
94
+ response.raise_for_status()
95
+ return response.json()
96
+
97
+ except requests.exceptions.RequestException as e:
98
+ print(f"DEBUG: Request exception: {str(e)}")
99
+ raise Exception(f"خطا در ارتباط با Groq API: {str(e)}")
100
+
101
+ def anonymize_text(self, text: str) -> Dict[str, Any]:
102
+ """ناشناس‌سازی متن با استفاده از Groq"""
103
+ if not text.strip():
104
+ return {
105
+ "success": False,
106
+ "error": "متن ورودی خالی است"
107
+ }
108
+
109
+ try:
110
+ response = self._make_api_request(text)
111
+
112
+ if "choices" not in response or not response["choices"]:
113
+ return {
114
+ "success": False,
115
+ "error": "پاسخ نامعتبر از API"
116
+ }
117
+
118
+ content = response["choices"][0]["message"]["content"]
119
+
120
+ # پاک کردن markdown اگر وجود دارد
121
+ if "```" in content:
122
+ lines = content.split('\n')
123
+ clean_lines = []
124
+ skip = False
125
+ for line in lines:
126
+ if line.strip().startswith('```'):
127
+ skip = not skip
128
+ continue
129
+ if not skip:
130
+ clean_lines.append(line)
131
+ content = '\n'.join(clean_lines)
132
+
133
+ # حذف خطوط اضافی و فضاهای خالی
134
+ content = content.strip()
135
+
136
+ return {
137
+ "success": True,
138
+ "anonymized_text": content,
139
+ "entities": [], # در حالت ساده entities نداریم
140
+ "statistics": self._count_entities(content),
141
+ "usage": response.get("usage", {})
142
+ }
143
+
144
+ except Exception as e:
145
+ return {
146
+ "success": False,
147
+ "error": f"خطا در پردازش: {str(e)}"
148
+ }
149
+
150
+ def _count_entities(self, text: str) -> Dict[str, int]:
151
+ """شمارش موجودیت‌ها در متن ناشناس‌سازی شده"""
152
+ import re
153
+
154
+ company_count = len(re.findall(r'company-\d+', text))
155
+ person_count = len(re.findall(r'person-\d+', text))
156
+ amount_count = len(re.findall(r'amount-\d+', text))
157
+ percent_count = len(re.findall(r'percent-\d+', text))
158
+ group_count = len(re.findall(r'group-\d+', text))
159
+
160
+ return {
161
+ "company": company_count,
162
+ "person": person_count,
163
+ "amount": amount_count,
164
+ "percent": percent_count,
165
+ "group": group_count
166
+ }
167
+
168
+ def create_interface():
169
+ """ایجاد رابط کاربری برای Hugging Face Spaces"""
170
+
171
+ # بررسی وجود کلید API
172
+ api_key_available = bool(os.getenv("GROQ_API_KEY"))
173
+
174
+ # CSS سفارشی
175
+ custom_css = """
176
+ .gradio-container {
177
+ font-family: 'Tahoma', 'Arial', sans-serif !important;
178
+ direction: rtl;
179
+ max-width: 1200px;
180
+ margin: 0 auto;
181
+ }
182
+ .result-box {
183
+ background-color: #f0f8ff;
184
+ border: 1px solid #ddd;
185
+ border-radius: 8px;
186
+ padding: 15px;
187
+ font-family: 'Tahoma', monospace;
188
+ line-height: 1.6;
189
+ }
190
+ .warning-box {
191
+ background-color: #fff3cd;
192
+ border: 1px solid #ffeaa7;
193
+ border-radius: 8px;
194
+ padding: 10px;
195
+ color: #856404;
196
+ }
197
+ .success-box {
198
+ background-color: #d4edda;
199
+ border: 1px solid #c3e6cb;
200
+ border-radius: 8px;
201
+ padding: 10px;
202
+ color: #155724;
203
+ }
204
+ """
205
+
206
+ with gr.Blocks(css=custom_css, title="ناشناس‌سازی متن فارسی", theme=gr.themes.Soft()) as interface:
207
+
208
+ # عنوان
209
+ gr.Markdown("""
210
+ # 🔒 سیستم ناشناس‌سازی متن فارسی
211
+ ### قدرت‌گرفته از Groq AI برای تشخیص و حفاظت از اطلاعات حساس
212
+
213
+ این سیستم قادر است نام افراد، شرکت‌ها، مبالغ مالی و درصدها را به صورت هوشمند تشخیص و ناشناس‌سازی کند.
214
+ """)
215
+
216
+ # ورود کلید API اگر در secrets موجود نباشد
217
+ if not api_key_available:
218
+ gr.Markdown("""
219
+ <div class="warning-box">
220
+ ⚠️ <strong>کلید API در متغیرهای محیطی یافت نشد</strong><br>
221
+ لطفاً کلید Groq API خود را در زیر وارد کنید یا در Settings > Secrets تنظیم کنید
222
+ </div>
223
+ """)
224
+
225
+ api_key_input = gr.Textbox(
226
+ label="🔑 کلید Groq API",
227
+ placeholder="gsk_...",
228
+ type="password",
229
+ value=""
230
+ )
231
+ else:
232
+ gr.Markdown("""
233
+ <div class="success-box">
234
+ ✅ <strong>سیستم آماده است</strong> - کلید API تنظیم شده
235
+ </div>
236
+ """)
237
+ api_key_input = gr.Textbox(visible=False)
238
+
239
+ with gr.Row():
240
+ with gr.Column(scale=1):
241
+ input_text = gr.Textbox(
242
+ label="📝 متن ورودی",
243
+ placeholder="متن خود را اینجا وارد کنید...",
244
+ lines=10,
245
+ max_lines=20
246
+ )
247
+
248
+ with gr.Row():
249
+ anonymize_btn = gr.Button(
250
+ "🔒 ناشناس‌سازی متن",
251
+ variant="primary",
252
+ size="lg"
253
+ )
254
+ clear_btn = gr.Button(
255
+ "🗑️ پاک کردن",
256
+ variant="secondary"
257
+ )
258
+
259
+ with gr.Column(scale=1):
260
+ output_text = gr.Textbox(
261
+ label="🎯 متن ناشناس‌سازی شده",
262
+ lines=10,
263
+ max_lines=20,
264
+ elem_classes=["result-box"]
265
+ )
266
+
267
+ # دکمه کپی
268
+ copy_btn = gr.Button(
269
+ "📋 کپی متن",
270
+ variant="secondary",
271
+ size="sm"
272
+ )
273
+
274
+ # متن برای کپی
275
+ copy_output = gr.Textbox(
276
+ label="📋 متن برای کپی (Ctrl+A و Ctrl+C)",
277
+ lines=3,
278
+ max_lines=10,
279
+ visible=False,
280
+ interactive=True
281
+ )
282
+
283
+ with gr.Row():
284
+ with gr.Column():
285
+ statistics_output = gr.Markdown(label="📊 آمار تشخیص")
286
+ with gr.Column():
287
+ usage_output = gr.Markdown(label="⚡ اطلاعات پردازش")
288
+
289
+ entities_output = gr.Markdown(label="📋 جزئیات تغییرات")
290
+
291
+ def process_text(text: str, api_key_manual: str = ""):
292
+ """پردازش متن"""
293
+ # تعیین کلید API - اولویت با manual input
294
+ final_api_key = api_key_manual.strip() if api_key_manual.strip() else os.getenv("GROQ_API_KEY")
295
+
296
+ if not final_api_key:
297
+ return (
298
+ "",
299
+ "❌ کلید API وارد نشده است. لطفاً در فیلد بالا وارد کنید یا در Settings تنظیم کنید.",
300
+ "",
301
+ ""
302
+ )
303
+
304
+ if not text.strip():
305
+ return (
306
+ "",
307
+ "❌ لطفاً متن ورودی را وارد کنید",
308
+ "",
309
+ ""
310
+ )
311
+
312
+ try:
313
+ anonymizer = GroqAnonymizer(api_key=final_api_key)
314
+ result = anonymizer.anonymize_text(text)
315
+
316
+ if not result["success"]:
317
+ return (
318
+ "",
319
+ f"❌ خطا: {result['error']}",
320
+ "",
321
+ ""
322
+ )
323
+
324
+ # آمار
325
+ stats = result.get("statistics", {})
326
+ stats_md = "📊 **آمار تشخیص:**\n\n"
327
+ total = sum(stats.values()) if stats else 0
328
+ stats_md += f"🔢 **کل موارد:** {total}\n\n"
329
+
330
+ type_names = {
331
+ 'company': 'شرکت‌ها',
332
+ 'person': 'افراد',
333
+ 'group': 'گروه‌ها',
334
+ 'amount': 'مبالغ',
335
+ 'percent': 'درصدها'
336
+ }
337
+
338
+ if stats:
339
+ for key, value in stats.items():
340
+ if value > 0:
341
+ name = type_names.get(key, key)
342
+ stats_md += f"• {name}: **{value}** مورد\n"
343
+
344
+ # اطلاعات پردازش
345
+ usage = result.get("usage", {})
346
+ usage_md = "⚡ **اطلاعات پردازش:**\n\n"
347
+ if usage:
348
+ usage_md += f"• مدل: Llama 3.1\n"
349
+ usage_md += f"• Token های ورودی: {usage.get('prompt_tokens', 'نامشخص')}\n"
350
+ usage_md += f"• Token های خروجی: {usage.get('completion_tokens', 'نامشخص')}\n"
351
+ else:
352
+ usage_md += "✅ پردازش با موفقیت انجام شد"
353
+
354
+ # جزئیات موجودیت‌ها
355
+ entities = result.get("entities", [])
356
+ entities_md = "📋 **جزئیات تغییرات:**\n\n"
357
+
358
+ if entities:
359
+ for i, entity in enumerate(entities, 1):
360
+ entities_md += f"**{i}.** *{entity.get('type', 'نامشخص')}*\n"
361
+ entities_md += f" • اصل: `{entity.get('original', '')}`\n"
362
+ entities_md += f" • جایگزین: `{entity.get('anonymized', '')}`\n\n"
363
+ else:
364
+ entities_md += "هیچ تغییری انجام نشده یا جزئیات در دسترس نیست"
365
+
366
+ return (
367
+ result["anonymized_text"],
368
+ stats_md,
369
+ usage_md,
370
+ entities_md
371
+ )
372
+
373
+ except Exception as e:
374
+ return (
375
+ "",
376
+ f"❌ خطای غیرمنتظره: {str(e)}",
377
+ "",
378
+ ""
379
+ )
380
+
381
+ def copy_text(text_to_copy):
382
+ """تابع کپی متن"""
383
+ if not text_to_copy.strip():
384
+ return gr.Textbox(visible=False), "⚠️ متنی برای کپی وجود ندارد"
385
+
386
+ # نمایش textbox با محتوای قابل کپی
387
+ return gr.Textbox(value=text_to_copy, visible=True), "✅ متن در کادر زیر آماده کپی است (Ctrl+A سپس Ctrl+C)"
388
+
389
+ def clear_all():
390
+ """پاک کردن تمام فیلدها"""
391
+ return "", "", "", "", "", gr.Textbox(visible=False)
392
+
393
+ # اتصال رویدادها
394
+ anonymize_btn.click(
395
+ fn=process_text,
396
+ inputs=[input_text, api_key_input],
397
+ outputs=[output_text, statistics_output, usage_output, entities_output]
398
+ )
399
+
400
+ clear_btn.click(
401
+ fn=clear_all,
402
+ outputs=[input_text, output_text, statistics_output, usage_output, entities_output, copy_output]
403
+ )
404
+
405
+ # مثال‌های نمونه
406
+ gr.Examples(
407
+ examples=[
408
+ ["ایران خودرو در اسفندماه سال 1402 حدود 23 هزار و 296 میلیارد تومان درآمد کسب کرد که در مقایسه با بهمن 4.58 درصد افزایش داشت."],
409
+ ["مهدی اخوان بهابادی، مدیرعامل همراه اول، اعلام کرد درآمد عملیاتی شرکت با رشد 37 درصدی به 70 هزار و 677 میلیارد تومان رسیده است."],
410
+ ["بانک پاسارگاد با شناسایی سود خالص 155 هزار میلیارد ریالی در رده دوم سودآورترین بانک‌های کشور قرار گرفت."],
411
+ ["شرکت سرمایه‌گذاری دارویی تأمین (تیپیکو) گزارش فعالیت هیئت‌مدیره خود را برای سال مالی منتهی به 31 اردیبهشت 1404 منتشر کرد."]
412
+ ],
413
+ inputs=input_text,
414
+ label="📚 مثال‌های آزمایشی"
415
+ )
416
+
417
+ # راهنمای استفاده
418
+ gr.Markdown("""
419
+ ---
420
+ ### 🎯 **ویژگی‌ها:**
421
+ - 🏢 تشخیص نام شرکت‌ها و سازمان‌ها
422
+ - 👤 تشخیص نام افراد با پیشوندهای مختلف
423
+ - 💰 تشخیص مبالغ مالی و اعداد
424
+ - 📊 تشخیص درصدها با فرمت‌های مختلف
425
+ - 🏗️ تشخیص نام گروه‌ها
426
+
427
+ ### 📝 **نحوه کار:**
428
+ 1. متن خود را در کادر ورودی وارد کنید
429
+ 2. دکمه "ناشناس‌سازی متن" را کلیک کنید
430
+ 3. نتیجه را در کادر خروجی مشاهده کنید
431
+ 4. آمار و جزئیات تغییرات را بررسی کنید
432
+
433
+ ### ⚠️ **توجه:**
434
+ - این سیستم برای متون فارسی بهینه‌سازی شده است
435
+ - حداکثر طول متن ورودی حدود 1000 کلمه توصیه می‌شود
436
+ - اطلاعات شما پس از پردازش حذف می‌شوند
437
+ """)
438
+
439
+ return interface
440
+
441
+ # اجرای برنامه
442
+ if __name__ == "__main__":
443
+ interface = create_interface()
444
+ interface.launch()
445
+
446
+ # =====================================
447
+ # فایل: requirements.txt
448
+ # =====================================
449
+ """
450
+ gradio==4.0.0
451
+ requests==2.31.0
452
+ """
453
+
454
+ # =====================================
455
+ # فایل: README.md
456
+ # =====================================
457
+ """
458
+ ---
459
+ title: Persian Text Anonymizer
460
+ emoji: 🔒
461
+ colorFrom: blue
462
+ colorTo: purple
463
+ sdk: gradio
464
+ sdk_version: 4.0.0
465
+ app_file: app.py
466
+ pinned: false
467
+ license: mit
468
+ ---
469
+
470
+ # 🔒 سیستم ناشناس‌سازی متن فارسی
471
+
472
+ سیستم هوشمند برای تشخیص و ناشناس‌سازی اطلاعات حساس در متون فارسی با استفاده از مدل‌های زبانی پیشرفته.
473
+
474
+ ## ویژگی‌ها
475
+
476
+ - 🏢 **تشخیص شرکت‌ها**: نام شرکت‌ها، بانک‌ها، موسسات
477
+ - 👤 **تشخیص افراد**: نام اشخاص با پیشوندهای مختلف
478
+ - 💰 **تشخیص مبالغ**: اعداد، مبالغ مالی، واحدهای اندازه‌گیری
479
+ - 📊 **تشخیص درصدها**: انواع فرمت‌های درصد
480
+ - 🏗️ **تشخیص گروه‌ها**: نام گروه‌ها و هلدینگ‌ها
481
+
482
+ ## تنظیمات
483
+
484
+ برای استفاده از این برنامه، نیاز به تنظیم متغیر محیطی `GROQ_API_KEY` دارید.
485
+
486
+ ## مثال استفاده
487
+
488
+ ```python
489
+ from app import GroqAnonymizer
490
+
491
+ anonymizer = GroqAnonymizer()
492
+ result = anonymizer.anonymize_text("احمد رضایی مدیرعامل شرکت پارس 100 میلیون تومان درآمد دارد.")
493
+ print(result["anonymized_text"])
494
+ # خروجی: "person-01 مدیرعامل company-01 amount-01 درآمد دارد."
495
+ ```
496
+
497
+ ## تکنولوژی
498
+
499
+ - **Groq API**: برای پردازش هوشمند متن
500
+ - **Gradio**: برای رابط کاربری وب
501
+ - **Llama 3.1**: مدل زبانی پیشرفته
502
+
503
+ ## مجوز
504
+
505
+ MIT License
506
+ """
507
+
508
+ # =====================================
509
+ # فایل: .gitignore
510
+ # =====================================
511
+ """
512
+ __pycache__/
513
+ *.py[cod]
514
+ *$py.class
515
+ *.so
516
+ .Python
517
+ build/
518
+ develop-eggs/
519
+ dist/
520
+ downloads/
521
+ eggs/
522
+ .eggs/
523
+ lib/
524
+ lib64/
525
+ parts/
526
+ sdist/
527
+ var/
528
+ wheels/
529
+ *.egg-info/
530
+ .installed.cfg
531
+ *.egg
532
+ MANIFEST
533
+
534
+ .env
535
+ .venv
536
+ env/
537
+ venv/
538
+ ENV/
539
+ env.bak/
540
+ venv.bak/
541
+
542
+ .DS_Store
543
+ .vscode/
544
+ .idea/
545
+ *.swp
546
+ *.swo
547
+
548
+ gradio_cached_examples/
549
+ flagged/
550
+ """