CoolFace
Apppublic

npmaiecosystem/loadbalancerfallback

sourceHugging Faceupdated 3mo agoView on Hugging Face
1likes
app.py203 linesDownload Raw Back to root
1from fastapi import FastAPI, Request, HTTPException2from fastapi.middleware.cors import CORSMiddleware3from pydantic import BaseModel4from typing import Annotated, Any, Optional5import asyncio6from redis.asyncio import Redis7import httpx8import os9 10app = FastAPI()11 12app.add_middleware(13    CORSMiddleware,14    allow_origins=["*"],  # Allows your Netlify URL to connect15    allow_credentials=False,16    allow_methods=["*"],  # Resolves the 405 OPTIONS error17    allow_headers=["*"],18)19 20 21@app.post("/")22def health_check():23    return "Healthy"24 25password = os.environ.get("PASSWORD")26print(password)27r = Redis(28    host='redis-15562.c1.us-west-2-2.ec2.cloud.redislabs.com',29    port=15562,30    decode_responses=True,31    username="default",32    password=password,33)34 35 36 37Model_links = {38    "llama3.2": "https://galactromedaNPMAIECOSYSTEM-model23.hf.space/llama3.2", #https://sonuramashishnpm-npmai.hf.space/llama39    "qwen2.5-coder:7b":"https://galactromedaNPMAIECOSYSTEM-model24.hf.space/qwen2.5-coder:7b", #https://sonuramashishnpm-npmai.hf.space/qwen40    "vicuna:7b":"https://galactromedaNPMAIECOSYSTEM-model25.hf.space/vicuna:7b", #https://sonuramashish22028704-vicuna7b.hf.space/vicuna41    "phi3:medium":"https://sonuramashish22028704-phi3medium.hf.space/phi3medium",42    "llama3.2:3b":"https://pmaiecosystem-model5.hf.space/llama3.2:3b",43    "llama3.1:8b":"https://pmaiecosystem-model5.hf.space/llama3.1:8b",44    "falcon:7b-instruct":"https://sonuramashish22028704-falcon7binstruct.hf.space/falcon",45    "meditron":"https://KarachiUniNPMAIECOSYSTEM-model14.hf.space/meditron",46    "granite4.1:3b":"https://karachiuninpmaiecosystem-model14.hf.space/granite4.1:3b",47    "wizard-math":"https://karachiuninpmaiecosystem-model15.hf.space/wizard-math",48    "llava":"https://karachiuninpmaiecosystem-model15.hf.space/llava",49    "olmo2":"https://karachiuninpmaiecosystem-model19.hf.space/olmo2",50    "nemotron-mini":"https://karachiuninpmaiecosystem-model19.hf.space/nemotron-mini",51    "internlm2:7b":"https://sonuramashish22028704-internlm27b.hf.space/internlm",52    "codellama:7b-instruct":"https://sonuramashish22028704-falcon7binstruct.hf.space/codellama",53    "mistral:7b":"https://sonuramashish22028704-mistral7b.hf.space/mistral",54    "qwen3.5:9b":"https://sonuramashish22028704-vicuna7b.hf.space/qwen359gb",55    "gemma2:9b":"https://sonuramashish22028704-internlm27b.hf.space/gemma29b",56    "qwen2.5:7b":"https://pmaiecosystem-model6.hf.space/qwen2.5:7b",57    "llama3.2:1b":"https://pmaiecosystem-model6.hf.space/llama3.2:1b",58    "qwen2-math:7b":"https://pmaiecosystem-model7.hf.space/qwen2-math:7b",59    "qwen2.5vl":"https://pmaiecosystem-model7.hf.space/qwen2.5vl",60    "phi3:3.8b":"https://sonuramashishnpmai-model8.hf.space/phi3:3.8b",61    "llava-phi3":"https://sonuramashishnpmai-model8.hf.space/llava-phi3",62    "gemma2:2b":"https://sonuramashishnpmai-model9.hf.space/gemma2:2b",63    "openhermes":"https://sonuramashishnpmai-model9.hf.space/openhermes",64    "deepseek-coder:6.7b":"https://sonuramashishnpmai-model10.hf.space/deepseek-coder:6.7b",65    "yi":"https://sonuramashishnpmai-model10.hf.space/yi",66    "granite3.3:2b":"https://sonuramashishnpmai-model12.hf.space/granite3.3:2b",67    "smollm:1.7b":"https://sonuramashishnpmai-model12.hf.space/smollm:1.7b",68    "stablelm2":"https://sonuramashishnpmai-model13.hf.space/stablelm2",69    "cniongolo_biomistral":"https://sonuramashishnpm-model13.hf.space/cniongolo_biomistral",70    "moondream":"https://karachiuninpmaiecosystem-model16.hf.space/moondream",71    "openchat":"https://karachiuninpmaiecosystem-model16.hf.space/openchat",72    "deepseek-r1:7b":"https://karachiuninpmaiecosystem-model17.hf.space/deepseek-r1:7b",73    "openbmb_minicpm-v2.6":"https://karachiuninpmaiecosystem-model17.hf.space/openbmb_minicpm-v2.6",74    "llama3:8b":"https://karachiuninpmaiecosystem-model18.hf.space/llama3:8b",75    "gemma3:4b":"https://karachiuninpmaiecosystem-model18.hf.space/gemma3:4b",76    "stable-code":"https://galactromedanpmaiecosystem-model20.hf.space/stable-code",77    "codellama:7b":"https://galactromedanpmaiecosystem-model20.hf.space/codellama:7b",78    "aya:8b":"https://galactromedanpmaiecosystem-model21.hf.space/aya:8b",79    "phi4:14b":"https://galactromedanpmaiecosystem-model20.hf.space/phi4:14b",80    "gemma4:e2b":"https://galactromedanpmaiecosystem-model22.hf.space/gemma4:e2b",81    "qwen3.5:2b":"https://galactromedanpmaiecosystem-model22.hf.space/qwen3.5:2b",82    "llama3.2_fall":"https://sonuramashishnpm-npm-journalist.hf.space/llm_fall_llama",83    "qwen2.5-coder:7b_fall":"https://sonuramashish22028704-mistral7b.hf.space/llm_fall_qwen2",84    "vicuna:7b_fall":"https://sonuramashishnpm-model4.hf.space/llm_fall_vicuna",85    "gemma3:12b_fall":"https://pmaiecosystem-gemma312b_fall.hf.space/llm_fall_gemma312b",86    "internlm2:7b_fall":"https://sonuramashishnpm-model2.hf.space/llm_fall_interlm",87    "falcon:7b-instruct_fall":"https://sonuramashishnpm-model1.hf.space/llm_fall_falcon",88    "codellama:7b-instruct_fall":"https://sonuramashishnpm-model3.hf.space/llm_fall_codellama",89    "mistral:7b_fall":"https://sonuramashishnpm-model2.hf.space/fall_llm_mistral",90    "phi3:medium_fall":"https://sonuramashishnpm-model1.hf.space/llama_fall_phi",91    "qwen3.5:9b_fall":"https://sonuramashishnpm-model4.hf.space/llm_fall_qwen359gb",92    "gemma2:9b_fall":"https://sonuramashishnpm-model3.hf.space/llm_fall_gemma29b",93    "gemma3:12b":"https://pmaiecosystem-gemma312b.hf.space/gemma312b",94}95 96# Updated Lua Script97LUA_CHECK_AND_INC = """98local key = KEYS[1]99local status = tonumber(redis.call('HGET', key, 'status') or '0')100if status < 1 then101    redis.call('HSET', key, 'status', status + 1)102    return status103end104return -1105"""106 107LUA_REMOVAL_STATUS = """108local key = KEYS[1]109local status = tonumber(redis.call('HGET', key, 'status') or '0')110if status > 0 then111    redis.call('HSET', key, 'status', status -1)112    return status -1113end114return 0115"""116 117async def check_cond(model_link: str, fall_model: Optional[list] = None):118    status = await r.eval(LUA_CHECK_AND_INC, 1, model_link)119    if status != -1:120        return {"link": model_link, "statusno": status}121 122    if fall_model:123        for model in fall_model:124            status = await r.eval(LUA_CHECK_AND_INC, 1, model)125            if status != -1:126                return {"link": model, "statusno": status}127                128    129    for model in Model_links.values():130        status = await r.eval(LUA_CHECK_AND_INC, 1, model)131        if status != -1:132            return {"link": model, "statusno": status}133 134    return None135 136 137class Input(BaseModel):138    model: str139    temperature: float = 0.5140    prompt: str141    change: bool = True142    Models: Optional[list] = None143 144@app.post("/load_balancer")145async def llm_router(inputs: Input):146    if not inputs.model or not inputs.prompt:147        raise HTTPException(status_code=400, detail="Model name and Prompt are required.")148 149    if inputs.model not in Model_links:150        raise HTTPException(status_code=444, detail="Model not found.")151 152    model_link = Model_links[inputs.model]153    fall_links = []154 155    fall_models = inputs.Models156    if fall_models:157        for m in fall_models:158            model_name = f"{m}_fall"159            if model_name in Model_links.keys():160                link = Model_links[model_name]161                fall_links.append(link)162            else:163                raise HTTPException(status_code=402, detail="Fallback models are not found in Models Dictionary")164 165    model_cond = await check_cond(model_link=model_link, fall_model=fall_links)166    167    if model_cond and model_cond.get("link") and model_cond.get("statusno") is not None:168        return await router(169            model_url=model_cond["link"],170            prompt=inputs.prompt,171            temp=inputs.temperature172        )173    else:174        raise HTTPException(status_code=503, detail="All model endpoints and fallbacks are busy.")175 176async def router(model_url, prompt, temp):177    error_log = ""178    process= ""179    payload = {"prompt": prompt, "temperature": temp}180    timeout = httpx.Timeout(connect=100.0, read=560.0, write=300.0, pool=320.0)181 182    try:183        async with httpx.AsyncClient(timeout=timeout) as client:184            response = await client.post(model_url, json=payload)185            response.raise_for_status()186            f_response = response.json()["response"]187            if f_response is not None and str(f_response).strip() != "":188                process += f_response189 190            else:191                raise ValueError("Empty string or None returned in response from LLM")192    except Exception as e:193        error_log += f"LLM backend error: {str(e)}"194        print(f"Detailed ERROR:-{e}")195 196    finally:197        await r.eval(LUA_REMOVAL_STATUS, 1, model_url)198 199    if error_log:200        raise HTTPException(status_code=502, detail=error_log)201        202    else:203        return {"response": process}