Spaces:
Paused
Paused
| from fastapi import FastAPI, HTTPException, Depends, Header | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.responses import StreamingResponse, HTMLResponse | |
| import uvicorn | |
| import os | |
| import logging | |
| import httpx | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| app = FastAPI(title="FreeLLMAPI") | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # ============================================================ | |
| # Provider Secrets | |
| # ============================================================ | |
| PROVIDER_MAP = { | |
| "GOOGLE_API_KEY": "google", | |
| "GROQ_API_KEY": "groq", | |
| "GITHUB_TOKEN": "github", | |
| "OPENROUTER_API_KEY": "openrouter", | |
| "MISTRAL_API_KEY": "mistral", | |
| "TOGETHER_API_KEY": "together", | |
| "NVIDIA_API_KEY": "nvidia", | |
| "COHERE_API_KEY": "cohere", | |
| "HF_TOKEN": "huggingface", | |
| "CEREBRAS_API_KEY": "cerebras", | |
| "SAMBANOVA_API_KEY": "sambanova", | |
| "CLOUDFLARE_API_TOKEN": "cloudflare", | |
| "ZHIPU_API_KEY": "zhipu", | |
| } | |
| PROVIDER_CONFIG = { | |
| "google": { | |
| "base_url": "https://generativelanguage.googleapis.com/v1beta/openai", | |
| "models": [ | |
| "gemini-2.0-flash", | |
| "gemini-2.0-flash-lite", | |
| "gemini-1.5-flash", | |
| "gemini-1.5-pro", | |
| ], | |
| }, | |
| "groq": { | |
| "base_url": "https://api.groq.com/openai/v1", | |
| "models": [ | |
| "llama-3.3-70b-versatile", | |
| "llama-3.1-8b-instant", | |
| "mixtral-8x7b-32768", | |
| "gemma2-9b-it", | |
| ], | |
| }, | |
| "github": { | |
| "base_url": "https://models.inference.ai.azure.com", | |
| "models": [ | |
| "gpt-4o", | |
| "gpt-4o-mini", | |
| "Phi-4", | |
| "DeepSeek-R1", | |
| ], | |
| }, | |
| "openrouter": { | |
| "base_url": "https://openrouter.ai/api/v1", | |
| "models": [ | |
| "deepseek/deepseek-r1:free", | |
| "google/gemma-3-27b-it:free", | |
| "meta-llama/llama-3.3-70b-instruct:free", | |
| ], | |
| }, | |
| "mistral": { | |
| "base_url": "https://api.mistral.ai/v1", | |
| "models": [ | |
| "mistral-small-latest", | |
| "mistral-large-latest", | |
| ], | |
| }, | |
| "together": { | |
| "base_url": "https://api.together.xyz/v1", | |
| "models": [ | |
| "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", | |
| "deepseek-ai/DeepSeek-R1", | |
| ], | |
| }, | |
| "nvidia": { | |
| "base_url": "https://integrate.api.nvidia.com/v1", | |
| "models": [ | |
| "meta/llama-3.1-70b-instruct", | |
| "deepseek-ai/deepseek-r1", | |
| ], | |
| }, | |
| "cohere": { | |
| "base_url": "https://api.cohere.com/compatibility/v1", | |
| "models": [ | |
| "command-r-plus", | |
| "command-r", | |
| ], | |
| }, | |
| "huggingface": { | |
| "base_url": "https://huggingface.co/api/inference-proxy/together", | |
| "models": [ | |
| "meta-llama/Llama-3.3-70B-Instruct", | |
| "Qwen/Qwen2.5-72B-Instruct", | |
| ], | |
| }, | |
| "cerebras": { | |
| "base_url": "https://api.cerebras.ai/v1", | |
| "models": [ | |
| "llama3.1-8b", | |
| "llama3.3-70b", | |
| ], | |
| }, | |
| "sambanova": { | |
| "base_url": "https://api.sambanova.ai/v1", | |
| "models": [ | |
| "Meta-Llama-3.1-405B-Instruct", | |
| ], | |
| }, | |
| "cloudflare": { | |
| "base_url": "https://api.cloudflare.com/client/v4/accounts/{}/ai/v1", | |
| "models": [ | |
| "@cf/meta/llama-3.1-8b-instruct", | |
| ], | |
| }, | |
| "zhipu": { | |
| "base_url": "https://open.bigmodel.cn/api/paas/v4", | |
| "models": [ | |
| "glm-4-flash", | |
| "glm-4", | |
| ], | |
| }, | |
| } | |
| # ============================================================ | |
| # Load Config | |
| # ============================================================ | |
| def load_config(): | |
| raw_keys = os.getenv("API_KEYS", "").strip() | |
| api_keys = set( | |
| k.strip() | |
| for k in raw_keys.split(",") | |
| if k.strip() | |
| ) | |
| providers = {} | |
| cf_account_id = os.getenv( | |
| "CLOUDFLARE_ACCOUNT_ID", | |
| "" | |
| ) | |
| for env_name, provider_name in PROVIDER_MAP.items(): | |
| key = os.getenv(env_name, "").strip() | |
| if not key: | |
| continue | |
| cfg = PROVIDER_CONFIG[provider_name] | |
| base_url = cfg["base_url"] | |
| if provider_name == "cloudflare": | |
| if cf_account_id: | |
| base_url = base_url.format(cf_account_id) | |
| providers[provider_name] = { | |
| "api_key": key, | |
| "base_url": base_url, | |
| "models": cfg["models"], | |
| } | |
| logger.info(f"✅ Provider loaded: {provider_name}") | |
| logger.info( | |
| f"🚀 API Keys={len(api_keys)} Providers={len(providers)}" | |
| ) | |
| return api_keys, providers | |
| API_KEYS, PROVIDERS = load_config() | |
| # ============================================================ | |
| # Auth | |
| # ============================================================ | |
| def verify_api_key( | |
| authorization: str = Header(...) | |
| ): | |
| token = authorization.replace( | |
| "Bearer ", | |
| "" | |
| ).strip() | |
| if token not in API_KEYS: | |
| raise HTTPException( | |
| status_code=401, | |
| detail="Invalid API key" | |
| ) | |
| return token | |
| # ============================================================ | |
| # Routes | |
| # ============================================================ | |
| async def root(): | |
| return f""" | |
| <html> | |
| <body style="font-family:Arial;padding:40px"> | |
| <h1>🚀 FreeLLMAPI</h1> | |
| <p>Status: ONLINE</p> | |
| <p>Providers: {len(PROVIDERS)}</p> | |
| <p>User Keys: {len(API_KEYS)}</p> | |
| </body> | |
| </html> | |
| """ | |
| async def health(): | |
| return { | |
| "status": "ok", | |
| "providers": list(PROVIDERS.keys()), | |
| "provider_count": len(PROVIDERS), | |
| "user_keys": len(API_KEYS), | |
| } | |
| async def keys(): | |
| result = {} | |
| for env_name, provider in PROVIDER_MAP.items(): | |
| result[provider] = bool( | |
| os.getenv(env_name) | |
| ) | |
| return { | |
| "providers": result, | |
| "provider_count": len(PROVIDERS), | |
| "user_api_keys": len(API_KEYS), | |
| } | |
| async def debug(): | |
| return { | |
| "providers_loaded": list(PROVIDERS.keys()), | |
| "provider_count": len(PROVIDERS), | |
| "user_api_keys": len(API_KEYS), | |
| "total_models": sum( | |
| len(x["models"]) | |
| for x in PROVIDERS.values() | |
| ), | |
| } | |
| async def models( | |
| _: str = Depends(verify_api_key) | |
| ): | |
| data = [] | |
| for provider in PROVIDERS.values(): | |
| for model in provider["models"]: | |
| data.append({ | |
| "id": model, | |
| "object": "model" | |
| }) | |
| return { | |
| "object": "list", | |
| "data": data | |
| } | |
| async def chat( | |
| body: dict, | |
| _: str = Depends(verify_api_key) | |
| ): | |
| model = body.get("model") | |
| provider = None | |
| for p in PROVIDERS.values(): | |
| if model in p["models"]: | |
| provider = p | |
| break | |
| if not provider: | |
| raise HTTPException( | |
| status_code=404, | |
| detail=f"Model not found: {model}" | |
| ) | |
| target_url = ( | |
| provider["base_url"] | |
| + "/chat/completions" | |
| ) | |
| headers = { | |
| "Authorization": | |
| f"Bearer {provider['api_key']}", | |
| "Content-Type": | |
| "application/json" | |
| } | |
| if provider["base_url"].startswith( | |
| "https://openrouter.ai" | |
| ): | |
| headers["HTTP-Referer"] = ( | |
| "https://huggingface.co" | |
| ) | |
| headers["X-Title"] = ( | |
| "HF FreeLLMAPI" | |
| ) | |
| if body.get("stream", False): | |
| async def generate(): | |
| async with httpx.AsyncClient( | |
| timeout=120 | |
| ) as client: | |
| async with client.stream( | |
| "POST", | |
| target_url, | |
| headers=headers, | |
| json=body, | |
| ) as response: | |
| async for chunk in response.aiter_bytes(): | |
| yield chunk | |
| return StreamingResponse( | |
| generate(), | |
| media_type="text/event-stream" | |
| ) | |
| async with httpx.AsyncClient( | |
| timeout=120 | |
| ) as client: | |
| response = await client.post( | |
| target_url, | |
| headers=headers, | |
| json=body, | |
| ) | |
| try: | |
| return response.json() | |
| except Exception: | |
| return { | |
| "raw": response.text | |
| } | |
| if __name__ == "__main__": | |
| uvicorn.run( | |
| app, | |
| host="0.0.0.0", | |
| port=7860 | |
| ) |