llmasajudge 0.1.11__py3-none-any.whl → 0.1.13__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.
llmasajudge/__init__.py CHANGED
@@ -214,6 +214,125 @@ from litellm.caching.caching import Cache
214
214
  __all__ = ["LLMAsAJudge", "OutputParsers"]
215
215
 
216
216
 
217
+ class UnlimitedDiskCache:
218
+ """
219
+ Drop-in replacement backend with 'unlimited' size for LiteLLM cache.
220
+
221
+ This wraps diskcache.Cache with a very large size limit (2^62 bytes ~ 4.6 exabytes)
222
+ to effectively disable automatic cache eviction, allowing the cache to grow
223
+ without size constraints.
224
+ """
225
+
226
+ def __init__(self, directory, size_limit=None):
227
+ """
228
+ Initialize unlimited disk cache.
229
+
230
+ Args:
231
+ directory: Path to cache directory
232
+ size_limit: Optional size limit in bytes. If None, uses 2^62 bytes (~4.6 exabytes)
233
+ """
234
+ import diskcache as dc
235
+
236
+ # Set to very large cap so culling never triggers (effectively unlimited)
237
+ cap = size_limit if size_limit is not None else (1 << 62)
238
+ self._dc = dc.Cache(directory, size_limit=cap)
239
+
240
+ # Sync API used by LiteLLM
241
+ def get_cache(self, key, **kwargs):
242
+ """Get value from cache by key."""
243
+ return self._dc.get(key)
244
+
245
+ def set_cache(self, key, value, ttl=None, **kwargs):
246
+ """Set value in cache with optional TTL."""
247
+ expire = None if ttl is None else float(ttl)
248
+ self._dc.set(key, value, expire=expire)
249
+
250
+ # Async API used by LiteLLM
251
+ async def async_get_cache(self, key, **kwargs):
252
+ """Async get value from cache by key."""
253
+ return self.get_cache(key, **kwargs)
254
+
255
+ async def async_set_cache(self, key, value, ttl=None, **kwargs):
256
+ """Async set value in cache with optional TTL."""
257
+ return self.set_cache(key, value, ttl=ttl, **kwargs)
258
+
259
+ async def async_set_cache_pipeline(self, cache_list, ttl=None, **kwargs):
260
+ """
261
+ Async batch set multiple cache entries.
262
+
263
+ Args:
264
+ cache_list: List of (key, value) tuples
265
+ ttl: Optional time-to-live in seconds
266
+ """
267
+ for k, v in cache_list:
268
+ self.set_cache(k, v, ttl=ttl)
269
+
270
+ async def batch_cache_write(self, key, value, ttl=None, **kwargs):
271
+ """Async batch write (single entry)."""
272
+ self.set_cache(key, value, ttl=ttl)
273
+
274
+ async def ping(self):
275
+ """Async ping check."""
276
+ return True
277
+
278
+ async def delete_cache_keys(self, keys):
279
+ """
280
+ Async delete multiple cache keys.
281
+
282
+ Args:
283
+ keys: List of keys to delete
284
+ """
285
+ for k in keys:
286
+ try:
287
+ del self._dc[k]
288
+ except KeyError:
289
+ pass
290
+ return True
291
+
292
+ async def disconnect(self):
293
+ """Async disconnect and close cache."""
294
+ self._dc.close()
295
+
296
+ def get_stats(self):
297
+ """
298
+ Get cache statistics.
299
+
300
+ Returns:
301
+ dict with size_limit, current_size, item_count, and percent_full
302
+ """
303
+ size_limit = self._dc.size_limit
304
+ volume = self._dc.volume() # Current size in bytes
305
+ count = len(self._dc) # Number of items
306
+
307
+ return {
308
+ "size_limit": size_limit,
309
+ "current_size": volume,
310
+ "item_count": count,
311
+ "percent_full": (volume / size_limit) * 100 if size_limit > 0 else 0.0,
312
+ }
313
+
314
+ def print_stats(self):
315
+ """Print human-readable cache statistics."""
316
+ stats = self.get_stats()
317
+
318
+ def human_size(bytes_val):
319
+ """Convert bytes to human readable format."""
320
+ for unit in ["B", "KB", "MB", "GB", "TB", "PB", "EB"]:
321
+ if bytes_val < 1024.0:
322
+ return f"{bytes_val:.2f} {unit}"
323
+ bytes_val /= 1024.0
324
+ return f"{bytes_val:.2f} EB"
325
+
326
+ print("=" * 60)
327
+ print("CACHE STATISTICS")
328
+ print("=" * 60)
329
+ print(f" Size limit: {human_size(stats['size_limit'])} ({stats['size_limit']:,} bytes)")
330
+ print(f" Current size: {human_size(stats['current_size'])} ({stats['current_size']:,} bytes)")
331
+ print(f" Items cached: {stats['item_count']}")
332
+ print(f" % full: {stats['percent_full']:.6f}%")
333
+ print("=" * 60)
334
+
335
+
217
336
  class OutputParsers:
