From 24c5502d7601ba3f2c5ab459015c74002b3af5c6 Mon Sep 17 00:00:00 2001 From: Heiner Lohaus Date: Wed, 15 May 2024 21:07:49 +0200 Subject: Add needs auth to provierds, Add PerplexityApi provider Add proxy support to nodriver --- g4f/Provider/DeepInfra.py | 3 +-- g4f/Provider/Reka.py | 26 +++++++++++++------------- g4f/Provider/Replicate.py | 1 + g4f/Provider/You.py | 13 +++---------- g4f/Provider/needs_auth/Gemini.py | 9 ++++++--- g4f/Provider/needs_auth/OpenaiChat.py | 9 ++++++--- g4f/Provider/needs_auth/PerplexityApi.py | 31 +++++++++++++++++++++++++++++++ g4f/Provider/needs_auth/__init__.py | 3 ++- g4f/Provider/you/har_file.py | 18 ++++++++---------- g4f/providers/retry_provider.py | 2 +- 10 files changed, 72 insertions(+), 43 deletions(-) create mode 100644 g4f/Provider/needs_auth/PerplexityApi.py (limited to 'g4f') diff --git a/g4f/Provider/DeepInfra.py b/g4f/Provider/DeepInfra.py index 9691539e..763b960a 100644 --- a/g4f/Provider/DeepInfra.py +++ b/g4f/Provider/DeepInfra.py @@ -8,8 +8,7 @@ class DeepInfra(Openai): label = "DeepInfra" url = "https://deepinfra.com" working = True - needs_auth = False - has_auth = True + needs_auth = True supports_stream = True supports_message_history = True default_model = "meta-llama/Meta-Llama-3-70b-instruct" diff --git a/g4f/Provider/Reka.py b/g4f/Provider/Reka.py index 09164b07..2306149e 100644 --- a/g4f/Provider/Reka.py +++ b/g4f/Provider/Reka.py @@ -9,6 +9,7 @@ from ..image import to_bytes class Reka(AbstractProvider): url = "https://chat.reka.ai/" working = True + needs_auth = True supports_stream = True default_vision_model = "reka" cookies = {} @@ -20,13 +21,12 @@ class Reka(AbstractProvider): messages: Messages, stream: bool, proxy: str = None, - timeout: int = 180, api_key: str = None, image: ImageType = None, **kwargs ) -> CreateResult: cls.proxy = proxy - + if not api_key: cls.cookies = get_cookies("chat.reka.ai") if not cls.cookies: @@ -34,19 +34,19 @@ class Reka(AbstractProvider): elif "appSession" not in cls.cookies: raise ValueError("No appSession found in cookies for chat.reka.ai, log in or provide bearer_auth") api_key = cls.get_access_token(cls) - + conversation = [] for message in messages: conversation.append({ "type": "human", "text": message["content"], }) - + if image: image_url = cls.upload_image(cls, api_key, image) conversation[-1]["image_url"] = image_url conversation[-1]["media_type"] = "image" - + headers = { 'accept': '*/*', 'accept-language': 'en,fr-FR;q=0.9,fr;q=0.8,es-ES;q=0.7,es;q=0.6,en-US;q=0.5,am;q=0.4,de;q=0.3', @@ -64,7 +64,7 @@ class Reka(AbstractProvider): 'sec-fetch-site': 'same-origin', 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36', } - + json_data = { 'conversation_history': conversation, 'stream': True, @@ -73,7 +73,7 @@ class Reka(AbstractProvider): 'model_name': 'reka-core', 'random_seed': int(time.time() * 1000), } - + tokens = '' response = requests.post('https://chat.reka.ai/api/chat', @@ -82,11 +82,11 @@ class Reka(AbstractProvider): for completion in response.iter_lines(): if b'data' in completion: token_data = json.loads(completion.decode('utf-8')[5:])['text'] - + yield (token_data.replace(tokens, '')) - + tokens = token_data - + def upload_image(cls, access_token, image: ImageType) -> str: boundary_token = os.urandom(8).hex() @@ -120,7 +120,7 @@ class Reka(AbstractProvider): cookies=cls.cookies, headers=headers, proxies=cls.proxy, data=data.encode('latin-1')) return response.json()['media_url'] - + def get_access_token(cls): headers = { 'accept': '*/*', @@ -141,8 +141,8 @@ class Reka(AbstractProvider): try: response = requests.get('https://chat.reka.ai/bff/auth/access_token', cookies=cls.cookies, headers=headers, proxies=cls.proxy) - + return response.json()['accessToken'] - + except Exception as e: raise ValueError(f"Failed to get access token: {e}, refresh your cookies / log in into chat.reka.ai") \ No newline at end of file diff --git a/g4f/Provider/Replicate.py b/g4f/Provider/Replicate.py index 89777cf2..7ff8ad65 100644 --- a/g4f/Provider/Replicate.py +++ b/g4f/Provider/Replicate.py @@ -10,6 +10,7 @@ from ..errors import ResponseError, MissingAuthError class Replicate(AsyncGeneratorProvider, ProviderModelMixin): url = "https://replicate.com" working = True + needs_auth = True default_model = "meta/meta-llama-3-70b-instruct" model_aliases = { "meta-llama/Meta-Llama-3-70B-Instruct": default_model diff --git a/g4f/Provider/You.py b/g4f/Provider/You.py index b4892035..2b08b38a 100644 --- a/g4f/Provider/You.py +++ b/g4f/Provider/You.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import re import json import base64 @@ -42,7 +44,6 @@ class You(AsyncGeneratorProvider, ProviderModelMixin): ] model_aliases = { "claude-v2": "claude-2", - "gpt-4o": "gpt-4o", } _cookies = None _cookies_used = 0 @@ -185,15 +186,7 @@ class You(AsyncGeneratorProvider, ProviderModelMixin): @classmethod async def create_cookies(cls, client: StreamSession) -> Cookies: if not cls._telemetry_ids: - try: - cls._telemetry_ids = await get_telemetry_ids() - except RuntimeError as e: - if str(e) == "Event loop is closed": - if debug.logging: - print("Event loop is closed error occurred in create_cookies.") - else: - raise - + cls._telemetry_ids = await get_telemetry_ids() user_uuid = str(uuid.uuid4()) telemetry_id = cls._telemetry_ids.pop() if debug.logging: diff --git a/g4f/Provider/needs_auth/Gemini.py b/g4f/Provider/needs_auth/Gemini.py index 25ad1c6e..e468f64a 100644 --- a/g4f/Provider/needs_auth/Gemini.py +++ b/g4f/Provider/needs_auth/Gemini.py @@ -59,7 +59,7 @@ class Gemini(AsyncGeneratorProvider): _cookies: Cookies = None @classmethod - async def nodriver_login(cls) -> AsyncIterator[str]: + async def nodriver_login(cls, proxy: str = None) -> AsyncIterator[str]: try: import nodriver as uc except ImportError: @@ -71,7 +71,10 @@ class Gemini(AsyncGeneratorProvider): user_data_dir = None if debug.logging: print(f"Open nodriver with user_dir: {user_data_dir}") - browser = await uc.start(user_data_dir=user_data_dir) + browser = await uc.start( + user_data_dir=user_data_dir, + browser_args=None if proxy is None else [f"--proxy-server={proxy}"], + ) login_url = os.environ.get("G4F_LOGIN_URL") if login_url: yield f"Please login: [Google Gemini]({login_url})\n\n" @@ -134,7 +137,7 @@ class Gemini(AsyncGeneratorProvider): ) as session: snlm0e = await cls.fetch_snlm0e(session, cls._cookies) if cls._cookies else None if not snlm0e: - async for chunk in cls.nodriver_login(): + async for chunk in cls.nodriver_login(proxy): yield chunk if cls._cookies is None: async for chunk in cls.webdriver_login(proxy): diff --git a/g4f/Provider/needs_auth/OpenaiChat.py b/g4f/Provider/needs_auth/OpenaiChat.py index 03ea4539..b4b8bb02 100644 --- a/g4f/Provider/needs_auth/OpenaiChat.py +++ b/g4f/Provider/needs_auth/OpenaiChat.py @@ -403,7 +403,7 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin): except NoValidHarFileError as e: error = e if cls._api_key is None: - await cls.nodriver_access_token() + await cls.nodriver_access_token(proxy) if cls._api_key is None and cls.needs_auth: raise error cls.default_model = cls.get_model(await cls.get_default_model(session, cls._headers)) @@ -625,7 +625,7 @@ this.fetch = async (url, options) => { cls._update_cookie_header() @classmethod - async def nodriver_access_token(cls): + async def nodriver_access_token(cls, proxy: str = None): try: import nodriver as uc except ImportError: @@ -637,7 +637,10 @@ this.fetch = async (url, options) => { user_data_dir = None if debug.logging: print(f"Open nodriver with user_dir: {user_data_dir}") - browser = await uc.start(user_data_dir=user_data_dir) + browser = await uc.start( + user_data_dir=user_data_dir, + browser_args=None if proxy is None else [f"--proxy-server={proxy}"], + ) page = await browser.get("https://chatgpt.com/") await page.select("[id^=headlessui-menu-button-]", 240) api_key = await page.evaluate( diff --git a/g4f/Provider/needs_auth/PerplexityApi.py b/g4f/Provider/needs_auth/PerplexityApi.py new file mode 100644 index 00000000..35d8d9d6 --- /dev/null +++ b/g4f/Provider/needs_auth/PerplexityApi.py @@ -0,0 +1,31 @@ +from __future__ import annotations + +from .Openai import Openai +from ...typing import AsyncResult, Messages + +class PerplexityApi(Openai): + label = "Perplexity API" + url = "https://www.perplexity.ai" + working = True + default_model = "llama-3-sonar-large-32k-online" + models = [ + "llama-3-sonar-small-32k-chat", + "llama-3-sonar-small-32k-online", + "llama-3-sonar-large-32k-chat", + "llama-3-sonar-large-32k-online", + "llama-3-8b-instruct", + "llama-3-70b-instruct", + "mixtral-8x7b-instruct" + ] + + @classmethod + def create_async_generator( + cls, + model: str, + messages: Messages, + api_base: str = "https://api.perplexity.ai", + **kwargs + ) -> AsyncResult: + return super().create_async_generator( + model, messages, api_base=api_base, **kwargs + ) \ No newline at end of file diff --git a/g4f/Provider/needs_auth/__init__.py b/g4f/Provider/needs_auth/__init__.py index 805d9fca..b5463b71 100644 --- a/g4f/Provider/needs_auth/__init__.py +++ b/g4f/Provider/needs_auth/__init__.py @@ -7,4 +7,5 @@ from .Poe import Poe from .Openai import Openai from .Groq import Groq from .OpenRouter import OpenRouter -from .OpenaiAccount import OpenaiAccount \ No newline at end of file +from .OpenaiAccount import OpenaiAccount +from .PerplexityApi import PerplexityApi \ No newline at end of file diff --git a/g4f/Provider/you/har_file.py b/g4f/Provider/you/har_file.py index cfdca12f..969ba96c 100644 --- a/g4f/Provider/you/har_file.py +++ b/g4f/Provider/you/har_file.py @@ -88,36 +88,34 @@ async def get_telemetry_ids(proxy: str = None) -> list: except NoValidHarFileError as e: if debug.logging: logging.error(e) - if debug.logging: - logging.error('Getting telemetry_id for you.com with nodriver') + try: from nodriver import start except ImportError: raise MissingRequirementsError('Add .har file from you.com or install "nodriver" package | pip install -U nodriver') - page = None + if debug.logging: + logging.error('Getting telemetry_id for you.com with nodriver') + + browser = page = None try: - browser = await start() + browser = await start( + browser_args=None if proxy is None else [f"--proxy-server={proxy}"], + ) page = await browser.get("https://you.com") - while not await page.evaluate('"GetTelemetryID" in this'): await page.sleep(1) - async def get_telemetry_id(): return await page.evaluate( f'this.GetTelemetryID("{public_token}", "{telemetry_url}");', await_promise=True ) - return [await get_telemetry_id()] - finally: try: if page is not None: await page.close() - if browser is not None: await browser.close() - except Exception as e: if debug.logging: logging.error(e) diff --git a/g4f/providers/retry_provider.py b/g4f/providers/retry_provider.py index e2520437..cde8c848 100644 --- a/g4f/providers/retry_provider.py +++ b/g4f/providers/retry_provider.py @@ -133,7 +133,7 @@ class NewBaseRetryProvider(BaseRetryProvider): if not stream: yield await provider.create_async(model, messages, **kwargs) elif hasattr(provider, "create_async_generator"): - async for token in provider.create_async_generator(model, messages, stream, **kwargs): + async for token in provider.create_async_generator(model, messages, stream=stream, **kwargs): yield token else: for token in provider.create_completion(model, messages, stream, **kwargs): -- cgit v1.2.3