feedback-analysis-agent / ARCHITECTURE.md
galbendavids's picture
עדכון: הסרת RAG, הוספת ארכיטקטורה מפורטת, תיקון לינקים, שינוי שם פרויקט ל-SQL-based
f073efc
# ארכיטקטורת המערכת - Feedback Analysis SQL-Based Agent
## סקירה כללית
המערכת היא מערכת ניתוח משובי משתמשים מבוססת SQL ו-LLM. המערכת מקבלת שאלות בשפה טבעית, יוצרת שאילתות SQL, מבצעת אותן על הנתונים, ומחזירה תשובות מפורטות.
## זרימת הנתונים - מהפרונט לאחור
### 1. Frontend (1_frontend/)
#### `index.html`
**תפקיד**: ממשק המשתמש הראשי
**סיבה לקיום**: מספק ממשק ווב אינטראקטיבי למשתמש
**תפקידים**:
- הצגת שדה קלט לשאלות
- הצגת תשובות, שאילתות SQL, תוצאות, וגרפים
- ניהול היסטוריית שאלות
- אנימציית loading
#### `app.js`
**תפקיד**: לוגיקת Frontend
**סיבה לקיום**: מטפל באינטראקציות המשתמש ותקשורת עם ה-Backend
**תפקידים**:
- שליחת שאלות ל-`/query-sql` endpoint
- הצגת תשובות וגרפים
- ניהול היסטוריה (טעינה ושחזור)
- עיבוד ויזואליזציות עם 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.html`
- `POST /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 ברירת מחדל
- הגדרת שמות עמודות
## זרימה מלאה - דוגמה
### שאילתת משתמש: "מה הדירוג הממוצע לפי שירות?"
1. **Frontend** (`app.js`):
```javascript
sendQuery() → POST /query-sql {query: "מה הדירוג הממוצע לפי שירות?"}
```
2. **Backend API** (`api.py`):
```python
@app.post("/query-sql")
def query_sql(request: QueryRequest):
result = sql_svc.analyze_query(request.query)
save_history(result) # שמירה להיסטוריה
return SQLQueryResponse(...)
```
3. **SQL Service** (`sql_service.py`):
```python
analyze_query("מה הדירוג הממוצע לפי שירות?")
```
4. **שלב 1 - יצירת SQL**:
```python
_generate_sql_queries(query)
→ LLM מקבל: schema_info + query
→ LLM מחזיר: ["SELECT ServiceName, AVG(Level) as avg_rating FROM Feedback_transformed GROUP BY ServiceName"]
```
5. **שלב 2 - ביצוע SQL**:
```python
_execute_sql_queries(["SELECT ServiceName, AVG(Level)..."])
→ טוען DataFrame ל-SQLite
→ מבצע שאילתה
→ מחזיר: DataFrame עם ServiceName ו-avg_rating
```
6. **שלב 3 - סינתזת תשובה**:
```python
_synthesize_answer(query, sql_queries, query_results)
→ LLM מקבל: query + SQL + results
→ LLM מחזיר: "הדירוג הממוצע לפי שירות: שירות X - 4.2, שירות Y - 3.8..."
→ (אופציונלי) _evaluate_answer_quality() + שיפור
```
7. **שלב 4 - יצירת ויזואליזציות**:
```python
_generate_visualizations(query_results)
→ מחזיר: [{type: "bar", x: "ServiceName", y: "avg_rating", ...}]
```
8. **חזרה ל-Frontend**:
```javascript
קבלת תשובה → הצגת summary → הצגת גרף → עדכון היסטוריה
```
## מבנה הנתונים
### AnalysisResult
```python
{
user_query: str,
sql_queries: List[str],
query_results: List[SQLQueryResult],
summary: str,
visualizations: Optional[List[Dict]]
}
```
### SQLQueryResult
```python
{
query: str,
result: pd.DataFrame,
error: Optional[str]
}
```
## LLM Models בשימוש
1. **יצירת SQL** (`_generate_sql_queries`):
- Model: Gemini 2.0 Flash / GPT-4o-mini
- Input: schema_info + user_query
- Output: JSON עם רשימת שאילתות SQL
2. **סינתזת תשובה** (`_synthesize_answer`):
- Model: Gemini 2.0 Flash / GPT-4o-mini
- Input: user_query + sql_queries + query_results
- Output: תשובה מפורטת בעברית
3. **הערכת איכות** (`_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 וסינתזת תשובות
```
## נקודות כניסה
1. **Frontend**: `1_frontend/index.html` - נקודת הכניסה למשתמש
2. **Backend**: `2_backend_llm/run.py` - מפעיל את FastAPI server
3. **API**: `2_backend_llm/app/api.py` - מגדיר את ה-endpoints