返回提交历史
Modified
README.md
+32
-11
Deleted
etc/interference/app.py
+0
-163
Deleted
etc/interference/requirements.txt
+0
-5
Added
g4f/api/__init__.py
+162
-0
Added
g4f/api/run.py
+4
-0
Added
g4f/cli.py
+28
-0
Modified
g4f/gui/__init__.py
+1
-1
Modified
g4f/gui/run.py
+18
-12
Deleted
g4f/interference/__init__.py
+0
-94
Deleted
g4f/interference/run.py
+0
-4
Modified
requirements.txt
+3
-1
Modified
setup.py
+6
-9
XFEstudio/gpt4free
Unify g4f tools into one CLI
77697be3
代码差异
12 个文件
+254
-300
@@ -7,18 +7,39 @@ By using this repository or any code related to it, you agree to the [legal noti
7
7
pip install -U g4f
8
8
```
9
9
10
or if you just want to use the gui or interference api, install with [pipx](https://pypa.github.io/pipx/)
11
12
```sh
13
pipx install g4f
14
```
15
10
16
## New features
11
17
- Telegram Channel: https://t.me/g4f_channel
12
18
- g4f GUI is back !!:
13
19
Install g4f with pip and then run:
14
```py
20
21
```sh
22
g4f gui
23
```
24
25
or
26
27
```sh
15
28
python -m g4f.gui.run
16
29
```
30
17
31
preview:
18
32
19
33
<img width="1470" alt="image" src="https://github.com/xtekky/gpt4free/assets/98614666/57ad818a-a0dd-4eae-83e1-3fff848ae040">
20
34
21
- run interference from pypi package:
35
- run interference api from pypi package:
36
37
```sh
38
g4f api
39
```
40
41
or
42
22
43
```py
23
44
python -m g4f.interference.run
24
45
```
@@ -33,7 +54,7 @@ python -m g4f.interference.run
33
54
- [Usage](#usage)
34
55
- [The `g4f` Package](#the-g4f-package)
35
56
- [interference openai-proxy api (use with openai python package)](#interference-openai-proxy-api-use-with-openai-python-package)
36
- [Providers](#models)
57
- [Models](#models)
37
58
- [gpt-3.5 / gpt-4](#gpt-35--gpt-4)
38
59
- [Other Models](#other-models)
39
60
- [Related gpt4free projects](#related-gpt4free-projects)
@@ -319,26 +340,26 @@ print(f"Result:", response)
319
340
320
341
### interference openai-proxy api (use with openai python package)
321
342
322
#### run interference from pypi package:
343
#### run interference api from pypi package:
323
344
```py
324
from g4f.interference import run_interference
345
from g4f.api import run_api
325
346
326
run_interference()
347
run_api()
327
348
```
328
349
329
#### run interference from repo:
350
#### run interference api from repo:
330
351
If you want to use the embedding function, you need to get a huggingface token. You can get one at https://huggingface.co/settings/tokens make sure your role is set to write. If you have your token, just use it instead of the OpenAI api-key.
331
352
332
get requirements:
353
run server:
333
354
334
355
```sh
335
pip install -r etc/interference/requirements.txt
356
g4f api
336
357
```
337
358
338
run server:
359
or
339
360
340
361
```sh
341
python3 -m etc/interference.app
362
python -m g4f.api
342
363
```
343
364
344
365
```py
@@ -1,163 +0,0 @@
1
import json
2
import time
3
import random
4
import string
5
import requests
6
7
from typing import Any
8
from flask import Flask, request
9
from flask_cors import CORS
10
from transformers import AutoTokenizer
11
from g4f import ChatCompletion
12
13
app = Flask(__name__)
14
CORS(app)
15
16
@app.route('/chat/completions', methods=['POST'])
17
def chat_completions():
18
model = request.get_json().get('model', 'gpt-3.5-turbo')
19
stream = request.get_json().get('stream', False)
20
messages = request.get_json().get('messages')
21
22
response = ChatCompletion.create(model = model,
23
stream = stream, messages = messages)
24
25
completion_id = ''.join(random.choices(string.ascii_letters + string.digits, k=28))
26
completion_timestamp = int(time.time())
27
28
if not stream:
29
return {
30
'id': f'chatcmpl-{completion_id}',
31
'object': 'chat.completion',
32
'created': completion_timestamp,
33
'model': model,
34
'choices': [
35
{
36
'index': 0,
37
'message': {
38
'role': 'assistant',
39
'content': response,
40
},
41
'finish_reason': 'stop',
42
}
43
],
44
'usage': {
45
'prompt_tokens': None,
46
'completion_tokens': None,
47
'total_tokens': None,
48
},
49
}
50
51
def streaming():
52
for chunk in response:
53
completion_data = {
54
'id': f'chatcmpl-{completion_id}',
55
'object': 'chat.completion.chunk',
56
'created': completion_timestamp,
57
'model': model,
58
'choices': [
59
{
60
'index': 0,
61
'delta': {
62
'content': chunk,
63
},
64
'finish_reason': None,
65
}
66
],
67
}
68
69
content = json.dumps(completion_data, separators=(',', ':'))
70
yield f'data: {content}\n\n'
71
time.sleep(0.1)
72
73
end_completion_data: dict[str, Any] = {
74
'id': f'chatcmpl-{completion_id}',
75
'object': 'chat.completion.chunk',
76
'created': completion_timestamp,
77
'model': model,
78
'choices': [
79
{
80
'index': 0,
81
'delta': {},
82
'finish_reason': 'stop',
83
}
84
],
85
}
86
content = json.dumps(end_completion_data, separators=(',', ':'))
87
yield f'data: {content}\n\n'
88
89
return app.response_class(streaming(), mimetype='text/event-stream')
90
91
92
# Get the embedding from huggingface
93
def get_embedding(input_text, token):
94
huggingface_token = token
95
embedding_model = 'sentence-transformers/all-mpnet-base-v2'
96
max_token_length = 500
97
98
# Load the tokenizer for the 'all-mpnet-base-v2' model
99
tokenizer = AutoTokenizer.from_pretrained(embedding_model)
100
# Tokenize the text and split the tokens into chunks of 500 tokens each
101
tokens = tokenizer.tokenize(input_text)
102
token_chunks = [tokens[i:i + max_token_length]
103
for i in range(0, len(tokens), max_token_length)]
104
105
# Initialize an empty list
106
embeddings = []
107
108
# Create embeddings for each chunk
109
for chunk in token_chunks:
110
# Convert the chunk tokens back to text
111
chunk_text = tokenizer.convert_tokens_to_string(chunk)
112
113
# Use the Hugging Face API to get embeddings for the chunk
114
api_url = f'https://api-inference.huggingface.co/pipeline/feature-extraction/{embedding_model}'
115
headers = {'Authorization': f'Bearer {huggingface_token}'}
116
chunk_text = chunk_text.replace('\n', ' ')
117
118
# Make a POST request to get the chunk's embedding
119
response = requests.post(api_url, headers=headers, json={
120
'inputs': chunk_text, 'options': {'wait_for_model': True}})
121
122
# Parse the response and extract the embedding
123
chunk_embedding = response.json()
124
# Append the embedding to the list
125
embeddings.append(chunk_embedding)
126
127
# averaging all the embeddings
128
# this isn't very effective
129
# someone a better idea?
130
num_embeddings = len(embeddings)
131
average_embedding = [sum(x) / num_embeddings for x in zip(*embeddings)]
132
embedding = average_embedding
133
return embedding
134
135
136
@app.route('/embeddings', methods=['POST'])
137
def embeddings():
138
input_text_list = request.get_json().get('input')
139
input_text = ' '.join(map(str, input_text_list))
140
token = request.headers.get('Authorization').replace('Bearer ', '')
141
embedding = get_embedding(input_text, token)
142
143
return {
144
'data': [
145
{
146
'embedding': embedding,
147
'index': 0,
148
'object': 'embedding'
149
}
150
],
151
'model': 'text-embedding-ada-002',
152
'object': 'list',
153
'usage': {
154
'prompt_tokens': None,
155
'total_tokens': None
156
}
157
}
158
159
def main():
160
app.run(host='0.0.0.0', port=1337, debug=True)
161
162
if __name__ == '__main__':
163
main()
@@ -1,5 +0,0 @@
1
flask_cors
2
watchdog~=3.0.0
3
transformers
4
tensorflow
5
torch
@@ -0,0 +1,162 @@
1
import json
2
import random
3
import string
4
import time
5
6
import requests
7
from flask import Flask, request
8
from flask_cors import CORS
9
from transformers import AutoTokenizer
10
11
from g4f import ChatCompletion
12
13
app = Flask(__name__)
14
CORS(app)
15
16
17
@app.route("/")
18
def index():
19
return "interference api, url: http://127.0.0.1:1337"
20
21
22
@app.route("/chat/completions", methods=["POST"])
23
def chat_completions():
24
model = request.get_json().get("model", "gpt-3.5-turbo")
25
stream = request.get_json().get("stream", False)
26
messages = request.get_json().get("messages")
27
28
response = ChatCompletion.create(model=model, stream=stream, messages=messages)
29
30
completion_id = "".join(random.choices(string.ascii_letters + string.digits, k=28))
31
completion_timestamp = int(time.time())
32
33
if not stream:
34
return {
35
"id": f"chatcmpl-{completion_id}",
36
"object": "chat.completion",
37
"created": completion_timestamp,
38
"model": model,
39
"choices": [
40
{
41
"index": 0,
42
"message": {
43
"role": "assistant",
44
"content": response,
45
},
46
"finish_reason": "stop",
47
}
48
],
49
"usage": {
50
"prompt_tokens": None,
51
"completion_tokens": None,
52
"total_tokens": None,
53
},
54
}
55
56
def streaming():
57
for chunk in response:
58
completion_data = {
59
"id": f"chatcmpl-{completion_id}",
60
"object": "chat.completion.chunk",
61
"created": completion_timestamp,
62
"model": model,
63
"choices": [
64
{
65
"index": 0,
66
"delta": {
67
"content": chunk,
68
},
69
"finish_reason": None,
70
}
71
],
72
}
73
74
content = json.dumps(completion_data, separators=(",", ":"))
75
yield f"data: {content}\n\n"
76
time.sleep(0.1)
77
78
end_completion_data = {
79
"id": f"chatcmpl-{completion_id}",
80
"object": "chat.completion.chunk",
81
"created": completion_timestamp,
82
"model": model,
83
"choices": [
84
{
85
"index": 0,
86
"delta": {},
87
"finish_reason": "stop",
88
}
89
],
90
}
91
content = json.dumps(end_completion_data, separators=(",", ":"))
92
yield f"data: {content}\n\n"
93
94
return app.response_class(streaming(), mimetype="text/event-stream")
95
96
97
# Get the embedding from huggingface
98
def get_embedding(input_text, token):
99
huggingface_token = token
100
embedding_model = "sentence-transformers/all-mpnet-base-v2"
101
max_token_length = 500
102
103
# Load the tokenizer for the 'all-mpnet-base-v2' model
104
tokenizer = AutoTokenizer.from_pretrained(embedding_model)
105
# Tokenize the text and split the tokens into chunks of 500 tokens each
106
tokens = tokenizer.tokenize(input_text)
107
token_chunks = [
108
tokens[i : i + max_token_length]
109
for i in range(0, len(tokens), max_token_length)
110
]
111
112
# Initialize an empty list
113
embeddings = []
114
115
# Create embeddings for each chunk
116
for chunk in token_chunks:
117
# Convert the chunk tokens back to text
118
chunk_text = tokenizer.convert_tokens_to_string(chunk)
119
120
# Use the Hugging Face API to get embeddings for the chunk
121
api_url = f"https://api-inference.huggingface.co/pipeline/feature-extraction/{embedding_model}"
122
headers = {"Authorization": f"Bearer {huggingface_token}"}
123
chunk_text = chunk_text.replace("\n", " ")
124
125
# Make a POST request to get the chunk's embedding
126
response = requests.post(
127
api_url,
128
headers=headers,
129
json={"inputs": chunk_text, "options": {"wait_for_model": True}},
130
)
131
132
# Parse the response and extract the embedding
133
chunk_embedding = response.json()
134
# Append the embedding to the list
135
embeddings.append(chunk_embedding)
136
137
# averaging all the embeddings
138
# this isn't very effective
139
# someone a better idea?
140
num_embeddings = len(embeddings)
141
average_embedding = [sum(x) / num_embeddings for x in zip(*embeddings)]
142
embedding = average_embedding
143
return embedding
144
145
146
@app.route("/embeddings", methods=["POST"])
147
def embeddings():
148
input_text_list = request.get_json().get("input")
149
input_text = " ".join(map(str, input_text_list))
150
token = request.headers.get("Authorization").replace("Bearer ", "")
151
embedding = get_embedding(input_text, token)
152
153
return {
154
"data": [{"embedding": embedding, "index": 0, "object": "embedding"}],
155
"model": "text-embedding-ada-002",
156
"object": "list",
157
"usage": {"prompt_tokens": None, "total_tokens": None},
158
}
159
160
161
def run_api():
162
app.run(host="0.0.0.0", port=1337)
@@ -0,0 +1,4 @@
1
from g4f.api import run_api
2
3
if __name__ == "__main__":
4
run_api()
@@ -0,0 +1,28 @@
1
import argparse
2
3
from g4f.api import run_api
4
from g4f.gui.run import gui_parser, run_gui_args
5
6
7
def run_gui(args):
8
print("Running GUI...")
9
10
11
def main():
12
parser = argparse.ArgumentParser(description="Run gpt4free")
13
subparsers = parser.add_subparsers(dest="mode", help="Mode to run the g4f in.")
14
subparsers.add_parser("api")
15
subparsers.add_parser("gui", parents=[gui_parser()], add_help=False)
16
17
args = parser.parse_args()
18
if args.mode == "api":
19
run_api()
20
elif args.mode == "gui":
21
run_gui_args(args)
22
else:
23
parser.print_help()
24
exit(1)
25
26
27
if __name__ == "__main__":
28
main()
@@ -27,4 +27,4 @@ def run_gui(host: str = '0.0.0.0', port: int = 80, debug: bool = False) -> None:
27
27
28
28
print(f"Running on port {config['port']}")
29
29
app.run(**config)
30
print(f"Closing port {config['port']}")
30
print(f"Closing port {config['port']}")
@@ -1,18 +1,24 @@
1
from g4f.gui import run_gui
2
1
from argparse import ArgumentParser
3
2
3
from g4f.gui import run_gui
4
4
5
if __name__ == '__main__':
6
7
parser = ArgumentParser(description='Run the GUI')
8
9
parser.add_argument('-host', type=str, default='0.0.0.0', help='hostname')
10
parser.add_argument('-port', type=int, default=80, help='port')
11
parser.add_argument('-debug', action='store_true', help='debug mode')
12
5
13
args = parser.parse_args()
14
port = args.port
6
def gui_parser():
7
parser = ArgumentParser(description="Run the GUI")
8
parser.add_argument("-host", type=str, default="0.0.0.0", help="hostname")
9
parser.add_argument("-port", type=int, default=80, help="port")
10
parser.add_argument("-debug", action="store_true", help="debug mode")
11
return parser
12
13
14
def run_gui_args(args):
15
15
host = args.host
16
port = args.port
16
17
debug = args.debug
17
18
run_gui(host, port, debug)
18
run_gui(host, port, debug)
19
20
21
if __name__ == "__main__":
22
parser = gui_parser()
23
args = parser.parse_args()
24
run_gui_args(args)
@@ -1,94 +0,0 @@
1
import json
2
import time
3
import random
4
import string
5
6
from typing import Any
7
from flask import Flask, request
8
from flask_cors import CORS
9
from g4f import ChatCompletion
10
11
app = Flask(__name__)
12
CORS(app)
13
14
@app.route('/')
15
def index():
16
return 'interference api, url: http://127.0.0.1:1337'
17
18
@app.route('/chat/completions', methods=['POST'])
19
def chat_completions():
20
model = request.get_json().get('model', 'gpt-3.5-turbo')
21
stream = request.get_json().get('stream', False)
22
messages = request.get_json().get('messages')
23
24
response = ChatCompletion.create(model = model,
25
stream = stream, messages = messages)
26
27
completion_id = ''.join(random.choices(string.ascii_letters + string.digits, k=28))
28
completion_timestamp = int(time.time())
29
30
if not stream:
31
return {
32
'id': f'chatcmpl-{completion_id}',
33
'object': 'chat.completion',
34
'created': completion_timestamp,
35
'model': model,
36
'choices': [
37
{
38
'index': 0,
39
'message': {
40
'role': 'assistant',
41
'content': response,
42
},
43
'finish_reason': 'stop',
44
}
45
],
46
'usage': {
47
'prompt_tokens': None,
48
'completion_tokens': None,
49
'total_tokens': None,
50
},
51
}
52
53
def streaming():
54
for chunk in response:
55
completion_data = {
56
'id': f'chatcmpl-{completion_id}',
57
'object': 'chat.completion.chunk',
58
'created': completion_timestamp,
59
'model': model,
60
'choices': [
61
{
62
'index': 0,
63
'delta': {
64
'content': chunk,
65
},
66
'finish_reason': None,
67
}
68
],
69
}
70
71
content = json.dumps(completion_data, separators=(',', ':'))
72
yield f'data: {content}\n\n'
73
time.sleep(0.1)
74
75
end_completion_data: dict[str, Any] = {
76
'id': f'chatcmpl-{completion_id}',
77
'object': 'chat.completion.chunk',
78
'created': completion_timestamp,
79
'model': model,
80
'choices': [
81
{
82
'index': 0,
83
'delta': {},
84
'finish_reason': 'stop',
85
}
86
],
87
}
88
content = json.dumps(end_completion_data, separators=(',', ':'))
89
yield f'data: {content}\n\n'
90
91
return app.response_class(streaming(), mimetype='text/event-stream')
92
93
def run_interference():
94
app.run(host='0.0.0.0', port=1337, debug=True)
@@ -1,4 +0,0 @@
1
from g4f.interference import run_interference
2
3
if __name__ == '__main__':
4
run_interference()
@@ -10,4 +10,6 @@ flask
10
10
flask-cors
11
11
typing-extensions
12
12
PyExecJS
13
duckduckgo-search
13
duckduckgo-search
14
transformers
15
tensorflow
@@ -11,10 +11,7 @@ with codecs.open(os.path.join(here, "README.md"), encoding="utf-8") as fh:
11
11
with open("requirements.txt") as f:
12
12
required = f.read().splitlines()
13
13
14
with open("etc/interference/requirements.txt") as f:
15
api_required = f.read().splitlines()
16
17
VERSION = '0.1.6.1'
14
VERSION = "0.1.6.1"
18
15
DESCRIPTION = (
19
16
"The official gpt4free repository | various collection of powerful language models"
20
17
)
@@ -29,13 +26,13 @@ setup(
29
26
long_description_content_type="text/markdown",
30
27
long_description=long_description,
31
28
packages=find_packages(),
32
package_data={"g4f": ["g4f/gui/client/*", "g4f/gui/server/*"]},
29
package_data={
30
"g4f": ["g4f/interference/*", "g4f/gui/client/*", "g4f/gui/server/*"]
31
},
33
32
include_package_data=True,
34
data_files=["etc/interference/app.py"],
35
33
install_requires=required,
36
extras_require={"api": api_required},
37
34
entry_points={
38
"console_scripts": ["g4f=interference.app:main"],
35
"console_scripts": ["g4f=g4f.cli:main"],
39
36
},
40
37
url="https://github.com/xtekky/gpt4free", # Link to your GitHub repository
41
38
project_urls={
@@ -75,4 +72,4 @@ setup(
75
72
"Operating System :: MacOS :: MacOS X",
76
73
"Operating System :: Microsoft :: Windows",
77
74
],
78
)
75
)