haliax 1.4.dev367__tar.gz → 1.4.dev369__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 (114) hide show
  1. haliax-1.4.dev369/.playbooks/add-types.md +45 -0
  2. {haliax-1.4.dev367 → haliax-1.4.dev369}/AGENTS.md +6 -2
  3. {haliax-1.4.dev367 → haliax-1.4.dev369}/PKG-INFO +1 -1
  4. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/scan.md +11 -0
  5. haliax-1.4.dev369/docs/vmap.md +9 -0
  6. haliax-1.4.dev369/src/haliax/__about__.py +1 -0
  7. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/nn/scan.py +31 -0
  8. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_scan.py +24 -0
  9. haliax-1.4.dev367/docs/vmap.md +0 -5
  10. haliax-1.4.dev367/src/haliax/__about__.py +0 -1
  11. {haliax-1.4.dev367 → haliax-1.4.dev369}/.coveragerc +0 -0
  12. {haliax-1.4.dev367 → haliax-1.4.dev369}/.flake8 +0 -0
  13. {haliax-1.4.dev367 → haliax-1.4.dev369}/.github/workflows/publish_dev.yaml +0 -0
  14. {haliax-1.4.dev367 → haliax-1.4.dev369}/.github/workflows/run_pre_commit.yaml +0 -0
  15. {haliax-1.4.dev367 → haliax-1.4.dev369}/.github/workflows/run_quick_levanter_tests.yaml +0 -0
  16. {haliax-1.4.dev367 → haliax-1.4.dev369}/.github/workflows/run_tests.yaml +0 -0
  17. {haliax-1.4.dev367 → haliax-1.4.dev369}/.gitignore +0 -0
  18. {haliax-1.4.dev367 → haliax-1.4.dev369}/.pre-commit-config.yaml +0 -0
  19. {haliax-1.4.dev367 → haliax-1.4.dev369}/.readthedocs.yaml +0 -0
  20. {haliax-1.4.dev367 → haliax-1.4.dev369}/CONTRIBUTING.md +0 -0
  21. {haliax-1.4.dev367 → haliax-1.4.dev369}/LICENSE +0 -0
  22. {haliax-1.4.dev367 → haliax-1.4.dev369}/README.md +0 -0
  23. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/api.md +0 -0
  24. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/broadcasting.md +0 -0
  25. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/cheatsheet.md +0 -0
  26. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/css/material.css +0 -0
  27. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/css/mkdocstrings.css +0 -0
  28. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/faq.md +0 -0
  29. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/figures/data_parallel_mesh.png +0 -0
  30. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/figures/data_parallel_mesh_replicated.png +0 -0
  31. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/figures/device_mesh_1d.png +0 -0
  32. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/figures/device_mesh_1d_zero.png +0 -0
  33. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/figures/device_mesh_2d.png +0 -0
  34. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/figures/device_mesh_2d_batch_partitioned.png +0 -0
  35. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/figures/device_mesh_2d_data_replicated.png +0 -0
  36. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/figures/device_mesh_2d_data_replicated_mlp_partitioned.png +0 -0
  37. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/figures/device_mesh_2d_intermediate_fully_partitioned.png +0 -0
  38. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/figures/device_mesh_2d_zero.png +0 -0
  39. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/fp8.md +0 -0
  40. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/index.md +0 -0
  41. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/indexing.md +0 -0
  42. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/matmul.md +0 -0
  43. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/nn.md +0 -0
  44. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/partitioning.md +0 -0
  45. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/rearrange.ipynb +0 -0
  46. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/rearrange.md +0 -0
  47. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/requirements.txt +0 -0
  48. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/state-dict.md +0 -0
  49. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/tutorial.md +0 -0
  50. {haliax-1.4.dev367 → haliax-1.4.dev369}/docs/typing.md +0 -0
  51. {haliax-1.4.dev367 → haliax-1.4.dev369}/mkdocs.yml +0 -0
  52. {haliax-1.4.dev367 → haliax-1.4.dev369}/pyproject.toml +0 -0
  53. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/__init__.py +0 -0
  54. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/_src/__init__.py +0 -0
  55. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/_src/compile_utils.py +0 -0
  56. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/_src/dot.py +0 -0
  57. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/_src/einsum.py +0 -0
  58. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/_src/fp8.py +0 -0
  59. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/_src/parsing.py +0 -0
  60. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/_src/rearrange.py +0 -0
  61. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/_src/scan.py +0 -0
  62. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/_src/state_dict.py +0 -0
  63. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/_src/util.py +0 -0
  64. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/axis.py +0 -0
  65. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/core.py +0 -0
  66. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/debug.py +0 -0
  67. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/haxtyping.py +0 -0
  68. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/hof.py +0 -0
  69. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/jax_utils.py +0 -0
  70. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/nn/__init__.py +0 -0
  71. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/nn/activations.py +0 -0
  72. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/nn/attention.py +0 -0
  73. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/nn/conv.py +0 -0
  74. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/nn/dropout.py +0 -0
  75. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/nn/embedding.py +0 -0
  76. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/nn/linear.py +0 -0
  77. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/nn/loss.py +0 -0
  78. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/nn/mlp.py +0 -0
  79. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/nn/normalization.py +0 -0
  80. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/nn/pool.py +0 -0
  81. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/ops.py +0 -0
  82. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/partitioning.py +0 -0
  83. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/quantization.py +0 -0
  84. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/random.py +0 -0
  85. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/specialized_fns.py +0 -0
  86. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/state_dict.py +0 -0
  87. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/tree_util.py +0 -0
  88. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/types.py +0 -0
  89. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/util.py +0 -0
  90. {haliax-1.4.dev367 → haliax-1.4.dev369}/src/haliax/wrap.py +0 -0
  91. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/core_test.py +0 -0
  92. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_attention.py +0 -0
  93. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_axis.py +0 -0
  94. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_conv.py +0 -0
  95. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_debug.py +0 -0
  96. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_dot.py +0 -0
  97. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_dtype_typing.py +0 -0
  98. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_einsum.py +0 -0
  99. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_fp8.py +0 -0
  100. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_hof.py +0 -0
  101. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_int8.py +0 -0
  102. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_namedarray_typing.py +0 -0
  103. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_nn.py +0 -0
  104. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_ops.py +0 -0
  105. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_parsing.py +0 -0
  106. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_partitioning.py +0 -0
  107. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_pool.py +0 -0
  108. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_random.py +0 -0
  109. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_rearrange.py +0 -0
  110. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_scatter_gather.py +0 -0
  111. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_specialized_fns.py +0 -0
  112. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_state_dict.py +0 -0
  113. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_tree_util.py +0 -0
  114. {haliax-1.4.dev367 → haliax-1.4.dev369}/tests/test_utils.py +0 -0
