Equimo 2.3.0__tar.gz → 2.5.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 (171) hide show
  1. {equimo-2.3.0 → equimo-2.5.0}/CHANGELOG.md +25 -0
  2. {equimo-2.3.0 → equimo-2.5.0}/NOTICE +12 -0
  3. {equimo-2.3.0 → equimo-2.5.0}/PKG-INFO +1 -1
  4. {equimo-2.3.0 → equimo-2.5.0}/pyproject.toml +1 -1
  5. equimo-2.5.0/src/equimo/__init__.py +1 -0
  6. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/audio/models/ast.py +5 -5
  7. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/_prng.py +5 -0
  8. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/language/models.py +5 -5
  9. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/tabular/models/tabpfn.py +4 -4
  10. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/timeseries/models/t0.py +2 -2
  11. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/models/_features.py +6 -7
  12. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/models/attnet.py +3 -3
  13. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/models/deq.py +5 -5
  14. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/models/fastervit.py +3 -3
  15. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/models/lowformer.py +3 -3
  16. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/models/mobilenet.py +3 -3
  17. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/models/parcae.py +35 -26
  18. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/models/partialformer.py +5 -5
  19. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/models/pmd.py +72 -23
  20. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/models/pmt.py +13 -4
  21. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/models/reduceformer.py +4 -4
  22. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/models/shvit.py +3 -3
  23. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/models/vit.py +5 -5
  24. equimo-2.5.0/src/equimo/vision/query_training/__init__.py +40 -0
  25. equimo-2.5.0/src/equimo/vision/query_training/_assignment.py +130 -0
  26. equimo-2.5.0/src/equimo/vision/query_training/_loss.py +523 -0
  27. equimo-2.5.0/src/equimo/vision/query_training/_sampling.py +162 -0
  28. equimo-2.3.0/src/equimo/__init__.py +0 -1
  29. {equimo-2.3.0 → equimo-2.5.0}/LICENSE.md +0 -0
  30. {equimo-2.3.0 → equimo-2.5.0}/LICENSES/Apache-2.0.txt +0 -0
  31. {equimo-2.3.0 → equimo-2.5.0}/LICENSES/pretrained/README.md +0 -0
  32. {equimo-2.3.0 → equimo-2.5.0}/LICENSES/pretrained/ast-BSD-3-Clause.txt +0 -0
  33. {equimo-2.3.0 → equimo-2.5.0}/LICENSES/pretrained/convnext-Apache-2.0.txt +0 -0
  34. {equimo-2.3.0 → equimo-2.5.0}/LICENSES/pretrained/convnextv2-CC-BY-NC-4.0.txt +0 -0
  35. {equimo-2.3.0 → equimo-2.5.0}/LICENSES/pretrained/dinov2-Apache-2.0.txt +0 -0
  36. {equimo-2.3.0 → equimo-2.5.0}/LICENSES/pretrained/dinov3-License.md +0 -0
  37. {equimo-2.3.0 → equimo-2.5.0}/LICENSES/pretrained/eupe-FAIR-Noncommercial-Research-License.md +0 -0
  38. {equimo-2.3.0 → equimo-2.5.0}/LICENSES/pretrained/lingbot-vision-Apache-2.0.txt +0 -0
  39. {equimo-2.3.0 → equimo-2.5.0}/LICENSES/pretrained/siglip2-Apache-2.0.txt +0 -0
  40. {equimo-2.3.0 → equimo-2.5.0}/LICENSES/pretrained/t0-alpha-Apache-2.0.txt +0 -0
  41. {equimo-2.3.0 → equimo-2.5.0}/LICENSES/pretrained/tabpfn-3-License-v1.0.txt +0 -0
  42. {equimo-2.3.0 → equimo-2.5.0}/LICENSES/pretrained/tips-CC-BY-4.0.txt +0 -0
  43. {equimo-2.3.0 → equimo-2.5.0}/LICENSES/tfc-t0-APACHE-2.0.txt +0 -0
  44. {equimo-2.3.0 → equimo-2.5.0}/README.md +0 -0
  45. {equimo-2.3.0 → equimo-2.5.0}/docs/licensing/t0-source-provenance.md +0 -0
  46. {equimo-2.3.0 → equimo-2.5.0}/docs/migration-v2.md +0 -0
  47. {equimo-2.3.0 → equimo-2.5.0}/docs/stability.md +0 -0
  48. {equimo-2.3.0 → equimo-2.5.0}/docs/timeseries.md +0 -0
  49. {equimo-2.3.0 → equimo-2.5.0}/models/huggingface/NOTICE +0 -0
  50. {equimo-2.3.0 → equimo-2.5.0}/models/huggingface/README.md +0 -0
  51. {equimo-2.3.0 → equimo-2.5.0}/models/huggingface/convnext-conversion.json +0 -0
  52. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/_checkpoint_limits.py +0 -0
  53. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/_io.py +0 -0
  54. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/_pretrained.py +0 -0
  55. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/audio/__init__.py +0 -0
  56. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/audio/io.py +0 -0
  57. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/audio/layers/__init__.py +0 -0
  58. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/audio/layers/patch.py +0 -0
  59. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/audio/models/__init__.py +0 -0
  60. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/catalog.py +0 -0
  61. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/conversion/__init__.py +0 -0
  62. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/conversion/utils.py +0 -0
  63. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/__init__.py +0 -0
  64. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/emamodel.py +0 -0
  65. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/factory.py +0 -0
  66. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/implicit/__init__.py +0 -0
  67. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/implicit/_base.py +0 -0
  68. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/implicit/deq.py +0 -0
  69. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/implicit/injectors.py +0 -0
  70. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/implicit/stabilizers.py +0 -0
  71. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/implicit/strategies.py +0 -0
  72. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/intermediates.py +0 -0
  73. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/layers/__init__.py +0 -0
  74. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/layers/_registry.py +0 -0
  75. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/layers/activation.py +0 -0
  76. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/layers/attention.py +0 -0
  77. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/layers/dropout.py +0 -0
  78. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/layers/ffn.py +0 -0
  79. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/layers/generic.py +0 -0
  80. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/layers/mamba.py +0 -0
  81. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/layers/norm.py +0 -0
  82. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/layers/rotary.py +0 -0
  83. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/ops/__init__.py +0 -0
  84. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/core/ops/scan.py +0 -0
  85. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/__init__.py +0 -0
  86. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/_blocks.py +0 -0
  87. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/_serialization_codecs.py +0 -0
  88. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/_typing.py +0 -0
  89. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/audio/__init__.py +0 -0
  90. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/audio/recipes.py +0 -0
  91. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/audio/selectors.py +0 -0
  92. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/calibration.py +0 -0
  93. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/config.py +0 -0
  94. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/continued_ssl.py +0 -0
  95. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/feature_extraction.py +0 -0
  96. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/heads.py +0 -0
  97. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/inspection.py +0 -0
  98. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/labels.py +0 -0
  99. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/language/__init__.py +0 -0
  100. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/language/recipes.py +0 -0
  101. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/language/selectors.py +0 -0
  102. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/masks.py +0 -0
  103. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/merging.py +0 -0
  104. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/paths.py +0 -0
  105. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/peft/__init__.py +0 -0
  106. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/peft/_common.py +0 -0
  107. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/peft/_compat.py +0 -0
  108. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/peft/adapters.py +0 -0
  109. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/peft/base.py +0 -0
  110. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/peft/bitfit.py +0 -0
  111. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/peft/dora.py +0 -0
  112. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/peft/ia3.py +0 -0
  113. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/peft/lora.py +0 -0
  114. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/peft/prefix.py +0 -0
  115. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/peft/prompts.py +0 -0
  116. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/peft/scale_shift.py +0 -0
  117. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/peft/vera.py +0 -0
  118. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/pooling.py +0 -0
  119. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/recipes.py +0 -0
  120. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/regularization.py +0 -0
  121. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/selectors.py +0 -0
  122. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/serialization.py +0 -0
  123. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/surgery.py +0 -0
  124. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/tags.py +0 -0
  125. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/vision/__init__.py +0 -0
  126. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/vision/dense.py +0 -0
  127. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/vision/eomt.py +0 -0
  128. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/finetune/vision/pmt.py +0 -0
  129. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/language/__init__.py +0 -0
  130. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/language/tokenizers.py +0 -0
  131. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/registry.py +0 -0
  132. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/serialization.py +0 -0
  133. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/tabular/__init__.py +0 -0
  134. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/tabular/layers/__init__.py +0 -0
  135. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/tabular/layers/attention.py +0 -0
  136. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/tabular/layers/blocks.py +0 -0
  137. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/tabular/layers/decoder.py +0 -0
  138. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/tabular/layers/mlp.py +0 -0
  139. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/tabular/layers/preprocessing.py +0 -0
  140. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/tabular/layers/registry.py +0 -0
  141. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/tabular/models/__init__.py +0 -0
  142. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/timeseries/__init__.py +0 -0
  143. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/timeseries/layers/__init__.py +0 -0
  144. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/timeseries/layers/axis_attn.py +0 -0
  145. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/timeseries/layers/blocks.py +0 -0
  146. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/timeseries/layers/patch_encoder.py +0 -0
  147. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/timeseries/layers/registry.py +0 -0
  148. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/timeseries/layers/residual_mlp.py +0 -0
  149. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/timeseries/models/__init__.py +0 -0
  150. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/utils.py +0 -0
  151. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/__init__.py +0 -0
  152. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/_encoder_identity.py +0 -0
  153. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/io.py +0 -0
  154. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/layers/__init__.py +0 -0
  155. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/layers/attention.py +0 -0
  156. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/layers/convolution.py +0 -0
  157. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/layers/downsample.py +0 -0
  158. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/layers/patch.py +0 -0
  159. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/layers/posemb.py +0 -0
  160. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/layers/registry.py +0 -0
  161. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/layers/squeeze_excite.py +0 -0
  162. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/layers/wavelet.py +0 -0
  163. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/models/__init__.py +0 -0
  164. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/models/_embedding.py +0 -0
  165. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/models/convnext.py +0 -0
  166. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/models/eomt.py +0 -0
  167. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/models/iformer.py +0 -0
  168. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/models/mlla.py +0 -0
  169. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/models/vssd.py +0 -0
  170. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/pmt_checkpoint.py +0 -0
  171. {equimo-2.3.0 → equimo-2.5.0}/src/equimo/vision/segmentation.py +0 -0
