| | """ |
| | 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" |
| | ) |
| |
|
| | |
| | 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) |
| | ) |
| |
|
| |
|
| | |
| | @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} |
| | )) |
| |
|
| |
|
| | |
| | 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) |
| |
|