leilaghomashchi commited on
Commit
9112046
·
verified ·
1 Parent(s): 2ac234e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +103 -321
app.py CHANGED
@@ -1,354 +1,136 @@
1
  """
2
- ناشناس‌ساز پیشرفته متون مالی/خبری فارسی
3
- قدرت‌گرفته از OpenRouter AI - Qwen3-14B
4
- نسخه: 1.0.1 (Fixed)
5
  """
6
 
7
  import requests
8
  import json
9
- import gradio as gr
10
- from typing import Dict, Any
11
  import os
12
- from dataclasses import dataclass
13
- import re
14
 
15
- @dataclass
16
- class OpenRouterConfig:
17
- """تنظیمات OpenRouter API برای Qwen3-14B"""
18
- api_key: str
19
- base_url: str = "https://openrouter.ai/api/v1"
20
- # ✅ نام مدل صحیح - بدون :free
21
- model: str = "qwen/qwen-2.5-14b-instruct"
22
- max_tokens: int = 16384
23
- temperature: float = 0.6
24
- top_p: float = 0.85
25
-
26
- class AdvancedOpenRouterAnonymizer:
27
- """سیستم پیشرفته ناشناس‌سازی با OpenRouter"""
28
 
29
- def __init__(self, api_key: str = None):
30
- if api_key is None:
31
- api_key = os.getenv("OPENROUTER_API_KEY")
32
- if not api_key:
33
- raise ValueError("کلید API یافت نشد - لطفاً در Settings تنظیم کنید")
34
-
35
- self.config = OpenRouterConfig(api_key=api_key)
36
- self.system_prompt = self._create_advanced_system_prompt()
37
 
38
- def _create_advanced_system_prompt(self) -> str:
39
- """ایجاد دستورالعمل سیستمی پیشرفته"""
40
- return """شما یک «ناشناس‌ساز متون مالی/خبری فارسی» هستید.
41
-
42
- ## قوانین اندیس‌گذاری:
43
- 1. **ترتیب پیوسته**: company-01, company-02, ... | person-01, person-02, ... | amount-01, amount-02, ... | percent-01, percent-02, ...
44
- 2. **ثبات**: اگر "همراه اول" → company-01 شد، در تمام متن همان باشد
45
- 3. **نام مستعار**: "فاما" = "فولاد مبارکه" → هر دو company-01
46
- 4. **اشاره ضمنی**: "این شرکت" اگر به company-01 اشاره دارد → company-01
47
-
48
- ## انواع موجودیت:
49
- - **company-XX**: شرکت‌ها، بانک‌ها، سازمان‌ها، گروه‌ها
50
- - **person-XX**: نام و نام خانوادگی اشخاص
51
- - **amount-XX**: مبالغ (واحد را حفظ کن)
52
- - **percent-XX**: درصدها
53
-
54
- ## قوانین کلیدی:
55
- 1. بازرس = شرکت است → company-XX
56
- 2. واحدها: "amount-01 میلیارد تومان" ✅
57
- 3. کلمات عمومی حفظ: "سه شرکت" → حفظ
58
- 4. تمام اعداد را شناسایی کن
59
- 5. درصدها را شناسایی کن
60
-
61
- ## مثال:
62
- ورودی: ایران خودرو در اسفند 1402 حدود 23 هزار و 296 میلیارد درآمد کسب کرد که 4.58 درصد افزایش داشت.
63
- خروجی: company-01 در اسفند 1402 حدود amount-01 درآمد کسب کرد که percent-01 افزایش داشت.
64
-
65
- ⚠️ فقط متن ناشناس‌شده، بدون توضیح اضافی."""
66
-
67
- def _make_api_request(self, text: str) -> Dict[str, Any]:
68
- """ارسال درخواست به OpenRouter API"""
69
-
70
- print(f"🔍 Debug: Using model = {self.config.model}")
71
 
72
- # ✅ Headers ساده‌شده
73
  headers = {
74
- "Authorization": f"Bearer {self.config.api_key}",
75
- "Content-Type": "application/json",
76
  }
