autoreg-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
141
skills/account-validation/templates/local-llm-proxy.py
Normal file
141
skills/account-validation/templates/local-llm-proxy.py
Normal file
@@ -0,0 +1,141 @@
|
||||
"""
|
||||
OpenAI-compatible proxy on localhost:8080
|
||||
Backend: dashscope deepseek-v4-pro (HERMES_DASHSCOPE_API_KEY)
|
||||
Auth: Bearer token check
|
||||
|
||||
Usage:
|
||||
python proxy_handler.py
|
||||
|
||||
Endpoints:
|
||||
GET /v1/models — list available models
|
||||
POST /v1/chat/completions — forward to dashscope (streaming supported)
|
||||
GET /health — health check (no auth needed)
|
||||
"""
|
||||
import json, sys, os, time, uuid, ssl
|
||||
from pathlib import Path
|
||||
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||
import urllib.request, urllib.error
|
||||
|
||||
PORT = 8080
|
||||
TOKEN = [REDACTED]"PROXY_TOKEN", "your-token-here")
|
||||
BACKENDS = [
|
||||
{
|
||||
"url": "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
|
||||
"key": os.environ.get("HERMES_DASHSCOPE_API_KEY", ""),
|
||||
"model": "deepseek-v4-pro"
|
||||
},
|
||||
{
|
||||
"url": "https://api.openai.com/v1/chat/completions",
|
||||
"key": os.environ.get("OPENAI_API_KEY", ""),
|
||||
"model": "gpt-4o"
|
||||
}
|
||||
]
|
||||
|
||||
class ProxyHandler(BaseHTTPRequestHandler):
|
||||
def do_GET(self): self.proxy()
|
||||
def do_POST(self): self.proxy()
|
||||
def do_OPTIONS(self):
|
||||
self.send_response(200)
|
||||
self.send_header('Access-Control-Allow-Origin', '*')
|
||||
self.send_header('Access-Control-Allow-Methods', 'GET,POST,OPTIONS')
|
||||
self.send_header('Access-Control-Allow-Headers', '*')
|
||||
self.end_headers()
|
||||
|
||||
def proxy(self):
|
||||
auth = self.headers.get('Authorization', '')
|
||||
if auth != f'Bearer {TOKEN}':
|
||||
self.send_response(401); self.end_headers()
|
||||
self.wfile.write(b'{"error":"Unauthorized"}'); return
|
||||
|
||||
path = self.path
|
||||
|
||||
if path == '/v1/models':
|
||||
self.send_response(200)
|
||||
self.send_header('Content-Type', 'application/json')
|
||||
self.send_header('Access-Control-Allow-Origin', '*')
|
||||
self.end_headers()
|
||||
self.wfile.write(json.dumps({
|
||||
"object": "list",
|
||||
"data": [{"id": b['model'], "object": "model", "owned_by": "proxy"}
|
||||
for b in BACKENDS if b['key']]
|
||||
}).encode())
|
||||
return
|
||||
|
||||
if path == '/v1/chat/completions':
|
||||
self.handle_chat(); return
|
||||
|
||||
if path == '/health':
|
||||
self.send_response(200); self.end_headers()
|
||||
self.wfile.write(b'{"status":"ok"}'); return
|
||||
|
||||
self.send_response(404); self.end_headers()
|
||||
self.wfile.write(b'{"error":"Not found"}')
|
||||
|
||||
def handle_chat(self):
|
||||
cl = int(self.headers.get('Content-Length', 0))
|
||||
body = json.loads(self.rfile.read(cl))
|
||||
stream = body.get('stream', False)
|
||||
|
||||
# Find first working backend
|
||||
backend = None
|
||||
for b in BACKENDS:
|
||||
if b['key']:
|
||||
backend = b; break
|
||||
|
||||
if not backend:
|
||||
self.send_response(502); self.end_headers()
|
||||
self.wfile.write(b'{"error":"No backend configured"}'); return
|
||||
|
||||
data = {
|
||||
"model": backend['model'],
|
||||
"messages": body.get('messages', []),
|
||||
"stream": stream,
|
||||
"temperature": body.get('temperature', 0.7),
|
||||
"max_tokens": body.get('max_tokens', 4096)
|
||||
}
|
||||
|
||||
try:
|
||||
ctx = ssl.create_default_context()
|
||||
req = urllib.request.Request(
|
||||
backend['url'],
|
||||
data=json.dumps(data).encode(),
|
||||
method='POST'
|
||||
)
|
||||
req.add_header('Content-Type', 'application/json')
|
||||
req.add_header('Authorization', f'Bearer {backend["key"]}')
|
||||
|
||||
if stream:
|
||||
self.send_response(200)
|
||||
self.send_header('Content-Type', 'text/event-stream')
|
||||
self.send_header('Cache-Control', 'no-cache')
|
||||
self.send_header('Access-Control-Allow-Origin', '*')
|
||||
self.end_headers()
|
||||
resp = urllib.request.urlopen(req, timeout=120, context=ctx)
|
||||
for line_bytes in resp:
|
||||
self.wfile.write(line_bytes); self.wfile.flush()
|
||||
else:
|
||||
resp = urllib.request.urlopen(req, timeout=120, context=ctx)
|
||||
rb = resp.read()
|
||||
self.send_response(resp.status)
|
||||
self.send_header('Content-Type', 'application/json')
|
||||
self.send_header('Access-Control-Allow-Origin', '*')
|
||||
self.end_headers()
|
||||
self.wfile.write(rb)
|
||||
except urllib.error.HTTPError as e:
|
||||
self.send_response(e.code)
|
||||
self.send_header('Content-Type', 'application/json')
|
||||
self.send_header('Access-Control-Allow-Origin', '*')
|
||||
self.end_headers()
|
||||
self.wfile.write(e.read())
|
||||
except Exception as e:
|
||||
self.send_response(500); self.end_headers()
|
||||
self.wfile.write(json.dumps({"error": str(e)}).encode())
|
||||
|
||||
def start_proxy():
|
||||
print(f"\n[PROXY] http://127.0.0.1:{PORT}")
|
||||
print(f"[PROXY] Auth: Bearer {TOKEN[:10]}...")
|
||||
print(f"[PROXY] Backends: {[b['model'] for b in BACKENDS if b['key']]}")
|
||||
HTTPServer(('0.0.0.0', PORT), ProxyHandler).serve_forever()
|
||||
|
||||
if __name__ == '__main__':
|
||||
start_proxy()
|
||||
Reference in New Issue
Block a user