Download code/tests/test_depth_module.py from maxpicy/mamba-cot-tts: direct link, hf CLI and curl.
- Browser
- Download file 5.36 kB
-
https://huggingface.co/maxpicy/mamba-cot-tts/resolve/main/code/tests/test_depth_module.py
- Command line
-
hf download hf://maxpicy/mamba-cot-tts/code/tests/test_depth_module.py
-
curl -L -o test_depth_module.py https://huggingface.co/maxpicy/mamba-cot-tts/resolve/main/code/tests/test_depth_module.py
5.36 kB
| # test_depth_module.py: The depth module and the frame-aligned grid. | |
| import sys | |
| from pathlib import Path | |
| import pytest | |
| import torch | |
| _REPO = Path(__file__).resolve().parent.parent | |
| sys.path.insert(0, str(_REPO)) | |
| def _module(**kw): | |
| from model import DepthModule | |
| torch.manual_seed(0) | |
| return DepthModule(d_model=64, num_levels=8, codebook_size=32, | |
| d_depth=48, num_layers=2, **kw) | |
| def test_loss_finite_and_semantic_weight(): | |
| m = _module() | |
| h = torch.randn(10, 64) | |
| tgt = torch.randint(0, 32, (10, 8)) | |
| l1 = m.forward_loss(h, tgt, semantic_weight=1.0) | |
| l2 = m.forward_loss(h, tgt, semantic_weight=3.0) | |
| assert torch.isfinite(l1) and l1.item() > 0 | |
| assert l2.item() > l1.item() | |
| lvl0 = l2.item() - l1.item() | |
| assert lvl0 > 0 | |
| def test_grad_flow_all_params(): | |
| m = _module() | |
| h = torch.randn(6, 64, requires_grad=True) | |
| tgt = torch.randint(0, 32, (6, 8)) | |
| loss = m.forward_loss(h, tgt) | |
| loss.backward() | |
| for name, p in m.named_parameters(): | |
| assert p.grad is not None, name | |
| assert torch.isfinite(p.grad).all(), name | |
| assert h.grad is not None and h.grad.abs().sum() > 0 | |
| def test_generate_frame_valid_and_deterministic(): | |
| m = _module() | |
| m.eval() | |
| h = torch.randn(1, 64) | |
| out1 = m.generate_frame(h) | |
| out2 = m.generate_frame(h) | |
| assert out1 == out2 | |
| assert len(out1) == 8 | |
| assert all(0 <= c < 32 for c in out1) | |
| out3 = m.generate_frame(h, level_temps=[0.0] + [1.0] * 7, top_k=5) | |
| assert len(out3) == 8 and all(0 <= c < 32 for c in out3) | |
| assert out3[0] == out1[0] | |
| def test_intra_frame_conditioning_is_causal(): | |
| m = _module() | |
| m.eval() | |
| h = torch.randn(3, 64) | |
| t1 = torch.randint(0, 32, (3, 8)) | |
| t2 = t1.clone() | |
| t2[:, 0] = (t2[:, 0] + 1) % 32 | |
| x1 = m._inputs_teacher_forced(h, t1) | |
| x2 = m._inputs_teacher_forced(h, t2) | |
| assert torch.equal(x1[:, 0], x2[:, 0]) | |
| assert not torch.equal(x1[:, 1], x2[:, 1]) | |
| def test_cross_frame_backcompat_default_off(): | |
| m = _module() | |
| assert not hasattr(m, "cross_embeds") | |
| assert not hasattr(m, "cross_start") | |
| assert m.cross_frame == 0 | |
| assert m._cross_summary(torch.randint(0, 32, (4, 8))) is None | |
| h = torch.randn(4, 64) | |
| tgt = torch.randint(0, 32, (4, 8)) | |
| x_none = m._inputs_teacher_forced(h, tgt, prev_codes=None) | |
| x_legacy = m._inputs_teacher_forced(h, tgt) | |
| assert torch.equal(x_none, x_legacy) | |
| def test_cross_frame_train_inference_parity(): | |
| m = _module(cross_frame=3) | |
| m.eval() | |
| h = torch.randn(1, 64) | |
| prev = torch.randint(0, 32, (8,)).tolist() | |
| gen = m.generate_frame(h, prev_codes=prev) | |
| tgt = torch.tensor(gen).view(1, 8) | |
| x = m._inputs_teacher_forced(h, tgt, prev_codes=torch.tensor(prev).view(1, 8)) | |
| y, _ = m.gru(x) | |
| y = m.norm(y) | |
| tf = [int(m.heads[k](y[:, k]).argmax(-1).item()) for k in range(8)] | |
| assert tf == gen | |
| def test_cross_frame_channel_is_live_and_gated(): | |
| m = _module(cross_frame=3) | |
| a = torch.tensor([5, 1, 2, 3, 0, 0, 0, 0]).view(1, 8) | |
| b = torch.tensor([5, 9, 8, 7, 0, 0, 0, 0]).view(1, 8) | |
| assert not torch.allclose(m._cross_summary(a), m._cross_summary(b)) | |
| cs = m.cross_start.unsqueeze(0) | |
| assert torch.allclose(m._cross_summary(None), cs) | |
| assert torch.allclose(m._cross_summary(torch.full((1, 8), -1)), cs) | |
| part = torch.tensor([5, 1, -1, 3, 0, 0, 0, 0]).view(1, 8) | |
| assert torch.allclose(m._cross_summary(part), cs) | |
| cb0_neg = torch.tensor([-1, 1, 2, 3, 0, 0, 0, 0]).view(1, 8) | |
| assert not torch.allclose(m._cross_summary(cb0_neg), cs) | |
| def test_cross_frame_grad_flow(): | |
| m = _module(cross_frame=3) | |
| h = torch.randn(12, 64) | |
| tgt = torch.randint(0, 32, (12, 8)) | |
| prev = torch.randint(0, 32, (12, 8)) | |
| prev[:3] = -1 | |
| loss = m.forward_loss(h, tgt, prev_codes=prev) | |
| loss.backward() | |
| assert m.cross_embeds[0].weight.grad.abs().sum() > 0 | |
| assert m.cross_start.grad.abs().sum() > 0 | |
| for name, p in m.named_parameters(): | |
| assert p.grad is not None and torch.isfinite(p.grad).all(), name | |
| def test_aligned_dataset_grid(tmp_path): | |
| import json | |
| from unittest.mock import MagicMock | |
| row = { | |
| "prompt": "hello world", | |
| "speech_tokens": [10, 11, 12, 13], | |
| "residual_codes": [[20 + k * 10 + t for t in range(4)] for k in range(7)], | |
| "speaker_id": 5, | |
| } | |
| p = tmp_path / "rows.jsonl" | |
| p.write_text(json.dumps(row) + "\n") | |
| tok = MagicMock() | |
| tok.encode.return_value = [101, 102] | |
| reg = MagicMock() | |
| reg.bos_id, reg.user_prompt_id = 1, 2 | |
| reg.audio_start_id, reg.audio_end_id, reg.eos_id = 3, 4, 5 | |
| from delay_dataset import DelayMimiDataset | |
| ds = DelayMimiDataset(str(p), tok, reg, max_seq_len=256, aligned=True) | |
| item = ds[0] | |
| codes = item["codes"] | |
| a0, a1 = item["audio_start"], item["audio_end"] | |
| assert a1 - a0 == 4 | |
| for s in range(4): | |
| assert codes[a0 + s][0].item() == row["speech_tokens"][s] | |
| for k in range(1, 8): | |
| assert codes[a0 + s][k].item() == row["residual_codes"][k - 1][s] | |
| assert (codes[:a0] == -1).all() and (codes[a1:] == -1).all() | |
| ds2 = DelayMimiDataset(str(p), tok, reg, max_seq_len=256, aligned=False) | |
| item2 = ds2[0] | |
| assert item2["audio_end"] - item2["audio_start"] == 4 + 7 | |
| if __name__ == "__main__": | |
| sys.exit(pytest.main([__file__, "-v"])) | |