Spaces:
Paused
Paused
File size: 3,348 Bytes
dcdc87a 4141a22 dcdc87a 4141a22 dcdc87a 4141a22 dcdc87a 4141a22 dcdc87a 4141a22 dcdc87a | 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 | #!/usr/bin/env python3
"""
SmilyAI Proxy β runs on a HF Space.
Forwards authenticated requests to a private HF Inference Endpoint.
Exists because PythonAnywhere's free tier can't reach arbitrary outbound
hosts, but *.hf.space IS whitelisted.
"""
import os
import json
import requests
from flask import Flask, request, Response, jsonify
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
# ββ Config (set these as SECRETS in the Space settings, not hardcoded!) ββββββ
TARGET_BASE_URL = os.environ.get("TARGET_BASE_URL", "").rstrip("/")
HF_TOKEN = os.environ.get("HF_TOKEN", "")
PROXY_SECRET = os.environ.get("PROXY_SECRET", "") # shared secret w/ your Flask app
if not TARGET_BASE_URL or not HF_TOKEN or not PROXY_SECRET:
print("β WARNING: TARGET_BASE_URL / HF_TOKEN / PROXY_SECRET not fully set!")
def check_auth(req) -> bool:
key = req.headers.get("X-Proxy-Key", "")
return PROXY_SECRET and key == PROXY_SECRET
@app.route("/", methods=["GET"])
def health():
return jsonify({"status": "ok", "service": "smilyai-proxy"})
@app.route("/v1/chat/completions", methods=["POST"])
def chat_completions():
if not check_auth(request):
return jsonify({"error": "unauthorized"}), 401
try:
payload = request.get_json(force=True)
except Exception:
return jsonify({"error": "invalid json body"}), 400
is_stream = bool(payload.get("stream", False))
headers = {
"Authorization": f"Bearer {HF_TOKEN}",
"Content-Type": "application/json; charset=utf-8", # β add charset here
}
url = f"{TARGET_BASE_URL}/chat/completions"
if not is_stream:
try:
r = requests.post(url, headers=headers, json=payload, timeout=120)
return Response(
r.content,
status=r.status_code,
content_type="application/json; charset=utf-8" # β fix here too
)
except Exception as e:
return jsonify({"error": str(e)}), 502
def generate():
try:
with requests.post(
url, headers=headers, json=payload,
stream=True, timeout=120
) as r:
# β KEY FIX: iter_lines with encoding="utf-8" explicitly
for raw_line in r.iter_lines(decode_unicode=False):
if raw_line is None:
continue
# decode bytes as utf-8 explicitly
if isinstance(raw_line, bytes):
line = raw_line.decode("utf-8", errors="replace")
else:
line = raw_line
if not line:
continue
yield (line + "\n\n").encode("utf-8")
except Exception as e:
err = json.dumps({"error": str(e)}, ensure_ascii=False)
yield f"data: {err}\n\n".encode("utf-8")
yield b"data: [DONE]\n\n"
return Response(
generate(),
content_type="text/event-stream; charset=utf-8", # β charset here
headers={
"Cache-Control": "no-cache",
"X-Accel-Buffering": "no",
"Transfer-Encoding": "chunked",
}
)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 7860))) |