diff options
Diffstat (limited to '')
-rw-r--r-- | g4f/Provider/FreeNetfly.py | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/g4f/Provider/FreeNetfly.py b/g4f/Provider/FreeNetfly.py new file mode 100644 index 00000000..624f33cf --- /dev/null +++ b/g4f/Provider/FreeNetfly.py @@ -0,0 +1,107 @@ +from __future__ import annotations + +import json +import asyncio +from aiohttp import ClientSession, ClientTimeout, ClientError +from typing import AsyncGenerator + +from ..typing import AsyncResult, Messages +from .base_provider import AsyncGeneratorProvider, ProviderModelMixin + + +class FreeNetfly(AsyncGeneratorProvider, ProviderModelMixin): + url = "https://free.netfly.top" + api_endpoint = "/api/openai/v1/chat/completions" + working = True + supports_gpt_35_turbo = True + supports_gpt_4 = True + default_model = 'gpt-3.5-turbo' + models = [ + 'gpt-3.5-turbo', + 'gpt-4', + ] + + @classmethod + async def create_async_generator( + cls, + model: str, + messages: Messages, + proxy: str = None, + **kwargs + ) -> AsyncResult: + headers = { + "accept": "application/json, text/event-stream", + "accept-language": "en-US,en;q=0.9", + "content-type": "application/json", + "dnt": "1", + "origin": cls.url, + "referer": f"{cls.url}/", + "sec-ch-ua": '"Not/A)Brand";v="8", "Chromium";v="126"', + "sec-ch-ua-mobile": "?0", + "sec-ch-ua-platform": '"Linux"', + "sec-fetch-dest": "empty", + "sec-fetch-mode": "cors", + "sec-fetch-site": "same-origin", + "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36", + } + data = { + "messages": messages, + "stream": True, + "model": model, + "temperature": 0.5, + "presence_penalty": 0, + "frequency_penalty": 0, + "top_p": 1 + } + + max_retries = 3 + retry_delay = 1 + + for attempt in range(max_retries): + try: + async with ClientSession(headers=headers) as session: + timeout = ClientTimeout(total=60) + async with session.post(f"{cls.url}{cls.api_endpoint}", json=data, proxy=proxy, timeout=timeout) as response: + response.raise_for_status() + async for chunk in cls._process_response(response): + yield chunk + return # If successful, exit the function + except (ClientError, asyncio.TimeoutError) as e: + if attempt == max_retries - 1: + raise # If all retries failed, raise the last exception + await asyncio.sleep(retry_delay) + retry_delay *= 2 # Exponential backoff + + @classmethod + async def _process_response(cls, response) -> AsyncGenerator[str, None]: + buffer = "" + async for line in response.content: + buffer += line.decode('utf-8') + if buffer.endswith('\n\n'): + for subline in buffer.strip().split('\n'): + if subline.startswith('data: '): + if subline == 'data: [DONE]': + return + try: + data = json.loads(subline[6:]) + content = data['choices'][0]['delta'].get('content') + if content: + yield content + except json.JSONDecodeError: + print(f"Failed to parse JSON: {subline}") + except KeyError: + print(f"Unexpected JSON structure: {data}") + buffer = "" + + # Process any remaining data in the buffer + if buffer: + for subline in buffer.strip().split('\n'): + if subline.startswith('data: ') and subline != 'data: [DONE]': + try: + data = json.loads(subline[6:]) + content = data['choices'][0]['delta'].get('content') + if content: + yield content + except (json.JSONDecodeError, KeyError): + pass + |