From 126496d3cacd06a4fa8cbb4e5bde417ce6bb5b4a Mon Sep 17 00:00:00 2001 From: Heiner Lohaus Date: Fri, 25 Aug 2023 06:41:32 +0200 Subject: Add OpenaiChat and Hugchat Provider Add tests for providers with auth Improve async support / 2x faster Shared get_cookies by domain function --- g4f/Provider/base_provider.py | 85 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 2 deletions(-) (limited to 'g4f/Provider/base_provider.py') diff --git a/g4f/Provider/base_provider.py b/g4f/Provider/base_provider.py index 98ad3514..56d79ee6 100644 --- a/g4f/Provider/base_provider.py +++ b/g4f/Provider/base_provider.py @@ -1,7 +1,11 @@ from abc import ABC, abstractmethod -from ..typing import Any, CreateResult +from ..typing import Any, CreateResult, AsyncGenerator, Union +import browser_cookie3 +import asyncio +from time import time +import math class BaseProvider(ABC): url: str @@ -30,4 +34,81 @@ class BaseProvider(ABC): ("stream", "bool"), ] param = ", ".join([": ".join(p) for p in params]) - return f"g4f.provider.{cls.__name__} supports: ({param})" \ No newline at end of file + return f"g4f.provider.{cls.__name__} supports: ({param})" + + +_cookies = {} + +def get_cookies(cookie_domain: str) -> dict: + if cookie_domain not in _cookies: + _cookies[cookie_domain] = {} + for cookie in browser_cookie3.load(cookie_domain): + _cookies[cookie_domain][cookie.name] = cookie.value + return _cookies[cookie_domain] + + +class AsyncProvider(BaseProvider): + @classmethod + def create_completion( + cls, + model: str, + messages: list[dict[str, str]], + stream: bool = False, + **kwargs: Any + ) -> CreateResult: + yield asyncio.run(cls.create_async(model, messages, **kwargs)) + + @staticmethod + @abstractmethod + async def create_async( + model: str, + messages: list[dict[str, str]], + **kwargs: Any, + ) -> str: + raise NotImplementedError() + + +class AsyncGeneratorProvider(AsyncProvider): + @classmethod + def create_completion( + cls, + model: str, + messages: list[dict[str, str]], + stream: bool = True, + **kwargs: Any + ) -> CreateResult: + if stream: + yield from run_generator(cls.create_async_generator(model, messages, **kwargs)) + else: + yield from AsyncProvider.create_completion(cls=cls, model=model, messages=messages, **kwargs) + + @classmethod + async def create_async( + cls, + model: str, + messages: list[dict[str, str]], + **kwargs: Any, + ) -> str: + chunks = [chunk async for chunk in cls.create_async_generator(model, messages, **kwargs)] + if chunks: + return "".join(chunks) + + @staticmethod + @abstractmethod + def create_async_generator( + model: str, + messages: list[dict[str, str]], + ) -> AsyncGenerator: + raise NotImplementedError() + + +def run_generator(generator: AsyncGenerator[Union[Any, str], Any]): + loop = asyncio.new_event_loop() + gen = generator.__aiter__() + + while True: + try: + yield loop.run_until_complete(gen.__anext__()) + + except StopAsyncIteration: + break -- cgit v1.2.3 From efd75a11b871d61ac31b0e274acdfb33daba361d Mon Sep 17 00:00:00 2001 From: abc <98614666+xtekky@users.noreply.github.com> Date: Sun, 27 Aug 2023 17:37:44 +0200 Subject: ~ | code styling --- g4f/Provider/base_provider.py | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) (limited to 'g4f/Provider/base_provider.py') diff --git a/g4f/Provider/base_provider.py b/g4f/Provider/base_provider.py index 56d79ee6..d5f23931 100644 --- a/g4f/Provider/base_provider.py +++ b/g4f/Provider/base_provider.py @@ -9,20 +9,19 @@ import math class BaseProvider(ABC): url: str - working = False - needs_auth = False - supports_stream = False + working = False + needs_auth = False + supports_stream = False supports_gpt_35_turbo = False - supports_gpt_4 = False + supports_gpt_4 = False @staticmethod @abstractmethod def create_completion( model: str, messages: list[dict[str, str]], - stream: bool, - **kwargs: Any, - ) -> CreateResult: + stream: bool, **kwargs: Any) -> CreateResult: + raise NotImplementedError() @classmethod @@ -42,8 +41,10 @@ _cookies = {} def get_cookies(cookie_domain: str) -> dict: if cookie_domain not in _cookies: _cookies[cookie_domain] = {} + for cookie in browser_cookie3.load(cookie_domain): _cookies[cookie_domain][cookie.name] = cookie.value + return _cookies[cookie_domain] @@ -53,18 +54,15 @@ class AsyncProvider(BaseProvider): cls, model: str, messages: list[dict[str, str]], - stream: bool = False, - **kwargs: Any - ) -> CreateResult: + stream: bool = False, **kwargs: Any) -> CreateResult: + yield asyncio.run(cls.create_async(model, messages, **kwargs)) @staticmethod @abstractmethod async def create_async( model: str, - messages: list[dict[str, str]], - **kwargs: Any, - ) -> str: + messages: list[dict[str, str]], **kwargs: Any) -> str: raise NotImplementedError() @@ -74,9 +72,8 @@ class AsyncGeneratorProvider(AsyncProvider): cls, model: str, messages: list[dict[str, str]], - stream: bool = True, - **kwargs: Any - ) -> CreateResult: + stream: bool = True, **kwargs: Any) -> CreateResult: + if stream: yield from run_generator(cls.create_async_generator(model, messages, **kwargs)) else: @@ -86,9 +83,8 @@ class AsyncGeneratorProvider(AsyncProvider): async def create_async( cls, model: str, - messages: list[dict[str, str]], - **kwargs: Any, - ) -> str: + messages: list[dict[str, str]], **kwargs: Any) -> str: + chunks = [chunk async for chunk in cls.create_async_generator(model, messages, **kwargs)] if chunks: return "".join(chunks) @@ -97,14 +93,14 @@ class AsyncGeneratorProvider(AsyncProvider): @abstractmethod def create_async_generator( model: str, - messages: list[dict[str, str]], - ) -> AsyncGenerator: + messages: list[dict[str, str]]) -> AsyncGenerator: + raise NotImplementedError() def run_generator(generator: AsyncGenerator[Union[Any, str], Any]): loop = asyncio.new_event_loop() - gen = generator.__aiter__() + gen = generator.__aiter__() while True: try: -- cgit v1.2.3 From 7294abc890c377d75c6c8c932620c2e2c8b3f0f9 Mon Sep 17 00:00:00 2001 From: Heiner Lohaus Date: Mon, 28 Aug 2023 01:43:45 +0200 Subject: Add async support for H2o Add format_prompt helper Fix create_completion in AsyncGeneratorProvider Move get_cookies from constructor to function Add ow HuggingChat implement Remove need auth form Liabots Add staic cache for access_token in OpenaiChat Add OpenAssistant provider Support stream and async in You Support async and add userId in Yqcloud Add log_time module --- g4f/Provider/base_provider.py | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) (limited to 'g4f/Provider/base_provider.py') diff --git a/g4f/Provider/base_provider.py b/g4f/Provider/base_provider.py index d5f23931..def2cd6d 100644 --- a/g4f/Provider/base_provider.py +++ b/g4f/Provider/base_provider.py @@ -4,8 +4,7 @@ from ..typing import Any, CreateResult, AsyncGenerator, Union import browser_cookie3 import asyncio -from time import time -import math + class BaseProvider(ABC): url: str @@ -48,6 +47,17 @@ def get_cookies(cookie_domain: str) -> dict: return _cookies[cookie_domain] +def format_prompt(messages: list[dict[str, str]], add_special_tokens=False): + if add_special_tokens or len(messages) > 1: + formatted = "\n".join( + ["%s: %s" % ((message["role"]).capitalize(), message["content"]) for message in messages] + ) + return f"{formatted}\nAssistant:" + else: + return messages.pop()["content"] + + + class AsyncProvider(BaseProvider): @classmethod def create_completion( @@ -72,20 +82,19 @@ class AsyncGeneratorProvider(AsyncProvider): cls, model: str, messages: list[dict[str, str]], - stream: bool = True, **kwargs: Any) -> CreateResult: - - if stream: - yield from run_generator(cls.create_async_generator(model, messages, **kwargs)) - else: - yield from AsyncProvider.create_completion(cls=cls, model=model, messages=messages, **kwargs) + stream: bool = True, + **kwargs + ) -> CreateResult: + yield from run_generator(cls.create_async_generator(model, messages, stream=stream, **kwargs)) @classmethod async def create_async( cls, model: str, - messages: list[dict[str, str]], **kwargs: Any) -> str: - - chunks = [chunk async for chunk in cls.create_async_generator(model, messages, **kwargs)] + messages: list[dict[str, str]], + **kwargs + ) -> str: + chunks = [chunk async for chunk in cls.create_async_generator(model, messages, stream=False, **kwargs)] if chunks: return "".join(chunks) @@ -93,8 +102,9 @@ class AsyncGeneratorProvider(AsyncProvider): @abstractmethod def create_async_generator( model: str, - messages: list[dict[str, str]]) -> AsyncGenerator: - + messages: list[dict[str, str]], + **kwargs + ) -> AsyncGenerator: raise NotImplementedError() -- cgit v1.2.3 From 901595b10f08972ee3ac5fc08c346dbb561a7d62 Mon Sep 17 00:00:00 2001 From: msi-JunXiang Date: Sun, 3 Sep 2023 16:26:26 +0800 Subject: type hints Use `from __future__ import annotations avoid `dict` and `list` cause "TypeErro: 'type' object is not subscriptable". Refer to the following Stack Overflow discussions for more information: 1. https://stackoverflow.com/questions/75202610/typeerror-type-object-is-not-subscriptable-python 2. https://stackoverflow.com/questions/59101121/type-hint-for-a-dict-gives-typeerror-type-object-is-not-subscriptable --- g4f/Provider/base_provider.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'g4f/Provider/base_provider.py') diff --git a/g4f/Provider/base_provider.py b/g4f/Provider/base_provider.py index def2cd6d..e667819a 100644 --- a/g4f/Provider/base_provider.py +++ b/g4f/Provider/base_provider.py @@ -1,9 +1,11 @@ -from abc import ABC, abstractmethod +from __future__ import annotations -from ..typing import Any, CreateResult, AsyncGenerator, Union +import asyncio +from abc import ABC, abstractmethod import browser_cookie3 -import asyncio + +from ..typing import Any, AsyncGenerator, CreateResult, Union class BaseProvider(ABC): -- cgit v1.2.3