ארכיטקטורת המערכת - Feedback Analysis SQL-Based Agent
סקירה כללית
המערכת היא מערכת ניתוח משובי משתמשים מבוססת SQL ו-LLM. המערכת מקבלת שאלות בשפה טבעית, יוצרת שאילתות SQL, מבצעת אותן על הנתונים, ומחזירה תשובות מפורטות.
זרימת הנתונים - מהפרונט לאחור
1. Frontend (1_frontend/)
index.html
תפקיד: ממשק המשתמש הראשי סיבה לקיום: מספק ממשק ווב אינטראקטיבי למשתמש תפקידים:
- הצגת שדה קלט לשאלות
- הצגת תשובות, שאילתות SQL, תוצאות, וגרפים
- ניהול היסטוריית שאלות
- אנימציית loading
app.js
תפקיד: לוגיקת Frontend סיבה לקיום: מטפל באינטראקציות המשתמש ותקשורת עם ה-Backend תפקידים:
- שליחת שאלות ל-
/query-sqlendpoint - הצגת תשובות וגרפים
- ניהול היסטוריה (טעינה ושחזור)
- עיבוד ויזואליזציות עם Chart.js
זרימת נתונים:
משתמש מזין שאלה → sendQuery() → POST /query-sql → קבלת תשובה → הצגה
2. Backend API (2_backend_llm/app/api.py)
api.py
תפקיד: FastAPI endpoints - נקודת הכניסה של ה-Backend סיבה לקיום: מספק API RESTful לתקשורת בין Frontend ל-Backend תפקידים:
GET /- מחזיר אתindex.htmlPOST /query-sql- מקבל שאלה, מחזיר תשובה מפורטתGET /history- מחזיר היסטוריית שאלותPOST /health- בדיקת תקינות השרת
זרימת נתונים:
Frontend → POST /query-sql {query: "..."}
→ api.py:query_sql()
→ SQLFeedbackService.analyze_query()
→ SQLQueryResponse {summary, sql_queries, query_results, visualizations}
→ Frontend
מודלים/פונקציות קרואות:
SQLFeedbackService- השירות הראשי לניתוחsave_history()- שמירת היסטוריה לדיסקload_history()- טעינת היסטוריה מהדיסק
3. SQL Service (2_backend_llm/app/sql_service.py)
sql_service.py
תפקיד: הליבה של המערכת - ניתוח SQL מבוסס LLM סיבה לקיום: מטפל בכל הלוגיקה של יצירת שאילתות SQL, ביצוען, וסינתזת תשובות תפקידים:
analyze_query()- הפונקציה הראשית - מנהלת את כל התהליך_get_schema_info()- יוצר מידע מפורט על כל השדות בטבלה_generate_sql_queries()- משתמש ב-LLM ליצירת שאילתות SQL_execute_sql_queries()- מבצע שאילתות SQL על הנתונים_synthesize_answer()- משתמש ב-LLM ליצירת תשובה מפורטת_evaluate_answer_quality()- מעריך את איכות התשובה_generate_visualizations()- יוצר מפרטי ויזואליזציות
זרימת נתונים:
analyze_query(query)
↓
1. _generate_sql_queries(query)
→ LLM (Gemini/OpenAI) מקבל: schema_info + query
→ מחזיר: ["SELECT ...", "SELECT ..."]
↓
2. _execute_sql_queries(sql_queries)
→ טוען DataFrame ל-SQLite in-memory
→ מבצע כל שאילתה
→ מחזיר: [SQLQueryResult, ...]
↓
3. _synthesize_answer(query, sql_queries, query_results)
→ LLM (Gemini/OpenAI) מקבל: query + sql_queries + results
→ מחזיר: תשובה מפורטת בעברית
→ (אופציונלי) _evaluate_answer_quality() + שיפור אם נדרש
↓
4. _generate_visualizations(query_results)
→ מנתח את התוצאות
→ מחזיר: [visualization_spec, ...]
↓
AnalysisResult {user_query, sql_queries, query_results, summary, visualizations}
מודלים/פונקציות קרואות:
LLM (Gemini/OpenAI)- ליצירת שאילתות SQL וסינתזת תשובותpandas.DataFrame- לניהול הנתוניםsqlite3- לביצוע שאילתות SQL
4. Data Loader (2_backend_llm/app/data_loader.py)
data_loader.py
תפקיד: טעינת נתונים מ-CSV סיבה לקיום: מטפל בטעינת וניקוי הנתונים מהקובץ תפקידים:
load_feedback()- טוען CSV, בודק שדות נדרשים, מנקה נתונים
זרימת נתונים:
load_feedback()
→ קורא CSV מ-settings.csv_path
→ בודק שדות: ID, ServiceName, Level, Text
→ מסיר שורות עם Text ריק
→ מחזיר: pd.DataFrame
5. Config (2_backend_llm/app/config.py)
config.py
תפקיד: הגדרות מערכת סיבה לקיום: מרכז את כל ההגדרות (API keys, נתיבי קבצים) תפקידים:
- טעינת API keys מ-.env
- הגדרת נתיב CSV ברירת מחדל
- הגדרת שמות עמודות
זרימה מלאה - דוגמה
שאילתת משתמש: "מה הדירוג הממוצע לפי שירות?"
Frontend (
app.js):sendQuery() → POST /query-sql {query: "מה הדירוג הממוצע לפי שירות?"}Backend API (
api.py):@app.post("/query-sql") def query_sql(request: QueryRequest): result = sql_svc.analyze_query(request.query) save_history(result) # שמירה להיסטוריה return SQLQueryResponse(...)SQL Service (
sql_service.py):analyze_query("מה הדירוג הממוצע לפי שירות?")שלב 1 - יצירת SQL:
_generate_sql_queries(query) → LLM מקבל: schema_info + query → LLM מחזיר: ["SELECT ServiceName, AVG(Level) as avg_rating FROM Feedback_transformed GROUP BY ServiceName"]שלב 2 - ביצוע SQL:
_execute_sql_queries(["SELECT ServiceName, AVG(Level)..."]) → טוען DataFrame ל-SQLite → מבצע שאילתה → מחזיר: DataFrame עם ServiceName ו-avg_ratingשלב 3 - סינתזת תשובה:
_synthesize_answer(query, sql_queries, query_results) → LLM מקבל: query + SQL + results → LLM מחזיר: "הדירוג הממוצע לפי שירות: שירות X - 4.2, שירות Y - 3.8..." → (אופציונלי) _evaluate_answer_quality() + שיפורשלב 4 - יצירת ויזואליזציות:
_generate_visualizations(query_results) → מחזיר: [{type: "bar", x: "ServiceName", y: "avg_rating", ...}]חזרה ל-Frontend:
קבלת תשובה → הצגת summary → הצגת גרף → עדכון היסטוריה
מבנה הנתונים
AnalysisResult
{
user_query: str,
sql_queries: List[str],
query_results: List[SQLQueryResult],
summary: str,
visualizations: Optional[List[Dict]]
}
SQLQueryResult
{
query: str,
result: pd.DataFrame,
error: Optional[str]
}
LLM Models בשימוש
יצירת SQL (
_generate_sql_queries):- Model: Gemini 2.0 Flash / GPT-4o-mini
- Input: schema_info + user_query
- Output: JSON עם רשימת שאילתות SQL
סינתזת תשובה (
_synthesize_answer):- Model: Gemini 2.0 Flash / GPT-4o-mini
- Input: user_query + sql_queries + query_results
- Output: תשובה מפורטת בעברית
הערכת איכות (
_evaluate_answer_quality):- Model: Gemini 2.0 Flash / GPT-4o-mini
- Input: user_query + answer + context
- Output: score (0-100) + reasoning
Database Schema
טבלה: Feedback_transformed (SQLite in-memory)
שדות:
- ID (UUID)
- ServiceName (TEXT)
- Level (INTEGER 1-5)
- Text (TEXT)
- ReferenceNumber (INTEGER, nullable)
- RequestID (UUID, nullable)
- ProcessID (UUID, nullable)
- Year (INTEGER)
- Month (INTEGER 1-12)
- DayInMonth (INTEGER 1-31)
- DayOfWeek (TEXT: Monday-Sunday)
- Hour (INTEGER 0-23)
- DayOrNight (TEXT: 'יום'/'לילה')
תלויות בין מודולים
Frontend (app.js)
↓ HTTP POST
API (api.py)
↓
SQL Service (sql_service.py)
↓
├─→ Data Loader (data_loader.py) - טעינת נתונים
├─→ Config (config.py) - הגדרות
└─→ LLM (Gemini/OpenAI) - יצירת SQL וסינתזת תשובות
נקודות כניסה
- Frontend:
1_frontend/index.html- נקודת הכניסה למשתמש - Backend:
2_backend_llm/run.py- מפעיל את FastAPI server - API:
2_backend_llm/app/api.py- מגדיר את ה-endpoints