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.
Files changed (45) hide show
  1. model_library/base/base.py +139 -62
  2. model_library/base/delegate_only.py +77 -10
  3. model_library/base/output.py +43 -0
  4. model_library/base/utils.py +35 -0
  5. model_library/config/alibaba_models.yaml +44 -57
  6. model_library/config/all_models.json +253 -126
  7. model_library/config/kimi_models.yaml +30 -3
  8. model_library/config/openai_models.yaml +15 -23
  9. model_library/config/zai_models.yaml +24 -3
  10. model_library/exceptions.py +3 -77
  11. model_library/providers/ai21labs.py +12 -8
  12. model_library/providers/alibaba.py +17 -8
  13. model_library/providers/amazon.py +49 -16
  14. model_library/providers/anthropic.py +93 -40
  15. model_library/providers/azure.py +22 -10
  16. model_library/providers/cohere.py +7 -7
  17. model_library/providers/deepseek.py +8 -8
  18. model_library/providers/fireworks.py +7 -8
  19. model_library/providers/google/batch.py +14 -10
  20. model_library/providers/google/google.py +48 -29
  21. model_library/providers/inception.py +7 -7
  22. model_library/providers/kimi.py +18 -8
  23. model_library/providers/minimax.py +15 -17
  24. model_library/providers/mistral.py +20 -8
  25. model_library/providers/openai.py +99 -22
  26. model_library/providers/openrouter.py +34 -0
  27. model_library/providers/perplexity.py +7 -7
  28. model_library/providers/together.py +7 -8
  29. model_library/providers/vals.py +12 -6
  30. model_library/providers/xai.py +47 -42
  31. model_library/providers/zai.py +38 -8
  32. model_library/registry_utils.py +39 -15
  33. model_library/retriers/__init__.py +0 -0
  34. model_library/retriers/backoff.py +73 -0
  35. model_library/retriers/base.py +225 -0
  36. model_library/retriers/token.py +427 -0
  37. model_library/retriers/utils.py +11 -0
  38. model_library/settings.py +1 -1
  39. model_library/utils.py +13 -0
  40. {model_library-0.1.7.dist-info → model_library-0.1.8.dist-info}/METADATA +2 -1
  41. model_library-0.1.8.dist-info/RECORD +70 -0
  42. {model_library-0.1.7.dist-info → model_library-0.1.8.dist-info}/WHEEL +1 -1
  43. model_library-0.1.7.dist-info/RECORD +0 -64
  44. {model_library-0.1.7.dist-info → model_library-0.1.8.dist-info}/licenses/LICENSE +0 -0
  45. {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 | Any:
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.7
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,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -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,,