77
 
78
- # ✅ Payload ساده‌شده
79
  payload = {
80
- "model": self.config.model,
81
  "messages": [
82
- {"role": "system", "content": self.system_prompt},
83
- {"role": "user", "content": text}
84
  ],
85
- "temperature": self.config.temperature,
86
- "top_p": self.config.top_p,
87
- "max_tokens": self.config.max_tokens
88
  }
89
 
90
- full_url = f"{self.config.base_url}/chat/completions"
91
-
92
  try:
93
- response = requests.post(
94
- full_url,
95
- headers=headers,
96
- json=payload,
97
- timeout=90
98
- )
99
 
100
- print(f"📡 Response Status: {response.status_code}")
101
 
102
- # نمایش پاسخ کامل در صورت خطا
103
- if response.status_code != 200:
104
- print(f"❌ Error Response: {response.text}")
105
-
106
- response.raise_for_status()
107
- return response.json()
108
-
109
- except requests.exceptions.HTTPError as e:
110
- error_detail = response.text if response else 'No response'
111
- print(f"❌ HTTP Error Details: {error_detail}")
112
-
113
- # پیام خطای بهتر
114
- try:
115
- error_json = json.loads(error_detail)
116
- error_msg = error_json.get('error', {}).get('message', str(e))
117
- except:
118
- error_msg = str(e)
119
-
120
- raise Exception(f"خطا در OpenRouter: {error_msg}")
121
 
122
- except requests.exceptions.RequestException as e:
123
- raise Exception(f"خطای شبکه: {str(e)}")
124
-
125
- def anonymize_text(self, text: str) -> Dict[str, Any]:
126
- """ناشناس‌سازی متن"""
127
- if not text.strip():
128
- return {
129
- "success": False,
130
- "error": "متن ورودی خالی است"
131
- }
132
-
133
- try:
134
- response = self._make_api_request(text)
135
-
136
- if "choices" not in response or not response["choices"]:
137
- return {
138
- "success": False,
139
- "error": "پاسخ نامعتبر از API"
140
- }
141
-
142
- content = response["choices"][0]["message"]["content"]
143
- content = self._clean_markdown(content)
144
- content = content.strip()
145
-
146
- analysis = self._analyze_anonymized_text(content)
147
-
148
- return {
149
- "success": True,
150
- "anonymized_text": content,
151
- "entities": analysis["entities"],
152
- "statistics": analysis["statistics"],
153
- "detailed_analysis": analysis["detailed_analysis"],
154
- "usage": response.get("usage", {}),
155
- "quality_check": self._validate_anonymized_text(content)
156
- }
157
-
158
  except Exception as e:
159
- return {
160
- "success": False,
161
- "error": f"خطا در پردازش: {str(e)}"
162
- }
163
-
164
- def _clean_markdown(self, content: str) -> str:
165
- """پاک کردن markdown از پاسخ"""
166
- if "```" in content:
167
- lines = content.split('\n')
168
- clean_lines = []
169
- skip = False
170
- for line in lines:
171
- if line.strip().startswith('```'):
172
- skip = not skip
173
- continue
174
- if not skip:
175
- clean_lines.append(line)
176
- content = '\n'.join(clean_lines)
177
- return content
178
-
179
- def _analyze_anonymized_text(self, text: str) -> Dict[str, Any]:
180
- """تحلیل متن ناشناس‌سازی شده"""
181
- companies = re.findall(r'company-(\d+)', text)
182
- persons = re.findall(r'person-(\d+)', text)
183
- amounts = re.findall(r'amount-(\d+)', text)
184
- percents = re.findall(r'percent-(\d+)', text)
185
-
186
- statistics = {
187
- "company": len(set(companies)),
188
- "person": len(set(persons)),
189
- "amount": len(set(amounts)),
190
- "percent": len(set(percents)),
191
- "total_replacements": len(companies) + len(persons) + len(amounts) + len(percents)
192
- }
193
-
194
- entities = {
195
- "companies": sorted(list(set(companies)), key=lambda x: int(x)),
196
- "persons": sorted(list(set(persons)), key=lambda x: int(x)),
197
- "amounts": sorted(list(set(amounts)), key=lambda x: int(x)),
198
- "percents": sorted(list(set(percents)), key=lambda x: int(x))
199
- }
200
-
201
- detailed_analysis = {
202
- "preserved_dates": len(re.findall(r'\d{4}/\d{1,2}/\d{1,2}|\d{1,2}\s+\w+\s+\d{4}', text)),
203
- "preserved_times": len(re.findall(r'\d{1,2}:\d{2}', text)),
204
- "financial_indicators": len(re.findall(r'\b(EPS|P/E|ARPU|NPL|ROE|ROA)\b', text)),
205
- "units_preserved": len(re.findall(r'(میلیارد|میلیون|هزار|تومان|ریال|درهم|دلار|یورو|تن|کیلوگرم)', text))
206
- }
207
-
208
- return {
209
- "statistics": statistics,
210
- "entities": entities,
211
- "detailed_analysis": detailed_analysis
212
- }
213
 
