LoRDxdd's picture
Add gpt4free API for Hugging Face
a4b70d9
from __future__ import annotations
import json
import random
import string
import asyncio
from aiohttp import ClientSession
from ...typing import AsyncResult, Messages
from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin
from ...requests.raise_for_status import raise_for_status
from ...errors import ResponseStatusError
from ...providers.response import ImageResponse
from ..helper import format_prompt, format_media_prompt
class Websim(AsyncGeneratorProvider, ProviderModelMixin):
url = "https://websim.ai"
login_url = None
chat_api_endpoint = "https://websim.ai/api/v1/inference/run_chat_completion"
image_api_endpoint = "https://websim.ai/api/v1/inference/run_image_generation"
working = False
needs_auth = False
use_nodriver = False
supports_stream = False
supports_system_message = True
supports_message_history = True
default_model = 'gemini-2.5-pro'
default_image_model = 'flux'
image_models = [default_image_model]
models = [default_model, 'gemini-2.5-flash'] + image_models
@staticmethod
def generate_project_id(for_image=False):
"""
Generate a project ID in the appropriate format
For chat: format like 'ke3_xh5gai3gjkmruomu'
For image: format like 'kx0m131_rzz66qb2xoy7'
"""
chars = string.ascii_lowercase + string.digits
if for_image:
first_part = ''.join(random.choices(chars, k=7))
second_part = ''.join(random.choices(chars, k=12))
return f"{first_part}_{second_part}"
else:
prefix = ''.join(random.choices(chars, k=3))
suffix = ''.join(random.choices(chars, k=15))
return f"{prefix}_{suffix}"
@classmethod
async def create_async_generator(
cls,
model: str,
messages: Messages,
prompt: str = None,
proxy: str = None,
aspect_ratio: str = "1:1",
project_id: str = None,
**kwargs
) -> AsyncResult:
is_image_request = model in cls.image_models
if project_id is None:
project_id = cls.generate_project_id(for_image=is_image_request)
headers = {
'accept': '*/*',
'accept-language': 'en-US,en;q=0.9',
'content-type': 'text/plain;charset=UTF-8',
'origin': 'https://websim.ai',
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',
'websim-flags;': ''
}
if is_image_request:
headers['referer'] = 'https://websim.ai/@ISWEARIAMNOTADDICTEDTOPILLOW/ai-image-prompt-generator'
async for result in cls._handle_image_request(
project_id=project_id,
messages=messages,
prompt=prompt,
aspect_ratio=aspect_ratio,
headers=headers,
proxy=proxy,
**kwargs
):
yield result
else:
headers['referer'] = 'https://websim.ai/@ISWEARIAMNOTADDICTEDTOPILLOW/zelos-ai-assistant'
async for result in cls._handle_chat_request(
project_id=project_id,
messages=messages,
headers=headers,
proxy=proxy,
**kwargs
):
yield result
@classmethod
async def _handle_image_request(
cls,
project_id: str,
messages: Messages,
prompt: str,
aspect_ratio: str,
headers: dict,
proxy: str = None,
**kwargs
) -> AsyncResult:
used_prompt = format_media_prompt(messages, prompt)
async with ClientSession(headers=headers) as session:
data = {
"project_id": project_id,
"prompt": used_prompt,
"aspect_ratio": aspect_ratio
}
async with session.post(f"{cls.image_api_endpoint}", json=data, proxy=proxy) as response:
await raise_for_status(response)
response_text = await response.text()
response_json = json.loads(response_text)
image_url = response_json.get("url")
if image_url:
yield ImageResponse(urls=[image_url], alt=used_prompt)
@classmethod
async def _handle_chat_request(
cls,
project_id: str,
messages: Messages,
headers: dict,
proxy: str = None,
**kwargs
) -> AsyncResult:
max_retries = 3
retry_count = 0
last_error = None
while retry_count < max_retries:
try:
async with ClientSession(headers=headers) as session:
data = {
"project_id": project_id,
"messages": messages
}
async with session.post(f"{cls.chat_api_endpoint}", json=data, proxy=proxy) as response:
if response.status == 429:
response_text = await response.text()
last_error = ResponseStatusError(f"Response {response.status}: {response_text}")
retry_count += 1
if retry_count < max_retries:
wait_time = 2 ** retry_count
await asyncio.sleep(wait_time)
continue
else:
raise last_error
await raise_for_status(response)
response_text = await response.text()
try:
response_json = json.loads(response_text)
content = response_json.get("content", "")
yield content.strip()
break
except json.JSONDecodeError:
yield response_text
break
except ResponseStatusError as e:
if "Rate limit exceeded" in str(e) and retry_count < max_retries:
retry_count += 1
wait_time = 2 ** retry_count
await asyncio.sleep(wait_time)
else:
if retry_count >= max_retries:
raise e
else:
raise
except Exception as e:
raise