python-open-router 0.3.3__py3-none-any.whl → 0.4.0__py3-none-any.whl
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.
- python_open_router/__init__.py +18 -4
- python_open_router/models.py +142 -20
- python_open_router/open_router.py +157 -9
- {python_open_router-0.3.3.dist-info → python_open_router-0.4.0.dist-info}/METADATA +1 -1
- python_open_router-0.4.0.dist-info/RECORD +9 -0
- {python_open_router-0.3.3.dist-info → python_open_router-0.4.0.dist-info}/WHEEL +1 -1
- python_open_router-0.3.3.dist-info/RECORD +0 -9
- {python_open_router-0.3.3.dist-info → python_open_router-0.4.0.dist-info}/licenses/LICENSE.md +0 -0
python_open_router/__init__.py
CHANGED
|
@@ -6,34 +6,48 @@ from python_open_router.exceptions import (
|
|
|
6
6
|
OpenRouterError,
|
|
7
7
|
)
|
|
8
8
|
from python_open_router.models import (
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
DefaultParameters,
|
|
10
|
+
DeletedKeyResponse,
|
|
11
11
|
Key,
|
|
12
|
+
KeyCreateResponse,
|
|
12
13
|
KeyData,
|
|
13
14
|
KeyDataWrapper,
|
|
15
|
+
KeyResponseWrapper,
|
|
14
16
|
KeysDataWrapper,
|
|
15
17
|
Modality,
|
|
16
18
|
Model,
|
|
17
19
|
ModelArchitecture,
|
|
20
|
+
ModelLinks,
|
|
21
|
+
ModelResponseWrapper,
|
|
18
22
|
ModelsDataWrapper,
|
|
23
|
+
PerRequestLimits,
|
|
24
|
+
PublicPricing,
|
|
19
25
|
SupportedParameter,
|
|
26
|
+
TopProviderInfo,
|
|
20
27
|
)
|
|
21
28
|
from python_open_router.open_router import OpenRouterClient
|
|
22
29
|
|
|
23
30
|
__all__ = [
|
|
24
|
-
"
|
|
25
|
-
"
|
|
31
|
+
"DefaultParameters",
|
|
32
|
+
"DeletedKeyResponse",
|
|
26
33
|
"Key",
|
|
34
|
+
"KeyCreateResponse",
|
|
27
35
|
"KeyData",
|
|
28
36
|
"KeyDataWrapper",
|
|
37
|
+
"KeyResponseWrapper",
|
|
29
38
|
"KeysDataWrapper",
|
|
30
39
|
"Modality",
|
|
31
40
|
"Model",
|
|
32
41
|
"ModelArchitecture",
|
|
42
|
+
"ModelLinks",
|
|
43
|
+
"ModelResponseWrapper",
|
|
33
44
|
"ModelsDataWrapper",
|
|
34
45
|
"OpenRouterAuthenticationError",
|
|
35
46
|
"OpenRouterClient",
|
|
36
47
|
"OpenRouterConnectionError",
|
|
37
48
|
"OpenRouterError",
|
|
49
|
+
"PerRequestLimits",
|
|
50
|
+
"PublicPricing",
|
|
38
51
|
"SupportedParameter",
|
|
52
|
+
"TopProviderInfo",
|
|
39
53
|
]
|
python_open_router/models.py
CHANGED
|
@@ -24,10 +24,23 @@ class KeyData(DataClassORJSONMixin):
|
|
|
24
24
|
"""The OpenRouter key data."""
|
|
25
25
|
|
|
26
26
|
label: str
|
|
27
|
-
usage:
|
|
27
|
+
usage: float
|
|
28
28
|
is_provisioning_key: bool
|
|
29
|
-
limit_remaining:
|
|
29
|
+
limit_remaining: float | None
|
|
30
30
|
is_free_tier: bool
|
|
31
|
+
limit: float | None = None
|
|
32
|
+
limit_reset: str | None = None
|
|
33
|
+
usage_daily: float = 0.0
|
|
34
|
+
usage_weekly: float = 0.0
|
|
35
|
+
usage_monthly: float = 0.0
|
|
36
|
+
byok_usage: float = 0.0
|
|
37
|
+
byok_usage_daily: float = 0.0
|
|
38
|
+
byok_usage_weekly: float = 0.0
|
|
39
|
+
byok_usage_monthly: float = 0.0
|
|
40
|
+
include_byok_in_limit: bool = False
|
|
41
|
+
is_management_key: bool = False
|
|
42
|
+
creator_user_id: str | None = None
|
|
43
|
+
expires_at: str | None = None
|
|
31
44
|
|
|
32
45
|
|
|
33
46
|
@dataclass
|
|
@@ -38,10 +51,11 @@ class KeysDataWrapper(DataClassORJSONMixin):
|
|
|
38
51
|
|
|
39
52
|
|
|
40
53
|
@dataclass
|
|
41
|
-
class
|
|
42
|
-
"""
|
|
54
|
+
class KeyCreateResponse(DataClassORJSONMixin):
|
|
55
|
+
"""Response from creating a key."""
|
|
43
56
|
|
|
44
|
-
data:
|
|
57
|
+
data: Key
|
|
58
|
+
key: str
|
|
45
59
|
|
|
46
60
|
|
|
47
61
|
@dataclass
|
|
@@ -52,15 +66,44 @@ class Key(DataClassORJSONMixin):
|
|
|
52
66
|
name: str
|
|
53
67
|
label: str
|
|
54
68
|
disabled: bool
|
|
55
|
-
limit: float
|
|
69
|
+
limit: float | None = None
|
|
56
70
|
usage: float = 0.0
|
|
71
|
+
created_at: str = ""
|
|
72
|
+
updated_at: str | None = None
|
|
73
|
+
limit_remaining: float | None = None
|
|
74
|
+
limit_reset: str | None = None
|
|
75
|
+
workspace_id: str = ""
|
|
76
|
+
expires_at: str | None = None
|
|
77
|
+
usage_daily: float = 0.0
|
|
78
|
+
usage_weekly: float = 0.0
|
|
79
|
+
usage_monthly: float = 0.0
|
|
80
|
+
byok_usage: float = 0.0
|
|
81
|
+
byok_usage_daily: float = 0.0
|
|
82
|
+
byok_usage_weekly: float = 0.0
|
|
83
|
+
byok_usage_monthly: float = 0.0
|
|
84
|
+
include_byok_in_limit: bool = False
|
|
85
|
+
creator_user_id: str | None = None
|
|
57
86
|
|
|
58
87
|
|
|
59
|
-
@dataclass
|
|
60
|
-
class
|
|
61
|
-
"""
|
|
88
|
+
@dataclass
|
|
89
|
+
class KeyResponseWrapper(DataClassORJSONMixin):
|
|
90
|
+
"""Wrapper for single key response."""
|
|
91
|
+
|
|
92
|
+
data: Key
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@dataclass
|
|
96
|
+
class DeletedKeyResponse(DataClassORJSONMixin):
|
|
97
|
+
"""Response after deleting a key."""
|
|
98
|
+
|
|
99
|
+
deleted: bool
|
|
62
100
|
|
|
63
|
-
|
|
101
|
+
|
|
102
|
+
@dataclass
|
|
103
|
+
class ModelResponseWrapper(DataClassORJSONMixin):
|
|
104
|
+
"""Wrapper for single OpenRouter model response."""
|
|
105
|
+
|
|
106
|
+
data: Model
|
|
64
107
|
|
|
65
108
|
|
|
66
109
|
@dataclass
|
|
@@ -75,25 +118,29 @@ class SupportedParameter(StrEnum):
|
|
|
75
118
|
|
|
76
119
|
TEMPERATURE = "temperature"
|
|
77
120
|
TOP_P = "top_p"
|
|
121
|
+
TOP_K = "top_k"
|
|
78
122
|
MAX_TOKENS = "max_tokens"
|
|
123
|
+
MAX_COMPLETION_TOKENS = "max_completion_tokens"
|
|
79
124
|
REASONING = "reasoning"
|
|
125
|
+
REASONING_EFFORT = "reasoning_effort"
|
|
80
126
|
INCLUDE_REASONING = "include_reasoning"
|
|
81
127
|
STOP = "stop"
|
|
82
|
-
TOK_K = "top_k"
|
|
83
128
|
SEED = "seed"
|
|
84
129
|
RESPONSE_FORMAT = "response_format"
|
|
130
|
+
STRUCTURED_OUTPUTS = "structured_outputs"
|
|
85
131
|
TOOLS = "tools"
|
|
86
132
|
TOOL_CHOICE = "tool_choice"
|
|
133
|
+
PARALLEL_TOOL_CALLS = "parallel_tool_calls"
|
|
87
134
|
FREQUENCY_PENALTY = "frequency_penalty"
|
|
88
135
|
PRESENCE_PENALTY = "presence_penalty"
|
|
89
|
-
MIN_P = "min_p"
|
|
90
136
|
REPETITION_PENALTY = "repetition_penalty"
|
|
137
|
+
MIN_P = "min_p"
|
|
138
|
+
TOP_A = "top_a"
|
|
91
139
|
LOGPROBS = "logprobs"
|
|
92
140
|
LOGIT_BIAS = "logit_bias"
|
|
93
141
|
TOP_LOGPROBS = "top_logprobs"
|
|
94
|
-
STRUCTURED_OUTPUTS = "structured_outputs"
|
|
95
142
|
WEB_SEARCH_OPTIONS = "web_search_options"
|
|
96
|
-
|
|
143
|
+
VERBOSITY = "verbosity"
|
|
97
144
|
|
|
98
145
|
|
|
99
146
|
class Modality(StrEnum):
|
|
@@ -105,14 +152,77 @@ class Modality(StrEnum):
|
|
|
105
152
|
FILE = "file"
|
|
106
153
|
EMBEDDINGS = "embeddings"
|
|
107
154
|
VIDEO = "video"
|
|
155
|
+
RERANK = "rerank"
|
|
156
|
+
SPEECH = "speech"
|
|
157
|
+
TRANSCRIPTION = "transcription"
|
|
108
158
|
|
|
109
159
|
|
|
110
160
|
@dataclass(kw_only=True)
|
|
111
161
|
class ModelArchitecture(DataClassORJSONMixin):
|
|
112
|
-
"""Model data."""
|
|
162
|
+
"""Model architecture data."""
|
|
113
163
|
|
|
114
164
|
input_modalities: list[Modality]
|
|
115
165
|
output_modalities: list[Modality]
|
|
166
|
+
modality: str | None = None
|
|
167
|
+
instruct_type: str | None = None
|
|
168
|
+
tokenizer: str | None = None
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
@dataclass(kw_only=True)
|
|
172
|
+
class PublicPricing(DataClassORJSONMixin):
|
|
173
|
+
"""Model pricing data."""
|
|
174
|
+
|
|
175
|
+
completion: str
|
|
176
|
+
prompt: str
|
|
177
|
+
audio: str | None = None
|
|
178
|
+
audio_output: str | None = None
|
|
179
|
+
image: str | None = None
|
|
180
|
+
image_output: str | None = None
|
|
181
|
+
image_token: str | None = None
|
|
182
|
+
input_audio_cache: str | None = None
|
|
183
|
+
input_cache_read: str | None = None
|
|
184
|
+
input_cache_write: str | None = None
|
|
185
|
+
input_cache_write_1h: str | None = None
|
|
186
|
+
internal_reasoning: str | None = None
|
|
187
|
+
request: str | None = None
|
|
188
|
+
web_search: str | None = None
|
|
189
|
+
discount: float | None = None
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
@dataclass(kw_only=True)
|
|
193
|
+
class TopProviderInfo(DataClassORJSONMixin):
|
|
194
|
+
"""Top provider information."""
|
|
195
|
+
|
|
196
|
+
is_moderated: bool
|
|
197
|
+
context_length: int | None = None
|
|
198
|
+
max_completion_tokens: int | None = None
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
@dataclass(kw_only=True)
|
|
202
|
+
class DefaultParameters(DataClassORJSONMixin):
|
|
203
|
+
"""Default model parameters."""
|
|
204
|
+
|
|
205
|
+
temperature: float | None = None
|
|
206
|
+
top_p: float | None = None
|
|
207
|
+
top_k: int | None = None
|
|
208
|
+
frequency_penalty: float | None = None
|
|
209
|
+
presence_penalty: float | None = None
|
|
210
|
+
repetition_penalty: float | None = None
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
@dataclass(kw_only=True)
|
|
214
|
+
class PerRequestLimits(DataClassORJSONMixin):
|
|
215
|
+
"""Per-request limits."""
|
|
216
|
+
|
|
217
|
+
completion_tokens: float
|
|
218
|
+
prompt_tokens: float
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
@dataclass(kw_only=True)
|
|
222
|
+
class ModelLinks(DataClassORJSONMixin):
|
|
223
|
+
"""Model links."""
|
|
224
|
+
|
|
225
|
+
details: str
|
|
116
226
|
|
|
117
227
|
|
|
118
228
|
@dataclass(kw_only=True)
|
|
@@ -121,24 +231,34 @@ class Model(DataClassORJSONMixin):
|
|
|
121
231
|
|
|
122
232
|
id: str
|
|
123
233
|
canonical_slug: str
|
|
124
|
-
hugging_face_id: str | None
|
|
125
234
|
name: str
|
|
126
|
-
|
|
127
|
-
context_length: int
|
|
235
|
+
context_length: int | None
|
|
128
236
|
architecture: ModelArchitecture
|
|
129
237
|
supported_parameters: list[SupportedParameter]
|
|
238
|
+
pricing: PublicPricing
|
|
239
|
+
top_provider: TopProviderInfo
|
|
240
|
+
hugging_face_id: str | None = None
|
|
241
|
+
description: str | None = None
|
|
242
|
+
created: int | None = None
|
|
243
|
+
default_parameters: DefaultParameters | None = None
|
|
244
|
+
links: ModelLinks | None = None
|
|
245
|
+
per_request_limits: PerRequestLimits | None = None
|
|
246
|
+
supported_voices: list[str] | None = None
|
|
247
|
+
expiration_date: str | None = None
|
|
248
|
+
knowledge_cutoff: str | None = None
|
|
130
249
|
|
|
131
250
|
@classmethod
|
|
132
251
|
def __pre_deserialize__(cls, d: dict[str, Any]) -> dict[str, Any]:
|
|
133
252
|
"""Pre deserialize hook."""
|
|
134
253
|
parameters = d.get("supported_parameters", [])
|
|
254
|
+
supported = set(SupportedParameter)
|
|
255
|
+
d["supported_parameters"] = [p for p in parameters if p in supported]
|
|
135
256
|
for parameter in parameters:
|
|
136
|
-
if parameter not in
|
|
257
|
+
if parameter not in supported:
|
|
137
258
|
_LOGGER.warning(
|
|
138
259
|
"Unsupported parameter: %s. Please report at https://github.com/joostlek/python-open-router/issues.",
|
|
139
260
|
parameter,
|
|
140
261
|
)
|
|
141
|
-
parameters.remove(parameter)
|
|
142
262
|
return d
|
|
143
263
|
|
|
144
264
|
@classmethod
|
|
@@ -146,4 +266,6 @@ class Model(DataClassORJSONMixin):
|
|
|
146
266
|
"""Post deserialize hook."""
|
|
147
267
|
if obj.hugging_face_id == "":
|
|
148
268
|
obj.hugging_face_id = None
|
|
269
|
+
if obj.description == "":
|
|
270
|
+
obj.description = None
|
|
149
271
|
return obj
|
|
@@ -9,17 +9,24 @@ import socket
|
|
|
9
9
|
from typing import TYPE_CHECKING, Any
|
|
10
10
|
|
|
11
11
|
from aiohttp import ClientError, ClientResponseError, ClientSession
|
|
12
|
-
from aiohttp.hdrs import METH_GET, METH_POST
|
|
12
|
+
from aiohttp.hdrs import METH_DELETE, METH_GET, METH_PATCH, METH_POST
|
|
13
|
+
import orjson
|
|
13
14
|
from yarl import URL
|
|
14
15
|
|
|
15
|
-
from python_open_router.exceptions import
|
|
16
|
+
from python_open_router.exceptions import (
|
|
17
|
+
OpenRouterAuthenticationError,
|
|
18
|
+
OpenRouterConnectionError,
|
|
19
|
+
)
|
|
16
20
|
from python_open_router.models import (
|
|
17
|
-
|
|
21
|
+
DeletedKeyResponse,
|
|
18
22
|
Key,
|
|
23
|
+
KeyCreateResponse,
|
|
19
24
|
KeyData,
|
|
20
25
|
KeyDataWrapper,
|
|
26
|
+
KeyResponseWrapper,
|
|
21
27
|
KeysDataWrapper,
|
|
22
28
|
Model,
|
|
29
|
+
ModelResponseWrapper,
|
|
23
30
|
ModelsDataWrapper,
|
|
24
31
|
)
|
|
25
32
|
|
|
@@ -81,6 +88,10 @@ class OpenRouterClient:
|
|
|
81
88
|
msg = "Error occurred while communicating with the service"
|
|
82
89
|
raise OpenRouterConnectionError(msg) from exception
|
|
83
90
|
|
|
91
|
+
if response.status == 401:
|
|
92
|
+
msg = "Authentication failed"
|
|
93
|
+
raise OpenRouterAuthenticationError(msg)
|
|
94
|
+
|
|
84
95
|
if response.status >= 400:
|
|
85
96
|
content_type = response.headers.get("Content-Type", "")
|
|
86
97
|
text = await response.text()
|
|
@@ -97,25 +108,162 @@ class OpenRouterClient:
|
|
|
97
108
|
response = await self._request(METH_GET, "key")
|
|
98
109
|
return KeyDataWrapper.from_json(response).data
|
|
99
110
|
|
|
100
|
-
async def get_keys(
|
|
111
|
+
async def get_keys(
|
|
112
|
+
self,
|
|
113
|
+
*,
|
|
114
|
+
include_disabled: bool | None = None,
|
|
115
|
+
offset: int | None = None,
|
|
116
|
+
workspace_id: str | None = None,
|
|
117
|
+
) -> list[Key]:
|
|
101
118
|
"""Get all keys."""
|
|
102
|
-
|
|
119
|
+
params: dict[str, Any] = {}
|
|
120
|
+
if include_disabled is not None:
|
|
121
|
+
params["include_disabled"] = str(include_disabled).lower()
|
|
122
|
+
if offset is not None:
|
|
123
|
+
params["offset"] = str(offset)
|
|
124
|
+
if workspace_id is not None:
|
|
125
|
+
params["workspace_id"] = workspace_id
|
|
126
|
+
response = await self._request(METH_GET, "keys", params=params or None)
|
|
103
127
|
return KeysDataWrapper.from_json(response).data
|
|
104
128
|
|
|
105
|
-
async def create_key(
|
|
129
|
+
async def create_key(
|
|
130
|
+
self,
|
|
131
|
+
name: str,
|
|
132
|
+
limit: float | None = None,
|
|
133
|
+
*,
|
|
134
|
+
limit_reset: str | None = None,
|
|
135
|
+
workspace_id: str | None = None,
|
|
136
|
+
expires_at: str | None = None,
|
|
137
|
+
include_byok_in_limit: bool | None = None,
|
|
138
|
+
) -> Key:
|
|
106
139
|
"""Create a new key."""
|
|
107
140
|
data: dict[str, Any] = {"name": name}
|
|
108
141
|
if limit is not None:
|
|
109
142
|
data["limit"] = limit
|
|
143
|
+
if limit_reset is not None:
|
|
144
|
+
data["limit_reset"] = limit_reset
|
|
145
|
+
if workspace_id is not None:
|
|
146
|
+
data["workspace_id"] = workspace_id
|
|
147
|
+
if expires_at is not None:
|
|
148
|
+
data["expires_at"] = expires_at
|
|
149
|
+
if include_byok_in_limit is not None:
|
|
150
|
+
data["include_byok_in_limit"] = include_byok_in_limit
|
|
110
151
|
|
|
111
152
|
response = await self._request(METH_POST, "keys", data=data)
|
|
112
|
-
return
|
|
153
|
+
return KeyCreateResponse.from_json(response).data
|
|
154
|
+
|
|
155
|
+
async def get_key(self, key_hash: str) -> Key:
|
|
156
|
+
"""Get a single key by hash."""
|
|
157
|
+
response = await self._request(METH_GET, f"keys/{key_hash}")
|
|
158
|
+
return KeyResponseWrapper.from_json(response).data
|
|
159
|
+
|
|
160
|
+
async def update_key(
|
|
161
|
+
self,
|
|
162
|
+
key_hash: str,
|
|
163
|
+
*,
|
|
164
|
+
name: str | None = None,
|
|
165
|
+
disabled: bool | None = None,
|
|
166
|
+
limit: float | None = None,
|
|
167
|
+
limit_reset: str | None = None,
|
|
168
|
+
include_byok_in_limit: bool | None = None,
|
|
169
|
+
) -> Key:
|
|
170
|
+
"""Update an existing key."""
|
|
171
|
+
data: dict[str, Any] = {}
|
|
172
|
+
if name is not None:
|
|
173
|
+
data["name"] = name
|
|
174
|
+
if disabled is not None:
|
|
175
|
+
data["disabled"] = disabled
|
|
176
|
+
if limit is not None:
|
|
177
|
+
data["limit"] = limit
|
|
178
|
+
if limit_reset is not None:
|
|
179
|
+
data["limit_reset"] = limit_reset
|
|
180
|
+
if include_byok_in_limit is not None:
|
|
181
|
+
data["include_byok_in_limit"] = include_byok_in_limit
|
|
182
|
+
|
|
183
|
+
response = await self._request(METH_PATCH, f"keys/{key_hash}", data=data)
|
|
184
|
+
return KeyResponseWrapper.from_json(response).data
|
|
185
|
+
|
|
186
|
+
async def delete_key(self, key_hash: str) -> bool:
|
|
187
|
+
"""Delete a key by hash."""
|
|
188
|
+
response = await self._request(METH_DELETE, f"keys/{key_hash}")
|
|
189
|
+
return DeletedKeyResponse.from_json(response).deleted
|
|
190
|
+
|
|
191
|
+
async def get_model(self, author: str, slug: str) -> Model:
|
|
192
|
+
"""Get a single model by author and slug."""
|
|
193
|
+
response = await self._request(METH_GET, f"model/{author}/{slug}")
|
|
194
|
+
return ModelResponseWrapper.from_json(response).data
|
|
195
|
+
|
|
196
|
+
@staticmethod
|
|
197
|
+
def _filter_model_params(
|
|
198
|
+
kwargs: dict[str, Any],
|
|
199
|
+
*,
|
|
200
|
+
numeric_keys: frozenset[str] = frozenset(),
|
|
201
|
+
) -> dict[str, Any]:
|
|
202
|
+
"""Filter None values and convert numeric params to strings."""
|
|
203
|
+
params = {k: v for k, v in kwargs.items() if v is not None}
|
|
204
|
+
for key in numeric_keys:
|
|
205
|
+
if key in params:
|
|
206
|
+
params[key] = str(params[key])
|
|
207
|
+
return params
|
|
113
208
|
|
|
114
|
-
async def get_models(
|
|
209
|
+
async def get_models( # pylint: disable=too-many-locals
|
|
210
|
+
self,
|
|
211
|
+
*,
|
|
212
|
+
category: str | None = None,
|
|
213
|
+
supported_parameters: str | None = None,
|
|
214
|
+
output_modalities: str | None = None,
|
|
215
|
+
sort: str | None = None,
|
|
216
|
+
q: str | None = None,
|
|
217
|
+
input_modalities: str | None = None,
|
|
218
|
+
context: int | None = None,
|
|
219
|
+
min_price: float | None = None,
|
|
220
|
+
max_price: float | None = None,
|
|
221
|
+
arch: str | None = None,
|
|
222
|
+
model_authors: str | None = None,
|
|
223
|
+
providers: str | None = None,
|
|
224
|
+
distillable: str | None = None,
|
|
225
|
+
zdr: str | None = None,
|
|
226
|
+
region: str | None = None,
|
|
227
|
+
) -> list[Model]:
|
|
115
228
|
"""Get all available models."""
|
|
116
|
-
|
|
229
|
+
numeric = frozenset({"context", "min_price", "max_price"})
|
|
230
|
+
params = self._filter_model_params(
|
|
231
|
+
{
|
|
232
|
+
"category": category,
|
|
233
|
+
"supported_parameters": supported_parameters,
|
|
234
|
+
"output_modalities": output_modalities,
|
|
235
|
+
"sort": sort,
|
|
236
|
+
"q": q,
|
|
237
|
+
"input_modalities": input_modalities,
|
|
238
|
+
"context": context,
|
|
239
|
+
"min_price": min_price,
|
|
240
|
+
"max_price": max_price,
|
|
241
|
+
"arch": arch,
|
|
242
|
+
"model_authors": model_authors,
|
|
243
|
+
"providers": providers,
|
|
244
|
+
"distillable": distillable,
|
|
245
|
+
"zdr": zdr,
|
|
246
|
+
"region": region,
|
|
247
|
+
},
|
|
248
|
+
numeric_keys=numeric,
|
|
249
|
+
)
|
|
250
|
+
response = await self._request(METH_GET, "models", params=params or None)
|
|
117
251
|
return ModelsDataWrapper.from_json(response).data
|
|
118
252
|
|
|
253
|
+
async def count_models(
|
|
254
|
+
self,
|
|
255
|
+
*,
|
|
256
|
+
output_modalities: str | None = None,
|
|
257
|
+
) -> int:
|
|
258
|
+
"""Get total count of available models."""
|
|
259
|
+
params: dict[str, Any] = {}
|
|
260
|
+
if output_modalities is not None:
|
|
261
|
+
params["output_modalities"] = output_modalities
|
|
262
|
+
response = await self._request(METH_GET, "models/count", params=params or None)
|
|
263
|
+
result: dict[str, Any] = orjson.loads(response) # pylint: disable=no-member
|
|
264
|
+
count: int = result.get("data", {}).get("count", 0)
|
|
265
|
+
return count
|
|
266
|
+
|
|
119
267
|
async def close(self) -> None:
|
|
120
268
|
"""Close open client session."""
|
|
121
269
|
if self.session and self._close_session:
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
python_open_router/__init__.py,sha256=9a8JXk66oCsPUc-XxgHBI29sVi6QbjlnUuCUxLDJUfo,1166
|
|
2
|
+
python_open_router/exceptions.py,sha256=68nskqNdXNMIK4iA1XOE1E5P5rbhAf27DDACkk-ZVwU,312
|
|
3
|
+
python_open_router/models.py,sha256=oVEE8q195laYFa7WXSYOKI6FiTqvJ6lPSTzTphj8eHI,6943
|
|
4
|
+
python_open_router/open_router.py,sha256=JB_2fu1akGJ8niuP7FOlExWTV3ytDvmH_sXWKY5iO6I,9520
|
|
5
|
+
python_open_router/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
python_open_router-0.4.0.dist-info/METADATA,sha256=Iv2GN34OuueJ3t0rUj_ELgoEFu-aHPYX7TvCm1XvSqU,6055
|
|
7
|
+
python_open_router-0.4.0.dist-info/WHEEL,sha256=EGEvSphFYqXKs23-kQBeyNoJP1nrT8ZJKQoi5p5DYL8,88
|
|
8
|
+
python_open_router-0.4.0.dist-info/licenses/LICENSE.md,sha256=Xbw7n2Ic30r4j8_MDNND4ss_sdoj9IGeIkEWc2Hsfs8,1077
|
|
9
|
+
python_open_router-0.4.0.dist-info/RECORD,,
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
python_open_router/__init__.py,sha256=UQt6SpcnmQkS2wiyjwA_Ggvvzu7Ucx8BOCyZLZ_F2uA,840
|
|
2
|
-
python_open_router/exceptions.py,sha256=68nskqNdXNMIK4iA1XOE1E5P5rbhAf27DDACkk-ZVwU,312
|
|
3
|
-
python_open_router/models.py,sha256=GHGwXr8DLYhf-jnmqNmqdQ4ISFRyYdWBd4WsQNlkDRY,3379
|
|
4
|
-
python_open_router/open_router.py,sha256=zq7aleWZfNFqbBb69Qp3_3jed95cwxtgGMlYFhDzYKw,4148
|
|
5
|
-
python_open_router/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
python_open_router-0.3.3.dist-info/METADATA,sha256=jKLq5jP-h8fd4mHXqj0Q8GLXFeDNhL6GMGUo5c0nVHM,6055
|
|
7
|
-
python_open_router-0.3.3.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
8
|
-
python_open_router-0.3.3.dist-info/licenses/LICENSE.md,sha256=Xbw7n2Ic30r4j8_MDNND4ss_sdoj9IGeIkEWc2Hsfs8,1077
|
|
9
|
-
python_open_router-0.3.3.dist-info/RECORD,,
|
{python_open_router-0.3.3.dist-info → python_open_router-0.4.0.dist-info}/licenses/LICENSE.md
RENAMED
|
File without changes
|