KashefTech commited on
Commit
22e98a0
·
verified ·
1 Parent(s): 7c96a11

Delete app_FIXED.py

Browse files
Files changed (1) hide show
  1. app_FIXED.py +0 -736
app_FIXED.py DELETED
@@ -1,736 +0,0 @@
1
- import gradio as gr
2
- import re
3
- import os
4
- import requests
5
- import json
6
- import logging
7
- from typing import Dict, List, Tuple, Optional
8
- from llm_sender_unified import create_llm_sender
9
- from qwen_anonymizer import create_qwen_anonymizer # ✅ اضافه شد
10
-
11
- # ✅ مدل‌های موجود - به‌روزرسانی نوامبر 2024
12
- AVAILABLE_MODELS = {
13
- "chatgpt": [
14
- # GPT-5 Series (جدیدترین)
15
- "gpt-5.1", # بهترین برای کدنویسی و وظایف agentic
16
- "gpt-5", # مدل reasoning قبلی
17
- # GPT-4 Series
18
- "gpt-4.1", # هوشمندترین non-reasoning
19
- "gpt-4o", # قدرتمند
20
- "gpt-4o-mini", # سریع و ارزان
21
- "gpt-4-turbo", # سریع‌تر از GPT-4
22
- ],
23
- "grok": [
24
- # Grok-4 Series (جدیدترین)
25
- "grok-4-fast-reasoning", # سریع با reasoning
26
- "grok-4-fast-non-reasoning", # سریع بدون reasoning
27
- "grok-4-0709", # نسخه پایدار
28
- # Grok-3 Series
29
- "grok-3", # قدرتمند
30
- "grok-3-mini", # سبک
31
- # Grok-2 Series
32
- "grok-2-vision-1212", # با قابلیت بینایی
33
- "grok-2-1212", # نسخه پایدار
34
- "grok-2" # نسخه قدیمی
35
- ]
36
- }
37
-
38
- # ✅ روش‌های ناشناس‌سازی
39
- ANONYMIZATION_METHODS = {
40
- "cerebras": "🧠 Cerebras (Llama 3.3 70B)",
41
- "qwen": "🤖 Qwen2.5-1.5B (فاین‌تیون شده)" # ✅ جدید
42
- }
43
-
44
- logging.basicConfig(level=logging.INFO)
45
- logger = logging.getLogger(__name__)
46
-
47
- class AnonymizerAdvanced:
48
- """ناشناس‌ساز پیشرفته با روش‌های متعدد"""
49
-
50
- def __init__(
51
- self,
52
- cerebras_key: str = None,
53
- llm_provider: str = "chatgpt",
54
- llm_model: str = None,
55
- entities_to_anonymize: List[str] = None,
56
- anonymization_method: str = "cerebras" # ✅ جدید
57
- ):
58
- self.cerebras_key = cerebras_key or os.getenv("CEREBRAS_API_KEY")
59
- self.llm_provider = llm_provider
60
- self.llm_model = llm_model
61
- self.entities_to_anonymize = entities_to_anonymize or ["person", "company", "amount", "percent"]
62
- self.anonymization_method = anonymization_method # ✅ جدید
63
- self.mapping_table = {}
64
- self.reverse_mapping = {}
65
-
66
- # ایجاد LLM sender
67
- self._create_llm_sender()
68
-
69
- # ✅ ایجاد Qwen Anonymizer
70
- if self.anonymization_method == "qwen":
71
- self.qwen_anonymizer = create_qwen_anonymizer()
72
- logger.info("✅ Qwen Anonymizer مقداردهی شد")
73
-
74
- logger.info(f"✅ Anonymizer Advanced مقداردهی شد با {llm_provider}")
75
-
76
- def _create_llm_sender(self):
77
- """ایجاد LLM sender مناسب"""
78
- try:
79
- # ✅ همیشه از Hugging Face Secrets استفاده کن
80
- if self.llm_provider == "chatgpt":
81
- api_key = os.getenv("OPENAI_API_KEY")
82
- logger.info("🔑 استفاده از OPENAI_API_KEY از Secrets")
83
- elif self.llm_provider == "grok":
84
- api_key = os.getenv("XAI_API_KEY")
85
- logger.info("🔑 استفاده از XAI_API_KEY از Secrets")
86
- else:
87
- api_key = None
88
- logger.warning("⚠️ Provider ناشناخته")
89
-
90
- # ایجاد sender
91
- self.llm_sender = create_llm_sender(
92
- provider=self.llm_provider,
93
- api_key=api_key,
94
- model=self.llm_model
95
- )
96
-
97
- logger.info(f"✅ LLM Sender ایجاد شد: {self.llm_provider} - {self.llm_sender.model}")
98
-
99
- except Exception as e:
100
- logger.error(f"❌ خطا در ایجاد LLM Sender: {e}")
101
- # fallback to ChatGPT
102
- self.llm_sender = create_llm_sender("chatgpt")
103
-
104
- def set_llm_provider(self, provider: str, model: str = None, entities: List[str] = None):
105
- """تغییر provider و مدل LLM و موجودیت‌های ناشناس‌سازی"""
106
- self.llm_provider = provider
107
- self.llm_model = model
108
- if entities is not None:
109
- self.entities_to_anonymize = entities
110
- self._create_llm_sender()
111
- logger.info(f"✅ LLM تغییر یافت به: {provider} - {model}")
112
- logger.info(f"✅ موجودیت‌های ناشناس‌سازی: {self.entities_to_anonymize}")
113
-
114
- def set_anonymization_method(self, method: str):
115
- """تغییر روش ناشناس‌سازی"""
116
- self.anonymization_method = method
117
-
118
- if method == "qwen" and not hasattr(self, 'qwen_anonymizer'):
119
- self.qwen_anonymizer = create_qwen_anonymizer()
120
- logger.info("✅ Qwen Anonymizer مقداردهی شد")
121
-
122
- logger.info(f"✅ روش ناشناس‌سازی تغییر یافت به: {method}")
123
-
124
- def anonymize_with_cerebras(self, text: str) -> Tuple[str, Dict]:
125
- """ناشناس‌سازی با Cerebras - بر اساس موجودیت‌های انتخابی"""
126
- logger.info("🧠 روش Cerebras...")
127
-
128
- if not self.cerebras_key:
129
- logger.error("❌ Cerebras API Key موجود نیست")
130
- raise ValueError("Cerebras API Key مورد نیاز است")
131
-
132
- # ✅ ساخت دستورات بر اساس موجودیت‌های انتخابی
133
- instructions = []
134
- instruction_number = 1
135
-
136
- if "person" in self.entities_to_anonymize:
137
- instructions.append(f"{instruction_number}. اسامی اشخاص → person-01, person-02, ...")
138
- instruction_number += 1
139
-
140
- if "company" in self.entities_to_anonymize:
141
- instructions.append(f"{instruction_number}. نام شرکت‌ها/سازمان‌ها → company-01, company-02, ...")
142
- instruction_number += 1
143
-
144
- if "amount" in self.entities_to_anonymize:
145
- instructions.append(f"{instruction_number}. اعداد و ارقام و مبالغ (مثل: 50 میلیارد، 100 هزار، 25.5 میلیون، ۳۰۰ دستگاه) → amount-01, amount-02, ...")
146
- instruction_number += 1
147
-
148
- if "percent" in self.entities_to_anonymize:
149
- instructions.append(f"{instruction_number}. درصدها → percent-01, percent-02, ...")
150
- instruction_number += 1
151
-
152
- # اگه هیچی انتخاب نشده، متن رو همون‌طور برگردون
153
- if not instructions:
154
- logger.warning("⚠️ هیچ موجودیتی برای ناشناس‌سازی انتخاب نشده!")
155
- return text, {}
156
-
157
- instructions_text = "\n".join(instructions)
158
- instructions_text += f"\n{instruction_number}. فقط این توکن‌ها استفاده کنید"
159
- instructions_text += f"\n{instruction_number + 1}. شماره‌های نسخه را درست حفظ کنید"
160
- instructions_text += f"\n{instruction_number + 2}. اگر موجودیت تکرار شود از شماره قدیمی استفاده کنید"
161
-
162
- try:
163
- # مرحله 1: ناشناس‌سازی متن
164
- # ✅ ساخت مثال برای amount (اگر انتخاب شده)
165
- example_text = ""
166
- if "amount" in self.entities_to_anonymize:
167
- example_text = """
168
- مثال:
169
- متن اصلی: "فروش 50 میلیارد ریال در سال گذشته بود."
170
- متن ناشناس: "فروش amount-01 در سال گذشته بود."
171
- """
172
-
173
- prompt1 = f"""متن زیر را ناشناس کنید. قوانین:
174
- {instructions_text}
175
- {example_text}
176
- متن:
177
- {text}
178
-
179
- خروجی: فقط متن ناشناس شده (بدون توضیح اضافی)"""
180
-
181
- response1 = requests.post(
182
- "https://api.cerebras.ai/v1/chat/completions",
183
- headers={
184
- "Authorization": f"Bearer {self.cerebras_key}",
185
- "Content-Type": "application/json"
186
- },
187
- json={
188
- "model": "llama-3.3-70b",
189
- "messages": [{"role": "user", "content": prompt1}],
190
- "max_tokens": 4096,
191
- "temperature": 0.1
192
- },
193
- timeout=60
194
- )
195
-
196
- if response1.status_code != 200:
197
- logger.error(f"❌ Cerebras Error: {response1.status_code}")
198
- raise Exception(f"Cerebras API Error: {response1.status_code}")
199
-
200
- anonymized_text = response1.json()['choices'][0]['message']['content'].strip()
201
- logger.info("✅ Cerebras: ناشناس‌سازی موفق")
202
-
203
- # مرحله 2: استخراج mapping - فقط برای موجودیت‌های انتخابی
204
- mapping_instructions = []
205
- json_example = "{\n"
206
-
207
- if "person" in self.entities_to_anonymize:
208
- mapping_instructions.append('- برای person-XX: نام کامل شخص (مثلاً "علی احمدی")')
209
- json_example += ' "person-01": "متن اصلی کامل",\n'
210
-
211
- if "company" in self.entities_to_anonymize:
212
- mapping_instructions.append('- برای company-XX: نام کامل شرکت/سازمان (مثلاً "شرکت پتروشیمی")')
213
- json_example += ' "company-01": "متن اصلی کامل",\n'
214
-
215
- if "amount" in self.entities_to_anonymize:
216
- mapping_instructions.append('- برای amount-XX: عدد + واحد (مثلاً "80 هزار تومان" یا "50 میلیارد ریال")')
217
- json_example += ' "amount-01": "مت�� اصلی کامل با واحد",\n'
218
-
219
- if "percent" in self.entities_to_anonymize:
220
- mapping_instructions.append('- برای percent-XX: عدد + کلمه "درصد" (مثلاً "40 درصد" نه فقط "40")')
221
- json_example += ' "percent-01": "عدد + درصد",\n'
222
-
223
- json_example += " ...\n}"
224
- mapping_instructions_text = "\n".join(mapping_instructions)
225
-
226
- prompt2 = f"""متن اصلی:
227
- {text}
228
-
229
- متن ناشناس شده:
230
- {anonymized_text}
231
-
232
- لطفاً یک جدول mapping برای همه توکن‌های ناشناس ایجاد کن.
233
- برای هر توکن، متن اصلی کامل آن را مشخص کن.
234
-
235
- **مهم:**
236
- {mapping_instructions_text}
237
-
238
- خروجی را به این فرمت JSON بده (فقط JSON، بدون توضیح اضافی):
239
- {json_example}"""
240
-
241
- response2 = requests.post(
242
- "https://api.cerebras.ai/v1/chat/completions",
243
- headers={
244
- "Authorization": f"Bearer {self.cerebras_key}",
245
- "Content-Type": "application/json"
246
- },
247
- json={
248
- "model": "llama-3.3-70b",
249
- "messages": [{"role": "user", "content": prompt2}],
250
- "max_tokens": 4096,
251
- "temperature": 0.1
252
- },
253
- timeout=60
254
- )
255
-
256
- if response2.status_code != 200:
257
- logger.error(f"❌ Cerebras Mapping Error: {response2.status_code}")
258
- raise Exception(f"Cerebras Mapping Error: {response2.status_code}")
259
-
260
- mapping_text = response2.json()['choices'][0]['message']['content'].strip()
261
-
262
- # پارس JSON
263
- mapping_dict = self._parse_json_mapping(mapping_text)
264
-
265
- logger.info("✅ Cerebras: mapping استخراج شد")
266
-
267
- return anonymized_text, mapping_dict
268
-
269
- except Exception as e:
270
- logger.error(f"❌ خطا در Cerebras: {e}")
271
- return f"❌ خطا در ناشناس‌سازی: {str(e)}", {}
272
-
273
- def anonymize_with_qwen(self, text: str) -> Tuple[str, Dict]:
274
- """✅ ناشناس‌سازی با مدل فاین‌تیون شده Qwen"""
275
- logger.info("🤖 روش Qwen...")
276
-
277
- try:
278
- if not hasattr(self, 'qwen_anonymizer'):
279
- self.qwen_anonymizer = create_qwen_anonymizer()
280
-
281
- anonymized_text, mapping_dict = self.qwen_anonymizer.anonymize(
282
- text,
283
- entities_to_anonymize=self.entities_to_anonymize
284
- )
285
-
286
- logger.info("✅ Qwen: ناشناس‌سازی موفق")
287
- return anonymized_text, mapping_dict
288
-
289
- except Exception as e:
290
- logger.error(f"❌ خطا در Qwen: {e}")
291
- return f"❌ خطا در ناشناس‌سازی: {str(e)}", {}
292
-
293
- def _parse_json_mapping(self, text: str) -> Dict:
294
- """پارس کردن JSON mapping از پاسخ LLM"""
295
- try:
296
- # حذف markdown code blocks
297
- text = re.sub(r'```json\s*', '', text)
298
- text = re.sub(r'```\s*', '', text)
299
- text = text.strip()
300
-
301
- # پیدا کردن اولین { و آخرین }
302
- start = text.find('{')
303
- end = text.rfind('}')
304
-
305
- if start != -1 and end != -1:
306
- json_text = text[start:end+1]
307
- mapping = json.loads(json_text)
308
- return mapping
309
- else:
310
- logger.error("❌ فرمت JSON نامعتبر")
311
- return {}
312
-
313
- except json.JSONDecodeError as e:
314
- logger.error(f"❌ خطا در پارس JSON: {e}")
315
- return {}
316
- except Exception as e:
317
- logger.error(f"❌ خطای غیرمنتظره: {e}")
318
- return {}
319
-
320
- def anonymize(self, text: str) -> Tuple[str, Dict]:
321
- """✅ ناشناس‌سازی با روش انتخابی"""
322
- if self.anonymization_method == "cerebras":
323
- return self.anonymize_with_cerebras(text)
324
- elif self.anonymization_method == "qwen":
325
- return self.anonymize_with_qwen(text)
326
- else:
327
- logger.error(f"❌ روش ناشناخته: {self.anonymization_method}")
328
- return text, {}
329
-
330
- def restore_text(self, anonymized_text: str) -> str:
331
- """بازگردانی متن با استفاده از mapping"""
332
- restored = anonymized_text
333
-
334
- for token, original in self.mapping_table.items():
335
- restored = restored.replace(token, original)
336
-
337
- return restored
338
-
339
- def analyze_with_llm(self, anonymized_text: str, prompt: str) -> str:
340
- """تحلیل متن ناشناس شده با LLM"""
341
- if not prompt or not prompt.strip():
342
- return "❌ دستور LLM خالی است!"
343
-
344
- full_prompt = f"""{prompt}
345
-
346
- متن:
347
- {anonymized_text}"""
348
-
349
- try:
350
- response = self.llm_sender.send_simple(full_prompt, lang='fa')
351
- return response
352
-
353
- except Exception as e:
354
- logger.error(f"❌ خطا در تحلیل LLM: {e}")
355
- return f"❌ خطا: {str(e)}"
356
-
357
-
358
- # ==================== Gradio Interface ====================
359
-
360
- # متغیر global برای نگهداری instance
361
- anonymizer = None
362
-
363
- def initialize_anonymizer():
364
- """مقداردهی اولیه anonymizer"""
365
- global anonymizer
366
- anonymizer = AnonymizerAdvanced(
367
- llm_provider="chatgpt",
368
- llm_model="gpt-4o-mini",
369
- anonymization_method="cerebras" # پیش‌فرض
370
- )
371
- logger.info("✅ Anonymizer مقداردهی شد")
372
-
373
- def process(
374
- input_text: str,
375
- analysis_prompt: str,
376
- llm_provider: str,
377
- llm_model: str,
378
- anonymize_all: bool,
379
- anonymize_person: bool,
380
- anonymize_company: bool,
381
- anonymize_amount: bool,
382
- anonymize_percent: bool,
383
- anonymization_method: str # ✅ پارامتر جدید
384
- ):
385
- """پردازش متن"""
386
- global anonymizer
387
-
388
- # بررسی اولیه
389
- if not input_text or not input_text.strip():
390
- return "", "", "", "### ⚠️ خطا\n\nمتن ورودی خالی است!"
391
-
392
- try:
393
- # تعیین موجودیت‌ها
394
- if anonymize_all:
395
- entities = ["person", "company", "amount", "percent"]
396
- else:
397
- entities = []
398
- if anonymize_person:
399
- entities.append("person")
400
- if anonymize_company:
401
- entities.append("company")
402
- if anonymize_amount:
403
- entities.append("amount")
404
- if anonymize_percent:
405
- entities.append("percent")
406
-
407
- if not entities:
408
- return "", "", "", "### ⚠️ خطا\n\nحداقل یک موجودیت را انتخاب کنید!"
409
-
410
- # تنظیم anonymizer
411
- anonymizer.set_llm_provider(llm_provider, llm_model, entities)
412
- anonymizer.set_anonymization_method(anonymization_method) # ✅ جدید
413
-
414
- # ناشناس‌سازی
415
- anonymized_text, mapping = anonymizer.anonymize(input_text)
416
-
417
- if not mapping:
418
- return "", "", anonymized_text, "### ⚠️ هشدار\n\nMapping خالی است!"
419
-
420
- anonymizer.mapping_table = mapping
421
-
422
- # تحلیل (اختیاری) - باید اول انجام بشه!
423
- has_analysis = analysis_prompt and analysis_prompt.strip()
424
-
425
- if has_analysis:
426
- # مرحله 1: تحلیل LLM
427
- llm_analysis = anonymizer.analyze_with_llm(anonymized_text, analysis_prompt)
428
- # مرحله 2: بازگردانی خروجی LLM (نه متن ناشناس اولیه!)
429
- restored_text = anonymizer.restore_text(llm_analysis)
430
- else:
431
- # بدون تحلیل
432
- llm_analysis = "تحلیل درخواست نشده"
433
- # بازگردانی متن ناشناس اولیه
434
- restored_text = anonymizer.restore_text(anonymized_text)
435
-
436
- # ساخت جدول mapping
437
- mapping_md = "### 📋 جدول نگاشت\n\n"
438
- mapping_md += "| توکن | مقدار اصلی |\n"
439
- mapping_md += "|------|------------|\n"
440
-
441
- for token, value in sorted(mapping.items()):
442
- mapping_md += f"| `{token}` | {value} |\n"
443
-
444
- return restored_text, llm_analysis, anonymized_text, mapping_md
445
-
446
- except Exception as e:
447
- logger.error(f"❌ خطا در پردازش: {e}")
448
- error_md = f"### ❌ خطا\n\n{str(e)}"
449
- return "", "", "", error_md
450
-
451
- def clear_all():
452
- """پاک کردن همه فیلدها"""
453
- return (
454
- "", # input_text
455
- "", # analysis_prompt
456
- "", # restored_text
457
- "", # llm_analysis
458
- "", # anonymized_text
459
- "### 📋 جدول نگاشت\n\nهنوز پردازشی انجام نشده", # mapping_table
460
- True, # anonymize_all
461
- False, # anonymize_person
462
- False, # anonymize_company
463
- False, # anonymize_amount
464
- False # anonymize_percent
465
- )
466
-
467
-
468
- # ==================== Gradio App ====================
469
-
470
- # مقداردهی اولیه
471
- initialize_anonymizer()
472
-
473
- # CSS سفارشی
474
- custom_css = """
475
- .input-box {
476
- direction: rtl;
477
- text-align: right;
478
- }
479
- .textbox {
480
- direction: rtl !important;
481
- text-align: right !important;
482
- }
483
- .thick-divider {
484
- border-top: 3px solid #ccc;
485
- margin: 20px 0;
486
- }
487
- .compact-checkbox label {
488
- padding: 5px 0 !important;
489
- }
490
- """
491
-
492
- with gr.Blocks(css=custom_css, title="سیستم ناشناس‌سازی متون", theme=gr.themes.Soft()) as app:
493
- gr.Markdown(
494
- """
495
- # 🔒 سیستم ناشناس‌سازی متون مالی و خبری
496
- ### با قابلیت تحلیل هوشمند و بازگردانی دقیق
497
- """,
498
- elem_classes="input-box"
499
- )
500
-
501
- # ردیف اول: تنظیمات
502
- with gr.Row():
503
- # سمت راست: انتخاب مدل
504
- with gr.Column(scale=1):
505
- with gr.Group():
506
- gr.Markdown("### 🎯 انتخاب مدل", elem_classes="input-box")
507
-
508
- # ✅ انتخاب روش ناشناس‌سازی
509
- anonymization_method = gr.Radio(
510
- choices=list(ANONYMIZATION_METHODS.keys()),
511
- value="cerebras",
512
- label="🔧 روش ناشناس‌سازی",
513
- interactive=True,
514
- elem_classes="input-box"
515
- )
516
-
517
- llm_provider = gr.Radio(
518
- choices=["chatgpt", "grok"],
519
- value="chatgpt",
520
- label="🤖 انتخاب مدل زبانی (برای تحلیل)",
521
- interactive=True
522
- )
523
-
524
- llm_model = gr.Dropdown(
525
- choices=AVAILABLE_MODELS["chatgpt"],
526
- value="gpt-4o-mini",
527
- label="📦 انتخاب نسخه مدل",
528
- interactive=True
529
- )
530
-
531
- # سمت چپ: انتخاب موجودیت‌ها
532
- with gr.Column(scale=1):
533
- with gr.Group():
534
- gr.Markdown("### 🎯 انتخاب موجودیت‌ها", elem_classes="input-box")
535
-
536
- anonymize_all = gr.Checkbox(
537
- label="✅ همه موجودیت‌ها",
538
- value=True,
539
- elem_classes="input-box compact-checkbox"
540
- )
541
-
542
- anonymize_person = gr.Checkbox(
543
- label="👤 اسامی اشخاص",
544
- value=False,
545
- elem_classes="input-box compact-checkbox"
546
- )
547
-
548
- anonymize_company = gr.Checkbox(
549
- label="🏢 نام شرکت‌ها",
550
- value=False,
551
- elem_classes="input-box compact-checkbox"
552
- )
553
-
554
- anonymize_amount = gr.Checkbox(
555
- label="💰 ارقام مالی",
556
- value=False,
557
- elem_classes="input-box compact-checkbox"
558
- )
559
-
560
- anonymize_percent = gr.Checkbox(
561
- label="📊 درصدها",
562
- value=False,
563
- elem_classes="input-box compact-checkbox"
564
- )
565
-
566
- # خط جداکننده پررنگ
567
- gr.Markdown("---", elem_classes="thick-divider")
568
-
569
- # ردیف دوم: دستورات پردازش و متن ورودی
570
- with gr.Row():
571
- # سمت راست: دستورات پردازش
572
- with gr.Column(scale=1):
573
- gr.Markdown("### 📋 دستورات پردازش", elem_classes="input-box")
574
-
575
- analysis_prompt = gr.Textbox(
576
- lines=22,
577
- placeholder="مثال: این متن را خلاصه کن\nیا: نکات کلیدی را استخراج کن",
578
- label="📋 دستورات LLM (اختیاری)",
579
- elem_classes="textbox"
580
- )
581
-
582
- # سمت چپ: متن ورودی
583
- with gr.Column(scale=1):
584
- gr.Markdown("### 📝 متن ورودی", elem_classes="input-box")
585
-
586
- input_text = gr.Textbox(
587
- lines=22,
588
- placeholder="متن مالی/خبری را وارد کنید...",
589
- label="",
590
- elem_classes="textbox"
591
- )
592
-
593
- # دکمه‌های پردازش و پاک کردن
594
- with gr.Row():
595
- process_btn = gr.Button(
596
- "▶️ پردازش",
597
- variant="primary",
598
- size="lg",
599
- scale=2
600
- )
601
-
602
- clear_btn = gr.Button(
603
- "🗑️ پاک کردن",
604
- variant="stop",
605
- size="lg",
606
- scale=1
607
- )
608
-
609
- # نتایج
610
- gr.Markdown("## 📊 نتایج پردازش", elem_classes="input-box")
611
-
612
- with gr.Row():
613
- with gr.Column(scale=1):
614
- restored_text = gr.Textbox(
615
- lines=12,
616
- label="✅ متن بازگردانی شده",
617
- interactive=False,
618
- elem_classes="textbox"
619
- )
620
-
621
- with gr.Column(scale=1):
622
- llm_analysis = gr.Textbox(
623
- lines=12,
624
- label="🤖 تحلیل LLM",
625
- interactive=False,
626
- elem_classes="textbox"
627
- )
628
-
629
- with gr.Column(scale=1):
630
- anonymized_text = gr.Textbox(
631
- lines=12,
632
- label="🔒 متن ناشناس‌شده",
633
- interactive=False,
634
- elem_classes="textbox"
635
- )
636
-
637
- mapping_table = gr.Markdown(
638
- value="### 📋 جدول نگاشت\n\nهنوز پردازشی انجام نشده",
639
- label="📋 جدول نگاشت",
640
- elem_classes="input-box"
641
- )
642
-
643
-
644
- # Event Handler برای تغییر provider
645
- def handle_provider_change(provider):
646
- models = AVAILABLE_MODELS.get(provider, [])
647
- default_model = models[0] if models else None
648
- return gr.update(choices=models, value=default_model)
649
-
650
- llm_provider.change(
651
- fn=handle_provider_change,
652
- inputs=[llm_provider],
653
- outputs=[llm_model]
654
- )
655
-
656
- def handle_select_all(select_all):
657
- if select_all:
658
- return (
659
- gr.update(value=False, interactive=False),
660
- gr.update(value=False, interactive=False),
661
- gr.update(value=False, interactive=False),
662
- gr.update(value=False, interactive=False)
663
- )
664
- else:
665
- return (
666
- gr.update(value=False, interactive=True),
667
- gr.update(value=False, interactive=True),
668
- gr.update(value=False, interactive=True),
669
- gr.update(value=False, interactive=True)
670
- )
671
-
672
- anonymize_all.change(
673
- fn=handle_select_all,
674
- inputs=[anonymize_all],
675
- outputs=[anonymize_person, anonymize_company, anonymize_amount, anonymize_percent]
676
- )
677
-
678
- # پردازش
679
- process_btn.click(
680
- fn=process,
681
- inputs=[
682
- input_text,
683
- analysis_prompt,
684
- llm_provider,
685
- llm_model,
686
- anonymize_all,
687
- anonymize_person,
688
- anonymize_company,
689
- anonymize_amount,
690
- anonymize_percent,
691
- anonymization_method # ✅ جدید
692
- ],
693
- outputs=[restored_text, llm_analysis, anonymized_text, mapping_table]
694
- )
695
-
696
- # پاک کردن
697
- clear_btn.click(
698
- fn=clear_all,
699
- outputs=[
700
- input_text,
701
- analysis_prompt,
702
- restored_text,
703
- llm_analysis,
704
- anonymized_text,
705
- mapping_table,
706
- anonymize_all,
707
- anonymize_person,
708
- anonymize_company,
709
- anonymize_amount,
710
- anonymize_percent
711
- ]
712
- )
713
-
714
- if __name__ == "__main__":
715
- print("=" * 70)
716
- print("🚀 سیستم ناشناس‌سازی متون در حال راه‌اندازی...")
717
- print("=" * 70)
718
- print("\n📋 نحوه استفاده:\n")
719
- print("1. API Keyها را در Hugging Face Secrets تنظیم کنید:")
720
- print(" - CEREBRAS_API_KEY (برای روش Cerebras)")
721
- print(" - HF_TOKEN (برای استفاده از مدل Qwen)")
722
- print(" - OPENAI_API_KEY (برای ChatGPT)")
723
- print(" - XAI_API_KEY (برای Grok)")
724
- print("2. روش ناشناس‌سازی را انتخاب کنید (Cerebras یا Qwen)")
725
- print("3. مدل زبانی (ChatGPT/Grok) و نسخه مدل را انتخاب کنید")
726
- print("4. موجودیت‌های مورد نظر برای ناشناس‌سازی را انتخاب کنید")
727
- print("5. متن و دستورات پردازش را وارد کنید")
728
- print("6. 'پردازش' را کلیک کنید\n")
729
- print("=" * 70 + "\n")
730
-
731
- app.launch(
732
- server_name="0.0.0.0",
733
- server_port=7860,
734
- share=False,
735
- show_error=True
736
- )