Spaces:
Running
Running
| import io | |
| from fastapi import FastAPI, File, UploadFile, Form, Request | |
| from fastapi.responses import JSONResponse | |
| from fastapi.templating import Jinja2Templates | |
| from fastapi.staticfiles import StaticFiles | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from PIL import Image | |
| from ai_router import route_model | |
| from utils.logger import log_request | |
| from utils.security import check_rate_limit, validate_image_size | |
| from config import DEVICE, ENABLE_EXTERNAL_AI | |
| # ================= CREATE APP FIRST ================= | |
| app = FastAPI(title="GenAI VQA System") | |
| # ================= CORS ================= | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # ================= STATIC + TEMPLATE ================= | |
| app.mount("/static", StaticFiles(directory="static"), name="static") | |
| templates = Jinja2Templates(directory="templates") | |
| # ================= HOME ================= | |
| async def home(request: Request): | |
| return templates.TemplateResponse("index.html", {"request": request}) | |
| # ================= API ================= | |
| async def get_logs_endpoint(user: str): | |
| import os | |
| logs = [] | |
| if os.path.exists("logs/requests.log"): | |
| with open("logs/requests.log", "r") as f: | |
| for line in f: | |
| if " - User: " in line: | |
| try: | |
| parts = line.split(" - INFO - User: ") | |
| timestamp = parts[0] | |
| rest = parts[1].split(" | Model: ") | |
| log_user = rest[0].strip() | |
| model_q = rest[1].split(" | Q: ") | |
| model = model_q[0].strip() | |
| question = model_q[1].strip() | |
| # Admin sees all, User sees only their own | |
| if user == "vignesh" or log_user == user: | |
| logs.append({ | |
| "timestamp": timestamp, | |
| "user": log_user, | |
| "model": model, | |
| "question": question | |
| }) | |
| except Exception as e: | |
| pass | |
| logs.reverse() | |
| return {"logs": logs} | |
| async def ask_question( | |
| file: UploadFile = File(...), | |
| question: str = Form(...), | |
| model_choice: str = Form("reasoning"), | |
| user: str = Form("guest"), | |
| lang: str = Form("en") | |
| ): | |
| check_rate_limit(user) | |
| image_bytes = await file.read() | |
| validate_image_size(len(image_bytes)) | |
| try: | |
| image = Image.open(io.BytesIO(image_bytes)).convert("RGB") | |
| except Exception as e: | |
| return JSONResponse({ | |
| "device": "Error", | |
| "model_used": model_choice, | |
| "caption": "Image Load Error", | |
| "answer": f"The supplied image was empty or an invalid format. Size received: {len(image_bytes)} bytes.", | |
| "explanation": str(e), | |
| "external_enabled": False | |
| }) | |
| caption, answer, explanation = route_model( | |
| model_choice, | |
| image, | |
| question, | |
| lang | |
| ) | |
| log_request(user, model_choice, question) | |
| return JSONResponse({ | |
| "device": DEVICE, | |
| "model_used": model_choice, | |
| "caption": caption, | |
| "answer": answer, | |
| "explanation": explanation, | |
| "external_enabled": ENABLE_EXTERNAL_AI | |
| }) |