@@ -2,6 +2,31 @@
2
2
 
3
3
  All notable changes to Equimo are documented here. Equimo follows Semantic Versioning from version 2.0.0 onward.
4
4
 
5
+ ## [2.5.0] - 2026-10-15
6
+
7
+ ### Changed
8
+
9
+ - Model forward and feature endpoints default `key` to `None` instead of a fixed `jax.random.PRNGKey(42)`. Deterministic
10
+ inference (`inference=True`) needs no key; a stochastic forward pass without a key raises a `ValueError` instead of
11
+ silently reusing the same randomness on every call.
12
+
13
+ ### Fixed
14
+
15
+ - `extract_features`, `DenseProbe`, and the other fine-tuning wrappers no longer fail with their default `key=None` on
16
+ ViT-family models (including DINOv2, DINOv3, SigLIP2, EUPE, and LingBot-Vision), VisionParcae, MobileNetV3, AST, the
17
+ text encoder, TabPFN, and T0, whose feature endpoints required a PRNG key even in inference mode.
18
+ - VisionParcae with `state_init="zero"` runs deterministic inference without a key. Key-dependent configurations,
19
+ including the default `state_init="like-init"`, raise an actionable error when the key is missing.
20
+
21
+ ## [2.4.0] - 2026-09-24
22
+
23
+ ### Added
24
+
25
+ - JAX-native query-segmentation assignment, validity-aware point sampling, class/mask/Dice losses, auxiliary-output
26
+ composition, and inspectable batch/device reductions, with pinned upstream numerical references.
27
+ - Padding-aware PMT BatchNorm and configurable collective axes for synchronized statistics, preserving default model
28
+ checkpoint layouts.
29
+
5
30
  ## [2.3.0] - 2026-09-24
