Spaces:
mxrkai
/
Runtime error

test24 / api /utils.py
Niansuh's picture
Update api/utils.py
c0e5311 verified
raw
history blame
19.9 kB
from datetime import datetime
import json
import uuid
import asyncio
import random
import string
import time
import re
from typing import Any, Dict, Optional
import os
import requests
import httpx
from fastapi import HTTPException
from api.models import ChatRequest
from api.logger import setup_logger
logger = setup_logger(__name__)
# Load environment variables
from dotenv import load_dotenv
load_dotenv()
# Base URL
BASE_URL = "https://www.blackbox.ai"
APP_SECRET = os.getenv("APP_SECRET")
# Allowed models (copy from your config.py)
ALLOWED_MODELS = [
{"id": "blackboxai", "name": "blackboxai"},
{"id": "blackboxai-pro", "name": "blackboxai-pro"},
{"id": "flux", "name": "flux"},
{"id": "llama-3.1-8b", "name": "llama-3.1-8b"},
{"id": "llama-3.1-70b", "name": "llama-3.1-70b"},
{"id": "llama-3.1-405b", "name": "llama-3.1-405"},
{"id": "gpt-4o", "name": "gpt-4o"},
{"id": "gemini-pro", "name": "gemini-pro"},
{"id": "gemini-1.5-flash", "name": "gemini-1.5-flash"},
{"id": "claude-sonnet-3.5", "name": "claude-sonnet-3.5"},
{"id": "PythonAgent", "name": "PythonAgent"},
{"id": "JavaAgent", "name": "JavaAgent"},
{"id": "JavaScriptAgent", "name": "JavaScriptAgent"},
{"id": "HTMLAgent", "name": "HTMLAgent"},
{"id": "GoogleCloudAgent", "name": "GoogleCloudAgent"},
{"id": "AndroidDeveloper", "name": "AndroidDeveloper"},
{"id": "SwiftDeveloper", "name": "SwiftDeveloper"},
{"id": "Next.jsAgent", "name": "Next.jsAgent"},
{"id": "MongoDBAgent", "name": "MongoDBAgent"},
{"id": "PyTorchAgent", "name": "PyTorchAgent"},
{"id": "ReactAgent", "name": "ReactAgent"},
{"id": "XcodeAgent", "name": "XcodeAgent"},
{"id": "AngularJSAgent", "name": "AngularJSAgent"},
{"id": "HerokuAgent", "name": "HerokuAgent"},
{"id": "GodotAgent", "name": "GodotAgent"},
{"id": "GoAgent", "name": "GoAgent"},
{"id": "GitlabAgent", "name": "GitlabAgent"},
{"id": "GitAgent", "name": "GitAgent"},
{"id": "RepoMap", "name": "RepoMap"},
{"id": "gemini-1.5-pro-latest", "name": "gemini-pro"},
{"id": "gemini-1.5-pro", "name": "gemini-1.5-pro"},
{"id": "claude-3-5-sonnet-20240620", "name": "claude-sonnet-3.5"},
{"id": "claude-3-5-sonnet", "name": "claude-sonnet-3.5"},
{"id": "Niansuh", "name": "Niansuh"},
{"id": "o1-preview", "name": "o1-preview"},
{"id": "claude-3-5-sonnet-20241022", "name": "claude-3-5-sonnet-20241022"},
{"id": "claude-3-5-sonnet-x", "name": "claude-3-5-sonnet-x"},
# Added New Agents
{"id": "FlaskAgent", "name": "FlaskAgent"},
{"id": "FirebaseAgent", "name": "FirebaseAgent"},
{"id": "FastAPIAgent", "name": "FastAPIAgent"},
{"id": "ErlangAgent", "name": "ErlangAgent"},
{"id": "ElectronAgent", "name": "ElectronAgent"},
{"id": "DockerAgent", "name": "DockerAgent"},
{"id": "DigitalOceanAgent", "name": "DigitalOceanAgent"},
{"id": "BitbucketAgent", "name": "BitbucketAgent"},
{"id": "AzureAgent", "name": "AzureAgent"},
{"id": "FlutterAgent", "name": "FlutterAgent"},
{"id": "YoutubeAgent", "name": "YoutubeAgent"},
{"id": "builderAgent", "name": "builderAgent"},
]
# Model mapping
MODEL_MAPPING = {
"blackboxai": "blackboxai",
"blackboxai-pro": "blackboxai-pro",
"flux": "flux",
"ImageGeneration": "flux",
"llama-3.1-8b": "llama-3.1-8b",
"llama-3.1-70b": "llama-3.1-70b",
"llama-3.1-405b": "llama-3.1-405",
"gpt-4o": "gpt-4o",
"gemini-pro": "gemini-pro",
"gemini-1.5-flash": "gemini-1.5-flash",
"claude-sonnet-3.5": "claude-sonnet-3.5",
"PythonAgent": "PythonAgent",
"JavaAgent": "JavaAgent",
"JavaScriptAgent": "JavaScriptAgent",
"HTMLAgent": "HTMLAgent",
"GoogleCloudAgent": "GoogleCloudAgent",
"AndroidDeveloper": "AndroidDeveloper",
"SwiftDeveloper": "SwiftDeveloper",
"Next.jsAgent": "Next.jsAgent",
"MongoDBAgent": "MongoDBAgent",
"PyTorchAgent": "PyTorchAgent",
"ReactAgent": "ReactAgent",
"XcodeAgent": "XcodeAgent",
"AngularJSAgent": "AngularJSAgent",
"HerokuAgent": "HerokuAgent",
"GodotAgent": "GodotAgent",
"GoAgent": "GoAgent",
"GitlabAgent": "GitlabAgent",
"GitAgent": "GitAgent",
"RepoMap": "RepoMap",
# Additional mappings
"gemini-flash": "gemini-1.5-flash",
"claude-3.5-sonnet": "claude-sonnet-3.5",
"gemini-1.5-pro-latest": "gemini-pro",
"gemini-1.5-pro": "gemini-1.5-pro",
"claude-3-5-sonnet-20240620": "claude-sonnet-3.5",
"claude-3-5-sonnet": "claude-sonnet-3.5",
"Niansuh": "Niansuh",
"o1-preview": "o1-preview",
"claude-3-5-sonnet-20241022": "claude-3-5-sonnet-20241022",
"claude-3-5-sonnet-x": "claude-3-5-sonnet-x",
# Added New Agents
"FlaskAgent": "FlaskAgent",
"FirebaseAgent": "FirebaseAgent",
"FastAPIAgent": "FastAPIAgent",
"ErlangAgent": "ErlangAgent",
"ElectronAgent": "ElectronAgent",
"DockerAgent": "DockerAgent",
"DigitalOceanAgent": "DigitalOceanAgent",
"BitbucketAgent": "BitbucketAgent",
"AzureAgent": "AzureAgent",
"FlutterAgent": "FlutterAgent",
"YoutubeAgent": "YoutubeAgent",
"builderAgent": "builderAgent",
}
# Agent modes
AGENT_MODE = {
'flux': {'mode': True, 'id': "ImageGenerationLV45LJp", 'name': "flux"},
'Niansuh': {'mode': True, 'id': "NiansuhAIk1HgESy", 'name': "Niansuh"},
'o1-preview': {'mode': True, 'id': "o1Dst8La8", 'name': "o1-preview"},
'claude-3-5-sonnet-20241022': {'mode': True, 'id': "Claude-Sonnet-3.5zO2HZSF", 'name': "claude-3-5-sonnet-20241022"},
'claude-3-5-sonnet-x': {'mode': True, 'id': "Claude-Sonnet-3.52022JE0UdQ3", 'name': "claude-3-5-sonnet-x"},
}
# Trending agent modes
TRENDING_AGENT_MODE = {
"blackboxai": {},
"gemini-1.5-flash": {'mode': True, 'id': 'Gemini'},
"llama-3.1-8b": {'mode': True, 'id': "llama-3.1-8b"},
'llama-3.1-70b': {'mode': True, 'id': "llama-3.1-70b"},
'llama-3.1-405b': {'mode': True, 'id': "llama-3.1-405"},
'blackboxai-pro': {'mode': True, 'id': "BLACKBOXAI-PRO"},
'PythonAgent': {'mode': True, 'id': "Python Agent"},
'JavaAgent': {'mode': True, 'id': "Java Agent"},
'JavaScriptAgent': {'mode': True, 'id': "JavaScript Agent"},
'HTMLAgent': {'mode': True, 'id': "HTML Agent"},
'GoogleCloudAgent': {'mode': True, 'id': "Google Cloud Agent"},
'AndroidDeveloper': {'mode': True, 'id': "Android Developer"},
'SwiftDeveloper': {'mode': True, 'id': "Swift Developer"},
'Next.jsAgent': {'mode': True, 'id': "Next.js Agent"},
'MongoDBAgent': {'mode': True, 'id': "MongoDB Agent"},
'PyTorchAgent': {'mode': True, 'id': "PyTorch Agent"},
'ReactAgent': {'mode': True, 'id': "React Agent"},
'XcodeAgent': {'mode': True, 'id': "Xcode Agent"},
'AngularJSAgent': {'mode': True, 'id': "AngularJS Agent"},
'HerokuAgent': {'mode': True, 'id': "HerokuAgent"},
'GodotAgent': {'mode': True, 'id': "GodotAgent"},
'GoAgent': {'mode': True, 'id': "GoAgent"},
'GitlabAgent': {'mode': True, 'id': "GitlabAgent"},
'GitAgent': {'mode': True, 'id': "GitAgent"},
'RepoMap': {'mode': True, 'id': "repomap"},
# Added New Agents
'FlaskAgent': {'mode': True, 'id': "FlaskAgent"},
'FirebaseAgent': {'mode': True, 'id': "FirebaseAgent"},
'FastAPIAgent': {'mode': True, 'id': "FastAPIAgent"},
'ErlangAgent': {'mode': True, 'id': "ErlangAgent"},
'ElectronAgent': {'mode': True, 'id': "ElectronAgent"},
'DockerAgent': {'mode': True, 'id': "DockerAgent"},
'DigitalOceanAgent': {'mode': True, 'id': "DigitalOceanAgent"},
'BitbucketAgent': {'mode': True, 'id': "BitbucketAgent"},
'AzureAgent': {'mode': True, 'id': "AzureAgent"},
'FlutterAgent': {'mode': True, 'id': "FlutterAgent"},
'YoutubeAgent': {'mode': True, 'id': "YoutubeAgent"},
'builderAgent': {'mode': True, 'id': "builderAgent"},
}
# Model prefixes
MODEL_PREFIXES = {
'gpt-4o': '@GPT-4o',
'gemini-pro': '@Gemini-PRO',
'PythonAgent': '@Python Agent',
'JavaAgent': '@Java Agent',
'JavaScriptAgent': '@JavaScript Agent',
'HTMLAgent': '@HTML Agent',
'GoogleCloudAgent': '@Google Cloud Agent',
'AndroidDeveloper': '@Android Developer',
'SwiftDeveloper': '@Swift Developer',
'Next.jsAgent': '@Next.js Agent',
'MongoDBAgent': '@MongoDB Agent',
'PyTorchAgent': '@PyTorch Agent',
'ReactAgent': '@React Agent',
'XcodeAgent': '@Xcode Agent',
'AngularJSAgent': '@AngularJS Agent',
'HerokuAgent': '@Heroku Agent',
'GodotAgent': '@Godot Agent',
'GoAgent': '@Go Agent',
'GitlabAgent': '@Gitlab Agent',
'GitAgent': '@Gitlab Agent',
'blackboxai-pro': '@BLACKBOXAI-PRO',
'flux': '@Image Generation',
# Added New Agents
'FlaskAgent': '@Flask Agent',
'FirebaseAgent': '@Firebase Agent',
'FastAPIAgent': '@FastAPI Agent',
'ErlangAgent': '@Erlang Agent',
'ElectronAgent': '@Electron Agent',
'DockerAgent': '@Docker Agent',
'DigitalOceanAgent': '@DigitalOcean Agent',
'BitbucketAgent': '@Bitbucket Agent',
'AzureAgent': '@Azure Agent',
'FlutterAgent': '@Flutter Agent',
'YoutubeAgent': '@Youtube Agent',
'builderAgent': '@builder Agent',
}
# Cache variables for getHid function
cached_hid = None
cache_time = 0
CACHE_DURATION = 36000 # 10 hours
# Headers for HTTP requests
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
'AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/130.0.0.0 Safari/537.36',
'Content-Type': 'application/json',
}
def getHid(force_refresh=False):
global cached_hid, cache_time
current_time = time.time()
# Check if we need to refresh or cache is valid
if not force_refresh and cached_hid and (current_time - cache_time) < CACHE_DURATION:
logger.info(f"Using cached_hid: {cached_hid}")
return cached_hid
try:
# Get initial HTML content
response = requests.get(BASE_URL, headers=headers)
response.raise_for_status()
content = response.text
# Use regex to find the specific static/chunks path
pattern = r"static/chunks/app/layout-[a-zA-Z0-9]+\.js"
match = re.search(pattern, content)
if match:
# Construct full URL of JS file
js_path = match.group()
full_url = f"{BASE_URL}/_next/{js_path}"
# Get JS file content
js_response = requests.get(full_url, headers=headers)
js_response.raise_for_status()
# Search for h-value in JS content
h_pattern = r'h="([0-9a-f-]+)"'
h_match = re.search(h_pattern, js_response.text)
if h_match:
h_value = h_match.group(1)
logger.info(f"Found h-value: {h_value}")
# Update cache
cached_hid = h_value
cache_time = current_time
return h_value
else:
logger.error("h-value not found in JS content")
return None
else:
logger.error("Specified JS file path not found in HTML content")
return None
except requests.exceptions.RequestException as e:
logger.error(f"An error occurred: {e}")
return None
# Helper function to create a random alphanumeric chat ID
def generate_chat_id(length: int = 7) -> str:
characters = string.ascii_letters + string.digits
return ''.join(random.choices(characters, k=length))
# Helper function to create chat completion data
def create_chat_completion_data(
content: str, model: str, timestamp: int, finish_reason: Optional[str] = None
) -> Dict[str, Any]:
return {
"id": f"chatcmpl-{uuid.uuid4()}",
"object": "chat.completion.chunk",
"created": timestamp,
"model": model,
"choices": [
{
"index": 0,
"delta": {"content": content, "role": "assistant"},
"finish_reason": finish_reason,
}
],
"usage": None,
}
# Function to convert message to dictionary format, ensuring base64 data and optional model prefix
def message_to_dict(message, model_prefix: Optional[str] = None):
if isinstance(message.content, str):
content = message.content
elif isinstance(message.content, list):
content = message.content[0]["text"]
else:
content = message.content
if model_prefix:
content = f"{model_prefix} {content}"
if isinstance(message.content, list) and len(message.content) == 2 and "image_url" in message.content[1]:
# Ensure base64 images are always included for all models
return {
"role": message.role,
"content": content,
"data": {
"imageBase64": message.content[1]["image_url"]["url"],
"fileText": "",
"title": "snapshot",
},
}
return {"role": message.role, "content": content}
# Function to strip model prefix from content if present
def strip_model_prefix(content: str, model_prefix: Optional[str] = None) -> str:
"""Remove the model prefix from the response content if present."""
if model_prefix and content.startswith(model_prefix):
logger.debug(f"Stripping prefix '{model_prefix}' from content.")
return content[len(model_prefix):].strip()
return content
# Process streaming response
async def process_streaming_response(request: ChatRequest):
chat_id = generate_chat_id()
referer_url = BASE_URL # MODEL_REFERERS are removed
logger.info(f"Generated Chat ID: {chat_id} - Model: {request.model} - URL: {referer_url}")
agent_mode = AGENT_MODE.get(request.model, {})
trending_agent_mode = TRENDING_AGENT_MODE.get(request.model, {})
model_prefix = MODEL_PREFIXES.get(request.model, "")
headers_api_chat = headers.copy()
headers_api_chat['Referer'] = referer_url
if request.model == 'o1-preview':
delay_seconds = random.randint(1, 60)
logger.info(f"Introducing a delay of {delay_seconds} seconds for model 'o1-preview' (Chat ID: {chat_id})")
await asyncio.sleep(delay_seconds)
json_data = {
"agentMode": agent_mode,
"clickedAnswer2": False,
"clickedAnswer3": False,
"clickedForceWebSearch": False,
"codeModelMode": True,
"githubToken": None,
"id": chat_id,
"isChromeExt": False,
"isMicMode": False,
"maxTokens": request.max_tokens,
"messages": [message_to_dict(msg, model_prefix=model_prefix) for msg in request.messages],
"mobileClient": False,
"playgroundTemperature": request.temperature,
"playgroundTopP": request.top_p,
"previewToken": None,
"trendingAgentMode": trending_agent_mode,
"userId": None,
"userSelectedModel": MODEL_MAPPING.get(request.model, request.model),
"userSystemPrompt": None,
"validated": getHid(),
"visitFromDelta": False,
}
async with httpx.AsyncClient() as client:
try:
async with client.stream(
"POST",
f"{BASE_URL}/api/chat",
headers=headers_api_chat,
json=json_data,
timeout=100,
) as response:
response.raise_for_status()
async for line in response.aiter_lines():
timestamp = int(datetime.now().timestamp())
if line:
content = line
if "https://www.blackbox.ai" in content:
getHid(True)
content = "hid已刷新,重新对话即可\n"
yield f"data: {json.dumps(create_chat_completion_data(content, request.model, timestamp))}\n\n"
break
if content.startswith("$@$v=undefined-rv1$@$"):
content = content[21:]
cleaned_content = strip_model_prefix(content, model_prefix)
yield f"data: {json.dumps(create_chat_completion_data(cleaned_content, request.model, timestamp))}\n\n"
yield f"data: {json.dumps(create_chat_completion_data('', request.model, timestamp, 'stop'))}\n\n"
yield "data: [DONE]\n\n"
except httpx.HTTPStatusError as e:
logger.error(f"HTTP error occurred for Chat ID {chat_id}: {e}")
raise HTTPException(status_code=e.response.status_code, detail=str(e))
except httpx.RequestError as e:
logger.error(f"Error occurred during request for Chat ID {chat_id}: {e}")
raise HTTPException(status_code=500, detail=str(e))
# Process non-streaming response
async def process_non_streaming_response(request: ChatRequest):
chat_id = generate_chat_id()
referer_url = BASE_URL
logger.info(f"Generated Chat ID: {chat_id} - Model: {request.model} - URL: {referer_url}")
agent_mode = AGENT_MODE.get(request.model, {})
trending_agent_mode = TRENDING_AGENT_MODE.get(request.model, {})
model_prefix = MODEL_PREFIXES.get(request.model, "")
headers_api_chat = headers.copy()
headers_api_chat['Referer'] = referer_url
if request.model == 'o1-preview':
delay_seconds = random.randint(20, 60)
logger.info(f"Introducing a delay of {delay_seconds} seconds for model 'o1-preview' (Chat ID: {chat_id})")
await asyncio.sleep(delay_seconds)
json_data = {
"agentMode": agent_mode,
"clickedAnswer2": False,
"clickedAnswer3": False,
"clickedForceWebSearch": False,
"codeModelMode": True,
"githubToken": None,
"id": chat_id,
"isChromeExt": False,
"isMicMode": False,
"maxTokens": request.max_tokens,
"messages": [message_to_dict(msg, model_prefix=model_prefix) for msg in request.messages],
"mobileClient": False,
"playgroundTemperature": request.temperature,
"playgroundTopP": request.top_p,
"previewToken": None,
"trendingAgentMode": trending_agent_mode,
"userId": None,
"userSelectedModel": MODEL_MAPPING.get(request.model, request.model),
"userSystemPrompt": None,
"validated": getHid(),
"visitFromDelta": False,
}
full_response = ""
async with httpx.AsyncClient() as client:
try:
async with client.stream(
method="POST", url=f"{BASE_URL}/api/chat", headers=headers_api_chat, json=json_data
) as response:
response.raise_for_status()
async for chunk in response.aiter_text():
full_response += chunk
except httpx.HTTPStatusError as e:
logger.error(f"HTTP error occurred for Chat ID {chat_id}: {e}")
raise HTTPException(status_code=e.response.status_code, detail=str(e))
except httpx.RequestError as e:
logger.error(f"Error occurred during request for Chat ID {chat_id}: {e}")
raise HTTPException(status_code=500, detail=str(e))
if "https://www.blackbox.ai" in full_response:
getHid(True)
full_response = "hid已刷新,重新对话即可"
if full_response.startswith("$@$v=undefined-rv1$@$"):
full_response = full_response[21:]
cleaned_full_response = strip_model_prefix(full_response, model_prefix)
return {
"id": f"chatcmpl-{uuid.uuid4()}",
"object": "chat.completion",
"created": int(datetime.now().timestamp()),
"model": request.model,
"choices": [
{
"index": 0,
"message": {"role": "assistant", "content": cleaned_full_response},
"finish_reason": "stop",
}
],
"usage": None,
}