mindnet/app/services/feedback_service.py
2025-12-07 19:29:48 +01:00

80 lines
2.4 KiB
Python

"""
app/services/feedback_service.py
Service zum Loggen von Suchanfragen und Feedback (WP-04c).
Speichert Daten als JSONL für späteres Self-Tuning (WP-08).
"""
import json
import os
import time
from pathlib import Path
from typing import Dict, Any, List
from app.models.dto import QueryRequest, QueryResponse, FeedbackRequest
# Pfad für Logs (lokal auf dem Beelink/PC)
LOG_DIR = Path("data/logs")
SEARCH_LOG_FILE = LOG_DIR / "search_history.jsonl"
FEEDBACK_LOG_FILE = LOG_DIR / "feedback.jsonl"
def _ensure_log_dir():
if not LOG_DIR.exists():
os.makedirs(LOG_DIR, exist_ok=True)
def log_search(req: QueryRequest, res: QueryResponse):
"""
Speichert den "Snapshot" der Suche.
WICHTIG: Wir speichern die Scores (Breakdown), damit wir später wissen,
warum das System so entschieden hat.
"""
_ensure_log_dir()
# Wir reduzieren die Datenmenge etwas (z.B. keine vollen Texte)
hits_summary = []
for hit in res.results:
# Falls Explanation an war, speichern wir den Breakdown, sonst die Scores
breakdown = None
if hit.explanation and hit.explanation.breakdown:
breakdown = hit.explanation.breakdown.model_dump()
hits_summary.append({
"node_id": hit.node_id,
"note_id": hit.note_id,
"total_score": hit.total_score,
"breakdown": breakdown, # Wichtig für Training!
"rank_semantic": hit.semantic_score,
"rank_edge": hit.edge_bonus
})
entry = {
"timestamp": time.time(),
"query_id": res.query_id,
"query_text": req.query,
"mode": req.mode,
"top_k": req.top_k,
"hits": hits_summary
}
try:
with open(SEARCH_LOG_FILE, "a", encoding="utf-8") as f:
f.write(json.dumps(entry, ensure_ascii=False) + "\n")
except Exception as e:
print(f"ERROR logging search: {e}")
def log_feedback(fb: FeedbackRequest):
"""
Speichert das User-Feedback.
"""
_ensure_log_dir()
entry = {
"timestamp": time.time(),
"query_id": fb.query_id,
"node_id": fb.node_id,
"score": fb.score,
"comment": fb.comment
}
try:
with open(FEEDBACK_LOG_FILE, "a", encoding="utf-8") as f:
f.write(json.dumps(entry, ensure_ascii=False) + "\n")
except Exception as e:
print(f"ERROR logging feedback: {e}")