zerrin commited on
Commit
4ab2d90
1 Parent(s): 315d075

Upload 11 files

Browse files
assets/config.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "HOST": "0.0.0.0",
3
+ "PORT": 5000,
4
+ "DEBUG": false,
5
+
6
+ "use_global": true,
7
+ "use_addons": true
8
+ }
assets/source/__init__.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ from .api import Api, non_streamed_format
2
+
3
+ # create api instance
4
+ api = Api()
5
+
6
+ __all__ = [
7
+ "api",
8
+ "non_streamed_format"
9
+ ]
assets/source/addons/__init__.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ All addons should be imported here
3
+ """
4
+ from .translation import translate, message_translation
5
+ from .expose import create_cloudflare_tunnel
6
+
7
+ # here the addons are exported
8
+ __all__ = [
9
+ 'translate',
10
+ 'message_translation',
11
+ 'create_cloudflare_tunnel'
12
+ ]
assets/source/addons/expose.md ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ # DeepInfra-Wrapper Addon - Cloudflare Quick-tunnels.
2
+
3
+ This addon is needed to globally expose our flask application and create a URL that can be accessed from anywhere.
4
+
5
+ ## Usage
6
+
7
+ To use, call `create_cloudflare_tunnel` function and pass the port as a paremeter. You will then see Cloudflare emit the created ULR inside the console.
8
+ Remember, you need to have `use_addons` set to `true` in the config.json
assets/source/addons/expose.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Code credits: ColabKobold
3
+
4
+ https://github.com/lostruins/koboldcpp
5
+ """
6
+
7
+ import os, sys, threading, time, subprocess, re
8
+
9
+ def create_cloudflare_tunnel(port: int):
10
+
11
+ """
12
+ Create a cloudflare tunnel for the server
13
+ """
14
+
15
+ try:
16
+
17
+ def run_tunnel():
18
+
19
+ """
20
+ Run the cloudflare tunnel
21
+ """
22
+
23
+ # variables to be used in the thread
24
+ tunnel_process = None
25
+ tunnel_output = ""
26
+ tunnel_raw_dump = ""
27
+
28
+ time.sleep(0.2)
29
+ if os.name == 'nt':
30
+
31
+ print("Starting Cloudflare Tunnel for Windows, please wait...", flush=True)
32
+ tunnel_process = subprocess.Popen(f"cloudflared.exe tunnel --url localhost:{port}", text=True, encoding='utf-8', shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)
33
+
34
+ elif sys.platform=="darwin":
35
+ print("Starting Cloudflare Tunnel for MacOS, please wait...", flush=True)
36
+ tunnel_process = subprocess.Popen(f"./cloudflared tunnel --url http://localhost:{port}", text=True, encoding='utf-8', shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)
37
+
38
+ else:
39
+ print("Starting Cloudflare Tunnel for Linux, please wait...", flush=True)
40
+ tunnel_process = subprocess.Popen(f"./cloudflared-linux-amd64 tunnel --url http://localhost:{port}", text=True, encoding='utf-8', shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)
41
+
42
+ # wait for the tunnel to be ready
43
+ time.sleep(10)
44
+
45
+ def tunnel_reader():
46
+
47
+ """
48
+ Read the stderr of the cloudflare tunnel process
49
+ """
50
+
51
+ nonlocal tunnel_process, tunnel_output, tunnel_raw_dump
52
+
53
+ pattern: str = r'https://[\w\.-]+\.trycloudflare\.com'
54
+
55
+ while True:
56
+
57
+ line = tunnel_process.stderr.readline() #cloudflare writes to stderr for some reason
58
+ tunnel_raw_dump += line+"\n"
59
+
60
+ if not line:
61
+
62
+ # if the line is empty, the tunnel is closed
63
+ return
64
+
65
+ found = re.findall(pattern, line)
66
+
67
+ for x in found:
68
+
69
+ tunneloutput = x
70
+
71
+ return
72
+
73
+ tunnel_reader_thread = threading.Thread(target=tunnel_reader)
74
+ tunnel_reader_thread.start()
75
+
76
+ time.sleep(5) # wait for the tunnel to be ready
77
+
78
+ if tunnel_output=="":
79
+
80
+ print(f"Error: Could not create cloudflare tunnel!\nMore Info:\n{tunnel_raw_dump}", flush=True)
81
+
82
+ time.sleep(0.5)
83
+ tunnel_process.wait()
84
+
85
+ # Windows
86
+ if os.name == 'nt':
87
+
88
+ if os.path.exists("cloudflared.exe") and os.path.getsize("cloudflared.exe") > 1000000:
89
+
90
+ print("Cloudflared file exists, reusing it...")
91
+
92
+ else:
93
+
94
+ print("Downloading Cloudflare Tunnel for Windows...")
95
+ subprocess.run("curl -fL https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-windows-amd64.exe -o cloudflared.exe", shell=True, capture_output=True, text=True, check=True, encoding='utf-8')
96
+
97
+ # MacOS
98
+ elif sys.platform=="darwin":
99
+
100
+ if os.path.exists("cloudflared") and os.path.getsize("cloudflared") > 1000000:
101
+ print("Cloudflared file exists, reusing it...")
102
+
103
+ else:
104
+
105
+ print("Downloading Cloudflare Tunnel for MacOS...")
106
+ subprocess.run("curl -fL https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-darwin-amd64.tgz -o cloudflared-darwin-amd64.tgz", shell=True, capture_output=True, text=True, check=True, encoding='utf-8')
107
+ subprocess.run("tar -xzf cloudflared-darwin-amd64.tgz", shell=True)
108
+ subprocess.run("chmod +x 'cloudflared'", shell=True)
109
+
110
+ else:
111
+
112
+ if os.path.exists("cloudflared-linux-amd64") and os.path.getsize("cloudflared-linux-amd64") > 1000000:
113
+ print("Cloudflared file exists, reusing it...")
114
+
115
+ else:
116
+
117
+ print("Downloading Cloudflare Tunnel for Linux...")
118
+ subprocess.run("curl -fL https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o cloudflared-linux-amd64", shell=True, capture_output=True, text=True, check=True, encoding='utf-8')
119
+ subprocess.run("chmod +x 'cloudflared-linux-amd64'", shell=True)
120
+
121
+ print("Attempting to start tunnel thread...", flush=True)
122
+ tunnel_thread = threading.Thread(target=run_tunnel)
123
+ tunnel_thread.start()
124
+
125
+ except Exception as ex:
126
+
127
+ print("Remote Tunnel Failed!")
128
+ print(str(ex))
129
+ return None
130
+
assets/source/addons/translation.md ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ # DeepInfra-Wrapper Addon - Translation
2
+
3
+ This addon is used to translate OpenAI model names to the actual model names. The names are semi-random.
4
+
5
+ ## Usage
6
+
7
+ To use this addon, you can call the `translate` function with a model name as the input. The function will return the corresponding actual model name.
8
+ Remember, you need to have `use_addons` set to `true` in the config.json
9
+
10
+ For regular use cases, turn this off.
assets/source/addons/translation.py ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ This addon is used to make OpenAI model names point to one of these models. The names are semi-random picked.
3
+ """
4
+
5
+ model_map = [
6
+ {"gpt-4-0613": "mistralai/Mistral-7B-Instruct-v0.3"},
7
+ {"davinci-002": ""},
8
+ {"gpt-4": "microsoft/WizardLM-2-8x22B"},
9
+ {"gpt-4o": "mistralai/Mistral-7B-Instruct-v0.2"},
10
+ {"gpt-4-0125-preview": "mistralai/Mixtral-8x7B-Instruct-v0.1"},
11
+ {"gpt-4-turbo-preview": "mistralai/Mixtral-8x22B-Instruct-v0.1"},
12
+ {"gpt-4-1106-preview": "cognitivecomputations/dolphin-2.6-mixtral-8x7b"},
13
+ {"gpt-3.5-turbo-16k": "meta-llama/Meta-Llama-3-8B-Instruct"},
14
+ {"gpt-3.5-turbo-instruct-0914": "meta-llama/Meta-Llama-3-70B-Instruct"},
15
+ ]
16
+
17
+ def translate(model: str) -> str:
18
+
19
+ """
20
+ Translate model names to the actual model names
21
+ """
22
+
23
+ for i in model_map:
24
+ if model in i:
25
+ return i[model]
26
+
27
+ return model
28
+
29
+ def message_translation(messages: list[dict[str, str]]) -> list[dict[str, str]]:
30
+
31
+ """
32
+ Translate messages
33
+
34
+ Current Message format
35
+
36
+ messages = [{"role": "user", "content": "Whatever"}]
37
+
38
+ Old format:
39
+
40
+ messages = [{"role": "user", "content": [{"text": "Whatever"}]}]
41
+
42
+ :param messages: list of messages
43
+
44
+ :return: list of messages
45
+ """
46
+ translated_messages = []
47
+
48
+ for message in messages:
49
+ # Check if the message content is in the old format
50
+ if isinstance(message['content'], list):
51
+ # Extract the text from the old format and assign it to the new format
52
+ content = message['content'][0]['text']
53
+ message['content'] = content
54
+
55
+ # Append the message to the list of translated messages
56
+ translated_messages.append(message)
57
+
58
+ return translated_messages
assets/source/api.py ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ---------------------------------------- IMPORTS ---------------------------------------- #
2
+
3
+ # this module allows us to get the headers from the get_headers function
4
+ from .headers.get_headers import get_headers
5
+
6
+ # this module allows us to get a random user agent
7
+ from fake_useragent import UserAgent
8
+
9
+ # this module allows us to generate random numbers
10
+ import secrets
11
+
12
+ # to make requests
13
+ import requests
14
+
15
+ # type hints
16
+ from typing import Generator, Any, Dict, List
17
+
18
+ # ---------------------------------------- FUNCTIONS ---------------------------------------- #
19
+ def non_streamed_format(model: str, content: str) -> Dict[str, Any]:
20
+
21
+ return {
22
+ "object": "chat.completion",
23
+ "model": f"{model}",
24
+ "choices": [{
25
+ "index": 0,
26
+ "message": {
27
+ "role": "assistant",
28
+ "content": f"{content}",
29
+ },
30
+ "finish_reason": "stop",
31
+ }],
32
+ }
33
+ # ---------------------------------------- API CLASS ---------------------------------------- #
34
+
35
+ class Api(object):
36
+
37
+ # initialize the class and set some variables here
38
+ def __init__(self) -> None:
39
+
40
+ """initialize the class"""
41
+
42
+ self.url: str = "https://api.deepinfra.com/v1/openai/chat/completions"
43
+
44
+ self.headers = get_headers(UserAgent().random, secrets.randbelow(500)) # get random headers
45
+
46
+ self.session = requests.Session() # create a session
47
+
48
+ # codec for encoding and decoding
49
+ self.codec = 'utf-8'
50
+
51
+ def get_models(self) -> Dict[str, List[Dict[str, str]]]:
52
+
53
+ """get all models"""
54
+
55
+ return {'data': [
56
+ {"id": "meta-llama/Meta-Llama-3-70B-Instruct", "context": 8192},
57
+ {"id": "meta-llama/Meta-Llama-3-8B-Instruct", "context": 8192},
58
+ {"id": "codellama/CodeLlama-34b-Instruct-hf", "context": 4096},
59
+ {"id": "jondurbin/airoboros-l2-70b-gpt4-1.4.1", "context": 4096},
60
+ {"id": "mistralai/Mistral-7B-Instruct-v0.2", "context": 32768},
61
+ {"id": "mistralai/Mistral-7B-Instruct-v0.3", "context": 32768},
62
+ {"id": "mistralai/Mixtral-8x7B-Instruct-v0.1", "context": 32768},
63
+ {"id": "mistralai/Mixtral-8x22B-Instruct-v0.1", "context": 65536},
64
+ {"id": "cognitivecomputations/dolphin-2.6-mixtral-8x7b", "context": 32768},
65
+ {"id": "lizpreciatior/lzlv_70b_fp16_hf", "context": 32768},
66
+ {"id": "deepinfra/airoboros-70b", "context": 4096},
67
+ {"id": "HuggingFaceH4/zephyr-orpo-141b-A35b-v0.1", "context": 65536},
68
+ {"id": "microsoft/WizardLM-2-8x22B", "context": 65536},
69
+ ]}
70
+
71
+
72
+ def chat(
73
+ self,
74
+ messages: List[Dict[str, str]],
75
+ model: str,
76
+ stream: bool = True,
77
+ temperature: int = 0.7,
78
+ max_tokens: int = 150,
79
+ top_p: float = 1.0,
80
+ top_k: int = 50,
81
+ presence_penalty: float = 0.0,
82
+ frequency_penalty: float = 0.0
83
+ ) -> Generator[str, Any, Any] | Dict[str, Any]:
84
+
85
+ """
86
+ Chat with the DeepInfra models.
87
+
88
+ :param messages: list of messages
89
+ :param model: model name
90
+
91
+ :param stream: stream the response
92
+ :param temperature: temperature
93
+ :param max_tokens: max tokens
94
+
95
+ :param top_p: top p
96
+ :param top_k: top k
97
+
98
+ :param presence_penalty: presence penalty
99
+ :param frequency_penalty: frequency penalty
100
+
101
+ :return: generator or dict
102
+ """
103
+
104
+ # compile the data
105
+ data = {
106
+ 'messages': messages,
107
+ 'model': model,
108
+ 'stream': stream,
109
+
110
+ 'temperature': temperature,
111
+ 'max_tokens': max_tokens,
112
+
113
+ 'top_p': top_p,
114
+ 'top_k': top_k,
115
+
116
+ 'presence_penalty': presence_penalty,
117
+ 'frequency_penalty': frequency_penalty,
118
+ }
119
+
120
+ # make a post request to the api
121
+ response = self.session.post(self.url, headers=self.headers, json=data, stream=stream)
122
+
123
+ # raise for status
124
+ response.raise_for_status()
125
+
126
+ # if stream is False
127
+ if not stream:
128
+ return non_streamed_format(model, response.json()['choices'][0]['message']['content'])
129
+
130
+ return response.iter_lines()
131
+
132
+ # Path: assets/source/api.py
assets/source/headers/__init__.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ from .get_headers import get_headers
2
+
3
+ __all__ = ['get_headers']
assets/source/headers/get_headers.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ def get_headers(user_agent: str, content_length: int):
2
+
3
+ return {
4
+ 'Authority': 'api.deepinfra.com',
5
+ 'Host': 'api.deepinfra.com',
6
+ 'User-Agent': f'{user_agent}',
7
+ 'Accept': 'text/event-stream',
8
+ 'Accept-Language': 'en-US,en;q=0.5',
9
+ 'Accept-Encoding': 'gzip, deflate, br',
10
+ 'Referer': 'https://deepinfra.com/',
11
+ 'Content-Type': 'application/json',
12
+ 'X-Deepinfra-Source': 'web-page',
13
+ 'Content-Length': f'{content_length}',
14
+ 'Origin': 'https://deepinfra.com',
15
+ 'Connection': 'keep-alive',
16
+ 'Sec-Fetch-Dest': 'empty',
17
+ 'Sec-Fetch-Mode': 'cors',
18
+ 'Sec-Fetch-Site': 'same-site'
19
+ }
20
+
21
+ # Path: assets/source/headers/get_headers.py
assets/templates/index.html ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>DeepInfra Wrapper - Developer Reference</title>
7
+ <style>
8
+ body {
9
+ background-color: #1a1a1a;
10
+ color: #e0e0e0;
11
+ font-family: 'Arial', sans-serif;
12
+ margin: 0;
13
+ padding: 0;
14
+ }
15
+ .container {
16
+ width: 80%;
17
+ margin: 0 auto;
18
+ padding: 20px;
19
+ }
20
+ header {
21
+ text-align: center;
22
+ padding: 50px 0;
23
+ }
24
+ header h1 {
25
+ color: #00ff00;
26
+ }
27
+ .status {
28
+ text-align: center;
29
+ padding: 10px;
30
+ margin-bottom: 20px;
31
+ background-color: #006400;
32
+ border-radius: 5px;
33
+ }
34
+ .routes {
35
+ margin-top: 20px;
36
+ }
37
+ .routes h2 {
38
+ color: #00ff00;
39
+ }
40
+ .routes ul {
41
+ list-style: none;
42
+ padding: 0;
43
+ }
44
+ .routes ul li {
45
+ background-color: #333333;
46
+ padding: 10px;
47
+ margin: 5px 0;
48
+ border-radius: 5px;
49
+ }
50
+ .routes ul li a {
51
+ color: #00ff00;
52
+ text-decoration: none;
53
+ }
54
+ .routes ul li a:hover {
55
+ text-decoration: underline;
56
+ }
57
+ </style>
58
+ </head>
59
+ <body>
60
+ <div class="container">
61
+ <header>
62
+ <h1>DeepInfra Wrapper</h1>
63
+ <div class="status">Status: Active</div>
64
+ </header>
65
+ <div class="routes">
66
+ <h2>Available Routes</h2>
67
+ <ul>
68
+ <li><a href="/chat/completions">/chat/completions</a></li>
69
+ <li><a href="/models">/models</a></li>
70
+ </ul>
71
+ </div>
72
+ </div>
73
+ </body>
74
+ </html>