orbitquant 0.1.6__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. {orbitquant-0.1.6 → orbitquant-0.2.0}/.github/workflows/publish-pypi.yml +1 -1
  2. orbitquant-0.2.0/PKG-INFO +340 -0
  3. orbitquant-0.2.0/README.md +296 -0
  4. orbitquant-0.2.0/docs/kernel-audit.md +192 -0
  5. {orbitquant-0.1.6 → orbitquant-0.2.0}/docs/paper-methodology-audit.md +35 -28
  6. {orbitquant-0.1.6 → orbitquant-0.2.0}/native-kernels/orbitquant-packed-matmul/CARD.md +17 -1
  7. {orbitquant-0.1.6 → orbitquant-0.2.0}/native-kernels/orbitquant-packed-matmul/benchmarks/benchmark.py +1 -1
  8. {orbitquant-0.1.6 → orbitquant-0.2.0}/native-kernels/orbitquant-packed-matmul/orbitquant_packed_matmul_cuda/packed_matmul.cu +123 -33
  9. {orbitquant-0.1.6 → orbitquant-0.2.0}/native-kernels/orbitquant-packed-matmul/orbitquant_packed_matmul_metal/packed_matmul.metal +97 -7
  10. {orbitquant-0.1.6 → orbitquant-0.2.0}/native-kernels/orbitquant-packed-matmul/orbitquant_packed_matmul_metal/packed_matmul.mm +38 -6
  11. {orbitquant-0.1.6 → orbitquant-0.2.0}/native-kernels/orbitquant-packed-matmul/tests/test_packed_matmul.py +48 -5
  12. {orbitquant-0.1.6 → orbitquant-0.2.0}/native-kernels/orbitquant-packed-matmul/torch-ext/orbitquant_packed_matmul/__init__.py +4 -2
  13. {orbitquant-0.1.6 → orbitquant-0.2.0}/pyproject.toml +2 -2
  14. {orbitquant-0.1.6 → orbitquant-0.2.0}/scripts/run_cuda_kernel_checks.sh +3 -3
  15. {orbitquant-0.1.6 → orbitquant-0.2.0}/scripts/run_paper_methodology_checks.sh +3 -1
  16. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/__init__.py +13 -3
  17. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/adaln.py +28 -13
  18. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/config.py +11 -1
  19. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/kernels/native_packed_matmul.py +3 -2
  20. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/kernels/triton_cuda.py +9 -7
  21. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/layers.py +45 -20
  22. orbitquant-0.2.0/src/orbitquant/linear_adapters.py +146 -0
  23. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/modeling.py +63 -8
  24. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/policies/generic_dit.py +68 -9
  25. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/quantizer.py +17 -3
  26. orbitquant-0.2.0/src/orbitquant/recipes.py +33 -0
  27. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/transformers_ops.py +11 -6
  28. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_ci.py +2 -1
  29. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_config.py +20 -0
  30. orbitquant-0.2.0/tests/test_documentation.py +35 -0
  31. orbitquant-0.2.0/tests/test_linear_adapters.py +115 -0
  32. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_model_quantization.py +4 -1
  33. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_native_kernel_package.py +4 -3
  34. orbitquant-0.2.0/tests/test_universal_transformers.py +187 -0
  35. {orbitquant-0.1.6 → orbitquant-0.2.0}/uv.lock +1 -1
  36. orbitquant-0.1.6/PKG-INFO +0 -584
  37. orbitquant-0.1.6/README.md +0 -540
  38. orbitquant-0.1.6/docs/kernel-audit.md +0 -282
  39. orbitquant-0.1.6/docs/kernel-hub-approval-request.md +0 -300
  40. orbitquant-0.1.6/docs/publication-checklist.md +0 -133
  41. orbitquant-0.1.6/docs/release-0.1.0.md +0 -154
  42. orbitquant-0.1.6/docs/release-0.1.1.md +0 -31
  43. orbitquant-0.1.6/docs/release-0.1.2.md +0 -28
  44. orbitquant-0.1.6/docs/release-0.1.3.md +0 -25
  45. orbitquant-0.1.6/docs/release-0.1.4.md +0 -36
  46. orbitquant-0.1.6/docs/release-0.1.6.md +0 -37
  47. orbitquant-0.1.6/docs/release-gates.md +0 -532
  48. orbitquant-0.1.6/tests/test_readme.py +0 -91
  49. orbitquant-0.1.6/tests/test_release_gates.py +0 -954
  50. {orbitquant-0.1.6 → orbitquant-0.2.0}/.github/workflows/ci.yml +0 -0
  51. {orbitquant-0.1.6 → orbitquant-0.2.0}/.gitignore +0 -0
  52. {orbitquant-0.1.6 → orbitquant-0.2.0}/LICENSE +0 -0
  53. {orbitquant-0.1.6 → orbitquant-0.2.0}/native-kernels/orbitquant-packed-matmul/build.toml +0 -0
  54. {orbitquant-0.1.6 → orbitquant-0.2.0}/native-kernels/orbitquant-packed-matmul/example.py +0 -0
  55. {orbitquant-0.1.6 → orbitquant-0.2.0}/native-kernels/orbitquant-packed-matmul/flake.lock +0 -0
  56. {orbitquant-0.1.6 → orbitquant-0.2.0}/native-kernels/orbitquant-packed-matmul/flake.nix +0 -0
  57. {orbitquant-0.1.6 → orbitquant-0.2.0}/native-kernels/orbitquant-packed-matmul/tests/__init__.py +0 -0
  58. {orbitquant-0.1.6 → orbitquant-0.2.0}/native-kernels/orbitquant-packed-matmul/torch-ext/torch_binding.cpp +0 -0
  59. {orbitquant-0.1.6 → orbitquant-0.2.0}/native-kernels/orbitquant-packed-matmul/torch-ext/torch_binding.h +0 -0
  60. {orbitquant-0.1.6 → orbitquant-0.2.0}/scripts/run_hf_compat_checks.sh +0 -0
  61. {orbitquant-0.1.6 → orbitquant-0.2.0}/scripts/run_mps_kernel_checks.sh +0 -0
  62. {orbitquant-0.1.6 → orbitquant-0.2.0}/scripts/runpod_ssh_health.sh +0 -0
  63. {orbitquant-0.1.6 → orbitquant-0.2.0}/scripts/verify_hf_kernel_model_artifact.py +0 -0
  64. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/artifacts/__init__.py +0 -0
  65. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/artifacts/assets.py +0 -0
  66. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/artifacts/benchmark.py +0 -0
  67. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/artifacts/checksums.py +0 -0
  68. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/artifacts/comparisons.py +0 -0
  69. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/artifacts/loader.py +0 -0
  70. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/artifacts/manifest.py +0 -0
  71. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/artifacts/model_card.py +0 -0
  72. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/artifacts/refresh.py +0 -0
  73. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/artifacts/repair.py +0 -0
  74. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/artifacts/validator.py +0 -0
  75. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/artifacts/writer.py +0 -0
  76. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/benchmarks.py +0 -0
  77. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/cli/__init__.py +0 -0
  78. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/cli/main.py +0 -0
  79. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/codebooks/__init__.py +0 -0
  80. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/codebooks/lloyd_max.py +0 -0
  81. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/errors.py +0 -0
  82. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/eval/__init__.py +0 -0
  83. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/eval/assets.py +0 -0
  84. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/eval/external_export.py +0 -0
  85. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/eval/external_metrics.py +0 -0
  86. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/eval/external_plan.py +0 -0
  87. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/eval/metrics.py +0 -0
  88. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/eval/native_plan.py +0 -0
  89. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/eval/native_runner.py +0 -0
  90. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/eval/native_settings.py +0 -0
  91. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/eval/prompts.py +0 -0
  92. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/eval/report.py +0 -0
  93. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/functional.py +0 -0
  94. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/hub.py +0 -0
  95. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/kernels/__init__.py +0 -0
  96. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/kernels/dispatch.py +0 -0
  97. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/kernels/mps.py +0 -0
  98. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/packing/__init__.py +0 -0
  99. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/packing/bitpack.py +0 -0
  100. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/pipeline.py +0 -0
  101. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/policies/__init__.py +0 -0
  102. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/policies/flux.py +0 -0
  103. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/policies/flux2.py +0 -0
  104. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/policies/wan.py +0 -0
  105. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/policies/z_image.py +0 -0
  106. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/rotations/__init__.py +0 -0
  107. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/rotations/fwht.py +0 -0
  108. {orbitquant-0.1.6 → orbitquant-0.2.0}/src/orbitquant/rotations/rpbh.py +0 -0
  109. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_adaln_rtn.py +0 -0
  110. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_artifact_writer.py +0 -0
  111. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_benchmarks.py +0 -0
  112. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_bitpack.py +0 -0
  113. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_cli.py +0 -0
  114. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_cli_report.py +0 -0
  115. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_codebooks.py +0 -0
  116. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_diffusers_modelmixin_integration.py +0 -0
  117. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_distribution.py +0 -0
  118. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_eval_assets.py +0 -0
  119. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_eval_prompts.py +0 -0
  120. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_eval_report.py +0 -0
  121. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_external_eval_plan.py +0 -0
  122. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_external_export.py +0 -0
  123. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_hub.py +0 -0
  124. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_kernel_model_verifier.py +0 -0
  125. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_kernels.py +0 -0
  126. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_manifest.py +0 -0
  127. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_model_card.py +0 -0
  128. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_native_packed_matmul.py +0 -0
  129. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_native_runner.py +0 -0
  130. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_native_settings.py +0 -0
  131. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_optional_dependencies.py +0 -0
  132. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_orbit_linear.py +0 -0
  133. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_paper_alignment.py +0 -0
  134. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_paper_methodology.py +0 -0
  135. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_pipeline_helpers.py +0 -0
  136. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_policies.py +0 -0
  137. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_prompt_jobs.py +0 -0
  138. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_prompt_selection.py +0 -0
  139. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_quantizer_adapter.py +0 -0
  140. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_rpbh.py +0 -0
  141. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_target_policies.py +0 -0
  142. {orbitquant-0.1.6 → orbitquant-0.2.0}/tests/test_transformers_pretrained_integration.py +0 -0
