Download src/triage_llm/api/app.py from perachon/p14-space: direct link, hf CLI and curl.
- Browser
- Download file 4.66 kB
-
https://huggingface.co/spaces/perachon/p14-space/resolve/main/src/triage_llm/api/app.py
- Command line
-
hf download hf://spaces/perachon/p14-space/src/triage_llm/api/app.py
-
curl -L -o app.py https://huggingface.co/spaces/perachon/p14-space/resolve/main/src/triage_llm/api/app.py
4.66 kB
| from __future__ import annotations | |
| from fastapi import FastAPI, HTTPException | |
| from triage_llm.api.audit import AuditStore | |
| from triage_llm.api.model import make_backend_from_env | |
| from triage_llm.eval.safety import detect_red_flags | |
| from triage_llm.schemas import TriageDecision, TriageRequest, TriageResponse | |
| app = FastAPI(title="CHSA - Agent IA Triage (POC)") | |
| audit = AuditStore() | |
| backend = make_backend_from_env() | |
| def _rule_based_decision(message: str, lang: str) -> tuple[TriageDecision | None, list[str]]: | |
| red_flags = detect_red_flags(message) | |
| if red_flags: | |
| if lang == "fr": | |
| decision = TriageDecision( | |
| priority="urgence_maximale", | |
| explanation=( | |
| "Des signes potentiellement graves ont été détectés dans votre message. " | |
| "Par prudence, une évaluation médicale urgente est recommandée." | |
| ), | |
| recommended_next_steps=[ | |
| ( | |
| "Appelez immédiatement les services d'urgence (15/112) " | |
| "si vous êtes en danger immédiat." | |
| ), | |
| "Ne conduisez pas vous-même si vous vous sentez mal.", | |
| ], | |
| red_flags=red_flags, | |
| ) | |
| else: | |
| decision = TriageDecision( | |
| priority="urgence_maximale", | |
| explanation=( | |
| "Potential red-flag symptoms were detected. For safety, " | |
| "urgent medical assessment is recommended." | |
| ), | |
| recommended_next_steps=[ | |
| "Call emergency services immediately if this is an emergency.", | |
| "Do not drive yourself if you feel unwell.", | |
| ], | |
| red_flags=red_flags, | |
| ) | |
| return decision, red_flags | |
| return None, [] | |
| def health() -> dict: | |
| info = backend.info() | |
| return {"status": "ok", "backend": info.name, "details": info.details} | |
| def triage(req: TriageRequest) -> TriageResponse: | |
| decision, red_flags = _rule_based_decision(req.patient_message, req.lang) | |
| follow_up_questions: list[str] | |
| if decision is None: | |
| # Keep the API contract stable: we use model text as explanation. | |
| raw = backend.generate(req.patient_message) | |
| decision = TriageDecision( | |
| priority="urgence_moderee", | |
| explanation=raw[:400], | |
| recommended_next_steps=( | |
| [ | |
| "Si aggravation ou malaise important, contactez les urgences.", | |
| "Sinon, consultez un professionnel de santé rapidement.", | |
| ] | |
| if req.lang == "fr" | |
| else [ | |
| "If symptoms worsen or you feel very unwell, seek emergency care.", | |
| "Otherwise, contact a clinician soon.", | |
| ] | |
| ), | |
| red_flags=red_flags, | |
| ) | |
| follow_up_questions = ( | |
| [ | |
| "Quel âge avez-vous ?", | |
| "Depuis quand les symptômes ont-ils commencé ?", | |
| "Avez-vous de la fièvre, des vomissements, ou une douleur thoracique ?", | |
| ] | |
| if req.lang == "fr" | |
| else [ | |
| "What is your age?", | |
| "When did symptoms start?", | |
| "Do you have fever, vomiting, or chest pain?", | |
| ] | |
| ) | |
| else: | |
| follow_up_questions = ( | |
| [ | |
| "Où êtes-vous actuellement (domicile, rue, seul/avec quelqu'un) ?", | |
| "Pouvez-vous parler en phrases complètes ?", | |
| "Avez-vous des antécédents médicaux importants (cœur, poumons) ?", | |
| ] | |
| if req.lang == "fr" | |
| else [ | |
| "Where are you right now (home, outside, alone/with someone)?", | |
| "Can you speak in full sentences?", | |
| "Any major medical history (heart/lungs)?", | |
| ] | |
| ) | |
| response = TriageResponse( | |
| interaction_id="", | |
| decision=decision, | |
| follow_up_questions=follow_up_questions, | |
| model_info=backend.info().details, | |
| ) | |
| interaction_id = audit.save(req.model_dump(mode="json"), response.model_dump(mode="json")) | |
| response.interaction_id = interaction_id | |
| return response | |
| def get_audit(interaction_id: str) -> dict: | |
| row = audit.get(interaction_id) | |
| if row is None: | |
| raise HTTPException(status_code=404, detail="Interaction not found") | |
| return row | |