GPTRouter 0.1.2__tar.gz → 0.1.3__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.1.2 → GPTRouter-0.1.3}/GPTRouter.egg-info/PKG-INFO +1 -1
- {GPTRouter-0.1.2 → GPTRouter-0.1.3}/GPTRouter.egg-info/SOURCES.txt +1 -0
- {GPTRouter-0.1.2 → GPTRouter-0.1.3}/PKG-INFO +1 -1
- {GPTRouter-0.1.2 → GPTRouter-0.1.3}/gpt_router/client.py +92 -33
- GPTRouter-0.1.3/gpt_router/exceptions.py +59 -0
- {GPTRouter-0.1.2 → GPTRouter-0.1.3}/setup.py +1 -1
- {GPTRouter-0.1.2 → GPTRouter-0.1.3}/GPTRouter.egg-info/dependency_links.txt +0 -0
- {GPTRouter-0.1.2 → GPTRouter-0.1.3}/GPTRouter.egg-info/requires.txt +0 -0
- {GPTRouter-0.1.2 → GPTRouter-0.1.3}/GPTRouter.egg-info/top_level.txt +0 -0
- {GPTRouter-0.1.2 → GPTRouter-0.1.3}/LICENSE +0 -0
- {GPTRouter-0.1.2 → GPTRouter-0.1.3}/README.md +0 -0
- {GPTRouter-0.1.2 → GPTRouter-0.1.3}/gpt_router/__init__.py +0 -0
- {GPTRouter-0.1.2 → GPTRouter-0.1.3}/gpt_router/constants.py +0 -0
- {GPTRouter-0.1.2 → GPTRouter-0.1.3}/gpt_router/enums.py +0 -0
- {GPTRouter-0.1.2 → GPTRouter-0.1.3}/gpt_router/models.py +0 -0
- {GPTRouter-0.1.2 → GPTRouter-0.1.3}/pyproject.toml +0 -0
- {GPTRouter-0.1.2 → GPTRouter-0.1.3}/setup.cfg +0 -0
|
@@ -5,11 +5,35 @@ import json
|
|
|
5
5
|
import httpx
|
|
6
6
|
from typing import Generator, List, Union
|
|
7
7
|
|
|
8
|
-
from gpt_router.models import
|
|
8
|
+
from gpt_router.models import (
|
|
9
|
+
ModelGenerationRequest,
|
|
10
|
+
GenerationResponse,
|
|
11
|
+
ChunkedGenerationResponse,
|
|
12
|
+
)
|
|
13
|
+
from gpt_router.exceptions import (
|
|
14
|
+
GPTRouterApiTimeoutError,
|
|
15
|
+
GPTRouterBadRequestError,
|
|
16
|
+
GPTRouterStreamingError,
|
|
17
|
+
GPTRouterForbiddenError,
|
|
18
|
+
GPTRouterInternalServerError,
|
|
19
|
+
GPTRouterNotAvailableError,
|
|
20
|
+
GPTRouterTooManyRequestsError,
|
|
21
|
+
GPTRouterUnauthorizedError,
|
|
22
|
+
)
|
|
9
23
|
from gpt_router.constants import DEFAULT_REQUEST_TIMEOUT
|
|
10
24
|
|
|
11
25
|
logger = logging.getLogger(__name__)
|
|
12
26
|
|
|
27
|
+
STATUS_CODE_EXCEPTION_MAPPING = {
|
|
28
|
+
400: GPTRouterBadRequestError,
|
|
29
|
+
406: GPTRouterNotAvailableError,
|
|
30
|
+
401: GPTRouterUnauthorizedError,
|
|
31
|
+
403: GPTRouterForbiddenError,
|
|
32
|
+
429: GPTRouterTooManyRequestsError,
|
|
33
|
+
500: GPTRouterInternalServerError,
|
|
34
|
+
503: GPTRouterNotAvailableError,
|
|
35
|
+
}
|
|
36
|
+
|
|
13
37
|
|
|
14
38
|
class GPTRouterClient:
|
|
15
39
|
models = None
|
|
@@ -35,17 +59,17 @@ class GPTRouterClient:
|
|
|
35
59
|
)
|
|
36
60
|
if response.status_code == 200:
|
|
37
61
|
return response.json()
|
|
38
|
-
elif
|
|
39
|
-
response.status_code == 202
|
|
40
|
-
or response.status_code == 204
|
|
41
|
-
):
|
|
62
|
+
elif response.status_code == 202 or response.status_code == 204:
|
|
42
63
|
return None
|
|
43
64
|
else:
|
|
44
|
-
|
|
65
|
+
error_class = STATUS_CODE_EXCEPTION_MAPPING.get(
|
|
66
|
+
response.status_code, Exception
|
|
67
|
+
)
|
|
68
|
+
raise error_class(response.json())
|
|
45
69
|
except httpx.TimeoutException as err:
|
|
46
70
|
logger.error(f"Timeout error: {err}")
|
|
47
|
-
raise
|
|
48
|
-
|
|
71
|
+
raise GPTRouterApiTimeoutError("Api Request timed out")
|
|
72
|
+
|
|
49
73
|
def _api_call(self, *, path: str, method: str, payload: dict):
|
|
50
74
|
try:
|
|
51
75
|
with httpx.Client() as client:
|
|
@@ -61,16 +85,16 @@ class GPTRouterClient:
|
|
|
61
85
|
)
|
|
62
86
|
if response.status_code == 200:
|
|
63
87
|
return response.json()
|
|
64
|
-
elif
|
|
65
|
-
response.status_code == 202
|
|
66
|
-
or response.status_code == 204
|
|
67
|
-
):
|
|
88
|
+
elif response.status_code == 202 or response.status_code == 204:
|
|
68
89
|
return None
|
|
69
90
|
else:
|
|
70
|
-
|
|
91
|
+
error_class = STATUS_CODE_EXCEPTION_MAPPING.get(
|
|
92
|
+
response.status_code, Exception
|
|
93
|
+
)
|
|
94
|
+
raise error_class(response.json())
|
|
71
95
|
except httpx.TimeoutException as err:
|
|
72
96
|
logger.error(f"Timeout error: {err}")
|
|
73
|
-
raise
|
|
97
|
+
raise GPTRouterApiTimeoutError("Api Request timed out")
|
|
74
98
|
|
|
75
99
|
async def astream_events(self, *, path: str, method: str, payload: dict):
|
|
76
100
|
try:
|
|
@@ -79,7 +103,10 @@ class GPTRouterClient:
|
|
|
79
103
|
method,
|
|
80
104
|
url=f"{self.base_url}/api{path}",
|
|
81
105
|
data=json.dumps(payload),
|
|
82
|
-
headers={
|
|
106
|
+
headers={
|
|
107
|
+
"Content-type": "application/json",
|
|
108
|
+
"ws-secret": self.api_key,
|
|
109
|
+
},
|
|
83
110
|
timeout=self.request_timeout,
|
|
84
111
|
) as response:
|
|
85
112
|
async for line in response.aiter_lines():
|
|
@@ -95,22 +122,30 @@ class GPTRouterClient:
|
|
|
95
122
|
continue
|
|
96
123
|
|
|
97
124
|
data: dict = json.loads(line_data.strip())
|
|
98
|
-
|
|
125
|
+
if data["event"] == "error":
|
|
126
|
+
raise GPTRouterStreamingError(data)
|
|
99
127
|
yield ChunkedGenerationResponse.model_validate(data)
|
|
128
|
+
except GPTRouterStreamingError as e:
|
|
129
|
+
raise e
|
|
100
130
|
except Exception:
|
|
101
131
|
continue
|
|
102
132
|
except httpx.TimeoutException as err:
|
|
103
133
|
logger.error(f"Timeout error: {err}")
|
|
104
134
|
raise TimeoutError("Request timed out")
|
|
105
135
|
|
|
106
|
-
def stream_events(
|
|
136
|
+
def stream_events(
|
|
137
|
+
self, *, path: str, method: str, payload: dict
|
|
138
|
+
) -> Generator[ChunkedGenerationResponse]:
|
|
107
139
|
try:
|
|
108
140
|
with httpx.Client() as client:
|
|
109
141
|
with client.stream(
|
|
110
142
|
method=method,
|
|
111
143
|
url=f"{self.base_url}/api{path}",
|
|
112
144
|
data=json.dumps(payload),
|
|
113
|
-
headers={
|
|
145
|
+
headers={
|
|
146
|
+
"Content-type": "application/json",
|
|
147
|
+
"ws-secret": self.api_key,
|
|
148
|
+
},
|
|
114
149
|
timeout=self.request_timeout,
|
|
115
150
|
) as response:
|
|
116
151
|
for line in response.iter_lines():
|
|
@@ -125,19 +160,31 @@ class GPTRouterClient:
|
|
|
125
160
|
continue
|
|
126
161
|
|
|
127
162
|
data = json.loads(line_data.strip())
|
|
163
|
+
if data["event"].lower() == "error":
|
|
164
|
+
raise GPTRouterStreamingError(data["message"])
|
|
128
165
|
yield ChunkedGenerationResponse.model_validate(data)
|
|
166
|
+
except GPTRouterStreamingError as e:
|
|
167
|
+
raise e
|
|
129
168
|
except Exception:
|
|
130
169
|
continue
|
|
131
170
|
except httpx.TimeoutException as err:
|
|
132
171
|
logger.error(f"Timeout error: {err}")
|
|
133
172
|
raise TimeoutError("Request timed out")
|
|
134
173
|
|
|
135
|
-
def generate(
|
|
174
|
+
def generate(
|
|
175
|
+
self,
|
|
176
|
+
*,
|
|
177
|
+
ordered_generation_requests: List[ModelGenerationRequest],
|
|
178
|
+
is_stream=False,
|
|
179
|
+
) -> Union[GenerationResponse, Generator[ChunkedGenerationResponse]]:
|
|
136
180
|
api_path = "/v1/generate"
|
|
137
181
|
api_method = "POST"
|
|
138
182
|
api_payload = {
|
|
139
183
|
"stream": is_stream,
|
|
140
|
-
"data":
|
|
184
|
+
"data": [
|
|
185
|
+
request.model_dump(exclude_none=True, by_alias=True)
|
|
186
|
+
for request in ordered_generation_requests
|
|
187
|
+
],
|
|
141
188
|
}
|
|
142
189
|
if is_stream:
|
|
143
190
|
return self.stream_events(
|
|
@@ -145,18 +192,28 @@ class GPTRouterClient:
|
|
|
145
192
|
method=api_method,
|
|
146
193
|
payload=api_payload,
|
|
147
194
|
)
|
|
148
|
-
return GenerationResponse.model_validate(
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
195
|
+
return GenerationResponse.model_validate(
|
|
196
|
+
self._api_call(
|
|
197
|
+
path=api_path,
|
|
198
|
+
method=api_method,
|
|
199
|
+
payload=api_payload,
|
|
200
|
+
)
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
async def agenerate(
|
|
204
|
+
self,
|
|
205
|
+
*,
|
|
206
|
+
ordered_generation_requests: List[ModelGenerationRequest],
|
|
207
|
+
is_stream=False,
|
|
208
|
+
) -> GenerationResponse:
|
|
155
209
|
api_path = "/v1/generate"
|
|
156
210
|
api_method = "POST"
|
|
157
211
|
api_payload = {
|
|
158
212
|
"stream": is_stream,
|
|
159
|
-
"data":
|
|
213
|
+
"data": [
|
|
214
|
+
request.model_dump(exclude_none=True, by_alias=True)
|
|
215
|
+
for request in ordered_generation_requests
|
|
216
|
+
],
|
|
160
217
|
}
|
|
161
218
|
if is_stream:
|
|
162
219
|
return self.astream_events(
|
|
@@ -164,8 +221,10 @@ class GPTRouterClient:
|
|
|
164
221
|
method=api_method,
|
|
165
222
|
payload=api_payload,
|
|
166
223
|
)
|
|
167
|
-
return GenerationResponse.model_validate(
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
224
|
+
return GenerationResponse.model_validate(
|
|
225
|
+
await self._async_api_call(
|
|
226
|
+
path=api_path,
|
|
227
|
+
method=api_method,
|
|
228
|
+
payload=api_payload,
|
|
229
|
+
)
|
|
230
|
+
)
|
|
@@ -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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|