galbendavids commited on
Commit
af1f36c
·
1 Parent(s): f77d065

תיקונים: וידוא טעינת feedback_transformed.csv, שיפור פרומפטים, שיפור מבקר, תיקון היסטוריה

Browse files
Files changed (2) hide show
  1. app/sql_service.py +92 -27
  2. app/static/app.js +8 -3
app/sql_service.py CHANGED
@@ -104,10 +104,17 @@ class SQLFeedbackService:
104
  ValueError: If CSV is missing required columns (handled internally)
105
  """
106
  try:
 
107
  self.df = load_feedback()
108
- print(f"Loaded {len(self.df)} feedback records", flush=True)
 
 
 
 
109
  except Exception as e:
110
- print(f"Error loading feedback data: {e}", flush=True)
 
 
111
  self.df = None
112
 
113
  def _get_schema_info(self) -> str:
@@ -241,7 +248,14 @@ class SQLFeedbackService:
241
  מידע על הטבלה:
242
  {schema_info}
243
 
244
- המשימה שלך: צור 1 עד 5 שאילתות SQL שיעזרו לענות על השאלה. כל שאילתה צריכה להיות שימושית וממוקדת.
 
 
 
 
 
 
 
245
 
246
  כללים חשובים:
247
  1. השתמש בשמות השדות המדויקים: ID, ServiceName, Level, Text, CreationDate
@@ -265,6 +279,8 @@ class SQLFeedbackService:
265
  ]
266
  }}
267
 
 
 
268
  תן רק את ה-JSON, ללא טקסט נוסף."""
269
 
270
  # Try Gemini first
@@ -404,29 +420,62 @@ class SQLFeedbackService:
404
 
405
  return results
406
 
407
- def _evaluate_answer_quality(self, query: str, answer: str) -> tuple[float, str]:
408
  """
409
  Evaluate the quality of an answer using an LLM reviewer.
410
 
 
 
 
 
 
 
411
  Returns:
412
  tuple: (score 0-100, feedback/reasoning)
413
  """
414
- evaluation_prompt = f"""אתה בודק איכות תשובות. הערך את התשובה הבאה:
415
-
416
- שאלת המשתמש: {query}
 
 
 
 
 
 
 
 
 
 
 
 
417
 
418
  התשובה שניתנה:
419
  {answer}
420
 
421
- הערך את התשובה לפי הקריטריונים הבאים (0-100):
422
- 1. האם התשובה עונה ישירות על השאלה? (0-30 נקודות)
 
423
  - אם השאלה מבקשת סיווג/חלוקה לפי שירותים (ServiceName) - האם התשובה כוללת ניתוח נפרד לכל שירות?
424
  - אם השאלה מבקשת סיווג/חלוקה לפי דירוגים (Level) - האם התשובה כוללת ניתוח נפרד לכל דירוג?
425
  - אם השאלה מבקשת סיווג/חלוקה לפי תאריכים - האם התשובה כוללת ניתוח נפרד לפי תקופות?
426
- 2. האם התשובה מבוססת על הנתונים? (0-25 נקודות)
 
 
 
 
 
 
427
  3. האם התשובה מפורטת ומקיפה? (0-20 נקודות)
428
- 4. האם התשובה ברורה ומובנת? (0-15 נקודות)
 
 
 
 
 
 
429
  5. האם התשובה כוללת תובנות עסקיות? (0-10 נקודות)
 
 
430
 
431
  תן ציון כולל (0-100) והסבר קצר (2-3 משפטים) למה הציון הזה.
432
 
@@ -523,14 +572,18 @@ class SQLFeedbackService:
523
 
524
  prompt = f"""אתה אנליסט עסקי בכיר במשרד הפנים, מומחה בייעול תהליכים דיגיטליים ושיפור חוויות המשתמשים בעולם התוכן הממשלתי.
525
 
526
- המשתמש שאל שאלה על משובי משתמשים על שירותים דיגיטליים.
527
 
528
- שאלת המשתמש: {query}
529
-
530
- כדי לענות על השאלה, בוצעו השאילתות הבאות והתקבלו התוצאות הבאות:
531
 
