galbendavids commited on
Commit
395afb7
·
1 Parent(s): feb8cc9

שיפורים: רקע תכלת, גרפים גדולים יותר, שיפור ולידציה, הכנה ל-HF Spaces

Browse files
Dockerfile CHANGED
@@ -17,9 +17,10 @@ RUN pip install --upgrade pip && \
17
  # Copy application code
18
  COPY . .
19
 
20
- # Expose port
21
- EXPOSE 8000
22
 
23
  # Run the application
24
- CMD ["python", "run.py"]
 
25
 
 
17
  # Copy application code
18
  COPY . .
19
 
20
+ # Expose port (7860 for HF Spaces, 8000 for local)
21
+ EXPOSE 7860
22
 
23
  # Run the application
24
+ # Use app.py for HF Spaces (detects port from env), run.py for local
25
+ CMD ["python", "app.py"]
26
 
HUGGINGFACE_DEPLOYMENT.md ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # הדרכה לפריסה ב-Hugging Face Spaces
2
+
3
+ מדריך זה מסביר איך לפרוס את מערכת ניתוח המשובים ב-Hugging Face Spaces.
4
+
5
+ ## דרישות מקדימות
6
+
7
+ 1. חשבון ב-[Hugging Face](https://huggingface.co/)
8
+ 2. API Key מ-Gemini או OpenAI
9
+ 3. קובץ `Feedback.csv` עם הנתונים
10
+
11
+ ## שלבים לפריסה
12
+
13
+ ### 1. הכנת הפרויקט
14
+
15
+ הפרויקט כבר מוכן לפריסה ב-HF Spaces:
16
+ - ✅ `app.py` - נקודת כניסה ל-HF Spaces
17
+ - ✅ `requirements.txt` - תלויות Python
18
+ - ✅ `README.md` - תיעוד עם metadata
19
+
20
+ ### 2. יצירת Space חדש ב-Hugging Face
21
+
22
+ 1. היכנס ל-[Hugging Face Spaces](https://huggingface.co/spaces)
23
+ 2. לחץ על **"Create new Space"**
24
+ 3. מלא את הפרטים:
25
+ - **Space name**: `feedback-analysis-agent` (או שם אחר לבחירתך)
26
+ - **SDK**: בחר **"Docker"** (כי אנחנו משתמשים ב-FastAPI)
27
+ - **Visibility**: בחר **Public** או **Private** לפי הצורך
28
+ 4. לחץ על **"Create Space"**
29
+
30
+ ### 3. העלאת הקוד
31
+
32
+ יש לך שתי אפשרויות:
33
+
34
+ #### אפשרות א': דרך Git (מומלץ)
35
+
36
+ 1. ב-HF Space, תמצא את ה-URL של ה-Git repository
37
+ 2. הוסף את ה-remote:
38
+ ```bash
39
+ git remote add huggingface https://huggingface.co/spaces/YOUR_USERNAME/YOUR_SPACE_NAME
40
+ ```
41
+ 3. דחוף את הקוד:
42
+ ```bash
43
+ git push huggingface main
44
+ ```
45
+
46
+ #### אפשרות ב': דרך ה-Web UI
47
+
48
+ 1. פתח את ה-Space ב-Hugging Face
49
+ 2. לחץ על **"Files and versions"**
50
+ 3. העלה את הקבצים הבאים:
51
+ - `app.py`
52
+ - `requirements.txt`
53
+ - `README.md`
54
+ - כל התיקייה `app/`
55
+ - `Feedback.csv` (אם אתה רוצה לכלול אותו ב-repo)
56
+
57
+ ### 4. הגדרת Environment Variables
58
+
59
+ 1. ב-Space שלך, לך ל-**"Settings"** → **"Repository secrets"**
60
+ 2. הוסף את ה-secrets הבאים:
61
+ - `GEMINI_API_KEY` - ה-API key שלך מ-Google Gemini
62
+ - או `OPENAI_API_KEY` - ה-API key שלך מ-OpenAI
63
+ - **הערה**: לפחות אחד מהם חייב להיות מוגדר
64
+
65
+ ### 5. העלאת קובץ הנתונים
66
+
67
+ יש לך שתי אפשרויות:
68
+
69
+ #### אפשרות א': דרך Git (אם הקובץ קטן)
70
+
71
+ 1. הוסף את `Feedback.csv` ל-repository
72
+ 2. דחוף את השינויים
73
+
74
+ #### אפשרות ב': דרך ה-Web UI
75
+
76
+ 1. פתח את ה-Space
77
+ 2. לחץ על **"Files and versions"**
78
+ 3. העלה את `Feedback.csv` לתיקייה הראשית
79
+
80
+ **הערה**: אם הקובץ גדול (>10MB), ייתכן שתצטרך להשתמש ב-Git LFS או להעלות אותו דרך API.
81
+
82
+ ### 6. הגדרת Dockerfile (אופציונלי)
83
+
84
+ אם אתה רוצה להתאים אישית את ה-Docker image:
85
+
86
+ 1. צור `Dockerfile` בשורש הפרויקט
87
+ 2. HF Spaces ישתמש בו אוטומטית
88
+
89
+ דוגמה ל-Dockerfile:
90
+ ```dockerfile
91
+ FROM python:3.10-slim
92
+
93
+ WORKDIR /app
94
+
95
+ COPY requirements.txt .
96
+ RUN pip install --no-cache-dir -r requirements.txt
97
+
98
+ COPY . .
99
+
100
+ EXPOSE 7860
101
+
102
+ CMD ["python", "app.py"]
103
+ ```
104
+
105
+ ### 7. בדיקה
106
+
107
+ 1. HF Spaces יבנה את ה-Space אוטומטית
108
+ 2. תוכל לראות את הלוגים ב-**"Logs"** tab
109
+ 3. לאחר שהבנייה תסתיים, ה-Space יהיה זמין ב-URL:
110
+ `https://huggingface.co/spaces/YOUR_USERNAME/YOUR_SPACE_NAME`
111
+
112
+ ## פתרון בעיות
113
+
114
+ ### Space לא עולה
115
+
116
+ 1. בדוק את ה-**Logs** tab - שם תראה שגיאות
117
+ 2. ודא ש-`app.py` קיים ופועל
118
+ 3. ודא ש-`requirements.txt` מעודכן
119
+
120
+ ### שגיאת API Key
121
+
122
+ 1. ודא שה-API key מוגדר ב-**Repository secrets**
123
+ 2. ודא שהשם של ה-secret תואם (GEMINI_API_KEY או OPENAI_API_KEY)
124
+
125
+ ### שגיאת "No feedback data available"
126
+
127
+ 1. ודא ש-`Feedback.csv` קיים ב-repository
128
+ 2. ודא שהקובץ נמצא בתיקייה הראשית
129
+ 3. בדוק את ה-Logs לפרטים נוספים
130
+
131
+ ### Port issues
132
+
133
+ - HF Spaces משתמש ב-port 7860 כברירת מחדל
134
+ - `app.py` כבר מוגדר להשתמש ב-port 7860
135
+ - אם יש בעיה, בדוק את ה-Logs
136
+
137
+ ## עדכונים
138
+
139
+ כדי לעדכן את ה-Space:
140
+
141
+ 1. בצע שינויים בקוד המקומי
142
+ 2. commit ו-push ל-HF Space:
143
+ ```bash
144
+ git add .
145
+ git commit -m "Update code"
146
+ git push huggingface main
147
+ ```
148
+ 3. HF Spaces יבנה מחדש אוטומטית
149
+
150
+ ## הערות חשובות
151
+
152
+ 1. **API Keys**: לעולם אל תכלול API keys בקוד! השתמש ב-Repository secrets
153
+ 2. **נתונים**: אם `Feedback.csv` מכיל מידע רגיש, שקול להשתמש ב-Private Space
154
+ 3. **גודל**: HF Spaces מגביל את גודל ה-repository (10GB ל-Free tier)
155
+ 4. **זמן ריצה**: HF Spaces יכול לעצור Spaces לא פעילים אחרי זמן מסוים
156
+
157
+ ## קישורים שימושיים
158
+
159
+ - [Hugging Face Spaces Documentation](https://huggingface.co/docs/hub/spaces)
160
+ - [Docker Spaces Guide](https://huggingface.co/docs/hub/spaces-sdks-docker)
161
+ - [Environment Variables in Spaces](https://huggingface.co/docs/hub/spaces-sdks-docker#environment-variables)
162
+
README.md CHANGED
@@ -1,3 +1,13 @@
 
 
 
 
 
 
 
 
 
 
1
  # Feedback Analysis Agent
2
 
3
  מערכת ניתוח משובי משתמשים מבוססת SQL ו-LLM.
@@ -179,8 +189,8 @@ schema_info = f"""
179
 
180
  ## קישורים
181
 
182
- - GitHub: [לעדכן]
183
- - קורות חיים: [לעדכן]
184
 
185
  ## רישיון
186
 
 
1
+ ---
2
+ title: Feedback Analysis Agent
3
+ emoji: 📊
4
+ colorFrom: blue
5
+ colorTo: cyan
6
+ sdk: docker
7
+ pinned: false
8
+ license: mit
9
+ ---
10
+
11
  # Feedback Analysis Agent
12
 
13
  מערכת ניתוח משובי משתמשים מבוססת SQL ו-LLM.
 
189
 
190
  ## קישורים
191
 
192
+ - **GitHub**: [https://github.com/galbendavids/Feedback_Analysis_RAG_Agent_runpod](https://github.com/galbendavids/Feedback_Analysis_RAG_Agent_runpod)
193
+ - **קורות חיים**: [https://github.com/galbendavids/Feedback_Analysis_RAG_Agent_runpod/blob/main/Gal%20Shlomo%20Ben%20David%20Ohayone_e-1.pdf](https://github.com/galbendavids/Feedback_Analysis_RAG_Agent_runpod/blob/main/Gal%20Shlomo%20Ben%20David%20Ohayone_e-1.pdf)
194
 
195
  ## רישיון
196
 
app.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Entry point for Hugging Face Spaces deployment.
3
+
4
+ This file is required by Hugging Face Spaces to run the FastAPI application.
5
+ It's a simple wrapper that imports and runs the FastAPI app from app.api.
6
+
7
+ Hugging Face Spaces will automatically detect this file and run it.
8
+ The app will be available on port 7860 (HF Spaces default).
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import os
14
+ import uvicorn
15
+
16
+ # Import the FastAPI app from the app package
17
+ from app.api import app
18
+
19
+ # Hugging Face Spaces will call this file directly
20
+ # The app is already defined in app.api, so we just need to run it
21
+ if __name__ == "__main__":
22
+ # Get port from environment variable (HF Spaces sets this) or default to 7860
23
+ port = int(os.environ.get("PORT", 7860))
24
+ # Run on all interfaces (0.0.0.0) - required for HF Spaces
25
+ uvicorn.run(app, host="0.0.0.0", port=port)
26
+
app/sql_service.py CHANGED
@@ -382,6 +382,9 @@ class SQLFeedbackService:
382
 
383
  הערך את התשובה לפי הקריטריונים הבאים (0-100):
384
  1. האם התשובה עונה ישירות על השאלה? (0-30 נקודות)
 
 
 
385
  2. האם התשובה מבוססת על הנתונים? (0-25 נקודות)
386
  3. האם התשובה מפורטת ומקיפה? (0-20 נקודות)
387
  4. האם התשובה ברורה ומובנת? (0-15 נקודות)
@@ -492,6 +495,12 @@ class SQLFeedbackService:
492
 
493
  המשימה שלך: כתוב תשובה מסכמת, ברורה ובשפה חופשית שמבוססת על התוצאות.
494
 
 
 
 
 
 
 
495
  דרישות:
496
  1. תשובה מפורטת ומקיפה (5-7 פסקאות, 400-600 מילים)
497
  2. תשובה ברורה ומסודרת - לא גיבוב של מילים
@@ -504,10 +513,11 @@ class SQLFeedbackService:
504
  מבנה התשובה:
505
  1. פתיחה - סיכום מנהלים קצר (2-3 משפטים)
506
  2. ניתוח מפורט של הממצאים (3-4 פסקאות)
 
507
  3. תובנות עסקיות והמלצות (2-3 פסקאות)
508
  4. סיכום (1-2 משפטים)
509
 
510
- אם יש שגיאות בשאילתות, ציין זאת בתשובה."""
511
 
512
  # Try Gemini first
513
  if settings.gemini_api_key and genai is not None:
@@ -545,6 +555,12 @@ class SQLFeedbackService:
545
  כתוב תשובה משופרת שמתמקדת יותר בשאלה המקורית, מבוססת יותר על הנתונים, ומפורטת יותר.
546
  התשובה חייבת לענות ישירות על השאלה: {query}
547
 
 
 
 
 
 
 
548
  דרישות:
549
  1. תשובה מפורטת ומקיפה (5-7 פסקאות, 400-600 מילים)
550
  2. תשובה שמתמקדת ישירות בשאלה שנשאלה
@@ -601,7 +617,13 @@ class SQLFeedbackService:
601
  {results_text}
602
 
603
  כתוב תשובה משופרת שמתמקדת יותר בשאלה המקורית, מבוססת יותר על הנתונים, ומפורטת יותר.
604
- התשובה חייבת לענות ישירות על השאלה: {query}"""
 
 
 
 
 
 
605
 
606
  try:
607
  response = client.chat.completions.create(
@@ -624,8 +646,24 @@ class SQLFeedbackService:
624
  except Exception as e:
625
  print(f"OpenAI error in synthesis: {e}", flush=True)
626
 
627
- # Fallback: return basic summary
628
- return f"בוצעו {len(sql_queries)} שאילתות. {len([r for r in query_results if not r.error])} הצליחו."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
629
 
630
  def _generate_visualizations(self, query_results: List[SQLQueryResult]) -> Optional[List[Dict[str, Any]]]:
631
  """
 
382
 
383
  הערך את התשובה לפי הקריטריונים הבאים (0-100):
384
  1. האם התשובה עונה ישירות על השאלה? (0-30 נקודות)
385
+ - אם השאלה מבקשת סיווג/חלוקה לפי שירותים (ServiceName) - האם התשובה כוללת ניתוח נפרד לכל שירות?
386
+ - אם השאלה מבקשת סיווג/חלוקה לפי דירוגים (Level) - האם התשובה כוללת ניתוח נפרד לכל דירוג?
387
+ - אם השאלה מבקשת סיווג/חלוקה לפי תאריכים - האם התשובה כוללת ניתוח נפרד לפי תקופות?
388
  2. האם התשובה מבוססת על הנתונים? (0-25 נקודות)
389
  3. האם התשובה מפורטת ומקיפה? (0-20 נקודות)
390
  4. האם התשובה ברורה ומובנת? (0-15 נקודות)
 
495
 
496
  המשימה שלך: כתוב תשובה מסכמת, ברורה ובשפה חופשית שמבוססת על התוצאות.
497
 
498
+ חשוב מאוד - קריטי:
499
+ - אם השאלה מבקשת סיווג/חלוקה לפי שירותים (ServiceName) - חובה לכלול ניתוח נפרד ומפורט לכל שירות!
500
+ - אם השאלה מבקשת סיווג/חלוקה לפי דירוגים (Level) - חובה לכלול ניתוח נפרד ומפורט לכל דירוג!
501
+ - אם השאלה מבקשת סיווג/חלוקה לפי תאריכים - חובה לכלול ניתוח נפרד לפי תקופות!
502
+ - תמיד תן תשובה מפורטת ומשמעותית - לא רק הודעה ששאילתות בוצעו!
503
+
504
  דרישות:
505
  1. תשובה מפורטת ומקיפה (5-7 פסקאות, 400-600 מילים)
506
  2. תשובה ברורה ומסודרת - לא גיבוב של מילים
 
513
  מבנה התשובה:
514
  1. פתיחה - סיכום מנהלים קצר (2-3 משפטים)
515
  2. ניתוח מפורט של הממצאים (3-4 פסקאות)
516
+ - אם נדרש סיווג לפי שירותים/דירוגים/תאריכים - כלול כאן ניתוח נפרד לכל קטגוריה
517
  3. תובנות עסקיות והמלצות (2-3 פסקאות)
518
  4. סיכום (1-2 משפטים)
519
 
520
+ אם יש שגיאות בשאילתות, ציין זאת בתשובה, אבל עדיין תן תשובה מפורטת על בסיס התוצאות שהתקבלו."""
521
 
522
  # Try Gemini first
523
  if settings.gemini_api_key and genai is not None:
 
555
  כתוב תשובה משופרת שמתמקדת יותר בשאלה המקורית, מבוססת יותר על הנתונים, ומפורטת יותר.
556
  התשובה חייבת לענות ישירות על השאלה: {query}
557
 
558
+ חשוב מאוד - קריטי:
559
+ - אם השאלה מבקשת סיווג/חלוקה לפי שירותים (ServiceName) - חובה לכלול ניתוח נפרד ומפורט לכל שירות!
560
+ - אם השאלה מבקשת סיווג/חלוקה לפי דירוגים (Level) - חובה לכלול ניתוח נפרד ומפורט לכל דירוג!
561
+ - אם השאלה מבקשת סיווג/חלוקה לפי תאריכים - חובה לכלול ניתוח נפרד לפי תקופות!
562
+ - תמיד תן תשובה מפורטת ומשמעותית - לא רק הודעה ששאילתות בוצעו!
563
+
564
  דרישות:
565
  1. תשובה מפורטת ומקיפה (5-7 פסקאות, 400-600 מילים)
566
  2. תשובה שמתמקדת ישירות בשאלה שנשאלה
 
617
  {results_text}
618
 
619
  כתוב תשובה משופרת שמתמקדת יותר בשאלה המקורית, מבוססת יותר על הנתונים, ומפורטת יותר.
620
+ התשובה חייבת לענות ישירות על השאלה: {query}
621
+
622
+ חשוב מאוד - קריטי:
623
+ - אם השאלה מבקשת סיווג/חלוקה לפי שירותים (ServiceName) - חובה לכלול ניתוח נפרד ומפורט לכל שירות!
624
+ - אם השאלה מבקשת סיווג/חלוקה לפי דירוגים (Level) - חובה לכלול ניתוח נפרד ומפורט לכל דירוג!
625
+ - אם השאלה מבקשת סיווג/חלוקה לפי תאריכים - חובה לכלול ניתוח נפרד לפי תקופות!
626
+ - תמיד תן תשובה מפורטת ומשמעותית - לא רק הודעה ששאילתות בוצעו!"""
627
 
628
  try:
629
  response = client.chat.completions.create(
 
646
  except Exception as e:
647
  print(f"OpenAI error in synthesis: {e}", flush=True)
648
 
649
+ # Fallback: generate a detailed answer from query results even if LLM failed
650
+ # This ensures we always return a meaningful answer, not just a status message
651
+ successful_results = [r for r in query_results if not r.error and len(r.result) > 0]
652
+ if successful_results:
653
+ fallback_text = f"בוצעו {len(sql_queries)} שאילתות, {len(successful_results)} הצליחו.\n\n"
654
+ fallback_text += "סיכום התוצאות:\n\n"
655
+ for i, qr in enumerate(successful_results, 1):
656
+ fallback_text += f"שאילתה {i}: {qr.query}\n"
657
+ fallback_text += f"מספר שורות: {len(qr.result)}\n"
658
+ # Include first few rows as summary
659
+ if len(qr.result) > 0:
660
+ fallback_text += "תוצאות (דוגמאות):\n"
661
+ fallback_text += qr.result.head(5).to_string(index=False)
662
+ fallback_text += "\n\n"
663
+ return fallback_text
664
+ else:
665
+ # If no successful results, still provide a helpful message
666
+ return f"בוצעו {len(sql_queries)} שאילתות, אך לא התקבלו תוצאות. ייתכן שהנתונים לא מכילים מידע התואם לשאלה."
667
 
668
  def _generate_visualizations(self, query_results: List[SQLQueryResult]) -> Optional[List[Dict[str, Any]]]:
669
  """
app/static/app.js CHANGED
@@ -236,7 +236,7 @@ function showVisualizations(visualizations) {
236
 
237
  const canvasDiv = document.createElement('div');
238
  canvasDiv.style.position = 'relative';
239
- canvasDiv.style.height = '350px';
240
  canvasDiv.style.background = '#ffffff';
241
  canvasDiv.style.borderRadius = '12px';
242
  canvasDiv.style.padding = '16px';
 
236
 
237
  const canvasDiv = document.createElement('div');
238
  canvasDiv.style.position = 'relative';
239
+ canvasDiv.style.height = '450px';
240
  canvasDiv.style.background = '#ffffff';
241
  canvasDiv.style.borderRadius = '12px';
242
  canvasDiv.style.padding = '16px';
app/static/index.html CHANGED
@@ -11,7 +11,7 @@
11
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Noto Sans Hebrew', 'Arial Hebrew', sans-serif;
12
  margin: 0;
13
  direction: rtl;
14
- background: linear-gradient(135deg, #1976d2 0%, #1565c0 50%, #0d47a1 100%);
15
  min-height: 100vh;
16
  color: #0b2545;
17
  padding-bottom: 40px;
 
11
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Noto Sans Hebrew', 'Arial Hebrew', sans-serif;
12
  margin: 0;
13
  direction: rtl;
14
+ background: linear-gradient(135deg, #03a9f4 0%, #0288d1 50%, #0277bd 100%);
15
  min-height: 100vh;
16
  color: #0b2545;
17
  padding-bottom: 40px;