6
31
 
7
32
  ### Added
@@ -23,6 +23,18 @@ Source: https://github.com/tensorflow/models/blob/b41a080d61cd4298fea9894804e965
23
23
  Equimo contributors modified the upstream code's formatting and type
24
24
  annotations.
25
25
 
26
+ Query assignment
27
+ ----------------
28
+
29
+ src/equimo/vision/query_training/_assignment.py adapts the Hungarian algorithm
30
+ from Optax, licensed under Apache-2.0 (LICENSES/Apache-2.0.txt).
31
+ Copyright 2024 DeepMind Technologies Limited. All Rights Reserved.
32
+ Source: https://github.com/google-deepmind/optax/blob/225a7079f4630bf75bee94ec78de9aa69c60fab3/optax/assignment/_hungarian_algorithm.py
33
+
34
+ Equimo contributors added target-slot validity, bounded loops, numerical-failure reporting,
35
+ fixed-capacity target-ordered outputs, explicit float32 arithmetic and stopped
36
+ gradients, and documented deterministic tie handling.
37
+
26
38
  LingBot-Vision
27
39
  -------------
28
40
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Equimo
3
- Version: 2.3.0
3
+ Version: 2.5.0
4
4
  Summary: Implementation of modern multimodal models in JAX/Equinox
5
5
  License-Expression: MIT AND Apache-2.0
6
6
  License-File: LICENSE.md
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "Equimo"
3
- version = "2.3.0"
3
+ version = "2.5.0"
4
4
  description = "Implementation of modern multimodal models in JAX/Equinox"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12,<3.15"
@@ -0,0 +1 @@
1
+ __version__ = "2.5.0"
@@ -190,7 +190,7 @@ class AudioSpectrogramTransformer(eqx.Module):
190
190
  def features(
191
191
  self,
192
192
  x: Float[Array, "time frequency"],
193
- key: PRNGKeyArray,
193
+ key: PRNGKeyArray | None = None,
194
194
  inference: Optional[bool] = None,
195
195
  **kwargs,
196
196
  ) -> Float[Array, "seqlen dim"]:
@@ -207,7 +207,7 @@ class AudioSpectrogramTransformer(eqx.Module):
207
207
  def intermediate_features(
208
208
  self,
209
209
  x: Float[Array, "time frequency"],
210
- key: PRNGKeyArray,
210
+ key: PRNGKeyArray | None = None,
211
211
  inference: Optional[bool] = None,
212
212
  indices: Sequence[int] | None = None,
213
213
  n_last_blocks: int | None = None,
@@ -251,7 +251,7 @@ class AudioSpectrogramTransformer(eqx.Module):
251
251
  self,
252
252
  x: Float[Array, "time frequency"],
253
253
  *,
254
- key: PRNGKeyArray,
254
+ key: PRNGKeyArray | None,
255
255
  inference: Optional[bool],
256
256
  ) -> Float[Array, "seqlen dim"]:
257
257
  x = self.patch_embed(x)
@@ -266,7 +266,7 @@ class AudioSpectrogramTransformer(eqx.Module):
266
266
  def forward_features(
267
267
  self,
268
268
  x: Float[Array, "time frequency"],
269
- key: PRNGKeyArray,
269
+ key: PRNGKeyArray | None = None,
270
270
  inference: Optional[bool] = None,
271
271
  **kwargs,
272
272
  ) -> dict:
@@ -283,7 +283,7 @@ class AudioSpectrogramTransformer(eqx.Module):
283
283
  def __call__(
284
284
  self,
285
285
  x: Float[Array, "time frequency"],
286
- key: PRNGKeyArray = jr.PRNGKey(42),
286
+ key: PRNGKeyArray | None = None,
287
287
  inference: Optional[bool] = None,
288
288
  **kwargs,
289
289
  ) -> Float[Array, "num_classes"]: # noqa: F821
