yahya1912 commited on
Commit
2a5b8f8
·
verified ·
1 Parent(s): 273d7ce

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +55 -52
app.py CHANGED
@@ -6,11 +6,11 @@ import json, re, os, requests
6
  hf_token = os.getenv("HF_TOKEN")
7
  google_key = os.getenv("GOOGLE_MAPS_API_KEY")
8
 
 
9
  client = InferenceClient("Qwen/Qwen2.5-7B-Instruct", token=hf_token)
10
 
11
  # ==================== SYSTEM PROMPT المُحسَّن ====================
12
- SYSTEM_PROMPT = """
13
- Analyze the Arabic map query and return ONLY a JSON object with these exact keys:
14
 
15
  1. "location": City, area, or "near me" if not specified.
16
  2. "category": The main place type. Use standard Arabic terms:
@@ -54,8 +54,7 @@ Input: "محطة وقود 24 ساعة رخيصة"
54
  Output: {"location": "near me", "category": "محطة وقود", "sub_type": null, "features": ["24 ساعة", "رخيصة"], "sort_by": "price"}
55
 
56
  Input: "مقهى هادئ للعمل في الرياض"
57
- Output: {"location": "الرياض", "category": "مقهى", "sub_type": null, "features": ["هادئ", "للعمل"], "sort_by": "relevance"}
58
- """
59
 
60
  # ==================== دوال البحث والمعالجة ====================
61
 
@@ -63,24 +62,19 @@ def build_search_query(parsed_data):
63
  """بناء جملة بحث محسّنة من البيانات المستخرجة"""
64
  parts = []
65
 
66
- # نبدأ بالتصنيف الرئيسي
67
  category = parsed_data.get("category", "")
68
  if category:
69
  parts.append(category)
70
 
71
- # نضيف النوع الفرعي إذا موجود
72
  sub_type = parsed_data.get("sub_type")
73
  if sub_type and sub_type != category:
74
  parts.append(str(sub_type))
75
 
76
- # نضيف الموقع
77
  location = parsed_data.get("location", "")
78
  if location and location != "near me":
79
  parts.append(f"في {location}")
80
 
81
- # نضيف الصفات المهمة للبحث (نختار الأكثر صلة)
82
  features = parsed_data.get("features", [])
83
- # نصفات تساعد في البحث: 24 ساعة، طوارئ، أطفال، إلخ
84
  search_features = [f for f in features if any(keyword in f for keyword in
85
  ["24", "طوارئ", "أطفال", "مجاني", "مفتوح", "فاخر", "اقتصادي"])]
86
  parts.extend(search_features)
@@ -91,7 +85,6 @@ def search_google_maps(parsed_data):
91
  if not google_key:
92
  return "⚠️ الرجاء إضافة GOOGLE_MAPS_API_KEY في إعدادات الـ Space."
93
 
94
- # بناء جملة البحث المحسّنة
95
  query = build_search_query(parsed_data)
96
 
97
  if not query.strip():
@@ -104,11 +97,7 @@ def search_google_maps(parsed_data):
104
  "key": google_key
105
  }
106
 
107
- # إضافة معايير إضافية حسب نوع الترتيب
108
  sort_by = parsed_data.get("sort_by", "relevance")
109
- if sort_by == "distance":
110
- # يمكن إضافة location bias لاحقاً إذا توفر GPS
111
- pass
112
 
113
  try:
114
  response = requests.get(url, params=params, timeout=10)
@@ -123,28 +112,23 @@ def search_google_maps(parsed_data):
123
  if not results:
124
  return "❌ لم يتم العثور على نتائج. جرب تعديل البحث."
125
 
126
- # ترتيب النتائج حسب المعيار المطلوب
127
  if sort_by == "rating":
128
  results = sorted(results, key=lambda x: x.get("rating", 0), reverse=True)
129
  elif sort_by == "price":
130
- # Google Places API يعطي price_level (0-4)
131
  results = sorted(results, key=lambda x: x.get("price_level", 4))
132
 
133
- # تنسيق النتائج للعرض
134
  output_list = []
135
- for i, place in enumerate(results[:6], 1): # عرض أول 6 نتائج
136
  name = place.get("name", "غير معروف")
137
  rating = place.get("rating", "غير متوفر")
138
  total_ratings = place.get("user_ratings_total", 0)
139
  address = place.get("formatted_address", "العنوان غير متوفر")
140
 
141
- # تحديد مستوى السعر
142
  price_level = place.get("price_level")
143
  price_str = ""
144
  if price_level:
145
  price_str = "💰" * price_level
146
 
147
- # حالة الافتتاح
148
  open_now = place.get("opening_hours", {}).get("open_now")
149
  status = ""
150
  if open_now is True:
@@ -152,7 +136,6 @@ def search_google_maps(parsed_data):
152
  elif open_now is False:
153
  status = " ❌ مغلق الآن"
154
 
155
- # أنواع الأماكن (types)
156
  types = place.get("types", [])
157
  place_type = ", ".join([t.replace("_", " ") for t in types[:2]])
