Spaces:
Runtime error
Runtime error
ademarteau commited on
Commit Β·
c3fc8d4
1
Parent(s): e7f1f53
fix: proxy HF Inference API through FastAPI to bypass HF Spaces CSP
Browse files- frontend/src/App.jsx +4 -8
- requirements-server.txt +1 -0
- server/inventory_env.py +25 -0
frontend/src/App.jsx
CHANGED
|
@@ -177,16 +177,12 @@ function runOneSimulation(computeROP, demandSeries, envKey) {
|
|
| 177 |
};
|
| 178 |
}
|
| 179 |
|
| 180 |
-
// βββ HF INFERENCE API ββββ
|
| 181 |
async function callQwen(messages, modelId, hfToken) {
|
| 182 |
-
const
|
| 183 |
-
const resp = await fetch(url, {
|
| 184 |
method: "POST",
|
| 185 |
-
headers: {
|
| 186 |
-
|
| 187 |
-
...(hfToken ? { Authorization: `Bearer ${hfToken}` } : {}),
|
| 188 |
-
},
|
| 189 |
-
body: JSON.stringify({ model: modelId, messages, max_tokens: 600, temperature: 0.7 }),
|
| 190 |
});
|
| 191 |
if (!resp.ok) throw new Error(`API error ${resp.status}: ${await resp.text()}`);
|
| 192 |
const data = await resp.json();
|
|
|
|
| 177 |
};
|
| 178 |
}
|
| 179 |
|
| 180 |
+
// βββ HF INFERENCE API (proxied through FastAPI to avoid CSP on HF Spaces) ββββ
|
| 181 |
async function callQwen(messages, modelId, hfToken) {
|
| 182 |
+
const resp = await fetch("/api/qwen", {
|
|
|
|
| 183 |
method: "POST",
|
| 184 |
+
headers: { "Content-Type": "application/json" },
|
| 185 |
+
body: JSON.stringify({ model: modelId, messages, max_tokens: 600, temperature: 0.7, hf_token: hfToken || "" }),
|
|
|
|
|
|
|
|
|
|
| 186 |
});
|
| 187 |
if (!resp.ok) throw new Error(`API error ${resp.status}: ${await resp.text()}`);
|
| 188 |
const data = await resp.json();
|
requirements-server.txt
CHANGED
|
@@ -4,3 +4,4 @@ pydantic==2.12.5
|
|
| 4 |
numpy==2.4.2
|
| 5 |
ciw==3.2.7
|
| 6 |
aiofiles==24.1.0
|
|
|
|
|
|
| 4 |
numpy==2.4.2
|
| 5 |
ciw==3.2.7
|
| 6 |
aiofiles==24.1.0
|
| 7 |
+
httpx==0.28.1
|
server/inventory_env.py
CHANGED
|
@@ -5,6 +5,7 @@ sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
|
|
| 5 |
from dataclasses import dataclass, asdict
|
| 6 |
from typing import List, Optional
|
| 7 |
import numpy as np
|
|
|
|
| 8 |
from fastapi import FastAPI, HTTPException
|
| 9 |
from fastapi.staticfiles import StaticFiles
|
| 10 |
from fastapi.responses import FileResponse
|
|
@@ -260,6 +261,30 @@ def state():
|
|
| 260 |
)
|
| 261 |
|
| 262 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 263 |
# ββ Serve React frontend (static files built by Dockerfile) ββββββββββββββββββ
|
| 264 |
_static_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "static")
|
| 265 |
if os.path.isdir(_static_dir):
|
|
|
|
| 5 |
from dataclasses import dataclass, asdict
|
| 6 |
from typing import List, Optional
|
| 7 |
import numpy as np
|
| 8 |
+
import httpx
|
| 9 |
from fastapi import FastAPI, HTTPException
|
| 10 |
from fastapi.staticfiles import StaticFiles
|
| 11 |
from fastapi.responses import FileResponse
|
|
|
|
| 261 |
)
|
| 262 |
|
| 263 |
|
| 264 |
+
# ββ HF Inference API proxy (avoids browser CSP restrictions on HF Spaces) ββββ
|
| 265 |
+
|
| 266 |
+
class QwenRequest(BaseModel):
|
| 267 |
+
model: str
|
| 268 |
+
messages: list
|
| 269 |
+
max_tokens: int = 600
|
| 270 |
+
temperature: float = 0.7
|
| 271 |
+
hf_token: str = ""
|
| 272 |
+
|
| 273 |
+
@app.post("/api/qwen", include_in_schema=False)
|
| 274 |
+
async def qwen_proxy(req: QwenRequest):
|
| 275 |
+
token = req.hf_token or os.environ.get("HF_TOKEN", "")
|
| 276 |
+
headers = {"Content-Type": "application/json"}
|
| 277 |
+
if token:
|
| 278 |
+
headers["Authorization"] = f"Bearer {token}"
|
| 279 |
+
url = f"https://api-inference.huggingface.co/models/{req.model}/v1/chat/completions"
|
| 280 |
+
payload = {"model": req.model, "messages": req.messages, "max_tokens": req.max_tokens, "temperature": req.temperature}
|
| 281 |
+
async with httpx.AsyncClient(timeout=60.0) as client:
|
| 282 |
+
resp = await client.post(url, json=payload, headers=headers)
|
| 283 |
+
if resp.status_code != 200:
|
| 284 |
+
raise HTTPException(status_code=resp.status_code, detail=resp.text)
|
| 285 |
+
return resp.json()
|
| 286 |
+
|
| 287 |
+
|
| 288 |
# ββ Serve React frontend (static files built by Dockerfile) ββββββββββββββββββ
|
| 289 |
_static_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "static")
|
| 290 |
if os.path.isdir(_static_dir):
|