From d44b39b31c83c6a4bc636bea931275702c700feb Mon Sep 17 00:00:00 2001 From: Heiner Lohaus Date: Sat, 6 Apr 2024 01:05:00 +0200 Subject: Add Groq and Openai interfaces, Add integration tests --- g4f/providers/base_provider.py | 37 +++++++++++++++++++------------------ g4f/providers/types.py | 6 +++++- 2 files changed, 24 insertions(+), 19 deletions(-) (limited to 'g4f/providers') diff --git a/g4f/providers/base_provider.py b/g4f/providers/base_provider.py index ee5bcbb8..37f4af15 100644 --- a/g4f/providers/base_provider.py +++ b/g4f/providers/base_provider.py @@ -6,9 +6,10 @@ from asyncio import AbstractEventLoop from concurrent.futures import ThreadPoolExecutor from abc import abstractmethod from inspect import signature, Parameter -from ..typing import CreateResult, AsyncResult, Messages, Union -from .types import BaseProvider -from ..errors import NestAsyncioError, ModelNotSupportedError +from typing import Callable, Union +from ..typing import CreateResult, AsyncResult, Messages +from .types import BaseProvider, FinishReason +from ..errors import NestAsyncioError, ModelNotSupportedError, MissingRequirementsError from .. import debug if sys.version_info < (3, 10): @@ -21,17 +22,23 @@ if sys.platform == 'win32': if isinstance(asyncio.get_event_loop_policy(), asyncio.WindowsProactorEventLoopPolicy): asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) -def get_running_loop() -> Union[AbstractEventLoop, None]: +def get_running_loop(check_nested: bool) -> Union[AbstractEventLoop, None]: try: loop = asyncio.get_running_loop() - if not hasattr(loop.__class__, "_nest_patched"): - raise NestAsyncioError( - 'Use "create_async" instead of "create" function in a running event loop. Or use "nest_asyncio" package.' - ) + if check_nested and not hasattr(loop.__class__, "_nest_patched"): + try: + import nest_asyncio + nest_asyncio.apply(loop) + except ImportError: + raise MissingRequirementsError('Install "nest_asyncio" package') return loop except RuntimeError: pass +# Fix for RuntimeError: async generator ignored GeneratorExit +async def await_callback(callback: Callable): + return await callback() + class AbstractProvider(BaseProvider): """ Abstract class for providing asynchronous functionality to derived classes. @@ -132,7 +139,7 @@ class AsyncProvider(AbstractProvider): Returns: CreateResult: The result of the completion creation. """ - get_running_loop() + get_running_loop(check_nested=True) yield asyncio.run(cls.create_async(model, messages, **kwargs)) @staticmethod @@ -158,7 +165,6 @@ class AsyncProvider(AbstractProvider): """ raise NotImplementedError() - class AsyncGeneratorProvider(AsyncProvider): """ Provides asynchronous generator functionality for streaming results. @@ -187,9 +193,9 @@ class AsyncGeneratorProvider(AsyncProvider): Returns: CreateResult: The result of the streaming completion creation. """ - loop = get_running_loop() + loop = get_running_loop(check_nested=True) new_loop = False - if not loop: + if loop is None: loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) new_loop = True @@ -197,16 +203,11 @@ class AsyncGeneratorProvider(AsyncProvider): generator = cls.create_async_generator(model, messages, stream=stream, **kwargs) gen = generator.__aiter__() - # Fix for RuntimeError: async generator ignored GeneratorExit - async def await_callback(callback): - return await callback() - try: while True: yield loop.run_until_complete(await_callback(gen.__anext__)) except StopAsyncIteration: ... - # Fix for: ResourceWarning: unclosed event loop finally: if new_loop: loop.close() @@ -233,7 +234,7 @@ class AsyncGeneratorProvider(AsyncProvider): """ return "".join([ chunk async for chunk in cls.create_async_generator(model, messages, stream=False, **kwargs) - if not isinstance(chunk, Exception) + if not isinstance(chunk, (Exception, FinishReason)) ]) @staticmethod diff --git a/g4f/providers/types.py b/g4f/providers/types.py index 67340958..a3eeb99e 100644 --- a/g4f/providers/types.py +++ b/g4f/providers/types.py @@ -97,4 +97,8 @@ class BaseRetryProvider(BaseProvider): __name__: str = "RetryProvider" supports_stream: bool = True -ProviderType = Union[Type[BaseProvider], BaseRetryProvider] \ No newline at end of file +ProviderType = Union[Type[BaseProvider], BaseRetryProvider] + +class FinishReason(): + def __init__(self, reason: str): + self.reason = reason \ No newline at end of file -- cgit v1.2.3