deepseek-proxy / app.py
Deploy Bot
Support both /v1/chat/completions and /chat/completions paths
db7241d
Raw
History Blame Contribute Delete
29.3 kB
"""
DeepSeek Web API Proxy Server (OpenAI-Compatible Gateway)
Hugging Face Space Edition
Version: 1.2.1
Description: Zero-dependency proxy mapping OpenAI completions to DeepSeek Web API
"""
import http.server
import socketserver
import json
import urllib.request
import urllib.error
import sys
import uuid
import struct
import binascii
import base64
import time
import threading
import traceback
import os
from collections import defaultdict
sys.stdout.reconfigure(encoding='utf-8')
# --- CONFIGURATION ---
PORT = int(os.environ.get("PORT", "7860"))
HOST = "0.0.0.0"
# Load token from env or file
def _load_token():
tok = os.environ.get("DEEPSEEK_TOKEN", "").strip()
if tok:
return tok
for path in ["token.txt", "/app/token.txt"]:
try:
with open(path, "r") as f:
tok = f.read().strip()
if tok:
return tok
except FileNotFoundError:
pass
return ""
USER_TOKEN = _load_token()
if not USER_TOKEN:
print("WARNING: DEEPSEEK_TOKEN not set! Set it in HF Secrets.")
print("Token format: oxMs/... (from browser at chat.deepseek.com)")
# --- SESSION MANAGEMENT ---
ACTIVE_SESSIONS = defaultdict(lambda: {"session_id": None, "message_history": []})
# Terminal Colors (disabled if no TTY)
class Colors:
if sys.stdout.isatty():
HEADER = '\033[95m'; BLUE = '\033[94m'; CYAN = '\033[96m'; GREEN = '\033[92m'
WARNING = '\033[93m'; FAIL = '\033[91m'; ENDC = '\033[0m'; BOLD = '\033[1m'
else:
HEADER = BLUE = CYAN = GREEN = WARNING = FAIL = ENDC = BOLD = ''
# --- HIGH PERFORMANCE DEEPSEEK POW SOLVER ---
RC = [
0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000,
0x000000000000808B, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
0x000000000000008A, 0x0000000000000088, 0x0000000080008009, 0x000000008000000A,
0x000000008000808B, 0x800000000000008B, 0x8000000000008089, 0x8000000000008003,
0x8000000000008002, 0x8000000000000080, 0x000000000000800A, 0x800000008000000A,
0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
]
def rotl64(v, k):
return ((v << k) | (v >> (64 - k))) & 0xffffffffffffffff
def keccakF23(s):
a0, a1, a2, a3, a4 = s[0], s[1], s[2], s[3], s[4]
a5, a6, a7, a8, a9 = s[5], s[6], s[7], s[8], s[9]
a10, a11, a12, a13, a14 = s[10], s[11], s[12], s[13], s[14]
a15, a16, a17, a18, a19 = s[15], s[16], s[17], s[18], s[19]
a20, a21, a22, a23, a24 = s[20], s[21], s[22], s[23], s[24]
for r in range(1, 24):
c0 = a0 ^ a5 ^ a10 ^ a15 ^ a20
c1 = a1 ^ a6 ^ a11 ^ a16 ^ a21
c2 = a2 ^ a7 ^ a12 ^ a17 ^ a22
c3 = a3 ^ a8 ^ a13 ^ a18 ^ a23
c4 = a4 ^ a9 ^ a14 ^ a19 ^ a24
d0 = c4 ^ rotl64(c1, 1)
d1 = c0 ^ rotl64(c2, 1)
d2 = c1 ^ rotl64(c3, 1)
d3 = c2 ^ rotl64(c4, 1)
d4 = c3 ^ rotl64(c0, 1)
a0 ^= d0; a5 ^= d0; a10 ^= d0; a15 ^= d0; a20 ^= d0
a1 ^= d1; a6 ^= d1; a11 ^= d1; a16 ^= d1; a21 ^= d1
a2 ^= d2; a7 ^= d2; a12 ^= d2; a17 ^= d2; a22 ^= d2
a3 ^= d3; a8 ^= d3; a13 ^= d3; a18 ^= d3; a23 ^= d3
a4 ^= d4; a9 ^= d4; a14 ^= d4; a19 ^= d4; a24 ^= d4
b0 = a0
b10 = rotl64(a1, 1)
b20 = rotl64(a2, 62)
b5 = rotl64(a3, 28)
b15 = rotl64(a4, 27)
b16 = rotl64(a5, 36)
b1 = rotl64(a6, 44)
b11 = rotl64(a7, 6)
b21 = rotl64(a8, 55)
b6 = rotl64(a9, 20)
b7 = rotl64(a10, 3)
b17 = rotl64(a11, 10)
b2 = rotl64(a12, 43)
b12 = rotl64(a13, 25)
b22 = rotl64(a14, 39)
b23 = rotl64(a15, 41)
b8 = rotl64(a16, 45)
b18 = rotl64(a17, 15)
b3 = rotl64(a18, 21)
b13 = rotl64(a19, 8)
b14 = rotl64(a20, 18)
b24 = rotl64(a21, 2)
b9 = rotl64(a22, 61)
b19 = rotl64(a23, 56)
b4 = rotl64(a24, 14)
a0 = b0 ^ ((~b1) & b2)
a1 = b1 ^ ((~b2) & b3)
a2 = b2 ^ ((~b3) & b4)
a3 = b3 ^ ((~b4) & b0)
a4 = b4 ^ ((~b0) & b1)
a5 = b5 ^ ((~b6) & b7)
a6 = b6 ^ ((~b7) & b8)
a7 = b7 ^ ((~b8) & b9)
a8 = b8 ^ ((~b9) & b5)
a9 = b9 ^ ((~b5) & b6)
a10 = b10 ^ ((~b11) & b12)
a11 = b11 ^ ((~b12) & b13)
a12 = b12 ^ ((~b13) & b14)
a13 = b13 ^ ((~b14) & b10)
a14 = b14 ^ ((~b10) & b11)
a15 = b15 ^ ((~b16) & b17)
a16 = b16 ^ ((~b17) & b18)
a17 = b17 ^ ((~b18) & b19)
a18 = b18 ^ ((~b19) & b15)
a19 = b19 ^ ((~b15) & b16)
a20 = b20 ^ ((~b21) & b22)
a21 = b21 ^ ((~b22) & b23)
a22 = b22 ^ ((~b23) & b24)
a23 = b23 ^ ((~b24) & b20)
a24 = b24 ^ ((~b20) & b21)
a0 &= 0xffffffffffffffff; a1 &= 0xffffffffffffffff; a2 &= 0xffffffffffffffff; a3 &= 0xffffffffffffffff; a4 &= 0xffffffffffffffff
a5 &= 0xffffffffffffffff; a6 &= 0xffffffffffffffff; a7 &= 0xffffffffffffffff; a8 &= 0xffffffffffffffff; a9 &= 0xffffffffffffffff
a10 &= 0xffffffffffffffff; a11 &= 0xffffffffffffffff; a12 &= 0xffffffffffffffff; a13 &= 0xffffffffffffffff; a14 &= 0xffffffffffffffff
a15 &= 0xffffffffffffffff; a16 &= 0xffffffffffffffff; a17 &= 0xffffffffffffffff; a18 &= 0xffffffffffffffff; a19 &= 0xffffffffffffffff
a20 &= 0xffffffffffffffff; a21 &= 0xffffffffffffffff; a22 &= 0xffffffffffffffff; a23 &= 0xffffffffffffffff; a24 &= 0xffffffffffffffff
a0 ^= RC[r]
s[0], s[1], s[2], s[3], s[4] = a0, a1, a2, a3, a4
s[5], s[6], s[7], s[8], s[9] = a5, a6, a7, a8, a9
s[10], s[11], s[12], s[13], s[14] = a10, a11, a12, a13, a14
s[15], s[16], s[17], s[18], s[19] = a15, a16, a17, a18, a19
s[20], s[21], s[22], s[23], s[24] = a20, a21, a22, a23, a24
def solve_pow(challenge_hex, salt, expire_at, difficulty):
target = binascii.unhexlify(challenge_hex)
t0, t1, t2, t3 = struct.unpack("<QQQQ", target)
prefix = f"{salt}_{expire_at}_".encode('utf-8')
rate = 136
# Pre-absorb the prefix state
base_state = [0] * 25
off = 0
while off + rate <= len(prefix):
for i in range(rate // 8):
val = struct.unpack_from("<Q", prefix, off + i * 8)[0]
base_state[i] ^= val
keccakF23(base_state)
off += rate
tail_len = len(prefix) - off
tail = bytearray(rate)
tail[:tail_len] = prefix[off:]
# Iterate through possible nonces
for n in range(difficulty):
num_str = str(n).encode('utf-8')
num_len = len(num_str)
s = list(base_state)
total_tail = tail_len + num_len
if total_tail < rate:
buf = bytearray(rate)
buf[:tail_len] = tail[:tail_len]
buf[tail_len:total_tail] = num_str
buf[total_tail] = 0x06
buf[rate - 1] |= 0x80
for i in range(rate // 8):
s[i] ^= struct.unpack_from("<Q", buf, i * 8)[0]
keccakF23(s)
else:
buf = bytearray(rate)
buf[:tail_len] = tail[:tail_len]
buf[tail_len:rate] = num_str[:rate - tail_len]
for i in range(rate // 8):
s[i] ^= struct.unpack_from("<Q", buf, i * 8)[0]
keccakF23(s)
buf2 = bytearray(rate)
rem = total_tail - rate
buf2[:rem] = num_str[rate - tail_len:]
buf2[rem] = 0x06
buf2[rate - 1] |= 0x80
for i in range(rate // 8):
s[i] ^= struct.unpack_from("<Q", buf2, i * 8)[0]
keccakF23(s)
if s[0] == t0 and s[1] == t1 and s[2] == t2 and s[3] == t3:
return n
raise ValueError("PoW: No solution found within difficulty range.")
# --- DEEPSEEK WEB API DRIVER ---
def create_chat_session():
url = "https://chat.deepseek.com/api/v0/chat_session/create"
headers = {
"Authorization": f"Bearer {USER_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Referer": "https://chat.deepseek.com/",
"Origin": "https://chat.deepseek.com",
"x-client-platform": "web",
"x-app-version": "20241129.1"
}
payload = json.dumps({"agent": "chat"}).encode('utf-8')
req = urllib.request.Request(url, data=payload, headers=headers, method="POST")
with urllib.request.urlopen(req, timeout=15) as response:
res_json = json.loads(response.read().decode('utf-8'))
if res_json.get("code") != 0:
raise ValueError(f"Failed to create session: {res_json.get('msg')}")
biz_data = res_json.get("data", {}).get("biz_data", {})
session_id = biz_data.get("id") or biz_data.get("chat_session", {}).get("id")
if not session_id:
raise ValueError("Failed to extract session id")
return session_id
POW_CACHE = {"header": None, "expires": 0}
POW_CACHE_LOCK = threading.Lock()
def get_pow_header(target_path="/api/v0/chat/completion"):
with POW_CACHE_LOCK:
if POW_CACHE["header"] and time.time() < POW_CACHE["expires"]:
print(f"{Colors.CYAN}⚑ Using cached PoW{Colors.ENDC}")
return POW_CACHE["header"]
url = "https://chat.deepseek.com/api/v0/chat/create_pow_challenge"
headers = {
"Authorization": f"Bearer {USER_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Referer": "https://chat.deepseek.com/",
"Origin": "https://chat.deepseek.com",
"x-client-platform": "web",
"x-app-version": "20241129.1"
}
payload = json.dumps({"target_path": target_path}).encode('utf-8')
req = urllib.request.Request(url, data=payload, headers=headers, method="POST")
with urllib.request.urlopen(req, timeout=15) as response:
res_json = json.loads(response.read().decode('utf-8'))
if res_json.get("code") != 0:
raise ValueError(f"Failed to fetch challenge: {res_json.get('msg')}")
challenge_data = res_json.get("data", {}).get("biz_data", {}).get("challenge", {})
algo = challenge_data.get("algorithm")
ch_hex = challenge_data.get("challenge")
salt = challenge_data.get("salt")
expire_at = challenge_data.get("expire_at")
difficulty = challenge_data.get("difficulty")
signature = challenge_data.get("signature")
t_path = challenge_data.get("target_path")
start_time = time.time()
print(f"{Colors.WARNING}⏳ Solving PoW (difficulty: {difficulty})...{Colors.ENDC}")
answer = solve_pow(ch_hex, salt, expire_at, difficulty)
elapsed = time.time() - start_time
print(f"{Colors.GREEN}βœ… Solved PoW! Answer: {answer} | Took {elapsed:.1f}s{Colors.ENDC}")
response_json = {
"algorithm": algo,
"challenge": ch_hex,
"salt": salt,
"answer": answer,
"signature": signature,
"target_path": t_path
}
pow_header = base64.b64encode(json.dumps(response_json).encode('utf-8')).decode('utf-8')
with POW_CACHE_LOCK:
POW_CACHE["header"] = pow_header
POW_CACHE["expires"] = time.time() + 300
print(f"{Colors.GREEN}πŸ’Ύ PoW cached for 5 minutes{Colors.ENDC}")
return pow_header
# --- OPENAI SPEC COMPLIANT GATEWAY ---
class ThreadedHTTPServer(socketserver.ThreadingMixIn, http.server.HTTPServer):
daemon_threads = True
allow_reuse_address = True
class OpenAICompatibleHandler(http.server.BaseHTTPRequestHandler):
def log_message(self, format, *args):
pass
def send_cors_headers(self):
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
self.send_header('Access-Control-Allow-Headers', 'Content-Type, Authorization, x-ds-pow-response')
def do_HEAD(self):
# Cline and other clients validate endpoints with HEAD requests before POSTing
chat_paths = ("/v1/chat/completions", "/chat/completions")
model_paths = ("/v1/models", "/models")
if self.path in model_paths + chat_paths + ("/health", "/healthz", "/", "/status"):
self.send_response(200)
self.send_cors_headers()
self.end_headers()
else:
self.send_response(404)
self.end_headers()
def do_OPTIONS(self):
self.send_response(200)
self.send_cors_headers()
self.end_headers()
def do_GET(self):
# Support both /models and /v1/models paths
path = self.path
if self.path == "/v1/models":
self.send_response(200)
self.send_cors_headers()
self.send_header('Content-Type', 'application/json')
self.end_headers()
models_data = {
"object": "list",
"data": [
{"id": "deepseek-chat", "object": "model", "created": 1700000000, "owned_by": "deepseek"},
{"id": "deepseek-reasoner", "object": "model", "created": 1700000000, "owned_by": "deepseek"}
]
}
self.wfile.write(json.dumps(models_data).encode('utf-8'))
elif self.path in ("/health", "/healthz"):
self.send_response(200)
self.send_cors_headers()
self.send_header('Content-Type', 'application/json')
self.end_headers()
health = {
"status": "healthy",
"service": "deepseek-proxy",
"timestamp": int(time.time()),
"token_configured": bool(USER_TOKEN),
"version": "1.2.1"
}
self.wfile.write(json.dumps(health).encode('utf-8'))
elif self.path in ("/", "/status"):
self.send_response(200)
self.send_cors_headers()
self.send_header('Content-Type', 'application/json')
self.end_headers()
status = {
"service": "DeepSeek Proxy (HF Space)",
"version": "1.2.1",
"endpoints": {
"chat": "POST /v1/chat/completions",
"models": "GET /v1/models",
"health": "GET /health"
},
"token_configured": bool(USER_TOKEN),
"instructions": "Set DEEPSEEK_TOKEN secret, then use with VS Code/Cline"
}
self.wfile.write(json.dumps(status).encode('utf-8'))
else:
self.send_response(404)
self.end_headers()
self.wfile.write(b"Not Found")
def do_POST(self):
# Support both /chat/completions and /v1/chat/completions paths
path = self.path
if self.path not in ("/v1/chat/completions", "/chat/completions"):
self.send_response(404)
self.end_headers()
self.wfile.write(b"Not Found")
return
if not USER_TOKEN:
self.send_error_response(500, "DEEPSEEK_TOKEN not configured. Set it in HF Space Settings -> Secrets.")
return
content_length = int(self.headers.get('Content-Length', 0))
post_data = self.rfile.read(content_length)
try:
req_body = json.loads(post_data.decode('utf-8'))
except Exception as e:
self.send_error_response(400, f"Invalid JSON: {e}")
return
messages = req_body.get("messages", [])
stream = req_body.get("stream", False)
model = req_body.get("model", "deepseek-chat")
conversation_id = req_body.get("conversation_id", "default")
thinking_enabled = (model == "deepseek-reasoner")
session_data = ACTIVE_SESSIONS[conversation_id]
prompt = ""
for msg in messages:
role = msg.get("role", "user")
content = msg.get("content", "")
if isinstance(content, list):
text_parts = []
for part in content:
if isinstance(part, dict):
pt = part.get("type", "text")
if pt == "text":
text_parts.append(part.get("text", ""))
elif pt == "file":
text_parts.append(f"\n```{part.get('name','file')}\n{part.get('content','')}\n```\n")
elif pt == "image_url":
text_parts.append("[Image: not supported]")
elif isinstance(part, str):
text_parts.append(part)
content = "".join(text_parts)
if role in ("system", "user", "assistant"):
prompt += f"{content}\n\n"
prompt = prompt.strip()
print(f"{Colors.BLUE}πŸ’¬ Request | Model: {model} | Stream: {stream}{Colors.ENDC}")
try:
if session_data["session_id"] is None:
session_id = create_chat_session()
session_data["session_id"] = session_id
print(f"{Colors.GREEN}πŸ†• Session: {session_id[:16]}...{Colors.ENDC}")
else:
session_id = session_data["session_id"]
print(f"{Colors.CYAN}♻️ Reusing session{Colors.ENDC}")
pow_header = get_pow_header()
except Exception as e:
traceback.print_exc()
self.send_error_response(500, f"Upstream setup error: {e}")
return
ds_headers = {
"Authorization": f"Bearer {USER_TOKEN}",
"Content-Type": "application/json",
"Accept": "text/event-stream",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Referer": "https://chat.deepseek.com/",
"Origin": "https://chat.deepseek.com",
"x-client-platform": "web",
"x-app-version": "20241129.1",
"x-ds-pow-response": pow_header
}
ds_payload = json.dumps({
"chat_session_id": session_id,
"prompt": prompt,
"parent_message_id": None,
"ref": "web",
"ref_file_ids": [],
"search_enabled": False,
"thinking_enabled": thinking_enabled
}).encode('utf-8')
ds_req = urllib.request.Request(
"https://chat.deepseek.com/api/v0/chat/completion",
data=ds_payload,
headers=ds_headers,
method="POST"
)
try:
response = urllib.request.urlopen(ds_req, timeout=90)
first_line = response.readline().decode('utf-8').strip()
if "INVALID_POW_RESPONSE" in first_line or "40301" in first_line:
response.close()
with POW_CACHE_LOCK:
POW_CACHE["header"] = None
POW_CACHE["expires"] = 0
pow_header = get_pow_header()
ds_headers["x-ds-pow-response"] = pow_header
ds_req = urllib.request.Request(
"https://chat.deepseek.com/api/v0/chat/completion",
data=ds_payload,
headers=ds_headers,
method="POST"
)
response = urllib.request.urlopen(ds_req, timeout=90)
print(f"{Colors.GREEN}πŸ”„ Retried with fresh PoW{Colors.ENDC}")
else:
class ResponseWithFirstLine:
def __init__(self, first_line, response):
self.first_line = first_line.encode('utf-8') + b'\n'
self.response = response
self.first_yielded = False
def __iter__(self):
if not self.first_yielded:
yield self.first_line
self.first_yielded = True
for line in self.response:
yield line
def close(self):
self.response.close()
response = ResponseWithFirstLine(first_line, response)
except urllib.error.HTTPError as e:
err_body = e.read().decode('utf-8') if e.fp else ""
print(f"{Colors.FAIL}❌ Upstream HTTP {e.code}: {err_body}{Colors.ENDC}")
self.send_error_response(e.code, f"Upstream error: {err_body}")
return
except Exception as e:
traceback.print_exc()
self.send_error_response(503, f"Failed to connect: {e}")
return
self.send_response(200)
self.send_cors_headers()
if stream:
self.send_header('Content-Type', 'text/event-stream')
self.send_header('Cache-Control', 'no-cache')
self.send_header('Connection', 'keep-alive')
self.end_headers()
self.stream_response(response, model)
else:
self.send_header('Content-Type', 'application/json')
self.end_headers()
self.blocking_response(response, model)
def stream_response(self, response, model):
created_time = int(time.time())
req_id = f"chatcmpl-{uuid.uuid4()}"
is_thinking = (model == "deepseek-reasoner")
try:
chunk_count = 0
for raw_line in response:
line = raw_line.decode('utf-8').strip()
if not line:
continue
if line.startswith("event:"):
event_name = line[6:].strip()
if event_name in ("close", "finish"):
break
continue
if not line.startswith("data:"):
continue
data_str = line[5:].strip()
if data_str == "[DONE]":
break
try:
ds_chunk = json.loads(data_str)
except:
continue
p_val = ds_chunk.get("p")
v_val = ds_chunk.get("v")
if p_val in ("response/accumulated_token_usage", "response/status"):
if p_val == "response/status" and v_val == "FINISHED":
break
continue
if p_val == "response/thinking_elapsed_secs":
is_thinking = False
continue
elif p_val == "response/content":
is_thinking = False
if isinstance(v_val, str):
self.send_openai_chunk(req_id, created_time, model, v_val, None, None)
continue
if isinstance(v_val, str):
chunk_count += 1
if is_thinking:
self.send_openai_chunk(req_id, created_time, model, None, v_val, None)
else:
self.send_openai_chunk(req_id, created_time, model, v_val, None, None)
self.send_openai_chunk(req_id, created_time, model, None, None, "stop")
self.wfile.write(b"data: [DONE]\n\n")
self.wfile.flush()
print(f"{Colors.GREEN}>> Stream done. {chunk_count} chunks{Colors.ENDC}")
except Exception as e:
print(f"{Colors.FAIL}>> Stream error: {e}{Colors.ENDC}")
finally:
response.close()
def send_openai_chunk(self, req_id, created_time, model, content, reasoning_content, finish_reason):
delta = {}
if content is not None:
delta["content"] = content
if reasoning_content is not None:
delta["reasoning_content"] = reasoning_content
chunk_payload = {
"id": req_id,
"object": "chat.completion.chunk",
"created": created_time,
"model": model,
"choices": [{"index": 0, "delta": delta, "finish_reason": finish_reason}]
}
sse_str = f"data: {json.dumps(chunk_payload)}\n\n"
self.wfile.write(sse_str.encode('utf-8'))
self.wfile.flush()
def blocking_response(self, response, model):
created_time = int(time.time())
req_id = f"chatcmpl-{uuid.uuid4()}"
full_content = ""
full_reasoning = ""
is_thinking = (model == "deepseek-reasoner")
try:
for raw_line in response:
line = raw_line.decode('utf-8').strip()
if not line:
continue
if line.startswith("event:"):
event_name = line[6:].strip()
if event_name in ("close", "finish"):
break
continue
if not line.startswith("data:"):
continue
data_str = line[5:].strip()
if data_str == "[DONE]":
break
try:
ds_chunk = json.loads(data_str)
except:
continue
p_val = ds_chunk.get("p")
v_val = ds_chunk.get("v")
if p_val in ("response/accumulated_token_usage", "response/status"):
if p_val == "response/status" and v_val == "FINISHED":
break
continue
if p_val == "response/thinking_elapsed_secs":
is_thinking = False
continue
elif p_val == "response/content":
is_thinking = False
if isinstance(v_val, str):
full_content += v_val
continue
if isinstance(v_val, str):
if is_thinking:
full_reasoning += v_val
else:
full_content += v_val
print(f"{Colors.GREEN}βœ… Blocking response: {len(full_content)} chars content{Colors.ENDC}")
res_payload = {
"id": req_id,
"object": "chat.completion",
"created": created_time,
"model": model,
"choices": [{
"index": 1,
"message": {
"role": "assistant",
"content": full_content,
"reasoning_content": full_reasoning if full_reasoning else None
},
"finish_reason": "stop"
}],
"usage": {
"prompt_tokens": len(full_content) // 4 + 10,
"completion_tokens": len(full_content) // 4,
"total_tokens": (len(full_content) // 4) * 2 + 10
}
}
self.wfile.write(json.dumps(res_payload).encode('utf-8'))
except Exception as e:
traceback.print_exc()
self.send_error_response(500, f"Error gathering response: {e}")
finally:
response.close()
def send_error_response(self, code, message):
self.send_response(code)
self.send_cors_headers()
self.send_header('Content-Type', 'application/json')
self.end_headers()
err_payload = {"error": {"message": message, "type": "api_error", "code": code}}
self.wfile.write(json.dumps(err_payload).encode('utf-8'))
# --- SERVER START ---
def start_server():
print(f"\n{Colors.HEADER}{Colors.BOLD}==================================================={Colors.ENDC}")
print(f"{Colors.CYAN}{Colors.BOLD} πŸš€ DEEPSEEK PROXY - HUGGING FACE SPACE EDITION πŸš€{Colors.ENDC}")
print(f"{Colors.HEADER}{Colors.BOLD}==================================================={Colors.ENDC}")
print(f"πŸ“‘ Endpoint: {Colors.BOLD}http://{HOST}:{PORT}/v1{Colors.ENDC}")
print(f"πŸ”‘ Token: {Colors.WARNING}{'βœ… Configured' if USER_TOKEN else '❌ NOT SET'}{Colors.ENDC}")
print(f"🧠 Models: {Colors.GREEN}deepseek-chat, deepseek-reasoner{Colors.ENDC}")
print(f"πŸ›‘οΈ PoW Engine: {Colors.GREEN}Keccak solver (cached 5 min){Colors.ENDC}")
print(f"πŸ“Š Health: {Colors.BOLD}GET /health{Colors.ENDC}")
print(f"{Colors.HEADER}==================================================={Colors.ENDC}\n")
server_address = (HOST, PORT)
try:
with ThreadedHTTPServer(server_address, OpenAICompatibleHandler) as httpd:
print(f"{Colors.GREEN}πŸ”₯ Server running on {HOST}:{PORT}{Colors.ENDC}")
httpd.serve_forever()
except KeyboardInterrupt:
print(f"\n{Colors.WARNING}⚠️ Shutting down...{Colors.ENDC}")
except Exception as e:
print(f"\n{Colors.FAIL}❌ Server error: {e}{Colors.ENDC}")
sys.exit(1)
if __name__ == "__main__":
start_server()