Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates for some providers #1846

Merged
merged 2 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion g4f/Provider/Bing.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def get_default_cookies():
'PPLState' : '1',
'KievRPSSecAuth': '',
'SUID' : '',
'SRCHUSR' : '',
'SRCHUSR' : f'DOB={date.today().strftime("%Y%m%d")}&T={int(time.time())}',
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
'SRCHHPGUSR' : f'HV={int(time.time())}',
'BCP' : 'AD=1&AL=1&SM=1',
'_Rwho' : f'u=d&ts={date.today().isoformat()}',
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
4 changes: 3 additions & 1 deletion g4f/Provider/Chatgpt4Online.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from ..typing import Messages, AsyncResult
from ..requests import get_args_from_browser
from ..webdriver import WebDriver
from .base_provider import AsyncGeneratorProvider
from .helper import get_random_string

Expand All @@ -23,9 +24,10 @@ async def create_async_generator(
model: str,
messages: Messages,
proxy: str = None,
webdriver: WebDriver = None,
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
**kwargs
) -> AsyncResult:
args = get_args_from_browser(f"{cls.url}/chat/", proxy=proxy)
args = get_args_from_browser(f"{cls.url}/chat/", webdriver, proxy=proxy)
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
async with ClientSession(**args) as session:
if not cls._wpnonce:
async with session.get(f"{cls.url}/chat/", proxy=proxy) as response:
Expand Down
30 changes: 24 additions & 6 deletions g4f/Provider/DuckDuckGo.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
import aiohttp

from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
from .helper import get_connector
from ..typing import AsyncResult, Messages
from ..requests.raise_for_status import raise_for_status
from ..providers.conversation import BaseConversation

class DuckDuckGo(AsyncGeneratorProvider, ProviderModelMixin):
url = "https://duckduckgo.com/duckchat"
Expand Down Expand Up @@ -42,23 +44,39 @@ async def create_async_generator(
cls,
model: str,
messages: Messages,
proxy: str = None,
connector: aiohttp.BaseConnector = None,
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
conversation: Conversation = None,
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
return_conversation: bool = False,
**kwargs
) -> AsyncResult:
async with aiohttp.ClientSession(headers=cls.headers) as session:
async with session.get(cls.status_url, headers={"x-vqd-accept": "1"}) as response:
await raise_for_status(response)
vqd_4 = response.headers.get("x-vqd-4")
async with aiohttp.ClientSession(headers=cls.headers, connector=get_connector(connector, proxy)) as session:
if conversation is not None and len(messages) > 1:
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
vqd_4 = conversation.vqd_4
messages = [*conversation.messages, messages[-2], messages[-1]]
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
else:
async with session.get(cls.status_url, headers={"x-vqd-accept": "1"}) as response:
await raise_for_status(response)
vqd_4 = response.headers.get("x-vqd-4")
messages = [messages[-1]]
payload = {
'model': cls.get_model(model),
'messages': messages
}
async with session.post(cls.chat_url, json=payload, headers={"x-vqd-4": vqd_4}) as response:
await raise_for_status(response)
if return_conversation:
yield Conversation(response.headers.get("x-vqd-4"), messages)
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
async for line in response.content:
if line.startswith(b"data: "):
chunk = line[6:]
if chunk.startswith(b"[DONE]"):
break
data = json.loads(chunk)
if "message" in data:
yield data["message"]
if "message" in data and data["message"]:
yield data["message"]

class Conversation(BaseConversation):
def __init__(self, vqd_4: str, messages: Messages) -> None:
self.vqd_4 = vqd_4
self.messages = messages
28 changes: 25 additions & 3 deletions g4f/Provider/FlowGpt.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from __future__ import annotations

import json
import time
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
import hashlib
from aiohttp import ClientSession

from ..typing import AsyncResult, Messages
from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
from .helper import get_random_hex, get_random_string
from ..requests.raise_for_status import raise_for_status