@@ -10,6 +10,11 @@ def split_for_mode(key: Any, num: int = 2, *, inference: bool | None) -> tuple:
10
10
 
11
11
  if inference is True:
12
12
  return (key,) * num
13
+ if key is None:
14
+ raise ValueError(
15
+ "A PRNG key is required for stochastic forward passes; pass key=... "
16
+ "or run with inference=True."
17
+ )
13
18
  return tuple(jr.split(key, num))
14
19
 
15
20
 
@@ -68,7 +68,7 @@ class TransformerEncoderStack(eqx.Module):
68
68
  def __call__(
69
69
  self,
70
70
  x: Float[Array, "seqlen dim"],
71
- key: PRNGKeyArray,
71
+ key: PRNGKeyArray | None = None,
72
72
  inference: Optional[bool] = None,
73
73
  mask: Optional[Float[Array, ""]] = None,
74
74
  *,
@@ -90,7 +90,7 @@ class TransformerEncoderStack(eqx.Module):
90
90
  def intermediate_features(
91
91
  self,
92
92
  x: Float[Array, "seqlen dim"],
93
- key: PRNGKeyArray,
93
+ key: PRNGKeyArray | None = None,
94
94
  inference: Optional[bool] = None,
95
95
  mask: Optional[Float[Array, ""]] = None,
96
96
  indices: Sequence[int] | None = None,
@@ -209,7 +209,7 @@ class TextTransformerEncoder(eqx.Module):
209
209
  self,
210
210
  ids: Int[Array, "seqlen"], # noqa: F821
211
211
  padding_mask: Float[Array, "seqlen"], # noqa: F821
212
- key: PRNGKeyArray,
212
+ key: PRNGKeyArray | None = None,
213
213
  inference: Optional[bool] = None,
214
214
  ) -> Float[Array, "seqlen dim"]:
215
215
  x, valid_mask = self._prepare_tokens(ids, padding_mask)
@@ -226,7 +226,7 @@ class TextTransformerEncoder(eqx.Module):
226
226
  self,
227
227
  ids: Int[Array, "seqlen"], # noqa: F821
228
228
  padding_mask: Float[Array, "seqlen"], # noqa: F821
229
- key: PRNGKeyArray,
229
+ key: PRNGKeyArray | None = None,
230
230
  inference: Optional[bool] = None,
231
231
  indices: Sequence[int] | None = None,
232
232
  n_last_blocks: int | None = None,
@@ -248,7 +248,7 @@ class TextTransformerEncoder(eqx.Module):
248
248
  self,
249
249
  ids: Int[Array, "seqlen"], # noqa: F821
250
250
  padding_mask: Float[Array, "seqlen"], # noqa: F821
251
- key: PRNGKeyArray,
251
+ key: PRNGKeyArray | None = None,
252
252
  inference: Optional[bool] = None,
253
253
  ) -> Float[Array, "dim"]:
254
254
  x = self.features(ids, padding_mask, key=key, inference=inference)
@@ -217,7 +217,7 @@ class TabPFN(eqx.Module):
217
217
  x: Float[Array, "rows columns"],
218
218
  y: Array,
219
219
  n_train: int,
220
- key: PRNGKeyArray,
220
+ key: PRNGKeyArray | None = None,
221
221
  inference: Optional[bool] = None,
222
222
  **kwargs,
223
223
  ) -> Float[Array, "rows dim"]:
@@ -256,7 +256,7 @@ class TabPFN(eqx.Module):
256
256
  x: Float[Array, "rows columns"],
257
257
  y: Array,
258
258
  n_train: int,
259
- key: PRNGKeyArray,
259
+ key: PRNGKeyArray | None = None,
260
260
  inference: Optional[bool] = None,
261
261
  indices: Sequence[int] | None = None,
262
262
  n_last_blocks: int | None = None,
@@ -322,7 +322,7 @@ class TabPFN(eqx.Module):
322
322
  x: Float[Array, "rows columns"],
323
323
  y: Array,
324
324
  n_train: int,
325
- key: PRNGKeyArray,
325
+ key: PRNGKeyArray | None = None,
326
326
  inference: Optional[bool] = None,
327
327
  **kwargs,
328
328
  ) -> dict:
@@ -339,7 +339,7 @@ class TabPFN(eqx.Module):
339
339
  x: Float[Array, "rows columns"],
340
340
  y: Array,
341
341
  n_train: int,
342
- key: PRNGKeyArray = jr.PRNGKey(42),
342
+ key: PRNGKeyArray | None = None,
343
343
  inference: Optional[bool] = None,
344
344
  **kwargs,
345
345
  ) -> Float[Array, "test classes"]:
@@ -474,7 +474,7 @@ class T0(eqx.Module):
474
474
  group_ids: Int[Array, "variates time"],
475
475
  variate_type: Int[Array, "variates time"],
476
476
  *,
477
- key: PRNGKeyArray,
477
+ key: PRNGKeyArray | None = None,
478
478
  inference: Optional[bool] = None,
479
479
  ) -> Float[Array, "tokens embed_dim"]:
