Download tests/export/test_backbone_export.py from mrwine/maya2-native-fast: direct link, hf CLI and curl.
- Browser
- Download file 3.48 kB
-
https://huggingface.co/mrwine/maya2-native-fast/resolve/main/tests/export/test_backbone_export.py
- Command line
-
hf download hf://mrwine/maya2-native-fast/tests/export/test_backbone_export.py
-
curl -L -o test_backbone_export.py https://huggingface.co/mrwine/maya2-native-fast/resolve/main/tests/export/test_backbone_export.py
3.48 kB
| import unittest | |
| import numpy as np | |
| import onnxruntime as ort | |
| import torch | |
| from transformers import AutoConfig | |
| from transformers.models.qwen3.modeling_qwen3 import Qwen3RotaryEmbedding | |
| from tools.maya_export import export_backbone as EB | |
| from tools.maya_export.common import ckpt_paths, work_dir | |
| # The full fp32 fused graph is 5.6 GB and cannot be loaded under the 4 GB limit, so the merge is checked on the | |
| # first two layers (same merge code, layer count 2). The full model is then the same graph over 28 layers. | |
| N = 2 | |
| BUILD = work_dir() / "backbone_build" / "fp32" | |
| TOL = 1e-4 | |
| def _sess(path): | |
| so = ort.SessionOptions() | |
| so.intra_op_num_threads = 4 | |
| return ort.InferenceSession(str(path), so, providers=["CPUExecutionProvider"]) | |
| class TestBackboneMerge(unittest.TestCase): | |
| def setUpClass(cls): | |
| paths = [BUILD / f"layer_{i:02d}.onnx" for i in range(N)] + [BUILD / "head.onnx"] | |
| if not all(p.exists() for p in paths): | |
| raise unittest.SkipTest("per-layer fp32 graphs not built (run export_backbone --precision fp32)") | |
| cls.layers = [_sess(BUILD / f"layer_{i:02d}.onnx") for i in range(N)] | |
| cls.head = _sess(BUILD / "head.onnx") | |
| cls.fused_path = BUILD / f"fused{N}_fp32.onnx" | |
| if not cls.fused_path.exists(): | |
| EB.merge([BUILD / f"layer_{i:02d}.onnx" for i in range(N)], BUILD / "head.onnx", cls.fused_path, "fp32") | |
| cls.fused = _sess(cls.fused_path) | |
| cfg = AutoConfig.from_pretrained(ckpt_paths()["backbone_dir"]) | |
| cfg._attn_implementation = "sdpa" | |
| cls.rot = Qwen3RotaryEmbedding(config=cfg).eval() | |
| def _rope(self, T, past): | |
| cos, sin = EB.rope(self.rot, T, past) | |
| return cos.numpy(), sin.numpy() | |
| def test_fused_matches_layers(self): | |
| rng = np.random.default_rng(0) | |
| steps = [(8, 0), (1, 8), (1, 9), (1, 10), (1, 11)] # 8 prefill tokens, then 4 decode steps | |
| kv_fused = {f"past_{kv}_{i}": np.zeros((1, EB.N_KV_HEADS, 0, EB.HEAD_DIM), np.float32) | |
| for i in range(N) for kv in ("k", "v")} | |
| kv_chain = [(np.zeros((1, EB.N_KV_HEADS, 0, EB.HEAD_DIM), np.float32), | |
| np.zeros((1, EB.N_KV_HEADS, 0, EB.HEAD_DIM), np.float32)) for _ in range(N)] | |
| for T, past in steps: | |
| x = (rng.standard_normal((1, T, EB.D_MODEL)) * 0.02).astype(np.float32) | |
| cos, sin = self._rope(T, past) | |
| mask = EB.masks(T, past).numpy() | |
| feed = {"embeds": x, "cos": cos, "sin": sin, "mask": mask, **kv_fused} | |
| hid_f, cb_f, *present = self.fused.run(None, feed) | |
| for i in range(N): | |
| kv_fused[f"past_k_{i}"] = present[2 * i] | |
| kv_fused[f"past_v_{i}"] = present[2 * i + 1] | |
| h = x | |
| for i in range(N): | |
| out, nk, nv = self.layers[i].run(None, {"h": h, "cos": cos, "sin": sin, "mask": mask, | |
| "past_k": kv_chain[i][0], "past_v": kv_chain[i][1]}) | |
| kv_chain[i] = (nk, nv) | |
| h = out | |
| hid_c, cb_c = self.head.run(None, {"hid": h}) | |
| rel_h = float(np.abs(hid_f - hid_c).max() / np.abs(hid_c).max()) | |
| rel_c = float(np.abs(cb_f - cb_c).max() / np.abs(cb_c).max()) | |
| self.assertLessEqual(rel_h, TOL, f"hidden T={T} past={past}") | |
| self.assertLessEqual(rel_c, TOL, f"cb0 T={T} past={past}") | |
| if __name__ == "__main__": | |
| unittest.main() | |