| """ |
| analysis.py — PsyPredict Text Analysis & Health Endpoints (FastAPI) |
| New endpoints: |
| POST /api/analyze/text — standalone DistilBERT text emotion + crisis scoring |
| GET /api/health — system health check (Ollama, DistilBERT status) |
| """ |
| from __future__ import annotations |
|
|
| import logging |
|
|
| from fastapi import APIRouter |
|
|
| from app.schemas import ( |
| HealthResponse, |
| TextAnalysisRequest, |
| TextAnalysisResponse, |
| ) |
| from app.services.crisis_engine import crisis_engine |
| from app.services.ollama_engine import ollama_engine |
| from app.services.text_emotion_engine import text_emotion_engine |
| from app.config import get_settings |
|
|
| logger = logging.getLogger(__name__) |
|
|
| router = APIRouter() |
|
|
| settings = get_settings() |
|
|
|
|
| |
| |
| |
|
|
| @router.post("/analyze/text", response_model=TextAnalysisResponse) |
| async def analyze_text(req: TextAnalysisRequest): |
| """ |
| Standalone text emotion analysis pipeline (no LLM, no history needed). |
| Returns multi-label emotion scores + crisis risk score. |
| Useful for lightweight pre-screening before full chat inference. |
| """ |
| |
| labels = await text_emotion_engine.classify(req.text) |
| dominant = labels[0].label if labels else "neutral" |
|
|
| |
| crisis_score, crisis_triggered = await crisis_engine.evaluate(req.text) |
|
|
| return TextAnalysisResponse( |
| emotions=labels, |
| dominant=dominant, |
| crisis_risk=round(float(crisis_score), 4), |
| crisis_triggered=crisis_triggered, |
| ) |
|
|
|
|
| |
| |
| |
|
|
| @router.get("/health", response_model=HealthResponse) |
| async def health(): |
| """ |
| System health check. |
| Returns status of Ollama (reachable?), model name, DistilBERT load status. |
| """ |
| ollama_ok = await ollama_engine.is_reachable() |
| distilbert_ok = text_emotion_engine.is_loaded |
|
|
| overall = "ok" if (ollama_ok and distilbert_ok) else "degraded" |
|
|
| if not ollama_ok: |
| logger.warning("Health check: Ollama unreachable at %s", settings.OLLAMA_BASE_URL) |
| if not distilbert_ok: |
| logger.warning("Health check: DistilBERT not loaded. Error: %s", text_emotion_engine.load_error) |
|
|
| return HealthResponse( |
| status=overall, |
| ollama_reachable=ollama_ok, |
| ollama_model=settings.OLLAMA_MODEL, |
| distilbert_loaded=distilbert_ok, |
| ) |
|
|