"""Routes API — Mode Apprentissage.""" from fastapi import APIRouter, Depends, HTTPException from pydantic import BaseModel from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, desc from typing import Literal from backend.database.db import get_db from backend.database.models import AIDecision, LearningFeedback router = APIRouter() _processor = None def _get_processor(): global _processor if not _processor: from backend.config.settings import get_settings from backend.ai.learning.feedback_processor import FeedbackProcessor _processor = FeedbackProcessor(get_settings()) return _processor class FeedbackIn(BaseModel): decision_id: int rating: Literal["good", "bad", "neutral"] better_action: dict | None = None comment: str | None = None @router.post("/feedback") async def submit_feedback(req: FeedbackIn, db: AsyncSession = Depends(get_db)): """Soumet un retour utilisateur sur une décision IA.""" proc = _get_processor() try: fb = await proc.record_feedback( db, decision_id=req.decision_id, rating=req.rating, better_action=req.better_action, comment=req.comment, ) return { "feedback_id": fb.id, "rating": fb.rating, "message": "Feedback enregistré — merci pour votre contribution!", } except ValueError as e: raise HTTPException(404, str(e)) @router.get("/stats") async def get_stats(db: AsyncSession = Depends(get_db)): """Statistiques globales du système d'apprentissage.""" return await _get_processor().get_stats(db) @router.get("/decisions") async def get_decisions( session_id: int | None = None, limit: int = 20, db: AsyncSession = Depends(get_db), ): """Historique des décisions IA avec leurs feedbacks.""" q = select(AIDecision).order_by(desc(AIDecision.created_at)).limit(limit) if session_id: q = q.where(AIDecision.session_id == session_id) result = await db.execute(q) decisions = result.scalars().all() return [ { "id": d.id, "session_id": d.session_id, "turn": d.turn, "phase": d.phase, "recommendation": d.recommendation, "reasoning": d.reasoning, "confidence": d.confidence, "outcome_rating": d.outcome_rating, "user_feedback": d.user_feedback, "model_used": d.model_used, "processing_ms": d.processing_ms, "created_at": d.created_at.isoformat(), } for d in decisions ] @router.post("/flush") async def flush_buffer(): """Force l'export du buffer d'apprentissage.""" await _get_processor().force_flush() return {"status": "flushed"}