@@ -0,0 +1,45 @@
1
+ # Adding NamedArray Type Annotations
2
+
3
+ This playbook explains how to migrate existing code to use the new type
4
+ annotation helpers described in `docs/typing.md`.
5
+
6
+ 1. **Read the documentation**: Familiarise yourself with `docs/typing.md`.
7
+ It describes the `Named[...]` syntax and the dtype aware helpers in
8
+ `haliax.typing`.
9
+ 2. **Annotate parameters**: Replace plain `NamedArray` annotations with
10
+ `Named[...]` that lists the required axes. Use ellipses or sets when the
11
+ exact order is flexible.
12
+
13
+ ```python
14
+ from haliax import Named
15
+
16
+ # old
17
+ def foo(x: NamedArray) -> NamedArray:
18
+ ...
19
+
20
+ # new
21
+ def foo(x: Named["batch", "embed"]) -> Named["batch", "embed"]:
22
+ ...
23
+ ```
24
+ 3. **Annotate dtypes when needed**: If the dtype matters, import symbolic dtypes
25
+ from `haliax.typing` (e.g. `ht.f32`, `ht.i32`). They can be indexed just
26
+ like `Named`.
27
+
28
+ ```python
29
+ import haliax.typing as ht
30
+
31
+ def bar(x: ht.f32["batch"]):
32
+ ...
33
+ ```
34
+ 4. **Runtime validation**: Use `arr.matches_axes(...)` to check that a
35
+ `NamedArray` conforms to the expected axes and dtype at runtime.
36
+
37
+ ```python
38
+ if not arr.matches_axes(Named["batch embed ..."]):
39
+ raise ValueError("unexpected axes")
40
+ ```
41
+ 5. **Update return types**: Functions returning `NamedArray` should annotate
42
+ their return values using the same conventions.
43
+
44
+ Following these steps will gradually port legacy code to the new
45
+ annotation style.
@@ -16,8 +16,7 @@ repository. Follow these notes when implementing new features or fixing bugs.
16
16
 
17
17
  ## Playbook
18
18
 
19
- - At the moment, there are no playbooks available. If you have a repeatable task that you think
20
- should be documented, please create a new markdown file in `.playbooks/` and add it to the list above.
19
+ - Adding Haliax-style tensor typing annotations are described in @.playbooks/add-typing.md
21
20
 
22
21
  ## Code Style
23
22
 
@@ -58,6 +57,11 @@ repository. Follow these notes when implementing new features or fixing bugs.
58
57
 
59
58
  * **Generic code**: many utilities are written with Python generics and dataclasses. Where possible,
60
59
  write reusable functions or classes that operate over TypeVars instead of hard coding concrete types.
60
+ * **Configurations**: configuration files are dataclasses loaded via `draccus`. Keep configs
61
+ declarative and typed.
62
+ * **Reproducibility**: Levanter aims for deterministic training where possible. Avoid sources of
63
+ nondeterminism unless explicitly required.
64
+ * Prefer Stacked with fold or scan over writing custom loops, for better compile times and gradient checkpointing support
61
65
 
62
66
  ## Library conventions
63
67
  - Haliax revolves around `NamedArray` and explicit `Axis` objects. Prefer APIs that accept
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: haliax
3
- Version: 1.4.dev367
3
+ Version: 1.4.dev369
4
4
  Summary: Named Tensors for Legible Deep Learning in JAX
5
5
  Project-URL: Homepage, https://github.com/stanford-crfm/haliax