532
  {results_text}
533
 
 
 
 
 
 
 
534
  המשימה שלך: כתוב תשובה מסכמת, ברורה ובשפה חופשית שמבוססת על התוצאות.
535
 
536
  ⚠️ חובה קריטית - תשובה מילולית מפורטת:
@@ -582,8 +635,8 @@ class SQLFeedbackService:
582
  if text and text.strip():
583
  answer = text.strip()
584
 
585
- # Evaluate answer quality
586
- score, reasoning = self._evaluate_answer_quality(query, answer)
587
  print(f"Answer quality score: {score:.1f}/100 - {reasoning}", flush=True)
588
 
589
  # If score is below 80, try to improve
@@ -591,14 +644,20 @@ class SQLFeedbackService:
591
  print(f"Answer quality below threshold (80). Attempting improvement...", flush=True)
592
  improvement_prompt = f"""התשובה הקודמת קיבלה ציון {score}/100. הסיבה: {reasoning}
593
 
594
- שאלת המשתמש: {query}
595
 
596
- התשובה הקודמת:
597
  {answer}
598
 
599
  תוצאות השאילתות:
600
  {results_text}
601
 
 
 
 
 
 
 
602
  כתוב תשובה משופרת שמתמקדת יותר בשאלה המקורית, מבוססת יותר על הנתונים, ומפורטת יותר.
603
  התשובה חייבת לענות ישירות על השאלה: {query}
604
 
@@ -625,8 +684,8 @@ class SQLFeedbackService:
625
  response = model.generate_content(improvement_prompt, generation_config=generation_config)
626
  improved_text = getattr(response, "text", None)
627
  if improved_text and improved_text.strip():
628
- # Re-evaluate improved answer
629
- improved_score, improved_reasoning = self._evaluate_answer_quality(query, improved_text.strip())
630
  print(f"Improved answer quality score: {improved_score:.1f}/100 - {improved_reasoning}", flush=True)
631
  if improved_score > score:
632
  return improved_text.strip()
@@ -651,8 +710,8 @@ class SQLFeedbackService:
651
  if text and text.strip():
652
  answer = text.strip()
653
 
654
- # Evaluate answer quality
655
- score, reasoning = self._evaluate_answer_quality(query, answer)
656
  print(f"Answer quality score: {score:.1f}/100 - {reasoning}", flush=True)
657
 
658
  # If score is below 80, try to improve
@@ -660,14 +719,20 @@ class SQLFeedbackService:
660
  print(f"Answer quality below threshold (80). Attempting improvement...", flush=True)
661
  improvement_prompt = f"""התשובה הקודמת קיבלה ציון {score}/100. הסיבה: {reasoning}
662
 
663
- שאלת המשתמש: {query}
664
 
665
- התשובה הקודמת:
666
  {answer}
667
 
668
  תוצאות השאילתות:
669
  {results_text}
670
 
 
 
 
 
 
 
671
  כתוב תשובה משופרת שמתמקדת יותר בשאלה המקורית, מבוססת יותר על הנתונים, ומפורטת יותר.
672
  התשובה חייבת לענות ישירות על השאלה: {query}
673
 
@@ -699,8 +764,8 @@ class SQLFeedbackService:
699
  )
700
  improved_text = response.choices[0].message.content
701
  if improved_text and improved_text.strip():
702
- # Re-evaluate improved answer
703
- improved_score, improved_reasoning = self._evaluate_answer_quality(query, improved_text.strip())
704
  print(f"Improved answer quality score: {improved_score:.1f}/100 - {improved_reasoning}", flush=True)
705
  if improved_score > score:
706
  return improved_text.strip()
 
104
  ValueError: If CSV is missing required columns (handled internally)
