P2THE28's picture
Upload folder using huggingface_hub
50a8ea3 verified
Raw History Blame Contribute Delete
8.39 kB
import os
import sys
import tempfile
from pathlib import Path
from fastapi import FastAPI, File, HTTPException, UploadFile
from fastapi.middleware.cors import CORSMiddleware
from gradio_client import Client, handle_file
from pydantic import BaseModel
# ============================================================
# PROJECT PATH
# ============================================================
PROJECT_ROOT = Path(__file__).resolve().parent.parent
# Allow Python to find:
# oosc/rights_navigator/
sys.path.append(str(PROJECT_ROOT))
# ============================================================
# RIGHTS NAVIGATOR
# ============================================================
from rights_navigator.rights_navigator import get_rights_response
# ============================================================
# FASTAPI APP
# ============================================================
app = FastAPI(
title="Civic & RTI Hub API"
)
# ============================================================
# CORS
# ============================================================
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# ============================================================
# HUGGING FACE TOKEN
# ============================================================
HF_TOKEN = os.getenv("HF_TOKEN")
# ============================================================
# HUGGING FACE SPACES
# ============================================================
# Friend's PDF Simplifier
SIMPLIFIER_SPACE_ID = "Ronak0/RC"
# Friend's RTI Drafter
DRAFTER_SPACE_ID = "Ronak0/rti-drafter"
# ============================================================
# CLIENTS
# ============================================================
# IMPORTANT:
# Do NOT connect to the Spaces when the server starts.
#
# They will be initialized only when /simplify or /draft
# is actually called.
simplifier_client = None
drafter_client = None
# ============================================================
# LAZY LOAD - PDF SIMPLIFIER
# ============================================================
def get_simplifier_client():
global simplifier_client
if simplifier_client is None:
print("Connecting to PDF Simplifier Space...")
simplifier_client = Client(
SIMPLIFIER_SPACE_ID,
token=HF_TOKEN
)
print("PDF Simplifier connected.")
return simplifier_client
# ============================================================
# LAZY LOAD - RTI DRAFTER
# ============================================================
def get_drafter_client():
global drafter_client
if drafter_client is None:
print("Connecting to RTI Drafter Space...")
drafter_client = Client(
DRAFTER_SPACE_ID,
token=HF_TOKEN
)
print("RTI Drafter connected.")
return drafter_client
# ============================================================
# REQUEST MODELS
# ============================================================
class DraftRequest(BaseModel):
prompt: str
class RightsRequest(BaseModel):
grievance: str
# ============================================================
# HEALTH CHECK
# ============================================================
@app.get("/")
async def root():
return {
"status": "online",
"service": "Civic & RTI Hub API",
"endpoints": [
"/simplify",
"/draft",
"/rights"
]
}
# ============================================================
# PDF SIMPLIFIER
# ============================================================
@app.post("/simplify")
@app.post("/api/simplify")
async def simplify_pdf(
file: UploadFile = File(...)
):
# --------------------------------------------------------
# Validate PDF
# --------------------------------------------------------
if not file.filename.lower().endswith(".pdf"):
raise HTTPException(
status_code=400,
detail="Must be a PDF file."
)
# --------------------------------------------------------
# Save uploaded PDF temporarily
# --------------------------------------------------------
with tempfile.NamedTemporaryFile(
delete=False,
suffix=".pdf"
) as tmp:
tmp.write(
await file.read()
)
tmp_path = tmp.name
try:
# ----------------------------------------------------
# Connect only when this endpoint is used
# ----------------------------------------------------
client = get_simplifier_client()
# ----------------------------------------------------
# Call friend's Hugging Face Space
# ----------------------------------------------------
raw_result = client.predict(
pdf_file=handle_file(tmp_path),
api_name="/simplify_document"
)
# ----------------------------------------------------
# Format response
# ----------------------------------------------------
points = [
p.strip()
for p in raw_result.split("\n\n")
if p.strip()
]
return {
"simplified_points": points
}
except Exception as e:
raise HTTPException(
status_code=500,
detail=f"PDF simplifier error: {str(e)}"
)
finally:
# ----------------------------------------------------
# Delete temporary PDF
# ----------------------------------------------------
if os.path.exists(tmp_path):
os.remove(tmp_path)
# ============================================================
# RTI DRAFTER
# ============================================================
@app.post("/draft")
@app.post("/api/draft")
async def draft_rti_endpoint(
request: DraftRequest
):
# --------------------------------------------------------
# Validate request
# --------------------------------------------------------
if not request.prompt.strip():
raise HTTPException(
status_code=400,
detail="Prompt cannot be empty."
)
try:
# ----------------------------------------------------
# Connect only when this endpoint is used
# ----------------------------------------------------
client = get_drafter_client()
# ----------------------------------------------------
# Call friend's Hugging Face Space
# ----------------------------------------------------
draft_result = client.predict(
user_prompt=request.prompt,
api_name="/draft_rti"
)
return {
"draft": draft_result
}
except Exception as e:
raise HTTPException(
status_code=500,
detail=f"RTI drafter error: {str(e)}"
)
# ============================================================
# RIGHTS NAVIGATOR
# ============================================================
@app.post("/rights")
@app.post("/api/rights")
async def rights_navigator_endpoint(
request: RightsRequest
):
# --------------------------------------------------------
# Validate grievance
# --------------------------------------------------------
if not request.grievance.strip():
raise HTTPException(
status_code=400,
detail="Grievance cannot be empty."
)
try:
# ----------------------------------------------------
# Call YOUR Rights Navigator
# ----------------------------------------------------
result = get_rights_response(
request.grievance
)
return result
except Exception as e:
raise HTTPException(
status_code=500,
detail=f"Rights Navigator error: {str(e)}"
)