File size: 3,757 Bytes
fdcb6c5
 
 
 
ea4b76e
fdcb6c5
 
 
 
 
 
ea4b76e
fdcb6c5
ea4b76e
 
fdcb6c5
ea4b76e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fdcb6c5
82bb4d1
fdcb6c5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ea4b76e
fdcb6c5
 
 
 
 
ea4b76e
 
 
 
 
fdcb6c5
 
 
 
 
 
 
ea4b76e
 
 
 
 
 
 
fdcb6c5
ea4b76e
 
 
 
 
fdcb6c5
ea4b76e
 
fdcb6c5
 
 
 
ea4b76e
fdcb6c5
 
 
 
ea4b76e
fdcb6c5
 
 
ea4b76e
 
 
fdcb6c5
ea4b76e
 
fdcb6c5
ea4b76e
 
 
fdcb6c5
ea4b76e
fdcb6c5
 
 
 
 
 
 
 
 
ea4b76e
 
 
 
 
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
import os
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import List, Literal
import httpx
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Read API keys from Hugging Face Secrets
OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
HF_TOKEN = os.environ.get("HF_TOKEN")

if not OPENAI_API_KEY:
    logger.warning("OPENAI_API_KEY not set — OpenAI provider will be unavailable")
if not HF_TOKEN:
    logger.warning("HF_TOKEN not set — Hugging Face provider will be unavailable")

# Provider config: each provider has a base URL and a key
PROVIDERS = {
    "openai": {
        "url": "https://api.openai.com/v1/chat/completions",
        "key": OPENAI_API_KEY,
    },
    "hf": {
        "url": "https://router.huggingface.co/v1/chat/completions",
        "key": HF_TOKEN,
    },
}

app = FastAPI(title="Proxy for Unity")

# Enable CORS for Unity WebGL builds
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # In production, specify your domain
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

class Message(BaseModel):
    role: str
    content: str

class ChatRequest(BaseModel):
    model: str
    temperature: float
    messages: List[Message]
    provider: Literal["openai", "hf"] = "openai"  # default keeps existing Unity code working

@app.get("/")
async def root():
    return {
        "status": "running",
        "message": "Proxy Active",
        "providers": {
            "openai": bool(OPENAI_API_KEY),
            "hf": bool(HF_TOKEN),
        },
        "endpoints": {
            "chat": "POST /chat"
        }
    }

@app.post("/chat")
async def proxy_chat(request: ChatRequest):
    provider_config = PROVIDERS.get(request.provider)
    if not provider_config or not provider_config["key"]:
        raise HTTPException(
            status_code=400,
            detail=f"Provider '{request.provider}' is not configured"
        )

    try:
        logger.info(
            f"Provider: {request.provider} | Model: {request.model} | "
            f"Messages: {len(request.messages)}"
        )

        async with httpx.AsyncClient(timeout=60.0) as client:
            response = await client.post(
                provider_config["url"],
                json={
                    "model": request.model,
                    "temperature": request.temperature,
                    "messages": [
                        {"role": msg.role, "content": msg.content}
                        for msg in request.messages
                    ]
                },
                headers={
                    "Authorization": f"Bearer {provider_config['key']}",
                    "Content-Type": "application/json"
                }
            )

            if response.status_code != 200:
                logger.error(f"{request.provider} API error: {response.text}")
                raise HTTPException(
                    status_code=response.status_code,
                    detail=response.text
                )

            result = response.json()
            logger.info(f"Successfully proxied {request.provider} request")
            return result

    except httpx.HTTPError as e:
        logger.error(f"HTTP error: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Proxy error: {str(e)}")
    except Exception as e:
        logger.error(f"Unexpected error: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Server error: {str(e)}")

@app.get("/health")
async def health():
    return {
        "status": "healthy",
        "openai_configured": bool(OPENAI_API_KEY),
        "hf_configured": bool(HF_TOKEN),
    }