GPTRouter 1.0.4__tar.gz → 1.0.6__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-1.0.4 → gptrouter-1.0.6}/GPTRouter.egg-info/PKG-INFO +16 -6
- {GPTRouter-1.0.4 → gptrouter-1.0.6}/GPTRouter.egg-info/requires.txt +1 -1
- {GPTRouter-1.0.4 → gptrouter-1.0.6}/PKG-INFO +16 -6
- {GPTRouter-1.0.4 → gptrouter-1.0.6}/README.md +4 -4
- {GPTRouter-1.0.4 → gptrouter-1.0.6}/gpt_router/client.py +38 -15
- gptrouter-1.0.6/gpt_router/constants.py +2 -0
- {GPTRouter-1.0.4 → gptrouter-1.0.6}/gpt_router/enums.py +5 -0
- {GPTRouter-1.0.4 → gptrouter-1.0.6}/gpt_router/models.py +21 -31
- {GPTRouter-1.0.4 → gptrouter-1.0.6}/pyproject.toml +9 -4
- {GPTRouter-1.0.4 → gptrouter-1.0.6}/setup.py +2 -2
- GPTRouter-1.0.4/gpt_router/constants.py +0 -2
- {GPTRouter-1.0.4 → gptrouter-1.0.6}/GPTRouter.egg-info/SOURCES.txt +0 -0
- {GPTRouter-1.0.4 → gptrouter-1.0.6}/GPTRouter.egg-info/dependency_links.txt +0 -0
- {GPTRouter-1.0.4 → gptrouter-1.0.6}/GPTRouter.egg-info/top_level.txt +0 -0
- {GPTRouter-1.0.4 → gptrouter-1.0.6}/LICENSE +0 -0
- {GPTRouter-1.0.4 → gptrouter-1.0.6}/gpt_router/__init__.py +0 -0
- {GPTRouter-1.0.4 → gptrouter-1.0.6}/gpt_router/exceptions.py +0 -0
- {GPTRouter-1.0.4 → gptrouter-1.0.6}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: GPTRouter
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.6
|
|
4
4
|
Summary: A Python package for working with GPTRouter APIs
|
|
5
5
|
Author-email: sirjanpreet@writesonic.com
|
|
6
6
|
Classifier: Development Status :: 3 - Alpha
|
|
@@ -10,6 +10,16 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
10
10
|
Classifier: Programming Language :: Python :: 3.11
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
12
|
License-File: LICENSE
|
|
13
|
+
Requires-Dist: httpx>=0.23.3
|
|
14
|
+
Requires-Dist: pydantic>=2.0
|
|
15
|
+
Requires-Dist: pyhumps>=3.8.0
|
|
16
|
+
Dynamic: author-email
|
|
17
|
+
Dynamic: classifier
|
|
18
|
+
Dynamic: description
|
|
19
|
+
Dynamic: description-content-type
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
Dynamic: requires-dist
|
|
22
|
+
Dynamic: summary
|
|
13
23
|
|
|
14
24
|
# GPTRouter Python Client
|
|
15
25
|
|
|
@@ -37,14 +47,14 @@ messages = [
|
|
|
37
47
|
{"role": "user", "content": "Write me a short poem"},
|
|
38
48
|
]
|
|
39
49
|
prompt_params = GenerationParams(messages=messages)
|
|
40
|
-
|
|
41
|
-
model_name=ModelsEnum.
|
|
42
|
-
provider_name=ProvidersEnum.
|
|
50
|
+
claude_request = ModelGenerationRequest(
|
|
51
|
+
model_name=ModelsEnum.CLAUDE_4_5_HAIKU.value,
|
|
52
|
+
provider_name=ProvidersEnum.CHAT_ANTHROPIC.value,
|
|
43
53
|
order=1,
|
|
44
54
|
prompt_params=prompt_params,
|
|
45
55
|
)
|
|
46
56
|
|
|
47
|
-
response = client.generate(ordered_generation_requests=[
|
|
57
|
+
response = client.generate(ordered_generation_requests=[claude_request])
|
|
48
58
|
print(response.choices[0].text)
|
|
49
59
|
```
|
|
50
60
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: GPTRouter
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.6
|
|
4
4
|
Summary: A Python package for working with GPTRouter APIs
|
|
5
5
|
Author-email: sirjanpreet@writesonic.com
|
|
6
6
|
Classifier: Development Status :: 3 - Alpha
|
|
@@ -10,6 +10,16 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
10
10
|
Classifier: Programming Language :: Python :: 3.11
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
12
|
License-File: LICENSE
|
|
13
|
+
Requires-Dist: httpx>=0.23.3
|
|
14
|
+
Requires-Dist: pydantic>=2.0
|
|
15
|
+
Requires-Dist: pyhumps>=3.8.0
|
|
16
|
+
Dynamic: author-email
|
|
17
|
+
Dynamic: classifier
|
|
18
|
+
Dynamic: description
|
|
19
|
+
Dynamic: description-content-type
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
Dynamic: requires-dist
|
|
22
|
+
Dynamic: summary
|
|
13
23
|
|
|
14
24
|
# GPTRouter Python Client
|
|
15
25
|
|
|
@@ -37,14 +47,14 @@ messages = [
|
|
|
37
47
|
{"role": "user", "content": "Write me a short poem"},
|
|
38
48
|
]
|
|
39
49
|
prompt_params = GenerationParams(messages=messages)
|
|
40
|
-
|
|
41
|
-
model_name=ModelsEnum.
|
|
42
|
-
provider_name=ProvidersEnum.
|
|
50
|
+
claude_request = ModelGenerationRequest(
|
|
51
|
+
model_name=ModelsEnum.CLAUDE_4_5_HAIKU.value,
|
|
52
|
+
provider_name=ProvidersEnum.CHAT_ANTHROPIC.value,
|
|
43
53
|
order=1,
|
|
44
54
|
prompt_params=prompt_params,
|
|
45
55
|
)
|
|
46
56
|
|
|
47
|
-
response = client.generate(ordered_generation_requests=[
|
|
57
|
+
response = client.generate(ordered_generation_requests=[claude_request])
|
|
48
58
|
print(response.choices[0].text)
|
|
49
59
|
```
|
|
50
60
|
|
|
@@ -24,14 +24,14 @@ messages = [
|
|
|
24
24
|
{"role": "user", "content": "Write me a short poem"},
|
|
25
25
|
]
|
|
26
26
|
prompt_params = GenerationParams(messages=messages)
|
|
27
|
-
|
|
28
|
-
model_name=ModelsEnum.
|
|
29
|
-
provider_name=ProvidersEnum.
|
|
27
|
+
claude_request = ModelGenerationRequest(
|
|
28
|
+
model_name=ModelsEnum.CLAUDE_4_5_HAIKU.value,
|
|
29
|
+
provider_name=ProvidersEnum.CHAT_ANTHROPIC.value,
|
|
30
30
|
order=1,
|
|
31
31
|
prompt_params=prompt_params,
|
|
32
32
|
)
|
|
33
33
|
|
|
34
|
-
response = client.generate(ordered_generation_requests=[
|
|
34
|
+
response = client.generate(ordered_generation_requests=[claude_request])
|
|
35
35
|
print(response.choices[0].text)
|
|
36
36
|
```
|
|
37
37
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
import asyncio
|
|
3
|
-
from pydantic import
|
|
3
|
+
from pydantic import TypeAdapter
|
|
4
4
|
import logging
|
|
5
5
|
import json
|
|
6
6
|
import httpx
|
|
@@ -86,7 +86,7 @@ class GPTRouterClient:
|
|
|
86
86
|
api_payload = {
|
|
87
87
|
"data": [
|
|
88
88
|
{
|
|
89
|
-
**request.
|
|
89
|
+
**request.model_dump(),
|
|
90
90
|
"order": index + 1,
|
|
91
91
|
}
|
|
92
92
|
for index, request in enumerate(ordered_generation_requests)
|
|
@@ -98,7 +98,30 @@ class GPTRouterClient:
|
|
|
98
98
|
method="POST",
|
|
99
99
|
payload=api_payload,
|
|
100
100
|
)
|
|
101
|
-
return ModelRouterEmbeddingsGenerationResponse.
|
|
101
|
+
return ModelRouterEmbeddingsGenerationResponse.model_validate(response)
|
|
102
|
+
|
|
103
|
+
async def agenerate_embeddings_v2(
|
|
104
|
+
self,
|
|
105
|
+
*,
|
|
106
|
+
input: List[str],
|
|
107
|
+
model_name: str,
|
|
108
|
+
model_router_metadata: Optional[GPTRouterMetadata] = None,
|
|
109
|
+
) -> ModelRouterEmbeddingsGenerationResponse:
|
|
110
|
+
"""
|
|
111
|
+
Generate embeddings using the v2 endpoint which uses round-robin load balancing
|
|
112
|
+
across multiple providers for improved availability and performance.
|
|
113
|
+
"""
|
|
114
|
+
api_payload = {
|
|
115
|
+
"input": input,
|
|
116
|
+
"modelName": model_name,
|
|
117
|
+
}
|
|
118
|
+
api_payload = self.add_metadata_info(api_payload, model_router_metadata)
|
|
119
|
+
response = await self._async_api_call(
|
|
120
|
+
path="/v1/generate/embeddings-v2",
|
|
121
|
+
method="POST",
|
|
122
|
+
payload=api_payload,
|
|
123
|
+
)
|
|
124
|
+
return ModelRouterEmbeddingsGenerationResponse.model_validate(response)
|
|
102
125
|
|
|
103
126
|
def add_metadata_info(
|
|
104
127
|
self,
|
|
@@ -107,9 +130,9 @@ class GPTRouterClient:
|
|
|
107
130
|
):
|
|
108
131
|
metadata = {}
|
|
109
132
|
if self.additional_metadata:
|
|
110
|
-
metadata.update(self.additional_metadata.
|
|
133
|
+
metadata.update(self.additional_metadata.model_dump())
|
|
111
134
|
if model_router_metadata:
|
|
112
|
-
metadata.update(model_router_metadata.
|
|
135
|
+
metadata.update(model_router_metadata.model_dump())
|
|
113
136
|
|
|
114
137
|
payload.update(
|
|
115
138
|
{
|
|
@@ -244,7 +267,7 @@ class GPTRouterClient:
|
|
|
244
267
|
data: dict = json.loads(line_data.strip())
|
|
245
268
|
if data["event"] == "error":
|
|
246
269
|
raise GPTRouterStreamingError(data)
|
|
247
|
-
yield
|
|
270
|
+
yield TypeAdapter(ChunkedGenerationResponse).validate_python(data)
|
|
248
271
|
except GPTRouterStreamingError as e:
|
|
249
272
|
raise e
|
|
250
273
|
except Exception:
|
|
@@ -331,7 +354,7 @@ class GPTRouterClient:
|
|
|
331
354
|
data = json.loads(line_data.strip())
|
|
332
355
|
if data["event"].lower() == "error":
|
|
333
356
|
raise GPTRouterStreamingError(data["message"])
|
|
334
|
-
yield
|
|
357
|
+
yield TypeAdapter(ChunkedGenerationResponse).validate_python(data)
|
|
335
358
|
except GPTRouterStreamingError as e:
|
|
336
359
|
raise e
|
|
337
360
|
except Exception:
|
|
@@ -390,7 +413,7 @@ class GPTRouterClient:
|
|
|
390
413
|
api_payload = {
|
|
391
414
|
"stream": is_stream,
|
|
392
415
|
"data": [
|
|
393
|
-
request.
|
|
416
|
+
request.model_dump(exclude_none=True, by_alias=True)
|
|
394
417
|
for request in ordered_generation_requests
|
|
395
418
|
],
|
|
396
419
|
}
|
|
@@ -408,7 +431,7 @@ class GPTRouterClient:
|
|
|
408
431
|
payload=api_payload,
|
|
409
432
|
**kwargs,
|
|
410
433
|
)
|
|
411
|
-
return
|
|
434
|
+
return TypeAdapter(GenerationResponse).validate_python(result)
|
|
412
435
|
|
|
413
436
|
async def agenerate(
|
|
414
437
|
self,
|
|
@@ -424,7 +447,7 @@ class GPTRouterClient:
|
|
|
424
447
|
api_payload = {
|
|
425
448
|
"stream": is_stream,
|
|
426
449
|
"data": [
|
|
427
|
-
request.
|
|
450
|
+
request.model_dump(exclude_none=True, by_alias=True)
|
|
428
451
|
for request in ordered_generation_requests
|
|
429
452
|
],
|
|
430
453
|
}
|
|
@@ -443,14 +466,14 @@ class GPTRouterClient:
|
|
|
443
466
|
payload=api_payload,
|
|
444
467
|
**kwargs,
|
|
445
468
|
)
|
|
446
|
-
return
|
|
469
|
+
return TypeAdapter(GenerationResponse).validate_python(result)
|
|
447
470
|
|
|
448
471
|
async def agenerate_images(
|
|
449
472
|
self, *, image_generation_request: ImageGenerationRequest
|
|
450
473
|
) -> List[ImageGenerationResponse]:
|
|
451
474
|
api_path = "/v1/generate/generate-image"
|
|
452
475
|
api_method = "POST"
|
|
453
|
-
api_payload = image_generation_request.
|
|
476
|
+
api_payload = image_generation_request.model_dump()
|
|
454
477
|
|
|
455
478
|
api_response = await self._async_api_call(
|
|
456
479
|
path=api_path,
|
|
@@ -462,7 +485,7 @@ class GPTRouterClient:
|
|
|
462
485
|
generated_images = self._extract_images_from_dict(generated_images)
|
|
463
486
|
|
|
464
487
|
return [
|
|
465
|
-
|
|
488
|
+
ImageGenerationResponse.model_validate(generated_img)
|
|
466
489
|
for generated_img in generated_images
|
|
467
490
|
]
|
|
468
491
|
|
|
@@ -496,7 +519,7 @@ class GPTRouterClient:
|
|
|
496
519
|
"""
|
|
497
520
|
api_path = "/v1/generate/edit-image"
|
|
498
521
|
api_method = "POST"
|
|
499
|
-
api_payload = image_edit_request.
|
|
522
|
+
api_payload = image_edit_request.model_dump()
|
|
500
523
|
|
|
501
524
|
api_response = await self._async_api_call(
|
|
502
525
|
path=api_path,
|
|
@@ -507,7 +530,7 @@ class GPTRouterClient:
|
|
|
507
530
|
generated_images = api_response.get("response", {}).get("data", [])
|
|
508
531
|
|
|
509
532
|
return [
|
|
510
|
-
|
|
533
|
+
ImageGenerationResponse.model_validate({
|
|
511
534
|
"url": img.get("url", None),
|
|
512
535
|
"base64": img.get("b64_json", None),
|
|
513
536
|
"finish_reason": "SUCCESS"
|
|
@@ -44,6 +44,7 @@ class ModelsEnum(Enum):
|
|
|
44
44
|
OPENAI_GPT_35_TURBO_INSTRUCT = "gpt-3.5-turbo-instruct"
|
|
45
45
|
|
|
46
46
|
CLAUDE_INSTANT_12 = "claude-instant-1.2"
|
|
47
|
+
CLAUDE_4_5_HAIKU = "claude-haiku-4-5-20251001"
|
|
47
48
|
|
|
48
49
|
DALLE_3 = "dall-e-3"
|
|
49
50
|
|
|
@@ -197,4 +198,8 @@ class GPTRouterEngines(Enum):
|
|
|
197
198
|
|
|
198
199
|
CLAUDE_3_7_SONNET_2025_02_19 = ModelDetails(
|
|
199
200
|
ProvidersEnum.CHAT_ANTHROPIC.value, "claude-3-7-sonnet-2025-02-19"
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
CLAUDE_4_5_HAIKU = ModelDetails(
|
|
204
|
+
ProvidersEnum.CHAT_ANTHROPIC.value, "claude-haiku-4-5-20251001"
|
|
200
205
|
)
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
from
|
|
2
|
-
from pydantic import BaseModel, Field, root_validator, validator
|
|
1
|
+
from pydantic import ConfigDict, BaseModel, Field
|
|
3
2
|
from enum import Enum
|
|
4
3
|
from typing import Dict, List, Literal, Optional, Any, Union
|
|
5
4
|
from humps import camelize
|
|
@@ -83,11 +82,7 @@ class ModelGenerationRequest(BaseModel):
|
|
|
83
82
|
provider_name: str
|
|
84
83
|
order: int = Field(int)
|
|
85
84
|
prompt_params: Optional[GenerationParams] = Field(default={})
|
|
86
|
-
|
|
87
|
-
class Config:
|
|
88
|
-
alias_generator = to_camel
|
|
89
|
-
allow_population_by_field_name = True
|
|
90
|
-
protected_namespaces = ()
|
|
85
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True, protected_namespaces=())
|
|
91
86
|
|
|
92
87
|
|
|
93
88
|
class Usage(BaseModel):
|
|
@@ -111,13 +106,9 @@ class GenerationResponse(BaseModel):
|
|
|
111
106
|
model: str
|
|
112
107
|
provider_id: Optional[str] = Field(None, alias="providerId")
|
|
113
108
|
model_id: Optional[str] = Field(None, alias="modelId")
|
|
114
|
-
meta: Optional[Usage]
|
|
109
|
+
meta: Optional[Usage] = None
|
|
115
110
|
citations: Optional[List[str]] = None
|
|
116
|
-
|
|
117
|
-
class Config:
|
|
118
|
-
alias_generator = to_camel
|
|
119
|
-
allow_population_by_field_name = True
|
|
120
|
-
protected_namespaces = ()
|
|
111
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True, protected_namespaces=())
|
|
121
112
|
|
|
122
113
|
|
|
123
114
|
class ChunkedGenerationResponse(BaseModel):
|
|
@@ -138,17 +129,16 @@ class ImageGenerationRequest(BaseModel):
|
|
|
138
129
|
user_id: Optional[str] = Field(None, alias="createdByUserId")
|
|
139
130
|
history_id: Optional[str] = Field(None, alias="historyId")
|
|
140
131
|
feature: Optional[str] = Field(None, alias="feature")
|
|
141
|
-
|
|
142
|
-
class Config:
|
|
143
|
-
allow_population_by_field_name = True
|
|
144
|
-
protected_namespaces = ()
|
|
132
|
+
model_config = ConfigDict(populate_by_name=True, protected_namespaces=())
|
|
145
133
|
|
|
146
134
|
@property
|
|
147
135
|
def size(self) -> Optional[str]:
|
|
148
136
|
return f"{self.width}x{self.height}" if self.width and self.height else None
|
|
149
137
|
|
|
150
|
-
def
|
|
151
|
-
|
|
138
|
+
def model_dump(self, *args, **kwargs):
|
|
139
|
+
kwargs.setdefault('exclude_none', True)
|
|
140
|
+
kwargs.setdefault('by_alias', True)
|
|
141
|
+
base_dict = super().model_dump(*args, **kwargs)
|
|
152
142
|
if self.size is not None:
|
|
153
143
|
base_dict["size"] = self.size
|
|
154
144
|
return base_dict
|
|
@@ -170,13 +160,12 @@ class ImageEditRequest(BaseModel):
|
|
|
170
160
|
response_format: Optional[str] = Field(alias="responseFormat", default=None)
|
|
171
161
|
size: Optional[str] = Field(default="1024x1024")
|
|
172
162
|
user: Optional[str] = Field(default=None)
|
|
163
|
+
model_config = ConfigDict(populate_by_name=True, protected_namespaces=())
|
|
173
164
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
def dict(self, *args, **kwargs):
|
|
179
|
-
base_dict = super().dict(*args, **kwargs, exclude_none=True, by_alias=True)
|
|
165
|
+
def model_dump(self, *args, **kwargs):
|
|
166
|
+
kwargs.setdefault('exclude_none', True)
|
|
167
|
+
kwargs.setdefault('by_alias', True)
|
|
168
|
+
base_dict = super().model_dump(*args, **kwargs)
|
|
180
169
|
return base_dict
|
|
181
170
|
|
|
182
171
|
|
|
@@ -187,13 +176,13 @@ class ModelRouterGenerationRequest(BaseModel):
|
|
|
187
176
|
should_validate_token_count: Optional[bool] = Field(
|
|
188
177
|
default=False, alias="shouldValidateTokenCount"
|
|
189
178
|
)
|
|
179
|
+
model_config = ConfigDict(populate_by_name=True, protected_namespaces=())
|
|
190
180
|
|
|
191
|
-
|
|
192
|
-
allow_population_by_field_name = True
|
|
193
|
-
|
|
194
|
-
def dict(self, *args, **kwargs):
|
|
181
|
+
def model_dump(self, *args, **kwargs):
|
|
195
182
|
# Generate the standard dict first.
|
|
196
|
-
|
|
183
|
+
kwargs.setdefault('exclude_none', True)
|
|
184
|
+
kwargs.setdefault('by_alias', True)
|
|
185
|
+
result = super().model_dump(*args, **kwargs)
|
|
197
186
|
|
|
198
187
|
result["providerName"] = self.model_provider
|
|
199
188
|
result["modelName"] = self.model_name
|
|
@@ -215,7 +204,8 @@ class ModelRouterGenerationResponse(BaseModel):
|
|
|
215
204
|
model: str
|
|
216
205
|
provider_id: Optional[str] = Field(None, alias="providerId")
|
|
217
206
|
model_id: Optional[str] = Field(None, alias="modelId")
|
|
218
|
-
meta: Optional[Usage]
|
|
207
|
+
meta: Optional[Usage] = None
|
|
208
|
+
model_config = ConfigDict(protected_namespaces=())
|
|
219
209
|
|
|
220
210
|
|
|
221
211
|
class EmbeddingsChoice(BaseModel):
|
|
@@ -7,13 +7,18 @@ readme = "README.md"
|
|
|
7
7
|
|
|
8
8
|
[tool.poetry.dependencies]
|
|
9
9
|
python = "^3.10"
|
|
10
|
-
httpx = "^0.
|
|
11
|
-
pydantic = "^
|
|
10
|
+
httpx = "^0.28.1"
|
|
11
|
+
pydantic = "^2.12"
|
|
12
12
|
pyhumps = "^3.8.0"
|
|
13
|
-
python-dotenv = "^1.
|
|
14
|
-
tenacity = "^9.
|
|
13
|
+
python-dotenv = "^1.2.1"
|
|
14
|
+
tenacity = "^9.1.2"
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
[build-system]
|
|
18
18
|
requires = ["poetry-core"]
|
|
19
19
|
build-backend = "poetry.core.masonry.api"
|
|
20
|
+
|
|
21
|
+
[dependency-groups]
|
|
22
|
+
dev = [
|
|
23
|
+
"bump-pydantic (>=0.8.0,<0.9.0)"
|
|
24
|
+
]
|
|
@@ -5,13 +5,13 @@ with open("README.md", "r") as fh:
|
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name="GPTRouter",
|
|
8
|
-
version="1.0.
|
|
8
|
+
version="1.0.6",
|
|
9
9
|
description="A Python package for working with GPTRouter APIs",
|
|
10
10
|
long_description=long_description,
|
|
11
11
|
long_description_content_type="text/markdown",
|
|
12
12
|
author_email="sirjanpreet@writesonic.com",
|
|
13
13
|
packages=["gpt_router"],
|
|
14
|
-
install_requires=["httpx>=0.23.3", "pydantic>=
|
|
14
|
+
install_requires=["httpx>=0.23.3", "pydantic>=2.0", "pyhumps>=3.8.0"],
|
|
15
15
|
classifiers=[
|
|
16
16
|
"Development Status :: 3 - Alpha",
|
|
17
17
|
"Intended Audience :: Developers",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|