158
 
@@ -163,7 +146,6 @@ def search_google_maps(parsed_data):
163
  ---"""
164
  output_list.append(card)
165
 
166
- # إضافة ملخص البحث
167
  summary = f"🔍 **نتائج البحث عن:** `{query}` | **الترتيب حسب:** {sort_by}\n\n"
168
  return summary + "\n".join(output_list)
169
 
@@ -172,45 +154,61 @@ def search_google_maps(parsed_data):
172
  except Exception as e:
173
  return f"❌ خطأ في الاتصال: {str(e)}"
174
 
175
- def main_process(user_query):
176
- if not user_query.strip():
177
- return {"error": "الرجاء إدخال استعلام"}, "لا توجد نتائج"
178
-
179
- # 1. تحليل القصد باستخدام LLM
180
  try:
181
- resp = client.chat_completions.create(
182
- messages=[
183
- {"role": "system", "content": SYSTEM_PROMPT},
184
- {"role": "user", "content": user_query}
185
- ],
 
 
 
 
186
  max_tokens=300,
187
- temperature=0.1
 
188
  )
189
 
190
- raw_content = resp.choices[0].message.content
191
- match = re.search(r'\{.*\}', raw_content, re.DOTALL)
 
 
 
 
 
192
 
 
 
193
  if not match:
194
  return {
195
  "error": "لم يتم العثور على JSON صالح",
196
- "raw_response": raw_content
197
- }, "خطأ في تحليل البيانات"
198
 
199
  parsed_data = json.loads(match.group(0))
200
-
201
- # التحقق من وجود الأخطاء في البيانات المستخرجة
202
- if "error" in parsed_data:
203
- return parsed_data, "فشل في تحليل الاستعلام"
204
-
205
- # 2. البحث في Google Maps
206
- map_results = search_google_maps(parsed_data)
207
-
208
- return parsed_data, map_results
209
 
210
  except json.JSONDecodeError as e:
211
- return {"error": f"خطأ في قراءة JSON: {str(e)}"}, "فشل في تحليل البيانات"
212
  except Exception as e:
213
- return {"error": f"خطأ غير متوقع: {str(e)}"}, "فشل في جلب البيانات"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
 
215
  # ==================== واجهة المستخدم ====================
216
 
@@ -246,13 +244,18 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
246
  "صيدلية قريبة مني مفتوحة الآن"
247
  ]
248
 
 
249
  with gr.Row():
250
- for i, ex in enumerate(examples[:3]):
251
- gr.Button(ex, size="sm").click(lambda x=ex: x, None, input_text)
 
 
252
 
253
  with gr.Row():
254
- for i, ex in enumerate(examples[3:]):
255
- gr.Button(ex, size="sm").click(lambda x=ex: x, None, input_text)
 
 
256
 
257
  btn.click(fn=main_process, inputs=input_text, outputs=[output_json, output_map])
258
 
 
6
  hf_token = os.getenv("HF_TOKEN")
7
  google_key = os.getenv("GOOGLE_MAPS_API_KEY")
8
 
9
+ # إنشاء العميل - الطريقة الصحيحة
10
  client = InferenceClient("Qwen/Qwen2.5-7B-Instruct", token=hf_token)
11
 
12
  # ==================== SYSTEM PROMPT المُحسَّن ====================
13
+ SYSTEM_PROMPT = """Analyze the Arabic map query and return ONLY a JSON object with these exact keys:
 
14
 
15
  1. "location": City, area, or "near me" if not specified.
16
  2. "category": The main place type. Use standard Arabic terms:
 
54
  Output: {"location": "near me", "category": "محطة وقود", "sub_type": null, "features": ["24 ساعة", "رخيصة"], "sort_by": "price"}
55
 
56
  Input: "مقهى هادئ للعمل في الرياض"
