""" HuggingFace Space: API Gateway Routes requests to appropriate services """ from fastapi import FastAPI, HTTPException from pydantic import BaseModel from typing import Optional, Dict, Any import httpx import os app = FastAPI( title="API Gateway Space", description="Routes requests to other spaces" ) # Service URLs from environment SERVICES = { "code_exec": os.getenv("CODE_EXEC_URL", ""), "search": os.getenv("SEARCH_URL", ""), "llm": os.getenv("LLM_URL", "") } class RouteRequest(BaseModel): service: str endpoint: str = "/api" data: Dict[str, Any] = {} timeout: int = 30 class RouteResponse(BaseModel): service: str response: Any error: Optional[str] = None @app.get("/") async def root(): return { "status": "running", "services": {k: bool(v) for k, v in SERVICES.items()} } @app.get("/health") async def health(): """Check health of all services""" health_status = {} async with httpx.AsyncClient(timeout=5.0) as client: for name, url in SERVICES.items(): if not url: health_status[name] = {"status": "not_configured"} continue try: response = await client.get(f"{url}/") health_status[name] = { "status": "healthy" if response.status_code == 200 else "unhealthy", "code": response.status_code } except Exception as e: health_status[name] = {"status": "unreachable", "error": str(e)} return health_status @app.post("/route", response_model=RouteResponse) async def route(request: RouteRequest): """Route a request to a service""" if request.service not in SERVICES: raise HTTPException(404, f"Service '{request.service}' not found") url = SERVICES[request.service] if not url: raise HTTPException(503, f"Service '{request.service}' not configured") try: async with httpx.AsyncClient(timeout=request.timeout) as client: response = await client.post( f"{url}{request.endpoint}", json=request.data ) if response.status_code == 200: return RouteResponse( service=request.service, response=response.json() ) else: return RouteResponse( service=request.service, response=None, error=f"Service returned {response.status_code}" ) except httpx.TimeoutException: return RouteResponse( service=request.service, response=None, error="Request timeout" ) except Exception as e: return RouteResponse( service=request.service, response=None, error=str(e) ) # Convenience endpoints @app.post("/execute") async def execute_code(code: str): """Shortcut to code execution""" return await route(RouteRequest( service="code_exec", endpoint="/api/execute", data={"code": code} )) @app.post("/search") async def search(query: str, max_results: int = 5): """Shortcut to web search""" return await route(RouteRequest( service="search", endpoint="/api/search", data={"query": query, "max_results": max_results} )) @app.post("/generate") async def generate(prompt: str, max_tokens: int = 200): """Shortcut to LLM generation""" return await route(RouteRequest( service="llm", endpoint="/api/generate", data={"prompt": prompt, "max_tokens": max_tokens} )) # Gradio interface def gradio_interface(): import gradio as gr async def unified_interface(service, input_text): if service == "code": response = await execute_code(input_text) elif service == "search": response = await search(input_text) else: response = await generate(input_text) if response.error: return f"Error: {response.error}" return str(response.response) iface = gr.Interface( fn=unified_interface, inputs=[ gr.Dropdown(["code", "search", "llm"], label="Service"), gr.Textbox(lines=5, label="Input") ], outputs=gr.Textbox(lines=10, label="Output"), title="API Gateway", description="Unified interface to all services" ) return iface if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=7860)