Test-ckode / app.py
bahi-bh's picture
Update app.py
931b5d1 verified
import asyncio
import json
from concurrent.futures import ThreadPoolExecutor
from typing import List
import g4f
from fastapi import FastAPI, HTTPException, Header
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import StreamingResponse
from pydantic import BaseModel
# =====================================
# CONFIG
# =====================================
API_KEY = "sk-your-secret-key"
executor = ThreadPoolExecutor(max_workers=5)
# =====================================
# APP
# =====================================
app = FastAPI(
title="AI Gateway"
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
# =====================================
# MODELS
# =====================================
class Message(BaseModel):
role: str
content: str
class ChatRequest(BaseModel):
model: str = "gpt-4o-mini"
messages: List[Message]
stream: bool = False
# =====================================
# AUTH
# =====================================
def verify_api_key(auth: str):
if not auth:
raise HTTPException(
status_code=401,
detail="Missing Authorization Header"
)
if not auth.startswith("Bearer "):
raise HTTPException(
status_code=401,
detail="Invalid Authorization"
)
token = auth.replace("Bearer ", "")
if token != API_KEY:
raise HTTPException(
status_code=403,
detail="Invalid API Key"
)
# =====================================
# GENERATE
# =====================================
def generate(model, messages):
response = g4f.ChatCompletion.create(
model=model,
messages=messages
)
return response
# =====================================
# STREAM
# =====================================
async def stream_generate(model, messages):
loop = asyncio.get_event_loop()
response = await loop.run_in_executor(
executor,
lambda: g4f.ChatCompletion.create(
model=model,
messages=messages,
stream=True
)
)
for chunk in response:
if chunk:
payload = {
"choices": [
{
"delta": {
"content": chunk
}
}
]
}
yield f"data: {json.dumps(payload)}\\n\\n"
yield "data: [DONE]\\n\\n"
# =====================================
# HOME
# =====================================
@app.get("/")
async def home():
return {
"status": "online"
}
# =====================================
# CHAT
# =====================================
@app.post("/v1/chat/completions")
async def chat(
req: ChatRequest,
authorization: str = Header(None)
):
verify_api_key(authorization)
messages = [
m.model_dump()
for m in req.messages
]
# =========================
# STREAM
# =========================
if req.stream:
return StreamingResponse(
stream_generate(
req.model,
messages
),
media_type="text/event-stream"
)
# =========================
# NORMAL
# =========================
loop = asyncio.get_event_loop()
response = await loop.run_in_executor(
executor,
lambda: generate(
req.model,
messages
)
)
return {
"choices": [
{
"message": {
"role": "assistant",
"content": response
}
}
]
}