214
- def _validate_anonymized_text(self, text: str) -> Dict[str, Any]:
215
- """اعتبارسنجی"""
216
- companies = re.findall(r'company-(\d+)', text)
217
- persons = re.findall(r'person-(\d+)', text)
218
- amounts = re.findall(r'amount-(\d+)', text)
219
- percents = re.findall(r'percent-(\d+)', text)
220
-
221
- validation_issues = []
222
-
223
- for entity_type, indices in [
224
- ("company", companies),
225
- ("person", persons),
226
- ("amount", amounts),
227
- ("percent", percents)
228
- ]:
229
- if indices:
230
- unique_indices = sorted(list(set([int(x) for x in indices])))
231
- if unique_indices[0] != 1:
232
- validation_issues.append(f"اندیس {entity_type} از 01 شروع نشده")
233
-
234
- expected = list(range(1, len(unique_indices) + 1))
235
- if unique_indices != expected:
236
- validation_issues.append(f"اندیس‌های {entity_type} پیوسته نیستند")
237
-
238
- return {
239
- "is_valid": len(validation_issues) == 0,
240
- "issues": validation_issues,
241
- "entity_counts": {
242
- "company": len(set(companies)),
243
- "person": len(set(persons)),
244
- "amount": len(set(amounts)),
245
- "percent": len(set(percents))
246
- }
247
- }
248
 
249
- def create_advanced_interface():
250
- """ایجاد رابط کاربری"""
 
251
 
252
- api_key_available = bool(os.getenv("OPENROUTER_API_KEY"))
 
 
253
 
