XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 1
返回提交历史

XFEstudio/gpt4free

Unify g4f tools into one CLI

77697be3
Arran Hobson Sayers <ahobsonsayers@gmail.com>
提交于

代码差异

12 个文件 +254 -300
Modified README.md +32 -11
@@ -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
Deleted etc/interference/app.py +0 -163
@@ -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()
Deleted etc/interference/requirements.txt +0 -5
@@ -1,5 +0,0 @@
1 flask_cors
2 watchdog~=3.0.0
3 transformers
4 tensorflow
5 torch
Added g4f/api/__init__.py +162 -0
@@ -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)
Added g4f/api/run.py +4 -0
@@ -0,0 +1,4 @@
1 from g4f.api import run_api
2
3 if __name__ == "__main__":
4 run_api()
Added g4f/cli.py +28 -0
@@ -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()
Modified g4f/gui/__init__.py +1 -1
@@ -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']}")
Modified g4f/gui/run.py +18 -12
@@ -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)
Deleted g4f/interference/__init__.py +0 -94
@@ -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)
Deleted g4f/interference/run.py +0 -4
@@ -1,4 +0,0 @@
1 from g4f.interference import run_interference
2
3 if __name__ == '__main__':
4 run_interference()
Modified requirements.txt +3 -1
@@ -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
Modified setup.py +6 -9
@@ -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 )