Testapi / app.py
bahi-bh's picture
Update app.py
d279c98 verified
from fastapi import FastAPI, Request, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import StreamingResponse, JSONResponse
from pydantic import BaseModel
from typing import List, Optional, AsyncGenerator
import json
import time
import uuid
import logging
import asyncio
# استيراد g4f بالطريقة الصحيحة
import g4f
from g4f import ChatCompletion
from g4f.Provider import (
Bing,
OpenaiChat,
Gemini,
You,
AIChat
)
# =====================================================
# LOGGING
# =====================================================
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# =====================================================
# CONFIG
# =====================================================
API_KEY = "sk-your-secret-key" # غيّر هذا
# =====================================================
# FASTAPI
# =====================================================
app = FastAPI(
title="Universal AI Gateway",
version="5.3.0"
)
# =====================================================
# CORS
# =====================================================
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# =====================================================
# MODELS
# =====================================================
class Message(BaseModel):
role: str
content: str
class ChatRequest(BaseModel):
model: str = "gpt-3.5-turbo"
messages: List[Message]
stream: bool = False
temperature: Optional[float] = 0.7
max_tokens: Optional[int] = 4096
# =====================================================
# AUTH
# =====================================================
def verify_api_key(req: Request):
# للاختبار: السماح بدون مفتاح
auth = req.headers.get("Authorization")
if not auth:
return True
if not auth.startswith("Bearer "):
raise HTTPException(status_code=401, detail="Invalid Authorization Format")
token = auth.replace("Bearer ", "").strip()
if token != API_KEY:
raise HTTPException(status_code=403, detail="Invalid API Key")
return True
# =====================================================
# ROOT
# =====================================================
@app.get("/")
async def root():
return {
"status": "online",
"service": "Universal AI Gateway",
"version": "5.3.0",
"providers": ["Bing", "OpenaiChat", "Gemini", "You"]
}
# =====================================================
# MODELS
# =====================================================
@app.get("/v1/models")
async def get_models():
# قائمة النماذج المدعومة فعلياً
models_data = [
{"id": "gpt-3.5-turbo", "object": "model", "owned_by": "g4f"},
{"id": "gpt-4", "object": "model", "owned_by": "g4f"},
{"id": "gpt-4o-mini", "object": "model", "owned_by": "g4f"},
{"id": "gemini", "object": "model", "owned_by": "g4f"},
]
return {
"object": "list",
"data": models_data
}
# =====================================================
# CHAT COMPLETIONS
# =====================================================
@app.post("/v1/chat/completions")
async def chat_completions(
req: Request,
body: ChatRequest
):
# التحقق من المفتاح
verify_api_key(req)
# تحويل الرسائل
messages = [
{"role": m.role, "content": m.content}
for m in body.messages
]
logger.info(f"Request: model={body.model}, stream={body.stream}")
logger.info(f"Messages: {messages}")
# =================================================
# STREAMING
# =================================================
if body.stream:
async def generate_stream() -> AsyncGenerator[str, None]:
chunk_id = f"chatcmpl-{uuid.uuid4().hex[:8]}"
try:
# استخدام ChatCompletion.create مع stream=True
response = await ChatCompletion.create_async(
model=body.model,
messages=messages,
stream=True,
provider=Bing # جرب Bing أو OpenaiChat
)
async for chunk in response:
if chunk:
payload = {
"id": chunk_id,
"object": "chat.completion.chunk",
"created": int(time.time()),
"model": body.model,
"choices": [
{
"index": 0,
"delta": {"content": chunk},
"finish_reason": None
}
]
}
yield f"data: {json.dumps(payload, ensure_ascii=False)}\n\n"
# إرسال إشارة النهاية
final_payload = {
"id": chunk_id,
"object": "chat.completion.chunk",
"created": int(time.time()),
"model": body.model,
"choices": [
{
"index": 0,
"delta": {},
"finish_reason": "stop"
}
]
}
yield f"data: {json.dumps(final_payload)}\n\n"
yield "data: [DONE]\n\n"
except Exception as e:
logger.error(f"Streaming error: {e}", exc_info=True)
error_msg = {"error": {"message": str(e), "type": "stream_error"}}
yield f"data: {json.dumps(error_msg)}\n\n"
yield "data: [DONE]\n\n"
return StreamingResponse(
generate_stream(),
media_type="text/event-stream",
headers={
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"Access-Control-Allow-Origin": "*"
}
)
# =================================================
# NORMAL RESPONSE
# =================================================
try:
# استخدام ChatCompletion.create_async
response = await ChatCompletion.create_async(
model=body.model,
messages=messages,
stream=False,
provider=Bing # جرب مزوداً مختلفاً إذا فشل
)
return JSONResponse({
"id": f"chatcmpl-{uuid.uuid4().hex[:8]}",
"object": "chat.completion",
"created": int(time.time()),
"model": body.model,
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": response
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 0,
"completion_tokens": 0,
"total_tokens": 0
}
})
except Exception as e:
logger.error(f"Chat error: {e}", exc_info=True)
raise HTTPException(
status_code=500,
detail=f"Provider error: {str(e)}"
)
# =====================================================
# RUN
# =====================================================
if __name__ == "__main__":
import uvicorn
uvicorn.run(
app,
host="0.0.0.0",
port=7860,
log_level="info"
)