From 55577031d556c613daae9ed174fd6c02f3d0dcaa Mon Sep 17 00:00:00 2001 From: Heiner Lohaus Date: Wed, 20 Sep 2023 14:52:50 +0200 Subject: Add check_running_loop requirement Add create_async function in ChatCompletion Use SelectorEventLoop on windows --- g4f/Provider/base_provider.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'g4f/Provider/base_provider.py') diff --git a/g4f/Provider/base_provider.py b/g4f/Provider/base_provider.py index 79f8f617..9d45aa44 100644 --- a/g4f/Provider/base_provider.py +++ b/g4f/Provider/base_provider.py @@ -25,6 +25,7 @@ class BaseProvider(ABC): raise NotImplementedError() + @classmethod @property def params(cls): @@ -46,6 +47,8 @@ class AsyncProvider(BaseProvider): stream: bool = False, **kwargs ) -> CreateResult: + check_running_loop() + yield asyncio.run(cls.create_async(model, messages, **kwargs)) @staticmethod @@ -67,10 +70,17 @@ class AsyncGeneratorProvider(AsyncProvider): stream: bool = True, **kwargs ) -> CreateResult: - loop = asyncio.new_event_loop() + check_running_loop() + + # Force use selector event loop on windows + loop = asyncio.SelectorEventLoop() try: - asyncio.set_event_loop(loop) - generator = cls.create_async_generator(model, messages, stream=stream, **kwargs) + generator = cls.create_async_generator( + model, + messages, + stream=stream, + **kwargs + ) gen = generator.__aiter__() while True: try: @@ -78,10 +88,8 @@ class AsyncGeneratorProvider(AsyncProvider): except StopAsyncIteration: break finally: - asyncio.set_event_loop(None) loop.close() - @classmethod async def create_async( cls, @@ -100,6 +108,11 @@ class AsyncGeneratorProvider(AsyncProvider): ) -> AsyncGenerator: raise NotImplementedError() +# Don't create a new loop in a running loop +def check_running_loop(): + if asyncio.events._get_running_loop() is not None: + raise RuntimeError( + 'Use "create_async" instead of "create" function in a async loop.') _cookies = {} -- cgit v1.2.3 From 587f4ad2c9c1daaa246cabb02dbec7ec013de754 Mon Sep 17 00:00:00 2001 From: Heiner Lohaus Date: Wed, 20 Sep 2023 15:01:33 +0200 Subject: Add "create_event_loop" helper --- g4f/Provider/base_provider.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'g4f/Provider/base_provider.py') diff --git a/g4f/Provider/base_provider.py b/g4f/Provider/base_provider.py index 9d45aa44..1e2d4c64 100644 --- a/g4f/Provider/base_provider.py +++ b/g4f/Provider/base_provider.py @@ -47,9 +47,11 @@ class AsyncProvider(BaseProvider): stream: bool = False, **kwargs ) -> CreateResult: - check_running_loop() - - yield asyncio.run(cls.create_async(model, messages, **kwargs)) + loop = create_event_loop() + try: + yield loop.run_until_complete(cls.create_async(model, messages, **kwargs)) + finally: + loop.close() @staticmethod @abstractmethod @@ -70,10 +72,7 @@ class AsyncGeneratorProvider(AsyncProvider): stream: bool = True, **kwargs ) -> CreateResult: - check_running_loop() - - # Force use selector event loop on windows - loop = asyncio.SelectorEventLoop() + loop = get_new_event_loop() try: generator = cls.create_async_generator( model, @@ -108,12 +107,17 @@ class AsyncGeneratorProvider(AsyncProvider): ) -> AsyncGenerator: raise NotImplementedError() -# Don't create a new loop in a running loop -def check_running_loop(): + +def create_event_loop(): + # Don't create a new loop in a running loop if asyncio.events._get_running_loop() is not None: raise RuntimeError( 'Use "create_async" instead of "create" function in a async loop.') + # Force use selector event loop on windows + return asyncio.SelectorEventLoop() + + _cookies = {} def get_cookies(cookie_domain: str) -> dict: -- cgit v1.2.3 From f90741c10b444abea918c7a0c58c6a1a7367b29c Mon Sep 17 00:00:00 2001 From: Heiner Lohaus Date: Wed, 20 Sep 2023 17:31:25 +0200 Subject: Improve code style in async support --- g4f/Provider/base_provider.py | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'g4f/Provider/base_provider.py') diff --git a/g4f/Provider/base_provider.py b/g4f/Provider/base_provider.py index 1e2d4c64..003f86ba 100644 --- a/g4f/Provider/base_provider.py +++ b/g4f/Provider/base_provider.py @@ -1,6 +1,7 @@ from __future__ import annotations import asyncio +from asyncio import SelectorEventLoop from abc import ABC, abstractmethod import browser_cookie3 @@ -57,7 +58,9 @@ class AsyncProvider(BaseProvider): @abstractmethod async def create_async( model: str, - messages: list[dict[str, str]], **kwargs: Any) -> str: + messages: list[dict[str, str]], + **kwargs + ) -> str: raise NotImplementedError() @@ -72,7 +75,7 @@ class AsyncGeneratorProvider(AsyncProvider): stream: bool = True, **kwargs ) -> CreateResult: - loop = get_new_event_loop() + loop = create_event_loop() try: generator = cls.create_async_generator( model, @@ -96,7 +99,14 @@ class AsyncGeneratorProvider(AsyncProvider): messages: list[dict[str, str]], **kwargs ) -> str: - return "".join([chunk async for chunk in cls.create_async_generator(model, messages, stream=False, **kwargs)]) + return "".join([ + chunk async for chunk in cls.create_async_generator( + model, + messages, + stream=False, + **kwargs + ) + ]) @staticmethod @abstractmethod @@ -108,14 +118,16 @@ class AsyncGeneratorProvider(AsyncProvider): raise NotImplementedError() -def create_event_loop(): +def create_event_loop() -> SelectorEventLoop: # Don't create a new loop in a running loop - if asyncio.events._get_running_loop() is not None: - raise RuntimeError( - 'Use "create_async" instead of "create" function in a async loop.') - - # Force use selector event loop on windows - return asyncio.SelectorEventLoop() + try: + if asyncio.get_running_loop() is not None: + raise RuntimeError( + 'Use "create_async" instead of "create" function in a async loop.') + except: + pass + # Force use selector event loop on windows and linux use it anyway + return SelectorEventLoop() _cookies = {} -- cgit v1.2.3 From 951a1332a7dc1878feb11b60677faff4bb7b391b Mon Sep 17 00:00:00 2001 From: Heiner Lohaus Date: Wed, 20 Sep 2023 23:06:52 +0200 Subject: Fix create_event_loop function Add PerplexityAi Provider --- g4f/Provider/base_provider.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'g4f/Provider/base_provider.py') diff --git a/g4f/Provider/base_provider.py b/g4f/Provider/base_provider.py index 003f86ba..0cceb220 100644 --- a/g4f/Provider/base_provider.py +++ b/g4f/Provider/base_provider.py @@ -6,7 +6,7 @@ from abc import ABC, abstractmethod import browser_cookie3 -from ..typing import Any, AsyncGenerator, CreateResult, Union +from ..typing import Any, AsyncGenerator, CreateResult class BaseProvider(ABC): @@ -22,7 +22,9 @@ class BaseProvider(ABC): def create_completion( model: str, messages: list[dict[str, str]], - stream: bool, **kwargs: Any) -> CreateResult: + stream: bool, + **kwargs + ) -> CreateResult: raise NotImplementedError() @@ -118,16 +120,15 @@ class AsyncGeneratorProvider(AsyncProvider): raise NotImplementedError() +# Don't create a new event loop in a running async loop. +# Force use selector event loop on windows and linux use it anyway. def create_event_loop() -> SelectorEventLoop: - # Don't create a new loop in a running loop try: - if asyncio.get_running_loop() is not None: - raise RuntimeError( - 'Use "create_async" instead of "create" function in a async loop.') - except: - pass - # Force use selector event loop on windows and linux use it anyway - return SelectorEventLoop() + asyncio.get_running_loop() + except RuntimeError: + return SelectorEventLoop() + raise RuntimeError( + 'Use "create_async" instead of "create" function in a async loop.') _cookies = {} -- cgit v1.2.3