| import numpy as np |
|
|
| from mla.model import Config, Model |
| from mla.kvcache import KVCache, forward_cached |
|
|
|
|
| def _tiny(): |
| return Config(vocab_size=64, d_model=32, n_layers=2, n_heads=4, |
| n_kv_heads=2, head_dim=8, swiglu_hidden=48, seq_len=16) |
|
|
|
|
| def test_cached_matches_full_forward(): |
| cfg = _tiny() |
| model = Model(cfg) |
| rng = np.random.default_rng(0) |
| T = 10 |
| ids = rng.integers(0, cfg.vocab_size, size=T) |
|
|
| full = model(np.array([ids], dtype=np.int64)).data[0] |
|
|
| cache = KVCache(cfg.n_layers) |
| step_logits = [] |
| for t in range(T): |
| lg = forward_cached(model, np.array([[ids[t]]], dtype=np.int64), cache) |
| step_logits.append(np.asarray(lg)[0, -1]) |
| inc = np.stack(step_logits) |
|
|
| assert cache.length() == T |
| assert np.allclose(full, inc, atol=1e-6, rtol=1e-6) |
|
|
|
|
| def test_cached_chunk_prefill_matches(): |
| cfg = _tiny() |
| model = Model(cfg) |
| rng = np.random.default_rng(1) |
| T = 8 |
| ids = rng.integers(0, cfg.vocab_size, size=T) |
|
|
| full = model(np.array([ids], dtype=np.int64)).data[0] |
|
|
| cache = KVCache(cfg.n_layers) |
| prefill = forward_cached(model, np.array([ids[:5]], dtype=np.int64), cache) |
| assert np.allclose(np.asarray(prefill)[0], full[:5], atol=1e-6, rtol=1e-6) |
| for t in range(5, T): |
| lg = forward_cached(model, np.array([[ids[t]]], dtype=np.int64), cache) |
| assert np.allclose(np.asarray(lg)[0, -1], full[t], atol=1e-6, rtol=1e-6) |
|
|