~ | Merge pull request #1000 from hlohaus/all

Add GPTalk and GptForLove Provider
This commit is contained in:
Tekky 2023-10-07 21:03:50 +01:00 committed by GitHub
commit 6334dac211
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 6885 additions and 173 deletions

View File

@ -215,7 +215,6 @@ from g4f.Provider import (
Acytoo,
Aichat,
Ails,
Aivvm,
Bard,
Bing,
ChatBase,
@ -278,7 +277,6 @@ import g4f, asyncio
_providers = [
g4f.Provider.Aichat,
g4f.Provider.Aivvm,
g4f.Provider.ChatBase,
g4f.Provider.Bing,
g4f.Provider.CodeLinkAva,
@ -371,7 +369,6 @@ if __name__ == "__main__":
| [chat.acytoo.com](https://chat.acytoo.com) | `g4f.Provider.Acytoo` | ✔️ | ❌ | ✔️ | ✔️ | ![Active](https://img.shields.io/badge/Active-brightgreen) | ❌ |
| [chat-gpt.org](https://chat-gpt.org/chat) | `g4f.Provider.Aichat` | ✔️ | ❌ | ❌ | ✔️ | ![Unknown](https://img.shields.io/badge/Unknown-grey) | ❌ |
| [ai.ls](https://ai.ls) | `g4f.Provider.Ails` | ✔️ | ❌ | ✔️ | ✔️ | ![Active](https://img.shields.io/badge/Active-brightgreen) | ❌ |
| [chat.aivvm.com](https://chat.aivvm.com) | `g4f.Provider.Aivvm` | ✔️ | ✔️ | ✔️ | ❌ | ![Active](https://img.shields.io/badge/Active-brightgreen) | ❌ |
| [bard.google.com](https://bard.google.com) | `g4f.Provider.Bard` | ❌ | ❌ | ❌ | ✔️ | ![Active](https://img.shields.io/badge/Active-brightgreen) | ✔️ |
| [bing.com](https://bing.com/chat) | `g4f.Provider.Bing` | ❌ | ✔️ | ✔️ | ✔️ | ![Active](https://img.shields.io/badge/Active-brightgreen) | ❌ |
| [www.chatbase.co](https://www.chatbase.co) | `g4f.Provider.ChatBase` | ✔️ | ✔️ | ✔️ | ✔️ | ![Active](https://img.shields.io/badge/Active-brightgreen) | ❌ |

View File

@ -3,6 +3,7 @@ from pathlib import Path
import asyncio
sys.path.append(str(Path(__file__).parent.parent))
sys.path.append(str(Path(__file__).parent.parent.parent))
import g4f
from testing.test_providers import get_providers

View File

@ -1,14 +1,14 @@
import sys
from pathlib import Path
sys.path.append(str(Path(__file__).parent.parent))
sys.path.append(str(Path(__file__).parent.parent.parent))
import g4f, asyncio
print("create:", end=" ", flush=True)
for response in g4f.ChatCompletion.create(
model=g4f.models.gpt_4_32k_0613,
provider=g4f.Provider.Aivvm,
model=g4f.models.default,
provider=g4f.Provider.GptForLove,
messages=[{"role": "user", "content": "send a bunch of emojis. i want to test something"}],
temperature=0.0,
stream=True
@ -19,7 +19,7 @@ print()
async def run_async():
response = await g4f.ChatCompletion.create_async(
model=g4f.models.gpt_35_turbo_16k_0613,
provider=g4f.Provider.Aivvm,
provider=g4f.Provider.GptGod,
messages=[{"role": "user", "content": "hello!"}],
)
print("create_async:", response)

View File

@ -3,7 +3,7 @@ import sys, re
from pathlib import Path
from os import path
sys.path.append(str(Path(__file__).parent.parent))
sys.path.append(str(Path(__file__).parent.parent.parent))
import g4f

47
etc/tool/improve_code.py Normal file
View File

@ -0,0 +1,47 @@
import sys, re
from pathlib import Path
from os import path
sys.path.append(str(Path(__file__).parent.parent.parent))
import g4f
def read_code(text):
match = re.search(r"```(python|py|)\n(?P<code>[\S\s]+?)\n```", text)
if match:
return match.group("code")
path = input("Path: ")
with open(path, "r") as file:
code = file.read()
prompt = f"""
Improve the code in this file:
```py
{code}
```
Don't remove anything.
Add typehints if possible.
Don't add any typehints to kwargs.
Don't remove license comments.
"""
print("Create code...")
response = []
for chunk in g4f.ChatCompletion.create(
model=g4f.models.gpt_35_long,
messages=[{"role": "user", "content": prompt}],
timeout=300,
stream=True
):
response.append(chunk)
print(chunk, end="", flush=True)
print()
response = "".join(response)
code = read_code(response)
if code:
with open(path, "w") as file:
file.write(code)

View File

@ -1,6 +1,6 @@
from __future__ import annotations
from aiohttp import ClientSession, ClientTimeout
from aiohttp import ClientSession
from ..typing import AsyncGenerator
from .base_provider import AsyncGeneratorProvider
@ -14,7 +14,6 @@ class AiAsk(AsyncGeneratorProvider):
cls,
model: str,
messages: list[dict[str, str]],
timeout: int = 30,
**kwargs
) -> AsyncGenerator:
headers = {
@ -22,7 +21,7 @@ class AiAsk(AsyncGeneratorProvider):
"origin": cls.url,
"referer": f"{cls.url}/chat",
}
async with ClientSession(headers=headers, timeout=ClientTimeout(timeout)) as session:
async with ClientSession(headers=headers) as session:
data = {
"continuous": True,
"id": "fRMSQtuHl91A4De9cCvKD",

View File

@ -1,6 +1,6 @@
from __future__ import annotations
from aiohttp import ClientSession, ClientTimeout
from aiohttp import ClientSession
from .base_provider import AsyncProvider, format_prompt
@ -15,7 +15,6 @@ class Aichat(AsyncProvider):
model: str,
messages: list[dict[str, str]],
proxy: str = None,
timeout: int = 30,
**kwargs
) -> str:
headers = {
@ -34,7 +33,7 @@ class Aichat(AsyncProvider):
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36",
}
async with ClientSession(
headers=headers, timeout=ClientTimeout(timeout)
headers=headers
) as session:
json_data = {
"message": format_prompt(messages),

View File

@ -1,7 +1,7 @@
from __future__ import annotations
import re
from aiohttp import ClientSession, ClientTimeout
from aiohttp import ClientSession
from .base_provider import AsyncProvider, format_prompt
@ -20,7 +20,6 @@ class ChatgptAi(AsyncProvider):
model: str,
messages: list[dict[str, str]],
proxy: str = None,
timeout: int = 30,
**kwargs
) -> str:
headers = {
@ -40,7 +39,7 @@ class ChatgptAi(AsyncProvider):
"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, timeout=ClientTimeout(timeout)
headers=headers
) as session:
if not cls._nonce:
async with session.get(cls.url, proxy=proxy) as response:

View File

@ -1,7 +1,7 @@
from __future__ import annotations
import time, json, re
from aiohttp import ClientSession, ClientTimeout
from aiohttp import ClientSession
from typing import AsyncGenerator
from .base_provider import AsyncGeneratorProvider
@ -18,7 +18,6 @@ class ChatgptDemo(AsyncGeneratorProvider):
model: str,
messages: list[dict[str, str]],
proxy: str = None,
timeout: int = 30,
**kwargs
) -> AsyncGenerator:
headers = {
@ -34,7 +33,7 @@ class ChatgptDemo(AsyncGeneratorProvider):
"sec-fetch-site": "same-origin",
"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, timeout=ClientTimeout(timeout)) as session:
async with ClientSession(headers=headers) as session:
async with session.get(f"{cls.url}/", proxy=proxy) as response:
response.raise_for_status()
response = await response.text()

83
g4f/Provider/GPTalk.py Normal file
View File

@ -0,0 +1,83 @@
from __future__ import annotations
import secrets, time, json
from aiohttp import ClientSession
from typing import AsyncGenerator
from .base_provider import AsyncGeneratorProvider
from .helper import format_prompt
class GPTalk(AsyncGeneratorProvider):
url = "https://gptalk.net"
supports_gpt_35_turbo = True
working = True
_auth = None
@classmethod
async def create_async_generator(
cls,
model: str,
messages: list[dict[str, str]],
**kwargs
) -> AsyncGenerator:
if not model:
model = "gpt-3.5-turbo"
timestamp = int(time.time())
headers = {
'authority': 'gptalk.net',
'accept': '*/*',
'accept-language': 'de-DE,de;q=0.9,en-DE;q=0.8,en;q=0.7,en-US;q=0.6,nl;q=0.5,zh-CN;q=0.4,zh-TW;q=0.3,zh;q=0.2',
'content-type': 'application/json',
'origin': 'https://gptalk.net',
'sec-ch-ua': '"Google Chrome";v="117", "Not;A=Brand";v="8", "Chromium";v="117"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Linux"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-origin',
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
'x-auth-appid': '2229',
'x-auth-openid': '',
'x-auth-platform': '',
'x-auth-timestamp': f"{timestamp}",
}
async with ClientSession(headers=headers) as session:
if not cls._auth or cls._auth["expires_at"] < timestamp:
data = {
"fingerprint": secrets.token_hex(16).zfill(32),
"platform": "fingerprint"
}
async with session.post(cls.url + "/api/chatgpt/user/login", json=data) as response:
response.raise_for_status()
cls._auth = (await response.json())["data"]
data = {
"content": format_prompt(messages),
"accept": "stream",
"from": 1,
"model": model,
"is_mobile": 0,
"user_agent": headers["user-agent"],
"is_open_ctx": 0,
"prompt": "",
"roid": 111,
"temperature": 0,
"ctx_msg_count": 3,
"created_at": timestamp
}
headers = {
'authorization': f'Bearer {cls._auth["token"]}',
}
async with session.post(cls.url + "/api/chatgpt/chatapi/text", json=data, headers=headers) 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:
response.raise_for_status()
async for line in response.content:
if line.startswith(b"data: "):
if line.startswith(b"data: [DONE]"):
break
message = json.loads(line[6:-1])["content"]
yield message[len(last_message):]
last_message = message

View File

@ -0,0 +1,79 @@
from __future__ import annotations
from aiohttp import ClientSession
import execjs, os, json
from ..typing import AsyncGenerator
from .base_provider import AsyncGeneratorProvider
from .helper import format_prompt
class GptForLove(AsyncGeneratorProvider):
url = "https://ai18.gptforlove.com"
supports_gpt_35_turbo = True
working = True
@classmethod
async def create_async_generator(
cls,
model: str,
messages: list[dict[str, str]],
**kwargs
) -> AsyncGenerator:
if not model:
model = "gpt-3.5-turbo"
headers = {
"authority": "api.gptplus.one",
"accept": "application/json, text/plain, */*",
"accept-language": "de-DE,de;q=0.9,en-DE;q=0.8,en;q=0.7,en-US;q=0.6,nl;q=0.5,zh-CN;q=0.4,zh-TW;q=0.3,zh;q=0.2",
"content-type": "application/json",
"origin": cls.url,
"referer": f"{cls.url}/",
"sec-ch-ua": "\"Google Chrome\";v=\"117\", \"Not;A=Brand\";v=\"8\", \"Chromium\";v=\"117\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "Linux",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "cross-site",
"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:
prompt = format_prompt(messages)
data = {
"prompt": prompt,
"options": {},
"systemMessage": "You are ChatGPT, the version is GPT3.5, a large language model trained by OpenAI. Follow the user's instructions carefully. Respond using markdown.",
"temperature": 0.8,
"top_p": 1,
"secret": get_secret(),
**kwargs
}
async with session.post("https://api.gptplus.one/chat-process", json=data) as response:
response.raise_for_status()
async for line in response.content:
line = json.loads(line)
if "detail" in line:
content = line["detail"]["choices"][0]["delta"].get("content")
if content:
yield content
elif "10分钟内提问超过了5次" in line:
raise RuntimeError("Rate limit reached")
else:
raise RuntimeError(f"Response: {line}")
def get_secret() -> str:
dir = os.path.dirname(__file__)
dir += '/npm/node_modules/crypto-js'
source = """
CryptoJS = require('{dir}/crypto-js')
var k = '14487141bvirvvG'
, e = Math.floor(new Date().getTime() / 1e3);
var t = CryptoJS.enc.Utf8.parse(e)
, o = CryptoJS.AES.encrypt(t, k, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
return o.toString()
"""
source = source.replace('{dir}', dir)
return execjs.compile(source).call('')

View File

@ -1,6 +1,6 @@
from __future__ import annotations
from aiohttp import ClientSession, ClientTimeout
from aiohttp import ClientSession
import json
from ..typing import AsyncGenerator
@ -32,7 +32,7 @@ class GptGo(AsyncGeneratorProvider):
"Sec-Fetch-Site" : "same-origin",
}
async with ClientSession(
headers=headers, timeout=ClientTimeout(timeout)
headers=headers
) as session:
async with session.get(
"https://gptgo.ai/action_get_token.php",

51
g4f/Provider/GptGod.py Normal file
View File

@ -0,0 +1,51 @@
from __future__ import annotations
import secrets, json
from aiohttp import ClientSession
from typing import AsyncGenerator
from .base_provider import AsyncGeneratorProvider
from .helper import format_prompt
class GptGod(AsyncGeneratorProvider):
url = "https://gptgod.site"
supports_gpt_35_turbo = True
working = True
@classmethod
async def create_async_generator(
cls,
model: str,
messages: list[dict[str, str]],
**kwargs
) -> AsyncGenerator:
headers = {
"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/118.0",
"Accept": "text/event-stream",
"Accept-Language": "de,en-US;q=0.7,en;q=0.3",
"Accept-Encoding": "gzip, deflate, br",
"Alt-Used": "gptgod.site",
"Connection": "keep-alive",
"Referer": "https://gptgod.site/",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"Pragma": "no-cache",
"Cache-Control": "no-cache",
}
async with ClientSession(headers=headers) as session:
prompt = format_prompt(messages)
data = {
"content": prompt,
"id": secrets.token_hex(16).zfill(32)
}
async with session.get(f"{cls.url}/api/session/free/gpt3p5", params=data) as response:
response.raise_for_status()
event = None
async for line in response.content:
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:
yield data
elif event == b"done":
break

View File

@ -2,7 +2,7 @@ from __future__ import annotations
import uuid
from aiohttp import ClientSession, ClientTimeout
from aiohttp import ClientSession
from ..typing import AsyncGenerator
from .base_provider import AsyncGeneratorProvider
@ -42,7 +42,6 @@ class Liaobots(AsyncGeneratorProvider):
messages: list[dict[str, str]],
auth: str = None,
proxy: str = None,
timeout: int = 30,
**kwargs
) -> AsyncGenerator:
model = model if model in models else "gpt-3.5-turbo"
@ -54,7 +53,7 @@ class Liaobots(AsyncGeneratorProvider):
"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(
headers=headers, timeout=ClientTimeout(timeout)
headers=headers
) as session:
cls._auth_code = auth if isinstance(auth, str) else cls._auth_code
if not cls._auth_code:

View File

@ -1,7 +1,7 @@
from __future__ import annotations
import json
from aiohttp import ClientSession, ClientTimeout
from aiohttp import ClientSession
from .base_provider import AsyncGeneratorProvider
from ..typing import AsyncGenerator
@ -18,7 +18,6 @@ class Vitalentum(AsyncGeneratorProvider):
model: str,
messages: list[dict[str, str]],
proxy: str = None,
timeout: int = 30,
**kwargs
) -> AsyncGenerator:
headers = {
@ -41,7 +40,7 @@ class Vitalentum(AsyncGeneratorProvider):
**kwargs
}
async with ClientSession(
headers=headers, timeout=ClientTimeout(timeout)
headers=headers
) as session:
async with session.post(cls.url + "/api/converse-edge", json=data, proxy=proxy) as response:
response.raise_for_status()

View File

@ -16,11 +16,10 @@ class Yqcloud(AsyncGeneratorProvider):
model: str,
messages: list[dict[str, str]],
proxy: str = None,
timeout: int = 30,
**kwargs,
) -> AsyncGenerator:
async with ClientSession(
headers=_create_header(), timeout=timeout
headers=_create_header()
) as session:
payload = _create_payload(messages)
async with session.post("https://api.aichatos.cloud/api/generateStream", proxy=proxy, json=payload) as response:

View File

@ -6,7 +6,6 @@ from .Aichat import Aichat
from .Ails import Ails
from .AItianhu import AItianhu
from .AItianhuSpace import AItianhuSpace
from .Aivvm import Aivvm
from .Bing import Bing
from .ChatBase import ChatBase
from .ChatForAi import ChatForAi
@ -14,11 +13,13 @@ from .Chatgpt4Online import Chatgpt4Online
from .ChatgptAi import ChatgptAi
from .ChatgptDemo import ChatgptDemo
from .ChatgptDuo import ChatgptDuo
from .ChatgptLogin import ChatgptLogin
from .ChatgptX import ChatgptX
from .DeepAi import DeepAi
from .FreeGpt import FreeGpt
from .GPTalk import GPTalk
from .GptForLove import GptForLove
from .GptGo import GptGo
from .GptGod import GptGod
from .H2o import H2o
from .Liaobots import Liaobots
from .Myshell import Myshell
@ -65,8 +66,11 @@ __all__ = [
'EasyChat',
'Forefront',
'FreeGpt',
'GPTalk',
'GptForLove',
'GetGpt',
'GptGo',
'GptGod',
'H2o',
'HuggingChat',
'Liaobots',

View File

@ -10,11 +10,11 @@ from ..typing import AsyncGenerator, CreateResult
class BaseProvider(ABC):
url: str
working = False
needs_auth = False
supports_stream = False
supports_gpt_35_turbo = False
supports_gpt_4 = False
working: bool = False
needs_auth: bool = False
supports_stream: bool = False
supports_gpt_35_turbo: bool = False
supports_gpt_4: bool = False
@staticmethod
@abstractmethod
@ -38,13 +38,15 @@ class BaseProvider(ABC):
) -> str:
if not loop:
loop = get_event_loop()
def create_func():
def create_func() -> str:
return "".join(cls.create_completion(
model,
messages,
False,
**kwargs
))
return await loop.run_in_executor(
executor,
create_func
@ -52,7 +54,7 @@ class BaseProvider(ABC):
@classmethod
@property
def params(cls):
def params(cls) -> str:
params = [
("model", "str"),
("messages", "list[dict[str, str]]"),
@ -103,7 +105,7 @@ class AsyncGeneratorProvider(AsyncProvider):
stream=stream,
**kwargs
)
gen = generator.__aiter__()
gen = generator.__aiter__()
while True:
try:
yield loop.run_until_complete(gen.__anext__())

View File

@ -1,8 +1,8 @@
from __future__ import annotations
from ..requests import StreamSession
from .base_provider import AsyncGeneratorProvider
from ..typing import AsyncGenerator
from ...requests import StreamSession
from ..base_provider import AsyncGeneratorProvider
from ...typing import AsyncGenerator
# to recreate this easily, send a post request to https://chat.aivvm.com/api/models
models = {
@ -18,8 +18,6 @@ models = {
class Aivvm(AsyncGeneratorProvider):
url = 'https://chat.aivvm.com'
supports_stream = True
working = True
supports_gpt_35_turbo = True
supports_gpt_4 = True

View File

@ -3,7 +3,7 @@ from __future__ import annotations
import os, re
from aiohttp import ClientSession
from .base_provider import AsyncProvider, format_prompt
from ..base_provider import AsyncProvider, format_prompt
class ChatgptLogin(AsyncProvider):

View File

@ -1,8 +1,7 @@
from __future__ import annotations
from ..ChatgptLogin import ChatgptLogin
from .ChatgptLogin import ChatgptLogin
class Opchatgpts(ChatgptLogin):
url = "https://opchatgpts.net"
working = True

View File

@ -11,3 +11,5 @@ from .Equing import Equing
from .Wuguokai import Wuguokai
from .V50 import V50
from .FastGpt import FastGpt
from .ChatgptLogin import ChatgptLogin
from .Aivvm import Aivvm

View File

@ -1,8 +1,10 @@
from __future__ import annotations
import asyncio, sys
import asyncio
import sys
from asyncio import AbstractEventLoop
from os import path
from typing import Dict, List
import browser_cookie3
# Change event loop policy on windows
@ -13,7 +15,7 @@ if sys.platform == 'win32':
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
# Local Cookie Storage
_cookies: dict[str, dict[str, str]] = {}
_cookies: Dict[str, Dict[str, str]] = {}
# If event loop is already running, handle nested event loops
# If "nest_asyncio" is installed, patch the event loop.
@ -34,11 +36,13 @@ def get_event_loop() -> AbstractEventLoop:
return event_loop
except ImportError:
raise RuntimeError(
'Use "create_async" instead of "create" function in a running event loop. Or install the "nest_asyncio" package.')
'Use "create_async" instead of "create" function in a running event loop. Or install the "nest_asyncio" package.'
)
# Load cookies for a domain from all supported browser.
# Cache the results in the "_cookies" variable
def get_cookies(cookie_domain: str) -> dict:
# Load cookies for a domain from all supported browsers.
# Cache the results in the "_cookies" variable.
def get_cookies(cookie_domain: str) -> Dict[str, str]:
if cookie_domain not in _cookies:
_cookies[cookie_domain] = {}
try:
@ -49,10 +53,13 @@ def get_cookies(cookie_domain: str) -> dict:
return _cookies[cookie_domain]
def format_prompt(messages: list[dict[str, str]], add_special_tokens=False):
def format_prompt(messages: List[Dict[str, str]], 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]
[
"%s: %s" % ((message["role"]).capitalize(), message["content"])
for message in messages
]
)
return f"{formatted}\nAssistant:"
else:

261
g4f/Provider/npm/node_modules/crypto-js/README.md generated vendored Normal file
View File

@ -0,0 +1,261 @@
# crypto-js [![Build Status](https://travis-ci.org/brix/crypto-js.svg?branch=develop)](https://travis-ci.org/brix/crypto-js)
JavaScript library of crypto standards.
## Node.js (Install)
Requirements:
- Node.js
- npm (Node.js package manager)
```bash
npm install crypto-js
```
### Usage
ES6 import for typical API call signing use case:
```javascript
import sha256 from 'crypto-js/sha256';
import hmacSHA512 from 'crypto-js/hmac-sha512';
import Base64 from 'crypto-js/enc-base64';
const message, nonce, path, privateKey; // ...
const hashDigest = sha256(nonce + message);
const hmacDigest = Base64.stringify(hmacSHA512(path + hashDigest, privateKey));
```
Modular include:
```javascript
var AES = require("crypto-js/aes");
var SHA256 = require("crypto-js/sha256");
...
console.log(SHA256("Message"));
```
Including all libraries, for access to extra methods:
```javascript
var CryptoJS = require("crypto-js");
console.log(CryptoJS.HmacSHA1("Message", "Key"));
```
## Client (browser)
Requirements:
- Node.js
- Bower (package manager for frontend)
```bash
bower install crypto-js
```
### Usage
Modular include:
```javascript
require.config({
packages: [
{
name: 'crypto-js',
location: 'path-to/bower_components/crypto-js',
main: 'index'
}
]
});
require(["crypto-js/aes", "crypto-js/sha256"], function (AES, SHA256) {
console.log(SHA256("Message"));
});
```
Including all libraries, for access to extra methods:
```javascript
// Above-mentioned will work or use this simple form
require.config({
paths: {
'crypto-js': 'path-to/bower_components/crypto-js/crypto-js'
}
});
require(["crypto-js"], function (CryptoJS) {
console.log(CryptoJS.HmacSHA1("Message", "Key"));
});
```
### Usage without RequireJS
```html
<script type="text/javascript" src="path-to/bower_components/crypto-js/crypto-js.js"></script>
<script type="text/javascript">
var encrypted = CryptoJS.AES(...);
var encrypted = CryptoJS.SHA256(...);
</script>
```
## API
See: https://cryptojs.gitbook.io/docs/
### AES Encryption
#### Plain text encryption
```javascript
var CryptoJS = require("crypto-js");
// Encrypt
var ciphertext = CryptoJS.AES.encrypt('my message', 'secret key 123').toString();
// Decrypt
var bytes = CryptoJS.AES.decrypt(ciphertext, 'secret key 123');
var originalText = bytes.toString(CryptoJS.enc.Utf8);
console.log(originalText); // 'my message'
```
#### Object encryption
```javascript
var CryptoJS = require("crypto-js");
var data = [{id: 1}, {id: 2}]
// Encrypt
var ciphertext = CryptoJS.AES.encrypt(JSON.stringify(data), 'secret key 123').toString();
// Decrypt
var bytes = CryptoJS.AES.decrypt(ciphertext, 'secret key 123');
var decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
console.log(decryptedData); // [{id: 1}, {id: 2}]
```
### List of modules
- ```crypto-js/core```
- ```crypto-js/x64-core```
- ```crypto-js/lib-typedarrays```
---
- ```crypto-js/md5```
- ```crypto-js/sha1```
- ```crypto-js/sha256```
- ```crypto-js/sha224```
- ```crypto-js/sha512```
- ```crypto-js/sha384```
- ```crypto-js/sha3```
- ```crypto-js/ripemd160```
---
- ```crypto-js/hmac-md5```
- ```crypto-js/hmac-sha1```
- ```crypto-js/hmac-sha256```
- ```crypto-js/hmac-sha224```
- ```crypto-js/hmac-sha512```
- ```crypto-js/hmac-sha384```
- ```crypto-js/hmac-sha3```
- ```crypto-js/hmac-ripemd160```
---
- ```crypto-js/pbkdf2```
---
- ```crypto-js/aes```
- ```crypto-js/tripledes```
- ```crypto-js/rc4```
- ```crypto-js/rabbit```
- ```crypto-js/rabbit-legacy```
- ```crypto-js/evpkdf```
---
- ```crypto-js/format-openssl```
- ```crypto-js/format-hex```
---
- ```crypto-js/enc-latin1```
- ```crypto-js/enc-utf8```
- ```crypto-js/enc-hex```
- ```crypto-js/enc-utf16```
- ```crypto-js/enc-base64```
---
- ```crypto-js/mode-cfb```
- ```crypto-js/mode-ctr```
- ```crypto-js/mode-ctr-gladman```
- ```crypto-js/mode-ofb```
- ```crypto-js/mode-ecb```
---
- ```crypto-js/pad-pkcs7```
- ```crypto-js/pad-ansix923```
- ```crypto-js/pad-iso10126```
- ```crypto-js/pad-iso97971```
- ```crypto-js/pad-zeropadding```
- ```crypto-js/pad-nopadding```
## Release notes
### 4.1.1
Fix module order in bundled release.
Include the browser field in the released package.json.
### 4.1.0
Added url safe variant of base64 encoding. [357](https://github.com/brix/crypto-js/pull/357)
Avoid webpack to add crypto-browser package. [364](https://github.com/brix/crypto-js/pull/364)
### 4.0.0
This is an update including breaking changes for some environments.
In this version `Math.random()` has been replaced by the random methods of the native crypto module.
For this reason CryptoJS might not run in some JavaScript environments without native crypto module. Such as IE 10 or before or React Native.
### 3.3.0
Rollback, `3.3.0` is the same as `3.1.9-1`.
The move of using native secure crypto module will be shifted to a new `4.x.x` version. As it is a breaking change the impact is too big for a minor release.
### 3.2.1
The usage of the native crypto module has been fixed. The import and access of the native crypto module has been improved.
### 3.2.0
In this version `Math.random()` has been replaced by the random methods of the native crypto module.
For this reason CryptoJS might does not run in some JavaScript environments without native crypto module. Such as IE 10 or before.
If it's absolute required to run CryptoJS in such an environment, stay with `3.1.x` version. Encrypting and decrypting stays compatible. But keep in mind `3.1.x` versions still use `Math.random()` which is cryptographically not secure, as it's not random enough.
This version came along with `CRITICAL` `BUG`.
DO NOT USE THIS VERSION! Please, go for a newer version!
### 3.1.x
The `3.1.x` are based on the original CryptoJS, wrapped in CommonJS modules.

6191
g4f/Provider/npm/node_modules/crypto-js/crypto-js.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,33 +1,33 @@
from __future__ import annotations
import random
from typing import List, Type, Dict
from ..typing import CreateResult
from .base_provider import BaseProvider, AsyncProvider
from ..debug import logging
class RetryProvider(AsyncProvider):
__name__ = "RetryProvider"
working = True
needs_auth = False
supports_stream = True
supports_gpt_35_turbo = False
supports_gpt_4 = False
__name__: str = "RetryProvider"
working: bool = True
needs_auth: bool = False
supports_stream: bool = True
supports_gpt_35_turbo: bool = False
supports_gpt_4: bool = False
def __init__(
self,
providers: list[type[BaseProvider]],
providers: List[Type[BaseProvider]],
shuffle: bool = True
) -> None:
self.providers = providers
self.shuffle = shuffle
self.providers: List[Type[BaseProvider]] = providers
self.shuffle: bool = shuffle
def create_completion(
self,
model: str,
messages: list[dict[str, str]],
messages: List[Dict[str, str]],
stream: bool = False,
**kwargs
) -> CreateResult:
@ -38,8 +38,8 @@ class RetryProvider(AsyncProvider):
if self.shuffle:
random.shuffle(providers)
self.exceptions = {}
started = False
self.exceptions: Dict[str, Exception] = {}
started: bool = False
for provider in providers:
try:
if logging:
@ -61,14 +61,14 @@ class RetryProvider(AsyncProvider):
async def create_async(
self,
model: str,
messages: list[dict[str, str]],
messages: List[Dict[str, str]],
**kwargs
) -> str:
providers = [provider for provider in self.providers]
if self.shuffle:
random.shuffle(providers)
self.exceptions = {}
self.exceptions: Dict[str, Exception] = {}
for provider in providers:
try:
return await provider.create_async(model, messages, **kwargs)
@ -79,7 +79,7 @@ class RetryProvider(AsyncProvider):
self.raise_exceptions()
def raise_exceptions(self):
def raise_exceptions(self) -> None:
if self.exceptions:
raise RuntimeError("\n".join(["All providers failed:"] + [
f"{p}: {self.exceptions[p].__class__.__name__}: {self.exceptions[p]}" for p in self.exceptions

View File

@ -1,17 +1,16 @@
from __future__ import annotations
from g4f import models
from .Provider import BaseProvider
from .typing import CreateResult, Union
from .debug import logging
from requests import get
from requests import get
from g4f.models import Model, ModelUtils
from .Provider import BaseProvider
from .typing import CreateResult, Union
from .debug import logging
logging = False
version = '0.1.5.4'
def check_pypi_version():
def check_pypi_version() -> None:
try:
response = get(f"https://pypi.org/pypi/g4f/json").json()
response = get("https://pypi.org/pypi/g4f/json").json()
latest_version = response["info"]["version"]
if version != latest_version:
@ -22,10 +21,10 @@ def check_pypi_version():
check_pypi_version()
def get_model_and_provider(model: Union[models.Model, str], provider: type[BaseProvider], stream: bool):
def get_model_and_provider(model: Union[Model, str], provider: Union[type[BaseProvider], None], stream: bool) -> tuple[Model, type[BaseProvider]]:
if isinstance(model, str):
if model in models.ModelUtils.convert:
model = models.ModelUtils.convert[model]
if model in ModelUtils.convert:
model = ModelUtils.convert[model]
else:
raise Exception(f'The model: {model} does not exist')
@ -39,8 +38,7 @@ def get_model_and_provider(model: Union[models.Model, str], provider: type[BaseP
raise Exception(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 Exception(f'ValueError: {provider.__name__} does not support "stream" argument')
if logging:
print(f'Using {provider.__name__} provider')
@ -50,11 +48,11 @@ def get_model_and_provider(model: Union[models.Model, str], provider: type[BaseP
class ChatCompletion:
@staticmethod
def create(
model : Union[models.Model, str],
messages : list[dict[str, str]],
provider : Union[type[BaseProvider], None] = None,
stream : bool = False,
auth : Union[str, None] = None,
model: Union[Model, str],
messages: list[dict[str, str]],
provider: Union[type[BaseProvider], None] = None,
stream: bool = False,
auth: Union[str, None] = None,
**kwargs
) -> Union[CreateResult, str]:
@ -72,9 +70,9 @@ class ChatCompletion:
@staticmethod
async def create_async(
model : Union[models.Model, str],
messages : list[dict[str, str]],
provider : Union[type[BaseProvider], None] = None,
model: Union[Model, str],
messages: list[dict[str, str]],
provider: Union[type[BaseProvider], None] = None,
**kwargs
) -> str:
model, provider = get_model_and_provider(model, provider, False)
@ -84,10 +82,12 @@ class ChatCompletion:
class Completion:
@staticmethod
def create(
model : Union[models.Model, str],
prompt : str,
provider : Union[type[BaseProvider], None] = None,
stream : bool = False, **kwargs) -> Union[CreateResult, str]:
model: str,
prompt: str,
provider: Union[type[BaseProvider], None] = None,
stream: bool = False,
**kwargs
) -> Union[CreateResult, str]:
allowed_models = [
'code-davinci-002',
@ -103,7 +103,6 @@ class Completion:
model, provider = get_model_and_provider(model, provider, stream)
result = provider.create_completion(model.name,
[{"role": "user", "content": prompt}], stream, **kwargs)
result = provider.create_completion(model.name, [{"role": "user", "content": prompt}], stream, **kwargs)
return result if stream else ''.join(result)

View File

@ -20,7 +20,6 @@ from .Provider import (
DeepAi,
Aichat,
AiAsk,
Aivvm,
GptGo,
Ylokh,
Bard,
@ -44,7 +43,7 @@ default = Model(
Yqcloud, # Answers short questions in chinese
ChatBase, # Don't want to answer creatively
ChatgptDuo, # Include search results
Aibn, Aichat, Aivvm, ChatForAi, ChatgptAi, ChatgptLogin, DeepAi, FreeGpt, GptGo, Myshell, Ylokh,
Aibn, Aichat, ChatForAi, ChatgptAi, ChatgptLogin, DeepAi, FreeGpt, GptGo, Myshell, Ylokh,
])
)
@ -53,7 +52,7 @@ gpt_35_long = Model(
name = 'gpt-3.5-turbo',
base_provider = 'openai',
best_provider = RetryProvider([
AiAsk, Aibn, Aichat, Aivvm, ChatForAi, ChatgptAi, ChatgptDemo, ChatgptDuo,
AiAsk, Aibn, Aichat, ChatForAi, ChatgptAi, ChatgptDemo, ChatgptDuo,
FreeGpt, GptGo, Liaobots, Myshell, Vitalentum, Ylokh, You, Yqcloud
])
)
@ -63,7 +62,7 @@ gpt_35_turbo = Model(
name = 'gpt-3.5-turbo',
base_provider = 'openai',
best_provider = RetryProvider([
DeepAi, ChatgptLogin, ChatgptAi, Aivvm, GptGo, AItianhu, Aichat, AItianhuSpace, Myshell, Aibn, ChatForAi, FreeGpt, Ylokh
DeepAi, ChatgptLogin, ChatgptAi, GptGo, AItianhu, Aichat, AItianhuSpace, Myshell, Aibn, ChatForAi, FreeGpt, Ylokh
])
)
@ -167,26 +166,23 @@ gpt_35_turbo_16k_0613 = Model(
gpt_35_turbo_0613 = Model(
name = 'gpt-3.5-turbo-0613',
base_provider = 'openai',
best_provider = RetryProvider([
Aivvm, ChatgptLogin
])
base_provider = 'openai'
)
gpt_4_0613 = Model(
name = 'gpt-4-0613',
base_provider = 'openai',
best_provider = Aivvm)
base_provider = 'openai'
)
gpt_4_32k = Model(
name = 'gpt-4-32k',
base_provider = 'openai',
best_provider = Aivvm)
base_provider = 'openai'
)
gpt_4_32k_0613 = Model(
name = 'gpt-4-32k-0613',
base_provider = 'openai',
best_provider = Aivvm)
base_provider = 'openai'
)
text_ada_001 = Model(
name = 'text-ada-001',

View File

@ -1,47 +1,51 @@
from __future__ import annotations
import warnings, json, asyncio
import warnings
import json
import asyncio
from functools import partialmethod
from asyncio import Future, Queue
from typing import AsyncGenerator
from typing import AsyncGenerator, Union, Optional
from curl_cffi.requests import AsyncSession, Response
import curl_cffi
is_newer_0_5_8 = hasattr(AsyncSession, "_set_cookies") or hasattr(curl_cffi.requests.Cookies, "get_cookies_for_curl")
is_newer_0_5_9 = hasattr(curl_cffi.AsyncCurl, "remove_handle")
is_newer_0_5_10 = hasattr(AsyncSession, "release_curl")
is_newer_0_5_8: bool = hasattr(AsyncSession, "_set_cookies") or hasattr(curl_cffi.requests.Cookies, "get_cookies_for_curl")
is_newer_0_5_9: bool = hasattr(curl_cffi.AsyncCurl, "remove_handle")
is_newer_0_5_10: bool = hasattr(AsyncSession, "release_curl")
class StreamResponse:
def __init__(self, inner: Response, queue: Queue):
self.inner = inner
self.queue = queue
def __init__(self, inner: Response, queue: Queue[bytes]) -> None:
self.inner: Response = inner
self.queue: Queue[bytes] = queue
self.request = inner.request
self.status_code = inner.status_code
self.reason = inner.reason
self.ok = inner.ok
self.status_code: int = inner.status_code
self.reason: str = inner.reason
self.ok: bool = inner.ok
self.headers = inner.headers
self.cookies = inner.cookies
async def text(self) -> str:
content = await self.read()
content: bytes = await self.read()
return content.decode()
def raise_for_status(self):
def raise_for_status(self) -> None:
if not self.ok:
raise RuntimeError(f"HTTP Error {self.status_code}: {self.reason}")
async def json(self, **kwargs):
async def json(self, **kwargs) -> dict:
return json.loads(await self.read(), **kwargs)
async def iter_lines(self, chunk_size=None, decode_unicode=False, delimiter=None) -> AsyncGenerator[bytes]:
async def iter_lines(
self, chunk_size: Optional[int] = None, decode_unicode: bool = False, delimiter: Optional[str] = None
) -> AsyncGenerator[bytes, None]:
"""
Copied from: https://requests.readthedocs.io/en/latest/_modules/requests/models/
which is under the License: Apache 2.0
"""
pending = None
pending: bytes = None
async for chunk in self.iter_content(
chunk_size=chunk_size, decode_unicode=decode_unicode
@ -63,7 +67,9 @@ class StreamResponse:
if pending is not None:
yield pending
async def iter_content(self, chunk_size=None, decode_unicode=False) -> As:
async def iter_content(
self, chunk_size: Optional[int] = None, decode_unicode: bool = False
) -> AsyncGenerator[bytes, None]:
if chunk_size:
warnings.warn("chunk_size is ignored, there is no way to tell curl that.")
if decode_unicode:
@ -77,22 +83,23 @@ class StreamResponse:
async def read(self) -> bytes:
return b"".join([chunk async for chunk in self.iter_content()])
class StreamRequest:
def __init__(self, session: AsyncSession, method: str, url: str, **kwargs):
self.session = session
self.loop = session.loop if session.loop else asyncio.get_running_loop()
self.queue = Queue()
self.method = method
self.url = url
self.options = kwargs
self.handle = None
def _on_content(self, data):
class StreamRequest:
def __init__(self, session: AsyncSession, method: str, url: str, **kwargs: Union[bool, int, str]) -> None:
self.session: AsyncSession = session
self.loop: asyncio.AbstractEventLoop = session.loop if session.loop else asyncio.get_running_loop()
self.queue: Queue[bytes] = Queue()
self.method: str = method
self.url: str = url
self.options: dict = kwargs
self.handle: Optional[curl_cffi.AsyncCurl] = None
def _on_content(self, data: bytes) -> None:
if not self.enter.done():
self.enter.set_result(None)
self.queue.put_nowait(data)
def _on_done(self, task: Future):
def _on_done(self, task: Future) -> None:
if not self.enter.done():
self.enter.set_result(None)
self.queue.put_nowait(None)
@ -102,8 +109,8 @@ class StreamRequest:
async def fetch(self) -> StreamResponse:
if self.handle:
raise RuntimeError("Request already started")
self.curl = await self.session.pop_curl()
self.enter = self.loop.create_future()
self.curl: curl_cffi.AsyncCurl = await self.session.pop_curl()
self.enter: asyncio.Future = self.loop.create_future()
if is_newer_0_5_10:
request, _, header_buffer, _, _ = self.session._set_curl_options(
self.curl,
@ -121,7 +128,7 @@ class StreamRequest:
**self.options
)
if is_newer_0_5_9:
self.handle = self.session.acurl.add_handle(self.curl)
self.handle = self.session.acurl.add_handle(self.curl)
else:
await self.session.acurl.add_handle(self.curl, False)
self.handle = self.session.acurl._curl2future[self.curl]
@ -136,18 +143,15 @@ class StreamRequest:
response.request = request
else:
response = self.session._parse_response(self.curl, request, _, header_buffer)
return StreamResponse(
response,
self.queue
)
return StreamResponse(response, self.queue)
async def __aenter__(self) -> StreamResponse:
return await self.fetch()
async def __aexit__(self, *args):
async def __aexit__(self, *args) -> None:
self.release_curl()
def release_curl(self):
def release_curl(self) -> None:
if is_newer_0_5_10:
self.session.release_curl(self.curl)
return
@ -162,12 +166,10 @@ class StreamRequest:
self.session.push_curl(self.curl)
self.curl = None
class StreamSession(AsyncSession):
def request(
self,
method: str,
url: str,
**kwargs
self, method: str, url: str, **kwargs
) -> StreamRequest:
return StreamRequest(self, method, url, **kwargs)