Skip to content

Commit beceb5c

Browse files
lpalbouAwni Hannun
andauthored
Fix ArraysCache.from_state not initializing left_padding and lengths (ml-explore#807)
* Fix ArraysCache.from_state not initializing left_padding and lengths The base class from_state uses __new__ to bypass __init__, but ArraysCache.state.setter only sets self.cache, not left_padding or lengths. This causes AttributeError when using loaded caches with models that use MambaCache (e.g., Qwen3-Next). The fix overrides from_state in ArraysCache to properly initialize these attributes before setting state. * Add test --------- Co-authored-by: Awni Hannun <awni@apple.com>
1 parent 12073b1 commit beceb5c

2 files changed

Lines changed: 21 additions & 2 deletions

File tree

mlx_lm/models/cache.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -561,10 +561,16 @@ def empty(self):
561561

562562

563563
class ArraysCache(_BaseCache):
564+
def __new__(cls, *args, **kwargs):
565+
instance = super().__new__(cls)
566+
instance.left_padding = None
567+
instance.lengths = None
568+
return instance
569+
564570
def __init__(self, size, left_padding: Optional[List[int]] = None):
565571
self.cache = [None] * size
566-
self.left_padding = mx.array(left_padding) if left_padding else None
567-
self.lengths = None
572+
if left_padding:
573+
self.left_padding = mx.array(left_padding)
568574

569575
def __setitem__(self, idx, value):
570576
self.cache[idx] = value

tests/test_prompt_cache.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,19 @@ def test_save_load_mixed_cache(self):
133133
self.assertTrue(mx.array_equal(k, lk))
134134
self.assertTrue(mx.array_equal(v, lv))
135135

136+
def test_save_load_mamba_cache(self):
137+
cache_file = os.path.join(self.test_dir, "prompt_cache.safetensors")
138+
139+
cache = [MambaCache()]
140+
cache[0][0] = mx.zeros((1, 4, 4))
141+
cache[0][1] = mx.zeros((1, 4, 4))
142+
143+
save_prompt_cache(cache_file, cache)
144+
loaded = load_prompt_cache(cache_file)
145+
146+
# Try to make a mask
147+
mask = loaded[0].make_mask(4)
148+
136149
def test_cache_with_generate(self):
137150
model, tokenizer = self.model, self.tokenizer
138151
prompt = tokenizer.encode("this is a prompt", return_tensors="mlx")[0]

0 commit comments

Comments
 (0)