6
6
  Project-URL: Bug Tracker, https://github.com/stanford-crfm/haliax/issues/
@@ -405,6 +405,17 @@ blocks = Stacked.init(Layers, Gpt2Block)(
405
405
  Any NamedArray passed to the Stacked init will have its Layers axis (if present) vmapped over. Any
406
406
  JAX array will have its first axis vmapped over.
407
407
 
408
+ #### Apply Blocks in Parallel with `vmap`
409
+
410
+ Sometimes you may want to apply each block independently, without feeding the
411
+ output of one block into the next. `Stacked.vmap` does exactly that: it uses
412
+ [`haliax.vmap`][] to broadcast the initial value to every block and evaluates
413
+ them in parallel, returning the stack of outputs.
414
+
415
+ ```python
416
+ y = stacked.vmap(x)
417
+ ```
418
+
408
419
 
409
420
  #### Fold Blocks vs Scan Blocks
410
421
 
@@ -0,0 +1,9 @@
1
+ ## Vectorization
2
+
3
+
4
+ This primitive is also used by [`Stacked.vmap`](scan.md#apply-blocks-in-parallel-with-vmap)
5
+ to apply an entire stack of blocks in parallel.
6
+
7
+ (This is a work in progress. Please contact dlwh for more information.)
8
+
9
+ ::: haliax.vmap
@@ -0,0 +1 @@
1
+ __version__ = "1.4.dev369"
@@ -233,6 +233,8 @@ class Stacked(ModuleWithStateDictSerialization, Generic[M]):
233
233
  output, while "scan" is the same as a for loop that accumulates a list of outputs as well as the final output.
234
234
 
235
235
  Stacked also supports gradient checkpointing, which is useful for very large models that don't fit in memory.
236
+ If your blocks are independent of each other you can instead use :py:meth:`Stacked.vmap`
237
+ to apply every block in parallel.
236
238
 
237
239
  Typically only one of "fold" or "scan" can be used with a given Stacked module, depending on the what the module
238
240
  returns: if the module returns a single output, use "fold"; if the module returns a sequence of outputs and
@@ -382,6 +384,35 @@ class Stacked(ModuleWithStateDictSerialization, Generic[M]):
382
384
 
383
385
  return do_fold(init, *args, **kwargs)
384
386
 
387
+ def vmap(self, init, *extra_args, **extra_kwargs):
388
+ """Apply each block independently using :func:`haliax.vmap`.
389
+
390
+ This maps ``init`` through every block in parallel, so each block
391
+ receives the same ``init`` but its own parameters. Extra ``args`` and
392
+ ``kwargs`` are also mapped over the block axis by default.
393
+
394
+ Returns the stacked outputs of each block.
395
+ """
396
+
397
+ if haliax.is_named_array(init):
398
+ init = init.broadcast_axis(self.Block)
399
+ elif haliax.jax_utils.is_jax_array_like(init):
400
+ init = jnp.broadcast_to(init, (self.Block.size,) + init.shape)
401
+ else:
402
+ init = tuple(init for _ in range(self.Block.size))
403
+
404
+ arg_spec = (0, 0) + (0,) * len(extra_args)
405
+ kwarg_spec = {k: 0 for k in extra_kwargs}
406
+
407
+ do_vmap = haliax.vmap(
408
+ Stacked._do_block,
409
+ self.Block,
410
+ default=0,
411
+ args=arg_spec,
412
+ kwargs=kwarg_spec,
413
+ )
414
+ return do_vmap(init, self.stacked, *extra_args, **extra_kwargs)
415
+
385
416
  @staticmethod
386
417
  def _do_block(carry, block, *extra_args, **extra_kwargs):
387
418
  return block(carry, *extra_args, **extra_kwargs)
@@ -45,6 +45,30 @@ def test_unstacked():
45
45
  assert hax.all(module.array == m.stacked.array[i])
46
46
 
47
47
 
48
+ def test_vmap():
49
+ class Module(eqx.Module):
50
+ weight: hax.NamedArray
51
+
52
+ def __call__(self, x):
53
+ return x + self.weight
54
+
55
+ @staticmethod
56
+ def init(weight):
57
+ return Module(weight=weight)
58
+
59
+ Block = hax.Axis("block", 4)
60
+ E = hax.Axis("E", 10)
61
+
62
+ weights = hax.random.uniform(jax.random.PRNGKey(0), (Block, E))
63
+ m = Stacked.init(Block, Module)(weight=weights)
64
+
65
+ x = hax.random.uniform(jax.random.PRNGKey(1), (E,))
66
+ y = m.vmap(x)
67
+
68
+ assert y.axes == (Block, E)
69
+ assert hax.all(y == weights + x)
70
+
71
+
48
72
  def test_seq_and_stacked_give_same_results():
49
73
  class Module(eqx.Module):
50
74
  named: hax.NamedArray
@@ -1,5 +0,0 @@
1
- ## Vectorization
2
-
3
- (This is a work in progress. Please contact dlwh for more information.)
4
-
5
- ::: haliax.vmap
@@ -1 +0,0 @@
1
- __version__ = "1.4.dev367"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes