prolau's picture
Upload folder using huggingface_hub
c84aa63 verified
Raw
History Blame Contribute Delete
3.27 kB
import os
# Load local .env file if it exists (for local testing without python-dotenv)
env_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), '.env')
if os.path.exists(env_path):
with open(env_path) as f:
for line in f:
if line.strip() and not line.startswith('#'):
try:
key, value = line.strip().split('=', 1)
os.environ[key] = value
except ValueError:
pass
from fastapi import FastAPI, UploadFile, Form, File, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
from pydantic import BaseModel
import uvicorn
from typing import Optional
import httpx
import urllib.parse
try:
from api.gemini_service import gemini_client
from api.gs_engine import gs_engine_client
except ImportError:
from gemini_service import gemini_client
from gs_engine import gs_engine_client
app = FastAPI(title="3DGS Simulation API")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
class GenerationResponse(BaseModel):
job_id: str
status: str
@app.post("/api/generate", response_model=GenerationResponse)
async def generate_3d_world(
prompt: str = Form(...),
image: Optional[UploadFile] = File(None)
):
try:
image_bytes = None
if image:
image_bytes = await image.read()
else:
# Fallback to a free Text-to-Image API if no image is uploaded
encoded_prompt = urllib.parse.quote(prompt)
image_url = f"https://image.pollinations.ai/prompt/{encoded_prompt}?width=512&height=512&nologo=true"
async with httpx.AsyncClient() as client:
resp = await client.get(image_url, timeout=30.0)
if resp.status_code == 200:
image_bytes = resp.content
layout_data = await gemini_client.analyze_spatial_layout(text_prompt=prompt, image_bytes=image_bytes)
job_id = await gs_engine_client.start_generation(layout_data, prompt=prompt, image_bytes=image_bytes)
return GenerationResponse(job_id=job_id, status="PENDING")
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.get("/api/status/{job_id}")
async def get_status(job_id: str):
status_data = gs_engine_client.get_status(job_id)
if status_data["status"] == "NOT_FOUND":
raise HTTPException(status_code=404, detail="Job not found")
return status_data
# Mount outputs directory for .ply files
os.makedirs("public/outputs", exist_ok=True)
app.mount("/outputs", StaticFiles(directory="public/outputs"), name="outputs")
# Mount Vite assets directory
if os.path.exists("frontend/dist/assets"):
app.mount("/assets", StaticFiles(directory="frontend/dist/assets"), name="assets")
# Catch-all to serve index.html for React Router
@app.get("/{full_path:path}")
async def serve_react(full_path: str):
return FileResponse("frontend/dist/index.html")
if __name__ == "__main__":
uvicorn.run("api.index:app", host="0.0.0.0", port=8000, reload=True)