480
480
  """Return post-normalization latent tokens before quantile decoding.
@@ -503,7 +503,7 @@ class T0(eqx.Module):
503
503
  group_ids: Int[Array, "variates time"],
504
504
  variate_type: Int[Array, "variates time"],
505
505
  *,
506
- key: PRNGKeyArray = jr.PRNGKey(42),
506
+ key: PRNGKeyArray | None = None,
507
507
  inference: Optional[bool] = None,
508
508
  ) -> Float[Array, "variates patches patch_size quantiles"]:
509
509
  key_encoder, key_blocks, key_decoder = split_for_mode(
@@ -8,7 +8,6 @@ its saved-checkpoint signature, unchanged.
8
8
  from typing import TYPE_CHECKING, Any, Collection, Optional, Sequence
9
9
 
10
10
  import jax
11
- import jax.random as jr
12
11
  from einops import reduce
13
12
  from jaxtyping import Array, Float, PRNGKeyArray
14
13
 
@@ -50,7 +49,7 @@ class DenseStageFeatures:
50
49
  def features(
51
50
  self,
52
51
  x: Float[Array, "channels height width"],
53
- key: PRNGKeyArray = jr.PRNGKey(42),
52
+ key: PRNGKeyArray | None = None,
54
53
  inference: Optional[bool] = None,
55
54
  **kwargs,
56
55
  ) -> Float[Array, "dim height width"]:
@@ -66,7 +65,7 @@ class DenseStageFeatures:
66
65
  def intermediate_features(
67
66
  self,
68
67
  x: Float[Array, "channels height width"],
69
- key: PRNGKeyArray = jr.PRNGKey(42),
68
+ key: PRNGKeyArray | None = None,
70
69
  inference: Optional[bool] = None,
71
70
  indices: Sequence[int] | None = None,
72
71
  n_last_blocks: int | None = None,
@@ -88,7 +87,7 @@ class DenseStageFeatures:
88
87
  def __call__(
89
88
  self,
90
89
  x: Float[Array, "channels height width"],
91
- key: PRNGKeyArray = jr.PRNGKey(42),
90
+ key: PRNGKeyArray | None = None,
92
91
  inference: Optional[bool] = None,
93
92
  **kwargs,
94
93
  ) -> Float[Array, "num_classes"]: # noqa: F821
@@ -116,7 +115,7 @@ class TokenStemFeatures:
116
115
  def features(
117
116
  self,
118
117
  x: Float[Array, "..."],
119
- key: PRNGKeyArray = jr.PRNGKey(42),
118
+ key: PRNGKeyArray | None = None,
120
119
  inference: Optional[bool] = None,
121
120
  ) -> Float[Array, "..."]:
122
121
  key_pd, *keys = split_for_mode(key, 1 + len(self.blocks), inference=inference)
@@ -130,7 +129,7 @@ class TokenStemFeatures:
130
129
  def intermediate_features(
131
130
  self,
132
131
  x: Float[Array, "..."],
133
- key: PRNGKeyArray = jr.PRNGKey(42),
132
+ key: PRNGKeyArray | None = None,
134
133
  inference: Optional[bool] = None,
135
134
  indices: Sequence[int] | None = None,
136
135
  n_last_blocks: int | None = None,
@@ -153,7 +152,7 @@ class TokenStemFeatures:
153
152
  def __call__(
154
153
  self,
155
154
  x: Float[Array, "..."],
156
- key: PRNGKeyArray = jr.PRNGKey(42),
155
+ key: PRNGKeyArray | None = None,
157
156
  inference: Optional[bool] = None,
158
157
  ) -> Float[Array, "..."]:
159
158
  """Features, token-mean pooling, and classification head."""
@@ -108,7 +108,7 @@ class AttNet(eqx.Module):
108
108
  def features(
109
109
  self,
110
110
  x: Float[Array, "channels height width"],
111
- key: PRNGKeyArray = jr.PRNGKey(42),
111
+ key: PRNGKeyArray | None = None,
112
112
  inference: Optional[bool] = None,
113
113
  **kwargs,
114
114
  ) -> Float[Array, "num_classes"]: # noqa: F821
@@ -119,7 +119,7 @@ class AttNet(eqx.Module):
119
119
  def intermediate_features(
120
120
  self,
121
121
  x: Float[Array, "channels height width"],
122
- key: PRNGKeyArray = jr.PRNGKey(42),
122
+ key: PRNGKeyArray | None = None,
123
123
  inference: Optional[bool] = None,
124
124
  indices: Sequence[int] | None = None,
125
125
  n_last_blocks: int | None = None,
@@ -141,7 +141,7 @@ class AttNet(eqx.Module):
141
141
  def __call__(
142
142
  self,
143
143
  x: Float[Array, "channels height width"],
144
- key: PRNGKeyArray = jr.PRNGKey(42),
144
+ key: PRNGKeyArray | None = None,
145
145
  inference: Optional[bool] = None,
146
146
  **kwargs,
147
147
  ) -> Float[Array, "num_classes"]: # noqa: F821
@@ -227,7 +227,7 @@ class BlockChunk(eqx.Module):
227
227
  x: Float[Array, "..."],
228
228
  *,
229
229
  z0: Float[Array, "..."] | None = None,
230
- key: PRNGKeyArray,
230
+ key: PRNGKeyArray | None,
231
231
  inference: Optional[bool] = False,
232
232
  **kwargs,
233
233
  ) -> Tuple[Float[Array, "..."], list]:
@@ -362,7 +362,7 @@ class DEQ(eqx.Module):
362
362
  def features(
363
363
  self,
364
364
  x: Float[Array, "channels height width"],
365
- key: PRNGKeyArray = jr.PRNGKey(42),
365
+ key: PRNGKeyArray | None = None,
366
366
  inference: Optional[bool] = None,
367
367
  **kwargs,
368
368
  ) -> Tuple[Float[Array, "num_classes"], list]: # noqa: F821
@@ -380,7 +380,7 @@ class DEQ(eqx.Module):
380
380
  def intermediate_features(
381
381
  self,
382
382
  x: Float[Array, "channels height width"],
383
- key: PRNGKeyArray = jr.PRNGKey(42),
383
+ key: PRNGKeyArray | None = None,
384
384
  inference: Optional[bool] = None,
385
385
  indices: Sequence[int] | None = None,
386
386
  n_last_blocks: int | None = None,
@@ -404,7 +404,7 @@ class DEQ(eqx.Module):
404
404
  def readout(
405
405
  self,
406
406
  z_star: Float[Array, "channels height width"],
407
- key: PRNGKeyArray = jr.PRNGKey(42),
407
+ key: PRNGKeyArray | None = None,
408
408
  inference: Optional[bool] = None,
409
409
  ):
410
410
  if len(self.fpi_index) == 0:
@@ -434,7 +434,7 @@ class DEQ(eqx.Module):
434
434
  def __call__(
435
435
  self,
436
436
  x: Float[Array, "channels height width"],
437
- key: PRNGKeyArray = jr.PRNGKey(42),
437
+ key: PRNGKeyArray | None = None,
438
438
  inference: Optional[bool] = None,
439
439
  **kwargs,
440
440
  ) -> Tuple[Float[Array, "num_classes"], list]: # noqa: F821
@@ -393,7 +393,7 @@ class FasterViT(eqx.Module):
393
393
  def features(
394
394
  self,
395
395
  x: Float[Array, "channels height width"],
396
- key: PRNGKeyArray = jr.PRNGKey(42),
396
+ key: PRNGKeyArray | None = None,
397
397
  inference: Optional[bool] = None,
398
398
  ) -> Float[Array, "seqlen dim"]:
399
399
  """Extract features from input image.