254
- with gr.Blocks(title="ناشناس‌ساز با Qwen3-14B", theme=gr.themes.Soft()) as interface:
255
-
256
- gr.Markdown("""
257
- # 🔒 ناشناس‌ساز پیشرفته متون فارسی
258
- ### 🚀 مدل: Qwen 2.5 14B Instruct (OpenRouter)
259
- """)
260
-
261
- if api_key_available:
262
- gr.Markdown("✅ **سیستم آماده است**")
263
- else:
264
- gr.Markdown("""
265
- ⚠️ **کلید API تنظیم نشده**
266
-
267
- لطفاً در Settings یک Secret با نام `OPENROUTER_API_KEY` اضافه کنید.
268
-
269
- دریافت کلید رایگان: https://openrouter.ai/keys
270
- """)
271
-
272
- with gr.Row():
273
- with gr.Column():
274
- input_text = gr.Textbox(
275
- label="📝 متن ورودی",
276
- placeholder="متن خود را وارد کنید...",
277
- lines=10,
278
- rtl=True
279
- )
280
- anonymize_btn = gr.Button("🔒 ناشناس‌سازی", variant="primary")
281
-
282
- with gr.Column():
283
- output_text = gr.Textbox(
284
- label="🎯 متن ناشناس‌سازی شده",
285
- lines=10,
286
- rtl=True
287
- )
288
-
289
- statistics_output = gr.Markdown(label="📊 آمار")
290
- usage_output = gr.Markdown(label="⚡ اطلاعات پردازش")
291
-
292
- def process_text(text: str):
293
- """پردازش متن"""
294
- if not text or not text.strip():
295
- return "", "❌ متن ورودی خالی است", ""
296
-
297
- try:
298
- anonymizer = AdvancedOpenRouterAnonymizer()
299
- result = anonymizer.anonymize_text(text)
300
-
301
- if not result["success"]:
302
- return "", f"❌ خطا: {result['error']}", ""
303
-
304
- # آمار
305
- stats = result.get("statistics", {})
306
- stats_md = f"""
307
- ## 📊 آمار کلی:
308
- - 🏢 شرکت‌ها: {stats.get('company', 0)}
309
- - 👤 اشخاص: {stats.get('person', 0)}
310
- - 💰 مبالغ: {stats.get('amount', 0)}
311
- - 📊 درصدها: {stats.get('percent', 0)}
312
- - 🔢 کل جایگزینی‌ها: {stats.get('total_replacements', 0)}
313
- """
314
-
315
- # اطلاعات پردازش
316
- usage = result.get("usage", {})
317
- usage_md = f"""
318
- ## ⚡ اطلاعات پردازش:
319
- - 🤖 مدل: Qwen 2.5 14B Instruct
320
- - 📥 ورودی: {usage.get('prompt_tokens', 0)} tokens
321
- - 📤 خروجی: {usage.get('completion_tokens', 0)} tokens
322
- - 📊 کل: {usage.get('total_tokens', 0)} tokens
323
- """
324
-
325
- return (
326
- result["anonymized_text"],
327
- stats_md,
328
- usage_md
329
- )
330
-
331
- except Exception as e:
332
- return "", f"❌ خطا: {str(e)}", ""
333
 
334
- anonymize_btn.click(
335
- fn=process_text,
336
- inputs=[input_text],
337
- outputs=[output_text, statistics_output, usage_output]
338
  )
339
 
340
- # مثال‌ها
341
- gr.Examples(
342
- examples=[
343
- ["همراه اول با سهمی ۵۳ درصدی بیشترین نقش را دارد."],
344
- ["ایران خودرو حدود 23 هزار میلیارد درآمد کسب کرد."],
345
- ["علی محمدی مدیرعامل بانک ملت گفت که سود 15 درصدی داشته‌اند."]
346
- ],
347
- inputs=input_text
348
- )
 
 
349
 
350
- return interface
 
351
 
352
  if __name__ == "__main__":
353
- interface = create_advanced_interface()
354
- interface.launch()
 
 
 
 
 
 
 
 
 
 
 
1
  """
2
+ OpenRouter API Debug & Test Script
3
+ این اسکریپت مشکلات احتمالی را تشخیص می‌دهد
 
4
  """
5
 
6
  import requests
7
  import json
 
 
8
  import os
 
 
9
 
10
+ def test_openrouter_connection():
11
+ """تست اتصال به OpenRouter"""
 
 
 
 
 
 
 
 
 
 
 
12
 
13
+ api_key = os.getenv("OPENROUTER_API_KEY")
 
 
 
 
 
 
 
14
 
15
+ if not api_key:
16
+ print(" کلید API یافت نشد!")
17
+ print("لطفاً OPENROUTER_API_KEY را در Settings تنظیم کنید")
18
+ return
19
+
20
+ print(f"✅ API Key موجود است (طول: {len(api_key)})")
21
+ print(f"🔑 شروع کلید: {api_key[:10]}...")
22
+
23
+ # لیست مدل‌های رایگان مختلف برای تست
24
+ models_to_test = [
25
+ "qwen/qwen-2.5-7b-instruct:free",
26
+ "meta-llama/llama-3.2-3b-instruct:free",
27
+ "microsoft/phi-3-mini-128k-instruct:free",
28
+ "google/gemini-2.0-flash-exp:free",
29
+ "qwen/qwen-2.5-14b-instruct:free"
30
+ ]
31
+
32
+ url = "https://openrouter.ai/api/v1/chat/completions"
33
+
34
+ test_message = "سلام"
35
+
36
+ for model in models_to_test:
37
+ print(f"\n{'='*60}")
38
+ print(f"🧪 تست مدل: {model}")
39
+ print(f"{'='*60}")
 
 
 
 
 
 
 
 
40
 
 
41
  headers = {
42
+ "Authorization": f"Bearer {api_key}",
43
+ "Content-Type": "application/json"
44
  }
