From e46b5fe043ffcdb87ddb97db14a7e699dd8a2690 Mon Sep 17 00:00:00 2001 From: Heiner Lohaus Date: Mon, 9 Oct 2023 10:22:17 +0200 Subject: [PATCH 01/12] Add proxy support to all providers --- g4f/Provider/AItianhu.py | 8 ++++---- g4f/Provider/AItianhuSpace.py | 8 ++++---- g4f/Provider/Acytoo.py | 7 +++---- g4f/Provider/AiAsk.py | 9 +++++---- g4f/Provider/Aibn.py | 15 ++++++++++----- g4f/Provider/Aichat.py | 3 ++- g4f/Provider/Ails.py | 6 +++--- g4f/Provider/Aivvm.py | 16 +++++++++++----- g4f/Provider/Bing.py | 31 +++++++++++++++++-------------- g4f/Provider/ChatBase.py | 9 +++++---- g4f/Provider/ChatForAi.py | 11 ++++++----- g4f/Provider/Chatgpt4Online.py | 9 +++++---- g4f/Provider/ChatgptAi.py | 3 ++- g4f/Provider/ChatgptDemo.py | 6 +++--- g4f/Provider/ChatgptDuo.py | 5 +++-- g4f/Provider/ChatgptX.py | 7 ++++--- g4f/Provider/Cromicle.py | 6 +++--- g4f/Provider/DeepAi.py | 8 ++++---- g4f/Provider/FreeGpt.py | 9 +++++++-- g4f/Provider/GPTalk.py | 13 +++++++------ g4f/Provider/GptForLove.py | 9 +++++---- g4f/Provider/GptGo.py | 2 +- g4f/Provider/GptGod.py | 11 ++++++----- g4f/Provider/Liaobots.py | 6 +++--- g4f/Provider/Myshell.py | 4 +++- g4f/Provider/Phind.py | 9 ++++++++- g4f/Provider/Vercel.py | 14 +++++++++----- g4f/Provider/Vitalentum.py | 2 +- g4f/__init__.py | 29 ++++++++++++++++++----------- 29 files changed, 162 insertions(+), 113 deletions(-) diff --git a/g4f/Provider/AItianhu.py b/g4f/Provider/AItianhu.py index c6e4dbad..56d9a9ab 100644 --- a/g4f/Provider/AItianhu.py +++ b/g4f/Provider/AItianhu.py @@ -2,7 +2,7 @@ from __future__ import annotations import json -from ..typing import AsyncGenerator +from ..typing import AsyncResult, Messages from ..requests import StreamSession from .base_provider import AsyncGeneratorProvider, format_prompt, get_cookies @@ -16,12 +16,12 @@ class AItianhu(AsyncGeneratorProvider): async def create_async_generator( cls, model: str, - messages: list[dict[str, str]], + messages: Messages, proxy: str = None, cookies: dict = None, - timeout: int = 30, + timeout: int = 120, **kwargs - ) -> AsyncGenerator: + ) -> AsyncResult: if not cookies: cookies = get_cookies("www.aitianhu.com") data = { diff --git a/g4f/Provider/AItianhuSpace.py b/g4f/Provider/AItianhuSpace.py index 78cdf657..7eb93d48 100644 --- a/g4f/Provider/AItianhuSpace.py +++ b/g4f/Provider/AItianhuSpace.py @@ -2,7 +2,7 @@ from __future__ import annotations import random, json -from ..typing import AsyncGenerator +from ..typing import AsyncResult, Messages from ..requests import StreamSession from .base_provider import AsyncGeneratorProvider, format_prompt, get_cookies @@ -20,13 +20,13 @@ class AItianhuSpace(AsyncGeneratorProvider): async def create_async_generator( cls, model: str, - messages: list[dict[str, str]], + messages: Messages, proxy: str = None, domain: str = None, cookies: dict = None, - timeout: int = 30, + timeout: int = 120, **kwargs - ) -> AsyncGenerator: + ) -> AsyncResult: if not model: model = "gpt-3.5-turbo" elif not model in domains: diff --git a/g4f/Provider/Acytoo.py b/g4f/Provider/Acytoo.py index d36ca6da..0ac3425c 100644 --- a/g4f/Provider/Acytoo.py +++ b/g4f/Provider/Acytoo.py @@ -2,7 +2,7 @@ from __future__ import annotations from aiohttp import ClientSession -from ..typing import AsyncGenerator +from ..typing import AsyncResult, Messages from .base_provider import AsyncGeneratorProvider @@ -15,11 +15,10 @@ class Acytoo(AsyncGeneratorProvider): async def create_async_generator( cls, model: str, - messages: list[dict[str, str]], + messages: Messages, proxy: str = None, **kwargs - ) -> AsyncGenerator: - + ) -> AsyncResult: async with ClientSession( headers=_create_header() ) as session: diff --git a/g4f/Provider/AiAsk.py b/g4f/Provider/AiAsk.py index 27d3bf15..f10be389 100644 --- a/g4f/Provider/AiAsk.py +++ b/g4f/Provider/AiAsk.py @@ -1,7 +1,7 @@ from __future__ import annotations from aiohttp import ClientSession -from ..typing import AsyncGenerator +from ..typing import AsyncResult, Messages from .base_provider import AsyncGeneratorProvider class AiAsk(AsyncGeneratorProvider): @@ -13,9 +13,10 @@ class AiAsk(AsyncGeneratorProvider): async def create_async_generator( cls, model: str, - messages: list[dict[str, str]], + messages: Messages, + proxy: str = None, **kwargs - ) -> AsyncGenerator: + ) -> AsyncResult: headers = { "accept": "application/json, text/plain, */*", "origin": cls.url, @@ -33,7 +34,7 @@ class AiAsk(AsyncGeneratorProvider): } buffer = "" rate_limit = "您的免费额度不够使用这个模型啦,请点击右上角登录继续使用!" - async with session.post(f"{cls.url}/v1/chat/gpt/", json=data) as response: + async with session.post(f"{cls.url}/v1/chat/gpt/", json=data, proxy=proxy) as response: response.raise_for_status() async for chunk in response.content.iter_any(): buffer += chunk.decode() diff --git a/g4f/Provider/Aibn.py b/g4f/Provider/Aibn.py index 3399d613..13f5c71e 100644 --- a/g4f/Provider/Aibn.py +++ b/g4f/Provider/Aibn.py @@ -3,7 +3,7 @@ from __future__ import annotations import time import hashlib -from ..typing import AsyncGenerator +from ..typing import AsyncResult, Messages from ..requests import StreamSession from .base_provider import AsyncGeneratorProvider @@ -17,11 +17,16 @@ class Aibn(AsyncGeneratorProvider): async def create_async_generator( cls, model: str, - messages: list[dict[str, str]], - timeout: int = 30, + messages: Messages, + proxy: str = None, + timeout: int = 120, **kwargs - ) -> AsyncGenerator: - async with StreamSession(impersonate="chrome107", timeout=timeout) as session: + ) -> AsyncResult: + async with StreamSession( + impersonate="chrome107", + proxies={"https": proxy}, + timeout=timeout + ) as session: timestamp = int(time.time()) data = { "messages": messages, diff --git a/g4f/Provider/Aichat.py b/g4f/Provider/Aichat.py index 8edd17e2..ddc9eb1d 100644 --- a/g4f/Provider/Aichat.py +++ b/g4f/Provider/Aichat.py @@ -2,6 +2,7 @@ from __future__ import annotations from aiohttp import ClientSession +from ..typing import Messages from .base_provider import AsyncProvider, format_prompt @@ -13,7 +14,7 @@ class Aichat(AsyncProvider): @staticmethod async def create_async( model: str, - messages: list[dict[str, str]], + messages: Messages, proxy: str = None, **kwargs ) -> str: diff --git a/g4f/Provider/Ails.py b/g4f/Provider/Ails.py index d533ae24..c1384faa 100644 --- a/g4f/Provider/Ails.py +++ b/g4f/Provider/Ails.py @@ -7,7 +7,7 @@ import json from datetime import datetime from aiohttp import ClientSession -from ..typing import SHA256, AsyncGenerator +from ..typing import SHA256, AsyncResult, Messages from .base_provider import AsyncGeneratorProvider @@ -19,11 +19,11 @@ class Ails(AsyncGeneratorProvider): @staticmethod async def create_async_generator( model: str, - messages: list[dict[str, str]], + messages: Messages, stream: bool, proxy: str = None, **kwargs - ) -> AsyncGenerator: + ) -> AsyncResult: headers = { "authority": "api.caipacity.com", "accept": "*/*", diff --git a/g4f/Provider/Aivvm.py b/g4f/Provider/Aivvm.py index 1a3b6f0b..83495a22 100644 --- a/g4f/Provider/Aivvm.py +++ b/g4f/Provider/Aivvm.py @@ -2,7 +2,7 @@ from __future__ import annotations from ..requests import StreamSession from .base_provider import AsyncGeneratorProvider -from ..typing import AsyncGenerator +from ..typing import AsyncResult, Messages # to recreate this easily, send a post request to https://chat.aivvm.com/api/models models = { @@ -26,11 +26,12 @@ class Aivvm(AsyncGeneratorProvider): async def create_async_generator( cls, model: str, - messages: list[dict[str, str]], + messages: Messages, stream: bool, - timeout: int = 30, + proxy: str = None, + timeout: int = 120, **kwargs - ) -> AsyncGenerator: + ) -> AsyncResult: if not model: model = "gpt-3.5-turbo" elif model not in models: @@ -48,7 +49,12 @@ class Aivvm(AsyncGeneratorProvider): "Origin": cls.url, "Referer": f"{cls.url}/", } - async with StreamSession(impersonate="chrome107", headers=headers, timeout=timeout) as session: + async with StreamSession( + impersonate="chrome107", + headers=headers, + proxies={"https": proxy}, + timeout=timeout + ) as session: async with session.post(f"{cls.url}/api/chat", json=json_data) as response: response.raise_for_status() async for chunk in response.iter_content(): diff --git a/g4f/Provider/Bing.py b/g4f/Provider/Bing.py index f4275a5f..f8c6a87a 100644 --- a/g4f/Provider/Bing.py +++ b/g4f/Provider/Bing.py @@ -7,7 +7,7 @@ import os import uuid import urllib.parse from aiohttp import ClientSession, ClientTimeout -from ..typing import AsyncGenerator +from ..typing import AsyncResult, Messages from .base_provider import AsyncGeneratorProvider class Tones(): @@ -32,11 +32,12 @@ class Bing(AsyncGeneratorProvider): @staticmethod def create_async_generator( model: str, - messages: list[dict[str, str]], + messages: Messages, + proxy: str = None, cookies: dict = None, tone: str = Tones.creative, **kwargs - ) -> AsyncGenerator: + ) -> AsyncResult: if len(messages) < 2: prompt = messages[0]["content"] context = None @@ -46,9 +47,9 @@ class Bing(AsyncGeneratorProvider): if not cookies or "SRCHD" not in cookies: cookies = default_cookies - return stream_generate(prompt, tone, context, cookies) + return stream_generate(prompt, tone, context, proxy, cookies) -def create_context(messages: list[dict[str, str]]): +def create_context(messages: Messages): context = "".join(f"[{message['role']}](#message)\n{message['content']}\n\n" for message in messages) return context @@ -59,10 +60,10 @@ class Conversation(): self.clientId = clientId self.conversationSignature = conversationSignature -async def create_conversation(session: ClientSession) -> Conversation: +async def create_conversation(session: ClientSession, proxy: str = None) -> Conversation: url = 'https://www.bing.com/turing/conversation/create?bundleVersion=1.1150.3' - async with await session.get(url) as response: + async with await session.get(url, proxy=proxy) as response: data = await response.json() conversationId = data.get('conversationId') @@ -80,7 +81,7 @@ async def list_conversations(session: ClientSession) -> list: response = await response.json() return response["chats"] -async def delete_conversation(session: ClientSession, conversation: Conversation) -> list: +async def delete_conversation(session: ClientSession, conversation: Conversation, proxy: str = None) -> list: url = "https://sydney.bing.com/sydney/DeleteSingleConversation" json = { "conversationId": conversation.conversationId, @@ -89,7 +90,7 @@ async def delete_conversation(session: ClientSession, conversation: Conversation "source": "cib", "optionsSets": ["autosave"] } - async with session.post(url, json=json) as response: + async with session.post(url, json=json, proxy=proxy) as response: response = await response.json() return response["result"]["value"] == "Success" @@ -239,20 +240,22 @@ def create_message(conversation: Conversation, prompt: str, tone: str, context: async def stream_generate( prompt: str, tone: str, - context: str=None, - cookies: dict=None, + context: str = None, + proxy: str = None, + cookies: dict = None ): async with ClientSession( timeout=ClientTimeout(total=900), cookies=cookies, headers=Defaults.headers, ) as session: - conversation = await create_conversation(session) + conversation = await create_conversation(session, proxy) try: async with session.ws_connect( f'wss://sydney.bing.com/sydney/ChatHub', autoping=False, - params={'sec_access_token': conversation.conversationSignature} + params={'sec_access_token': conversation.conversationSignature}, + proxy=proxy ) as wss: await wss.send_str(format_message({'protocol': 'json', 'version': 1})) @@ -297,4 +300,4 @@ async def stream_generate( raise Exception(f"{result['value']}: {result['message']}") return finally: - await delete_conversation(session, conversation) \ No newline at end of file + await delete_conversation(session, conversation, proxy) \ No newline at end of file diff --git a/g4f/Provider/ChatBase.py b/g4f/Provider/ChatBase.py index b98fe565..ce5160d8 100644 --- a/g4f/Provider/ChatBase.py +++ b/g4f/Provider/ChatBase.py @@ -2,7 +2,7 @@ from __future__ import annotations from aiohttp import ClientSession -from ..typing import AsyncGenerator +from ..typing import AsyncResult, Messages from .base_provider import AsyncGeneratorProvider @@ -16,9 +16,10 @@ class ChatBase(AsyncGeneratorProvider): async def create_async_generator( cls, model: str, - messages: list[dict[str, str]], + messages: Messages, + proxy: str = None, **kwargs - ) -> AsyncGenerator: + ) -> AsyncResult: if model == "gpt-4": chat_id = "quran---tafseer-saadi-pdf-wbgknt7zn" elif model == "gpt-3.5-turbo" or not model: @@ -44,7 +45,7 @@ class ChatBase(AsyncGeneratorProvider): "chatId": chat_id, "conversationId": f"kcXpqEnqUie3dnJlsRi_O-{chat_id}" } - async with session.post("https://www.chatbase.co/api/fe/chat", json=data) as response: + async with session.post("https://www.chatbase.co/api/fe/chat", json=data, proxy=proxy) as response: response.raise_for_status() async for stream in response.content.iter_any(): yield stream.decode() diff --git a/g4f/Provider/ChatForAi.py b/g4f/Provider/ChatForAi.py index 86b29639..f2fe0335 100644 --- a/g4f/Provider/ChatForAi.py +++ b/g4f/Provider/ChatForAi.py @@ -1,6 +1,6 @@ from __future__ import annotations -from ..typing import AsyncGenerator +from ..typing import AsyncResult, Messages from ..requests import StreamSession from .base_provider import AsyncGeneratorProvider @@ -14,11 +14,12 @@ class ChatForAi(AsyncGeneratorProvider): async def create_async_generator( cls, model: str, - messages: list[dict[str, str]], - timeout: int = 30, + messages: Messages, + proxy: str = None, + timeout: int = 120, **kwargs - ) -> AsyncGenerator: - async with StreamSession(impersonate="chrome107", timeout=timeout) as session: + ) -> AsyncResult: + async with StreamSession(impersonate="chrome107", proxies={"https": proxy}, timeout=timeout) as session: prompt = messages[-1]["content"] data = { "conversationId": "temp", diff --git a/g4f/Provider/Chatgpt4Online.py b/g4f/Provider/Chatgpt4Online.py index b9631429..bfcb1dec 100644 --- a/g4f/Provider/Chatgpt4Online.py +++ b/g4f/Provider/Chatgpt4Online.py @@ -3,7 +3,7 @@ from __future__ import annotations import json from aiohttp import ClientSession -from ..typing import AsyncGenerator +from ..typing import AsyncResult, Messages from .base_provider import AsyncGeneratorProvider @@ -16,9 +16,10 @@ class Chatgpt4Online(AsyncGeneratorProvider): async def create_async_generator( cls, model: str, - messages: list[dict[str, str]], + messages: Messages, + proxy: str = None, **kwargs - ) -> AsyncGenerator: + ) -> AsyncResult: async with ClientSession() as session: data = { "botId": "default", @@ -30,7 +31,7 @@ class Chatgpt4Online(AsyncGeneratorProvider): "newMessage": messages[-1]["content"], "stream": True } - async with session.post(cls.url + "/wp-json/mwai-ui/v1/chats/submit", json=data) as response: + async with session.post(cls.url + "/wp-json/mwai-ui/v1/chats/submit", json=data, proxy=proxy) as response: response.raise_for_status() async for line in response.content: if line.startswith(b"data: "): diff --git a/g4f/Provider/ChatgptAi.py b/g4f/Provider/ChatgptAi.py index 996f99a5..cf45909c 100644 --- a/g4f/Provider/ChatgptAi.py +++ b/g4f/Provider/ChatgptAi.py @@ -3,6 +3,7 @@ from __future__ import annotations import re from aiohttp import ClientSession +from ..typing import Messages from .base_provider import AsyncProvider, format_prompt @@ -18,7 +19,7 @@ class ChatgptAi(AsyncProvider): async def create_async( cls, model: str, - messages: list[dict[str, str]], + messages: Messages, proxy: str = None, **kwargs ) -> str: diff --git a/g4f/Provider/ChatgptDemo.py b/g4f/Provider/ChatgptDemo.py index 95cb9ecf..875751b9 100644 --- a/g4f/Provider/ChatgptDemo.py +++ b/g4f/Provider/ChatgptDemo.py @@ -2,8 +2,8 @@ from __future__ import annotations import time, json, re from aiohttp import ClientSession -from typing import AsyncGenerator +from ..typing import AsyncResult, Messages from .base_provider import AsyncGeneratorProvider from .helper import format_prompt @@ -16,10 +16,10 @@ class ChatgptDemo(AsyncGeneratorProvider): async def create_async_generator( cls, model: str, - messages: list[dict[str, str]], + messages: Messages, proxy: str = None, **kwargs - ) -> AsyncGenerator: + ) -> AsyncResult: headers = { "authority": "chat.chatgptdemo.net", "accept-language": "de-DE,de;q=0.9,en-DE;q=0.8,en;q=0.7,en-US", diff --git a/g4f/Provider/ChatgptDuo.py b/g4f/Provider/ChatgptDuo.py index 119ff16b..039efc84 100644 --- a/g4f/Provider/ChatgptDuo.py +++ b/g4f/Provider/ChatgptDuo.py @@ -1,5 +1,6 @@ from __future__ import annotations +from ..typing import Messages from curl_cffi.requests import AsyncSession from .base_provider import AsyncProvider, format_prompt @@ -13,9 +14,9 @@ class ChatgptDuo(AsyncProvider): async def create_async( cls, model: str, - messages: list[dict[str, str]], + messages: Messages, proxy: str = None, - timeout: int = 30, + timeout: int = 120, **kwargs ) -> str: async with AsyncSession( diff --git a/g4f/Provider/ChatgptX.py b/g4f/Provider/ChatgptX.py index 2944fb26..8052f65b 100644 --- a/g4f/Provider/ChatgptX.py +++ b/g4f/Provider/ChatgptX.py @@ -19,6 +19,7 @@ class ChatgptX(AsyncGeneratorProvider): cls, model: str, messages: Messages, + proxy: str = None, **kwargs ) -> AsyncResult: headers = { @@ -32,7 +33,7 @@ class ChatgptX(AsyncGeneratorProvider): 'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36', } async with ClientSession(headers=headers) as session: - async with session.get(f"{cls.url}/") as response: + async with session.get(f"{cls.url}/", proxy=proxy) as response: response = await response.text() result = re.search(r' AsyncGenerator[str, None]: + ) -> AsyncResult: async with ClientSession( headers=_create_header() ) as session: diff --git a/g4f/Provider/DeepAi.py b/g4f/Provider/DeepAi.py index bac3e3fe..e1ee4446 100644 --- a/g4f/Provider/DeepAi.py +++ b/g4f/Provider/DeepAi.py @@ -6,22 +6,22 @@ import random import hashlib from aiohttp import ClientSession -from ..typing import AsyncGenerator +from ..typing import AsyncResult, Messages from .base_provider import AsyncGeneratorProvider class DeepAi(AsyncGeneratorProvider): - url: str = "https://deepai.org" + url = "https://deepai.org" working = True supports_gpt_35_turbo = True @staticmethod async def create_async_generator( model: str, - messages: list[dict[str, str]], + messages: Messages, proxy: str = None, **kwargs - ) -> AsyncGenerator: + ) -> AsyncResult: token_js = """ var agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36' diff --git a/g4f/Provider/FreeGpt.py b/g4f/Provider/FreeGpt.py index 73b8acea..c9c05131 100644 --- a/g4f/Provider/FreeGpt.py +++ b/g4f/Provider/FreeGpt.py @@ -21,10 +21,15 @@ class FreeGpt(AsyncGeneratorProvider): cls, model: str, messages: list[dict[str, str]], - timeout: int = 30, + proxy: str = None, + timeout: int = 120, **kwargs ) -> AsyncGenerator: - async with StreamSession(impersonate="chrome107", timeout=timeout) as session: + async with StreamSession( + impersonate="chrome107", + timeout=timeout, + proxies={"https": proxy} + ) as session: prompt = messages[-1]["content"] timestamp = int(time.time()) data = { diff --git a/g4f/Provider/GPTalk.py b/g4f/Provider/GPTalk.py index c85399c1..afb6ff68 100644 --- a/g4f/Provider/GPTalk.py +++ b/g4f/Provider/GPTalk.py @@ -2,8 +2,8 @@ from __future__ import annotations import secrets, time, json from aiohttp import ClientSession -from typing import AsyncGenerator +from ..typing import AsyncResult, Messages from .base_provider import AsyncGeneratorProvider from .helper import format_prompt @@ -18,9 +18,10 @@ class GPTalk(AsyncGeneratorProvider): async def create_async_generator( cls, model: str, - messages: list[dict[str, str]], + messages: Messages, + proxy: str = None, **kwargs - ) -> AsyncGenerator: + ) -> AsyncResult: if not model: model = "gpt-3.5-turbo" timestamp = int(time.time()) @@ -48,7 +49,7 @@ class GPTalk(AsyncGeneratorProvider): "fingerprint": secrets.token_hex(16).zfill(32), "platform": "fingerprint" } - async with session.post(cls.url + "/api/chatgpt/user/login", json=data) as response: + async with session.post(cls.url + "/api/chatgpt/user/login", json=data, proxy=proxy) as response: response.raise_for_status() cls._auth = (await response.json())["data"] data = { @@ -68,11 +69,11 @@ class GPTalk(AsyncGeneratorProvider): headers = { 'authorization': f'Bearer {cls._auth["token"]}', } - async with session.post(cls.url + "/api/chatgpt/chatapi/text", json=data, headers=headers) as response: + async with session.post(cls.url + "/api/chatgpt/chatapi/text", json=data, headers=headers, proxy=proxy) as response: response.raise_for_status() token = (await response.json())["data"]["token"] last_message = "" - async with session.get(cls.url + "/api/chatgpt/chatapi/stream", params={"token": token}) as response: + async with session.get(cls.url + "/api/chatgpt/chatapi/stream", params={"token": token}, proxy=proxy) as response: response.raise_for_status() async for line in response.content: if line.startswith(b"data: "): diff --git a/g4f/Provider/GptForLove.py b/g4f/Provider/GptForLove.py index 53c403e1..01cef443 100644 --- a/g4f/Provider/GptForLove.py +++ b/g4f/Provider/GptForLove.py @@ -3,7 +3,7 @@ from __future__ import annotations from aiohttp import ClientSession import execjs, os, json -from ..typing import AsyncGenerator +from ..typing import AsyncResult, Messages from .base_provider import AsyncGeneratorProvider from .helper import format_prompt @@ -16,9 +16,10 @@ class GptForLove(AsyncGeneratorProvider): async def create_async_generator( cls, model: str, - messages: list[dict[str, str]], + messages: Messages, + proxy: str = None, **kwargs - ) -> AsyncGenerator: + ) -> AsyncResult: if not model: model = "gpt-3.5-turbo" headers = { @@ -47,7 +48,7 @@ class GptForLove(AsyncGeneratorProvider): "secret": get_secret(), **kwargs } - async with session.post("https://api.gptplus.one/chat-process", json=data) as response: + async with session.post("https://api.gptplus.one/chat-process", json=data, proxy=proxy) as response: response.raise_for_status() async for line in response.content: try: diff --git a/g4f/Provider/GptGo.py b/g4f/Provider/GptGo.py index 51764221..5f6cc362 100644 --- a/g4f/Provider/GptGo.py +++ b/g4f/Provider/GptGo.py @@ -18,7 +18,6 @@ class GptGo(AsyncGeneratorProvider): model: str, messages: list[dict[str, str]], proxy: str = None, - timeout: int = 30, **kwargs ) -> AsyncGenerator: headers = { @@ -73,6 +72,7 @@ class GptGo(AsyncGeneratorProvider): ("model", "str"), ("messages", "list[dict[str, str]]"), ("stream", "bool"), + ("proxy", "str"), ("temperature", "float"), ] param = ", ".join([": ".join(p) for p in params]) diff --git a/g4f/Provider/GptGod.py b/g4f/Provider/GptGod.py index 662884dd..6c975389 100644 --- a/g4f/Provider/GptGod.py +++ b/g4f/Provider/GptGod.py @@ -1,7 +1,7 @@ from __future__ import annotations import secrets, json from aiohttp import ClientSession -from typing import AsyncGenerator +from ..typing import AsyncResult, Messages from .base_provider import AsyncGeneratorProvider from .helper import format_prompt @@ -14,9 +14,10 @@ class GptGod(AsyncGeneratorProvider): async def create_async_generator( cls, model: str, - messages: list[dict[str, str]], + messages: Messages, + proxy: str = None, **kwargs - ) -> AsyncGenerator: + ) -> AsyncResult: headers = { "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/118.0", "Accept": "text/event-stream", @@ -24,7 +25,7 @@ class GptGod(AsyncGeneratorProvider): "Accept-Encoding": "gzip, deflate, br", "Alt-Used": "gptgod.site", "Connection": "keep-alive", - "Referer": "https://gptgod.site/", + "Referer": f"{cls.url}/", "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-origin", @@ -37,7 +38,7 @@ class GptGod(AsyncGeneratorProvider): "content": prompt, "id": secrets.token_hex(16).zfill(32) } - async with session.get(f"{cls.url}/api/session/free/gpt3p5", params=data) as response: + async with session.get(f"{cls.url}/api/session/free/gpt3p5", params=data, proxy=proxy) as response: response.raise_for_status() event = None async for line in response.content: diff --git a/g4f/Provider/Liaobots.py b/g4f/Provider/Liaobots.py index 2ab96ce3..740be856 100644 --- a/g4f/Provider/Liaobots.py +++ b/g4f/Provider/Liaobots.py @@ -4,7 +4,7 @@ import uuid from aiohttp import ClientSession -from ..typing import AsyncGenerator +from ..typing import AsyncResult, Messages from .base_provider import AsyncGeneratorProvider models = { @@ -39,11 +39,11 @@ class Liaobots(AsyncGeneratorProvider): async def create_async_generator( cls, model: str, - messages: list[dict[str, str]], + messages: Messages, auth: str = None, proxy: str = None, **kwargs - ) -> AsyncGenerator: + ) -> AsyncResult: model = model if model in models else "gpt-3.5-turbo" headers = { "authority": "liaobots.com", diff --git a/g4f/Provider/Myshell.py b/g4f/Provider/Myshell.py index da170fa3..6ed4fd7a 100644 --- a/g4f/Provider/Myshell.py +++ b/g4f/Provider/Myshell.py @@ -28,6 +28,7 @@ class Myshell(AsyncGeneratorProvider): cls, model: str, messages: list[dict[str, str]], + proxy: str = None, timeout: int = 90, **kwargs ) -> AsyncGenerator: @@ -47,7 +48,8 @@ class Myshell(AsyncGeneratorProvider): async with session.ws_connect( "wss://api.myshell.ai/ws/?EIO=4&transport=websocket", autoping=False, - timeout=timeout + timeout=timeout, + proxy=proxy ) as wss: # Send and receive hello message await wss.receive_str() diff --git a/g4f/Provider/Phind.py b/g4f/Provider/Phind.py index 0db4e3c2..ae4de686 100644 --- a/g4f/Provider/Phind.py +++ b/g4f/Provider/Phind.py @@ -19,6 +19,7 @@ class Phind(AsyncGeneratorProvider): model: str, messages: list[dict[str, str]], proxy: str = None, + timeout: int = 120, **kwargs ) -> AsyncGenerator: chars = 'abcdefghijklmnopqrstuvwxyz0123456789' @@ -43,7 +44,12 @@ class Phind(AsyncGeneratorProvider): "Origin": cls.url, "Referer": f"{cls.url}/" } - async with StreamSession(headers=headers, timeout=(5, 180), proxies={"https": proxy}, impersonate="chrome107") as session: + async with StreamSession( + headers=headers, + timeout=(5, timeout), + proxies={"https": proxy}, + impersonate="chrome107" + ) as session: async with session.post(f"{cls.url}/api/infer/answer", json=data) as response: response.raise_for_status() new_lines = 0 @@ -71,6 +77,7 @@ class Phind(AsyncGeneratorProvider): ("messages", "list[dict[str, str]]"), ("stream", "bool"), ("proxy", "str"), + ("timeout", "int"), ] param = ", ".join([": ".join(p) for p in params]) return f"g4f.provider.{cls.__name__} supports: ({param})" diff --git a/g4f/Provider/Vercel.py b/g4f/Provider/Vercel.py index 2d20ca6a..2d856664 100644 --- a/g4f/Provider/Vercel.py +++ b/g4f/Provider/Vercel.py @@ -2,7 +2,7 @@ from __future__ import annotations import json, base64, requests, execjs, random, uuid -from ..typing import Any, TypedDict, CreateResult +from ..typing import Messages, TypedDict, CreateResult from .base_provider import BaseProvider from abc import abstractmethod @@ -17,8 +17,9 @@ class Vercel(BaseProvider): @abstractmethod def create_completion( model: str, - messages: list[dict[str, str]], + messages: Messages, stream: bool, + proxy: str = None, **kwargs ) -> CreateResult: if not model: @@ -52,15 +53,18 @@ class Vercel(BaseProvider): 'model' : model_info[model]['id'], 'messages' : messages, 'playgroundId': str(uuid.uuid4()), - 'chatIndex' : 0} | model_info[model]['default_params'] + 'chatIndex' : 0, + **model_info[model]['default_params'], + **kwargs + } max_retries = kwargs.get('max_retries', 20) for i in range(max_retries): response = requests.post('https://sdk.vercel.ai/api/generate', - headers=headers, json=json_data, stream=True) + headers=headers, json=json_data, stream=True, proxies={"https": proxy}) try: response.raise_for_status() - except: + except Exception: continue for token in response.iter_content(chunk_size=None): yield token.decode() diff --git a/g4f/Provider/Vitalentum.py b/g4f/Provider/Vitalentum.py index ade492d2..37e259b2 100644 --- a/g4f/Provider/Vitalentum.py +++ b/g4f/Provider/Vitalentum.py @@ -42,7 +42,7 @@ class Vitalentum(AsyncGeneratorProvider): async with ClientSession( headers=headers ) as session: - async with session.post(cls.url + "/api/converse-edge", json=data, proxy=proxy) as response: + async with session.post(f"{cls.url}/api/converse-edge", json=data, proxy=proxy) as response: response.raise_for_status() async for line in response.content: line = line.decode() diff --git a/g4f/__init__.py b/g4f/__init__.py index 4b1e4b80..89b3e6d1 100644 --- a/g4f/__init__.py +++ b/g4f/__init__.py @@ -2,7 +2,7 @@ from __future__ import annotations from requests import get from g4f.models import Model, ModelUtils from .Provider import BaseProvider -from .typing import CreateResult, Union +from .typing import Messages, CreateResult, Union from .debug import logging version = '0.1.5.6' @@ -27,19 +27,19 @@ def get_model_and_provider(model : Union[Model, str], if model in ModelUtils.convert: model = ModelUtils.convert[model] else: - raise Exception(f'The model: {model} does not exist') + raise ValueError(f'The model: {model} does not exist') if not provider: provider = model.best_provider if not provider: - raise Exception(f'No provider found for model: {model}') + raise RuntimeError(f'No provider found for model: {model}') if not provider.working: - raise Exception(f'{provider.__name__} is not working') + raise RuntimeError(f'{provider.__name__} is not working') if not provider.supports_stream and stream: - raise Exception(f'ValueError: {provider.__name__} does not support "stream" argument') + raise ValueError(f'{provider.__name__} does not support "stream" argument') if logging: print(f'Using {provider.__name__} provider') @@ -48,17 +48,20 @@ def get_model_and_provider(model : Union[Model, str], class ChatCompletion: @staticmethod - def create(model: Union[Model, str], - messages : list[dict[str, str]], + def create( + model: Union[Model, str], + messages : Messages, provider : Union[type[BaseProvider], None] = None, stream : bool = False, - auth : Union[str, None] = None, **kwargs) -> Union[CreateResult, str]: + auth : Union[str, None] = None, + **kwargs + ) -> Union[CreateResult, str]: model, provider = get_model_and_provider(model, provider, stream) if provider.needs_auth and not auth: - raise Exception( - f'ValueError: {provider.__name__} requires authentication (use auth=\'cookie or token or jwt ...\' param)') + raise ValueError( + f'{provider.__name__} requires authentication (use auth=\'cookie or token or jwt ...\' param)') if provider.needs_auth: kwargs['auth'] = auth @@ -69,10 +72,14 @@ class ChatCompletion: @staticmethod async def create_async( model: Union[Model, str], - messages: list[dict[str, str]], + messages: Messages, provider: Union[type[BaseProvider], None] = None, + stream: bool = False, **kwargs ) -> str: + if stream: + raise ValueError(f'"create_async" does not support "stream" argument') + model, provider = get_model_and_provider(model, provider, False) return await provider.create_async(model.name, messages, **kwargs) From 7a699c8ca0c49a6e887e2e1debd0dcff23d696f9 Mon Sep 17 00:00:00 2001 From: Heiner Lohaus Date: Mon, 9 Oct 2023 13:12:07 +0200 Subject: [PATCH 02/12] Readme: Create Provider with AI Tool --- README.md | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 927e5c93..0a4c9ab6 100644 --- a/README.md +++ b/README.md @@ -521,38 +521,50 @@ if __name__ == "__main__": ## Contribute -to add another provider, its very simple: +####Create Provider with AI Tool + +Call in your terminal the "create_provider" script: +```bash +$ python etc/tool/create_provider.py +``` +1. Enter your name for the new provider. +2. Copy&Paste cURL command from your browser developer tools. +3. Let the AI ​​create the provider for you. +4. Customize the provider according to your needs. + +####Create Provider 0. Check out the current [list of potential providers](https://github.com/zukixa/cool-ai-stuff#ai-chat-websites), or find your own provider source! 1. Create a new file in [g4f/provider](./g4f/provider) with the name of the Provider 2. Implement a class that extends [BaseProvider](./g4f/provider/base_provider.py). ```py -from .base_provider import BaseProvider -from ..typing import CreateResult, Any +from __future__ import annotations +from ..typing import AsyncResult, Messages +from .base_provider import AsyncGeneratorProvider -class HogeService(BaseProvider): - url = "http://hoge.com" - working = True +class HogeService(AsyncGeneratorProvider): + url = "https://chat-gpt.com" supports_gpt_35_turbo = True + working = True - @staticmethod - def create_completion( + @classmethod + async def create_async_generator( + cls, model: str, - messages: list[dict[str, str]], - stream: bool, - **kwargs: Any, - ) -> CreateResult: - pass + messages: Messages, + proxy: str = None, + **kwargs + ) -> AsyncResult: + yield "" ``` -3. Here, you can adjust the settings, for example if the website does support streaming, set `working` to `True`... -4. Write code to request the provider in `create_completion` and `yield` the response, _even if_ its a one-time response, do not hesitate to look at other providers for inspiration +3. Here, you can adjust the settings, for example if the website does support streaming, set `supports_stream` to `True`... +4. Write code to request the provider in `create_async_generator` and `yield` the response, _even if_ its a one-time response, do not hesitate to look at other providers for inspiration 5. Add the Provider Name in [g4f/provider/**init**.py](./g4f/provider/__init__.py) ```py -from .base_provider import BaseProvider from .HogeService import HogeService __all__ = [ From c6b33e527c9af9c72a615a7b23c8d40b5783862f Mon Sep 17 00:00:00 2001 From: Heiner Lohaus Date: Mon, 9 Oct 2023 13:33:20 +0200 Subject: [PATCH 03/12] Add Proxy Support and Create Provider to Readme Add proxy support to many providers --- README.md | 31 +++++++++----- etc/tool/create_provider.py | 54 +++++++++++------------- g4f/Provider/FreeGpt.py | 6 +-- g4f/Provider/needs_auth/Bard.py | 14 +++--- g4f/Provider/needs_auth/HuggingChat.py | 9 ++-- g4f/Provider/needs_auth/OpenAssistant.py | 11 ++--- g4f/Provider/needs_auth/OpenaiChat.py | 17 +++++--- g4f/Provider/needs_auth/Raycast.py | 15 +++++-- g4f/Provider/needs_auth/Theb.py | 26 +++++++----- 9 files changed, 103 insertions(+), 80 deletions(-) diff --git a/README.md b/README.md index 0a4c9ab6..542f92fb 100644 --- a/README.md +++ b/README.md @@ -224,19 +224,15 @@ from g4f.Provider import ( Bing, ChatBase, ChatgptAi, - ChatgptLogin, - CodeLinkAva, DeepAi, H2o, HuggingChat, - Opchatgpts, OpenAssistant, OpenaiChat, Raycast, Theb, Vercel, Vitalentum, - Wewordle, Ylokh, You, Yqcloud, @@ -284,19 +280,18 @@ _providers = [ g4f.Provider.Aichat, g4f.Provider.ChatBase, g4f.Provider.Bing, - g4f.Provider.CodeLinkAva, g4f.Provider.DeepAi, g4f.Provider.GptGo, - g4f.Provider.Wewordle, g4f.Provider.You, g4f.Provider.Yqcloud, ] -async def run_provider(provider: g4f.Provider.AsyncProvider): +async def run_provider(provider: g4f.Provider.BaseProvider): try: - response = await provider.create_async( - model=g4f.models.default.name, + response = await g4f.ChatCompletion.create_async( + model=g4f.models.default, messages=[{"role": "user", "content": "Hello"}], + provider=provider, ) print(f"{provider.__name__}:", response) except Exception as e: @@ -311,6 +306,22 @@ async def run_all(): asyncio.run(run_all()) ``` +##### Proxy Support: + +All providers support specifying a proxy in the create function. + +```py +import g4f + +response = await g4f.ChatCompletion.create( + model=g4f.models.default, + messages=[{"role": "user", "content": "Hello"}], + proxy="http://host:port", + # or socks5://user:pass@host:port +) +print(f"Result:", response) +``` + ### interference openai-proxy api (use with openai python package) #### run interference from pypi package: @@ -528,7 +539,7 @@ Call in your terminal the "create_provider" script: $ python etc/tool/create_provider.py ``` 1. Enter your name for the new provider. -2. Copy&Paste cURL command from your browser developer tools. +2. Copy&Paste a cURL command from your browser developer tools. 3. Let the AI ​​create the provider for you. 4. Customize the provider according to your needs. diff --git a/etc/tool/create_provider.py b/etc/tool/create_provider.py index 4e3d7b02..26212f6a 100644 --- a/etc/tool/create_provider.py +++ b/etc/tool/create_provider.py @@ -12,23 +12,13 @@ def read_code(text): if match: return match.group("code") -def read_result(result): - lines = [] - for line in result.split("\n"): - if (line.startswith("```")): - break - if (line): - lines.append(line) - explanation = "\n".join(lines) if lines else "" - return explanation, read_code(result) - def input_command(): print("Enter/Paste the cURL command. Ctrl-D or Ctrl-Z ( windows ) to save it.") contents = [] while True: try: line = input() - except: + except EOFError: break contents.append(line) return "\n".join(contents) @@ -41,12 +31,12 @@ from __future__ import annotations from aiohttp import ClientSession -from ..typing import AsyncGenerator +from ..typing import AsyncResult, Messages from .base_provider import AsyncGeneratorProvider -from .helper import format_prompt +from .helper import format_prompt -class ChatgptDuo(AsyncGeneratorProvider): +class ChatGpt(AsyncGeneratorProvider): url = "https://chat-gpt.com" supports_gpt_35_turbo = True working = True @@ -55,9 +45,10 @@ class ChatgptDuo(AsyncGeneratorProvider): async def create_async_generator( cls, model: str, - messages: list[dict[str, str]], + messages: Messages, + proxy: str = None, **kwargs - ) -> AsyncGenerator: + ) -> AsyncResult: headers = { "authority": "chat-gpt.com", "accept": "application/json", @@ -65,16 +56,16 @@ class ChatgptDuo(AsyncGeneratorProvider): "referer": f"{cls.url}/chat", } async with ClientSession(headers=headers) as session: - prompt = format_prompt(messages), + prompt = format_prompt(messages) data = { "prompt": prompt, - "purpose": "ask", + "purpose": "", } - async with session.post(cls.url + "/api/chat", json=data) as response: + async with session.post(f"{cls.url}/api/chat", json=data, proxy=proxy) as response: response.raise_for_status() - async for stream in response.content: - if stream: - yield stream.decode() + async for chunk in response.content: + if chunk: + yield chunk.decode() """ if not path.isfile(provider_path): @@ -95,18 +86,23 @@ Replace "hello" with `format_prompt(messages)`. And replace "gpt-3.5-turbo" with `model`. """ - print("Create code...") - response = g4f.ChatCompletion.create( + response = [] + for chunk in g4f.ChatCompletion.create( model=g4f.models.gpt_35_long, messages=[{"role": "user", "content": prompt}], - auth=True, - timeout=120, - ) - print(response) - explanation, code = read_result(response) + timeout=300, + stream=True + ): + response.append(chunk) + print(chunk, end="", flush=True) + print() + response = "".join(response) + + code = read_code(response) if code: with open(provider_path, "w") as file: file.write(code) + print("Saved at:", provider_path) with open(f"g4f/Provider/__init__.py", "a") as file: file.write(f"\nfrom .{name} import {name}") else: diff --git a/g4f/Provider/FreeGpt.py b/g4f/Provider/FreeGpt.py index c9c05131..8a3ca6cc 100644 --- a/g4f/Provider/FreeGpt.py +++ b/g4f/Provider/FreeGpt.py @@ -2,7 +2,7 @@ from __future__ import annotations import time, hashlib, random -from ..typing import AsyncGenerator +from ..typing import AsyncResult, Messages from ..requests import StreamSession from .base_provider import AsyncGeneratorProvider @@ -20,11 +20,11 @@ class FreeGpt(AsyncGeneratorProvider): async def create_async_generator( cls, model: str, - messages: list[dict[str, str]], + messages: Messages, proxy: str = None, timeout: int = 120, **kwargs - ) -> AsyncGenerator: + ) -> AsyncResult: async with StreamSession( impersonate="chrome107", timeout=timeout, diff --git a/g4f/Provider/needs_auth/Bard.py b/g4f/Provider/needs_auth/Bard.py index 7c42b680..fe9777db 100644 --- a/g4f/Provider/needs_auth/Bard.py +++ b/g4f/Provider/needs_auth/Bard.py @@ -6,7 +6,9 @@ import re from aiohttp import ClientSession -from ..base_provider import AsyncProvider, format_prompt, get_cookies +from ...typing import Messages +from ..base_provider import AsyncProvider +from ..helper import format_prompt, get_cookies class Bard(AsyncProvider): @@ -19,25 +21,22 @@ class Bard(AsyncProvider): async def create_async( cls, model: str, - messages: list[dict[str, str]], + messages: Messages, proxy: str = None, cookies: dict = None, **kwargs ) -> str: prompt = format_prompt(messages) - if proxy and "://" not in proxy: - proxy = f"http://{proxy}" if not cookies: cookies = get_cookies(".google.com") headers = { 'authority': 'bard.google.com', - 'origin': 'https://bard.google.com', - 'referer': 'https://bard.google.com/', + 'origin': cls.url, + 'referer': f'{cls.url}/', 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36', 'x-same-domain': '1', } - async with ClientSession( cookies=cookies, headers=headers @@ -67,7 +66,6 @@ class Bard(AsyncProvider): 'lamda', 'BardFrontendService' ]) - async with session.post( f'{cls.url}/_/BardChatUi/data/{intents}/StreamGenerate', data=data, diff --git a/g4f/Provider/needs_auth/HuggingChat.py b/g4f/Provider/needs_auth/HuggingChat.py index 1d500338..68c6713b 100644 --- a/g4f/Provider/needs_auth/HuggingChat.py +++ b/g4f/Provider/needs_auth/HuggingChat.py @@ -4,8 +4,9 @@ import json, uuid from aiohttp import ClientSession -from ...typing import AsyncGenerator -from ..base_provider import AsyncGeneratorProvider, format_prompt, get_cookies +from ...typing import AsyncResult, Messages +from ..base_provider import AsyncGeneratorProvider +from ..helper import format_prompt, get_cookies class HuggingChat(AsyncGeneratorProvider): @@ -18,12 +19,12 @@ class HuggingChat(AsyncGeneratorProvider): async def create_async_generator( cls, model: str, - messages: list[dict[str, str]], + messages: Messages, stream: bool = True, proxy: str = None, cookies: dict = None, **kwargs - ) -> AsyncGenerator: + ) -> AsyncResult: model = model if model else cls.model if proxy and "://" not in proxy: proxy = f"http://{proxy}" diff --git a/g4f/Provider/needs_auth/OpenAssistant.py b/g4f/Provider/needs_auth/OpenAssistant.py index 3b0e0424..de62636c 100644 --- a/g4f/Provider/needs_auth/OpenAssistant.py +++ b/g4f/Provider/needs_auth/OpenAssistant.py @@ -4,8 +4,9 @@ import json from aiohttp import ClientSession -from ...typing import Any, AsyncGenerator -from ..base_provider import AsyncGeneratorProvider, format_prompt, get_cookies +from ...typing import AsyncResult, Messages +from ..base_provider import AsyncGeneratorProvider +from ..helper import format_prompt, get_cookies class OpenAssistant(AsyncGeneratorProvider): @@ -18,11 +19,11 @@ class OpenAssistant(AsyncGeneratorProvider): async def create_async_generator( cls, model: str, - messages: list[dict[str, str]], + messages: Messages, proxy: str = None, cookies: dict = None, - **kwargs: Any - ) -> AsyncGenerator: + **kwargs + ) -> AsyncResult: if not cookies: cookies = get_cookies("open-assistant.io") diff --git a/g4f/Provider/needs_auth/OpenaiChat.py b/g4f/Provider/needs_auth/OpenaiChat.py index c41909e3..b4b4a670 100644 --- a/g4f/Provider/needs_auth/OpenaiChat.py +++ b/g4f/Provider/needs_auth/OpenaiChat.py @@ -4,7 +4,7 @@ import uuid, json, time from ..base_provider import AsyncGeneratorProvider from ..helper import get_browser, get_cookies, format_prompt -from ...typing import AsyncGenerator +from ...typing import AsyncResult, Messages from ...requests import StreamSession class OpenaiChat(AsyncGeneratorProvider): @@ -18,13 +18,13 @@ class OpenaiChat(AsyncGeneratorProvider): async def create_async_generator( cls, model: str, - messages: list[dict[str, str]], + messages: Messages, proxy: str = None, + timeout: int = 120, access_token: str = None, cookies: dict = None, - timeout: int = 30, - **kwargs: dict - ) -> AsyncGenerator: + **kwargs + ) -> AsyncResult: proxies = {"https": proxy} if not access_token: access_token = await cls.get_access_token(cookies, proxies) @@ -32,7 +32,12 @@ class OpenaiChat(AsyncGeneratorProvider): "Accept": "text/event-stream", "Authorization": f"Bearer {access_token}", } - async with StreamSession(proxies=proxies, headers=headers, impersonate="chrome107", timeout=timeout) as session: + async with StreamSession( + proxies=proxies, + headers=headers, + impersonate="chrome107", + timeout=timeout + ) as session: messages = [ { "id": str(uuid.uuid4()), diff --git a/g4f/Provider/needs_auth/Raycast.py b/g4f/Provider/needs_auth/Raycast.py index 619b217b..4b448985 100644 --- a/g4f/Provider/needs_auth/Raycast.py +++ b/g4f/Provider/needs_auth/Raycast.py @@ -4,7 +4,7 @@ import json import requests -from ...typing import Any, CreateResult +from ...typing import CreateResult, Messages from ..base_provider import BaseProvider @@ -19,9 +19,10 @@ class Raycast(BaseProvider): @staticmethod def create_completion( model: str, - messages: list[dict[str, str]], + messages: Messages, stream: bool, - **kwargs: Any, + proxy: str = None, + **kwargs, ) -> CreateResult: auth = kwargs.get('auth') headers = { @@ -47,7 +48,13 @@ class Raycast(BaseProvider): "system_instruction": "markdown", "temperature": 0.5 } - response = requests.post("https://backend.raycast.com/api/v1/ai/chat_completions", headers=headers, json=data, stream=True) + response = requests.post( + "https://backend.raycast.com/api/v1/ai/chat_completions", + headers=headers, + json=data, + stream=True, + proxies={"https": proxy} + ) for token in response.iter_lines(): if b'data: ' not in token: continue diff --git a/g4f/Provider/needs_auth/Theb.py b/g4f/Provider/needs_auth/Theb.py index c35ea592..9803db97 100644 --- a/g4f/Provider/needs_auth/Theb.py +++ b/g4f/Provider/needs_auth/Theb.py @@ -2,11 +2,11 @@ from __future__ import annotations import json import random - import requests -from ...typing import Any, CreateResult +from ...typing import Any, CreateResult, Messages from ..base_provider import BaseProvider +from ..helper import format_prompt class Theb(BaseProvider): @@ -19,12 +19,11 @@ class Theb(BaseProvider): @staticmethod def create_completion( model: str, - messages: list[dict[str, str]], - stream: bool, **kwargs: Any) -> CreateResult: - - conversation = "\n".join(f"{message['role']}: {message['content']}" for message in messages) - conversation += "\nassistant: " - + messages: Messages, + stream: bool, + proxy: str = None, + **kwargs + ) -> CreateResult: auth = kwargs.get("auth", { "bearer_token":"free", "org_id":"theb", @@ -54,7 +53,7 @@ class Theb(BaseProvider): req_rand = random.randint(100000000, 9999999999) json_data: dict[str, Any] = { - "text" : conversation, + "text" : format_prompt(messages), "category" : "04f58f64a4aa4191a957b47290fee864", "model" : "ee8d4f29cb7047f78cbe84313ed6ace8", "model_params": { @@ -67,8 +66,13 @@ class Theb(BaseProvider): } } - response = requests.post(f"https://beta.theb.ai/api/conversation?org_id={org_id}&req_rand={req_rand}", - headers=headers, json=json_data, stream=True) + response = requests.post( + f"https://beta.theb.ai/api/conversation?org_id={org_id}&req_rand={req_rand}", + headers=headers, + json=json_data, + stream=True, + proxies={"https": proxy} + ) response.raise_for_status() content = "" From 1883d55147c240fda917c96ed6191ce6d09983fb Mon Sep 17 00:00:00 2001 From: abc <98614666+xtekky@users.noreply.github.com> Date: Mon, 9 Oct 2023 23:45:29 +0100 Subject: [PATCH 04/12] ~ Conversion from str Provider to g4f.Provider --- g4f/Provider/__init__.py | 62 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/g4f/Provider/__init__.py b/g4f/Provider/__init__.py index 5b0ec33b..d256064c 100644 --- a/g4f/Provider/__init__.py +++ b/g4f/Provider/__init__.py @@ -38,6 +38,68 @@ from .deprecated import * from .needs_auth import * from .unfinished import * +class ProviderUtils: + convert: dict[str, BaseProvider] = { + 'AItianhu': AItianhu, + 'AItianhuSpace': AItianhuSpace, + 'Acytoo': Acytoo, + 'AiAsk': AiAsk, + 'AiService': AiService, + 'Aibn': Aibn, + 'Aichat': Aichat, + 'Ails': Ails, + 'Aivvm': Aivvm, + 'AsyncGeneratorProvider': AsyncGeneratorProvider, + 'AsyncProvider': AsyncProvider, + 'Bard': Bard, + 'BaseProvider': BaseProvider, + 'Bing': Bing, + 'ChatBase': ChatBase, + 'ChatForAi': ChatForAi, + 'Chatgpt4Online': Chatgpt4Online, + 'ChatgptAi': ChatgptAi, + 'ChatgptDemo': ChatgptDemo, + 'ChatgptDuo': ChatgptDuo, + 'ChatgptLogin': ChatgptLogin, + 'ChatgptX': ChatgptX, + 'CodeLinkAva': CodeLinkAva, + 'Cromicle': Cromicle, + 'DeepAi': DeepAi, + 'DfeHub': DfeHub, + 'EasyChat': EasyChat, + 'Equing': Equing, + 'FastGpt': FastGpt, + 'Forefront': Forefront, + 'FreeGpt': FreeGpt, + 'GPTalk': GPTalk, + 'GetGpt': GetGpt, + 'GptForLove': GptForLove, + 'GptGo': GptGo, + 'GptGod': GptGod, + 'H2o': H2o, + 'HuggingChat': HuggingChat, + 'Komo': Komo, + 'Liaobots': Liaobots, + 'Lockchat': Lockchat, + 'MikuChat': MikuChat, + 'Myshell': Myshell, + 'Opchatgpts': Opchatgpts, + 'OpenAssistant': OpenAssistant, + 'OpenaiChat': OpenaiChat, + 'PerplexityAi': PerplexityAi, + 'Phind': Phind, + 'Raycast': Raycast, + 'Theb': Theb, + 'V50': V50, + 'Vercel': Vercel, + 'Vitalentum': Vitalentum, + 'Wewordle': Wewordle, + 'Wuguokai': Wuguokai, + 'Ylokh': Ylokh, + 'You': You, + 'Yqcloud': Yqcloud + } + __all__ = [ 'BaseProvider', 'AsyncProvider', From f9355ad5fcade92258cf1678210a45db3911e3e8 Mon Sep 17 00:00:00 2001 From: abc <98614666+xtekky@users.noreply.github.com> Date: Mon, 9 Oct 2023 23:45:44 +0100 Subject: [PATCH 05/12] ~ remove chatforai --- g4f/models.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/g4f/models.py b/g4f/models.py index b4247703..ced8e290 100644 --- a/g4f/models.py +++ b/g4f/models.py @@ -9,7 +9,6 @@ from .Provider import ( ChatgptDuo, Vitalentum, ChatgptAi, - ChatForAi, AItianhu, ChatBase, Liaobots, @@ -28,7 +27,8 @@ from .Provider import ( Aibn, Bing, You, - H2o + H2o, + Aivvm ) @dataclass(unsafe_hash=True) @@ -45,7 +45,7 @@ default = Model( Yqcloud, # Answers short questions in chinese ChatBase, # Don't want to answer creatively ChatgptDuo, # Include search results - Aibn, Aichat, ChatForAi, ChatgptAi, ChatgptLogin, DeepAi, FreeGpt, GptGo, Myshell, Ylokh, + Aibn, Aichat, ChatgptAi, ChatgptLogin, DeepAi, FreeGpt, GptGo, Myshell, Ylokh, ]) ) @@ -54,7 +54,7 @@ gpt_35_long = Model( name = 'gpt-3.5-turbo', base_provider = 'openai', best_provider = RetryProvider([ - AiAsk, Aibn, Aichat, ChatForAi, ChatgptAi, ChatgptDemo, ChatgptDuo, + AiAsk, Aibn, Aichat, ChatgptAi, ChatgptDemo, ChatgptDuo, FreeGpt, GptGo, Liaobots, Myshell, Vitalentum, Ylokh, You, Yqcloud, GPTalk, GptGod ]) @@ -65,7 +65,7 @@ gpt_35_turbo = Model( name = 'gpt-3.5-turbo', base_provider = 'openai', best_provider = RetryProvider([ - DeepAi, ChatgptLogin, ChatgptAi, GptGo, AItianhu, Aichat, AItianhuSpace, Myshell, Aibn, ChatForAi, FreeGpt, Ylokh + DeepAi, ChatgptLogin, ChatgptAi, GptGo, AItianhu, Aichat, AItianhuSpace, Myshell, Aibn, FreeGpt, Ylokh ]) ) @@ -169,7 +169,8 @@ gpt_35_turbo_16k_0613 = Model( gpt_35_turbo_0613 = Model( name = 'gpt-3.5-turbo-0613', - base_provider = 'openai' + base_provider = 'openai', + best_provider=Aivvm ) gpt_4_0613 = Model( From 7f8526a1227e016fc79328ddcbe7afd09c0d63d1 Mon Sep 17 00:00:00 2001 From: abc <98614666+xtekky@users.noreply.github.com> Date: Mon, 9 Oct 2023 23:46:02 +0100 Subject: [PATCH 06/12] ~ New system for str to Provider --- g4f/gui/server/backend.py | 19 ++++++++++++------- g4f/gui/server/provider.py | 17 +++++++++++++++++ 2 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 g4f/gui/server/provider.py diff --git a/g4f/gui/server/backend.py b/g4f/gui/server/backend.py index 9a1dbbf8..8f4b529f 100644 --- a/g4f/gui/server/backend.py +++ b/g4f/gui/server/backend.py @@ -1,9 +1,11 @@ import g4f from flask import request -from threading import Thread from .internet import search from .config import special_instructions +from .provider import get_provider + +g4f.logging = True class Backend_Api: def __init__(self, app) -> None: @@ -31,22 +33,25 @@ class Backend_Api: conversation = request.json['meta']['content']['conversation'] prompt = request.json['meta']['content']['parts'][0] model = request.json['model'] + provider = get_provider(request.json.get('provider')) messages = special_instructions[jailbreak] + conversation + search(internet_access, prompt) + [prompt] def stream(): - answer = g4f.ChatCompletion.create(model = model, - messages = messages, stream=True) + if provider: + answer = g4f.ChatCompletion.create(model=model, + provider=provider, messages=messages, stream=True) + else: + answer = g4f.ChatCompletion.create(model=model, + messages=messages, stream=True) for token in answer: yield token - + return self.app.response_class(stream(), mimetype='text/event-stream') - except Exception as e: - print(e) + except Exception as e: return { - '_token': 'anerroroccuredmf', '_action': '_ask', 'success': False, "error": f"an error occured {str(e)}"}, 400 \ No newline at end of file diff --git a/g4f/gui/server/provider.py b/g4f/gui/server/provider.py new file mode 100644 index 00000000..286f881b --- /dev/null +++ b/g4f/gui/server/provider.py @@ -0,0 +1,17 @@ +import g4f + +def get_provider(provider: str) -> g4f.Provider.BaseProvider: + + if isinstance(provider, str): + print(provider) + if provider == 'g4f.Provider.Auto': + return None + + if provider in g4f.Provider.ProviderUtils.convert: + return g4f.Provider.ProviderUtils.convert[provider] + + else: + return None + + else: + return None From abc2fa2ca10c19cb2cbd500b8474d1edbe057781 Mon Sep 17 00:00:00 2001 From: abc <98614666+xtekky@users.noreply.github.com> Date: Mon, 9 Oct 2023 23:46:14 +0100 Subject: [PATCH 07/12] ~ Command line arguments for GUI --- g4f/gui/run.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/g4f/gui/run.py b/g4f/gui/run.py index da672d59..731c7cbf 100644 --- a/g4f/gui/run.py +++ b/g4f/gui/run.py @@ -1,4 +1,18 @@ from g4f.gui import run_gui +from argparse import ArgumentParser + if __name__ == '__main__': - run_gui() \ No newline at end of file + + parser = ArgumentParser(description='Run the GUI') + + parser.add_argument('-host', type=str, default='0.0.0.0', help='hostname') + parser.add_argument('-port', type=int, default=80, help='port') + parser.add_argument('-debug', action='store_true', help='debug mode') + + args = parser.parse_args() + port = args.port + host = args.host + debug = args.debug + + run_gui(host, port, debug) \ No newline at end of file From e05987ace34b3db38d3849f7c33405bcc7e50ee9 Mon Sep 17 00:00:00 2001 From: abc <98614666+xtekky@users.noreply.github.com> Date: Mon, 9 Oct 2023 23:47:58 +0100 Subject: [PATCH 08/12] ~ | g4f `v-0.1.5.7` [Set Provider in GUI] + Provider Proxy --- g4f/__init__.py | 2 +- g4f/gui/__init__.py | 2 +- g4f/gui/client/html/index.html | 291 +++++++++++++++++---------------- g4f/gui/client/js/chat.v2.js | 14 +- 4 files changed, 165 insertions(+), 144 deletions(-) diff --git a/g4f/__init__.py b/g4f/__init__.py index 89b3e6d1..fa20f6eb 100644 --- a/g4f/__init__.py +++ b/g4f/__init__.py @@ -5,7 +5,7 @@ from .Provider import BaseProvider from .typing import Messages, CreateResult, Union from .debug import logging -version = '0.1.5.6' +version = '0.1.5.7' version_check = True def check_pypi_version() -> None: diff --git a/g4f/gui/__init__.py b/g4f/gui/__init__.py index 90a6c7a6..48b78881 100644 --- a/g4f/gui/__init__.py +++ b/g4f/gui/__init__.py @@ -16,7 +16,7 @@ def run_gui(host: str = '0.0.0.0', port: int = 80, debug: bool = False) -> None: view_func = site.routes[route]['function'], methods = site.routes[route]['methods'], ) - + backend_api = Backend_Api(app) for route in backend_api.routes: app.add_url_rule( diff --git a/g4f/gui/client/html/index.html b/g4f/gui/client/html/index.html index 3acde2df..bb472706 100644 --- a/g4f/gui/client/html/index.html +++ b/g4f/gui/client/html/index.html @@ -1,161 +1,178 @@ - - - - - - - - - - - - - - - - - - - - - - - - g4f - gui - - -
-
-
-
- + /* Track */ + #message-input::-webkit-scrollbar-track { + background: #f1f1f1; + } + + /* Handle */ + #message-input::-webkit-scrollbar-thumb { + background: #c7a2ff; + } + + /* Handle on hover */ + #message-input::-webkit-scrollbar-thumb:hover { + background: #8b3dff; + } + + + + g4f - gui + + + +
+
+
+
+ +
+
+ +
+ + telegram: @g4f_official
+
-
- -
- - telegram: @g4f_official
-
-
-
- - github: @gpt4free
- leave a star ; ) -
+
+ + github: @gpt4free
+ leave a star ; ) +
+
+
+
+
+
+ +
+
+
+
+
+ +
+
-
-
- +
+
+ + + Web Access
-
+
+
-
-
- -
- -
-
-
-
+
+
- - - Web Access -
-
- + + + + + + + + + + + + + + + + + + + + + + + + + + +
-
- -
-
- Pick a color scheme - - - - - - - - - - - - - - -
-
-
+
- + + \ No newline at end of file diff --git a/g4f/gui/client/js/chat.v2.js b/g4f/gui/client/js/chat.v2.js index df827030..e1faa6bb 100644 --- a/g4f/gui/client/js/chat.v2.js +++ b/g4f/gui/client/js/chat.v2.js @@ -52,7 +52,7 @@ const remove_cancel_button = async () => { const ask_gpt = async (message) => { try { - message_input.value = ``; + message_input.value = ``; message_input.innerHTML = ``; message_input.innerText = ``; @@ -60,10 +60,11 @@ const ask_gpt = async (message) => { window.scrollTo(0, 0); window.controller = new AbortController(); - jailbreak = document.getElementById("jailbreak"); - model = document.getElementById("model"); - prompt_lock = true; - window.text = ``; + jailbreak = document.getElementById("jailbreak"); + provider = document.getElementById("provider"); + model = document.getElementById("model"); + prompt_lock = true; + window.text = ``; window.token = message_id(); stop_generating.classList.remove(`stop_generating-hidden`); @@ -109,12 +110,15 @@ const ask_gpt = async (message) => { headers: { "content-type": `application/json`, accept: `text/event-stream`, + // v: `1.0.0`, + // ts: Date.now().toString(), }, body: JSON.stringify({ conversation_id: window.conversation_id, action: `_ask`, model: model.options[model.selectedIndex].value, jailbreak: jailbreak.options[jailbreak.selectedIndex].value, + provider: provider.options[provider.selectedIndex].value, meta: { id: window.token, content: { From b8febf67e324ada0e8ea7a15ec59ef47c3097803 Mon Sep 17 00:00:00 2001 From: abc <98614666+xtekky@users.noreply.github.com> Date: Mon, 9 Oct 2023 23:49:45 +0100 Subject: [PATCH 09/12] ~ | g4f `v-0.1.5.7` --- README.md | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 542f92fb..4e16a063 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ By using this repository or any code related to it, you agree to the [legal notice](./LEGAL_NOTICE.md). The author is not responsible for any copies, forks, reuploads made by other users, or anything else related to gpt4free. This is the author's only account and repository. To prevent impersonation or irresponsible actions, please comply with the GNU GPL license this Repository uses. -- latest pypi version: ([0.1.5.6](https://pypi.org/project/g4f/0.1.5.6)): +- latest pypi version: `[0.1.5.7](https://pypi.org/project/g4f/0.1.5.7)``: ```sh pip install -U g4f ``` diff --git a/setup.py b/setup.py index 5defd3fa..de5f5d97 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ with open("requirements.txt") as f: with open("etc/interference/requirements.txt") as f: api_required = f.read().splitlines() -VERSION = '0.1.5.6' +VERSION = '0.1.5.7' DESCRIPTION = ( "The official gpt4free repository | various collection of powerful language models" ) From 5f2786b348c1a26a69b4f2f860aaab4561fe1ce3 Mon Sep 17 00:00:00 2001 From: abc <98614666+xtekky@users.noreply.github.com> Date: Mon, 9 Oct 2023 23:50:01 +0100 Subject: [PATCH 10/12] ~ --- etc/tool/create_provider.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/tool/create_provider.py b/etc/tool/create_provider.py index 26212f6a..62cfd605 100644 --- a/etc/tool/create_provider.py +++ b/etc/tool/create_provider.py @@ -107,4 +107,4 @@ And replace "gpt-3.5-turbo" with `model`. file.write(f"\nfrom .{name} import {name}") else: with open(provider_path, "r") as file: - code = file.read() + code = file.read() \ No newline at end of file From 6135f4ac08508f902cc417ef1e9d11b299ab5fd9 Mon Sep 17 00:00:00 2001 From: abc <98614666+xtekky@users.noreply.github.com> Date: Mon, 9 Oct 2023 23:51:47 +0100 Subject: [PATCH 11/12] ~ | g4f `v-0.1.5.7` --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4e16a063..691c5857 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ By using this repository or any code related to it, you agree to the [legal notice](./LEGAL_NOTICE.md). The author is not responsible for any copies, forks, reuploads made by other users, or anything else related to gpt4free. This is the author's only account and repository. To prevent impersonation or irresponsible actions, please comply with the GNU GPL license this Repository uses. -- latest pypi version: `[0.1.5.7](https://pypi.org/project/g4f/0.1.5.7)``: +- latest pypi version: `[0.1.5.7](https://pypi.org/project/g4f/0.1.5.7)`: ```sh pip install -U g4f ``` From 417ce27422f19cb43ddec8cf2af43bdbb1b795e6 Mon Sep 17 00:00:00 2001 From: Commenter123321 <36051603+Commenter123321@users.noreply.github.com> Date: Tue, 10 Oct 2023 09:13:18 +0200 Subject: [PATCH 12/12] Update Aivvm.py --- g4f/Provider/Aivvm.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/g4f/Provider/Aivvm.py b/g4f/Provider/Aivvm.py index 83495a22..3e4bbaeb 100644 --- a/g4f/Provider/Aivvm.py +++ b/g4f/Provider/Aivvm.py @@ -45,12 +45,12 @@ class Aivvm(AsyncGeneratorProvider): "temperature" : kwargs.get("temperature", 0.7) } headers = { - "Accept": "*/*", + "Accept": "text/event-stream", "Origin": cls.url, "Referer": f"{cls.url}/", } async with StreamSession( - impersonate="chrome107", + impersonate="chrome117", headers=headers, proxies={"https": proxy}, timeout=timeout @@ -73,4 +73,4 @@ class Aivvm(AsyncGeneratorProvider): ('temperature', 'float'), ] 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})'