File size: 7,902 Bytes
ef881c7 e406d5a 9c93dcd ef881c7 e406d5a ef881c7 e406d5a ef881c7 e406d5a ef881c7 e406d5a ef881c7 e406d5a ef881c7 e406d5a ef881c7 e406d5a ef881c7 e406d5a ef881c7 e406d5a ef881c7 e406d5a ef881c7 e406d5a ef881c7 |
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 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
import json
import time
import hashlib
import base64
import asyncio
import aiohttp
from fastapi import FastAPI, Request, Response
from typing import Optional, Dict, List, Any
import uvicorn
from pydantic import BaseModel
# Configuration
API_CHALLENGE_URL = 'https://api.eqing.tech/api/altcaptcha/challenge'
NEXTWAY_CHAT_URL = 'https://origin.eqing.tech/api/openai/v1/chat/completions'
CREDENTIAL_EXPIRY_MARGIN = 60 * 1000
PORT = 7860
API_ENDPOINT = '/v1/chat/completions'
MODEL_NAME = "gpt-4o-free"
REQUEST_TIMEOUT = 480
MAX_RETRIES = 3
RETRY_DELAY = 1
# Global variables
current_credential = None
credential_expiry = None
is_refreshing_credential = False
MODEL_MAPPING = {
'gpt-4o-all-lite': 'gpt-4o-mini',
'gpt-4o-image': 'gpt-4o-mini-image-free',
'grok-3-re': 'grok-3-free',
'gemini-2.0-flash': 'gemini-2.0-flash-free'
}
app = FastAPI()
class ChatRequest(BaseModel):
messages: List[Dict[str, str]]
model: Optional[str]
stream: Optional[bool] = True
temperature: Optional[float] = 0.5
presence_penalty: Optional[float] = 0
frequency_penalty: Optional[float] = 0
top_p: Optional[float] = 1
max_tokens: Optional[int] = 4000
async def extract_streaming_content(response):
buffer = ""
complete_response = ""
async for chunk in response.content:
buffer += chunk.decode()
lines = buffer.split('\n')
# Process complete lines
for line in lines[:-1]:
line = line.strip()
if line.startswith('data: '):
content = process_data_line(line[5:].strip())
if content:
complete_response += content
# Keep the last incomplete line in buffer
buffer = lines[-1] if lines else ""
# Process any remaining data
if buffer:
line = buffer.strip()
if line.startswith('data: '):
content = process_data_line(line[5:].strip())
if content:
complete_response += content
return complete_response
def process_data_line(data_str: str) -> str:
if not data_str or data_str in ['[ORIGIN]', '[DONE]']:
return ''
try:
json_data = json.loads(data_str)
if (json_data.get('choices') and
json_data['choices'][0].get('delta') and
'content' in json_data['choices'][0]['delta']):
return json_data['choices'][0]['delta']['content']
except json.JSONDecodeError:
print(f'Invalid JSON data: {data_str}')
return ''
async def solve_challenge(challenge: str, salt: str, algorithm: str = "SHA-512", max_number: int = 1000000):
start_time = time.time()
for number in range(max_number):
hash_value = await verify_hash(salt, number, algorithm)
if hash_value == challenge:
return {"number": number, "took": int((time.time() - start_time) * 1000)}
return None
async def verify_hash(salt: str, number: int, algorithm: str) -> str:
input_str = f"{salt}{number}"
if algorithm == "SHA-512":
hash_obj = hashlib.sha512(input_str.encode())
return hash_obj.hexdigest()
elif algorithm == "SHA-256":
hash_obj = hashlib.sha256(input_str.encode())
return hash_obj.hexdigest()
else:
raise ValueError(f"Unsupported algorithm: {algorithm}")
async def generate_credential():
global current_credential, credential_expiry
async with aiohttp.ClientSession() as session:
try:
async with session.get(API_CHALLENGE_URL) as response:
if response.status != 200:
print(f"Challenge request failed with status {response.status}")
return None
data = await response.json()
solution = await solve_challenge(
data['challenge'],
data['salt'],
data['algorithm'],
data['maxnumber']
)
if not solution:
print("Failed to solve challenge")
return None
credential_obj = {
"algorithm": data['algorithm'],
"challenge": data['challenge'],
"number": solution['number'],
"salt": data['salt'],
"signature": data['signature'],
"took": solution['took']
}
credential = base64.b64encode(json.dumps(credential_obj).encode()).decode()
expiry = int(data['salt'].split('?expires=')[1]) * 1000
return {"credential": credential, "expiry": expiry}
except Exception as e:
print(f"Error generating credential: {e}")
return None
async def get_credential():
global current_credential, credential_expiry, is_refreshing_credential
if (not current_credential or
not credential_expiry or
credential_expiry <= time.time() * 1000 + CREDENTIAL_EXPIRY_MARGIN):
if not is_refreshing_credential:
is_refreshing_credential = True
try:
cred_data = await generate_credential()
if cred_data:
current_credential = cred_data['credential']
credential_expiry = cred_data['expiry']
finally:
is_refreshing_credential = False
else:
await asyncio.sleep(2)
return current_credential
async def handle_chat_request(model: str, messages: List[Dict[str, str]], retries=0):
captcha_token = await get_credential()
if not captcha_token:
return None
body = {
"messages": messages,
"stream": True,
"model": model,
"temperature": 0.5,
"presence_penalty": 0,
"frequency_penalty": 0,
"top_p": 1,
"max_tokens": 4000,
"captchaToken": captcha_token
}
async with aiohttp.ClientSession() as session:
try:
async with session.post(
NEXTWAY_CHAT_URL,
json=body,
timeout=aiohttp.ClientTimeout(total=REQUEST_TIMEOUT)
) as response:
if response.status != 200:
if retries < MAX_RETRIES:
await asyncio.sleep(RETRY_DELAY)
return await handle_chat_request(model, messages, retries + 1)
return None
return await extract_streaming_content(response)
except (aiohttp.ClientError, asyncio.TimeoutError) as e:
print(f"Error in chat request: {e}")
if retries < MAX_RETRIES:
await asyncio.sleep(RETRY_DELAY)
return await handle_chat_request(model, messages, retries + 1)
return None
@app.post(API_ENDPOINT)
async def chat_endpoint(request: ChatRequest):
try:
model = MODEL_MAPPING.get(request.model, request.model or MODEL_NAME)
response_content = await handle_chat_request(model, request.messages)
if response_content is None:
return Response(
content="Failed to get response from API",
status_code=500
)
return {
"choices": [{
"message": {
"role": "assistant",
"content": response_content.strip()
},
"finish_reason": "stop",
"index": 0
}],
"model": model,
"object": "chat.completion"
}
except Exception as e:
print(f"Error handling chat request: {e}")
return Response(content="Internal server error", status_code=500)
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=PORT) |