class FlowGpt(AsyncGeneratorProvider, ProviderModelMixin):
Expand All @@ -17,9 +20,17 @@ class FlowGpt(AsyncGeneratorProvider, ProviderModelMixin):
models = [
"gpt-3.5-turbo",
"gpt-3.5-long",
"gpt-4-turbo",
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
"google-gemini",
"claude-instant",
"claude-v1",
"claude-v2",
"llama2-13b"
"llama2-13b",
"mythalion-13b",
"pygmalion-13b",
"chronos-hermes-13b",
"Mixtral-8x7B",
"Dolphin-2.6-8x7B"
]
model_aliases = {
"gemini": "google-gemini",
Expand All @@ -36,6 +47,12 @@ async def create_async_generator(
**kwargs
) -> AsyncResult:
model = cls.get_model(model)
timestamp = str(int(time.time()))
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
auth = "Bearer null"
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
nonce = get_random_hex()
data = f"{timestamp}-{nonce}-{auth}"
signature = hashlib.md5(data.encode()).hexdigest()
hlohaus marked this conversation as resolved.
Show resolved Hide resolved

headers = {
"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:122.0) Gecko/20100101 Firefox/122.0",
"Accept": "*/*",
Expand All @@ -49,7 +66,12 @@ async def create_async_generator(
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-site",
"TE": "trailers"
"TE": "trailers",
"Authorization": auth,
"x-flow-device-id": f"f-{get_random_string(19)}",
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
"x-nonce": nonce,
"x-signature": signature,
"x-timestamp": timestamp
}
async with ClientSession(headers=headers) as session:
history = [message for message in messages[:-1] if message["role"] != "system"]
Expand All @@ -69,7 +91,7 @@ async def create_async_generator(
"generateImage": False,
"generateAudio": False
}
async with session.post("https://backend-k8s.flowgpt.com/v2/chat-anonymous", json=data, proxy=proxy) as response:
async with session.post("https://backend-k8s.flowgpt.com/v2/chat-anonymous-encrypted", json=data, proxy=proxy) as response:
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
await raise_for_status(response)
async for chunk in response.content:
if chunk.strip():
Expand Down
17 changes: 8 additions & 9 deletions g4f/Provider/PerplexityLabs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@

import random
import json
from aiohttp import ClientSession, BaseConnector

from ..typing import AsyncResult, Messages
from ..requests import StreamSession, raise_for_status
from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
from .helper import get_connector

API_URL = "https://labs-api.perplexity.ai/socket.io/"
WS_URL = "wss://labs-api.perplexity.ai/socket.io/"
API_URL = "https://www.perplexity.ai/socket.io/"
WS_URL = "wss://www.perplexity.ai/socket.io/"

class PerplexityLabs(AsyncGeneratorProvider, ProviderModelMixin):
url = "https://labs.perplexity.ai"
Expand All @@ -35,7 +34,6 @@ async def create_async_generator(
model: str,
messages: Messages,
proxy: str = None,
connector: BaseConnector = None,
**kwargs
) -> AsyncResult:
headers = {
Expand All @@ -51,21 +49,22 @@ async def create_async_generator(
"Sec-Fetch-Site": "same-site",
"TE": "trailers",
}
async with ClientSession(headers=headers, connector=get_connector(connector, proxy)) as session:
async with StreamSession(headers=headers, proxies={"all": proxy}) as session:
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
t = format(random.getrandbits(32), "08x")
async with session.get(
f"{API_URL}?EIO=4&transport=polling&t={t}"
) as response:
await raise_for_status(response)
text = await response.text()

assert text.startswith("0")
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
sid = json.loads(text[1:])["sid"]
post_data = '40{"jwt":"anonymous-ask-user"}'
async with session.post(
f"{API_URL}?EIO=4&transport=polling&t={t}&sid={sid}",
data=post_data
) as response:
assert await response.text() == "OK"

await raise_for_status(response)
assert await response.text() == "OK"
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
async with session.ws_connect(f"{WS_URL}?EIO=4&transport=websocket&sid={sid}", autoping=False) as ws:
await ws.send_str("2probe")
assert(await ws.receive_str() == "3probe")
Expand Down
4 changes: 2 additions & 2 deletions g4f/Provider/bing/conversation.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ async def create_conversation(session: ClientSession, headers: dict, tone: str)
Conversation: An instance representing the created conversation.
"""
if tone == "Copilot":
url = "https://copilot.microsoft.com/turing/conversation/create?bundleVersion=1.1686.0"
url = "https://copilot.microsoft.com/turing/conversation/create?bundleVersion=1.1690.0"
else:
url = "https://www.bing.com/turing/conversation/create?bundleVersion=1.1686.0"
url = "https://www.bing.com/turing/conversation/create?bundleVersion=1.1690.0"
async with session.get(url, headers=headers) as response:
if response.status == 404:
raise RateLimitError("Response 404: Do less requests and reuse conversations")
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
5 changes: 5 additions & 0 deletions g4f/Provider/needs_auth/Gemini.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,18 @@ async def create_async_generator(
model: str,
messages: Messages,
proxy: str = None,
api_key: str = None,
cookies: Cookies = None,
connector: BaseConnector = None,
image: ImageType = None,
image_name: str = None,
**kwargs
) -> AsyncResult:
prompt = format_prompt(messages)
if api_key is not None:
if cookies is None:
cookies = {}
cookies["__Secure-1PSID"] = api_key
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
cookies = cookies if cookies else get_cookies(".google.com", False, True)
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
base_connector = get_connector(connector, proxy)
async with ClientSession(
Expand Down
6 changes: 5 additions & 1 deletion g4f/gui/client/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
</script>
<script src="https://unpkg.com/gpt-tokenizer/dist/cl100k_base.js" async></script>
<script src="/static/js/text_to_speech/index.js" async></script>
<!--
<script src="/static/js/whisper-web/index.js" async></script>
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
-->
<script>
const user_image = '<img src="/static/img/user.png" alt="your avatar">';
const gpt_image = '<img src="/static/img/gpt.png" alt="your avatar">';
Expand Down Expand Up @@ -89,6 +92,7 @@
</div>
<div class="settings hidden">
<div class="paper">
<h3>Settings</h3>
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
<div class="field">
<span class="label">Web Access</span>
<input type="checkbox" id="switch" />
Expand Down Expand Up @@ -127,7 +131,7 @@
</div>
<div class="field box">
<label for="Gemini-api_key" class="label" title="">Gemini:</label>
<textarea id="Gemini-api_key" name="Gemini[api_key]" placeholder="Cookies"></textarea>
<textarea id="Gemini-api_key" name="Gemini[api_key]" placeholder="&quot;__Secure-1PSID&quot; cookie"></textarea>
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
</div>
<div class="field box">
<label for="GeminiPro-api_key" class="label" title="">GeminiPro:</label>
Expand Down
14 changes: 12 additions & 2 deletions g4f/gui/client/static/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,8 @@ label[for="camera"] {
width: 100%;
}

.buttons input:checked+label:after {
.buttons input:checked+label:after,
.settings input:checked+label:after {
left: calc(100% - 5px - 20px);
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
}

Expand Down Expand Up @@ -844,6 +845,10 @@ ul {
max-width: none;
}

.settings h3 {
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
padding-left: 50px;
}

.buttons {
align-items: flex-start;
flex-wrap: wrap;
Expand Down Expand Up @@ -1099,10 +1104,15 @@ a:-webkit-any-link {
width: 100%;
display: flex;
flex-direction: column;
overflow: auto;
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
}

.settings h3 {
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
padding-left: 10px;
padding-top: 10px;
}

.settings .paper {
overflow: auto;
flex-direction: column;
min-width: 400px;
}
Expand Down
3 changes: 3 additions & 0 deletions g4f/gui/server/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ def get_providers(self) -> list[str]:
else provider.__name__) +
(" (WebDriver)"
if "webdriver" in provider.get_parameters()
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
else "") +
(" (Auth)"
if provider.needs_auth
else "")
for provider in __providers__
if provider.working
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
34 changes: 33 additions & 1 deletion g4f/requests/curl_cffi.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
has_curl_mime = True
except ImportError:
has_curl_mime = False
try:
from curl_cffi.requests import CurlWsFlag
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
has_curl_ws = True
except ImportError:
has_curl_ws = False
from typing import AsyncGenerator, Any
from functools import partialmethod
import json
Expand Down Expand Up @@ -73,6 +78,12 @@ def request(
"""Create and return a StreamResponse object for the given HTTP request."""
return StreamResponse(super().request(method, url, stream=True, **kwargs))

def ws_connect(self, url, *args, **kwargs):
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
return WebSocket(self, url)

def _ws_connect(self, url):
hlohaus marked this conversation as resolved.
Show resolved Hide resolved
return super().ws_connect(url)

# Defining HTTP methods as partial methods of the request method.
head = partialmethod(request, "HEAD")
get = partialmethod(request, "GET")
Expand All @@ -88,4 +99,25 @@ def add_field(self, name, data=None, content_type: str = None, filename: str = N
else:
class FormData():
def __init__(self) -> None:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message CurlMimi in curl_cffi is missing | pip install -U g4f[curl_cffi] has a typo. It should likely be CurlMime instead of CurlMimi. Additionally, consider providing more context or guidance on resolving the error for better user experience.

raise RuntimeError("CurlMimi in curl_cffi is missing | pip install -U g4f[curl_cffi]")
raise RuntimeError("CurlMimi in curl_cffi is missing | pip install -U g4f[curl_cffi]")

class WebSocket():
def __init__(self, session, url) -> None:
if not has_curl_ws:
raise RuntimeError("CurlWsFlag in curl_cffi is missing | pip install -U g4f[curl_cffi]")
self.session: StreamSession = session
self.url: str = url

async def __aenter__(self):
self.inner = await self.session._ws_connect(self.url)
return self

async def __aexit__(self, *args):
self.inner.aclose()

async def receive_str(self) -> str:
bytes, _ = await self.inner.arecv()
return bytes.decode(errors="ignore")

async def send_str(self, data: str):
await self.inner.asend(data.encode(), CurlWsFlag.TEXT)
Loading