Skip to content
Open
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
40 changes: 30 additions & 10 deletions dspy/clients/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,27 +63,47 @@ def configure_cache(
else:
litellm.cache = None

import dspy

dspy.cache = Cache(
DSPY_CACHE = Cache(
enable_disk_cache,
enable_memory_cache,
disk_cache_dir,
disk_size_limit_bytes,
memory_max_entries,
)

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.

DSPY_CACHE = Cache(
enable_disk_cache=True,
enable_memory_cache=True,
disk_cache_dir=DISK_CACHE_DIR,
disk_size_limit_bytes=DISK_CACHE_LIMIT,
memory_max_entries=1000000,
)
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))

try:
_dspy_cache = Cache(
enable_disk_cache=True,
enable_memory_cache=True,
disk_cache_dir=disk_cache_dir,
disk_size_limit_bytes=disk_cache_limit,
memory_max_entries=1000000,
)
except Exception as e:
# If cache creation fails (e.g., in AWS Lambda), create a memory-only cache
logger.warning("Failed to initialize disk cache, falling back to memory-only cache: %s", e)
_dspy_cache = Cache(
enable_disk_cache=False,
enable_memory_cache=True,
disk_cache_dir=disk_cache_dir,
disk_size_limit_bytes=disk_cache_limit,
memory_max_entries=1000000,
)
return _dspy_cache

DSPY_CACHE = _get_dspy_cache()

if "LITELLM_LOCAL_MODEL_COST_MAP" not in os.environ:
# Accessed at run time by litellm; i.e., fine to keep after import
Expand Down
27 changes: 27 additions & 0 deletions tests/clients/test_cache.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
from dataclasses import dataclass
from unittest.mock import patch

Expand Down Expand Up @@ -317,3 +318,29 @@ def test_function(**kwargs):
)
is not None
)


def test_cache_fallback_on_restricted_environment():
"""Test that DSPy gracefully falls back to memory-only cache when disk cache fails."""
old_env = os.environ.get("DSPY_CACHEDIR")
try:
# Set an invalid cache directory that can't be created
os.environ["DSPY_CACHEDIR"] = "/dev/null/invalid_path"

import dspy
from dspy.clients import _get_dspy_cache

dspy.cache = _get_dspy_cache()

# Cache should work with memory-only fallback despite invalid disk path
test_request = {"model": "test", "prompt": "hello"}
dspy.cache.put(test_request, "fallback_result")
result = dspy.cache.get(test_request)

assert result == "fallback_result", "Memory cache fallback should work"

finally:
if old_env is None:
os.environ.pop("DSPY_CACHEDIR", None)
else:
os.environ["DSPY_CACHEDIR"] = old_env