From 6ce493d4dfc2884832ff5b5be4479a55818b2fe7 Mon Sep 17 00:00:00 2001 From: H Lohaus Date: Sat, 16 Nov 2024 13:19:51 +0100 Subject: Fix api streaming, fix AsyncClient (#2357) * Fix api streaming, fix AsyncClient, Improve Client class, Some providers fixes, Update models list, Fix some tests, Update model list in Airforce provid er, Add OpenAi image generation url to api, Fix reload and debug in api arguments, Fix websearch in gui * Fix Cloadflare and Pi and AmigoChat provider * Fix conversation support in DDG provider, Add cloudflare bypass with nodriver * Fix unittests without curl_cffi --- etc/unittest/__main__.py | 2 +- etc/unittest/backend.py | 33 ++++++++------------- etc/unittest/client.py | 76 +++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 76 insertions(+), 35 deletions(-) (limited to 'etc/unittest') diff --git a/etc/unittest/__main__.py b/etc/unittest/__main__.py index ee748917..f8a73280 100644 --- a/etc/unittest/__main__.py +++ b/etc/unittest/__main__.py @@ -1,10 +1,10 @@ import unittest + from .asyncio import * from .backend import * from .main import * from .model import * from .client import * -from .client import * from .include import * from .integration import * diff --git a/etc/unittest/backend.py b/etc/unittest/backend.py index ee6174d5..a2999c5c 100644 --- a/etc/unittest/backend.py +++ b/etc/unittest/backend.py @@ -1,15 +1,19 @@ +from __future__ import annotations + import unittest import asyncio from unittest.mock import MagicMock -from .mocks import ProviderMock -import g4f from g4f.errors import MissingRequirementsError - try: - from g4f.gui.server.backend import Backend_Api, get_error_message + from g4f.gui.server.backend import Backend_Api has_requirements = True except: has_requirements = False +try: + from duckduckgo_search.exceptions import DuckDuckGoSearchException +except ImportError: + class DuckDuckGoSearchException: + pass class TestBackendApi(unittest.TestCase): @@ -31,28 +35,15 @@ class TestBackendApi(unittest.TestCase): def test_get_providers(self): response = self.api.get_providers() - self.assertIsInstance(response, list) + self.assertIsInstance(response, dict) self.assertTrue(len(response) > 0) def test_search(self): from g4f.gui.server.internet import search try: result = asyncio.run(search("Hello")) + except DuckDuckGoSearchException as e: + self.skipTest(e) except MissingRequirementsError: self.skipTest("search is not installed") - self.assertEqual(5, len(result)) - -class TestUtilityFunctions(unittest.TestCase): - - def setUp(self): - if not has_requirements: - self.skipTest("gui is not installed") - - def test_get_error_message(self): - g4f.debug.last_provider = ProviderMock - exception = Exception("Message") - result = get_error_message(exception) - self.assertEqual("ProviderMock: Exception: Message", result) - -if __name__ == '__main__': - unittest.main() \ No newline at end of file + self.assertEqual(5, len(result)) \ No newline at end of file diff --git a/etc/unittest/client.py b/etc/unittest/client.py index 54e2091f..97f9f6c8 100644 --- a/etc/unittest/client.py +++ b/etc/unittest/client.py @@ -1,6 +1,8 @@ +from __future__ import annotations + import unittest -from g4f.client import Client, ChatCompletion, ChatCompletionChunk +from g4f.client import Client, AsyncClient, ChatCompletion, ChatCompletionChunk from .mocks import AsyncGeneratorProviderMock, ModelProviderMock, YieldProviderMock DEFAULT_MESSAGES = [{'role': 'user', 'content': 'Hello'}] @@ -8,37 +10,38 @@ DEFAULT_MESSAGES = [{'role': 'user', 'content': 'Hello'}] class AsyncTestPassModel(unittest.IsolatedAsyncioTestCase): async def test_response(self): - client = Client(provider=AsyncGeneratorProviderMock) - response = await client.chat.completions.async_create(DEFAULT_MESSAGES, "") + client = AsyncClient(provider=AsyncGeneratorProviderMock) + response = await client.chat.completions.create(DEFAULT_MESSAGES, "") self.assertIsInstance(response, ChatCompletion) self.assertEqual("Mock", response.choices[0].message.content) async def test_pass_model(self): - client = Client(provider=ModelProviderMock) - response = await client.chat.completions.async_create(DEFAULT_MESSAGES, "Hello") + client = AsyncClient(provider=ModelProviderMock) + response = await client.chat.completions.create(DEFAULT_MESSAGES, "Hello") self.assertIsInstance(response, ChatCompletion) self.assertEqual("Hello", response.choices[0].message.content) async def test_max_tokens(self): - client = Client(provider=YieldProviderMock) + client = AsyncClient(provider=YieldProviderMock) messages = [{'role': 'user', 'content': chunk} for chunk in ["How ", "are ", "you", "?"]] - response = await client.chat.completions.async_create(messages, "Hello", max_tokens=1) + response = await client.chat.completions.create(messages, "Hello", max_tokens=1) self.assertIsInstance(response, ChatCompletion) self.assertEqual("How ", response.choices[0].message.content) - response = await client.chat.completions.async_create(messages, "Hello", max_tokens=2) + response = await client.chat.completions.create(messages, "Hello", max_tokens=2) self.assertIsInstance(response, ChatCompletion) self.assertEqual("How are ", response.choices[0].message.content) async def test_max_stream(self): - client = Client(provider=YieldProviderMock) + client = AsyncClient(provider=YieldProviderMock) messages = [{'role': 'user', 'content': chunk} for chunk in ["How ", "are ", "you", "?"]] - response = await client.chat.completions.async_create(messages, "Hello", stream=True) + response = client.chat.completions.create(messages, "Hello", stream=True) async for chunk in response: + chunk: ChatCompletionChunk = chunk self.assertIsInstance(chunk, ChatCompletionChunk) if chunk.choices[0].delta.content is not None: self.assertIsInstance(chunk.choices[0].delta.content, str) messages = [{'role': 'user', 'content': chunk} for chunk in ["You ", "You ", "Other", "?"]] - response = await client.chat.completions.async_create(messages, "Hello", stream=True, max_tokens=2) + response = client.chat.completions.create(messages, "Hello", stream=True, max_tokens=2) response_list = [] async for chunk in response: response_list.append(chunk) @@ -48,11 +51,58 @@ class AsyncTestPassModel(unittest.IsolatedAsyncioTestCase): self.assertEqual(chunk.choices[0].delta.content, "You ") async def test_stop(self): + client = AsyncClient(provider=YieldProviderMock) + messages = [{'role': 'user', 'content': chunk} for chunk in ["How ", "are ", "you", "?"]] + response = await client.chat.completions.create(messages, "Hello", stop=["and"]) + self.assertIsInstance(response, ChatCompletion) + self.assertEqual("How are you?", response.choices[0].message.content) + +class TestPassModel(unittest.TestCase): + + def test_response(self): + client = Client(provider=AsyncGeneratorProviderMock) + response = client.chat.completions.create(DEFAULT_MESSAGES, "") + self.assertIsInstance(response, ChatCompletion) + self.assertEqual("Mock", response.choices[0].message.content) + + def test_pass_model(self): + client = Client(provider=ModelProviderMock) + response = client.chat.completions.create(DEFAULT_MESSAGES, "Hello") + self.assertIsInstance(response, ChatCompletion) + self.assertEqual("Hello", response.choices[0].message.content) + + def test_max_tokens(self): + client = Client(provider=YieldProviderMock) + messages = [{'role': 'user', 'content': chunk} for chunk in ["How ", "are ", "you", "?"]] + response = client.chat.completions.create(messages, "Hello", max_tokens=1) + self.assertIsInstance(response, ChatCompletion) + self.assertEqual("How ", response.choices[0].message.content) + response = client.chat.completions.create(messages, "Hello", max_tokens=2) + self.assertIsInstance(response, ChatCompletion) + self.assertEqual("How are ", response.choices[0].message.content) + + def test_max_stream(self): + client = Client(provider=YieldProviderMock) + messages = [{'role': 'user', 'content': chunk} for chunk in ["How ", "are ", "you", "?"]] + response = client.chat.completions.create(messages, "Hello", stream=True) + for chunk in response: + self.assertIsInstance(chunk, ChatCompletionChunk) + if chunk.choices[0].delta.content is not None: + self.assertIsInstance(chunk.choices[0].delta.content, str) + messages = [{'role': 'user', 'content': chunk} for chunk in ["You ", "You ", "Other", "?"]] + response = client.chat.completions.create(messages, "Hello", stream=True, max_tokens=2) + response_list = list(response) + self.assertEqual(len(response_list), 3) + for chunk in response_list: + if chunk.choices[0].delta.content is not None: + self.assertEqual(chunk.choices[0].delta.content, "You ") + + def test_stop(self): client = Client(provider=YieldProviderMock) messages = [{'role': 'user', 'content': chunk} for chunk in ["How ", "are ", "you", "?"]] - response = await client.chat.completions.async_create(messages, "Hello", stop=["and"]) + response = client.chat.completions.create(messages, "Hello", stop=["and"]) self.assertIsInstance(response, ChatCompletion) self.assertEqual("How are you?", response.choices[0].message.content) if __name__ == '__main__': - unittest.main() + unittest.main() \ No newline at end of file -- cgit v1.2.3