MHD011 commited on
Commit
e1cc896
·
verified ·
1 Parent(s): 5f253ea

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +36 -59
app.py CHANGED
@@ -60,7 +60,7 @@ initialize()
60
 
61
  # سكيما قاعدة البيانات (نفسها كما في الكود الأصلي)
62
  DB_SCHEMA = """
63
- CREATE TABLE public.profiles (
64
  id uuid NOT NULL,
65
  updated_at timestamp with time zone,
66
  username text UNIQUE CHECK (char_length(username) >= 3),
@@ -74,14 +74,14 @@ CREATE TABLE public.profiles (
74
  CONSTRAINT profiles_id_fkey FOREIGN KEY (id) REFERENCES auth.users(id)
75
  );
76
 
77
- CREATE TABLE public.place (
78
  id bigint GENERATED ALWAYS AS IDENTITY NOT NULL,
79
  created_at timestamp with time zone DEFAULT (now() AT TIME ZONE 'utc'::text),
80
  name text,
81
  CONSTRAINT place_pkey PRIMARY KEY (id)
82
  );
83
 
84
- CREATE TABLE public.user_place (
85
  id bigint GENERATED ALWAYS AS IDENTITY NOT NULL,
86
  created_at timestamp with time zone NOT NULL DEFAULT now(),
87
  place_id bigint,
@@ -91,7 +91,7 @@ CREATE TABLE public.user_place (
91
  CONSTRAINT user_place_user_cam_mac_fkey FOREIGN KEY (user_cam_mac) REFERENCES public.profiles(cam_mac)
92
  );
93
 
94
- CREATE TABLE public.data (
95
  id bigint GENERATED ALWAYS AS IDENTITY NOT NULL,
96
  created_at timestamp without time zone,
97
  caption text,
@@ -104,7 +104,7 @@ CREATE TABLE public.data (
104
  CONSTRAINT data_user_place_id_fkey FOREIGN KEY (user_place_id) REFERENCES public.user_place(id)
105
  );
106
 
107
- CREATE TABLE public.biodata (
108
  id bigint GENERATED ALWAYS AS IDENTITY NOT NULL,
109
  created_at timestamp with time zone NOT NULL DEFAULT now(),
110
  mac_address text,
@@ -119,7 +119,7 @@ CREATE TABLE public.biodata (
119
  CONSTRAINT biodata_mac_address_fkey FOREIGN KEY (mac_address) REFERENCES public.profiles(cam_mac)
120
  );
121
 
122
- CREATE TABLE public.notification (
123
  id bigint GENERATED ALWAYS AS IDENTITY NOT NULL,
124
  created_at timestamp without time zone NOT NULL DEFAULT now(),
125
  user_cam_mac text,
@@ -136,7 +136,7 @@ CREATE TABLE public.notification (
136
  CONSTRAINT notification_user_cam_mac_fkey FOREIGN KEY (user_cam_mac) REFERENCES public.profiles(cam_mac)
137
  );
138
 
139
- CREATE TABLE public.flag (
140
  id bigint GENERATED ALWAYS AS IDENTITY NOT NULL,
141
  flag smallint,
142
  user_mac_address text,
@@ -192,17 +192,27 @@ def is_safe_sql(sql):
192
 
193
  return True
194
 
195
- def clean_sql(sql):
196
  """تنظيف استعلام SQL لضمان أنه SELECT فقط"""
 
 
 
 
 
 
197
  # إزالة أي شيء قبل SELECT
198
  sql = re.sub(r'^[^S]*(SELECT)', 'SELECT', sql, flags=re.IGNORECASE)
199
 
200
- # أخذ أول عبارة SQL فقط (تجاهل أي شيء بعد ;)
201
  sql = sql.split(';')[0] + ';'
202
 
203
  # إزالة المسافات الزائدة
204
  sql = ' '.join(sql.split()).strip()
205
 
 
 
 
 
206
  return sql
207
 
208
  @app.route('/api/query', methods=['POST'])
@@ -222,39 +232,45 @@ def handle_query():
222
  1. قم بتحويل السؤال إلى استعلام SELECT فقط لـ PostgreSQL.
223
  2. يجب أن يتضمن الشرط: WHERE cam_mac = '{data['cam_mac']}'.
224
  3. ممنوع تمامًا استخدام أي أوامر غير SELECT.
 
225
 
226
  ### هيكل قاعدة البيانات:
227
  {DB_SCHEMA}
228
 
 
 
 
 
 
 
 
229
  ### السؤال:
230
  {data['text']}
231
 
232
  ### استعلام SQL (SELECT فقط):
233
  """
234
 
