Add duckduckgo-search to slim requirements,

Add pass provider as model in the client,
Fix missing @property in version utils
This commit is contained in:
Heiner Lohaus 2024-11-26 16:36:45 +01:00
parent 6b48af1757
commit cab71ca8b6
9 changed files with 64 additions and 11 deletions

View file

@ -292,7 +292,7 @@ client = AsyncClient(provider=g4f.Provider.OpenaiChat)
response = await client.chat.completions.create( response = await client.chat.completions.create(
model="gpt-4", model="gpt-4",
provider=g4f.Provider.Bing, provider=g4f.Provider.CopilotAccount,
messages=[ messages=[
{ {
"role": "user", "role": "user",

View file

@ -7,7 +7,7 @@ import g4f
g4f.debug.logging = True # Enable debug logging g4f.debug.logging = True # Enable debug logging
g4f.debug.version_check = False # Disable automatic version checking g4f.debug.version_check = False # Disable automatic version checking
print(g4f.Provider.Bing.params) # Print supported args for Bing print(g4f.Provider.Gemini.params) # Print supported args for Bing
# Using automatic a provider for the given model # Using automatic a provider for the given model
## Streamed completion ## Streamed completion
@ -78,7 +78,7 @@ for message in response:
Image upload and generation are supported by three main providers: Image upload and generation are supported by three main providers:
- **Bing & Other GPT-4 Providers:** Utilizes Microsoft's Image Creator. - **Microsoft Copilot & Other GPT-4 Providers:** Utilizes Microsoft's Image Creator.
- **Google Gemini:** Available for free accounts with IP addresses outside Europe. - **Google Gemini:** Available for free accounts with IP addresses outside Europe.
- **OpenaiChat with GPT-4:** Accessible for users with a Plus subscription. - **OpenaiChat with GPT-4:** Accessible for users with a Plus subscription.

View file

@ -2,7 +2,10 @@ from __future__ import annotations
import unittest import unittest
from g4f.client import Client, AsyncClient, ChatCompletion, ChatCompletionChunk from g4f.errors import ModelNotFoundError
from g4f.client import Client, AsyncClient, ChatCompletion, ChatCompletionChunk, get_model_and_provider
from g4f.Provider.Copilot import Copilot
from g4f.models import gpt_4o
from .mocks import AsyncGeneratorProviderMock, ModelProviderMock, YieldProviderMock from .mocks import AsyncGeneratorProviderMock, ModelProviderMock, YieldProviderMock
DEFAULT_MESSAGES = [{'role': 'user', 'content': 'Hello'}] DEFAULT_MESSAGES = [{'role': 'user', 'content': 'Hello'}]
@ -104,5 +107,35 @@ class TestPassModel(unittest.TestCase):
self.assertIsInstance(response, ChatCompletion) self.assertIsInstance(response, ChatCompletion)
self.assertEqual("How are you?", response.choices[0].message.content) self.assertEqual("How are you?", response.choices[0].message.content)
def test_model_not_found(self):
def run_exception():
client = Client()
client.chat.completions.create(DEFAULT_MESSAGES, "Hello")
self.assertRaises(ModelNotFoundError, run_exception)
def test_best_provider(self):
not_default_model = "gpt-4o"
model, provider = get_model_and_provider(not_default_model, None, False)
self.assertTrue(hasattr(provider, "create_completion"))
self.assertEqual(model, not_default_model)
def test_default_model(self):
default_model = ""
model, provider = get_model_and_provider(default_model, None, False)
self.assertTrue(hasattr(provider, "create_completion"))
self.assertEqual(model, default_model)
def test_provider_as_model(self):
provider_as_model = Copilot.__name__
model, provider = get_model_and_provider(provider_as_model, None, False)
self.assertTrue(hasattr(provider, "create_completion"))
self.assertIsInstance(model, str)
self.assertEqual(model, Copilot.default_model)
def test_get_model(self):
model, provider = get_model_and_provider(gpt_4o.name, None, False)
self.assertTrue(hasattr(provider, "create_completion"))
self.assertEqual(model, gpt_4o.name)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View file

@ -1,7 +1,9 @@
import unittest import unittest
import asyncio import asyncio
import g4f import g4f
from g4f import ChatCompletion, get_last_provider from g4f import ChatCompletion, get_last_provider
from g4f.errors import VersionNotFoundError
from g4f.Provider import RetryProvider from g4f.Provider import RetryProvider
from .mocks import ProviderMock from .mocks import ProviderMock
@ -27,4 +29,11 @@ class TestGetLastProvider(unittest.TestCase):
last_provider_dict = get_last_provider(True) last_provider_dict = get_last_provider(True)
self.assertIsInstance(last_provider_dict, dict) self.assertIsInstance(last_provider_dict, dict)
self.assertIn('name', last_provider_dict) self.assertIn('name', last_provider_dict)
self.assertEqual(ProviderMock.__name__, last_provider_dict['name']) self.assertEqual(ProviderMock.__name__, last_provider_dict['name'])
def test_get_latest_version(self):
try:
self.assertIsInstance(g4f.version.utils.current_version, str)
except VersionNotFoundError:
pass
self.assertIsInstance(g4f.version.utils.latest_version, str)

View file

@ -61,9 +61,15 @@ def get_model_and_provider(model : Union[Model, str],
if not provider: if not provider:
if not model: if not model:
model = default model = default
provider = model.best_provider
elif isinstance(model, str): elif isinstance(model, str):
raise ModelNotFoundError(f'Model not found: {model}') if model in ProviderUtils.convert:
provider = model.best_provider provider = ProviderUtils.convert[model]
model = provider.default_model if hasattr(provider, "default_model") else ""
else:
raise ModelNotFoundError(f'Model not found: {model}')
else:
provider = model.best_provider
if not provider: if not provider:
raise ProviderNotFoundError(f'No provider found for model: {model}') raise ProviderNotFoundError(f'No provider found for model: {model}')

View file

@ -1327,6 +1327,8 @@ async function on_api() {
} }
async function load_version() { async function load_version() {
let new_version = document.querySelector(".new_version");
if (new_version) return;
const versions = await api("version"); const versions = await api("version");
document.title = 'g4f - ' + versions["version"]; document.title = 'g4f - ' + versions["version"];
let text = "version ~ " let text = "version ~ "
@ -1334,7 +1336,7 @@ async function load_version() {
let release_url = 'https://github.com/xtekky/gpt4free/releases/latest'; let release_url = 'https://github.com/xtekky/gpt4free/releases/latest';
let title = `New version: ${versions["latest_version"]}`; let title = `New version: ${versions["latest_version"]}`;
text += `<a href="${release_url}" target="_blank" title="${title}">${versions["version"]}</a> 🆕`; text += `<a href="${release_url}" target="_blank" title="${title}">${versions["version"]}</a> 🆕`;
const new_version = document.createElement("div"); new_version = document.createElement("div");
new_version.classList.add("new_version"); new_version.classList.add("new_version");
const link = `<a href="${release_url}" target="_blank" title="${title}">v${versions["latest_version"]}</a>`; const link = `<a href="${release_url}" target="_blank" title="${title}">v${versions["latest_version"]}</a>`;
new_version.innerHTML = `g4f ${link}&nbsp;&nbsp;🆕`; new_version.innerHTML = `g4f ${link}&nbsp;&nbsp;🆕`;
@ -1344,6 +1346,7 @@ async function load_version() {
text += versions["version"]; text += versions["version"];
} }
document.getElementById("version_text").innerHTML = text document.getElementById("version_text").innerHTML = text
setTimeout(load_version, 1000 * 60 * 60); // 1 hour
} }
setTimeout(load_version, 100); setTimeout(load_version, 100);

View file

@ -123,6 +123,7 @@ def get_session_from_browser(url: str, webdriver: WebDriver = None, proxy: str =
timeout=timeout, timeout=timeout,
impersonate="chrome" impersonate="chrome"
) )
def get_cookie_params_from_dict(cookies: Cookies, url: str = None, domain: str = None) -> list[CookieParam]: def get_cookie_params_from_dict(cookies: Cookies, url: str = None, domain: str = None) -> list[CookieParam]:
[CookieParam.from_json({ [CookieParam.from_json({
"name": key, "name": key,
@ -172,12 +173,12 @@ def merge_cookies(cookies: Iterator[Morsel], response: Response) -> Cookies:
cookies = {} cookies = {}
for cookie in response.cookies.jar: for cookie in response.cookies.jar:
cookies[cookie.name] = cookie.value cookies[cookie.name] = cookie.value
async def get_nodriver(proxy: str = None, **kwargs)-> Browser: async def get_nodriver(proxy: str = None, **kwargs)-> Browser:
if not has_nodriver: if not has_nodriver:
raise MissingRequirementsError('Install "nodriver" package | pip install -U nodriver') raise MissingRequirementsError('Install "nodriver" package | pip install -U nodriver')
user_data_dir = user_config_dir("g4f-nodriver") if has_platformdirs else None user_data_dir = user_config_dir("g4f-nodriver") if has_platformdirs else None
debug.log(f"Copilot: Open nodriver with user_dir: {user_data_dir}") debug.log(f"Open nodriver with user_dir: {user_data_dir}")
return await nodriver.start( return await nodriver.start(
user_data_dir=user_data_dir, user_data_dir=user_data_dir,
browser_args=None if proxy is None else [f"--proxy-server={proxy}"], browser_args=None if proxy is None else [f"--proxy-server={proxy}"],

View file

@ -88,7 +88,7 @@ class VersionUtils:
raise VersionNotFoundError("Version not found") raise VersionNotFoundError("Version not found")
@cached_property @property
def latest_version(self) -> str: def latest_version(self) -> str:
""" """
Retrieves the latest version of the 'g4f' package. Retrieves the latest version of the 'g4f' package.

View file

@ -3,6 +3,7 @@ pycryptodome
curl_cffi>=0.6.2 curl_cffi>=0.6.2
aiohttp aiohttp
certifi certifi
duckduckgo-search>=6.3.7
nest_asyncio nest_asyncio
werkzeug werkzeug
pillow pillow