@@ -6,7 +6,7 @@ on:
6
6
  version:
7
7
  description: Version to publish
8
8
  required: true
9
- default: "0.1.6"
9
+ default: "0.2.0"
10
10
 
11
11
  jobs:
12
12
  build:
@@ -0,0 +1,340 @@
1
+ Metadata-Version: 2.4
2
+ Name: orbitquant
3
+ Version: 0.2.0
4
+ Summary: Calibration-free OrbitQuant for transformer linear projections
5
+ Project-URL: Homepage, https://github.com/iamwavecut/OrbitQuant
6
+ Project-URL: Repository, https://github.com/iamwavecut/OrbitQuant
7
+ Project-URL: Issues, https://github.com/iamwavecut/OrbitQuant/issues
8
+ Project-URL: Paper, https://arxiv.org/abs/2607.02461
9
+ Author: WaveCut
10
+ License-Expression: Apache-2.0
11
+ License-File: LICENSE
12
+ Keywords: diffusers,diffusion,orbitquant,quantization,transformers
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: License :: OSI Approved :: Apache Software License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Requires-Python: >=3.11
22
+ Requires-Dist: huggingface-hub>=0.33
23
+ Requires-Dist: numpy>=2.0
24
+ Requires-Dist: packaging>=24.0
25
+ Requires-Dist: safetensors>=0.5
26
+ Requires-Dist: torch>=2.5
27
+ Requires-Dist: tqdm>=4.66
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest-xdist>=3.8; extra == 'dev'
30
+ Requires-Dist: pytest>=8.4; extra == 'dev'
31
+ Requires-Dist: ruff>=0.12; extra == 'dev'
32
+ Provides-Extra: eval
33
+ Requires-Dist: imageio-ffmpeg>=0.6; extra == 'eval'
34
+ Requires-Dist: imageio>=2.37; extra == 'eval'
35
+ Requires-Dist: pillow>=11.0; extra == 'eval'
36
+ Provides-Extra: hf
37
+ Requires-Dist: accelerate>=1.8; extra == 'hf'
38
+ Requires-Dist: diffusers>=0.35; extra == 'hf'
39
+ Requires-Dist: transformers>=4.53; extra == 'hf'
40
+ Provides-Extra: kernels
41
+ Requires-Dist: kernels>=0.16; extra == 'kernels'
42
+ Requires-Dist: triton>=3.5; (platform_system == 'Linux') and extra == 'kernels'
43
+ Description-Content-Type: text/markdown
44
+
45
+ # OrbitQuant
46
+
47
+ OrbitQuant is a calibration-free post-training quantizer for transformer linear
48
+ projections. It implements the method from
49
+ [OrbitQuant: Data-Agnostic Quantization for Image and Video Diffusion Transformers](https://arxiv.org/abs/2607.02461)
50
+ and exposes it through Hugging Face Transformers, Diffusers, and a direct
51
+ PyTorch API.
52
+
53
+ The implementation is clean-room and Apache-2.0 licensed.
54
+
55
+ ## Features
56
+
57
+ - Automatic coverage of registered linear-compatible modules in transformer
58
+ backbones, independent of model class or modality.
59
+ - Built-in support for `torch.nn.Linear` and Hugging Face `Conv1D` projections.
60
+ - Public adapters for custom `F.linear`-equivalent module types and transposed
61
+ weight layouts.
62
+ - RPBH rotation, exact unit-sphere Lloyd-Max codebooks, packed 2/3/4/6/8-bit
63
+ weights, and online activation quantization without calibration data.
64
+ - Model-specific policies for paper-sensitive AdaLN and output-layer handling.
65
+ - Compact `safetensors` artifacts and Hugging Face `save_pretrained()` /
66
+ `from_pretrained()` integration.
67
+ - Packed-weight CUDA, Triton, and Metal inference paths that avoid a full
68
+ dequantized weight matrix.
69
+
70
+ Embeddings, timestep modules, task heads, and common final projections are
71
+ kept in source precision by default. Every automatic decision is available as
72
+ a machine-readable inventory before quantization.
73
+
74
+ ## Install
75
+
76
+ ```bash
77
+ pip install "orbitquant[hf]"
78
+ ```
79
+
80
+ Install the CUDA/Triton and local-kernel loader dependencies with:
81
+
82
+ ```bash
83
+ pip install "orbitquant[hf,kernels]"
84
+ ```
85
+
86
+ ## Quantize A Transformers Model
87
+
88
+ Importing `orbitquant` registers the backend with supported Transformers and
89
+ Diffusers versions. The default `target_policy="auto"` selects a known
90
+ paper policy where applicable and otherwise uses the universal policy.
91
+
92
+ ```python
93
+ import torch
94
+ import orbitquant
95
+ from transformers import AutoModelForCausalLM
96
+
97
+ config = orbitquant.recipe(
98
+ "w4a4",
99
+ runtime_mode="auto_fused",
100
+ )
101
+
102
+ model = AutoModelForCausalLM.from_pretrained(
103
+ "your-org/your-transformer",
104
+ dtype=torch.bfloat16,
105
+ quantization_config=config,
106
+ )
107
+ model.save_pretrained("./your-transformer-orbitquant-w4a4")
108
+ ```
109
+
110
+ Load the packed model after importing the backend:
111
+
112
+ ```python
113
+ import orbitquant
114
+ from transformers import AutoModelForCausalLM
115
+
116
+ model = AutoModelForCausalLM.from_pretrained(
117
+ "./your-transformer-orbitquant-w4a4",
118
+ device_map="auto",
119
+ )
120
+ ```
121
+
122
+ Named recipes are `w4a4`, `w3a3`, `w2a4`, `w2a3`, and `w4a6`. They create a
123
+ normal `OrbitQuantConfig`, so every field can be overridden.
124
+
125
+ ## Inspect Coverage
126
+
127
+ Inspect a model before replacing modules:
128
+
129
+ ```python
130
+ from orbitquant import inspect_linear_module_policy, recipe
131
+ from transformers import AutoModel
132
+
133
+ model = AutoModel.from_pretrained("your-org/your-transformer")
134
+ report = inspect_linear_module_policy(model, recipe("w4a4"))
135
+
136
+ print(report["action_counts"])
137
+ print(report["quantized_modules"])
138
+ print(report["skipped_modules"])
139
+ print(report["unsupported_linear_modules"])
140
+ ```
141
+
142
+ The universal policy quantizes every registered linear-compatible module except
143
+ known embeddings, timestep modules, task/output heads, and explicit skips. It
144
+ does not depend on names such as `layers`, `blocks`, or a particular model
145
+ class.
146
+
147
+ Use `modules_to_convert` as an allowlist and define AdaLN/skips with exact names,
148
+ substrings, or glob patterns:
149
+
150
+ ```python
151
+ from orbitquant import OrbitQuantConfig
152
+
153
+ config = OrbitQuantConfig(
154
+ modules_to_convert=["backbone.*.projection"],
155
+ modules_to_use_adaln=["backbone.*.modulation"],
156
+ modules_to_not_convert=["*.sensitive_output"],
157
+ )
158
+ ```
159
+
160
+ Explicit dtype overrides remain available through `modules_dtype_dict`.
161
+
162
+ ## Quantize An Instantiated Module
163
+
164
+ For ordinary PyTorch models or frameworks that do not use Hugging Face loading
165
+ hooks:
166
+
167
+ ```python
168
+ from orbitquant import quantize_model, recipe
169
+
170
+ summary = quantize_model(
171
+ model,
172
+ recipe("w4a4"),
173
+ quantization_device="cuda",
174
+ )
175
+ print(summary.quantized_modules)
176
+ ```
177
+
178
+ The replacement supports arbitrary leading dimensions and treats the final
179
+ dimension as `in_features`, including sequence, image-token, and video-token
180
+ layouts.
181
+
182
+ ## Custom Linear Modules
183
+
184
+ Register a module whose forward operation is equivalent to `F.linear`. The
185
+ adapter describes only its source weight layout and feature attributes:
186
+
187
+ ```python
188
+ from orbitquant import register_linear_adapter
189
+
190
+ register_linear_adapter(
191
+ MyLinear,
192
+ weight_layout="in_out",
193
+ in_features_attr="input_size",
194
+ out_features_attr="output_size",
195
+ )
196
+ ```
197
+
198
+ OrbitQuant stores every replacement in canonical `[out_features, in_features]`
199
+ layout. Modules with additional routing, tensor-parallel communication, sparse
200
+ expert selection, or non-linear forward semantics need an architecture-aware
201
+ adapter; the inspection report lists unregistered linear candidates instead of
202
+ silently replacing them.
203
+
204
+ ## Diffusers
205
+
206
+ Quantize the denoiser component of a pipeline:
207
+
208
+ ```python
209
+ import torch
210
+ from diffusers import DiffusionPipeline
211
+ from orbitquant import quantize_pipeline, recipe, save_quantized_pipeline_component
212
+
213
+ pipe = DiffusionPipeline.from_pretrained(
214
+ "black-forest-labs/FLUX.2-klein-4B",
215
+ torch_dtype=torch.bfloat16,
216
+ )
217
+ config = recipe("w4a4", target_policy="flux2")
218
+ summary = quantize_pipeline(
219
+ pipe,
220
+ config,
221
+ component="transformer",
222
+ quantization_device="cuda",
223
+ )
224
+ save_quantized_pipeline_component(
225
+ pipe,
226
+ "./flux2-klein-orbitquant-w4a4",
227
+ config=config,
228
+ component="transformer",
229
+ source_model_id="black-forest-labs/FLUX.2-klein-4B",
230
+ summary=summary,
231
+ )
232
+ ```
233
+
234
+ Published FLUX, Z-Image, and Wan repositories are compact Diffusers component
235
+ artifacts. Their model cards contain the matching pipeline code and native
236
+ generation settings.
237
+
238
+ Load a published component artifact together with its recorded source pipeline:
239
+
240
+ ```python
241
+ import torch
242
+ from huggingface_hub import snapshot_download
243
+ from orbitquant import load_quantized_pipeline_from_artifact
244
+
245
+ artifact_dir = snapshot_download(
246
+ "WaveCut/FLUX.1-schnell-OrbitQuant-W4A4",
247
+ repo_type="model",
248
+ )
249
+ pipe = load_quantized_pipeline_from_artifact(
250
+ artifact_dir,
251
+ torch_dtype=torch.bfloat16,
252
+ runtime_mode="auto_fused",
253
+ )
254
+ ```
255
+
256
+ ## Packed Runtime
257
+
258
+ `runtime_mode="auto_fused"` is the default:
259
+
260
+ | Device | Dispatch |
261
+ | --- | --- |
262
+ | CUDA | Native packed CUDA package, then Triton packed matmul |
263
+ | MPS | Native packed Metal package |
264
+ | CPU | PyTorch reference path |
265
+
266
+ CUDA and MPS do not silently materialize a full BF16/FP16 weight matrix in
267
+ `auto_fused`. If no packed backend is available, the error includes the missing
268
+ backend and installation guidance.
269
+
270
+ Use the explicit reference path for compatibility or numerical debugging:
271
+
272
+ ```python
273
+ config = orbitquant.recipe("w4a4", runtime_mode="dequant_bf16")
274
+ ```
275
+
276
+ Build the ABI3 native package locally without Kernel Hub:
277
+
278
+ ```bash
279
+ cd native-kernels/orbitquant-packed-matmul
280
+ nix --option sandbox relaxed run .#build-and-copy -L
281
+ export PYTHONPATH="$PWD/build/<matching-torch-backend-platform-variant>:$PYTHONPATH"
282
+ ```
283
+
284
+ The variant must match the Torch minor version, CUDA or Metal backend, C++ ABI,
285
+ architecture, and operating system. See
286
+ [`docs/kernel-audit.md`](docs/kernel-audit.md) for tested shapes, benchmark
287
+ methodology, and local package verification.
288
+
289
+ ## Validated Architecture Coverage
290
+
291
+ The integration suite instantiates and inventories encoder-only, decoder-only,
292
+ encoder-decoder, causal LM, and vision transformer families:
293
+
294
+ | Family | Projection type |
295
+ | --- | --- |
296
+ | BERT | `torch.nn.Linear` |
297
+ | GPT-2 | Hugging Face `Conv1D` with transposed source weights |
298
+ | Llama | `torch.nn.Linear`, including GQA projections |
299
+ | T5 | encoder and decoder `torch.nn.Linear` projections |
300
+ | ViT | vision transformer `torch.nn.Linear` projections |
301
+
302
+ The paper-aligned release artifacts remain FLUX.1-schnell, Z-Image-Turbo, and
303
+ Wan 2.1 T2V. FLUX.2 Klein is an additional validated diffusion target.
304
+
305
+ Architecture coverage means the model can be discovered, quantized, executed,
306
+ saved, and restored without model-name-specific code. It does not guarantee a
307
+ quality-preserving bit setting. OrbitQuant was evaluated in the paper on image
308
+ and video diffusion transformers; language and classification models can be
309
+ more sensitive, and their quality must be measured before publishing a
310
+ checkpoint. The library exposes module overrides for such recipes but does not
311
+ silently substitute a different quantization algorithm.
312
+
313
+ ## Method Conformance
314
+
315
+ The implementation follows the paper's shared data-agnostic basis:
316
+
317
+ - RPBH permutation, Rademacher signs, block FWHT, and orthonormal scaling.
318
+ - Offline folded weight rotation with BF16 row norms and quantized unit
319
+ directions.
320
+ - Online per-token norm, normalized activation rotation, nearest-centroid
321
+ quantization, and rescaling.
322
+ - One fixed codebook per `(input dimension, bit width, algorithm version)` and
323
+ no prompt, timestep, or calibration statistics.
324
+ - INT4 group-64 RTN for model policies that identify dynamic AdaLN projections.
325
+
326
+ The detailed requirement matrix is in
327
+ [`docs/paper-methodology-audit.md`](docs/paper-methodology-audit.md).
328
+
329
+ ## Development
330
+
331
+ ```bash
332
+ uv sync --extra hf --extra dev
333
+ uv run pytest -q
334
+ uv run ruff check .
335
+ ```
336
+
337
+ ## License
338
+
339
+ OrbitQuant is licensed under Apache-2.0. Model artifacts retain the license and
340
+ provenance of their source checkpoints.
@@ -0,0 +1,296 @@
1
+ # OrbitQuant
2
+
3
+ OrbitQuant is a calibration-free post-training quantizer for transformer linear
4
+ projections. It implements the method from
5
+ [OrbitQuant: Data-Agnostic Quantization for Image and Video Diffusion Transformers](https://arxiv.org/abs/2607.02461)
6
+ and exposes it through Hugging Face Transformers, Diffusers, and a direct
7
+ PyTorch API.
8
+
9
+ The implementation is clean-room and Apache-2.0 licensed.
10
+
11
+ ## Features
12
+
13
+ - Automatic coverage of registered linear-compatible modules in transformer
14
+ backbones, independent of model class or modality.
15
+ - Built-in support for `torch.nn.Linear` and Hugging Face `Conv1D` projections.
16
+ - Public adapters for custom `F.linear`-equivalent module types and transposed
17
+ weight layouts.
18
+ - RPBH rotation, exact unit-sphere Lloyd-Max codebooks, packed 2/3/4/6/8-bit
19
+ weights, and online activation quantization without calibration data.
20
+ - Model-specific policies for paper-sensitive AdaLN and output-layer handling.
21
+ - Compact `safetensors` artifacts and Hugging Face `save_pretrained()` /
22
+ `from_pretrained()` integration.
23
+ - Packed-weight CUDA, Triton, and Metal inference paths that avoid a full
24
+ dequantized weight matrix.
25
+
26
+ Embeddings, timestep modules, task heads, and common final projections are
27
+ kept in source precision by default. Every automatic decision is available as
28
+ a machine-readable inventory before quantization.
29
+
30
+ ## Install
31
+
32
+ ```bash
33
+ pip install "orbitquant[hf]"
34
+ ```
35
+
36
+ Install the CUDA/Triton and local-kernel loader dependencies with:
37
+
38
+ ```bash
39
+ pip install "orbitquant[hf,kernels]"
40
+ ```
41
+
42
+ ## Quantize A Transformers Model
43
+
44
+ Importing `orbitquant` registers the backend with supported Transformers and
45
+ Diffusers versions. The default `target_policy="auto"` selects a known
46
+ paper policy where applicable and otherwise uses the universal policy.
47
+
48
+ ```python
49
+ import torch
50
+ import orbitquant
51
+ from transformers import AutoModelForCausalLM
52
+
53
+ config = orbitquant.recipe(
54
+ "w4a4",
55
+ runtime_mode="auto_fused",
56
+ )
57
+
58
+ model = AutoModelForCausalLM.from_pretrained(
59
+ "your-org/your-transformer",
60
+ dtype=torch.bfloat16,
61
+ quantization_config=config,
62
+ )
63
+ model.save_pretrained("./your-transformer-orbitquant-w4a4")
64
+ ```
65
+
66
+ Load the packed model after importing the backend:
67
+
68
+ ```python
69
+ import orbitquant
70
+ from transformers import AutoModelForCausalLM
71
+
72
+ model = AutoModelForCausalLM.from_pretrained(
73
+ "./your-transformer-orbitquant-w4a4",
74
+ device_map="auto",
75
+ )
76
+ ```
77
+
78
+ Named recipes are `w4a4`, `w3a3`, `w2a4`, `w2a3`, and `w4a6`. They create a
79
+ normal `OrbitQuantConfig`, so every field can be overridden.
80
+
81
+ ## Inspect Coverage
82
+
83
+ Inspect a model before replacing modules:
84
+
85
+ ```python
86
+ from orbitquant import inspect_linear_module_policy, recipe
87
+ from transformers import AutoModel
88
+
89
+ model = AutoModel.from_pretrained("your-org/your-transformer")
90
+ report = inspect_linear_module_policy(model, recipe("w4a4"))
91
+
92
+ print(report["action_counts"])
93
+ print(report["quantized_modules"])
94
+ print(report["skipped_modules"])
95
+ print(report["unsupported_linear_modules"])
96
+ ```
97
+
98
+ The universal policy quantizes every registered linear-compatible module except
99
+ known embeddings, timestep modules, task/output heads, and explicit skips. It
100
+ does not depend on names such as `layers`, `blocks`, or a particular model
101
+ class.
102
+
103
+ Use `modules_to_convert` as an allowlist and define AdaLN/skips with exact names,
104
+ substrings, or glob patterns:
105
+
106
+ ```python
107
+ from orbitquant import OrbitQuantConfig
108
+
109
+ config = OrbitQuantConfig(
110
+ modules_to_convert=["backbone.*.projection"],
111
+ modules_to_use_adaln=["backbone.*.modulation"],
112
+ modules_to_not_convert=["*.sensitive_output"],
113
+ )
114
+ ```
115
+
116
+ Explicit dtype overrides remain available through `modules_dtype_dict`.
117
+
118
+ ## Quantize An Instantiated Module
119
+
120
+ For ordinary PyTorch models or frameworks that do not use Hugging Face loading
121
+ hooks:
122
+
123
+ ```python
124
+ from orbitquant import quantize_model, recipe
125
+
126
+ summary = quantize_model(
127
+ model,
128
+ recipe("w4a4"),
129
+ quantization_device="cuda",
130
+ )
131
+ print(summary.quantized_modules)
132
+ ```
133
+
134
+ The replacement supports arbitrary leading dimensions and treats the final
135
+ dimension as `in_features`, including sequence, image-token, and video-token
136
+ layouts.
137
+
138
+ ## Custom Linear Modules
139
+
140
+ Register a module whose forward operation is equivalent to `F.linear`. The
141
+ adapter describes only its source weight layout and feature attributes:
142
+
143
+ ```python
144
+ from orbitquant import register_linear_adapter
145
+
146
+ register_linear_adapter(
147
+ MyLinear,
148
+ weight_layout="in_out",
149
+ in_features_attr="input_size",
150
+ out_features_attr="output_size",
151
+ )
152
+ ```
153
+
154
+ OrbitQuant stores every replacement in canonical `[out_features, in_features]`
155
+ layout. Modules with additional routing, tensor-parallel communication, sparse
156
+ expert selection, or non-linear forward semantics need an architecture-aware
157
+ adapter; the inspection report lists unregistered linear candidates instead of
158
+ silently replacing them.
159
+
160
+ ## Diffusers
161
+
162
+ Quantize the denoiser component of a pipeline:
163
+
164
+ ```python
165
+ import torch
166
+ from diffusers import DiffusionPipeline
167
+ from orbitquant import quantize_pipeline, recipe, save_quantized_pipeline_component
168
+
169
+ pipe = DiffusionPipeline.from_pretrained(
170
+ "black-forest-labs/FLUX.2-klein-4B",
171
+ torch_dtype=torch.bfloat16,
172
+ )
173
+ config = recipe("w4a4", target_policy="flux2")
174
+ summary = quantize_pipeline(
175
+ pipe,
176
+ config,
177
+ component="transformer",
178
+ quantization_device="cuda",
179
+ )
180
+ save_quantized_pipeline_component(
181
+ pipe,
182
+ "./flux2-klein-orbitquant-w4a4",
183
+ config=config,
184
+ component="transformer",
185
+ source_model_id="black-forest-labs/FLUX.2-klein-4B",
186
+ summary=summary,
187
+ )
188
+ ```
189
+
190
+ Published FLUX, Z-Image, and Wan repositories are compact Diffusers component
191
+ artifacts. Their model cards contain the matching pipeline code and native
192
+ generation settings.
193
+
194
+ Load a published component artifact together with its recorded source pipeline:
195
+
196
+ ```python
197
+ import torch
198
+ from huggingface_hub import snapshot_download
199
+ from orbitquant import load_quantized_pipeline_from_artifact
200
+
201
+ artifact_dir = snapshot_download(
202
+ "WaveCut/FLUX.1-schnell-OrbitQuant-W4A4",
203
+ repo_type="model",
204
+ )
205
+ pipe = load_quantized_pipeline_from_artifact(
206
+ artifact_dir,
207
+ torch_dtype=torch.bfloat16,
208
+ runtime_mode="auto_fused",
209
+ )
210
+ ```
211
+
212
+ ## Packed Runtime
213
+
214
+ `runtime_mode="auto_fused"` is the default:
215
+
216
+ | Device | Dispatch |
217
+ | --- | --- |
218
+ | CUDA | Native packed CUDA package, then Triton packed matmul |
219
+ | MPS | Native packed Metal package |
220
+ | CPU | PyTorch reference path |
221
+
222
+ CUDA and MPS do not silently materialize a full BF16/FP16 weight matrix in
223
+ `auto_fused`. If no packed backend is available, the error includes the missing
224
+ backend and installation guidance.
225
+
226
+ Use the explicit reference path for compatibility or numerical debugging:
227
+
228
+ ```python
229
+ config = orbitquant.recipe("w4a4", runtime_mode="dequant_bf16")
230
+ ```
231
+
232
+ Build the ABI3 native package locally without Kernel Hub:
233
+
234
+ ```bash
235
+ cd native-kernels/orbitquant-packed-matmul
236
+ nix --option sandbox relaxed run .#build-and-copy -L
237
+ export PYTHONPATH="$PWD/build/<matching-torch-backend-platform-variant>:$PYTHONPATH"
238
+ ```
239
+
240
+ The variant must match the Torch minor version, CUDA or Metal backend, C++ ABI,
241
+ architecture, and operating system. See
242
+ [`docs/kernel-audit.md`](docs/kernel-audit.md) for tested shapes, benchmark
243
+ methodology, and local package verification.
244
+
245
+ ## Validated Architecture Coverage
246
+
247
+ The integration suite instantiates and inventories encoder-only, decoder-only,
248
+ encoder-decoder, causal LM, and vision transformer families:
249
+
250
+ | Family | Projection type |
251
+ | --- | --- |
252
+ | BERT | `torch.nn.Linear` |
253
+ | GPT-2 | Hugging Face `Conv1D` with transposed source weights |
254
+ | Llama | `torch.nn.Linear`, including GQA projections |
255
+ | T5 | encoder and decoder `torch.nn.Linear` projections |
256
+ | ViT | vision transformer `torch.nn.Linear` projections |
257
+
258
+ The paper-aligned release artifacts remain FLUX.1-schnell, Z-Image-Turbo, and
259
+ Wan 2.1 T2V. FLUX.2 Klein is an additional validated diffusion target.
260
+
261
+ Architecture coverage means the model can be discovered, quantized, executed,
262
+ saved, and restored without model-name-specific code. It does not guarantee a
263
+ quality-preserving bit setting. OrbitQuant was evaluated in the paper on image
264
+ and video diffusion transformers; language and classification models can be
265
+ more sensitive, and their quality must be measured before publishing a
266
+ checkpoint. The library exposes module overrides for such recipes but does not
267
+ silently substitute a different quantization algorithm.
268
+
269
+ ## Method Conformance
270
+
271
+ The implementation follows the paper's shared data-agnostic basis:
272
+
273
+ - RPBH permutation, Rademacher signs, block FWHT, and orthonormal scaling.
274
+ - Offline folded weight rotation with BF16 row norms and quantized unit
275
+ directions.
276
+ - Online per-token norm, normalized activation rotation, nearest-centroid
277
+ quantization, and rescaling.
278
+ - One fixed codebook per `(input dimension, bit width, algorithm version)` and
279
+ no prompt, timestep, or calibration statistics.
280
+ - INT4 group-64 RTN for model policies that identify dynamic AdaLN projections.
281
+
282
+ The detailed requirement matrix is in
283
+ [`docs/paper-methodology-audit.md`](docs/paper-methodology-audit.md).
284
+
285
+ ## Development
286
+
287
+ ```bash
288
+ uv sync --extra hf --extra dev
289
+ uv run pytest -q
290
+ uv run ruff check .
291
+ ```
292
+
293
+ ## License
294
+
295
+ OrbitQuant is licensed under Apache-2.0. Model artifacts retain the license and
296
+ provenance of their source checkpoints.