from __future__ import annotations from fastapi import FastAPI, UploadFile, File, HTTPException, Query from fastapi.responses import JSONResponse from typing import Optional from pathlib import Path import tempfile import requests from .reviewer import PDFReviewer app = FastAPI(title="TMLR Reviewer PDF API", description="Generate reviews for uploaded PDFs") reviewer = PDFReviewer() @app.post("/review") async def review_pdf( file: Optional[UploadFile] = File(None), url: Optional[str] = Query(None, description="URL of PDF to review"), test: bool = Query(False, description="Return mock data for testing") ): """Upload a PDF file and return the structured review as JSON. You can either: - Upload a file directly - Provide a URL to a PDF - Use test=true for mock data """ # Return mock data if test mode is enabled if test: return JSONResponse(content={ "contributions": "Test contribution summary", "strengths": "- Test strength 1\n- Test strength 2", "weaknesses": "- Test weakness 1\n- Test weakness 2", "requested_changes": "- Test change 1\n- Test change 2", "impact_concerns": "No concerns for test", "claims_and_evidence": "yes", "audience_interest": "yes" }) # Check if either file or URL is provided if not file and not url: raise HTTPException(status_code=400, detail="Either file upload or URL is required") if file and url: raise HTTPException(status_code=400, detail="Please provide either file or URL, not both") # Handle URL download if url: try: # Download PDF from URL response = requests.get(url, timeout=30) response.raise_for_status() # Verify it's a PDF content_type = response.headers.get('content-type', '') if 'application/pdf' not in content_type.lower(): raise HTTPException(status_code=400, detail=f"URL does not point to a PDF. Content-Type: {content_type}") # Save to temporary file with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp: tmp.write(response.content) tmp_path = Path(tmp.name) except requests.RequestException as e: raise HTTPException(status_code=400, detail=f"Failed to download PDF from URL: {str(e)}") # Handle file upload else: if file.content_type != "application/pdf": raise HTTPException(status_code=400, detail="Only PDF files are supported") # Save to temporary location suffix = Path(file.filename).suffix or ".pdf" with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp: content = await file.read() tmp.write(content) tmp_path = Path(tmp.name) try: review_result = reviewer.review_pdf(tmp_path) except Exception as exc: raise HTTPException(status_code=500, detail=str(exc)) finally: tmp_path.unlink(missing_ok=True) return JSONResponse(content=review_result)