105
  """
106
  try:
107
+ from .config import settings
108
  self.df = load_feedback()
109
+ csv_path_used = settings.csv_path
110
+ print(f"✅ Loaded {len(self.df)} feedback records from: {csv_path_used}", flush=True)
111
+ if 'CreationDate' in self.df.columns:
112
+ sample_dates = self.df['CreationDate'].head(3).tolist()
113
+ print(f"✅ CreationDate sample: {sample_dates}", flush=True)
114
  except Exception as e:
115
+ print(f"Error loading feedback data: {e}", flush=True)
116
+ import traceback
117
+ traceback.print_exc()
118
  self.df = None
119
 
120
  def _get_schema_info(self) -> str:
 
248
  מידע על הטבלה:
249
  {schema_info}
250
 
251
+ המשימה שלך: צור 1 עד 3 שאילתות SQL ממוקדות שיעזרו לענות על השאלה.
252
+
253
+ ⚠️ חשוב מאוד:
254
+ - לא חייב להריץ כמה שאילתות - לפעמים מספיקה שאילתה אחת!
255
+ - שאילתות צריכות להיות ממוקדות ולא מפוזרות
256
+ - כל שאילתה צריכה להיות שימושית ונחוצה לענות על השאלה
257
+ - אם השאלה פשוטה, מספיקה שאילתה אחת
258
+ - אם השאלה מורכבת, אפשר 2-3 שאילתות ממוקדות
259
 
260
  כללים חשובים:
261
  1. השתמש בשמות השדות המדויקים: ID, ServiceName, Level, Text, CreationDate
 
279
  ]
280
  }}
281
 
282
+ ⚠️ זכור: לא חייב להריץ כמה שאילתות! אם השאלה פשוטה, מספיקה שאילתה אחת ממוקדת.
283
+
284
  תן רק את ה-JSON, ללא טקסט נוסף."""
285
 
286
  # Try Gemini first
 
420
 
421
  return results
422
 
423
+ def _evaluate_answer_quality(self, query: str, answer: str, sql_queries: List[str] = None, query_results: List = None) -> tuple[float, str]:
424
  """
425
  Evaluate the quality of an answer using an LLM reviewer.
426
 
427
+ Args:
428
+ query: The user's original question
429
+ answer: The synthesized answer to evaluate
430
+ sql_queries: List of SQL queries that were executed (optional, for context)
431
+ query_results: Results from executing those queries (optional, for context)
432
+
433
  Returns:
434
  tuple: (score 0-100, feedback/reasoning)
435
  """
436
+ # Build context about queries and results if available
437
+ context_text = ""
438
+ if sql_queries and query_results:
439
+ context_text = "\n\nהשאילתות שבוצעו:\n"
440
+ for i, (q, r) in enumerate(zip(sql_queries, query_results), 1):
441
+ context_text += f"{i}. {q}\n"
442
+ if hasattr(r, 'error') and r.error:
443
+ context_text += f" שגיאה: {r.error}\n"
444
+ elif hasattr(r, 'result'):
445
+ context_text += f" תוצאות: {len(r.result) if hasattr(r.result, '__len__') else 'N/A'} שורות\n"
446
+
447
+ evaluation_prompt = f"""אתה בודק איכות תשובות מקצועי. הערך את התשובה הבאה:
448
+
449
+ שאלת המשתמש המקורית: {query}
450
+ {context_text}
451
 
452
  התשובה שניתנה:
453
  {answer}
454
 
455
+ ⚠️ הערך את התשובה לפי הקריטריונים הבאים (0-100):
456
+ 1. האם התשובה עונה ישירות על השאלה המקורית? (0-30 נקודות)
457
+ - האם התשובה מתייחסת ישירות לשאלה: {query}?
458
  - אם השאלה מבקשת סיווג/חלוקה לפי שירותים (ServiceName) - האם התשובה כוללת ניתוח נפרד לכל שירות?
459
  - אם השאלה מבקשת סיווג/חלוקה לפי דירוגים (Level) - האם התשובה כוללת ניתוח נפרד לכל דירוג?
460
  - אם השאלה מבקשת סיווג/חלוקה לפי תאריכים - האם התשובה כוללת ניתוח נפרד לפי תקופות?
461
+ - האם התשובה היא תשובה מילולית מפורטת ולא רק הודעה ששאילתות בוצעו?
462
+
463
+ 2. ��אם התשובה מבוססת על הנתונים והשאילתות? (0-25 נקודות)
464
+ - האם התשובה משתמשת בנתונים מהשאילתות?
465
+ - האם התשובה מסבירה איך השאילתות עוזרות לענות על השאלה?
466
+ - האם התשובה כוללת מספרים מדויקים מהתוצאות?
467
+
468
  3. האם התשובה מפורטת ומקיפה? (0-20 נקודות)
469
+ - האם התשובה ארוכה ומפורטת (לפחות 400-600 מילים)?
470
+ - האם התשובה כוללת ניתוח מעמיק ולא רק רשימת נתונים?
471
+
472
+ 4. האם התשובה ברורה וקוהרנטית? (0-15 נקודות)
473
+ - האם התשובה כתובה בשפה ברורה ומובנת?
474
+ - האם התשובה מאורגנת היטב (לא גיבוב של מילים)?
475
+
476
  5. האם התשובה כוללת תובנות עסקיות? (0-10 נקודות)
477
+ - האם התשובה כוללת תובנות על תהליכים דיגיטליים?
478
+ - האם התשובה כוללת המלצות מעשיות?
479
 
480
  תן ציון כולל (0-100) והסבר קצר (2-3 משפטים) למה הציון הזה.
481
 
 
572
 
573
  prompt = f"""אתה אנליסט עסקי בכיר במשרד הפנים, מומחה בייעול תהליכים דיגיטליים ושיפור חוויות המשתמשים בעולם התוכן הממשלתי.
