import os import shutil from typing import List, Optional from fastapi import FastAPI, UploadFile, File, Header, HTTPException, Depends from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel from core.config import settings from core.ingestion import processor from core.model import generator app = FastAPI(title=settings.APP_NAME) # CORS configuration app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"], ) # Authentication Dependency def verify_api_key(x_api_key: Optional[str] = Header(None)): if settings.API_KEY and x_api_key != settings.API_KEY: raise HTTPException(status_code=403, detail="Invalid API Key") return x_api_key class GenerateRequest(BaseModel): course_name: str description: str constraints: Optional[str] = "" max_tokens: int = 2000 @app.get("/health") def health_check(): return { "status": "healthy", "device": settings.DEVICE, "gpu_available": generator.is_gpu } @app.post("/ingest") async def ingest_file(file: UploadFile = File(...), api_key: str = Depends(verify_api_key)): if file.size > settings.MAX_FILE_SIZE: raise HTTPException(status_code=413, detail="File too large") file_path = os.path.join(settings.UPLOAD_DIR, file.filename) with open(file_path, "wb") as buffer: shutil.copyfileobj(file.file, buffer) chunks = processor.ingest_document(file_path) if chunks is None: raise HTTPException(status_code=400, detail="Could not extract text from file") return {"filename": file.filename, "chunks_ingested": chunks} @app.post("/generate_syllabus") async def generate_syllabus(req: GenerateRequest, api_key: str = Depends(verify_api_key)): # 1. Search for relevant context query = f"{req.course_name} {req.description}" docs = processor.search(query, k=5) context = "\n".join([d.page_content for d in docs]) # 2. Build prompt prompt = f"Design a comprehensive syllabus for a course titled '{req.course_name}'. Description: {req.description}. Constraints: {req.constraints}" # 3. Generate syllabus = generator.generate(prompt, context=context, max_tokens=req.max_tokens) return { "course_name": req.course_name, "syllabus": syllabus, "sources": [d.metadata["source"] for d in docs] } if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=settings.PORT)