feat: first IA page
This commit is contained in:
@@ -15,6 +15,7 @@ from .routes import (
|
||||
analytics_router,
|
||||
dashboard_router,
|
||||
revenus_router,
|
||||
ia_router,
|
||||
)
|
||||
|
||||
app = FastAPI(
|
||||
@@ -41,6 +42,7 @@ app.include_router(tags_router)
|
||||
app.include_router(analytics_router)
|
||||
app.include_router(dashboard_router)
|
||||
app.include_router(revenus_router)
|
||||
app.include_router(ia_router)
|
||||
|
||||
|
||||
# Health check endpoints (keep in main app)
|
||||
|
||||
@@ -6,6 +6,7 @@ from .tags import router as tags_router
|
||||
from .analytics import router as analytics_router
|
||||
from .dashboard import router as dashboard_router
|
||||
from .revenus import router as revenus_router
|
||||
from .ia import router as ia_router
|
||||
|
||||
__all__ = [
|
||||
"extraction_router",
|
||||
@@ -14,4 +15,5 @@ __all__ = [
|
||||
"analytics_router",
|
||||
"dashboard_router",
|
||||
"revenus_router",
|
||||
"ia_router",
|
||||
]
|
||||
|
||||
88
src/plesna_gerance/api/routes/ia.py
Normal file
88
src/plesna_gerance/api/routes/ia.py
Normal file
@@ -0,0 +1,88 @@
|
||||
"""Routes IA — Requêtes en langage naturel via Ollama."""
|
||||
|
||||
import logging
|
||||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from pydantic import BaseModel
|
||||
|
||||
import httpx
|
||||
|
||||
from ...services.ollama_service import ask_ollama, check_ollama_health
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
router = APIRouter(prefix="/api/ia", tags=["ia"])
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Request / Response models
|
||||
# ============================================================
|
||||
|
||||
|
||||
class AskRequest(BaseModel):
|
||||
question: str
|
||||
chart_type: str = "auto"
|
||||
|
||||
|
||||
class AskResponse(BaseModel):
|
||||
answer: str | None = None
|
||||
data: dict | None = None
|
||||
chart_config: dict | None = None
|
||||
sql_query: str | None = None
|
||||
error: str | None = None
|
||||
|
||||
|
||||
class HealthResponse(BaseModel):
|
||||
ollama_available: bool
|
||||
model: str
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Endpoints
|
||||
# ============================================================
|
||||
|
||||
|
||||
@router.post("/ask", response_model=AskResponse)
|
||||
async def ask_ia(request: AskRequest) -> AskResponse:
|
||||
"""Pose une question en langage naturel et obtient une réponse via Ollama.
|
||||
|
||||
Le LLM génère les requêtes SQL nécessaires, exécute les outils,
|
||||
et retourne une réponse avec données et graphique optionnel.
|
||||
"""
|
||||
if not request.question.strip():
|
||||
raise HTTPException(status_code=400, detail="La question ne peut pas être vide.")
|
||||
|
||||
try:
|
||||
result = await ask_ollama(request.question, request.chart_type)
|
||||
return AskResponse(
|
||||
answer=result.get("answer"),
|
||||
data=result.get("data"),
|
||||
chart_config=result.get("chart_config"),
|
||||
sql_query=result.get("sql_query"),
|
||||
)
|
||||
except httpx.TimeoutException:
|
||||
raise HTTPException(
|
||||
status_code=504,
|
||||
detail="Ollama n'a pas répondu dans le délai imparti.",
|
||||
)
|
||||
except httpx.ConnectError:
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail="Impossible de se connecter à Ollama. Vérifiez qu'il est lancé.",
|
||||
)
|
||||
except httpx.HTTPStatusError as e:
|
||||
logger.error(f"Ollama HTTP error: {e}")
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail=f"Erreur Ollama : {e.response.status_code}",
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"IA ask error: {e}", exc_info=True)
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@router.get("/health", response_model=HealthResponse)
|
||||
async def ia_health() -> HealthResponse:
|
||||
"""Vérifie la disponibilité d'Ollama et du modèle configuré."""
|
||||
result = await check_ollama_health()
|
||||
return HealthResponse(**result)
|
||||
Reference in New Issue
Block a user