GPTRouter 0.0.2__tar.gz → 0.2.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {GPTRouter-0.0.2 → GPTRouter-0.2.5}/GPTRouter.egg-info/PKG-INFO +2 -2
- {GPTRouter-0.0.2 → GPTRouter-0.2.5}/GPTRouter.egg-info/SOURCES.txt +1 -0
- GPTRouter-0.2.5/GPTRouter.egg-info/requires.txt +3 -0
- {GPTRouter-0.0.2 → GPTRouter-0.2.5}/PKG-INFO +2 -2
- {GPTRouter-0.0.2 → GPTRouter-0.2.5}/gpt_router/client.py +117 -31
- GPTRouter-0.2.5/gpt_router/constants.py +2 -0
- GPTRouter-0.2.5/gpt_router/enums.py +162 -0
- GPTRouter-0.2.5/gpt_router/exceptions.py +59 -0
- GPTRouter-0.2.5/gpt_router/models.py +98 -0
- {GPTRouter-0.0.2 → GPTRouter-0.2.5}/pyproject.toml +3 -1
- GPTRouter-0.2.5/setup.py +22 -0
- GPTRouter-0.0.2/GPTRouter.egg-info/requires.txt +0 -2
- GPTRouter-0.0.2/gpt_router/constants.py +0 -2
- GPTRouter-0.0.2/gpt_router/enums.py +0 -38
- GPTRouter-0.0.2/gpt_router/models.py +0 -53
- GPTRouter-0.0.2/setup.py +0 -25
- {GPTRouter-0.0.2 → GPTRouter-0.2.5}/GPTRouter.egg-info/dependency_links.txt +0 -0
- {GPTRouter-0.0.2 → GPTRouter-0.2.5}/GPTRouter.egg-info/top_level.txt +0 -0
- {GPTRouter-0.0.2 → GPTRouter-0.2.5}/LICENSE +0 -0
- {GPTRouter-0.0.2 → GPTRouter-0.2.5}/README.md +0 -0
- {GPTRouter-0.0.2 → GPTRouter-0.2.5}/gpt_router/__init__.py +0 -0
- {GPTRouter-0.0.2 → GPTRouter-0.2.5}/setup.cfg +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: GPTRouter
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.5
|
|
4
4
|
Summary: A Python package for working with GPTRouter APIs
|
|
5
|
-
Author-email: sirjanpreet
|
|
5
|
+
Author-email: sirjanpreet@writesonic.com
|
|
6
6
|
Classifier: Development Status :: 3 - Alpha
|
|
7
7
|
Classifier: Intended Audience :: Developers
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: GPTRouter
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.5
|
|
4
4
|
Summary: A Python package for working with GPTRouter APIs
|
|
5
|
-
Author-email: sirjanpreet
|
|
5
|
+
Author-email: sirjanpreet@writesonic.com
|
|
6
6
|
Classifier: Development Status :: 3 - Alpha
|
|
7
7
|
Classifier: Intended Audience :: Developers
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -1,15 +1,41 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
|
|
2
|
+
from pydantic import parse_obj_as
|
|
3
3
|
import logging
|
|
4
4
|
import json
|
|
5
5
|
import httpx
|
|
6
|
-
from typing import Generator, List, Union
|
|
6
|
+
from typing import Generator, List, Optional, Union
|
|
7
7
|
|
|
8
|
-
from gpt_router.models import
|
|
8
|
+
from gpt_router.models import (
|
|
9
|
+
ImageGenerationRequest,
|
|
10
|
+
ImageGenerationResponse,
|
|
11
|
+
ModelGenerationRequest,
|
|
12
|
+
GenerationResponse,
|
|
13
|
+
ChunkedGenerationResponse,
|
|
14
|
+
)
|
|
15
|
+
from gpt_router.exceptions import (
|
|
16
|
+
GPTRouterApiTimeoutError,
|
|
17
|
+
GPTRouterBadRequestError,
|
|
18
|
+
GPTRouterStreamingError,
|
|
19
|
+
GPTRouterForbiddenError,
|
|
20
|
+
GPTRouterInternalServerError,
|
|
21
|
+
GPTRouterNotAvailableError,
|
|
22
|
+
GPTRouterTooManyRequestsError,
|
|
23
|
+
GPTRouterUnauthorizedError,
|
|
24
|
+
)
|
|
9
25
|
from gpt_router.constants import DEFAULT_REQUEST_TIMEOUT
|
|
10
26
|
|
|
11
27
|
logger = logging.getLogger(__name__)
|
|
12
28
|
|
|
29
|
+
STATUS_CODE_EXCEPTION_MAPPING = {
|
|
30
|
+
400: GPTRouterBadRequestError,
|
|
31
|
+
406: GPTRouterNotAvailableError,
|
|
32
|
+
401: GPTRouterUnauthorizedError,
|
|
33
|
+
403: GPTRouterForbiddenError,
|
|
34
|
+
429: GPTRouterTooManyRequestsError,
|
|
35
|
+
500: GPTRouterInternalServerError,
|
|
36
|
+
503: GPTRouterNotAvailableError,
|
|
37
|
+
}
|
|
38
|
+
|
|
13
39
|
|
|
14
40
|
class GPTRouterClient:
|
|
15
41
|
models = None
|
|
@@ -35,17 +61,17 @@ class GPTRouterClient:
|
|
|
35
61
|
)
|
|
36
62
|
if response.status_code == 200:
|
|
37
63
|
return response.json()
|
|
38
|
-
elif
|
|
39
|
-
response.status_code == 202
|
|
40
|
-
or response.status_code == 204
|
|
41
|
-
):
|
|
64
|
+
elif response.status_code == 202 or response.status_code == 204:
|
|
42
65
|
return None
|
|
43
66
|
else:
|
|
44
|
-
|
|
67
|
+
error_class = STATUS_CODE_EXCEPTION_MAPPING.get(
|
|
68
|
+
response.status_code, Exception
|
|
69
|
+
)
|
|
70
|
+
raise error_class(response.json())
|
|
45
71
|
except httpx.TimeoutException as err:
|
|
46
72
|
logger.error(f"Timeout error: {err}")
|
|
47
|
-
raise
|
|
48
|
-
|
|
73
|
+
raise GPTRouterApiTimeoutError("Api Request timed out")
|
|
74
|
+
|
|
49
75
|
def _api_call(self, *, path: str, method: str, payload: dict):
|
|
50
76
|
try:
|
|
51
77
|
with httpx.Client() as client:
|
|
@@ -61,16 +87,16 @@ class GPTRouterClient:
|
|
|
61
87
|
)
|
|
62
88
|
if response.status_code == 200:
|
|
63
89
|
return response.json()
|
|
64
|
-
elif
|
|
65
|
-
response.status_code == 202
|
|
66
|
-
or response.status_code == 204
|
|
67
|
-
):
|
|
90
|
+
elif response.status_code == 202 or response.status_code == 204:
|
|
68
91
|
return None
|
|
69
92
|
else:
|
|
70
|
-
|
|
93
|
+
error_class = STATUS_CODE_EXCEPTION_MAPPING.get(
|
|
94
|
+
response.status_code, Exception
|
|
95
|
+
)
|
|
96
|
+
raise error_class(response.json())
|
|
71
97
|
except httpx.TimeoutException as err:
|
|
72
98
|
logger.error(f"Timeout error: {err}")
|
|
73
|
-
raise
|
|
99
|
+
raise GPTRouterApiTimeoutError("Api Request timed out")
|
|
74
100
|
|
|
75
101
|
async def astream_events(self, *, path: str, method: str, payload: dict):
|
|
76
102
|
try:
|
|
@@ -79,7 +105,10 @@ class GPTRouterClient:
|
|
|
79
105
|
method,
|
|
80
106
|
url=f"{self.base_url}/api{path}",
|
|
81
107
|
data=json.dumps(payload),
|
|
82
|
-
headers={
|
|
108
|
+
headers={
|
|
109
|
+
"Content-type": "application/json",
|
|
110
|
+
"ws-secret": self.api_key,
|
|
111
|
+
},
|
|
83
112
|
timeout=self.request_timeout,
|
|
84
113
|
) as response:
|
|
85
114
|
async for line in response.aiter_lines():
|
|
@@ -95,22 +124,30 @@ class GPTRouterClient:
|
|
|
95
124
|
continue
|
|
96
125
|
|
|
97
126
|
data: dict = json.loads(line_data.strip())
|
|
98
|
-
|
|
99
|
-
|
|
127
|
+
if data["event"] == "error":
|
|
128
|
+
raise GPTRouterStreamingError(data)
|
|
129
|
+
yield parse_obj_as(ChunkedGenerationResponse, data)
|
|
130
|
+
except GPTRouterStreamingError as e:
|
|
131
|
+
raise e
|
|
100
132
|
except Exception:
|
|
101
133
|
continue
|
|
102
134
|
except httpx.TimeoutException as err:
|
|
103
135
|
logger.error(f"Timeout error: {err}")
|
|
104
136
|
raise TimeoutError("Request timed out")
|
|
105
137
|
|
|
106
|
-
def stream_events(
|
|
138
|
+
def stream_events(
|
|
139
|
+
self, *, path: str, method: str, payload: dict
|
|
140
|
+
) -> Generator[ChunkedGenerationResponse]:
|
|
107
141
|
try:
|
|
108
142
|
with httpx.Client() as client:
|
|
109
143
|
with client.stream(
|
|
110
144
|
method=method,
|
|
111
145
|
url=f"{self.base_url}/api{path}",
|
|
112
146
|
data=json.dumps(payload),
|
|
113
|
-
headers={
|
|
147
|
+
headers={
|
|
148
|
+
"Content-type": "application/json",
|
|
149
|
+
"ws-secret": self.api_key,
|
|
150
|
+
},
|
|
114
151
|
timeout=self.request_timeout,
|
|
115
152
|
) as response:
|
|
116
153
|
for line in response.iter_lines():
|
|
@@ -125,19 +162,31 @@ class GPTRouterClient:
|
|
|
125
162
|
continue
|
|
126
163
|
|
|
127
164
|
data = json.loads(line_data.strip())
|
|
128
|
-
|
|
165
|
+
if data["event"].lower() == "error":
|
|
166
|
+
raise GPTRouterStreamingError(data["message"])
|
|
167
|
+
yield parse_obj_as(ChunkedGenerationResponse, data)
|
|
168
|
+
except GPTRouterStreamingError as e:
|
|
169
|
+
raise e
|
|
129
170
|
except Exception:
|
|
130
171
|
continue
|
|
131
172
|
except httpx.TimeoutException as err:
|
|
132
173
|
logger.error(f"Timeout error: {err}")
|
|
133
174
|
raise TimeoutError("Request timed out")
|
|
134
175
|
|
|
135
|
-
def generate(
|
|
176
|
+
def generate(
|
|
177
|
+
self,
|
|
178
|
+
*,
|
|
179
|
+
ordered_generation_requests: List[ModelGenerationRequest],
|
|
180
|
+
is_stream=False,
|
|
181
|
+
) -> Union[GenerationResponse, Generator[ChunkedGenerationResponse]]:
|
|
136
182
|
api_path = "/v1/generate"
|
|
137
183
|
api_method = "POST"
|
|
138
184
|
api_payload = {
|
|
139
185
|
"stream": is_stream,
|
|
140
|
-
"data":
|
|
186
|
+
"data": [
|
|
187
|
+
request.dict(exclude_none=True, by_alias=True)
|
|
188
|
+
for request in ordered_generation_requests
|
|
189
|
+
],
|
|
141
190
|
}
|
|
142
191
|
if is_stream:
|
|
143
192
|
return self.stream_events(
|
|
@@ -145,18 +194,33 @@ class GPTRouterClient:
|
|
|
145
194
|
method=api_method,
|
|
146
195
|
payload=api_payload,
|
|
147
196
|
)
|
|
148
|
-
|
|
197
|
+
result = self._api_call(
|
|
149
198
|
path=api_path,
|
|
150
199
|
method=api_method,
|
|
151
200
|
payload=api_payload,
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
|
|
201
|
+
)
|
|
202
|
+
return parse_obj_as(GenerationResponse, result)
|
|
203
|
+
|
|
204
|
+
async def agenerate(
|
|
205
|
+
self,
|
|
206
|
+
*,
|
|
207
|
+
ordered_generation_requests: List[ModelGenerationRequest],
|
|
208
|
+
is_stream=False,
|
|
209
|
+
tag: Optional[str] = None,
|
|
210
|
+
user_id: Optional[str] = None,
|
|
211
|
+
history_id: Optional[str] = None,
|
|
212
|
+
) -> GenerationResponse:
|
|
155
213
|
api_path = "/v1/generate"
|
|
156
214
|
api_method = "POST"
|
|
157
215
|
api_payload = {
|
|
158
216
|
"stream": is_stream,
|
|
159
|
-
"data":
|
|
217
|
+
"data": [
|
|
218
|
+
request.dict(exclude_none=True, by_alias=True)
|
|
219
|
+
for request in ordered_generation_requests
|
|
220
|
+
],
|
|
221
|
+
"tag": tag,
|
|
222
|
+
"createdByUserId": user_id,
|
|
223
|
+
"historyId": history_id,
|
|
160
224
|
}
|
|
161
225
|
if is_stream:
|
|
162
226
|
return self.astream_events(
|
|
@@ -164,8 +228,30 @@ class GPTRouterClient:
|
|
|
164
228
|
method=api_method,
|
|
165
229
|
payload=api_payload,
|
|
166
230
|
)
|
|
167
|
-
|
|
231
|
+
result = await self._async_api_call(
|
|
232
|
+
path=api_path,
|
|
233
|
+
method=api_method,
|
|
234
|
+
payload=api_payload,
|
|
235
|
+
)
|
|
236
|
+
return parse_obj_as(GenerationResponse, result)
|
|
237
|
+
|
|
238
|
+
async def agenerate_images(
|
|
239
|
+
self, *, image_generation_request: ImageGenerationRequest
|
|
240
|
+
) -> List[ImageGenerationResponse]:
|
|
241
|
+
api_path = "/v1/generate/generate-image"
|
|
242
|
+
api_method = "POST"
|
|
243
|
+
api_payload = image_generation_request.dict()
|
|
244
|
+
|
|
245
|
+
api_response = await self._async_api_call(
|
|
168
246
|
path=api_path,
|
|
169
247
|
method=api_method,
|
|
170
248
|
payload=api_payload,
|
|
171
|
-
)
|
|
249
|
+
)
|
|
250
|
+
generated_images = api_response.get("response", [])
|
|
251
|
+
if isinstance(generated_images, dict):
|
|
252
|
+
generated_images = generated_images.get('artifacts', [])
|
|
253
|
+
|
|
254
|
+
return [
|
|
255
|
+
parse_obj_as(ImageGenerationResponse, generated_img)
|
|
256
|
+
for generated_img in generated_images
|
|
257
|
+
]
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
from collections import namedtuple
|
|
2
|
+
from enum import Enum
|
|
3
|
+
|
|
4
|
+
class ProvidersEnum(Enum):
|
|
5
|
+
OPENAI = "openai"
|
|
6
|
+
CHAT_OPENAI = "chat_openai"
|
|
7
|
+
ANTHROPIC = "anthropic"
|
|
8
|
+
CHAT_ANTHROPIC = "chat_anthropic"
|
|
9
|
+
AZURE_CHAT_OPENAI = "azure_chat_openai"
|
|
10
|
+
COHERE = "cohere"
|
|
11
|
+
DALLE = "dall-e"
|
|
12
|
+
TOGETHER_AI = "together_ai"
|
|
13
|
+
MISTRAL_AI = "mistral_ai"
|
|
14
|
+
PERPLEXITY = "perplexity"
|
|
15
|
+
STABLE_DIFFUSION = "stable-diffusion"
|
|
16
|
+
DALL_E = "dall-e"
|
|
17
|
+
OPENROUTER = "openrouter"
|
|
18
|
+
|
|
19
|
+
class ModelsEnum(Enum):
|
|
20
|
+
OPENAI_GPT_35_TURBO_16K = "gpt-3.5-turbo-16k"
|
|
21
|
+
AZURE_GPT_35_TURBO_16K = "gpt-35-turbo-16k"
|
|
22
|
+
|
|
23
|
+
OPENAI_GPT_35_TURBO_1106 = "gpt-3.5-turbo-1106"
|
|
24
|
+
|
|
25
|
+
OPENAI_GPT_35_TURBO_0613 = "gpt-3.5-turbo-0613"
|
|
26
|
+
|
|
27
|
+
AZURE_GPT_35_TURBO = "gpt-35-turbo"
|
|
28
|
+
|
|
29
|
+
OPENAI_GPT_4 = "gpt-4"
|
|
30
|
+
AZURE_GPT_4 = "gpt-4"
|
|
31
|
+
|
|
32
|
+
OPENAI_GPT_4_0613 = "gpt-4-0613"
|
|
33
|
+
|
|
34
|
+
OPENAI_GPT_4_32K = "gpt-4-32k"
|
|
35
|
+
AZURE_GPT_4_32K = "gpt-4-32k"
|
|
36
|
+
|
|
37
|
+
OPENAI_GPT_35_TURBO_INSTRUCT = "gpt-3.5-turbo-instruct"
|
|
38
|
+
|
|
39
|
+
CLAUDE_INSTANT_12 = "claude-instant-1.2"
|
|
40
|
+
|
|
41
|
+
DALLE_3 = "dall-e-3"
|
|
42
|
+
|
|
43
|
+
STABLE_DIFFUSION_XL = "stable-diffusion-xl-1024-v1-0"
|
|
44
|
+
STABLE_DIFFUSION_V6 = "stable-diffusion-v1-6"
|
|
45
|
+
|
|
46
|
+
class StreamingEventType(Enum):
|
|
47
|
+
UPDATE = "update"
|
|
48
|
+
META = "meta"
|
|
49
|
+
ERROR = "error"
|
|
50
|
+
GENERATION_SOURCE = "generation_source"
|
|
51
|
+
END = "end"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
ModelDetails = namedtuple("ModelDetails", ["provider_name", "model_name"])
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class GPTRouterEngines(Enum):
|
|
58
|
+
OPENAI_GPT_35_TURBO = ModelDetails(
|
|
59
|
+
ProvidersEnum.CHAT_OPENAI.value, "gpt-3.5-turbo"
|
|
60
|
+
)
|
|
61
|
+
OPENAI_GPT_35_TURBO_0613 = ModelDetails(
|
|
62
|
+
ProvidersEnum.CHAT_OPENAI.value, "gpt-3.5-turbo-0613"
|
|
63
|
+
)
|
|
64
|
+
OPENAI_GPT_35_TURBO_1106 = ModelDetails(
|
|
65
|
+
ProvidersEnum.CHAT_OPENAI.value, "gpt-3.5-turbo-1106"
|
|
66
|
+
)
|
|
67
|
+
OPENAI_GPT_35_TURBO_16K_0613 = ModelDetails(
|
|
68
|
+
ProvidersEnum.CHAT_OPENAI.value, "gpt-3.5-turbo-16k-0613"
|
|
69
|
+
)
|
|
70
|
+
OPENAI_GPT_35_TURBO_INSTRUCT = ModelDetails(
|
|
71
|
+
ProvidersEnum.OPENAI.value, "gpt-3.5-turbo-instruct"
|
|
72
|
+
)
|
|
73
|
+
OPENAI_GPT_35_TURBO_0125 = ModelDetails(
|
|
74
|
+
ProvidersEnum.CHAT_OPENAI.value, "gpt-3.5-turbo-0125"
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
OPENAI_GPT_4_0613 = ModelDetails(ProvidersEnum.CHAT_OPENAI.value, "gpt-4-0613")
|
|
78
|
+
OPENAI_GPT_4_TURBO = ModelDetails(
|
|
79
|
+
ProvidersEnum.CHAT_OPENAI.value, "gpt-4-1106-preview"
|
|
80
|
+
)
|
|
81
|
+
OPENAI_GPT_4_TURBO_2024_04_09 = ModelDetails(
|
|
82
|
+
ProvidersEnum.CHAT_OPENAI.value, "gpt-4-turbo-2024-04-09"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
OPENAI_GPT_4_TURBO_0125 = ModelDetails(
|
|
86
|
+
ProvidersEnum.CHAT_OPENAI.value, "gpt-4-0125-preview"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
AZURE_OPENAI_GPT_4_TURBO_0125 = ModelDetails(
|
|
90
|
+
ProvidersEnum.AZURE_CHAT_OPENAI.value, "gpt4-turbo-0125"
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
OPENAI_GPT_4_O = ModelDetails(ProvidersEnum.CHAT_OPENAI.value, "gpt-4o")
|
|
94
|
+
|
|
95
|
+
OPENAI_GPT_4_32K_0613 = ModelDetails(
|
|
96
|
+
ProvidersEnum.CHAT_OPENAI.value, "gpt-4-32k-0613"
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
AZURE_GPT_35_TURBO = ModelDetails(
|
|
100
|
+
ProvidersEnum.AZURE_CHAT_OPENAI.value, "gpt-35-turbo"
|
|
101
|
+
)
|
|
102
|
+
AZURE_GPT_35_TURBO_16K = ModelDetails(
|
|
103
|
+
ProvidersEnum.AZURE_CHAT_OPENAI.value, "gpt-35-turbo-16k"
|
|
104
|
+
)
|
|
105
|
+
AZURE_GPT_35_TURBO_1106 = ModelDetails(
|
|
106
|
+
ProvidersEnum.AZURE_CHAT_OPENAI.value, "gpt-35-turbo-1106"
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
AZURE_GPT_4 = ModelDetails(ProvidersEnum.AZURE_CHAT_OPENAI.value, "gpt-4")
|
|
110
|
+
AZURE_GPT_4_TURBO = ModelDetails(
|
|
111
|
+
ProvidersEnum.AZURE_CHAT_OPENAI.value, "gpt-4-turbo"
|
|
112
|
+
)
|
|
113
|
+
AZURE_GPT_4_32K = ModelDetails(
|
|
114
|
+
ProvidersEnum.AZURE_CHAT_OPENAI.value, "gpt-4-32k"
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
CLAUDE_INSTANT_12 = ModelDetails(
|
|
118
|
+
ProvidersEnum.ANTHROPIC.value, "claude-instant-1.2"
|
|
119
|
+
)
|
|
120
|
+
CLAUDE_2 = ModelDetails(ProvidersEnum.ANTHROPIC.value, "claude-2")
|
|
121
|
+
CLAUDE_21 = ModelDetails(ProvidersEnum.ANTHROPIC.value, "claude-2.1")
|
|
122
|
+
CLAUDE_3_OPUS = ModelDetails(
|
|
123
|
+
ProvidersEnum.ANTHROPIC.value, "claude-3-opus-20240229"
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
MISTRAL_7B = ModelDetails(
|
|
127
|
+
ProvidersEnum.TOGETHER_AI.value, "mistralai/Mistral-7B-Instruct-v0.2"
|
|
128
|
+
)
|
|
129
|
+
MIXTRAL_8X7B = ModelDetails(
|
|
130
|
+
ProvidersEnum.TOGETHER_AI.value, "mistralai/Mixtral-8x7B-Instruct-v0.1"
|
|
131
|
+
)
|
|
132
|
+
LLAMA_2_70B = ModelDetails(
|
|
133
|
+
ProvidersEnum.TOGETHER_AI.value, "togethercomputer/llama-2-70b-chat"
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
MISTRAL_MEDIUM = ModelDetails(ProvidersEnum.MISTRAL_AI.value, "mistral-medium")
|
|
137
|
+
|
|
138
|
+
PPTX_70B_ONLINE = ModelDetails(
|
|
139
|
+
ProvidersEnum.PERPLEXITY.value, "pplx-70b-online"
|
|
140
|
+
)
|
|
141
|
+
PPTX_7B_ONLINE = ModelDetails(ProvidersEnum.PERPLEXITY.value, "pplx-7b-online")
|
|
142
|
+
|
|
143
|
+
STABLE_DIFFUSION_XL = ModelDetails(
|
|
144
|
+
ProvidersEnum.STABLE_DIFFUSION.value, "stable-diffusion-xl-1024-v1-0"
|
|
145
|
+
)
|
|
146
|
+
DALLE_3 = ModelDetails(ProvidersEnum.DALL_E.value, "dall-e-3")
|
|
147
|
+
|
|
148
|
+
LLAMA_3_70B_NITRO = ModelDetails(
|
|
149
|
+
ProvidersEnum.OPENROUTER, "meta-llama/llama-3-70b-instruct:nitro"
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
CLAUDE_3_SONNET = ModelDetails(
|
|
153
|
+
ProvidersEnum.CHAT_ANTHROPIC.value, "claude-3-sonnet-20240229"
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
CLAUDE_3_HAIKU = ModelDetails(
|
|
157
|
+
ProvidersEnum.CHAT_ANTHROPIC.value, "claude-3-haiku-20240307"
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
OPENROUTER_CLAUDE_3_HAIKU = ModelDetails(
|
|
161
|
+
ProvidersEnum.OPENROUTER.value, "anthropic/claude-3-haiku"
|
|
162
|
+
)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
class GPTRouterBadRequestError(Exception):
|
|
2
|
+
"""Exception raised for HTTP status code 400: Bad Request within the GPTRouter.
|
|
3
|
+
|
|
4
|
+
This status code indicates that the GPTRouter could not understand the request due to invalid syntax."""
|
|
5
|
+
|
|
6
|
+
pass
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class GPTRouterNotAvailableError(Exception):
|
|
10
|
+
"""Exception raised when GPTRouter is unavailable"""
|
|
11
|
+
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class GPTRouterUnauthorizedError(Exception):
|
|
16
|
+
"""Exception raised for HTTP status code 401: Unauthorized.
|
|
17
|
+
|
|
18
|
+
This status code indicates that the client must authenticate itself with the correct GPTRouter API Token."""
|
|
19
|
+
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class GPTRouterForbiddenError(Exception):
|
|
24
|
+
"""Exception raised for HTTP status code 403: Forbidden.
|
|
25
|
+
|
|
26
|
+
This status code indicates that the client does not have privileges to perform an action on GPTRouter."""
|
|
27
|
+
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class GPTRouterInternalServerError(Exception):
|
|
32
|
+
"""Exception raised for HTTP status code 500: Internal Server Error within the GPTRouter.
|
|
33
|
+
|
|
34
|
+
This status code indicates a server error at GPTRouter end, as the name suggests."""
|
|
35
|
+
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class GPTRouterTooManyRequestsError(Exception):
|
|
40
|
+
"""Exception raised for status code 429: Too Many Requests.
|
|
41
|
+
|
|
42
|
+
This status code indicates that the user has sent too many requests in a given amount of time."""
|
|
43
|
+
|
|
44
|
+
def __init__(self, message="You are being rate limited"):
|
|
45
|
+
self.message = message
|
|
46
|
+
super().__init__(self.message)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class GPTRouterApiTimeoutError(Exception):
|
|
50
|
+
"""Exception raised for API request timeout within the GPTRouter.
|
|
51
|
+
Indicates that the request took too long to complete."""
|
|
52
|
+
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class GPTRouterStreamingError(Exception):
|
|
57
|
+
"""Exception raised for Errors received during streaming a generation response"""
|
|
58
|
+
|
|
59
|
+
pass
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field
|
|
2
|
+
|
|
3
|
+
from typing import List, Optional, Dict, Any
|
|
4
|
+
from humps import camelize
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def to_camel(string):
|
|
8
|
+
return camelize(string)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class GenerationParams(BaseModel):
|
|
12
|
+
messages: Optional[List[Any]] = None
|
|
13
|
+
max_tokens: Optional[int] = None
|
|
14
|
+
temperature: Optional[float] = None
|
|
15
|
+
top_p: Optional[float] = None
|
|
16
|
+
n: Optional[int] = None
|
|
17
|
+
user: Optional[str] = None
|
|
18
|
+
prompt: Optional[str] = None
|
|
19
|
+
frequency_penalty: Optional[float] = None
|
|
20
|
+
presence_penalty: Optional[float] = None
|
|
21
|
+
functions: Optional[List[Any]] = None
|
|
22
|
+
function_call: Optional[dict] = None
|
|
23
|
+
tools: Optional[List[Any]] = None
|
|
24
|
+
response_format: Optional[Dict[str, Any]] = None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ModelGenerationRequest(BaseModel):
|
|
28
|
+
model_name: str
|
|
29
|
+
provider_name: str
|
|
30
|
+
order: int = Field(int)
|
|
31
|
+
prompt_params: Optional[GenerationParams] = Field(default={})
|
|
32
|
+
|
|
33
|
+
class Config:
|
|
34
|
+
alias_generator = to_camel
|
|
35
|
+
allow_population_by_field_name = True
|
|
36
|
+
protected_namespaces = ()
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class Usage(BaseModel):
|
|
40
|
+
completion_tokens: Optional[int] = None
|
|
41
|
+
prompt_tokens: Optional[int] = None
|
|
42
|
+
total_tokens: Optional[int] = None
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class Choice(BaseModel):
|
|
46
|
+
index: int
|
|
47
|
+
text: str
|
|
48
|
+
finish_reason: str
|
|
49
|
+
role: Optional[str] = None
|
|
50
|
+
function_call: Optional[Any] = None
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class GenerationResponse(BaseModel):
|
|
54
|
+
id: str
|
|
55
|
+
choices: List[Choice]
|
|
56
|
+
model: str
|
|
57
|
+
provider_id: Optional[str] = Field(None, alias="providerId")
|
|
58
|
+
model_id: Optional[str] = Field(None, alias="modelId")
|
|
59
|
+
meta: Optional[Usage]
|
|
60
|
+
|
|
61
|
+
class Config:
|
|
62
|
+
alias_generator = to_camel
|
|
63
|
+
allow_population_by_field_name = True
|
|
64
|
+
protected_namespaces = ()
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class ChunkedGenerationResponse(BaseModel):
|
|
68
|
+
event: str
|
|
69
|
+
data: dict
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class ImageGenerationRequest(BaseModel):
|
|
73
|
+
model_name: str = Field(alias="model")
|
|
74
|
+
provider_name: str = Field(alias="imageVendor")
|
|
75
|
+
prompt: str
|
|
76
|
+
num_images: int = Field(alias="numImages", default=1)
|
|
77
|
+
width: Optional[int] = Field(None, alias="width")
|
|
78
|
+
height: Optional[int] = Field(None, alias="height")
|
|
79
|
+
|
|
80
|
+
class Config:
|
|
81
|
+
allow_population_by_field_name = True
|
|
82
|
+
protected_namespaces = ()
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def size(self) -> Optional[str]:
|
|
86
|
+
return f"{self.width}x{self.height}" if self.width and self.height else None
|
|
87
|
+
|
|
88
|
+
def dict(self, *args, **kwargs):
|
|
89
|
+
base_dict = super().dict(*args, **kwargs, exclude_none=True, by_alias=True)
|
|
90
|
+
if self.size is not None:
|
|
91
|
+
base_dict["size"] = self.size
|
|
92
|
+
return base_dict
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class ImageGenerationResponse(BaseModel):
|
|
96
|
+
url: str = None
|
|
97
|
+
base64: str = None
|
|
98
|
+
finish_reason: Optional[str] = Field(default="SUCCESS", alias='finishReason')
|
GPTRouter-0.2.5/setup.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from setuptools import setup
|
|
2
|
+
|
|
3
|
+
with open("README.md", "r") as fh:
|
|
4
|
+
long_description = fh.read()
|
|
5
|
+
|
|
6
|
+
setup(
|
|
7
|
+
name="GPTRouter",
|
|
8
|
+
version="0.2.5",
|
|
9
|
+
description="A Python package for working with GPTRouter APIs",
|
|
10
|
+
long_description=long_description,
|
|
11
|
+
long_description_content_type="text/markdown",
|
|
12
|
+
author_email="sirjanpreet@writesonic.com",
|
|
13
|
+
packages=["gpt_router"],
|
|
14
|
+
install_requires=["httpx>=0.23.3", "pydantic>=1.10.13", "pyhumps>=3.8.0"],
|
|
15
|
+
classifiers=[
|
|
16
|
+
"Development Status :: 3 - Alpha",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.10",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
],
|
|
22
|
+
)
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
from enum import Enum
|
|
2
|
-
|
|
3
|
-
class ProvidersEnum(Enum):
|
|
4
|
-
OPENAI = "openai"
|
|
5
|
-
CHAT_OPENAI = "chat_openai"
|
|
6
|
-
ANTHROPIC = "anthropic"
|
|
7
|
-
AZURE_CHAT_OPENAI = "azure_chat_openai"
|
|
8
|
-
COHERE = "cohere"
|
|
9
|
-
|
|
10
|
-
class ModelsEnum(Enum):
|
|
11
|
-
OPENAI_GPT_35_TURBO_16K = "gpt-3.5-turbo-16k"
|
|
12
|
-
AZURE_GPT_35_TURBO_16K = "gpt-35-turbo-16k"
|
|
13
|
-
|
|
14
|
-
OPENAI_GPT_35_TURBO_1106 = "gpt-3.5-turbo-1106"
|
|
15
|
-
|
|
16
|
-
OPENAI_GPT_35_TURBO_0613 = "gpt-3.5-turbo-0613"
|
|
17
|
-
|
|
18
|
-
OPENAI_GPT_35_TURBO = "gpt-3.5-turbo"
|
|
19
|
-
AZURE_GPT_35_TURBO = "gpt-35-turbo"
|
|
20
|
-
|
|
21
|
-
OPENAI_GPT_4 = "gpt-4"
|
|
22
|
-
AZURE_GPT_4 = "gpt-4"
|
|
23
|
-
|
|
24
|
-
OPENAI_GPT_4_0613 = "gpt-4-0613"
|
|
25
|
-
|
|
26
|
-
OPENAI_GPT_4_32K = "gpt-4-32k"
|
|
27
|
-
AZURE_GPT_4_32K = "gpt-4-32k"
|
|
28
|
-
|
|
29
|
-
OPENAI_GPT_35_TURBO_INSTRUCT = "gpt-3.5-turbo-instruct"
|
|
30
|
-
|
|
31
|
-
CLAUDE_INSTANT_12 = "claude-instant-1.2"
|
|
32
|
-
|
|
33
|
-
class StreamingEventType(Enum):
|
|
34
|
-
UPDATE = "update"
|
|
35
|
-
META = "meta"
|
|
36
|
-
ERROR = "error"
|
|
37
|
-
GENERATION_SOURCE = "generation_source"
|
|
38
|
-
END = "end"
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
from pydantic import BaseModel, Field
|
|
2
|
-
|
|
3
|
-
from typing import List, Optional, Dict, Any
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class GenerationParams(BaseModel):
|
|
7
|
-
messages: Optional[List[Dict[str, str]]] = None
|
|
8
|
-
max_tokens: Optional[int] = None
|
|
9
|
-
temperature: Optional[float] = 0.7
|
|
10
|
-
top_p: Optional[float] = None
|
|
11
|
-
n: Optional[int] = None
|
|
12
|
-
user: Optional[str] = None
|
|
13
|
-
prompt: Optional[str] = None
|
|
14
|
-
frequency_penalty: Optional[float] = None
|
|
15
|
-
presence_penalty: Optional[float] = None
|
|
16
|
-
functions: Optional[List[str]] = []
|
|
17
|
-
function_call: Optional[str] = None
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class ModelGenerationRequest(BaseModel):
|
|
21
|
-
model_name: str = Field(alias='modelName')
|
|
22
|
-
provider_name: str = Field(alias='providerName')
|
|
23
|
-
order: int = Field(int)
|
|
24
|
-
prompt_params: Optional[GenerationParams] = Field(default={}, alias="promptParams")
|
|
25
|
-
|
|
26
|
-
class Config:
|
|
27
|
-
populate_by_name = True
|
|
28
|
-
|
|
29
|
-
class Usage(BaseModel):
|
|
30
|
-
completion_tokens: Optional[int] = None
|
|
31
|
-
prompt_tokens: Optional[int] = None
|
|
32
|
-
total_tokens: Optional[int] = None
|
|
33
|
-
|
|
34
|
-
class Choice(BaseModel):
|
|
35
|
-
index: int
|
|
36
|
-
text: str
|
|
37
|
-
finish_reason: str
|
|
38
|
-
role: Optional[str] = None
|
|
39
|
-
function_call: Optional[Any] = None
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
class GenerationResponse(BaseModel):
|
|
43
|
-
id: str
|
|
44
|
-
choices: List[Choice]
|
|
45
|
-
model: str
|
|
46
|
-
provider_id: Optional[str] = Field(None, alias='providerId')
|
|
47
|
-
model_id: Optional[str] = Field(None, alias='modelId')
|
|
48
|
-
meta: Optional[Usage]
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
class ChunkedGenerationResponse(BaseModel):
|
|
52
|
-
event: str
|
|
53
|
-
data: dict
|
GPTRouter-0.0.2/setup.py
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
from setuptools import setup
|
|
2
|
-
|
|
3
|
-
with open("README.md", "r") as fh:
|
|
4
|
-
long_description = fh.read()
|
|
5
|
-
|
|
6
|
-
setup(
|
|
7
|
-
name='GPTRouter',
|
|
8
|
-
version='0.0.2',
|
|
9
|
-
description='A Python package for working with GPTRouter APIs',
|
|
10
|
-
long_description=long_description,
|
|
11
|
-
long_description_content_type="text/markdown",
|
|
12
|
-
author_email='sirjanpreet.ext@writesonic.com',
|
|
13
|
-
packages=['gpt_router'],
|
|
14
|
-
install_requires=[
|
|
15
|
-
'httpx>=0.25.2',
|
|
16
|
-
"pydantic==2.5.2"
|
|
17
|
-
],
|
|
18
|
-
classifiers=[
|
|
19
|
-
'Development Status :: 3 - Alpha',
|
|
20
|
-
'Intended Audience :: Developers',
|
|
21
|
-
'Programming Language :: Python :: 3',
|
|
22
|
-
'Programming Language :: Python :: 3.10',
|
|
23
|
-
'Programming Language :: Python :: 3.11',
|
|
24
|
-
],
|
|
25
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|