57
+ Output: {"location": "الرياض", "category": "مقهى", "sub_type": null, "features": ["هادئ", "للعمل"], "sort_by": "relevance"}"""
 
58
 
59
  # ==================== دوال البحث والمعالجة ====================
60
 
 
62
  """بناء جملة بحث محسّنة من البيانات المستخرجة"""
63
  parts = []
64
 
 
65
  category = parsed_data.get("category", "")
66
  if category:
67
  parts.append(category)
68
 
 
69
  sub_type = parsed_data.get("sub_type")
70
  if sub_type and sub_type != category:
71
  parts.append(str(sub_type))
72
 
 
73
  location = parsed_data.get("location", "")
74
  if location and location != "near me":
75
  parts.append(f"في {location}")
76
 
 
77
  features = parsed_data.get("features", [])
 
78
  search_features = [f for f in features if any(keyword in f for keyword in
79
  ["24", "طوارئ", "أطفال", "مجاني", "مفتوح", "فاخر", "اقتصادي"])]
80
  parts.extend(search_features)
 
85
  if not google_key:
86
  return "⚠️ الرجاء إضافة GOOGLE_MAPS_API_KEY في إعدادات الـ Space."
87
 
 
88
  query = build_search_query(parsed_data)
89
 
90
  if not query.strip():
 
97
  "key": google_key
98
  }
99
 
 
100
  sort_by = parsed_data.get("sort_by", "relevance")
 
 
 
101
 
102
  try:
103
  response = requests.get(url, params=params, timeout=10)
 
112
  if not results:
113
  return "❌ لم يتم العثور على نتائج. جرب تعديل البحث."
114
 
 
115
  if sort_by == "rating":
116
  results = sorted(results, key=lambda x: x.get("rating", 0), reverse=True)
117
  elif sort_by == "price":
 
118
  results = sorted(results, key=lambda x: x.get("price_level", 4))
119
 
 
120
  output_list = []
121
+ for i, place in enumerate(results[:6], 1):
122
  name = place.get("name", "غير معروف")
123
  rating = place.get("rating", "غير متوفر")
124
  total_ratings = place.get("user_ratings_total", 0)
125
  address = place.get("formatted_address", "العنوان غير متوفر")
126
 
 
127
  price_level = place.get("price_level")
128
  price_str = ""
129
  if price_level:
130
  price_str = "💰" * price_level
131
 
 
132
  open_now = place.get("opening_hours", {}).get("open_now")
133
  status = ""
134
  if open_now is True:
 
136
  elif open_now is False:
137
  status = " ❌ مغلق الآن"
138
 
 
139
  types = place.get("types", [])
140
  place_type = ", ".join([t.replace("_", " ") for t in types[:2]])
141
 
 
146
  ---"""
147
  output_list.append(card)
148
 
 
149
  summary = f"🔍 **نتائج البحث عن:** `{query}` | **الترتيب حسب:** {sort_by}\n\n"
150
  return summary + "\n".join(output_list)
151
 
 
154
  except Exception as e:
155
  return f"❌ خطأ في الاتصال: {str(e)}"
156
 
157
+ def parse_arabic_query(user_query):
158
+ """تحليل الاستعلام باستخدام LLM - الطريقة الصحيحة"""
 
 
 
159
  try:
160
+ # الطريقة الصحيحة لاستخدام InferenceClient مع النماذج المحادثة
161
+ messages = [
162
+ {"role": "system", "content": SYSTEM_PROMPT},
163
+ {"role": "user", "content": user_query}
164
+ ]
165
+
166
+ # استخدام chat_completion (مع underscore) أو text_generation
167
+ response = client.chat_completion(
168
+ messages=messages,
169
  max_tokens=300,
170
+ temperature=0.1,
171
+ stream=False
172
  )
173
 
174
+ # استخراج المحتوى - قد يكون في أماكن مختلفة حسب الإصدار
175
+ if hasattr(response, 'choices') and response.choices:
176
+ raw_content = response.choices[0].message.content
177
+ elif isinstance(response, dict) and 'choices' in response:
178
+ raw_content = response['choices'][0]['message']['content']
179
+ else:
180
+ raw_content = str(response)
181
 
182
+ # البحث عن JSON في الرد
183
+ match = re.search(r'\{.*\}', raw_content, re.DOTALL)
184
  if not match:
185
  return {
186
  "error": "لم يتم العثور على JSON صالح",
187
+ "raw_response": raw_content[:500]
188
+ }
189
 
190
  parsed_data = json.loads(match.group(0))
191
+ return parsed_data
 
 
 
 
 
 
 
 
192
 
193
  except json.JSONDecodeError as e:
194
+ return {"error": f"خطأ في قراءة JSON: {str(e)}"}
195
  except Exception as e:
196
+ return {"error": f"خطأ في تحليل الاستعلام: {str(e)}"}
197
+
198
+ def main_process(user_query):
199
+ if not user_query.strip():
200
+ return {"error": "الرجاء إدخال استعلام"}, "لا توجد نتائج"
201
+
202
+ # 1. تحليل القصد
203
+ parsed_data = parse_arabic_query(user_query)
204
+
205
+ if "error" in parsed_data:
206
+ return parsed_data, f"⚠️ {parsed_data.get('error', 'خطأ غير معروف')}"
207
+
208
+ # 2. البحث في Google Maps
209
+ map_results = search_google_maps(parsed_data)
210
+
211
+ return parsed_data, map_results
212
 
213
  # ==================== واجهة المستخدم ====================
214
 
 
244
  "صيدلية قريبة مني مفتوحة الآن"
245
  ]
246
 
247
+ example_buttons = []
248
  with gr.Row():
249
+ for ex in examples[:3]:
250
+ btn_ex = gr.Button(ex, size="sm")
251
+ btn_ex.click(lambda x=ex: x, None, input_text)
252
+ example_buttons.append(btn_ex)
253
 
254
  with gr.Row():
255
+ for ex in examples[3:]:
256
+ btn_ex = gr.Button(ex, size="sm")
257
+ btn_ex.click(lambda x=ex: x, None, input_text)
258
+ example_buttons.append(btn_ex)
259
 
260
  btn.click(fn=main_process, inputs=input_text, outputs=[output_json, output_map])
261