group-wbl/.venv/lib/python3.13/site-packages/langgraph/_internal/_cache.py

32 lines
1.2 KiB
Python
Raw Normal View History

2026-01-09 09:48:03 +08:00
from __future__ import annotations
from collections.abc import Hashable, Mapping, Sequence
from typing import Any
def _freeze(obj: Any, depth: int = 10) -> Hashable:
if isinstance(obj, Hashable) or depth <= 0:
# already hashable, no need to freeze
return obj
elif isinstance(obj, Mapping):
# sort keys so {"a":1,"b":2} == {"b":2,"a":1}
return tuple(sorted((k, _freeze(v, depth - 1)) for k, v in obj.items()))
elif isinstance(obj, Sequence):
return tuple(_freeze(x, depth - 1) for x in obj)
# numpy / pandas etc. can provide their own .tobytes()
elif hasattr(obj, "tobytes"):
return (
type(obj).__name__,
obj.tobytes(),
obj.shape if hasattr(obj, "shape") else None,
)
return obj # strings, ints, dataclasses with frozen=True, etc.
def default_cache_key(*args: Any, **kwargs: Any) -> str | bytes:
"""Default cache key function that uses the arguments and keyword arguments to generate a hashable key."""
import pickle
# protocol 5 strikes a good balance between speed and size
return pickle.dumps((_freeze(args), _freeze(kwargs)), protocol=5, fix_imports=False)