Download tests/test_continuous_engine_grad.py from thefinalboss/fractus-cte: direct link, hf CLI and curl.
- Browser
- Download file 3.81 kB
-
https://huggingface.co/thefinalboss/fractus-cte/resolve/66c6bb52bbb2d2ce439c3d333390924ec520c9af/tests/test_continuous_engine_grad.py
- Command line
-
hf download hf://thefinalboss/fractus-cte@66c6bb52bbb2d2ce439c3d333390924ec520c9af/tests/test_continuous_engine_grad.py
-
curl -L -o test_continuous_engine_grad.py https://huggingface.co/thefinalboss/fractus-cte/resolve/66c6bb52bbb2d2ce439c3d333390924ec520c9af/tests/test_continuous_engine_grad.py
3.81 kB
| """Regression test for the frozen-expert Phase 3 defect. | |
| Before the fix, tick_chunk read the experts' detached _cached_W buffer | |
| directly, so expert params received no gradient. This test fails on the | |
| old code and must pass on the refactored engine. | |
| Also tests multi-block gradient flow and structure. | |
| """ | |
| import torch | |
| from fractus.continuous_engine import ContinuousThoughtEngine | |
| def _build_13m(n_layers=1): | |
| return ContinuousThoughtEngine( | |
| vocab_size=50257, d_model=128, n_heads=2, d_head=64, | |
| n_layers=n_layers, n_levels=2, n_oscillators=8, coupling_rank=4, | |
| n_experts=4, top_k=2, expert_d_ff=128, siren_rank=32, | |
| ) | |
| def test_cte_experts_receive_gradient(): | |
| """Every expert parameter gets a finite, non-zero gradient after tick_chunk + backward.""" | |
| eng = _build_13m() | |
| eng.reset_thought(batch_size=1) | |
| tokens = torch.randint(0, eng.vocab_size, (1, 16)) | |
| logits = eng.tick_chunk(tokens) | |
| loss = logits.pow(2).mean() | |
| loss.backward() | |
| # MoE is at eng.blocks[0].moe. | |
| moe_params = list(eng.blocks[0].moe.named_parameters()) | |
| assert len(moe_params) > 0, "blocks[0].moe has no parameters" | |
| for name, p in moe_params: | |
| assert p.requires_grad, f"{name} should requires_grad=True" | |
| assert p.grad is not None, f"{name} received NO gradient (frozen-expert bug)" | |
| assert torch.isfinite(p.grad).all(), f"{name} has non-finite grad" | |
| assert p.grad.abs().sum().item() > 0, f"{name} received zero gradient" | |
| def test_cte_has_moe_attribute(): | |
| """The CTE must use PhaseRoutedMoE in each block.""" | |
| from fractus.nn.moe import PhaseRoutedMoE | |
| eng = _build_13m() | |
| assert isinstance(eng.blocks[0].moe, PhaseRoutedMoE) | |
| assert len(eng.blocks) == 1, "default should be 1 block" | |
| def test_cte_multi_block_gradient_flow(): | |
| """Multi-block CTE: gradient flows through ALL blocks.""" | |
| eng = _build_13m(n_layers=3) | |
| assert len(eng.blocks) == 3 | |
| eng.reset_thought(batch_size=1) | |
| tokens = torch.randint(0, eng.vocab_size, (1, 16)) | |
| logits = eng.tick_chunk(tokens) | |
| loss = logits.pow(2).mean() | |
| loss.backward() | |
| # Every block's MoE must receive gradient. | |
| for i, blk in enumerate(eng.blocks): | |
| moe_params = list(blk.moe.parameters()) | |
| assert len(moe_params) > 0, f"block {i} moe has no params" | |
| for p in moe_params: | |
| assert p.grad is not None, f"block {i} moe param received NO gradient" | |
| assert p.grad.abs().sum().item() > 0, f"block {i} moe param got zero grad" | |
| # Every block's attention must receive gradient. | |
| for i, blk in enumerate(eng.blocks): | |
| attn_params = list(blk.attn.parameters()) | |
| for p in attn_params: | |
| assert p.grad is not None, f"block {i} attn param received NO gradient" | |
| def test_cte_multi_block_continuous_thought(): | |
| """Multi-block: thought_state and per-block (S,z) carry across chunks.""" | |
| eng = _build_13m(n_layers=2) | |
| eng.reset_thought(batch_size=1) | |
| chunk1 = torch.tensor([[i + 1 for i in range(16)]]) | |
| chunk2 = torch.tensor([[i + 17 for i in range(16)]]) | |
| eng.tick_chunk(chunk1) | |
| ts1 = eng.thought_state.clone() | |
| S1_0 = eng.blocks[0].attn_S.clone() | |
| S1_1 = eng.blocks[1].attn_S.clone() | |
| eng.tick_chunk(chunk2) | |
| ts2 = eng.thought_state.clone() | |
| S2_0 = eng.blocks[0].attn_S.clone() | |
| S2_1 = eng.blocks[1].attn_S.clone() | |
| assert not torch.equal(ts1, ts2), "thought_state must change across chunks" | |
| assert not torch.equal(S1_0, S2_0), "block 0 S must change" | |
| assert not torch.equal(S1_1, S2_1), "block 1 S must change" | |
| assert S2_0.abs().max() > 0, "block 0 S must be nonzero" | |
| assert S2_1.abs().max() > 0, "block 1 S must be nonzero" | |