235
- # تحضير المدخلات بدون تحويل نوع البيانات مباشرة
236
- inputs = tokenizer(prompt, return_tensors="pt", truncation=True, max_length=512)
237
-
238
- # نقل المدخلات إلى الجهاز المناسب (CPU/GPU)
239
- device = 'cuda' if torch.cuda.is_available() else 'cpu'
240
- inputs = {k: v.to(device) for k, v in inputs.items()}
241
 
242
  with torch.no_grad():
243
  outputs = model.generate(
244
  **inputs,
245
  max_length=256,
246
  num_beams=4,
247
- early_stopping=True
 
248
  )
249
 
250
  sql = tokenizer.decode(outputs[0], skip_special_tokens=True)
251
- logger.info(f"⚡ الاستعلام المولد: {sql}")
252
 
253
- sql = clean_sql(sql)
 
254
 
255
  if not is_safe_sql(sql):
256
- return jsonify({"error": "تم توليد استعلام غير آمن"}), 400
257
-
 
258
  conn = get_db_connection()
259
  if not conn:
260
  return jsonify({"error": "فشل الاتصال بقاعدة البيانات"}), 500
@@ -287,45 +303,6 @@ def handle_query():
287
  logger.error(f"❌ خطأ غير متوقع: {str(e)}", exc_info=True)
288
  return jsonify({"error": "فشل في معالجة الطلب"}), 500
289
 
290
- try:
291
- cursor = conn.cursor()
292
- cursor.execute(sql)
293
-
294
- if cursor.description:
295
- columns = [desc[0] for desc in cursor.description]
296
- rows = cursor.fetchall()
297
- data = [dict(zip(columns, row)) for row in rows]
298
-
299
- response = {
300
- "data": data,
301
- "sql": sql,
302
- "timestamp": datetime.now().isoformat()
303
- }
304
- else:
305
- conn.commit()
306
- response = {
307
- "message": "تم تنفيذ الاستعلام بنجاح (لا توجد بيانات للإرجاع)",
308
- "sql": sql
309
- }
310
-
311
- return jsonify(response)
312
-
313
- except Exception as e:
314
- logger.error(f"❌ خطأ في تنفيذ SQL: {e}\nالاستعلام: {sql}")
315
- return jsonify({
316
- "error": "خطأ في تنفيذ الاستعلام",
317
- "sql": sql,
318
- "details": str(e)
319
- }), 500
320
-
321
- finally:
322
- if conn:
323
- conn.close()
324
-
325
- except Exception as e:
326
- logger.error(f"❌ خطأ غير متوقع: {str(e)}", exc_info=True)
327
- return jsonify({"error": "فشل في معالجة الطلب"}), 500
328
-
329
  @app.route('/health')
330
  def health_check():
