Spaces:
Sleeping
Sleeping
File size: 6,295 Bytes
400e20f ae199cb 7659667 400e20f ae199cb 400e20f ae199cb 400e20f ae199cb 400e20f 7659667 400e20f 7659667 400e20f 7659667 400e20f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
from fastapi import FastAPI, UploadFile, File, Form, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel
import uuid
import os
from datetime import datetime
from config import config
from database import db
from ai_model import ai_models
import uvicorn
import json
app = FastAPI(
title="MobileDoc API",
description="Mobile Doctor Backend MVP",
version="1.0.0"
)
# ---------------- Middleware ----------------
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# ---------------- File Handling ----------------
os.makedirs(config.UPLOAD_DIR, exist_ok=True)
app.mount("/uploads", StaticFiles(directory=config.UPLOAD_DIR), name="uploads")
# ---------------- Pydantic Models ----------------
class UserProfile(BaseModel):
username: str
email: str
age: int
gender: str
allergies: str = ""
conditions: str = ""
class LoginRequest(BaseModel):
username: str
class SymptomsRequest(BaseModel):
user_id: str
symptoms: str
class AnalysisResponse(BaseModel):
success: bool
data: dict
message: str = ""
# ---------------- Routes ----------------
@app.get("/")
async def root():
return {"status": "AI Health Diagnostics API Running", "timestamp": datetime.now().isoformat()}
# ---------- Create User Profile ----------
@app.post("/create-profile", response_model=AnalysisResponse)
async def create_profile(profile: UserProfile):
try:
user_id = str(uuid.uuid4())
user_data = {
"id": user_id,
"username": profile.username.strip(),
"email": profile.email.strip(),
"age": profile.age,
"gender": profile.gender,
"allergies": profile.allergies,
"conditions": profile.conditions
}
db.create_user(user_data)
return AnalysisResponse(
success=True,
data={"user_id": user_id},
message="Profile created successfully"
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
# ---------- Check User Profile ----------
@app.post("/check-profile", response_model=AnalysisResponse)
async def check_profile(request: LoginRequest):
username = request.username.strip()
try:
response = db.client.table("users").select("*").eq("username", username).execute()
users = response.data or []
if not users:
raise HTTPException(status_code=404, detail="User not found")
user = users[0]
return AnalysisResponse(
success=True,
data={"user_id": user["id"], "username": user["username"]},
message="Profile found"
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
# ---------- Symptom Check ----------
@app.post("/symptom-check", response_model=AnalysisResponse)
async def symptom_check(request: SymptomsRequest):
try:
# Fetch user from Supabase
user_response = db.client.table("users").select("*").eq("id", request.user_id).execute()
users = user_response.data or []
if not users:
raise HTTPException(status_code=404, detail="User not found")
user_profile = users[0]
# Run AI analysis
analysis_result = ai_models.analyze_symptoms(request.symptoms, user_profile)
# Log analysis
db.log_symptom_analysis({
"id": str(uuid.uuid4()),
"user_id": request.user_id,
"symptoms": request.symptoms,
"result": json.dumps(analysis_result)
})
return AnalysisResponse(
success=True,
data=analysis_result,
message="Symptoms analyzed successfully"
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
# ---------- Image Analysis ----------
@app.post("/analyze-image", response_model=AnalysisResponse)
async def analyze_image(
user_id: str = Form(...),
image_type: str = Form("skin"),
file: UploadFile = File(...)
):
try:
allowed_types = ["image/jpeg", "image/png", "image/jpg"]
if file.content_type not in allowed_types:
raise HTTPException(status_code=400, detail="Invalid image format")
image_data = await file.read()
if len(image_data) > config.MAX_IMAGE_SIZE:
raise HTTPException(status_code=400, detail="Image too large")
analysis_result = ai_models.analyze_image(image_data, image_type)
filename = f"{uuid.uuid4()}_{file.filename}"
file_path = os.path.join(config.UPLOAD_DIR, filename)
with open(file_path, "wb") as f:
f.write(image_data)
db.log_image_analysis({
"id": str(uuid.uuid4()),
"user_id": user_id,
"filename": filename,
"result": json.dumps(analysis_result),
"confidence": analysis_result.get("confidence", 0.0)
})
return AnalysisResponse(
success=True,
data=analysis_result,
message="Image analyzed successfully"
)
except Exception as e:
print("🔥 SERVER ERROR:", repr(e))
raise HTTPException(status_code=500, detail=str(e))
# ---------- User History ----------
@app.get("/user-history/{user_id}", response_model=AnalysisResponse)
async def get_user_history(user_id: str):
try:
symptoms = db.client.table("symptoms_history").select("*").eq("user_id", user_id).order("created_at", desc=True).limit(10).execute()
images = db.client.table("image_analysis").select("*").eq("user_id", user_id).order("created_at", desc=True).limit(10).execute()
return AnalysisResponse(
success=True,
data={
"symptom_checks": symptoms.data or [],
"image_analyses": images.data or []
},
message="History retrieved successfully"
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
# ---------- Run Server ----------
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000) |