218
337
  """Stock output parsers for common judge output formats."""
219
338
 
@@ -455,7 +574,9 @@ Output only the number. No explanation. No extra text.""",
455
574
  backoff_max: float = 4.0,
456
575
  custom_generation_fns: Optional[List[Callable[[str], str]]] = None,
457
576
  mode: str = "majority",
577
+ use_cache: bool = False,
458
578
  litellm_cache_dir: Optional[str] = None,
579
+ cache_size_gb: Optional[float] = None,
459
580
  ):
460
581
  self.models = models or []
461
582
  self.custom_generation_fns = custom_generation_fns or []
@@ -516,9 +637,20 @@ Output only the number. No explanation. No extra text.""",
516
637
  )
517
638
 
518
639
  # optional local cache setup
519
- self.cache_enabled = litellm_cache_dir is not None
640
+ # Enable cache if use_cache=True OR if litellm_cache_dir is explicitly provided (backward compatible)
641
+ self.cache_enabled = use_cache or (litellm_cache_dir is not None)
520
642
  if self.cache_enabled:
521
- litellm.cache = Cache(type="disk", disk_cache_dir=litellm_cache_dir)
643
+ # Only set up cache if it hasn't been set up already
644
+ if litellm.cache is None:
645
+ # Set default cache directory if not specified
646
+ if litellm_cache_dir is None:
647
+ litellm_cache_dir = ".litellm_cache"
648
+
649
+ # Convert GB to bytes if specified, otherwise unlimited
650
+ size_limit_bytes = None if cache_size_gb is None else int(cache_size_gb * 1024 * 1024 * 1024)
651
+ cache_backend = UnlimitedDiskCache(litellm_cache_dir, size_limit=size_limit_bytes)
652
+ litellm.cache = Cache(disk_cache_dir=litellm_cache_dir)
653
+ litellm.cache.cache = cache_backend
522
654
 
523
655
 
524
656
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: llmasajudge
3
- Version: 0.1.11
3
+ Version: 0.1.13
4
4
  Summary: LLM Judge: simple right/wrong voting across models
5
5
  Author-email: Brett Young <byyoung3@gmail.com>
6
6
  Project-URL: Homepage, https://example.com
@@ -0,0 +1,5 @@
1
+ llmasajudge/__init__.py,sha256=u_92YWEEMEPnAxb_uyUiOsn7tkD5x2Z4_ZlAihT9STY,32405
2
+ llmasajudge-0.1.13.dist-info/METADATA,sha256=uuYRR5rYdvvEF8Pcx3Qheo58l3CXgIWzOzC7om6uCbQ,515
3
+ llmasajudge-0.1.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
4
+ llmasajudge-0.1.13.dist-info/top_level.txt,sha256=rRaIpM1llpEqahR9flT3RjpZHi2o16iOgnGYJ8cO4_0,12
5
+ llmasajudge-0.1.13.dist-info/RECORD,,
@@ -1,5 +0,0 @@
1
- llmasajudge/__init__.py,sha256=IkCie_90ABggVrtTVXKhf1VSLgWQ9qRrAb9VN0I0uSo,27626
2
- llmasajudge-0.1.11.dist-info/METADATA,sha256=rTP1z67wo_ewBiMIx8819MiWjmXqtOno9mfBH0aRpwc,515
3
- llmasajudge-0.1.11.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
4
- llmasajudge-0.1.11.dist-info/top_level.txt,sha256=rRaIpM1llpEqahR9flT3RjpZHi2o16iOgnGYJ8cO4_0,12
5
- llmasajudge-0.1.11.dist-info/RECORD,,