574
 
575
+ שאלת המשתמש המקורית: {query}
576
 
577
+ כדי לענות על השאלה, נוצרו ובוצעו השאילתות הבאות:
 
 
578
 
579
  {results_text}
580
 
581
+ ⚠️ חשוב מאוד - הבנת השאלה והתשובה:
582
+ 1. קרא היטב את שאלת המשתמש המקורית: {query}
583
+ 2. הבן למה כל שאילתה נוצרה - מה היא מנסה לגלות?
584
+ 3. הבן איך התוצאות של כל שאילתה מסייעות לענות על השאלה המקורית
585
+ 4. חשוב היטב איך לאחד את כל המידע (השאלה + השאילתות + התוצאות) לתשובה קוהרנטית וברורה
586
+
587
  המשימה שלך: כתוב תשובה מסכמת, ברורה ובשפה חופשית שמבוססת על התוצאות.
588
 
589
  ⚠️ חובה קריטית - תשובה מילולית מפורטת:
 
635
  if text and text.strip():
636
  answer = text.strip()
637
 
638
+ # Evaluate answer quality with context
639
+ score, reasoning = self._evaluate_answer_quality(query, answer, sql_queries, query_results)
640
  print(f"Answer quality score: {score:.1f}/100 - {reasoning}", flush=True)
641
 
642
  # If score is below 80, try to improve
 
644
  print(f"Answer quality below threshold (80). Attempting improvement...", flush=True)
