model-library 0.1.7__py3-none-any.whl → 0.1.8__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.
- model_library/base/base.py +139 -62
- model_library/base/delegate_only.py +77 -10
- model_library/base/output.py +43 -0
- model_library/base/utils.py +35 -0
- model_library/config/alibaba_models.yaml +44 -57
- model_library/config/all_models.json +253 -126
- model_library/config/kimi_models.yaml +30 -3
- model_library/config/openai_models.yaml +15 -23
- model_library/config/zai_models.yaml +24 -3
- model_library/exceptions.py +3 -77
- model_library/providers/ai21labs.py +12 -8
- model_library/providers/alibaba.py +17 -8
- model_library/providers/amazon.py +49 -16
- model_library/providers/anthropic.py +93 -40
- model_library/providers/azure.py +22 -10
- model_library/providers/cohere.py +7 -7
- model_library/providers/deepseek.py +8 -8
- model_library/providers/fireworks.py +7 -8
- model_library/providers/google/batch.py +14 -10
- model_library/providers/google/google.py +48 -29
- model_library/providers/inception.py +7 -7
- model_library/providers/kimi.py +18 -8
- model_library/providers/minimax.py +15 -17
- model_library/providers/mistral.py +20 -8
- model_library/providers/openai.py +99 -22
- model_library/providers/openrouter.py +34 -0
- model_library/providers/perplexity.py +7 -7
- model_library/providers/together.py +7 -8
- model_library/providers/vals.py +12 -6
- model_library/providers/xai.py +47 -42
- model_library/providers/zai.py +38 -8
- model_library/registry_utils.py +39 -15
- model_library/retriers/__init__.py +0 -0
- model_library/retriers/backoff.py +73 -0
- model_library/retriers/base.py +225 -0
- model_library/retriers/token.py +427 -0
- model_library/retriers/utils.py +11 -0
- model_library/settings.py +1 -1
- model_library/utils.py +13 -0
- {model_library-0.1.7.dist-info → model_library-0.1.8.dist-info}/METADATA +2 -1
- model_library-0.1.8.dist-info/RECORD +70 -0
- {model_library-0.1.7.dist-info → model_library-0.1.8.dist-info}/WHEEL +1 -1
- model_library-0.1.7.dist-info/RECORD +0 -64
- {model_library-0.1.7.dist-info → model_library-0.1.8.dist-info}/licenses/LICENSE +0 -0
- {model_library-0.1.7.dist-info → model_library-0.1.8.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import logging
|
|
3
|
+
import time
|
|
4
|
+
import uuid
|
|
5
|
+
from asyncio.tasks import Task
|
|
6
|
+
from math import ceil, floor
|
|
7
|
+
from typing import Any, Callable, Coroutine
|
|
8
|
+
|
|
9
|
+
from redis.asyncio import Redis
|
|
10
|
+
|
|
11
|
+
from model_library.base.base import QueryResult, RateLimit
|
|
12
|
+
from model_library.exceptions import exception_message
|
|
13
|
+
from model_library.retriers.base import BaseRetrier
|
|
14
|
+
from model_library.retriers.utils import jitter
|
|
15
|
+
|
|
16
|
+
RETRY_WAIT_TIME: float = 20.0
|
|
17
|
+
TOKEN_WAIT_TIME: float = 5.0
|
|
18
|
+
|
|
19
|
+
MAX_PRIORITY: int = 1
|
|
20
|
+
MIN_PRIORITY: int = 5
|
|
21
|
+
|
|
22
|
+
MAX_RETRIES: int = 10
|
|
23
|
+
|
|
24
|
+
redis_client: Redis
|
|
25
|
+
LOCK_TIMEOUT: int = 10 # using 10 in case there is high compute load, don't want to error on lock releases
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def set_redis_client(client: Redis):
|
|
29
|
+
global redis_client
|
|
30
|
+
redis_client = client
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
refill_tasks: dict[str, tuple[dict[str, int | Any], Task[None]]] = {}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class TokenRetrier(BaseRetrier):
|
|
37
|
+
"""
|
|
38
|
+
Token-based retry strategy
|
|
39
|
+
Predicts the number of tokens required for a query, sends resquests to respect the rate limit,
|
|
40
|
+
then adjusts the estimate based on actual usage.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
@staticmethod
|
|
44
|
+
def get_token_key(client_registry_key: tuple[str, str]) -> str:
|
|
45
|
+
"""Get the key which stores remaining tokens"""
|
|
46
|
+
return f"{client_registry_key[0]}:{client_registry_key[1]}:tokens"
|
|
47
|
+
|
|
48
|
+
@staticmethod
|
|
49
|
+
def get_priority_key(client_registry_key: tuple[str, str], priority: int) -> str:
|
|
50
|
+
"""Get the key which stores the amount of tasks waiting for a given priority"""
|
|
51
|
+
return f"{client_registry_key[0]}:{client_registry_key[1]}:priority:{priority}"
|
|
52
|
+
|
|
53
|
+
@staticmethod
|
|
54
|
+
async def init_remaining_tokens(
|
|
55
|
+
client_registry_key: tuple[str, str],
|
|
56
|
+
limit: int,
|
|
57
|
+
limit_refresh_seconds: int,
|
|
58
|
+
logger: logging.Logger,
|
|
59
|
+
get_rate_limit_func: Callable[[], Coroutine[Any, Any, RateLimit | None]],
|
|
60
|
+
) -> None:
|
|
61
|
+
"""
|
|
62
|
+
Initialize remaining tokens in storage and start background refill process
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
async def _header_correction_loop(
|
|
66
|
+
key: str,
|
|
67
|
+
limit: int,
|
|
68
|
+
tokens_per_second: int,
|
|
69
|
+
get_rate_limit_func: Callable[[], Coroutine[Any, Any, RateLimit | None]],
|
|
70
|
+
version: str,
|
|
71
|
+
) -> None:
|
|
72
|
+
"""
|
|
73
|
+
Background loop that correct tokens based on provider headers
|
|
74
|
+
Every 5 seconds
|
|
75
|
+
"""
|
|
76
|
+
interval = 5.0
|
|
77
|
+
|
|
78
|
+
assert redis_client
|
|
79
|
+
while True:
|
|
80
|
+
await asyncio.sleep(interval)
|
|
81
|
+
current_version = await redis_client.get("version:" + key)
|
|
82
|
+
if current_version != version:
|
|
83
|
+
logger.debug(
|
|
84
|
+
f"version changed ({current_version} != {version}), exiting _header_correction_loop for {key}"
|
|
85
|
+
)
|
|
86
|
+
return
|
|
87
|
+
|
|
88
|
+
rate_limit = await get_rate_limit_func()
|
|
89
|
+
if rate_limit is None:
|
|
90
|
+
# kill the task as no headers are provided
|
|
91
|
+
logger.debug(
|
|
92
|
+
f"no rate limit headers, exiting _header_correction_loop for {key}"
|
|
93
|
+
)
|
|
94
|
+
return
|
|
95
|
+
|
|
96
|
+
tokens_remaining = rate_limit.token_remaining_total
|
|
97
|
+
|
|
98
|
+
async with redis_client.lock(key + ":lock", timeout=LOCK_TIMEOUT):
|
|
99
|
+
current = int(await redis_client.get(key))
|
|
100
|
+
|
|
101
|
+
# increment
|
|
102
|
+
elapsed = time.time() - rate_limit.unix_timestamp
|
|
103
|
+
adjusted = floor(tokens_remaining + (tokens_per_second * elapsed))
|
|
104
|
+
|
|
105
|
+
# if the headers show a lower value, correct with that
|
|
106
|
+
if adjusted < current:
|
|
107
|
+
await redis_client.set(key, adjusted)
|
|
108
|
+
logger.info(
|
|
109
|
+
f"Corrected {key} from {current} to {adjusted} based on headers ({elapsed:.1f}s old)"
|
|
110
|
+
)
|
|
111
|
+
else:
|
|
112
|
+
logger.debug(
|
|
113
|
+
f"Not correcting {key} from {current} to {adjusted} based on headers ({elapsed:.1f}s old) (higher value)"
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
async def _token_refill_loop(
|
|
117
|
+
key: str,
|
|
118
|
+
limit: int,
|
|
119
|
+
tokens_per_second: int,
|
|
120
|
+
version: str,
|
|
121
|
+
) -> None:
|
|
122
|
+
"""
|
|
123
|
+
Background loop that refills tokens
|
|
124
|
+
Every second
|
|
125
|
+
"""
|
|
126
|
+
interval: float = 1.0
|
|
127
|
+
|
|
128
|
+
assert redis_client
|
|
129
|
+
while True:
|
|
130
|
+
await asyncio.sleep(interval)
|
|
131
|
+
current_version = await redis_client.get("version:" + key)
|
|
132
|
+
if current_version != version:
|
|
133
|
+
logger.debug(
|
|
134
|
+
f"version changed ({current_version} != {version}), exiting _token_refill_loop for {key}"
|
|
135
|
+
)
|
|
136
|
+
return
|
|
137
|
+
|
|
138
|
+
async with redis_client.lock(key + ":lock", timeout=LOCK_TIMEOUT):
|
|
139
|
+
# increment
|
|
140
|
+
current = await redis_client.incrby(key, tokens_per_second)
|
|
141
|
+
logger.debug(
|
|
142
|
+
f"[Token Refill] | {key} | Amount: {tokens_per_second} | Current: {current}"
|
|
143
|
+
)
|
|
144
|
+
# cap at limit
|
|
145
|
+
if current > limit:
|
|
146
|
+
logger.debug(f"[Token Cap] | {key} | Limit: {limit}")
|
|
147
|
+
await redis_client.set(key, limit)
|
|
148
|
+
|
|
149
|
+
key = TokenRetrier.get_token_key(client_registry_key)
|
|
150
|
+
|
|
151
|
+
# limit_key is only used to check if the limit has changed
|
|
152
|
+
limit_key = f"{key}:limit"
|
|
153
|
+
|
|
154
|
+
async with redis_client.lock("init:" + key + ":lock", timeout=LOCK_TIMEOUT):
|
|
155
|
+
old_limit = int(await redis_client.get(limit_key) or 0)
|
|
156
|
+
|
|
157
|
+
# keep track of version so we can clean up old tasks
|
|
158
|
+
# even if the limit has not changed, reset background tasks just in case
|
|
159
|
+
version = str(uuid.uuid4())
|
|
160
|
+
await redis_client.set("version:" + key, version)
|
|
161
|
+
|
|
162
|
+
if old_limit != limit or not await redis_client.exists(key):
|
|
163
|
+
# if new limit if different, set it
|
|
164
|
+
await redis_client.set(key, limit)
|
|
165
|
+
await redis_client.set(limit_key, limit)
|
|
166
|
+
|
|
167
|
+
tokens_per_second = floor(limit / limit_refresh_seconds)
|
|
168
|
+
|
|
169
|
+
refill_task = asyncio.create_task(
|
|
170
|
+
_token_refill_loop(key, limit, tokens_per_second, version)
|
|
171
|
+
)
|
|
172
|
+
correction_task = asyncio.create_task(
|
|
173
|
+
_header_correction_loop(
|
|
174
|
+
key, limit, tokens_per_second, get_rate_limit_func, version
|
|
175
|
+
)
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
refill_tasks["refill:" + key] = (
|
|
179
|
+
{
|
|
180
|
+
"limit": limit,
|
|
181
|
+
"limit_refresh_seconds": limit_refresh_seconds,
|
|
182
|
+
},
|
|
183
|
+
refill_task,
|
|
184
|
+
)
|
|
185
|
+
refill_tasks["correction:" + key] = (
|
|
186
|
+
{
|
|
187
|
+
"limit": limit,
|
|
188
|
+
"limit_refresh_seconds": limit_refresh_seconds,
|
|
189
|
+
"get_rate_limit_func": get_rate_limit_func,
|
|
190
|
+
},
|
|
191
|
+
correction_task,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
async def _get_remaining_tokens(self) -> int:
|
|
195
|
+
"""Get remaining tokens"""
|
|
196
|
+
tokens = await redis_client.get(self.token_key)
|
|
197
|
+
return int(tokens)
|
|
198
|
+
|
|
199
|
+
async def _deduct_remaining_tokens(self) -> None:
|
|
200
|
+
"""Deduct from remaining tokens"""
|
|
201
|
+
# NOTE: decrby is atomic
|
|
202
|
+
await redis_client.decrby(self.token_key, self.actual_estimate_total_tokens)
|
|
203
|
+
|
|
204
|
+
def __init__(
|
|
205
|
+
self,
|
|
206
|
+
logger: logging.Logger,
|
|
207
|
+
max_tries: int | None = MAX_RETRIES,
|
|
208
|
+
max_time: float | None = None,
|
|
209
|
+
retry_callback: Callable[[int, Exception | None, float, float], None]
|
|
210
|
+
| None = None,
|
|
211
|
+
*,
|
|
212
|
+
client_registry_key: tuple[str, str],
|
|
213
|
+
estimate_input_tokens: int,
|
|
214
|
+
estimate_output_tokens: int,
|
|
215
|
+
dynamic_estimate_instance_id: str | None = None,
|
|
216
|
+
retry_wait_time: float = RETRY_WAIT_TIME,
|
|
217
|
+
token_wait_time: float = TOKEN_WAIT_TIME,
|
|
218
|
+
):
|
|
219
|
+
super().__init__(
|
|
220
|
+
strategy="token",
|
|
221
|
+
logger=logger,
|
|
222
|
+
max_tries=max_tries,
|
|
223
|
+
max_time=max_time,
|
|
224
|
+
retry_callback=retry_callback,
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
self.client_registry_key = client_registry_key
|
|
228
|
+
|
|
229
|
+
self.estimate_input_tokens = estimate_input_tokens
|
|
230
|
+
self.estimate_output_tokens = estimate_output_tokens
|
|
231
|
+
self.estimate_total_tokens = estimate_input_tokens + estimate_output_tokens
|
|
232
|
+
self.actual_estimate_total_tokens = (
|
|
233
|
+
self.estimate_total_tokens
|
|
234
|
+
) # when multiplying base estimate_total_tokens by ratio
|
|
235
|
+
|
|
236
|
+
self.retry_wait_time = retry_wait_time
|
|
237
|
+
self.token_wait_time = token_wait_time
|
|
238
|
+
|
|
239
|
+
self.priority = MAX_PRIORITY
|
|
240
|
+
|
|
241
|
+
self.token_key = TokenRetrier.get_token_key(client_registry_key)
|
|
242
|
+
self._token_key_lock = self.token_key + ":lock"
|
|
243
|
+
self._init_key_lock = "init:" + self.token_key + ":lock"
|
|
244
|
+
|
|
245
|
+
self.dynamic_estimate_key = (
|
|
246
|
+
f"{self.token_key}:dynamic_estimate:{dynamic_estimate_instance_id}"
|
|
247
|
+
if dynamic_estimate_instance_id
|
|
248
|
+
else None
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
async def _calculate_wait_time(
|
|
252
|
+
self, attempt: int, exception: Exception | None = None
|
|
253
|
+
) -> float:
|
|
254
|
+
"""Wait time between retries"""
|
|
255
|
+
return jitter(self.retry_wait_time)
|
|
256
|
+
|
|
257
|
+
async def _on_retry(
|
|
258
|
+
self, exception: Exception | None, elapsed: float, wait_time: float
|
|
259
|
+
) -> None:
|
|
260
|
+
"""Log retry attempt and update priority/attempts only on actual exceptions"""
|
|
261
|
+
|
|
262
|
+
self.priority = min(MIN_PRIORITY, self.priority + 1)
|
|
263
|
+
|
|
264
|
+
logger_msg = (
|
|
265
|
+
f"[Token Retry] | Attempt: {self.attempts}/{self.max_tries} | Elapsed: {elapsed:.1f}s | "
|
|
266
|
+
f"Next wait: {wait_time:.1f}s | Priority: {self.priority} ({MAX_PRIORITY}-{MIN_PRIORITY}) | "
|
|
267
|
+
f"Exception: {exception_message(exception)}"
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
self.logger.warning(logger_msg)
|
|
271
|
+
|
|
272
|
+
if self.retry_callback:
|
|
273
|
+
self.retry_callback(self.attempts, exception, elapsed, wait_time)
|
|
274
|
+
|
|
275
|
+
async def _has_lower_priority_waiting(self) -> bool:
|
|
276
|
+
"""
|
|
277
|
+
Check if there are lower priority requests waiting
|
|
278
|
+
"""
|
|
279
|
+
|
|
280
|
+
# NOTE: no lock needed, stale counts are fine
|
|
281
|
+
for priority in range(MAX_PRIORITY, self.priority):
|
|
282
|
+
key = TokenRetrier.get_priority_key(self.client_registry_key, priority)
|
|
283
|
+
count = await redis_client.get(key)
|
|
284
|
+
self.logger.debug(f"priority: {priority}, count: {count}")
|
|
285
|
+
if count and int(count) > 0:
|
|
286
|
+
return True
|
|
287
|
+
return False
|
|
288
|
+
|
|
289
|
+
async def _pre_function(self) -> None:
|
|
290
|
+
"""
|
|
291
|
+
Loop until sufficient tokens are available.
|
|
292
|
+
Acquires priority semaphore, checks for lower priority requests, deducts tokens from Redis.
|
|
293
|
+
Logs token waits but does not count as retry attempts.
|
|
294
|
+
"""
|
|
295
|
+
|
|
296
|
+
priority_key = TokenRetrier.get_priority_key(
|
|
297
|
+
self.client_registry_key, self.priority
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
# let storage know we are waiting at this priority
|
|
301
|
+
await redis_client.incr(priority_key)
|
|
302
|
+
self.logger.debug(f"priority: {self.priority}, waiting: {priority_key}")
|
|
303
|
+
|
|
304
|
+
try:
|
|
305
|
+
while True:
|
|
306
|
+
wait_time = jitter(self.token_wait_time)
|
|
307
|
+
|
|
308
|
+
# if there is a task with lower priority waiting, go back to waiting
|
|
309
|
+
if await self._has_lower_priority_waiting():
|
|
310
|
+
self.logger.debug(
|
|
311
|
+
f"[Token Wait] Lower priority requests exist, waiting {wait_time:.1f}s | "
|
|
312
|
+
f"Priority: {self.priority}"
|
|
313
|
+
)
|
|
314
|
+
else:
|
|
315
|
+
# dynamically adjust actual estimate tokens based on past requests
|
|
316
|
+
if self.dynamic_estimate_key:
|
|
317
|
+
# NOTE: ok to not lock, don't need precise ratio
|
|
318
|
+
ratio = float(
|
|
319
|
+
await redis_client.get(self.dynamic_estimate_key) or 1.0
|
|
320
|
+
)
|
|
321
|
+
self.actual_estimate_total_tokens = ceil(
|
|
322
|
+
self.estimate_total_tokens * ratio
|
|
323
|
+
)
|
|
324
|
+
self.logger.debug(
|
|
325
|
+
f"Adjusted actual estimate tokens to {self.actual_estimate_total_tokens} using ratio {ratio}"
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
# TODO: use luascript to avoid using locks
|
|
329
|
+
|
|
330
|
+
# NOTE: `async with` releases lock in all situations
|
|
331
|
+
async with redis_client.lock(
|
|
332
|
+
self._token_key_lock, timeout=LOCK_TIMEOUT
|
|
333
|
+
):
|
|
334
|
+
tokens_remaining = await self._get_remaining_tokens()
|
|
335
|
+
|
|
336
|
+
# if we have enough tokens, deduct estimate tokens and make request
|
|
337
|
+
if tokens_remaining >= self.actual_estimate_total_tokens:
|
|
338
|
+
self.logger.debug(
|
|
339
|
+
f"Enough tokens {self.actual_estimate_total_tokens}/{tokens_remaining}, deducting"
|
|
340
|
+
)
|
|
341
|
+
await self._deduct_remaining_tokens()
|
|
342
|
+
return
|
|
343
|
+
|
|
344
|
+
self.logger.warning(
|
|
345
|
+
f"[Token Wait] Insufficient tokens, waiting {wait_time:.1f}s | "
|
|
346
|
+
f"estimate_tokens: {self.actual_estimate_total_tokens}/{tokens_remaining} | "
|
|
347
|
+
f"Priority: {self.priority}"
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
# Zzz
|
|
351
|
+
self.logger.debug(f"Sleeping for {wait_time:.1f}s")
|
|
352
|
+
await asyncio.sleep(wait_time)
|
|
353
|
+
finally:
|
|
354
|
+
# let storage know we are done waiting at this priority
|
|
355
|
+
await redis_client.decr(priority_key)
|
|
356
|
+
|
|
357
|
+
async def _adjust_dynamic_estimate_ratio(self, actual_tokens: int) -> None:
|
|
358
|
+
if not self.dynamic_estimate_key:
|
|
359
|
+
return
|
|
360
|
+
|
|
361
|
+
observed_ratio = actual_tokens / self.estimate_total_tokens
|
|
362
|
+
|
|
363
|
+
alpha = 0.3
|
|
364
|
+
|
|
365
|
+
async with redis_client.lock(
|
|
366
|
+
self.dynamic_estimate_key + ":lock", timeout=LOCK_TIMEOUT
|
|
367
|
+
):
|
|
368
|
+
current_ratio = float(
|
|
369
|
+
await redis_client.get(self.dynamic_estimate_key) or 1.0
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
new_ratio = (observed_ratio * alpha) + (current_ratio * (1 - alpha))
|
|
373
|
+
|
|
374
|
+
# NOTE: for now, will not cap the ratio as estimates will likely be very off
|
|
375
|
+
# the ratio between the tokenized estimate and the dynamic estimate should not be too far off
|
|
376
|
+
# new_ratio = max(0.01, min(100.0, new_ratio))
|
|
377
|
+
|
|
378
|
+
await redis_client.set(self.dynamic_estimate_key, new_ratio)
|
|
379
|
+
|
|
380
|
+
self.logger.info(
|
|
381
|
+
f"[Token Ratio] {self.token_key} | Observed: {observed_ratio:.5f} | "
|
|
382
|
+
f"Global Ratio: {current_ratio:.5f} -> {new_ratio:.5f}"
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
async def _post_function(self, result: tuple[QueryResult, float]) -> None:
|
|
386
|
+
"""Adjust token estimate based on actual usage"""
|
|
387
|
+
|
|
388
|
+
metadata = result[0].metadata
|
|
389
|
+
|
|
390
|
+
countable_input_tokens = metadata.total_input_tokens - (
|
|
391
|
+
metadata.cache_read_tokens or 0
|
|
392
|
+
)
|
|
393
|
+
countable_output_tokens = metadata.total_output_tokens
|
|
394
|
+
actual_tokens = countable_input_tokens + countable_output_tokens
|
|
395
|
+
|
|
396
|
+
difference = self.actual_estimate_total_tokens - actual_tokens
|
|
397
|
+
self.logger.info(
|
|
398
|
+
f"Adjusting {self.token_key} by {difference}. Estimated {self.actual_estimate_total_tokens}, actual {actual_tokens}"
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
await self._adjust_dynamic_estimate_ratio(actual_tokens)
|
|
402
|
+
|
|
403
|
+
# NOTE: this can generate negative values, which represent `debt`
|
|
404
|
+
async with redis_client.lock(self._token_key_lock, timeout=LOCK_TIMEOUT):
|
|
405
|
+
await redis_client.incrby(self.token_key, difference)
|
|
406
|
+
|
|
407
|
+
result[0].metadata.extra["token_metadata"] = {
|
|
408
|
+
"estimated": self.estimate_total_tokens,
|
|
409
|
+
"estimated_with_dynamic_ratio": self.actual_estimate_total_tokens,
|
|
410
|
+
"actual": actual_tokens,
|
|
411
|
+
"difference": difference,
|
|
412
|
+
"ratio": actual_tokens / self.estimate_total_tokens,
|
|
413
|
+
"dynamic_ratio_used": self.actual_estimate_total_tokens
|
|
414
|
+
/ self.estimate_total_tokens,
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
async def validate(self) -> None:
|
|
418
|
+
try:
|
|
419
|
+
assert redis_client
|
|
420
|
+
except Exception as e:
|
|
421
|
+
raise Exception(
|
|
422
|
+
f"redis client not set, run `TokenRetrier.set_redis_client`. Exception: {e}"
|
|
423
|
+
)
|
|
424
|
+
if not await redis_client.exists(self.token_key):
|
|
425
|
+
raise Exception(
|
|
426
|
+
"remaining_tokens not intialized, run `model.init_token_retry`"
|
|
427
|
+
)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import random
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def jitter(wait: float) -> float:
|
|
5
|
+
"""
|
|
6
|
+
Increase or decrease the wait time by up to 20%.
|
|
7
|
+
"""
|
|
8
|
+
jitter_fraction = 0.2
|
|
9
|
+
min_wait = wait * (1 - jitter_fraction)
|
|
10
|
+
max_wait = wait * (1 + jitter_fraction)
|
|
11
|
+
return random.uniform(min_wait, max_wait)
|
model_library/settings.py
CHANGED
|
@@ -22,7 +22,7 @@ class ModelLibrarySettings:
|
|
|
22
22
|
except AttributeError:
|
|
23
23
|
return default
|
|
24
24
|
|
|
25
|
-
def __getattr__(self, name: str) -> str
|
|
25
|
+
def __getattr__(self, name: str) -> str:
|
|
26
26
|
# load key from override
|
|
27
27
|
if name in self._key_overrides:
|
|
28
28
|
return self._key_overrides[name]
|
model_library/utils.py
CHANGED
|
@@ -2,6 +2,7 @@ import logging
|
|
|
2
2
|
from collections.abc import Mapping, Sequence
|
|
3
3
|
|
|
4
4
|
import httpx
|
|
5
|
+
from anthropic import AsyncAnthropic
|
|
5
6
|
from openai import AsyncOpenAI
|
|
6
7
|
from pydantic.main import BaseModel
|
|
7
8
|
|
|
@@ -62,6 +63,18 @@ def create_openai_client_with_defaults(
|
|
|
62
63
|
)
|
|
63
64
|
|
|
64
65
|
|
|
66
|
+
def create_anthropic_client_with_defaults(
|
|
67
|
+
api_key: str, base_url: str | None = None, default_headers: dict[str, str] = {}
|
|
68
|
+
) -> AsyncAnthropic:
|
|
69
|
+
return AsyncAnthropic(
|
|
70
|
+
base_url=base_url,
|
|
71
|
+
api_key=api_key,
|
|
72
|
+
default_headers=default_headers,
|
|
73
|
+
http_client=default_httpx_client(),
|
|
74
|
+
max_retries=3,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
|
|
65
78
|
def get_context_window_for_model(model_name: str, default: int = 128_000) -> int:
|
|
66
79
|
"""
|
|
67
80
|
Get the context window for a model by looking up its configuration from the registry.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: model-library
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.8
|
|
4
4
|
Summary: Model Library for vals.ai
|
|
5
5
|
Author-email: "Vals AI, Inc." <contact@vals.ai>
|
|
6
6
|
License: MIT
|
|
@@ -23,6 +23,7 @@ Requires-Dist: ai21<5.0,>=4.3.0
|
|
|
23
23
|
Requires-Dist: boto3<2.0,>=1.38.27
|
|
24
24
|
Requires-Dist: google-genai[aiohttp]>=1.51.0
|
|
25
25
|
Requires-Dist: google-cloud-storage>=1.26.0
|
|
26
|
+
Requires-Dist: pytest-xdist>=3.8.0
|
|
26
27
|
Dynamic: license-file
|
|
27
28
|
|
|
28
29
|
# Model Library
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
model_library/__init__.py,sha256=AKc_15aklOf-LbcS9z1Xer_moRWNpG6Dh3kqvSQ0nOI,714
|
|
2
|
+
model_library/exceptions.py,sha256=8d1BKI9wdzmF8hKH3lncwjvoQW7cT5b-rZ4GwqPndOY,6899
|
|
3
|
+
model_library/file_utils.py,sha256=FAZRRtDT8c4Rjfoj64Te3knEHggXAAfRRuS8WLCsSe8,3682
|
|
4
|
+
model_library/logging.py,sha256=rZrrVQlEmyZzvKx6nIOR8bKHl49wQIIW5c36Zqcigm4,888
|
|
5
|
+
model_library/model_utils.py,sha256=l8oCltGeimMGtnne_3Q1EguVtzCj61UMsLsma-1czwg,753
|
|
6
|
+
model_library/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
model_library/register_models.py,sha256=-CtFggD296wqO2nd6yC5GIWBoi0YD0kDyG8bwxBa1ec,13696
|
|
8
|
+
model_library/registry_utils.py,sha256=Qcu5du88RlcHo_mpZqOumLDie019sKQ_qX55XcjYWNc,9530
|
|
9
|
+
model_library/settings.py,sha256=6xD9RADiiLWDk3xafYeCV9_4ZwxA2vYzpul-VP3qQlQ,867
|
|
10
|
+
model_library/utils.py,sha256=uBLM9vfh2YG0pYsNSYCgmOc1GbE7zW9ykhBSlYJ3q0c,3302
|
|
11
|
+
model_library/base/__init__.py,sha256=TtxCXGUtkEqWZNMMofLPuC4orN7Ja2hemtbtHitt_UA,266
|
|
12
|
+
model_library/base/base.py,sha256=mB1oanWnXNk_C5M70LcwXQ1EvPdjFpcENq_Me2VvQJk,20588
|
|
13
|
+
model_library/base/batch.py,sha256=-jd6L0ECc5pkj73zoX2ZYcv_9iQdqxEi1kEilwaXWSA,2895
|
|
14
|
+
model_library/base/delegate_only.py,sha256=LYmci02i3ShQuF_3N0gJsUySVvFB__PEAgTQQryp0nA,4764
|
|
15
|
+
model_library/base/input.py,sha256=JrnvBZ_xLcEmaMjnOfUS6GFV0QWtCGpJq0RQQL2YBG8,1934
|
|
16
|
+
model_library/base/output.py,sha256=z8x3-0a3seRBuNwRDWgzdXjKS5bSASuR01qoRTmDoWI,8796
|
|
17
|
+
model_library/base/utils.py,sha256=AjVeC41vg8vbGGL0fQmSGtnnTuZ589Xl7ljv0N1Jzd0,3330
|
|
18
|
+
model_library/config/README.md,sha256=i8_wHnlI6uHIqWN9fYBkDCglZM2p5ZMVD3SLlxiwUVk,4274
|
|
19
|
+
model_library/config/ai21labs_models.yaml,sha256=ZWHhk1cep2GQIYHqkTS_0152mF3oZg2tSzMPmvfMRSI,2478
|
|
20
|
+
model_library/config/alibaba_models.yaml,sha256=KTNt9YJrAmgVKiQp3yeloiqaHg7PyobSK_97_p5kjbE,1826
|
|
21
|
+
model_library/config/all_models.json,sha256=5L_V2DQsJTESTfluxfqUo6FJOr55EaF8z5dSSCaevWU,537531
|
|
22
|
+
model_library/config/amazon_models.yaml,sha256=HgLmhpfedHCQtkPEviEJCBbAb-dNQPOnVtf4UnwrDds,7654
|
|
23
|
+
model_library/config/anthropic_models.yaml,sha256=bTc_3Oqn4wCdq-dcWcEfmXrPVZjcR8-V6pTao7sGa_E,10475
|
|
24
|
+
model_library/config/cohere_models.yaml,sha256=ZfWrS1K45Hxd5nT_gpP5YGAovJcBIlLNIdaRyE3V-7o,5022
|
|
25
|
+
model_library/config/deepseek_models.yaml,sha256=4CCrf-4UPBgFCrS6CQa3vzNiaYlD4B6dFJFK_kIYBWY,1156
|
|
26
|
+
model_library/config/dummy_model.yaml,sha256=lImYJBtBVJk_jgnLbkuSyOshQphVlYCMkw-UiJIBYhY,877
|
|
27
|
+
model_library/config/fireworks_models.yaml,sha256=bAlXvjkdt-CnRp66WbfDv2qTrF5UHceRd2pvrsBERMk,6324
|
|
28
|
+
model_library/config/google_models.yaml,sha256=Rg127nsBbHpk62X7WBq2ckdHo0bwYM0NVjF7T2h_1c0,16494
|
|
29
|
+
model_library/config/inception_models.yaml,sha256=YCqfQlkH_pTdHIKee5dP_aRFXw_fTIEQCpUvX2bwO0M,560
|
|
30
|
+
model_library/config/kimi_models.yaml,sha256=336jcbMhcKDHFNxzRIYxFTV7v2W_93y2sY-IkiYtkuo,1340
|
|
31
|
+
model_library/config/minimax_models.yaml,sha256=gWTuTcl1-zyCF6KRuU6DSre2Cw5gXC-TeKV2Qp4StnQ,1263
|
|
32
|
+
model_library/config/mistral_models.yaml,sha256=mYKYSzJl24lUiA_erSkom7nCBxAoeJ57Mi3090q1ArM,5162
|
|
33
|
+
model_library/config/openai_models.yaml,sha256=pKsYFF4TnuWnAJVby6Bw6JFJhr6rbkt75N4VIg40iO4,25061
|
|
34
|
+
model_library/config/perplexity_models.yaml,sha256=WUDqhLvnB0kQhCCwPv19FYLHozet3m33Spdo6bGff3Q,2336
|
|
35
|
+
model_library/config/together_models.yaml,sha256=BeqRJonYzPvWwoLfkyH0RMRKBYUrCSEQhg_25Nvx97M,23867
|
|
36
|
+
model_library/config/xai_models.yaml,sha256=2KRNNQy3kV-4xxSfhj7Uhp9TZF-S5qPlM8Ef-04zv8Y,7985
|
|
37
|
+
model_library/config/zai_models.yaml,sha256=-96aPrxpwWcEQD7vNZjDhTMi8lWYWl56AHYt-mwEkgM,2418
|
|
38
|
+
model_library/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
|
+
model_library/providers/ai21labs.py,sha256=xXqgk-bAC6WTZ7rvN9eHoE_IUukaU_qF3eLw-TX8gTY,6356
|
|
40
|
+
model_library/providers/alibaba.py,sha256=0oMgs09BmRknuY5E66OL987xjtIrLHMh2jzSce8UiCY,3226
|
|
41
|
+
model_library/providers/amazon.py,sha256=VvC0-DoZWXx-obMMkw9YLQOwwcMNYnCSIGrMGkun7tI,15589
|
|
42
|
+
model_library/providers/anthropic.py,sha256=SQuGxg_XH4g1nPDkrejYdW5pDRArm__IBUixYKlfWI8,25022
|
|
43
|
+
model_library/providers/azure.py,sha256=mEwoGz8ajwI6MW464spPoa36uFsPWaG_4WtwQZWkxuE,1784
|
|
44
|
+
model_library/providers/cohere.py,sha256=9ZGNekBlvubVw8o-emxdIhre_00iq5saENCVaD74Jqc,944
|
|
45
|
+
model_library/providers/deepseek.py,sha256=S7Ud80vKVJMCkovaLEtZEPr1jI_yfOq-R0Ln-jWwqdo,1040
|
|
46
|
+
model_library/providers/fireworks.py,sha256=y5Si_nRrvDKJnQtsoIFPFUO6s6Y6PBij8NVz6in5H9I,2146
|
|
47
|
+
model_library/providers/inception.py,sha256=_UHWd8b3_YbR5tHXOGwPkz5YHEBXVaYM8bP0i-yfZJE,985
|
|
48
|
+
model_library/providers/kimi.py,sha256=r1K0mbaNY_OUTERLttoItcjWMb9wTu7ghEIP0kXblG0,1362
|
|
49
|
+
model_library/providers/minimax.py,sha256=VTLzELrya4q_q5pdkmOA61kALbMu6ZkNxMdkuIZSDY8,1361
|
|
50
|
+
model_library/providers/mistral.py,sha256=SkIHBkeDZuLfNYkvcm7holk63zNIIGJ8KmoXjQi399o,10299
|
|
51
|
+
model_library/providers/openai.py,sha256=tDWozNzs8jcbtjQWEoMzYQq0qZObqOb_iK5AD-MVT3k,37618
|
|
52
|
+
model_library/providers/openrouter.py,sha256=FRKyeUyCSSQFCvoKvVbKzYJ_SL60jEU-Y6wWDyvevYc,962
|
|
53
|
+
model_library/providers/perplexity.py,sha256=GT7nfu42ATbG7Eu_J8nrIwJMr_BpFpLOaQVOQG4gtRk,961
|
|
54
|
+
model_library/providers/together.py,sha256=M1xAsbBd-41a3yHj2MDrysrIav9pp7eqGYUo16a4L8s,1911
|
|
55
|
+
model_library/providers/vals.py,sha256=lQXaQ6494r0Ujv2B9epLfVNdWk1nkMOZt1LKgAYsXhc,10084
|
|
56
|
+
model_library/providers/xai.py,sha256=WzAV1WnUrx9UenLGkP77JslKDFVz1T0g25PfCYzMOlw,10687
|
|
57
|
+
model_library/providers/zai.py,sha256=C-0Q41vEhsb6PIbFIW4kXGSx1-mTuB-czB7Vq1_KBqk,1924
|
|
58
|
+
model_library/providers/google/__init__.py,sha256=ypuLVL_QJEQ7C3S47FhC9y4wyawYOdGikAViJmACI0U,115
|
|
59
|
+
model_library/providers/google/batch.py,sha256=kqe9ponDe9Tkrh_-4kWd5-47wYf4V_XSKXZnrFOzAHc,10187
|
|
60
|
+
model_library/providers/google/google.py,sha256=9sEBUmLqKy1M62kwc_1ViaTDoW6j5rGA3z9kgCn9ATY,18418
|
|
61
|
+
model_library/retriers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
62
|
+
model_library/retriers/backoff.py,sha256=vmpzLje51yfvSgAEST_yNrL87_J_0pmI-jwnRek5Ie0,2296
|
|
63
|
+
model_library/retriers/base.py,sha256=zmiGZq4yvJx7aE0FD8rqZuJxZavhKTXLjt58z5TKJNw,6832
|
|
64
|
+
model_library/retriers/token.py,sha256=ypHzuJjEORsv931sjEI1lejRO8Ju_ljSrCGV4pgaa34,16794
|
|
65
|
+
model_library/retriers/utils.py,sha256=fhtQ64aT8mZcwZ8aTXnLRU4HVIf8JQ3CfmArvxZPWvQ,279
|
|
66
|
+
model_library-0.1.8.dist-info/licenses/LICENSE,sha256=x6mf4o7U_wHaaqcfxoU-0R6uYJLbqL_TNuoULP3asaA,1070
|
|
67
|
+
model_library-0.1.8.dist-info/METADATA,sha256=PlDQKGnuuNlRnlD5MiEUmc5egBmkFSjAGpJbup6sSAs,7024
|
|
68
|
+
model_library-0.1.8.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
69
|
+
model_library-0.1.8.dist-info/top_level.txt,sha256=HtQYxA_7RP8UT35I6VcUw20L6edI0Zf2t5Ys1uDGVjs,14
|
|
70
|
+
model_library-0.1.8.dist-info/RECORD,,
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
model_library/__init__.py,sha256=AKc_15aklOf-LbcS9z1Xer_moRWNpG6Dh3kqvSQ0nOI,714
|
|
2
|
-
model_library/exceptions.py,sha256=4TJ1aDkpPV-gv3gLIO7pi5ORRBG2hPXSBAvOXS6I_Wg,9027
|
|
3
|
-
model_library/file_utils.py,sha256=FAZRRtDT8c4Rjfoj64Te3knEHggXAAfRRuS8WLCsSe8,3682
|
|
4
|
-
model_library/logging.py,sha256=rZrrVQlEmyZzvKx6nIOR8bKHl49wQIIW5c36Zqcigm4,888
|
|
5
|
-
model_library/model_utils.py,sha256=l8oCltGeimMGtnne_3Q1EguVtzCj61UMsLsma-1czwg,753
|
|
6
|
-
model_library/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
model_library/register_models.py,sha256=-CtFggD296wqO2nd6yC5GIWBoi0YD0kDyG8bwxBa1ec,13696
|
|
8
|
-
model_library/registry_utils.py,sha256=BVauHcP02Et2maLxowNBbdpGd32cnLz1_zSjDLVJjp0,8843
|
|
9
|
-
model_library/settings.py,sha256=QyeUqzWBpexFi014L_mZkoXP49no3SAQNJRObATXrL8,873
|
|
10
|
-
model_library/utils.py,sha256=dcww26Ph0PSihEzSN4gZ48XXxN3Bt5oWveVYX6UACyI,2922
|
|
11
|
-
model_library/base/__init__.py,sha256=TtxCXGUtkEqWZNMMofLPuC4orN7Ja2hemtbtHitt_UA,266
|
|
12
|
-
model_library/base/base.py,sha256=nrdPS92-vFkDVJJvNVOQ8e6U1zCyZxOtFg18ZgM4o0s,17467
|
|
13
|
-
model_library/base/batch.py,sha256=-jd6L0ECc5pkj73zoX2ZYcv_9iQdqxEi1kEilwaXWSA,2895
|
|
14
|
-
model_library/base/delegate_only.py,sha256=5v2twEuQl1jF34M8iFcaZQlk0_uBLew4B46TkHUEssw,2441
|
|
15
|
-
model_library/base/input.py,sha256=JrnvBZ_xLcEmaMjnOfUS6GFV0QWtCGpJq0RQQL2YBG8,1934
|
|
16
|
-
model_library/base/output.py,sha256=jwd3rfRFUcqm8q-O5H684ToNZPvcD_obtf6ugmhzUus,7613
|
|
17
|
-
model_library/base/utils.py,sha256=eiMTiFFXHTb44Nnz3fjxf9YQzJpdfNI7tprSi9COPu0,2268
|
|
18
|
-
model_library/config/README.md,sha256=i8_wHnlI6uHIqWN9fYBkDCglZM2p5ZMVD3SLlxiwUVk,4274
|
|
19
|
-
model_library/config/ai21labs_models.yaml,sha256=ZWHhk1cep2GQIYHqkTS_0152mF3oZg2tSzMPmvfMRSI,2478
|
|
20
|
-
model_library/config/alibaba_models.yaml,sha256=-RLWOwh3ZaCQqjaZ-4Zw0BJNVE6JVHJ8Ggm9gQJZ6QI,2082
|
|
21
|
-
model_library/config/all_models.json,sha256=U-XQrbaWWhjmkawg0Bd9NTxoDN-DT0WPhmDLF6OALR4,533621
|
|
22
|
-
model_library/config/amazon_models.yaml,sha256=HgLmhpfedHCQtkPEviEJCBbAb-dNQPOnVtf4UnwrDds,7654
|
|
23
|
-
model_library/config/anthropic_models.yaml,sha256=bTc_3Oqn4wCdq-dcWcEfmXrPVZjcR8-V6pTao7sGa_E,10475
|
|
24
|
-
model_library/config/cohere_models.yaml,sha256=ZfWrS1K45Hxd5nT_gpP5YGAovJcBIlLNIdaRyE3V-7o,5022
|
|
25
|
-
model_library/config/deepseek_models.yaml,sha256=4CCrf-4UPBgFCrS6CQa3vzNiaYlD4B6dFJFK_kIYBWY,1156
|
|
26
|
-
model_library/config/dummy_model.yaml,sha256=lImYJBtBVJk_jgnLbkuSyOshQphVlYCMkw-UiJIBYhY,877
|
|
27
|
-
model_library/config/fireworks_models.yaml,sha256=bAlXvjkdt-CnRp66WbfDv2qTrF5UHceRd2pvrsBERMk,6324
|
|
28
|
-
model_library/config/google_models.yaml,sha256=Rg127nsBbHpk62X7WBq2ckdHo0bwYM0NVjF7T2h_1c0,16494
|
|
29
|
-
model_library/config/inception_models.yaml,sha256=YCqfQlkH_pTdHIKee5dP_aRFXw_fTIEQCpUvX2bwO0M,560
|
|
30
|
-
model_library/config/kimi_models.yaml,sha256=AAqse_BCE-lrHkJHIWJVqMtttnZQCa-5Qy5qiLUJjYs,755
|
|
31
|
-
model_library/config/minimax_models.yaml,sha256=gWTuTcl1-zyCF6KRuU6DSre2Cw5gXC-TeKV2Qp4StnQ,1263
|
|
32
|
-
model_library/config/mistral_models.yaml,sha256=mYKYSzJl24lUiA_erSkom7nCBxAoeJ57Mi3090q1ArM,5162
|
|
33
|
-
model_library/config/openai_models.yaml,sha256=1lKsTQwsxMMJqXtEoYs3liy6NcaK4p8NN7b-GSFnl8k,25261
|
|
34
|
-
model_library/config/perplexity_models.yaml,sha256=WUDqhLvnB0kQhCCwPv19FYLHozet3m33Spdo6bGff3Q,2336
|
|
35
|
-
model_library/config/together_models.yaml,sha256=BeqRJonYzPvWwoLfkyH0RMRKBYUrCSEQhg_25Nvx97M,23867
|
|
36
|
-
model_library/config/xai_models.yaml,sha256=2KRNNQy3kV-4xxSfhj7Uhp9TZF-S5qPlM8Ef-04zv8Y,7985
|
|
37
|
-
model_library/config/zai_models.yaml,sha256=lcYMh2FCrLWkKqdCnarRlwDoL3SbutRBNAiMPBUYQiw,1894
|
|
38
|
-
model_library/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
|
-
model_library/providers/ai21labs.py,sha256=NXoEu0NFwxLVJIN751tEuKLFYk4ECSDnWMik35pL5Y4,6277
|
|
40
|
-
model_library/providers/alibaba.py,sha256=k6LZErV_l9oTFTdKTwyw1SXD509Rl3AqFbN8umCryEE,2941
|
|
41
|
-
model_library/providers/amazon.py,sha256=F8anL4pmeadA0P9luUZSSnEcke90WH7mCa3afJ2akgM,14156
|
|
42
|
-
model_library/providers/anthropic.py,sha256=xbSZx6R54UhNQij-vwFKPCIQJoTzxLblJMIxdqGcsqs,23094
|
|
43
|
-
model_library/providers/azure.py,sha256=brQNCED-zHvYjL5K5hdjFBNso6hJZg0HTHNnAgJPPG0,1408
|
|
44
|
-
model_library/providers/cohere.py,sha256=lCBm1PP1l_UOa1pKFMIZM3C0wCv3QWB6UP0-jvjkFa4,1066
|
|
45
|
-
model_library/providers/deepseek.py,sha256=7T4lxDiV5wmWUK7TAKwr332_T6uyXNCOiirZOCCETL0,1159
|
|
46
|
-
model_library/providers/fireworks.py,sha256=w-5mOF5oNzqx_0ijCoTm1lSn2ZHwhp6fURKhV3LEqIc,2309
|
|
47
|
-
model_library/providers/inception.py,sha256=Nrky53iujIM9spAWoNRtoJg2inFiL0li6E75vT3b6V8,1107
|
|
48
|
-
model_library/providers/kimi.py,sha256=zzvcKpZLsM1xPebpLeMxNKTt_FRiLN1rFWrIly7wfXA,1092
|
|
49
|
-
model_library/providers/minimax.py,sha256=ckVyoXdtVxGT3aU-AknBQCa7_mOckNMfOXSgwbrJNIY,1610
|
|
50
|
-
model_library/providers/mistral.py,sha256=kmp74jEETMnB8fQ5VNfNVkksIrPMGJwJeXJDnTVwKa8,10117
|
|
51
|
-
model_library/providers/openai.py,sha256=gMykcN5eHFHqCrK9y5twc18h7XSMI68mB9YGYnpt93A,34522
|
|
52
|
-
model_library/providers/perplexity.py,sha256=eIzzkaZ4ZMlRKFVI9bnwyo91iJkh7aEmJ-0_4OKeAWc,1083
|
|
53
|
-
model_library/providers/together.py,sha256=7Y4QLnX8c_fyXUud-W_C1gidmROQainTgODBwbvFyXQ,2033
|
|
54
|
-
model_library/providers/vals.py,sha256=dbaL8toYTssm8qVlrgqzqwCeeTV9h-xfA37uBuoWtfg,9894
|
|
55
|
-
model_library/providers/xai.py,sha256=eA3CsiOWIF_vKxNZC95INUKOazz54R6vpVrGM8VR1tY,10719
|
|
56
|
-
model_library/providers/zai.py,sha256=O_GM6KlJ0fM2wYoxO9xrCWfnpYH7IpoKEzjiD4jB8Kc,1050
|
|
57
|
-
model_library/providers/google/__init__.py,sha256=ypuLVL_QJEQ7C3S47FhC9y4wyawYOdGikAViJmACI0U,115
|
|
58
|
-
model_library/providers/google/batch.py,sha256=ycK2arf00lhZQNgyM5Yd01LAScul6rvVv--dUcRWWSA,9977
|
|
59
|
-
model_library/providers/google/google.py,sha256=txQaet1HobyjYd3dp9Mgonx3x5ln3LMuW10Qsyum3B4,17809
|
|
60
|
-
model_library-0.1.7.dist-info/licenses/LICENSE,sha256=x6mf4o7U_wHaaqcfxoU-0R6uYJLbqL_TNuoULP3asaA,1070
|
|
61
|
-
model_library-0.1.7.dist-info/METADATA,sha256=436seE0dN2884VkHzGHyp36aARqBxqKMKRccmKYG3_E,6989
|
|
62
|
-
model_library-0.1.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
63
|
-
model_library-0.1.7.dist-info/top_level.txt,sha256=HtQYxA_7RP8UT35I6VcUw20L6edI0Zf2t5Ys1uDGVjs,14
|
|
64
|
-
model_library-0.1.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|