@@ -422,7 +422,7 @@ class FasterViT(eqx.Module):
422
422
  def intermediate_features(
423
423
  self,
424
424
  x: Float[Array, "channels height width"],
425
- key: PRNGKeyArray = jr.PRNGKey(42),
425
+ key: PRNGKeyArray | None = None,
426
426
  inference: Optional[bool] = None,
427
427
  indices: Sequence[int] | None = None,
428
428
  n_last_blocks: int | None = None,
@@ -451,7 +451,7 @@ class FasterViT(eqx.Module):
451
451
  def __call__(
452
452
  self,
453
453
  x: Float[Array, "channels height width"],
454
- key: PRNGKeyArray = jr.PRNGKey(42),
454
+ key: PRNGKeyArray | None = None,
455
455
  inference: Optional[bool] = None,
456
456
  ) -> Float[Array, "num_classes"]: # noqa: F821
457
457
  """Process input image through the full network.
@@ -223,7 +223,7 @@ class LowFormer(eqx.Module):
223
223
  def features(
224
224
  self,
225
225
  x: Float[Array, "channels height width"],
226
- key: PRNGKeyArray = jr.PRNGKey(42),
226
+ key: PRNGKeyArray | None = None,
227
227
  inference: Optional[bool] = None,
228
228
  **kwargs,
229
229
  ) -> Float[Array, "seqlen dim"]:
@@ -251,7 +251,7 @@ class LowFormer(eqx.Module):
251
251
  def intermediate_features(
252
252
  self,
253
253
  x: Float[Array, "channels height width"],
254
- key: PRNGKeyArray = jr.PRNGKey(42),
254
+ key: PRNGKeyArray | None = None,
255
255
  inference: Optional[bool] = None,
256
256
  indices: Sequence[int] | None = None,
257
257
  n_last_blocks: int | None = None,
@@ -280,7 +280,7 @@ class LowFormer(eqx.Module):
280
280
  def __call__(
281
281
  self,
282
282
  x: Float[Array, "channels height width"],
283
- key: PRNGKeyArray = jr.PRNGKey(42),
283
+ key: PRNGKeyArray | None = None,
284
284
  inference: Optional[bool] = None,
285
285
  **kwargs,
286
286
  ) -> Float[Array, "num_classes"]: # noqa: F821
@@ -75,7 +75,7 @@ class MobileNetv3(eqx.Module):
75
75
  def features(
76
76
  self,
77
77
  x: Float[Array, "..."],
78
- key: PRNGKeyArray,
78
+ key: PRNGKeyArray | None = None,
79
79
  inference: Optional[bool] = None,
80
80
  ) -> Float[Array, "..."]:
81
81
  key_conv1, key_layers = split_for_mode(key, 2, inference=inference)
@@ -93,7 +93,7 @@ class MobileNetv3(eqx.Module):
93
93
  def intermediate_features(
94
94
  self,
95
95
  x: Float[Array, "..."],
96
- key: PRNGKeyArray,
96
+ key: PRNGKeyArray | None = None,
97
97
  inference: Optional[bool] = None,
98
98
  indices: Sequence[int] | None = None,
99
99
  n_last_blocks: int | None = None,
@@ -124,7 +124,7 @@ class MobileNetv3(eqx.Module):
124
124
  def __call__(
125
125
  self,
126
126
  x: Float[Array, "..."],
127
- key: PRNGKeyArray,
127
+ key: PRNGKeyArray | None = None,
128
128
  inference: Optional[bool] = None,
129
129
  ) -> Float[Array, "..."]:
130
130
  key_f, key_d = split_for_mode(key, 2, inference=inference)
@@ -1067,7 +1067,7 @@ class VisionParcae(eqx.Module):
1067
1067
  H: int,
1068
1068
  W: int,
1069
1069
  inference: Optional[bool],
1070
- key: PRNGKeyArray,
1070
+ key: PRNGKeyArray | None,
1071
1071
  rotary=None,
1072
1072
  checkpoint: bool = False,
1073
1073
  **kwargs,
@@ -1288,7 +1288,7 @@ class VisionParcae(eqx.Module):
1288
1288
  H: int,
1289
1289
  W: int,
1290
1290
  inference: Optional[bool],
1291
- key: PRNGKeyArray,
1291
+ key: PRNGKeyArray | None,
1292
1292
  rotary=None,
1293
1293
  checkpoint: bool = False,
1294
1294
  **kwargs,
@@ -1315,7 +1315,7 @@ class VisionParcae(eqx.Module):
1315
1315
  H: int,
1316
1316
  W: int,
1317
1317
  inference: Optional[bool],
1318
- key: PRNGKeyArray,
1318
+ key: PRNGKeyArray | None,
1319
1319
  num_steps: int | Array | None = None,
1320
1320
  num_steps_pair: tuple[int | Array, int | Array]
1321
1321
  | list[int | Array]
@@ -1344,11 +1344,17 @@ class VisionParcae(eqx.Module):
1344
1344
  key=key_rope,
1345
1345
  )
1346
1346
 
1347
- keys = jnp.stack(
1348
- split_for_mode(
1349
- key_loop,
1350
- self.max_recurrence,
1351
- inference=deterministic_inference,
1347
+ # A missing key is only accepted for deterministic inference, where no
1348
+ # recurrent step consumes randomness.
1349
+ keys = (
1350
+ None
1351
+ if key_loop is None
1352
+ else jnp.stack(
1353
+ split_for_mode(
1354
+ key_loop,
1355
+ self.max_recurrence,
1356
+ inference=deterministic_inference,
1357
+ )
1352
1358
  )
1353
1359
  )
1354
1360
 
@@ -1372,9 +1378,13 @@ class VisionParcae(eqx.Module):
1372
1378
  grad_scan_bound = min(self.max_recurrence, self.mean_backprop_depth)
1373
1379
  no_grad_scan_bound = self.max_recurrence - grad_scan_bound
1374
1380
 
1375
- def no_grad_body(carry, xs):
1381
+ def step_key(index):
1382
+ if keys is None:
1383
+ return None
1384
+ return jax.lax.dynamic_index_in_dim(keys, index, axis=0, keepdims=False)
1385
+
1386
+ def no_grad_body(carry, t):
1376
1387
  h_cur, last_cur = carry
1377
- t, key_step = xs
1378
1388
  active = t < no_grad_steps
1379
1389
 
1380
1390
  def inactive(c):
@@ -1388,7 +1398,7 @@ class VisionParcae(eqx.Module):
1388
1398
  H=H,
1389
1399
  W=W,
1390
1400
  inference=inference,
1391
- key=key_step,
1401
+ key=step_key(t),
1392
1402
  rotary=rotary,
1393
1403
  checkpoint=False,
1394
1404
  **kwargs,
@@ -1401,11 +1411,7 @@ class VisionParcae(eqx.Module):
1401
1411
 
1402
1412
  if no_grad_scan_bound:
1403
1413
  no_grad_ts = jnp.arange(no_grad_scan_bound, dtype=jnp.int32)
1404
- (h, last_h), _ = jax.lax.scan(
1405
- no_grad_body,
1406
- (h, h),
1407
- (no_grad_ts, keys[:no_grad_scan_bound]),
1408
- )
1414
+ (h, last_h), _ = jax.lax.scan(no_grad_body, (h, h), no_grad_ts)
1409
1415
  h = jax.lax.stop_gradient(h)
1410
1416
  last_h = jax.lax.stop_gradient(last_h)
1411
1417
  else:
@@ -1424,16 +1430,13 @@ class VisionParcae(eqx.Module):
1424
1430
  no_grad_steps + t,
1425
1431
  jnp.asarray(self.max_recurrence - 1, jnp.int32),
1426
1432
  )
1427
- key_step = jax.lax.dynamic_index_in_dim(
1428
- keys, key_index, axis=0, keepdims=False
1429
- )
1430
1433
  h_next = self._recurrent_step(
1431
1434
  h_active,
1432
1435
  e,
1433
1436
  H=H,
1434
1437
  W=W,
1435
1438
  inference=inference,
1436
- key=key_step,
1439
+ key=step_key(key_index),
1437
1440
  rotary=rotary,
1438
1441
  checkpoint=self.recurrent_checkpoint,
1439
1442
  **kwargs,
@@ -1463,7 +1466,7 @@ class VisionParcae(eqx.Module):
1463
1466
  self,
1464
1467
  x: Float[Array, "channels height width"],
1465
1468
  *,
1466
- key: PRNGKeyArray,
1469
+ key: PRNGKeyArray | None,
1467
1470
  mask: Optional[Int[Array, "embed_h embed_w"]] = None,
1468
1471
  inference: Optional[bool] = None,
1469
1472
  num_steps: int | Array | None = None,
@@ -1474,6 +1477,12 @@ class VisionParcae(eqx.Module):
1474
1477
  **kwargs,
1475
1478
  ) -> tuple[Float[Array, "seq dim"], dict]:
1476
1479
  deterministic_inference = inference is True and self.state_init == "zero"
1480
+ if key is None and not deterministic_inference:
1481
+ raise ValueError(
1482
+ "VisionParcae requires a PRNG key unless inference=True and "
1483
+ f"state_init='zero' (got inference={inference!r}, "
1484
+ f"state_init={self.state_init!r})."
1485
+ )
1477
1486
  key_embed, key_prelude, key_loop, key_coda = split_for_mode(
1478
1487
  key, 4, inference=deterministic_inference
1479
1488
  )
@@ -1525,7 +1534,7 @@ class VisionParcae(eqx.Module):
1525
1534
  def features(
1526
1535
  self,
1527
1536
  x: Float[Array, "channels height width"],
1528
- key: PRNGKeyArray,
1537
+ key: PRNGKeyArray | None = None,
1529
1538
  mask: Optional[Int[Array, "embed_h embed_w"]] = None,
1530
1539
  inference: Optional[bool] = None,
1531
1540
  num_steps: int | Array | None = None,
@@ -1556,7 +1565,7 @@ class VisionParcae(eqx.Module):
1556
1565
  def forward_features(
1557
1566
  self,
1558
1567
  x: Float[Array, "channels height width"],
1559
- key: PRNGKeyArray,
1568
+ key: PRNGKeyArray | None = None,
1560
1569
  inference: Optional[bool] = None,
1561
1570
  **kwargs,
1562
1571
  ) -> dict:
@@ -1590,7 +1599,7 @@ class VisionParcae(eqx.Module):
1590
1599
  def intermediate_features(
1591
1600
  self,
1592
1601
  x: Float[Array, "channels height width"],
1593
- key: PRNGKeyArray,
1602
+ key: PRNGKeyArray | None = None,
1594
1603
  inference: Optional[bool] = None,
1595
1604
  indices: Sequence[int] | None = None,
1596
1605
  n_last_blocks: int | None = None,
@@ -1686,7 +1695,7 @@ class VisionParcae(eqx.Module):
1686
1695
  *,
1687
1696
  H: int | None = None,
1688
1697
  W: int | None = None,
1689
- key: PRNGKeyArray = jr.PRNGKey(42),
1698
+ key: PRNGKeyArray | None = None,
1690
1699
  inference: Optional[bool] = True,
1691
1700
  **kwargs,
1692
1701
  ) -> Float[Array, "num_classes"]: # noqa: F821
@@ -1723,7 +1732,7 @@ class VisionParcae(eqx.Module):
1723
1732
  def __call__(
1724
1733
  self,
1725
1734
  x: Float[Array, "channels height width"],
1726
- key: PRNGKeyArray = jr.PRNGKey(42),
1735
+ key: PRNGKeyArray | None = None,
1727
1736
  inference: Optional[bool] = None,
1728
1737
  num_steps: int | Array | None = None,
1729
1738
  num_steps_pair: tuple[int | Array, int | Array]
@@ -305,7 +305,7 @@ class PartialFormer(eqx.Module):
305
305
  def features(
306
306
  self,
307
307
  x: Float[Array, "channels height width"],
308
- key: PRNGKeyArray = ...,
308
+ key: PRNGKeyArray | None = ...,
309
309
  inference: Optional[bool] = ...,
310
310
  return_qa: Literal[False] = ...,
311
311
  ) -> Float[Array, "seqlen dim"]: ...
@@ -314,7 +314,7 @@ class PartialFormer(eqx.Module):
314
314
  def features(
315
315
  self,
316
316
  x: Float[Array, "channels height width"],
317
- key: PRNGKeyArray = ...,
317
+ key: PRNGKeyArray | None = ...,
318
318
  inference: Optional[bool] = ...,
319
319
  *,
320
320
  return_qa: Literal[True],
@@ -323,7 +323,7 @@ class PartialFormer(eqx.Module):
323
323
  def features(
324
324
  self,
325
325
  x: Float[Array, "channels height width"],
326
- key: PRNGKeyArray = jr.PRNGKey(42),
326
+ key: PRNGKeyArray | None = None,
327
327
  inference: Optional[bool] = None,
328
328
  return_qa: bool = False,
329
329
  ) -> (
@@ -364,7 +364,7 @@ class PartialFormer(eqx.Module):
364
364
  def intermediate_features(
365
365
  self,
366
366
  x: Float[Array, "channels height width"],
367
- key: PRNGKeyArray = jr.PRNGKey(42),
367
+ key: PRNGKeyArray | None = None,
368
368
  inference: Optional[bool] = None,
369
369
  indices: Sequence[int] | None = None,
370
370
  n_last_blocks: int | None = None,
@@ -401,7 +401,7 @@ class PartialFormer(eqx.Module):
401
401
  def __call__(
402
402
  self,
403
403
  x: Float[Array, "channels height width"],
404
- key: PRNGKeyArray = jr.PRNGKey(42),
404
+ key: PRNGKeyArray | None = None,
405
405
  inference: Optional[bool] = None,
406
406
  ) -> Float[Array, "num_classes"]: # noqa: F821
407
407
  """Process input image through the full network.