331
  return jsonify({
 
60
 
61
  # سكيما قاعدة البيانات (نفسها كما في الكود الأصلي)
62
  DB_SCHEMA = """
63
+ profiles (
64
  id uuid NOT NULL,
65
  updated_at timestamp with time zone,
66
  username text UNIQUE CHECK (char_length(username) >= 3),
 
74
  CONSTRAINT profiles_id_fkey FOREIGN KEY (id) REFERENCES auth.users(id)
75
  );
76
 
77
+ place (
78
  id bigint GENERATED ALWAYS AS IDENTITY NOT NULL,
79
  created_at timestamp with time zone DEFAULT (now() AT TIME ZONE 'utc'::text),
80
  name text,
81
  CONSTRAINT place_pkey PRIMARY KEY (id)
82
  );
83
 
84
+ user_place (
85
  id bigint GENERATED ALWAYS AS IDENTITY NOT NULL,
86
  created_at timestamp with time zone NOT NULL DEFAULT now(),
87
  place_id bigint,
 
91
  CONSTRAINT user_place_user_cam_mac_fkey FOREIGN KEY (user_cam_mac) REFERENCES public.profiles(cam_mac)
92
  );
93
 
94
+ data (
95
  id bigint GENERATED ALWAYS AS IDENTITY NOT NULL,
96
  created_at timestamp without time zone,
97
  caption text,
 
104
  CONSTRAINT data_user_place_id_fkey FOREIGN KEY (user_place_id) REFERENCES public.user_place(id)
105
  );
106
 
107
+ biodata (
108
  id bigint GENERATED ALWAYS AS IDENTITY NOT NULL,
109
  created_at timestamp with time zone NOT NULL DEFAULT now(),
110
  mac_address text,
 
119
  CONSTRAINT biodata_mac_address_fkey FOREIGN KEY (mac_address) REFERENCES public.profiles(cam_mac)
120
  );
121
 
122
+ notification (
123
  id bigint GENERATED ALWAYS AS IDENTITY NOT NULL,
124
  created_at timestamp without time zone NOT NULL DEFAULT now(),
125
  user_cam_mac text,
 
136
  CONSTRAINT notification_user_cam_mac_fkey FOREIGN KEY (user_cam_mac) REFERENCES public.profiles(cam_mac)
137
  );
138
 
139
+ flag (
140
  id bigint GENERATED ALWAYS AS IDENTITY NOT NULL,
141
  flag smallint,
142
  user_mac_address text,
 
192
 
193
  return True
194
 
195
+ def clean_sql(sql, cam_mac):
196
  """تنظيف استعلام SQL لضمان أنه SELECT فقط"""
197
+ # إزالة أي أوامر غير SELECT
198
+ sql = re.sub(r'CREATE\s+TABLE', '', sql, flags=re.IGNORECASE)
199
+ sql = re.sub(r'INSERT\s+INTO', '', sql, flags=re.IGNORECASE)
200
+ sql = re.sub(r'UPDATE\s+', '', sql, flags=re.IGNORECASE)
201
+ sql = re.sub(r'DELETE\s+FROM', '', sql, flags=re.IGNORECASE)
202
+
203
  # إزالة أي شيء قبل SELECT
204
  sql = re.sub(r'^[^S]*(SELECT)', 'SELECT', sql, flags=re.IGNORECASE)
205
 
206
+ # أخذ أول عبارة SQL فقط
207
  sql = sql.split(';')[0] + ';'
208
 
209
  # إزالة المسافات الزائدة
210
  sql = ' '.join(sql.split()).strip()
211
 
212
+ # إذا لم يعد يحتوي على SELECT بعد التنظيف
213
+ if not sql.upper().startswith('SELECT'):
214
+ return f"SELECT id, created_at FROM data WHERE cam_mac = '{cam_mac}' ORDER BY created_at DESC LIMIT 1;"
215
+
216
  return sql
217
 
218
  @app.route('/api/query', methods=['POST'])
 
232
  1. قم بتحويل السؤال إلى استعلام SELECT فقط لـ PostgreSQL.
233
  2. يجب أن يتضمن الشرط: WHERE cam_mac = '{data['cam_mac']}'.
234
  3. ممنوع تمامًا استخدام أي أوامر غير SELECT.
235
+ 4. استخدم أسماء الجداول الموجودة فقط: profiles, place, user_place, data, biodata, notification, flag.
236
 
237
  ### هيكل قاعدة البيانات:
238
  {DB_SCHEMA}
239
 
240
+ ### أمثلة صحيحة:
241
+ - السؤال: "ما عدد زياراتي للمكتب؟"
242
+ SQL: SELECT COUNT(*) FROM data WHERE cam_mac = '{data['cam_mac']}';
243
+
244
+ - السؤال: "ما هي آخر زيارة؟"
245
+ SQL: SELECT id, created_at FROM data WHERE cam_mac = '{data['cam_mac']}' ORDER BY created_at DESC LIMIT 1;
246
+
247
  ### السؤال:
248
  {data['text']}
249
 
250
  ### استعلام SQL (SELECT فقط):
251
  """
252
 
253
+ inputs = tokenizer(prompt, return_tensors="pt", truncation=True, max_length=512).to('cpu')
 
 
 
 
 
254
 
255
  with torch.no_grad():
256
  outputs = model.generate(
257
  **inputs,
258
  max_length=256,
259
  num_beams=4,
260
+ early_stopping=True,
261
+ temperature=0.7
262
  )
263
 
264
  sql = tokenizer.decode(outputs[0], skip_special_tokens=True)
265
+ logger.info(f"⚡ الاستعلام المولد (قبل التنظيف): {sql}")
266
 
267
+ sql = clean_sql(sql, data['cam_mac'])
268
+ logger.info(f"🔧 الاستعلام بعد التنظيف: {sql}")
269
 
270
  if not is_safe_sql(sql):
271
+ logger.warning(f"استعلام غير آمن بعد التنظيف، استخدام استعلام افتراضي")
272
+ sql = f"SELECT id, created_at FROM data WHERE cam_mac = '{data['cam_mac']}' ORDER BY created_at DESC LIMIT 10;"
273
+
274
  conn = get_db_connection()
275
  if not conn:
276
  return jsonify({"error": "فشل الاتصال بقاعدة البيانات"}), 500
 
303
  logger.error(f"❌ خطأ غير متوقع: {str(e)}", exc_info=True)
304
  return jsonify({"error": "فشل في معالجة الطلب"}), 500
305
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
306
  @app.route('/health')
307
  def health_check():
308
  return jsonify({