Spaces:
Running
Running
File size: 3,957 Bytes
4c40bac eff2c28 bf0b08e eff2c28 6784fde 4c40bac eff2c28 4c40bac eff2c28 4c40bac eff2c28 2a464ca eff2c28 3b8a72f eff2c28 6784fde bf0b08e 6784fde bf0b08e 6784fde bf0b08e 6784fde bf0b08e 6784fde bf0b08e 6784fde bf0b08e 3b8a72f eff2c28 6784fde 3b8a72f bf0b08e e6c065b bf0b08e e6c065b 6784fde bf0b08e 6784fde eff2c28 6784fde eff2c28 6784fde e6c065b eff2c28 4c40bac eff2c28 6784fde 4c40bac eff2c28 4c40bac eff2c28 bf0b08e eff2c28 bf0b08e 4c40bac eff2c28 3b8a72f 4c40bac eff2c28 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | import gradio as gr
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import StreamingResponse
import random
import threading
import uvicorn
import aiohttp
from src.config import get_api_keys
from src.model_tester import ModelTester
from src.scheduler import Scheduler
model_tester = ModelTester()
scheduler = Scheduler(task_callback=lambda: model_tester.scan_all_models())
fastapi_app = FastAPI(title="OpenRouter Free API")
@fastapi_app.on_event("startup")
async def startup_event():
threading.Thread(target=lambda: scheduler.start(), daemon=True).start()
@fastapi_app.get("/v1/models")
async def list_models():
available = model_tester.get_available_models(free_only=False)
available_free = model_tester.get_available_models(free_only=True)
models = []
for model_id in available:
is_free = model_id in available_free
models.append({
"id": model_id,
"object": "model",
"created": 1677610602,
"owned_by": "openrouter",
"free": is_free
})
return {"object": "list", "data": models}
async def proxy_request(body: dict):
"""透传请求,只替换 model 和 key"""
api_key = random.choice(get_api_keys())
model_tester.refresh_model_list()
available_free = model_tester.get_all_free_models()
model_hint = body.get("model")
target_model = None
if model_hint and available_free:
for m in available_free:
model_name = m.replace(":free", "").split("/")[-1]
if model_hint.lower() in model_name.lower():
target_model = m
break
if not target_model and available_free:
target_model = random.choice(available_free[:5])
if not target_model:
raise HTTPException(status_code=400, detail="No available model")
body["model"] = target_model
url = "https://openrouter.ai/api/v1/chat/completions"
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
async with aiohttp.ClientSession() as session:
async with session.post(url, json=body, headers=headers, timeout=aiohttp.ClientTimeout(total=120)) as response:
if body.get("stream"):
async for chunk in response.content:
yield chunk
else:
yield await response.json()
@fastapi_app.post("/v1/chat/completions")
async def chat_completions(request: Request):
body = await request.json()
if body.get("stream"):
return StreamingResponse(
proxy_request(body),
media_type="text/event-stream"
)
result = None
async for data in proxy_request(body):
result = data
break
if not result:
raise HTTPException(status_code=400, detail="Request failed")
if "error" in result:
raise HTTPException(status_code=400, detail=result["error"])
return result
@fastapi_app.get("/health")
async def health():
return {"status": "ok"}
def get_scan_status():
scan_result = model_tester.scan_result
total = scan_result.get("total_available", 0)
free = scan_result.get("free_available", 0)
return f"Free: {free} | Total: {total}"
def format_model_list(models):
return "\n".join(models) if models else "No models available"
with gr.Blocks(title="OpenRouter Free API") as demo:
gr.Markdown("# OpenRouter Free API")
gr.Markdown("Standard OpenAI-compatible API with free model support")
gr.Markdown(f"**Status: {get_scan_status()}**")
gr.Markdown("## Available Free Models")
gr.Textbox(value=format_model_list(model_tester.get_available_models(free_only=True)), lines=15, interactive=False)
app = gr.mount_gradio_app(fastapi_app, demo, path="/")
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=7860)
|