645
  improvement_prompt = f"""התשובה הקודמת קיבלה ציון {score}/100. הסיבה: {reasoning}
646
 
647
+ שאלת המשתמש המקורית: {query}
648
 
649
+ התשובה הקודמת (שצריך לשפר):
650
  {answer}
651
 
652
  תוצאות השאילתות:
653
  {results_text}
654
 
655
+ ⚠️ חשוב מאוד - הבנת השאלה והתשובה:
656
+ 1. קרא היטב את שאלת המשתמש המקורית: {query}
657
+ 2. הבן למה כל שאילתה נוצרה - מה היא מנסה לגלות?
658
+ 3. הבן איך התוצאות של כל שאילתה מסייעות לענות על השאלה המקורית
659
+ 4. חשוב היטב איך לאחד את כל המידע (השאלה + השאילתות + התוצאות) לתשובה קוהרנטית וברורה
660
+
661
  כתוב תשובה משופרת שמתמקדת יותר בשאלה המקורית, מבוססת יותר על הנתונים, ומפורטת יותר.
662
  התשובה חייבת לענות ישירות על השאלה: {query}
663
 
 
684
  response = model.generate_content(improvement_prompt, generation_config=generation_config)
685
  improved_text = getattr(response, "text", None)
686
  if improved_text and improved_text.strip():
687
+ # Re-evaluate improved answer with context
688
+ improved_score, improved_reasoning = self._evaluate_answer_quality(query, improved_text.strip(), sql_queries, query_results)
689
  print(f"Improved answer quality score: {improved_score:.1f}/100 - {improved_reasoning}", flush=True)
690
  if improved_score > score:
691
  return improved_text.strip()
 
710
  if text and text.strip():
711
  answer = text.strip()
712
 
713
+ # Evaluate answer quality with context
714
+ score, reasoning = self._evaluate_answer_quality(query, answer, sql_queries, query_results)
715
  print(f"Answer quality score: {score:.1f}/100 - {reasoning}", flush=True)
716
 
717
  # If score is below 80, try to improve
 
719
  print(f"Answer quality below threshold (80). Attempting improvement...", flush=True)
720
  improvement_prompt = f"""התשובה הקודמת קיבלה ציון {score}/100. הסיבה: {reasoning}
721
 
722
+ שאלת המשתמש המקורית: {query}
723
 
724
+ התשובה הקודמת (שצריך לשפר):
725
  {answer}
726
 
727
  תוצאות השאילתות:
728
  {results_text}
729
 
730
+ ⚠️ חשוב מאוד - הבנת השאלה והתשובה:
731
+ 1. קרא היטב את שאלת המשתמש המקורית: {query}
732
+ 2. הבן למה כל שאילתה נוצרה - מה היא מנסה לגלות?
733
+ 3. הבן איך התוצאות של כל שאילתה מסייעות לענות על השאלה המקורית
734
+ 4. חשוב היטב איך לאחד את כל המידע (השאלה + השאילתות + התוצאות) לתשובה קוהרנטית וברורה
735
+
736
  כתוב תשובה משופרת שמתמקדת יותר בשאלה המקורית, מבוססת יותר על הנתונים, ומפורטת יותר.
737
  התשובה חייבת לענות ישירות על השאלה: {query}
738
 
 
764
  )
765
  improved_text = response.choices[0].message.content
766
  if improved_text and improved_text.strip():
767
+ # Re-evaluate improved answer with context
768
+ improved_score, improved_reasoning = self._evaluate_answer_quality(query, improved_text.strip(), sql_queries, query_results)
769
  print(f"Improved answer quality score: {improved_score:.1f}/100 - {improved_reasoning}", flush=True)
770
  if improved_score > score:
771
  return improved_text.strip()
app/static/app.js CHANGED
@@ -51,7 +51,10 @@ async function refreshHistory() {
51
  });
52
  } catch (e) {
53
  console.error('history fetch failed', e);
54
- container.innerHTML = '<div style="color: #d32f2f;">שגיאה בטעינת ההיסטוריה</div>';
 
 
 
55
  }
56
  }
57
 
@@ -126,8 +129,10 @@ async function sendQuery() {
126
  showVisualizations(j.visualizations);
127
  }
128
 
129
- // Refresh history
130
- await refreshHistory();
 
 
131
 
132
  // Scroll to response
133
  responseSection.scrollIntoView({ behavior: 'smooth', block: 'start' });
 
51
  });
52
  } catch (e) {
53
  console.error('history fetch failed', e);
54
+ const container = document.getElementById('history');
55
+ if (container) {
56
+ container.innerHTML = '<div style="color: #d32f2f;">שגיאה בטעינת ההיסטוריה: ' + escapeHtml(e.message) + '</div>';
57
+ }
58
  }
59
  }
60
 
 
129
  showVisualizations(j.visualizations);
130
  }
131
 
132
+ // Refresh history after a short delay to ensure server has saved it
133
+ setTimeout(async () => {
134
+ await refreshHistory();
135
+ }, 500);
136
 
137
  // Scroll to response
138
  responseSection.scrollIntoView({ behavior: 'smooth', block: 'start' });