mirror of
https://github.com/xtekky/gpt4free.git
synced 2025-12-15 06:41:34 -08:00
184 lines
6.6 KiB
Python
184 lines
6.6 KiB
Python
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_image_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 = True
|
|
needs_auth = False
|
|
use_nodriver = False
|
|
supports_stream = False
|
|
supports_system_message = True
|
|
supports_message_history = True
|
|
|
|
default_model = 'gemini-1.5-pro'
|
|
default_image_model = 'flux'
|
|
image_models = [default_image_model]
|
|
models = [default_model, 'gemini-1.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_image_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
|