summaryrefslogtreecommitdiffstats
path: root/g4f
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--g4f/Provider/AItianhu.py36
-rw-r--r--g4f/Provider/AItianhuSpace.py23
-rw-r--r--g4f/Provider/Aichat.py18
-rw-r--r--g4f/Provider/Ails.py24
-rw-r--r--g4f/Provider/Bing.py90
-rw-r--r--g4f/Provider/ChatBase.py20
-rw-r--r--g4f/Provider/Chatgpt4Online.py4
-rw-r--r--g4f/Provider/ChatgptAi.py13
-rw-r--r--g4f/Provider/ChatgptDemo.py12
-rw-r--r--g4f/Provider/ChatgptFree.py35
-rw-r--r--g4f/Provider/ChatgptLogin.py14
-rw-r--r--g4f/Provider/ChatgptX.py15
-rw-r--r--g4f/Provider/GPTalk.py6
-rw-r--r--g4f/Provider/GptChatly.py10
-rw-r--r--g4f/Provider/GptForLove.py7
-rw-r--r--g4f/Provider/GptGo.py35
-rw-r--r--g4f/Provider/GptGod.py7
-rw-r--r--g4f/Provider/Liaobots.py2
-rw-r--r--g4f/Provider/Vercel.py66
-rw-r--r--g4f/Provider/Ylokh.py18
-rw-r--r--g4f/Provider/deprecated/AiService.py9
-rw-r--r--g4f/Provider/deprecated/CodeLinkAva.py23
-rw-r--r--g4f/Provider/deprecated/EasyChat.py40
-rw-r--r--g4f/Provider/deprecated/Equing.py11
-rw-r--r--g4f/Provider/deprecated/FastGpt.py13
-rw-r--r--g4f/Provider/deprecated/H2o.py2
-rw-r--r--g4f/Provider/deprecated/Lockchat.py7
-rw-r--r--g4f/Provider/deprecated/V50.py21
-rw-r--r--g4f/Provider/deprecated/Vitalentum.py23
-rw-r--r--g4f/Provider/deprecated/Wuguokai.py19
-rw-r--r--g4f/Provider/helper.py22
-rw-r--r--g4f/Provider/needs_auth/Bard.py14
-rw-r--r--g4f/Provider/needs_auth/Raycast.py10
-rw-r--r--g4f/Provider/needs_auth/Theb.py40
-rw-r--r--g4f/Provider/unfinished/ChatAiGpt.py8
-rw-r--r--g4f/Provider/unfinished/MikuChat.py3
-rw-r--r--g4f/Provider/unfinished/PerplexityAi.py2
-rw-r--r--g4f/__init__.py2
-rw-r--r--g4f/api/__init__.py17
-rw-r--r--g4f/gui/server/backend.py25
-rw-r--r--g4f/gui/server/internet.py13
-rw-r--r--g4f/gui/server/provider.py14
-rw-r--r--g4f/gui/server/website.py6
-rw-r--r--g4f/requests.py5
44 files changed, 399 insertions, 405 deletions
diff --git a/g4f/Provider/AItianhu.py b/g4f/Provider/AItianhu.py
index 18ab08d8..2fdcfcde 100644
--- a/g4f/Provider/AItianhu.py
+++ b/g4f/Provider/AItianhu.py
@@ -24,9 +24,9 @@ class AItianhu(AsyncGeneratorProvider):
if not cookies:
cookies = get_cookies(domain_name='www.aitianhu.com')
- if not cookies:
- raise RuntimeError(f"g4f.provider.{cls.__name__} requires cookies [refresh https://www.aitianhu.com on chrome]")
-
+ if not cookies:
+ raise RuntimeError(f"g4f.provider.{cls.__name__} requires cookies [refresh https://www.aitianhu.com on chrome]")
+
data = {
"prompt": format_prompt(messages),
"options": {},
@@ -35,7 +35,7 @@ class AItianhu(AsyncGeneratorProvider):
"top_p": 1,
**kwargs
}
-
+
headers = {
'authority': 'www.aitianhu.com',
'accept': 'application/json, text/plain, */*',
@@ -51,31 +51,31 @@ class AItianhu(AsyncGeneratorProvider):
'sec-fetch-site': 'same-origin',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36',
}
-
+
async with StreamSession(headers=headers,
- cookies=cookies,
- timeout=timeout,
- proxies={"https": proxy},
- impersonate="chrome107", verify=False) as session:
+ cookies=cookies,
+ timeout=timeout,
+ proxies={"https": proxy},
+ impersonate="chrome107", verify=False) as session:
async with session.post(f"{cls.url}/api/chat-process", json=data) as response:
response.raise_for_status()
-
+
async for line in response.iter_lines():
if line == b"<script>":
raise RuntimeError("Solve challenge and pass cookies")
-
+
if b"platform's risk control" in line:
raise RuntimeError("Platform's Risk Control")
-
+
line = json.loads(line)
-
- if "detail" in line:
- content = line["detail"]["choices"][0]["delta"].get("content")
- if content:
- yield content
- else:
+
+ if "detail" not in line:
raise RuntimeError(f"Response: {line}")
+ if content := line["detail"]["choices"][0]["delta"].get(
+ "content"
+ ):
+ yield content
@classmethod
diff --git a/g4f/Provider/AItianhuSpace.py b/g4f/Provider/AItianhuSpace.py
index 46856060..d316fc6f 100644
--- a/g4f/Provider/AItianhuSpace.py
+++ b/g4f/Provider/AItianhuSpace.py
@@ -27,26 +27,26 @@ class AItianhuSpace(AsyncGeneratorProvider):
if not model:
model = "gpt-3.5-turbo"
-
- elif not model in domains:
+
+ elif model not in domains:
raise ValueError(f"Model are not supported: {model}")
-
+
if not domain:
chars = 'abcdefghijklmnopqrstuvwxyz0123456789'
rand = ''.join(random.choice(chars) for _ in range(6))
domain = f"{rand}.{domains[model]}"
-
+
if debug.logging:
print(f"AItianhuSpace | using domain: {domain}")
-
+
if not cookies:
cookies = get_cookies('.aitianhu.space')
- if not cookies:
- raise RuntimeError(f"g4f.provider.{cls.__name__} requires cookies [refresh https://{domain} on chrome]")
-
+ if not cookies:
+ raise RuntimeError(f"g4f.provider.{cls.__name__} requires cookies [refresh https://{domain} on chrome]")
+
url = f'https://{domain}'
async with StreamSession(proxies={"https": proxy},
- cookies=cookies, timeout=timeout, impersonate="chrome110", verify=False) as session:
+ cookies=cookies, timeout=timeout, impersonate="chrome110", verify=False) as session:
data = {
"prompt": format_prompt(messages),
@@ -71,8 +71,9 @@ class AItianhuSpace(AsyncGeneratorProvider):
raise RuntimeError("Platform's Risk Control")
line = json.loads(line)
if "detail" in line:
- content = line["detail"]["choices"][0]["delta"].get("content")
- if content:
+ if content := line["detail"]["choices"][0]["delta"].get(
+ "content"
+ ):
yield content
elif "message" in line and "AI-4接口非常昂贵" in line["message"]:
raise RuntimeError("Rate limit for GPT 4 reached")
diff --git a/g4f/Provider/Aichat.py b/g4f/Provider/Aichat.py
index d32c99e1..77ae4429 100644
--- a/g4f/Provider/Aichat.py
+++ b/g4f/Provider/Aichat.py
@@ -20,8 +20,10 @@ class Aichat(AsyncProvider):
cookies = get_cookies('chat-gpt.org') if not kwargs.get('cookies') else kwargs.get('cookies')
if not cookies:
- raise RuntimeError(f"g4f.provider.Aichat requires cookies, [refresh https://chat-gpt.org on chrome]")
-
+ raise RuntimeError(
+ "g4f.provider.Aichat requires cookies, [refresh https://chat-gpt.org on chrome]"
+ )
+
headers = {
'authority': 'chat-gpt.org',
'accept': '*/*',
@@ -37,13 +39,13 @@ class Aichat(AsyncProvider):
'sec-fetch-site': 'same-origin',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36',
}
-
+
async with StreamSession(headers=headers,
cookies=cookies,
timeout=6,
proxies={"https": proxy} if proxy else None,
impersonate="chrome110", verify=False) as session:
-
+
json_data = {
"message": format_prompt(messages),
"temperature": kwargs.get('temperature', 0.5),
@@ -51,14 +53,14 @@ class Aichat(AsyncProvider):
"top_p": kwargs.get('top_p', 1),
"frequency_penalty": 0,
}
-
+
async with session.post("https://chat-gpt.org/api/text",
json=json_data) as response:
-
+
response.raise_for_status()
result = await response.json()
-
+
if not result['response']:
raise Exception(f"Error Response: {result}")
-
+
return result["message"]
diff --git a/g4f/Provider/Ails.py b/g4f/Provider/Ails.py
index 4d072646..fae3e62a 100644
--- a/g4f/Provider/Ails.py
+++ b/g4f/Provider/Ails.py
@@ -44,8 +44,8 @@ class Ails(AsyncGeneratorProvider):
"from-url": "https://ai.ls/?chat=1"
}
async with ClientSession(
- headers=headers
- ) as session:
+ headers=headers
+ ) as session:
timestamp = _format_timestamp(int(time.time() * 1000))
json_data = {
"model": "gpt-3.5-turbo",
@@ -57,10 +57,10 @@ class Ails(AsyncGeneratorProvider):
"s": _hash({"t": timestamp, "m": messages[-1]["content"]}),
}
async with session.post(
- "https://api.caipacity.com/v1/chat/completions",
- proxy=proxy,
- json=json_data
- ) as response:
+ "https://api.caipacity.com/v1/chat/completions",
+ proxy=proxy,
+ json=json_data
+ ) as response:
response.raise_for_status()
start = "data: "
async for line in response.content:
@@ -68,10 +68,9 @@ class Ails(AsyncGeneratorProvider):
if line.startswith(start) and line != "data: [DONE]":
line = line[len(start):-1]
line = json.loads(line)
- token = line["choices"][0]["delta"].get("content")
- if token:
+ if token := line["choices"][0]["delta"].get("content"):
if "ai.ls" in token or "ai.ci" in token:
- raise Exception("Response Error: " + token)
+ raise Exception(f"Response Error: {token}")
yield token
@@ -89,12 +88,7 @@ class Ails(AsyncGeneratorProvider):
def _hash(json_data: dict[str, str]) -> SHA256:
- base_string: str = "%s:%s:%s:%s" % (
- json_data["t"],
- json_data["m"],
- "WI,2rU#_r:r~aF4aJ36[.Z(/8Rv93Rf",
- len(json_data["m"]),
- )
+ base_string: str = f'{json_data["t"]}:{json_data["m"]}:WI,2rU#_r:r~aF4aJ36[.Z(/8Rv93Rf:{len(json_data["m"])}'
return SHA256(hashlib.sha256(base_string.encode()).hexdigest())
diff --git a/g4f/Provider/Bing.py b/g4f/Provider/Bing.py
index 91e9dc2c..ae7f106b 100644
--- a/g4f/Provider/Bing.py
+++ b/g4f/Provider/Bing.py
@@ -56,9 +56,10 @@ class Bing(AsyncGeneratorProvider):
return stream_generate(prompt, tone, image, context, proxy, cookies)
def create_context(messages: Messages):
- context = "".join(f"[{message['role']}](#message)\n{message['content']}\n\n" for message in messages)
-
- return context
+ return "".join(
+ f"[{message['role']}](#message)\n{message['content']}\n\n"
+ for message in messages
+ )
class Conversation():
def __init__(self, conversationId: str, clientId: str, conversationSignature: str, imageInfo: dict=None) -> None:
@@ -71,7 +72,7 @@ async def create_conversation(session: ClientSession, tone: str, image: str = No
url = 'https://www.bing.com/turing/conversation/create?bundleVersion=1.1199.4'
async with await session.get(url, proxy=proxy) as response:
data = await response.json()
-
+
conversationId = data.get('conversationId')
clientId = data.get('clientId')
conversationSignature = response.headers.get('X-Sydney-Encryptedconversationsignature')
@@ -110,30 +111,30 @@ async def create_conversation(session: ClientSession, tone: str, image: str = No
new_img_binary_data = compress_image_to_base64(new_img, compression_rate)
data, boundary = build_image_upload_api_payload(new_img_binary_data, conversation, tone)
headers = session.headers.copy()
- headers["content-type"] = 'multipart/form-data; boundary=' + boundary
+ headers["content-type"] = f'multipart/form-data; boundary={boundary}'
headers["referer"] = 'https://www.bing.com/search?q=Bing+AI&showconv=1&FORM=hpcodx'
headers["origin"] = 'https://www.bing.com'
async with await session.post("https://www.bing.com/images/kblob", data=data, headers=headers, proxy=proxy) as image_upload_response:
- if image_upload_response.status == 200:
- image_info = await image_upload_response.json()
- result = {}
- if image_info.get('blobId'):
- result['bcid'] = image_info.get('blobId', "")
- result['blurredBcid'] = image_info.get('processedBlobId', "")
- if result['blurredBcid'] != "":
- result["imageUrl"] = "https://www.bing.com/images/blob?bcid=" + result['blurredBcid']
- elif result['bcid'] != "":
- result["imageUrl"] = "https://www.bing.com/images/blob?bcid=" + result['bcid']
- if config['visualSearch']["enableFaceBlurDebug"]:
- result['originalImageUrl'] = "https://www.bing.com/images/blob?bcid=" + result['blurredBcid']
- else:
- result['originalImageUrl'] = "https://www.bing.com/images/blob?bcid=" + result['bcid']
- conversation.imageInfo = result
- else:
- raise Exception("Failed to parse image info.")
- else:
+ if image_upload_response.status != 200:
raise Exception("Failed to upload image.")
+ image_info = await image_upload_response.json()
+ if not image_info.get('blobId'):
+ raise Exception("Failed to parse image info.")
+ result = {'bcid': image_info.get('blobId', "")}
+ result['blurredBcid'] = image_info.get('processedBlobId', "")
+ if result['blurredBcid'] != "":
+ result["imageUrl"] = "https://www.bing.com/images/blob?bcid=" + result['blurredBcid']
+ elif result['bcid'] != "":
+ result["imageUrl"] = "https://www.bing.com/images/blob?bcid=" + result['bcid']
+ result['originalImageUrl'] = (
+ "https://www.bing.com/images/blob?bcid="
+ + result['blurredBcid']
+ if config['visualSearch']["enableFaceBlurDebug"]
+ else "https://www.bing.com/images/blob?bcid="
+ + result['bcid']
+ )
+ conversation.imageInfo = result
except Exception as e:
print(f"An error happened while trying to send image: {str(e)}")
return conversation
@@ -282,7 +283,18 @@ def build_image_upload_api_payload(image_bin: str, conversation: Conversation, t
'knowledgeRequest': payload
}
boundary="----WebKitFormBoundary" + ''.join(random.choices(string.ascii_letters + string.digits, k=16))
- data = '--' + boundary + '\r\nContent-Disposition: form-data; name="knowledgeRequest"\r\n\r\n' + json.dumps(knowledge_request,ensure_ascii=False) + "\r\n--" + boundary + '\r\nContent-Disposition: form-data; name="imageBase64"\r\n\r\n' + image_bin + "\r\n--" + boundary + "--\r\n"
+ data = (
+ f'--{boundary}'
+ + '\r\nContent-Disposition: form-data; name="knowledgeRequest"\r\n\r\n'
+ + json.dumps(knowledge_request, ensure_ascii=False)
+ + "\r\n--"
+ + boundary
+ + '\r\nContent-Disposition: form-data; name="imageBase64"\r\n\r\n'
+ + image_bin
+ + "\r\n--"
+ + boundary
+ + "--\r\n"
+ )
return data, boundary
def is_data_uri_an_image(data_uri):
@@ -329,7 +341,7 @@ def extract_data_uri(data_uri):
def get_orientation(data: bytes):
try:
- if data[0:2] != b'\xFF\xD8':
+ if data[:2] != b'\xFF\xD8':
raise Exception('NotJpeg')
with Image.open(data) as img:
exif_data = img._getexif()
@@ -347,11 +359,11 @@ def process_image(orientation, img, new_width, new_height):
if orientation:
if orientation > 4:
img = img.transpose(Image.FLIP_LEFT_RIGHT)
- if orientation == 3 or orientation == 4:
+ if orientation in [3, 4]:
img = img.transpose(Image.ROTATE_180)
- if orientation == 5 or orientation == 6:
+ if orientation in [5, 6]:
img = img.transpose(Image.ROTATE_270)
- if orientation == 7 or orientation == 8:
+ if orientation in [7, 8]:
img = img.transpose(Image.ROTATE_90)
new_img.paste(img, (0, 0))
return new_img
@@ -362,8 +374,7 @@ def compress_image_to_base64(img, compression_rate):
try:
output_buffer = io.BytesIO()
img.save(output_buffer, format="JPEG", quality=int(compression_rate * 100))
- base64_image = base64.b64encode(output_buffer.getvalue()).decode('utf-8')
- return base64_image
+ return base64.b64encode(output_buffer.getvalue()).decode('utf-8')
except Exception as e:
raise e
@@ -425,19 +436,14 @@ async def stream_generate(
cookies: dict = None
):
async with ClientSession(
- timeout=ClientTimeout(total=900),
- cookies=cookies,
- headers=Defaults.headers,
- ) as session:
+ timeout=ClientTimeout(total=900),
+ cookies=cookies,
+ headers=Defaults.headers,
+ ) as session:
conversation = await create_conversation(session, tone, image, proxy)
try:
- async with session.ws_connect(
- f'wss://sydney.bing.com/sydney/ChatHub',
- autoping=False,
- params={'sec_access_token': conversation.conversationSignature},
- proxy=proxy
- ) as wss:
-
+ async with session.ws_connect('wss://sydney.bing.com/sydney/ChatHub', autoping=False, params={'sec_access_token': conversation.conversationSignature}, proxy=proxy) as wss:
+
await wss.send_str(format_message({'protocol': 'json', 'version': 1}))
await wss.receive(timeout=900)
await wss.send_str(create_message(conversation, prompt, tone, context))
@@ -451,7 +457,7 @@ async def stream_generate(
for obj in objects:
if obj is None or not obj:
continue
-
+
response = json.loads(obj)
if response.get('type') == 1 and response['arguments'][0].get('messages'):
message = response['arguments'][0]['messages'][0]
diff --git a/g4f/Provider/ChatBase.py b/g4f/Provider/ChatBase.py
index 3d45b40b..8f9e2aad 100644
--- a/g4f/Provider/ChatBase.py
+++ b/g4f/Provider/ChatBase.py
@@ -20,16 +20,16 @@ class ChatBase(AsyncGeneratorProvider):
**kwargs
) -> AsyncResult:
chat_id = 'z2c2HSfKnCTh5J4650V0I'
-
+
headers = {
- "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36",
- "Accept" : "*/*",
- "Accept-language" : "en,fr-FR;q=0.9,fr;q=0.8,es-ES;q=0.7,es;q=0.6,en-US;q=0.5,am;q=0.4,de;q=0.3",
- "Origin" : cls.url,
- "Referer" : cls.url + "/",
- "Sec-Fetch-Dest" : "empty",
- "Sec-Fetch-Mode" : "cors",
- "Sec-Fetch-Site" : "same-origin",
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36",
+ "Accept": "*/*",
+ "Accept-language": "en,fr-FR;q=0.9,fr;q=0.8,es-ES;q=0.7,es;q=0.6,en-US;q=0.5,am;q=0.4,de;q=0.3",
+ "Origin": cls.url,
+ "Referer": f"{cls.url}/",
+ "Sec-Fetch-Dest": "empty",
+ "Sec-Fetch-Mode": "cors",
+ "Sec-Fetch-Site": "same-origin",
}
async with ClientSession(headers=headers) as session:
data = {
@@ -38,7 +38,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, proxy=proxy) as response:
response.raise_for_status()
async for stream in response.content.iter_any():
diff --git a/g4f/Provider/Chatgpt4Online.py b/g4f/Provider/Chatgpt4Online.py
index 25208067..e81c8d4c 100644
--- a/g4f/Provider/Chatgpt4Online.py
+++ b/g4f/Provider/Chatgpt4Online.py
@@ -31,8 +31,8 @@ class Chatgpt4Online(AsyncGeneratorProvider):
"newMessage": messages[-1]["content"],
"stream": True
}
-
- async with session.post(cls.url + "/wp-json/mwai-ui/v1/chats/submit", json=data, proxy=proxy) as response:
+
+ async with session.post(f"{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 d5fd5bff..9783d868 100644
--- a/g4f/Provider/ChatgptAi.py
+++ b/g4f/Provider/ChatgptAi.py
@@ -38,18 +38,17 @@ class ChatgptAi(AsyncGeneratorProvider):
"user-agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
}
async with ClientSession(
- headers=headers
- ) as session:
+ headers=headers
+ ) as session:
if not cls._system:
async with session.get(cls.url, proxy=proxy) as response:
response.raise_for_status()
text = await response.text()
- result = re.search(r"data-system='(.*?)'", text)
- if result:
+ if result := re.search(r"data-system='(.*?)'", text):
cls._system = json.loads(html.unescape(result.group(1)))
- if not cls._system:
- raise RuntimeError("System args not found")
-
+ if not cls._system:
+ raise RuntimeError("System args not found")
+
data = {
"botId": cls._system["botId"],
"customId": cls._system["customId"],
diff --git a/g4f/Provider/ChatgptDemo.py b/g4f/Provider/ChatgptDemo.py
index 9efa89ba..bc592ca6 100644
--- a/g4f/Provider/ChatgptDemo.py
+++ b/g4f/Provider/ChatgptDemo.py
@@ -37,10 +37,13 @@ class ChatgptDemo(AsyncGeneratorProvider):
async with session.get(f"{cls.url}/", proxy=proxy) as response:
response.raise_for_status()
response = await response.text()
- result = re.search(r'<div id="USERID" style="display: none">(.*?)<\/div>', response)
- if not result:
+ if result := re.search(
+ r'<div id="USERID" style="display: none">(.*?)<\/div>',
+ response,
+ ):
+ user_id = result.group(1)
+ else:
raise RuntimeError("No user id found")
- user_id = result.group(1)
async with session.post(f"{cls.url}/new_chat", json={"user_id": user_id}, proxy=proxy) as response:
response.raise_for_status()
chat_id = (await response.json())["id_"]
@@ -56,6 +59,5 @@ class ChatgptDemo(AsyncGeneratorProvider):
async for line in response.content:
if line.startswith(b"data: "):
line = json.loads(line[6:-1])
- chunk = line["choices"][0]["delta"].get("content")
- if chunk:
+ if chunk := line["choices"][0]["delta"].get("content"):
yield chunk \ No newline at end of file
diff --git a/g4f/Provider/ChatgptFree.py b/g4f/Provider/ChatgptFree.py
index 806ff7cc..1bc6181a 100644
--- a/g4f/Provider/ChatgptFree.py
+++ b/g4f/Provider/ChatgptFree.py
@@ -31,8 +31,8 @@ class ChatgptFree(AsyncProvider):
if not cookies:
cookies = get_cookies('chatgptfree.ai')
- if not cookies:
- raise RuntimeError(f"g4f.provider.{cls.__name__} requires cookies [refresh https://chatgptfree.ai on chrome]")
+ if not cookies:
+ raise RuntimeError(f"g4f.provider.{cls.__name__} requires cookies [refresh https://chatgptfree.ai on chrome]")
headers = {
'authority': 'chatgptfree.ai',
@@ -48,14 +48,14 @@ class ChatgptFree(AsyncProvider):
'sec-fetch-site': 'same-origin',
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36',
}
-
+
async with StreamSession(
- headers=headers,
- cookies=cookies,
- impersonate="chrome107",
- proxies={"https": proxy},
- timeout=timeout
- ) as session:
+ headers=headers,
+ cookies=cookies,
+ impersonate="chrome107",
+ proxies={"https": proxy},
+ timeout=timeout
+ ) as session:
if not cls._nonce:
async with session.get(f"{cls.url}/") as response:
@@ -67,13 +67,13 @@ class ChatgptFree(AsyncProvider):
if not result:
raise RuntimeError("No post id found")
cls._post_id = result.group(1)
-
- result = re.search(r'data-nonce="(.*?)"', response)
- if not result:
+
+ if result := re.search(r'data-nonce="(.*?)"', response):
+ cls._nonce = result.group(1)
+
+ else:
raise RuntimeError("No nonce found")
-
- cls._nonce = result.group(1)
-
+
prompt = format_prompt(messages)
data = {
"_wpnonce": cls._nonce,
@@ -83,8 +83,7 @@ class ChatgptFree(AsyncProvider):
"message": prompt,
"bot_id": "0"
}
- async with session.post(cls.url + "/wp-admin/admin-ajax.php",
- data=data, cookies=cookies) as response:
-
+ async with session.post(f"{cls.url}/wp-admin/admin-ajax.php", data=data, cookies=cookies) as response:
+
response.raise_for_status()
return (await response.json())["data"] \ No newline at end of file
diff --git a/g4f/Provider/ChatgptLogin.py b/g4f/Provider/ChatgptLogin.py
index fee9252d..206e4a89 100644
--- a/g4f/Provider/ChatgptLogin.py
+++ b/g4f/Provider/ChatgptLogin.py
@@ -45,10 +45,13 @@ class ChatgptLogin(AsyncGeneratorProvider):
async with session.get(f"{cls.url}/chat/", proxy=proxy) as response:
response.raise_for_status()
response = await response.text()
- result = re.search(r'<div id="USERID" style="display: none">(.*?)<\/div>', response)
- if not result:
+ if result := re.search(
+ r'<div id="USERID" style="display: none">(.*?)<\/div>',
+ response,
+ ):
+ cls._user_id = result.group(1)
+ else:
raise RuntimeError("No user id found")
- cls._user_id = result.group(1)
async with session.post(f"{cls.url}/chat/new_chat", json={"user_id": cls._user_id}, proxy=proxy) as response:
response.raise_for_status()
chat_id = (await response.json())["id_"]
@@ -64,8 +67,9 @@ class ChatgptLogin(AsyncGeneratorProvider):
response.raise_for_status()
async for line in response.content:
if line.startswith(b"data: "):
- content = json.loads(line[6:])["choices"][0]["delta"].get("content")
- if content:
+ if content := json.loads(line[6:])["choices"][0][
+ "delta"
+ ].get("content"):
yield content
async with session.post(f"{cls.url}/chat/delete_chat", json={"chat_id": chat_id}, proxy=proxy) as response:
response.raise_for_status() \ No newline at end of file
diff --git a/g4f/Provider/ChatgptX.py b/g4f/Provider/ChatgptX.py
index 8052f65b..9a8711b9 100644
--- a/g4f/Provider/ChatgptX.py
+++ b/g4f/Provider/ChatgptX.py
@@ -35,14 +35,15 @@ class ChatgptX(AsyncGeneratorProvider):
async with ClientSession(headers=headers) as session:
async with session.get(f"{cls.url}/", proxy=proxy) as response:
response = await response.text()
- result = re.search(r'<meta name="csrf-token" content="(.*?)"', response)
- if result:
+ if result := re.search(
+ r'<meta name="csrf-token" content="(.*?)"', response
+ ):
csrf_token = result.group(1)
- result = re.search(r"openconversions\('(.*?)'\)", response)
- if result:
+ if result := re.search(r"openconversions\('(.*?)'\)", response):
chat_id = result.group(1)
- result = re.search(r'<input type="hidden" id="user_id" value="(.*?)"', response)
- if result:
+ if result := re.search(
+ r'<input type="hidden" id="user_id" value="(.*?)"', response
+ ):
user_id = result.group(1)
if not csrf_token or not chat_id or not user_id:
@@ -63,7 +64,7 @@ class ChatgptX(AsyncGeneratorProvider):
'x-csrf-token': csrf_token,
'x-requested-with': 'XMLHttpRequest'
}
- async with session.post(cls.url + '/sendchat', data=data, headers=headers, proxy=proxy) as response:
+ async with session.post(f'{cls.url}/sendchat', data=data, headers=headers, proxy=proxy) as response:
response.raise_for_status()
chat = await response.json()
if "response" not in chat or not chat["response"]:
diff --git a/g4f/Provider/GPTalk.py b/g4f/Provider/GPTalk.py
index afb6ff68..c6b57d91 100644
--- a/g4f/Provider/GPTalk.py
+++ b/g4f/Provider/GPTalk.py
@@ -49,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, proxy=proxy) as response:
+ async with session.post(f"{cls.url}/api/chatgpt/user/login", json=data, proxy=proxy) as response:
response.raise_for_status()
cls._auth = (await response.json())["data"]
data = {
@@ -69,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, proxy=proxy) as response:
+ async with session.post(f"{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}, proxy=proxy) as response:
+ async with session.get(f"{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/GptChatly.py b/g4f/Provider/GptChatly.py
index f4953b78..465d2527 100644
--- a/g4f/Provider/GptChatly.py
+++ b/g4f/Provider/GptChatly.py
@@ -23,13 +23,15 @@ class GptChatly(AsyncProvider):
cookies = get_cookies('gptchatly.com') if not cookies else cookies
if not cookies:
- raise RuntimeError(f"g4f.provider.GptChatly requires cookies, [refresh https://gptchatly.com on chrome]")
-
+ raise RuntimeError(
+ "g4f.provider.GptChatly requires cookies, [refresh https://gptchatly.com on chrome]"
+ )
+
if model.startswith("gpt-4"):
chat_url = f"{cls.url}/fetch-gpt4-response"
else:
chat_url = f"{cls.url}/fetch-response"
-
+
headers = {
'authority': 'gptchatly.com',
'accept': '*/*',
@@ -45,7 +47,7 @@ class GptChatly(AsyncProvider):
'sec-fetch-site': 'same-origin',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36',
}
-
+
async with StreamSession(headers=headers,
proxies={"https": proxy}, cookies=cookies, impersonate='chrome110') as session:
data = {
diff --git a/g4f/Provider/GptForLove.py b/g4f/Provider/GptForLove.py
index 9f7156b2..28939592 100644
--- a/g4f/Provider/GptForLove.py
+++ b/g4f/Provider/GptForLove.py
@@ -55,8 +55,9 @@ class GptForLove(AsyncGeneratorProvider):
except:
raise RuntimeError(f"Broken line: {line}")
if "detail" in line:
- content = line["detail"]["choices"][0]["delta"].get("content")
- if content:
+ if content := line["detail"]["choices"][0]["delta"].get(
+ "content"
+ ):
yield content
elif "10分钟内提问超过了5次" in line:
raise RuntimeError("Rate limit reached")
@@ -66,7 +67,7 @@ class GptForLove(AsyncGeneratorProvider):
def get_secret() -> str:
dir = os.path.dirname(__file__)
- include = dir + '/npm/node_modules/crypto-js/crypto-js'
+ include = f'{dir}/npm/node_modules/crypto-js/crypto-js'
source = """
CryptoJS = require({include})
var k = '14487141bvirvvG'
diff --git a/g4f/Provider/GptGo.py b/g4f/Provider/GptGo.py
index 255c0ca9..6d477da0 100644
--- a/g4f/Provider/GptGo.py
+++ b/g4f/Provider/GptGo.py
@@ -21,18 +21,18 @@ class GptGo(AsyncGeneratorProvider):
**kwargs
) -> AsyncResult:
headers = {
- "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36",
- "Accept" : "*/*",
- "Accept-language" : "en,fr-FR;q=0.9,fr;q=0.8,es-ES;q=0.7,es;q=0.6,en-US;q=0.5,am;q=0.4,de;q=0.3",
- "Origin" : cls.url,
- "Referer" : cls.url + "/",
- "Sec-Fetch-Dest" : "empty",
- "Sec-Fetch-Mode" : "cors",
- "Sec-Fetch-Site" : "same-origin",
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36",
+ "Accept": "*/*",
+ "Accept-language": "en,fr-FR;q=0.9,fr;q=0.8,es-ES;q=0.7,es;q=0.6,en-US;q=0.5,am;q=0.4,de;q=0.3",
+ "Origin": cls.url,
+ "Referer": f"{cls.url}/",
+ "Sec-Fetch-Dest": "empty",
+ "Sec-Fetch-Mode": "cors",
+ "Sec-Fetch-Site": "same-origin",
}
async with ClientSession(
- headers=headers
- ) as session:
+ headers=headers
+ ) as session:
async with session.get(
"https://gptgo.ai/action_get_token.php",
params={
@@ -46,12 +46,12 @@ class GptGo(AsyncGeneratorProvider):
token = (await response.json(content_type=None))["token"]
async with session.get(
- "https://gptgo.ai/action_ai_gpt.php",
- params={
- "token": token,
- },
- proxy=proxy
- ) as response:
+ "https://gptgo.ai/action_ai_gpt.php",
+ params={
+ "token": token,
+ },
+ proxy=proxy
+ ) as response:
response.raise_for_status()
start = "data: "
async for line in response.content:
@@ -62,8 +62,7 @@ class GptGo(AsyncGeneratorProvider):
line = json.loads(line[len(start):-1])
if line["choices"][0]["finish_reason"] == "stop":
break
- content = line["choices"][0]["delta"].get("content")
- if content:
+ if content := line["choices"][0]["delta"].get("content"):
yield content
diff --git a/g4f/Provider/GptGod.py b/g4f/Provider/GptGod.py
index 060500a9..8a575746 100644
--- a/g4f/Provider/GptGod.py
+++ b/g4f/Provider/GptGod.py
@@ -33,7 +33,7 @@ class GptGod(AsyncGeneratorProvider):
"Pragma": "no-cache",
"Cache-Control": "no-cache",
}
-
+
async with ClientSession(headers=headers) as session:
prompt = format_prompt(messages)
data = {
@@ -45,12 +45,11 @@ class GptGod(AsyncGeneratorProvider):
event = None
async for line in response.content:
print(line)
-
+
if line.startswith(b'event: '):
event = line[7:-1]
elif event == b"data" and line.startswith(b"data: "):
- data = json.loads(line[6:-1])
- if data:
+ if data := json.loads(line[6:-1]):
yield data
elif event == b"done":
break \ No newline at end of file
diff --git a/g4f/Provider/Liaobots.py b/g4f/Provider/Liaobots.py
index 740be856..9dc52aae 100644
--- a/g4f/Provider/Liaobots.py
+++ b/g4f/Provider/Liaobots.py
@@ -49,7 +49,7 @@ class Liaobots(AsyncGeneratorProvider):
"authority": "liaobots.com",
"content-type": "application/json",
"origin": cls.url,
- "referer": cls.url + "/",
+ "referer": f"{cls.url}/",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36",
}
async with ClientSession(
diff --git a/g4f/Provider/Vercel.py b/g4f/Provider/Vercel.py
index 7c3b8c55..eb5aa20a 100644
--- a/g4f/Provider/Vercel.py
+++ b/g4f/Provider/Vercel.py
@@ -24,30 +24,27 @@ class Vercel(BaseProvider):
if not model:
model = "gpt-3.5-turbo"
-
+
elif model not in model_info:
raise ValueError(f"Vercel does not support {model}")
-
+
headers = {
- 'authority' : 'sdk.vercel.ai',
- 'accept' : '*/*',
- 'accept-language' : 'en,fr-FR;q=0.9,fr;q=0.8,es-ES;q=0.7,es;q=0.6,en-US;q=0.5,am;q=0.4,de;q=0.3',
- 'cache-control' : 'no-cache',
- 'content-type' : 'application/json',
- 'custom-encoding' : get_anti_bot_token(),
- 'origin' : 'https://sdk.vercel.ai',
- 'pragma' : 'no-cache',
- 'referer' : 'https://sdk.vercel.ai/',
- 'sec-ch-ua' : '"Google Chrome";v="117", "Not;A=Brand";v="8", "Chromium";v="117"',
- 'sec-ch-ua-mobile' : '?0',
+ 'authority': 'sdk.vercel.ai',
+ 'accept': '*/*',
+ 'accept-language': 'en,fr-FR;q=0.9,fr;q=0.8,es-ES;q=0.7,es;q=0.6,en-US;q=0.5,am;q=0.4,de;q=0.3',
+ 'cache-control': 'no-cache',
+ 'content-type': 'application/json',
+ 'custom-encoding': get_anti_bot_token(),
+ 'origin': 'https://sdk.vercel.ai',
+ 'pragma': 'no-cache',
+ 'referer': 'https://sdk.vercel.ai/',
+ 'sec-ch-ua': '"Google Chrome";v="117", "Not;A=Brand";v="8", "Chromium";v="117"',
+ 'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"macOS"',
- 'sec-fetch-dest' : 'empty',
- 'sec-fetch-mode' : 'cors',
- 'sec-fetch-site' : 'same-origin',
- 'user-agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.%s.%s Safari/537.36' % (
- random.randint(99, 999),
- random.randint(99, 999)
- )
+ 'sec-fetch-dest': 'empty',
+ 'sec-fetch-mode': 'cors',
+ 'sec-fetch-site': 'same-origin',
+ 'user-agent': f'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.{random.randint(99, 999)}.{random.randint(99, 999)} Safari/537.36',
}
json_data = {
@@ -60,7 +57,7 @@ class Vercel(BaseProvider):
}
max_retries = kwargs.get('max_retries', 20)
- for i in range(max_retries):
+ for _ in range(max_retries):
response = requests.post('https://sdk.vercel.ai/api/generate',
headers=headers, json=json_data, stream=True, proxies={"https": proxy})
try:
@@ -74,22 +71,19 @@ class Vercel(BaseProvider):
def get_anti_bot_token() -> str:
headers = {
- 'authority' : 'sdk.vercel.ai',
- 'accept' : '*/*',
- 'accept-language' : 'en,fr-FR;q=0.9,fr;q=0.8,es-ES;q=0.7,es;q=0.6,en-US;q=0.5,am;q=0.4,de;q=0.3',
- 'cache-control' : 'no-cache',
- 'pragma' : 'no-cache',
- 'referer' : 'https://sdk.vercel.ai/',
- 'sec-ch-ua' : '"Google Chrome";v="117", "Not;A=Brand";v="8", "Chromium";v="117"',
- 'sec-ch-ua-mobile' : '?0',
+ 'authority': 'sdk.vercel.ai',
+ 'accept': '*/*',
+ 'accept-language': 'en,fr-FR;q=0.9,fr;q=0.8,es-ES;q=0.7,es;q=0.6,en-US;q=0.5,am;q=0.4,de;q=0.3',
+ 'cache-control': 'no-cache',
+ 'pragma': 'no-cache',
+ 'referer': 'https://sdk.vercel.ai/',
+ 'sec-ch-ua': '"Google Chrome";v="117", "Not;A=Brand";v="8", "Chromium";v="117"',
+ 'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"macOS"',
- 'sec-fetch-dest' : 'empty',
- 'sec-fetch-mode' : 'cors',
- 'sec-fetch-site' : 'same-origin',
- 'user-agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.%s.%s Safari/537.36' % (
- random.randint(99, 999),
- random.randint(99, 999)
- )
+ 'sec-fetch-dest': 'empty',
+ 'sec-fetch-mode': 'cors',
+ 'sec-fetch-site': 'same-origin',
+ 'user-agent': f'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.{random.randint(99, 999)}.{random.randint(99, 999)} Safari/537.36',
}
response = requests.get('https://sdk.vercel.ai/openai.jpeg',
diff --git a/g4f/Provider/Ylokh.py b/g4f/Provider/Ylokh.py
index b13f846e..dce76f22 100644
--- a/g4f/Provider/Ylokh.py
+++ b/g4f/Provider/Ylokh.py
@@ -23,10 +23,7 @@ class Ylokh(AsyncGeneratorProvider):
**kwargs
) -> AsyncResult:
model = model if model else "gpt-3.5-turbo"
- headers = {
- "Origin" : cls.url,
- "Referer": cls.url + "/",
- }
+ headers = {"Origin": cls.url, "Referer": f"{cls.url}/"}
data = {
"messages": messages,
"model": model,
@@ -39,10 +36,10 @@ class Ylokh(AsyncGeneratorProvider):
**kwargs
}
async with StreamSession(
- headers=headers,
- proxies={"https": proxy},
- timeout=timeout
- ) as session:
+ headers=headers,
+ proxies={"https": proxy},
+ timeout=timeout
+ ) as session:
async with session.post("https://chatapi.ylokh.xyz/v1/chat/completions", json=data) as response:
response.raise_for_status()
if stream:
@@ -52,8 +49,9 @@ class Ylokh(AsyncGeneratorProvider):
if line.startswith("data: [DONE]"):
break
line = json.loads(line[6:])
- content = line["choices"][0]["delta"].get("content")
- if content:
+ if content := line["choices"][0]["delta"].get(
+ "content"
+ ):
yield content
else:
chat = await response.json()
diff --git a/g4f/Provider/deprecated/AiService.py b/g4f/Provider/deprecated/AiService.py
index d1d15859..325af670 100644
--- a/g4f/Provider/deprecated/AiService.py
+++ b/g4f/Provider/deprecated/AiService.py
@@ -18,9 +18,12 @@ class AiService(BaseProvider):
stream: bool,
**kwargs: Any,
) -> CreateResult:
- base = "\n".join(f"{message['role']}: {message['content']}" for message in messages)
- base += "\nassistant: "
-
+ base = (
+ "\n".join(
+ f"{message['role']}: {message['content']}" for message in messages
+ )
+ + "\nassistant: "
+ )
headers = {
"accept": "*/*",
"content-type": "text/plain;charset=UTF-8",
diff --git a/g4f/Provider/deprecated/CodeLinkAva.py b/g4f/Provider/deprecated/CodeLinkAva.py
index 8407ebb9..64ce1af9 100644
--- a/g4f/Provider/deprecated/CodeLinkAva.py
+++ b/g4f/Provider/deprecated/CodeLinkAva.py
@@ -20,18 +20,18 @@ class CodeLinkAva(AsyncGeneratorProvider):
**kwargs
) -> AsyncGenerator:
headers = {
- "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36",
- "Accept" : "*/*",
- "Accept-language" : "en,fr-FR;q=0.9,fr;q=0.8,es-ES;q=0.7,es;q=0.6,en-US;q=0.5,am;q=0.4,de;q=0.3",
- "Origin" : cls.url,
- "Referer" : cls.url + "/",
- "Sec-Fetch-Dest" : "empty",
- "Sec-Fetch-Mode" : "cors",
- "Sec-Fetch-Site" : "same-origin",
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36",
+ "Accept": "*/*",
+ "Accept-language": "en,fr-FR;q=0.9,fr;q=0.8,es-ES;q=0.7,es;q=0.6,en-US;q=0.5,am;q=0.4,de;q=0.3",
+ "Origin": cls.url,
+ "Referer": f"{cls.url}/",
+ "Sec-Fetch-Dest": "empty",
+ "Sec-Fetch-Mode": "cors",
+ "Sec-Fetch-Site": "same-origin",
}
async with ClientSession(
- headers=headers
- ) as session:
+ headers=headers
+ ) as session:
data = {
"messages": messages,
"temperature": 0.6,
@@ -46,8 +46,7 @@ class CodeLinkAva(AsyncGeneratorProvider):
if line.startswith("data: [DONE]"):
break
line = json.loads(line[6:-1])
- content = line["choices"][0]["delta"].get("content")
- if content:
+ if content := line["choices"][0]["delta"].get("content"):
yield content
diff --git a/g4f/Provider/deprecated/EasyChat.py b/g4f/Provider/deprecated/EasyChat.py
index ffe9a785..bd49c09c 100644
--- a/g4f/Provider/deprecated/EasyChat.py
+++ b/g4f/Provider/deprecated/EasyChat.py
@@ -30,7 +30,7 @@ class EasyChat(BaseProvider):
"https://chat4.fastgpt.me",
"https://gxos1h1ddt.fastgpt.me"
]
-
+
server = active_servers[kwargs.get("active_server", random.randint(0, 5))]
headers = {
"authority" : f"{server}".replace("https://", ""),
@@ -68,30 +68,26 @@ class EasyChat(BaseProvider):
response = session.post(f"{server}/api/openai/v1/chat/completions",
headers=headers, json=json_data, stream=stream)
-
- if response.status_code == 200:
-
- if stream == False:
- json_data = response.json()
-
- if "choices" in json_data:
- yield json_data["choices"][0]["message"]["content"]
- else:
- raise Exception("No response from server")
-
+
+ if response.status_code != 200:
+ raise Exception(f"Error {response.status_code} from server : {response.reason}")
+ if not stream:
+ json_data = response.json()
+
+ if "choices" in json_data:
+ yield json_data["choices"][0]["message"]["content"]
else:
+ raise Exception("No response from server")
+
+ else:
- for chunk in response.iter_lines():
+ for chunk in response.iter_lines():
- if b"content" in chunk:
- splitData = chunk.decode().split("data:")
-
- if len(splitData) > 1:
- yield json.loads(splitData[1])["choices"][0]["delta"]["content"]
- else:
- continue
- else:
- raise Exception(f"Error {response.status_code} from server : {response.reason}")
+ if b"content" in chunk:
+ splitData = chunk.decode().split("data:")
+
+ if len(splitData) > 1:
+ yield json.loads(splitData[1])["choices"][0]["delta"]["content"]
@classmethod
diff --git a/g4f/Provider/deprecated/Equing.py b/g4f/Provider/deprecated/Equing.py
index 794274f2..5ba125a3 100644
--- a/g4f/Provider/deprecated/Equing.py
+++ b/g4f/Provider/deprecated/Equing.py
@@ -56,18 +56,17 @@ class Equing(BaseProvider):
response = requests.post('https://next.eqing.tech/api/openai/v1/chat/completions',
headers=headers, json=json_data, stream=stream)
-
+
if not stream:
yield response.json()["choices"][0]["message"]["content"]
return
-
+
for line in response.iter_content(chunk_size=1024):
if line:
if b'content' in line:
- line_json = json.loads(line.decode('utf-8').split('data: ')[1])
- token = line_json['choices'][0]['delta'].get('content')
- if token:
- yield token
+ line_json = json.loads(line.decode('utf-8').split('data: ')[1])
+ if token := line_json['choices'][0]['delta'].get('content'):
+ yield token
@classmethod
@property
diff --git a/g4f/Provider/deprecated/FastGpt.py b/g4f/Provider/deprecated/FastGpt.py
index 65efa29d..17b21b37 100644
--- a/g4f/Provider/deprecated/FastGpt.py
+++ b/g4f/Provider/deprecated/FastGpt.py
@@ -55,7 +55,7 @@ class FastGpt(BaseProvider):
'frequency_penalty' : kwargs.get('frequency_penalty', 0),
'top_p' : kwargs.get('top_p', 1),
}
-
+
subdomain = random.choice([
'jdaen979ew',
'chat9'
@@ -63,15 +63,16 @@ class FastGpt(BaseProvider):
response = requests.post(f'https://{subdomain}.fastgpt.me/api/openai/v1/chat/completions',
headers=headers, json=json_data, stream=stream)
-
+
for line in response.iter_lines():
if line:
try:
if b'content' in line:
- line_json = json.loads(line.decode('utf-8').split('data: ')[1])
- token = line_json['choices'][0]['delta'].get('content')
- if token:
- yield token
+ line_json = json.loads(line.decode('utf-8').split('data: ')[1])
+ if token := line_json['choices'][0]['delta'].get(
+ 'content'
+ ):
+ yield token
except:
continue
diff --git a/g4f/Provider/deprecated/H2o.py b/g4f/Provider/deprecated/H2o.py
index 47290a3e..cead17e1 100644
--- a/g4f/Provider/deprecated/H2o.py
+++ b/g4f/Provider/deprecated/H2o.py
@@ -22,7 +22,7 @@ class H2o(AsyncGeneratorProvider):
**kwargs
) -> AsyncResult:
model = model if model else cls.model
- headers = {"Referer": cls.url + "/"}
+ headers = {"Referer": f"{cls.url}/"}
async with ClientSession(
headers=headers
diff --git a/g4f/Provider/deprecated/Lockchat.py b/g4f/Provider/deprecated/Lockchat.py
index 4bd7c5fe..5acfbfbf 100644
--- a/g4f/Provider/deprecated/Lockchat.py
+++ b/g4f/Provider/deprecated/Lockchat.py
@@ -33,7 +33,7 @@ class Lockchat(BaseProvider):
}
response = requests.post("http://supertest.lockchat.app/v1/chat/completions",
json=payload, headers=headers, stream=True)
-
+
response.raise_for_status()
for token in response.iter_lines():
if b"The model: `gpt-4` does not exist" in token:
@@ -44,11 +44,10 @@ class Lockchat(BaseProvider):
stream = stream,
temperature = temperature,
**kwargs)
-
+
if b"content" in token:
token = json.loads(token.decode("utf-8").split("data: ")[1])
- token = token["choices"][0]["delta"].get("content")
- if token:
+ if token := token["choices"][0]["delta"].get("content"):
yield (token)
@classmethod
diff --git a/g4f/Provider/deprecated/V50.py b/g4f/Provider/deprecated/V50.py
index 9a8b032c..f4f4d823 100644
--- a/g4f/Provider/deprecated/V50.py
+++ b/g4f/Provider/deprecated/V50.py
@@ -21,9 +21,12 @@ class V50(BaseProvider):
messages: list[dict[str, str]],
stream: bool, **kwargs: Any) -> CreateResult:
- conversation = "\n".join(f"{message['role']}: {message['content']}" for message in messages)
- conversation += "\nassistant: "
-
+ conversation = (
+ "\n".join(
+ f"{message['role']}: {message['content']}" for message in messages
+ )
+ + "\nassistant: "
+ )
payload = {
"prompt" : conversation,
"options" : {},
@@ -33,7 +36,7 @@ class V50(BaseProvider):
"model" : model,
"user" : str(uuid.uuid4())
}
-
+
headers = {
'authority' : 'p5.v50.ltd',
'accept' : 'application/json, text/plain, */*',
@@ -47,9 +50,13 @@ class V50(BaseProvider):
'sec-fetch-site' : 'same-origin',
'user-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36'
}
- response = requests.post("https://p5.v50.ltd/api/chat-process",
- json=payload, headers=headers, proxies=kwargs['proxy'] if 'proxy' in kwargs else {})
-
+ response = requests.post(
+ "https://p5.v50.ltd/api/chat-process",
+ json=payload,
+ headers=headers,
+ proxies=kwargs.get('proxy', {}),
+ )
+
if "https://fk1.v50.ltd" not in response.text:
yield response.text
diff --git a/g4f/Provider/deprecated/Vitalentum.py b/g4f/Provider/deprecated/Vitalentum.py
index 8deb1f50..d6ba9336 100644
--- a/g4f/Provider/deprecated/Vitalentum.py
+++ b/g4f/Provider/deprecated/Vitalentum.py
@@ -20,14 +20,14 @@ class Vitalentum(AsyncGeneratorProvider):
**kwargs
) -> AsyncResult:
headers = {
- "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36",
- "Accept" : "text/event-stream",
- "Accept-language" : "de,en-US;q=0.7,en;q=0.3",
- "Origin" : cls.url,
- "Referer" : cls.url + "/",
- "Sec-Fetch-Dest" : "empty",
- "Sec-Fetch-Mode" : "cors",
- "Sec-Fetch-Site" : "same-origin",
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36",
+ "Accept": "text/event-stream",
+ "Accept-language": "de,en-US;q=0.7,en;q=0.3",
+ "Origin": cls.url,
+ "Referer": f"{cls.url}/",
+ "Sec-Fetch-Dest": "empty",
+ "Sec-Fetch-Mode": "cors",
+ "Sec-Fetch-Site": "same-origin",
}
conversation = json.dumps({"history": [{
"speaker": "human" if message["role"] == "user" else "bot",
@@ -39,8 +39,8 @@ class Vitalentum(AsyncGeneratorProvider):
**kwargs
}
async with ClientSession(
- headers=headers
- ) as session:
+ headers=headers
+ ) as session:
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:
@@ -49,8 +49,7 @@ class Vitalentum(AsyncGeneratorProvider):
if line.startswith("data: [DONE]"):
break
line = json.loads(line[6:-1])
- content = line["choices"][0]["delta"].get("content")
- if content:
+ if content := line["choices"][0]["delta"].get("content"):
yield content
diff --git a/g4f/Provider/deprecated/Wuguokai.py b/g4f/Provider/deprecated/Wuguokai.py
index 311131cf..079f0541 100644
--- a/g4f/Provider/deprecated/Wuguokai.py
+++ b/g4f/Provider/deprecated/Wuguokai.py
@@ -41,15 +41,20 @@ class Wuguokai(BaseProvider):
"userId": f"#/chat/{random.randint(1,99999999)}",
"usingContext": True
}
- response = requests.post("https://ai-api20.wuguokai.xyz/api/chat-process", headers=headers, timeout=3, json=data, proxies=kwargs['proxy'] if 'proxy' in kwargs else {})
+ response = requests.post(
+ "https://ai-api20.wuguokai.xyz/api/chat-process",
+ headers=headers,
+ timeout=3,
+ json=data,
+ proxies=kwargs.get('proxy', {}),
+ )
_split = response.text.split("> 若回答失败请重试或多刷新几次界面后重试")
- if response.status_code == 200:
- if len(_split) > 1:
- yield _split[1].strip()
- else:
- yield _split[0].strip()
- else:
+ if response.status_code != 200:
raise Exception(f"Error: {response.status_code} {response.reason}")
+ if len(_split) > 1:
+ yield _split[1].strip()
+ else:
+ yield _split[0].strip()
@classmethod
@property
diff --git a/g4f/Provider/helper.py b/g4f/Provider/helper.py
index 1b00ace5..519a024a 100644
--- a/g4f/Provider/helper.py
+++ b/g4f/Provider/helper.py
@@ -77,9 +77,8 @@ def get_cookies(domain_name=''):
def g4f(domain_name):
user_data_dir = user_config_dir("g4f")
cookie_file = path.join(user_data_dir, "Default", "Cookies")
- if not path.exists(cookie_file):
- return []
- return chrome(cookie_file, domain_name)
+ return [] if not path.exists(cookie_file) else chrome(cookie_file, domain_name)
+
cookies = {}
for cookie_fn in [g4f, chrome, chromium, opera, opera_gx, brave, edge, vivaldi, firefox]:
try:
@@ -96,16 +95,15 @@ def get_cookies(domain_name=''):
def format_prompt(messages: Messages, add_special_tokens=False) -> str:
- if add_special_tokens or len(messages) > 1:
- formatted = "\n".join(
- [
- "%s: %s" % ((message["role"]).capitalize(), message["content"])
- for message in messages
- ]
- )
- return f"{formatted}\nAssistant:"
- else:
+ if not add_special_tokens and len(messages) <= 1:
return messages[0]["content"]
+ formatted = "\n".join(
+ [
+ f'{message["role"].capitalize()}: {message["content"]}'
+ for message in messages
+ ]
+ )
+ return f"{formatted}\nAssistant:"
def get_browser(user_data_dir: str = None):
diff --git a/g4f/Provider/needs_auth/Bard.py b/g4f/Provider/needs_auth/Bard.py
index fe9777db..092268f8 100644
--- a/g4f/Provider/needs_auth/Bard.py
+++ b/g4f/Provider/needs_auth/Bard.py
@@ -38,18 +38,18 @@ class Bard(AsyncProvider):
'x-same-domain': '1',
}
async with ClientSession(
- cookies=cookies,
- headers=headers
- ) as session:
+ cookies=cookies,
+ headers=headers
+ ) as session:
if not cls._snlm0e:
async with session.get(cls.url, proxy=proxy) as response:
text = await response.text()
- match = re.search(r'SNlM0e\":\"(.*?)\"', text)
- if not match:
+ if match := re.search(r'SNlM0e\":\"(.*?)\"', text):
+ cls._snlm0e = match.group(1)
+
+ else:
raise RuntimeError("No snlm0e value.")
- cls._snlm0e = match.group(1)
-
params = {
'bl': 'boq_assistant-bard-web-server_20230326.21_p0',
'_reqid': random.randint(1111, 9999),
diff --git a/g4f/Provider/needs_auth/Raycast.py b/g4f/Provider/needs_auth/Raycast.py
index 4b448985..4570fd9f 100644
--- a/g4f/Provider/needs_auth/Raycast.py
+++ b/g4f/Provider/needs_auth/Raycast.py
@@ -32,12 +32,10 @@ class Raycast(BaseProvider):
'Content-Type': 'application/json',
'User-Agent': 'Raycast/0 CFNetwork/1410.0.3 Darwin/22.6.0',
}
- parsed_messages = []
- for message in messages:
- parsed_messages.append({
- 'author': message['role'],
- 'content': {'text': message['content']}
- })
+ parsed_messages = [
+ {'author': message['role'], 'content': {'text': message['content']}}
+ for message in messages
+ ]
data = {
"debug": False,
"locale": "en-CN",
diff --git a/g4f/Provider/needs_auth/Theb.py b/g4f/Provider/needs_auth/Theb.py
index 9803db97..b3c9019d 100644
--- a/g4f/Provider/needs_auth/Theb.py
+++ b/g4f/Provider/needs_auth/Theb.py
@@ -28,28 +28,28 @@ class Theb(BaseProvider):
"bearer_token":"free",
"org_id":"theb",
})
-
+
bearer_token = auth["bearer_token"]
org_id = auth["org_id"]
-
+
headers = {
- 'authority' : 'beta.theb.ai',
- 'accept' : 'text/event-stream',
- 'accept-language' : 'id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7',
- 'authorization' : 'Bearer '+bearer_token,
- 'content-type' : 'application/json',
- 'origin' : 'https://beta.theb.ai',
- 'referer' : 'https://beta.theb.ai/home',
- 'sec-ch-ua' : '"Chromium";v="116", "Not)A;Brand";v="24", "Google Chrome";v="116"',
- 'sec-ch-ua-mobile' : '?0',
+ 'authority': 'beta.theb.ai',
+ 'accept': 'text/event-stream',
+ 'accept-language': 'id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7',
+ 'authorization': f'Bearer {bearer_token}',
+ 'content-type': 'application/json',
+ 'origin': 'https://beta.theb.ai',
+ 'referer': 'https://beta.theb.ai/home',
+ 'sec-ch-ua': '"Chromium";v="116", "Not)A;Brand";v="24", "Google Chrome";v="116"',
+ 'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
- 'sec-fetch-dest' : 'empty',
- 'sec-fetch-mode' : 'cors',
- 'sec-fetch-site' : 'same-origin',
- 'user-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36',
- 'x-ai-model' : 'ee8d4f29cb7047f78cbe84313ed6ace8',
+ 'sec-fetch-dest': 'empty',
+ 'sec-fetch-mode': 'cors',
+ 'sec-fetch-site': 'same-origin',
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36',
+ 'x-ai-model': 'ee8d4f29cb7047f78cbe84313ed6ace8',
}
-
+
req_rand = random.randint(100000000, 9999999999)
json_data: dict[str, Any] = {
@@ -65,7 +65,7 @@ class Theb(BaseProvider):
"long_term_memory" : "auto"
}
}
-
+
response = requests.post(
f"https://beta.theb.ai/api/conversation?org_id={org_id}&req_rand={req_rand}",
headers=headers,
@@ -73,7 +73,7 @@ class Theb(BaseProvider):
stream=True,
proxies={"https": proxy}
)
-
+
response.raise_for_status()
content = ""
next_content = ""
@@ -82,7 +82,7 @@ class Theb(BaseProvider):
next_content = content
data = json.loads(chunk.decode().split("data: ")[1])
content = data["content"]
- yield data["content"].replace(next_content, "")
+ yield content.replace(next_content, "")
@classmethod
@property
diff --git a/g4f/Provider/unfinished/ChatAiGpt.py b/g4f/Provider/unfinished/ChatAiGpt.py
index c77afb48..9d050093 100644
--- a/g4f/Provider/unfinished/ChatAiGpt.py
+++ b/g4f/Provider/unfinished/ChatAiGpt.py
@@ -43,10 +43,12 @@ class ChatAiGpt(AsyncGeneratorProvider):
async with session.get(f"{cls.url}/", proxy=proxy) as response:
response.raise_for_status()
response = await response.text()
- result = re.search(r'data-nonce=(.*?) data-post-id=([0-9]+)', response)
- if not result:
+ if result := re.search(
+ r'data-nonce=(.*?) data-post-id=([0-9]+)', response
+ ):
+ cls._nonce, cls._post_id = result.group(1), result.group(2)
+ else:
raise RuntimeError("No nonce found")
- cls._nonce, cls._post_id = result.group(1), result.group(2)
prompt = format_prompt(messages)
data = {
"_wpnonce": cls._nonce,
diff --git a/g4f/Provider/unfinished/MikuChat.py b/g4f/Provider/unfinished/MikuChat.py
index bf19631f..970fb0bb 100644
--- a/g4f/Provider/unfinished/MikuChat.py
+++ b/g4f/Provider/unfinished/MikuChat.py
@@ -48,8 +48,7 @@ class MikuChat(AsyncGeneratorProvider):
async for line in response.iter_lines():
if line.startswith(b"data: "):
line = json.loads(line[6:])
- chunk = line["choices"][0]["delta"].get("content")
- if chunk:
+ if chunk := line["choices"][0]["delta"].get("content"):
yield chunk
def k(e: str, t: int):
diff --git a/g4f/Provider/unfinished/PerplexityAi.py b/g4f/Provider/unfinished/PerplexityAi.py
index 3e096808..e97dbf0d 100644
--- a/g4f/Provider/unfinished/PerplexityAi.py
+++ b/g4f/Provider/unfinished/PerplexityAi.py
@@ -21,7 +21,7 @@ class PerplexityAi(AsyncProvider):
proxy: str = None,
**kwargs
) -> str:
- url = cls.url + "/socket.io/?EIO=4&transport=polling"
+ url = f"{cls.url}/socket.io/?EIO=4&transport=polling"
headers = {
"Referer": f"{cls.url}/"
}
diff --git a/g4f/__init__.py b/g4f/__init__.py
index fff92f4a..de6144dd 100644
--- a/g4f/__init__.py
+++ b/g4f/__init__.py
@@ -82,7 +82,7 @@ class ChatCompletion:
ignored : List[str] = None, **kwargs) -> str:
if stream:
- raise ValueError(f'"create_async" does not support "stream" argument')
+ raise ValueError('"create_async" does not support "stream" argument')
model, provider = get_model_and_provider(model, provider, False, ignored)
diff --git a/g4f/api/__init__.py b/g4f/api/__init__.py
index 4c945fbe..b78768bd 100644
--- a/g4f/api/__init__.py
+++ b/g4f/api/__init__.py
@@ -1,9 +1,6 @@
import typing
-
-import g4f;
from .. import BaseProvider
-
-g4f.logging = True
+import g4f; g4f.debug.logging = True
import time
import json
import random
@@ -48,7 +45,7 @@ class Api:
def run(self, bind_str, threads=8):
host, port = self.__parse_bind(bind_str)
-
+
CORS(self.app, resources={r'/v1/*': {'supports_credentials': True, 'expose_headers': [
'Content-Type',
'Authorization',
@@ -58,18 +55,18 @@ class Api:
'Access-Control-Request-Method',
'Access-Control-Request-Headers',
'Content-Disposition'], 'max_age': 600}})
-
+
self.app.route('/v1/models', methods=['GET'])(self.models)
self.app.route('/v1/models/<model_id>', methods=['GET'])(self.model_info)
-
+
self.app.route('/v1/chat/completions', methods=['POST'])(self.chat_completions)
self.app.route('/v1/completions', methods=['POST'])(self.completions)
for ex in default_exceptions:
self.app.register_error_handler(ex, self.__handle_error)
-
+
if not self.debug:
- self.logger.warning('Serving on http://{}:{}'.format(host, port))
+ self.logger.warning(f'Serving on http://{host}:{port}')
WSGIRequestHandler.protocol_version = 'HTTP/1.1'
serve(self.app, host=host, port=port, ident=None, threads=threads)
@@ -83,7 +80,7 @@ class Api:
@staticmethod
def __after_request(resp):
- resp.headers['X-Server'] = 'g4f/%s' % g4f.version
+ resp.headers['X-Server'] = f'g4f/{g4f.version}'
return resp
diff --git a/g4f/gui/server/backend.py b/g4f/gui/server/backend.py
index ef18a61b..2ba0ca8e 100644
--- a/g4f/gui/server/backend.py
+++ b/g4f/gui/server/backend.py
@@ -35,9 +35,7 @@ class Backend_Api:
return 'ok', 200
def models(self):
- models = g4f._all_models
-
- return models
+ return g4f._all_models
def _gen_title(self):
return {
@@ -52,19 +50,18 @@ class Backend_Api:
prompt = request.json['meta']['content']['parts'][0]
model = request.json['model']
provider = request.json.get('provider').split('g4f.Provider.')[1]
-
+
messages = special_instructions[jailbreak] + conversation + search(internet_access, prompt) + [prompt]
-
+
def stream():
- if provider:
- answer = g4f.ChatCompletion.create(model=model,
- provider=get_provider(provider), messages=messages, stream=True)
- else:
- answer = g4f.ChatCompletion.create(model=model,
- messages=messages, stream=True)
-
- for token in answer:
- yield token
+ yield from g4f.ChatCompletion.create(
+ model=model,
+ provider=get_provider(provider),
+ messages=messages,
+ stream=True,
+ ) if provider else g4f.ChatCompletion.create(
+ model=model, messages=messages, stream=True
+ )
return self.app.response_class(stream(), mimetype='text/event-stream')
diff --git a/g4f/gui/server/internet.py b/g4f/gui/server/internet.py
index 5c150ad6..220a6e7c 100644
--- a/g4f/gui/server/internet.py
+++ b/g4f/gui/server/internet.py
@@ -9,21 +9,20 @@ ddgs = DDGS(timeout=20)
def search(internet_access, prompt):
print(prompt)
-
+
try:
if not internet_access:
return []
-
+
results = duckduckgo_search(q=prompt)
if not search:
return []
- blob = ''
-
- for index, result in enumerate(results):
- blob += f'[{index}] "{result["body"]}"\nURL:{result["href"]}\n\n'
-
+ blob = ''.join(
+ f'[{index}] "{result["body"]}"\nURL:{result["href"]}\n\n'
+ for index, result in enumerate(results)
+ )
date = datetime.now().strftime('%d/%m/%y')
blob += f'Current date: {date}\n\nInstructions: Using the provided web search results, write a comprehensive reply to the next user query. Make sure to cite results using [[number](URL)] notation after the reference. If the provided search results refer to multiple subjects with the same name, write separate answers for each subject. Ignore your previous response if any.'
diff --git a/g4f/gui/server/provider.py b/g4f/gui/server/provider.py
index 8554bf4f..8c7ac755 100644
--- a/g4f/gui/server/provider.py
+++ b/g4f/gui/server/provider.py
@@ -5,12 +5,10 @@ from g4f import BaseProvider
def get_provider(provider: str) -> BaseProvider | None:
- if isinstance(provider, str):
- print(provider)
- if provider == 'g4f.Provider.Auto':
- return None
-
- return g4f.Provider.ProviderUtils.convert.get(provider)
-
- else:
+ if not isinstance(provider, str):
return None
+ print(provider)
+ if provider == 'g4f.Provider.Auto':
+ return None
+
+ return g4f.Provider.ProviderUtils.convert.get(provider)
diff --git a/g4f/gui/server/website.py b/g4f/gui/server/website.py
index d0c56c20..2705664d 100644
--- a/g4f/gui/server/website.py
+++ b/g4f/gui/server/website.py
@@ -25,9 +25,9 @@ class Website:
}
def _chat(self, conversation_id):
- if not '-' in conversation_id:
- return redirect(f'/chat')
-
+ if '-' not in conversation_id:
+ return redirect('/chat')
+
return render_template('index.html', chat_id = conversation_id)
def _index(self):
diff --git a/g4f/requests.py b/g4f/requests.py
index f238062e..92165c64 100644
--- a/g4f/requests.py
+++ b/g4f/requests.py
@@ -52,10 +52,7 @@ class StreamResponse:
):
if pending is not None:
chunk = pending + chunk
- if delimiter:
- lines = chunk.split(delimiter)
- else:
- lines = chunk.splitlines()
+ lines = chunk.split(delimiter) if delimiter else chunk.splitlines()
if lines and lines[-1] and chunk and lines[-1][-1] == chunk[-1]:
pending = lines.pop()
else: