Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions dspy/clients/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@

DISK_CACHE_DIR = os.environ.get("DSPY_CACHEDIR") or os.path.join(Path.home(), ".dspy_cache")
DISK_CACHE_LIMIT = int(os.environ.get("DSPY_CACHE_LIMIT", 3e10)) # 30 GB default


def configure_cache(
enable_disk_cache: bool | None = True,
enable_memory_cache: bool | None = True,
disk_cache_dir: str | None = DISK_CACHE_DIR,
disk_size_limit_bytes: int | None = DISK_CACHE_LIMIT,
memory_max_entries: int | None = 1000000,
memory_max_entries: int = 1000000,
):
"""Configure the cache for DSPy.

Expand All @@ -28,7 +30,8 @@ def configure_cache(
enable_memory_cache: Whether to enable in-memory cache.
disk_cache_dir: The directory to store the on-disk cache.
disk_size_limit_bytes: The size limit of the on-disk cache.
memory_max_entries: The maximum number of entries in the in-memory cache.
memory_max_entries: The maximum number of entries in the in-memory cache. To allow the cache to grow without
bounds, set this parameter to `math.inf` or a similar value.
"""

DSPY_CACHE = Cache(
Expand All @@ -40,13 +43,15 @@ def configure_cache(
)

import dspy

# Update the reference to point to the new cache
dspy.cache = DSPY_CACHE


litellm.telemetry = False
litellm.cache = None # By default we disable LiteLLM cache and use DSPy on-disk cache.


def _get_dspy_cache():
disk_cache_dir = os.environ.get("DSPY_CACHEDIR") or os.path.join(Path.home(), ".dspy_cache")
disk_cache_limit = int(os.environ.get("DSPY_CACHE_LIMIT", 3e10))
Expand All @@ -71,6 +76,7 @@ def _get_dspy_cache():
)
return _dspy_cache


DSPY_CACHE = _get_dspy_cache()

if "LITELLM_LOCAL_MODEL_COST_MAP" not in os.environ:
Expand Down
6 changes: 5 additions & 1 deletion dspy/clients/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def __init__(
enable_memory_cache: bool,
disk_cache_dir: str,
disk_size_limit_bytes: int | None = 1024 * 1024 * 10,
memory_max_entries: int | None = 1000000,
memory_max_entries: int = 1000000,
):
"""
Args:
Expand All @@ -43,6 +43,10 @@ def __init__(
self.enable_disk_cache = enable_disk_cache
self.enable_memory_cache = enable_memory_cache
if self.enable_memory_cache:
if memory_max_entries is None:
raise ValueError("`memory_max_entries` cannot be None. Use `math.inf` if you need an unbounded cache.")
elif memory_max_entries <= 0:
raise ValueError(f"`memory_max_entries` must be a positive number, but received {memory_max_entries}")
self.memory_cache = LRUCache(maxsize=memory_max_entries)
else:
self.memory_cache = {}
Expand Down
21 changes: 21 additions & 0 deletions tests/clients/test_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,27 @@ def test_initialization(tmp_path):
assert disabled_cache.disk_cache == {}


def test_invalid_cache_initialization():
with pytest.raises(ValueError, match=r"`memory_max_entries` must be a positive number, but received -1"):
Cache(
enable_disk_cache=False,
enable_memory_cache=True,
disk_cache_dir="",
disk_size_limit_bytes=0,
memory_max_entries=-1,
)
with pytest.raises(
ValueError, match=r"`memory_max_entries` cannot be None. Use `math.inf` if you need an unbounded cache."
):
Cache(
enable_disk_cache=False,
enable_memory_cache=True,
disk_cache_dir="",
disk_size_limit_bytes=0,
memory_max_entries=None,
)


def test_cache_key_generation(cache):
"""Test cache key generation with different types of inputs."""
# Test with simple dictionary
Expand Down