45
 
 
46
  payload = {
47
+ "model": model,
48
  "messages": [
49
+ {"role": "user", "content": test_message}
 
50
  ],
51
+ "max_tokens": 100
 
 
52
  }
53
 
 
 
54
  try:
55
+ print("📡 در حال ارسال درخواست...")
56
+ response = requests.post(url, headers=headers, json=payload, timeout=30)
 
 
 
 
57
 
58
+ print(f"📊 Status Code: {response.status_code}")
59
 
60
+ if response.status_code == 200:
61
+ print("✅ موفق!")
62
+ result = response.json()
63
+ content = result['choices'][0]['message']['content']
64
+ print(f"📝 پاسخ: {content[:100]}...")
65
+ print(f"💰 Usage: {result.get('usage', {})}")
66
+ print(f"\n🎉 این مدل کار می‌کند: {model}")
67
+ return model
68
+ else:
69
+ print(f"❌ خطا!")
70
+ print(f"📄 پاسخ سرور:")
71
+ try:
72
+ error_data = response.json()
73
+ print(json.dumps(error_data, indent=2, ensure_ascii=False))
74
+ except:
75
+ print(response.text)
 
 
 
76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  except Exception as e:
78
+ print(f"❌ Exception: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
 
80
+ print("\n" + "="*60)
81
+ print("❌ هیچ مدلی کار نکرد!")
82
+ print("\n💡 راهنمایی:")
83
+ print("1. بررسی کنید کلید API معتبر است")
84
+ print("2. به https://openrouter.ai/keys بروید و کلید جدید بگیرید")
85
+ print("3. مطمئن شوید کردیت کافی دارید")
86
+ print("4. لیست مدل‌های موجود: https://openrouter.ai/docs/models")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
+ def get_available_models():
89
+ """لیست مدل‌های موجود"""
90
+ api_key = os.getenv("OPENROUTER_API_KEY")
91
 
92
+ if not api_key:
93
+ print("❌ کلید API یافت نشد!")
94
+ return
95
 
96
+ print("\n📋 در حال دریافت لیست مدل‌ها...")
97
+
98
+ try:
99
+ headers = {
100
+ "Authorization": f"Bearer {api_key}"
101
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
 
103
+ response = requests.get(
104
+ "https://openrouter.ai/api/v1/models",
105
+ headers=headers,
106
+ timeout=30
107
  )
108
 
109
+ if response.status_code == 200:
110
+ models = response.json()
111
+ free_models = [m for m in models.get('data', []) if ':free' in m.get('id', '')]
112
+
113
+ print(f"\n✅ تعداد مدل‌های رایگان: {len(free_models)}")
114
+ print("\n🆓 مدل‌های رایگان موجود:")
115
+ for model in free_models[:20]:
116
+ print(f" - {model['id']}")
117
+ else:
118
+ print(f"❌ خطا: {response.status_code}")
119
+ print(response.text)
120
 
121
+ except Exception as e:
122
+ print(f"❌ خطا: {str(e)}")
123
 
124
  if __name__ == "__main__":
125
+ print("🔍 OpenRouter Connection Debugger")
126
+ print("="*60)
127
+
128
+ # تست اتصال
129
+ working_model = test_openrouter_connection()
130
+
131
+ # دریافت لیست مدل‌ها
132
+ # get_available_models()
133
+
134
+ if working_model:
135
+ print(f"\n\n✅ مدل کاری: {working_model}")
136
+ print("این را در کد اصلی استفاده کنید!")