|
|
|
|
|
|
|
|
|
|
|
import os |
|
|
from contextlib import asynccontextmanager |
|
|
|
|
|
from fastapi import FastAPI |
|
|
from fastapi.middleware.cors import CORSMiddleware |
|
|
from fastapi.routing import APIRoute |
|
|
from fastapi.staticfiles import StaticFiles |
|
|
|
|
|
from src.utils.logger import logger, setup_logging |
|
|
|
|
|
|
|
|
setup_logging() |
|
|
|
|
|
|
|
|
try: |
|
|
from dotenv import load_dotenv |
|
|
load_dotenv() |
|
|
logger(tag="env").info("Environment variables loaded from .env file") |
|
|
except ImportError: |
|
|
logger(tag="env").warning("python-dotenv not available, using system environment variables") |
|
|
except Exception as e: |
|
|
logger(tag="env").warning(f"Error loading .env file: {e}") |
|
|
|
|
|
|
|
|
from src.api.routes import account as account_route |
|
|
from src.api.routes import audio as audio_route |
|
|
from src.api.routes import emr as emr_route |
|
|
from src.api.routes import migration as migration_route |
|
|
from src.api.routes import patient as patients_route |
|
|
from src.api.routes import session as session_route |
|
|
from src.api.routes import static as static_route |
|
|
from src.api.routes import summarise as summarise_route |
|
|
from src.api.routes import system as system_route |
|
|
from src.core.state import AppState, get_state |
|
|
from src.data.repositories import account as account_repo |
|
|
from src.data.repositories import emr as emr_repo |
|
|
from src.data.repositories import information as information_repo |
|
|
from src.data.repositories import medical_memory as medical_memory_repo |
|
|
from src.data.repositories import medical_record as medical_record_repo |
|
|
from src.data.repositories import patient as patient_repo |
|
|
from src.data.repositories import session as session_repo |
|
|
from src.services import local_llm_service |
|
|
|
|
|
|
|
|
def startup_event(state: AppState): |
|
|
"""Initialize application on startup""" |
|
|
logger(tag="startup").info("Starting Medical AI Assistant...") |
|
|
|
|
|
|
|
|
try: |
|
|
import psutil |
|
|
ram = psutil.virtual_memory() |
|
|
cpu = psutil.cpu_percent(interval=1) |
|
|
logger(tag="startup").info(f"System Resources – RAM: {ram.percent}%, CPU: {cpu}%") |
|
|
|
|
|
if ram.percent > 85: |
|
|
logger(tag="startup").warning("High RAM usage detected!") |
|
|
if cpu > 90: |
|
|
logger(tag="startup").warning("High CPU usage detected!") |
|
|
except ImportError: |
|
|
logger(tag="startup").info("psutil not available, skipping system resource check") |
|
|
|
|
|
|
|
|
gemini_keys = len([k for k in state.gemini_rotator.keys if k]) |
|
|
if gemini_keys == 0: |
|
|
logger(tag="startup").warning("No Gemini API keys found! Set GEMINI_API_1, GEMINI_API_2, etc. environment variables.") |
|
|
else: |
|
|
logger(tag="startup").info(f"{gemini_keys} Gemini API keys available") |
|
|
|
|
|
nvidia_keys = len([k for k in state.nvidia_rotator.keys if k]) |
|
|
if nvidia_keys == 0: |
|
|
logger(tag="startup").warning("No NVIDIA API keys found! Set NVIDIA_API_1, NVIDIA_API_2, etc. environment variables.") |
|
|
else: |
|
|
logger(tag="startup").info(f"{nvidia_keys} NVIDIA API keys available") |
|
|
|
|
|
|
|
|
if state.embedding_client.is_available(): |
|
|
logger(tag="startup").info("Embedding model loaded successfully") |
|
|
else: |
|
|
logger(tag="startup").info("Using fallback embedding mode") |
|
|
|
|
|
logger(tag="startup").info("Medical AI Assistant startup complete") |
|
|
|
|
|
account_repo.init() |
|
|
patient_repo.init() |
|
|
session_repo.init() |
|
|
medical_memory_repo.init() |
|
|
medical_record_repo.init() |
|
|
emr_repo.init() |
|
|
information_repo.init() |
|
|
|
|
|
|
|
|
try: |
|
|
from src.data.migration import run_database_migration |
|
|
logger(tag="startup").info("Running database migration...") |
|
|
migration_result = run_database_migration() |
|
|
if migration_result['success']: |
|
|
logger(tag="startup").info(f"Database migration completed: {migration_result['total_fixed']} records fixed") |
|
|
else: |
|
|
logger(tag="startup").warning(f"Database migration failed: {migration_result.get('error', 'Unknown error')}") |
|
|
except Exception as e: |
|
|
logger(tag="startup").warning(f"Database migration error: {e}") |
|
|
|
|
|
if os.getenv("USE_LOCAL_MODEL", "False") == "True": |
|
|
local_llm_service.load_model() |
|
|
|
|
|
def shutdown_event(): |
|
|
"""Cleanup on shutdown""" |
|
|
logger(tag="shutdown").info("Shutting down Medical AI Assistant...") |
|
|
|
|
|
@asynccontextmanager |
|
|
async def lifespan(app: FastAPI): |
|
|
|
|
|
state = get_state() |
|
|
state.initialize() |
|
|
|
|
|
|
|
|
startup_event(state) |
|
|
yield |
|
|
|
|
|
shutdown_event() |
|
|
|
|
|
|
|
|
app = FastAPI( |
|
|
lifespan=lifespan, |
|
|
title="Medical AI Assistant", |
|
|
description="AI-powered medical chatbot with memory and context awareness", |
|
|
version="1.0.0" |
|
|
) |
|
|
|
|
|
|
|
|
app.add_middleware( |
|
|
CORSMiddleware, |
|
|
allow_origins=["*"], |
|
|
allow_credentials=True, |
|
|
allow_methods=["*"], |
|
|
allow_headers=["*"], |
|
|
) |
|
|
|
|
|
|
|
|
app.mount("/static", StaticFiles(directory="static"), name="static") |
|
|
|
|
|
|
|
|
app.include_router(static_route.router) |
|
|
app.include_router(session_route.router) |
|
|
app.include_router(patients_route.router) |
|
|
app.include_router(account_route.router) |
|
|
app.include_router(summarise_route.router) |
|
|
app.include_router(system_route.router) |
|
|
app.include_router(audio_route.router) |
|
|
app.include_router(emr_route.router) |
|
|
app.include_router(migration_route.router) |
|
|
|
|
|
@app.get("/api/info") |
|
|
async def get_api_info(): |
|
|
"""Get API information and capabilities, lists all paths available in the api.""" |
|
|
return { |
|
|
"name": "Medical Diagnosis System", |
|
|
"version": "1.0.0", |
|
|
"description": "AI-powered medical chatbot with memory and context awareness", |
|
|
"features": [ |
|
|
"Multi-user support with profiles", |
|
|
"Chat session management", |
|
|
"Medical context memory", |
|
|
"API key rotation", |
|
|
"Embedding-based similarity search", |
|
|
"Medical knowledge base integration" |
|
|
], |
|
|
"endpoints": [route.path for route in app.routes if isinstance(route, APIRoute)] |
|
|
} |
|
|
|