haliax 1.4.dev364__tar.gz → 1.4.dev366__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.
- {haliax-1.4.dev364 → haliax-1.4.dev366}/.pre-commit-config.yaml +16 -16
- haliax-1.4.dev366/AGENTS.md +79 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/PKG-INFO +2 -1
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/nn.md +0 -1
- haliax-1.4.dev366/docs/typing.md +100 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/pyproject.toml +7 -1
- haliax-1.4.dev366/src/haliax/__about__.py +1 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/__init__.py +16 -16
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/_src/dot.py +0 -2
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/_src/fp8.py +0 -1
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/_src/state_dict.py +3 -4
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/core.py +2 -15
- haliax-1.4.dev366/src/haliax/haxtyping.py +138 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/hof.py +1 -1
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/nn/attention.py +0 -1
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/nn/embedding.py +0 -2
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/nn/scan.py +3 -3
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/partitioning.py +1 -1
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/random.py +0 -3
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/wrap.py +0 -3
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_attention.py +0 -1
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_dot.py +1 -1
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_dtype_typing.py +1 -1
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_namedarray_typing.py +7 -7
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_scatter_gather.py +0 -1
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_tree_util.py +0 -1
- haliax-1.4.dev364/docs/typing.md +0 -61
- haliax-1.4.dev364/src/haliax/__about__.py +0 -1
- haliax-1.4.dev364/src/haliax/typing.py +0 -88
- {haliax-1.4.dev364 → haliax-1.4.dev366}/.coveragerc +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/.flake8 +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/.github/workflows/publish_dev.yaml +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/.github/workflows/run_pre_commit.yaml +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/.github/workflows/run_quick_levanter_tests.yaml +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/.github/workflows/run_tests.yaml +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/.gitignore +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/.readthedocs.yaml +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/CONTRIBUTING.md +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/LICENSE +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/README.md +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/api.md +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/broadcasting.md +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/cheatsheet.md +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/css/material.css +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/css/mkdocstrings.css +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/faq.md +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/figures/data_parallel_mesh.png +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/figures/data_parallel_mesh_replicated.png +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/figures/device_mesh_1d.png +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/figures/device_mesh_1d_zero.png +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/figures/device_mesh_2d.png +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/figures/device_mesh_2d_batch_partitioned.png +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/figures/device_mesh_2d_data_replicated.png +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/figures/device_mesh_2d_data_replicated_mlp_partitioned.png +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/figures/device_mesh_2d_intermediate_fully_partitioned.png +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/figures/device_mesh_2d_zero.png +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/fp8.md +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/index.md +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/indexing.md +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/matmul.md +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/partitioning.md +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/rearrange.ipynb +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/rearrange.md +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/requirements.txt +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/scan.md +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/state-dict.md +1 -1
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/tutorial.md +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/docs/vmap.md +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/mkdocs.yml +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/_src/__init__.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/_src/compile_utils.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/_src/einsum.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/_src/parsing.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/_src/rearrange.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/_src/scan.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/_src/util.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/axis.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/debug.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/jax_utils.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/nn/__init__.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/nn/activations.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/nn/conv.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/nn/dropout.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/nn/linear.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/nn/loss.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/nn/mlp.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/nn/normalization.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/nn/pool.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/ops.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/quantization.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/specialized_fns.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/state_dict.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/tree_util.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/types.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/src/haliax/util.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/core_test.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_axis.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_conv.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_debug.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_einsum.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_fp8.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_hof.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_int8.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_nn.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_ops.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_parsing.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_partitioning.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_pool.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_random.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_rearrange.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_scan.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_specialized_fns.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_state_dict.py +0 -0
- {haliax-1.4.dev364 → haliax-1.4.dev366}/tests/test_utils.py +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# See https://pre-commit.com/hooks.html for more hooks
|
|
3
3
|
exclude: ".git"
|
|
4
4
|
default_stages:
|
|
5
|
-
- commit
|
|
5
|
+
- pre-commit
|
|
6
6
|
fail_fast: true
|
|
7
7
|
|
|
8
8
|
repos:
|
|
@@ -16,24 +16,24 @@ repos:
|
|
|
16
16
|
- id: check-merge-conflict
|
|
17
17
|
- id: check-added-large-files
|
|
18
18
|
|
|
19
|
-
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
-
|
|
23
|
-
|
|
24
|
-
- repo: https://github.com/timothycrosley/isort
|
|
25
|
-
rev: 5.11.5
|
|
26
|
-
hooks:
|
|
27
|
-
- id: isort
|
|
19
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
20
|
+
rev: v0.11.10
|
|
21
|
+
hooks:
|
|
22
|
+
- id: ruff
|
|
23
|
+
args: [ --fix, --exit-non-zero-on-fix ]
|
|
28
24
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
#- repo: local
|
|
26
|
+
# hooks:
|
|
27
|
+
# - id: ty-check
|
|
28
|
+
# name: ty-check
|
|
29
|
+
# language: python
|
|
30
|
+
# entry: ty check
|
|
31
|
+
# pass_filenames: false
|
|
32
|
+
# args: [--python=.venv/]
|
|
33
|
+
# additional_dependencies: [ty]
|
|
34
34
|
|
|
35
35
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
36
|
-
rev: 'v1.
|
|
36
|
+
rev: 'v1.16.1'
|
|
37
37
|
hooks:
|
|
38
38
|
- id: mypy
|
|
39
39
|
args: [--ignore-missing-imports, --check-untyped-defs]
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Haliax LLM Agent Guidelines
|
|
2
|
+
|
|
3
|
+
This document summarizes important conventions for contributing code or documentation to the Haliax
|
|
4
|
+
repository. Follow these notes when implementing new features or fixing bugs.
|
|
5
|
+
|
|
6
|
+
## General Guidelines
|
|
7
|
+
|
|
8
|
+
* **Get better.** Whenever you discover something missing from these guidelines, or the requester
|
|
9
|
+
suggests a better way to do something, please update this document. The goal is to make it easier for
|
|
10
|
+
everyone to contribute and maintain the codebase. Generally speaking, you should add bullets or new sections.
|
|
11
|
+
Be sure to do this when directed to. For example, if directed that you should never relax tolerances in
|
|
12
|
+
floating point tests, add that to the list.
|
|
13
|
+
* **Playbooks.** Sometimes, there are repeatable tasks (e.g. porting models) for which we follow a standard set of steps.
|
|
14
|
+
Please reference `.playbooks/` to see what playbooks are available, or see the list below. If you want to add a playbook
|
|
15
|
+
write a markdown doc named e.g. `.playbooks/port-models.md` and add a pointer to it in the list below.
|
|
16
|
+
|
|
17
|
+
## Playbook
|
|
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.
|
|
21
|
+
|
|
22
|
+
## Code Style
|
|
23
|
+
|
|
24
|
+
* **Python version**: the project targets Python >=3.10.
|
|
25
|
+
* **Formatting and Linting**: We use `ruff` via `pre-commit`.
|
|
26
|
+
* **Typing**: the code base uses `mypy` for static type checking. `mypy` is run by pre‑commit and the
|
|
27
|
+
configuration is found in `pyproject.toml`.
|
|
28
|
+
* **Run `pre-commit run --all-files`** before committing. The CI workflows run the same checks.
|
|
29
|
+
* **Doc Strings**: All public functions, classes, and modules should have docstrings, unless
|
|
30
|
+
their purpose is painfully obvious. Use
|
|
31
|
+
[Google style](https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings) for
|
|
32
|
+
consistency.
|
|
33
|
+
* **Commenting**: Use comments to explain why something is done a certain way, especially if it is not
|
|
34
|
+
immediately obvious. Avoid commenting on every line of code; focus on the intent and purpose of
|
|
35
|
+
complex logic. Demarcating logical groups of code with comments is encouraged, unless it is better
|
|
36
|
+
to refactor the code into smaller functions or classes.
|
|
37
|
+
* **Mkdocs**: We use [Mkdocs](https://www.mkdocs.org/) for documentation. The main documentation is in
|
|
38
|
+
the `docs` directory. Use Markdown for writing docs, and follow the existing structure. When linking to
|
|
39
|
+
symbols, prefer using mkdocs-style links (e.g. With a custom title: `[full.path.object2][]` or
|
|
40
|
+
`[Object 1][full.path.object1]`)
|
|
41
|
+
* **Documentation**: When adding new features, ensure that the documentation is updated accordingly.
|
|
42
|
+
This includes updating the Mkdocs files and any relevant docstrings. If you add a new module or
|
|
43
|
+
significant functionality, consider adding a dedicated section in the documentation.
|
|
44
|
+
|
|
45
|
+
## Testing
|
|
46
|
+
|
|
47
|
+
* Tests are executed with `pytest`. The default workflow runs
|
|
48
|
+
`pytest tests -m "not entry and not slow and not ray"`.
|
|
49
|
+
* In general, never relax tolerances in floating point tests unless specifically discussed with the
|
|
50
|
+
team. Use `assert_allclose` with appropriate tolerances for numerical comparisons. We typically use
|
|
51
|
+
1e-4 for more complex modules, and 1e-5 for simpler ones.
|
|
52
|
+
* Tests should be reasonably fast. Mark long-running tests with @pytest.mark.slow so they are excluded from the default suite.
|
|
53
|
+
* Always mark tests that depend on pytorch with `@skip_if_no_torch` to ensure they are skipped
|
|
54
|
+
when PyTorch is not available. This is particularly important for tests that require PyTorch-specific
|
|
55
|
+
functionality.
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
## Design Preferences
|
|
59
|
+
|
|
60
|
+
* **Generic code**: many utilities are written with Python generics and dataclasses. Where possible,
|
|
61
|
+
write reusable functions or classes that operate over TypeVars instead of hard coding concrete types.
|
|
62
|
+
* **Configurations**: configuration files are dataclasses loaded via `draccus`. Keep configs
|
|
63
|
+
declarative and typed.
|
|
64
|
+
* **Reproducibility**: Levanter aims for deterministic training where possible. Avoid sources of
|
|
65
|
+
nondeterminism unless explicitly required.
|
|
66
|
+
* Prefer Stacked with fold or scan over writing custom loops, for better compile times and gradient checkpointing support
|
|
67
|
+
|
|
68
|
+
## Library conventions
|
|
69
|
+
- Haliax revolves around `NamedArray` and explicit `Axis` objects. Prefer APIs that accept
|
|
70
|
+
axes or axis names rather than hard‑coding positional dimensions.
|
|
71
|
+
- Utilities should be written so they work with arbitrary axis names. Avoid relying on
|
|
72
|
+
fixed axis orders when possible.
|
|
73
|
+
- Use the provided modules in `haliax.nn` or Equinox when building neural network layers.
|
|
74
|
+
- Type annotations can use named shapes shorthand provided in `haliax.haxtyping`: `ht.f32[NamedArray, "batch"]`
|
|
75
|
+
for a float32 array with a "batch" axis, or `ht.Float[NamedArray, "batch"]` for any floating point dtype.
|
|
76
|
+
|
|
77
|
+
## Documentation
|
|
78
|
+
- Public functions and modules require docstrings. If behavior is non‑obvious,
|
|
79
|
+
add examples in `docs/`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: haliax
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.dev366
|
|
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/
|
|
@@ -29,6 +29,7 @@ Requires-Dist: mkdocs>=1.4.3; extra == 'dev'
|
|
|
29
29
|
Requires-Dist: mkdocstrings-python>=1.1.2; extra == 'dev'
|
|
30
30
|
Requires-Dist: mkdocstrings>=0.22.0; extra == 'dev'
|
|
31
31
|
Requires-Dist: mypy>=0.910; extra == 'dev'
|
|
32
|
+
Requires-Dist: pre-commit; extra == 'dev'
|
|
32
33
|
Requires-Dist: pygments; extra == 'dev'
|
|
33
34
|
Requires-Dist: pymdown-extensions; extra == 'dev'
|
|
34
35
|
Requires-Dist: pytest>=7.4.0; extra == 'dev'
|
|
@@ -55,7 +55,6 @@ We don't provide an explicit attention module, but we do provide an attention fu
|
|
|
55
55
|
|
|
56
56
|
:::haliax.nn.attention.dot_product_attention
|
|
57
57
|
:::haliax.nn.attention.dot_product_attention_weights
|
|
58
|
-
:::haliax.nn.attention.self_attention
|
|
59
58
|
|
|
60
59
|
### Masks
|
|
61
60
|
::: haliax.nn.attention.causal_mask
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
from haliax import NamedArrayfrom haliax import NamedArray
|
|
2
|
+
|
|
3
|
+
# NamedArray Type Annotations
|
|
4
|
+
|
|
5
|
+
Haliax supports an extension to [`jaxtyping`](https://docs.kidger.site/jaxtyping/)
|
|
6
|
+
that allows you to annotate functions and methods that take or return
|
|
7
|
+
[`NamedArray`][haliax.core.NamedArray] objects. If you are familiar with
|
|
8
|
+
[`jaxtyping`](https://docs.kidger.site/jaxtyping/), the syntax is very similar.
|
|
9
|
+
In fact, for non-NamedArrays, it is exactly the same.
|
|
10
|
+
|
|
11
|
+
```python
|
|
12
|
+
from haliax import NamedArray
|
|
13
|
+
import haliax.haxtyping as ht
|
|
14
|
+
|
|
15
|
+
def foo(x: ht.Float[NamedArray, "batch embed ..."]):
|
|
16
|
+
...
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
At runtime you can verify that a `NamedArray` conforms to a particular
|
|
20
|
+
annotation using `matches_axes`:
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
if not arr.matches_axes(Float[NamedArray, "batch embed ..."]):
|
|
24
|
+
raise ValueError("unexpected axes")
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## DType-aware annotations
|
|
28
|
+
|
|
29
|
+
Sometimes it is useful to express both the axes **and** the dtype in the type
|
|
30
|
+
annotation. The :mod:`haliax.typing` module defines symbolic types for all of
|
|
31
|
+
JAX's common dtypes that can be indexed just like ``Named``. In documentation
|
|
32
|
+
examples we'll use ``import haliax.typing as ht``:
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
import haliax.haxtyping as ht
|
|
36
|
+
|
|
37
|
+
def foo(x: ht.f32[NamedArray, "batch"]):
|
|
38
|
+
...
|
|
39
|
+
|
|
40
|
+
def bar(x: ht.i32[NamedArray, "batch"]):
|
|
41
|
+
...
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
For convenience the module also provides aggregate categories ``Float``,
|
|
45
|
+
``Complex``, ``Int`` and ``UInt`` that match any floating point, complex,
|
|
46
|
+
signed integer or unsigned integer dtype respectively:
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
def baz(x: ht.Float[NamedArray, "batch"]):
|
|
50
|
+
...
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
At runtime ``matches_axes`` also checks the dtype when one is present:
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from haliax import Axis, zeros
|
|
57
|
+
import haliax.haxtyping as ht
|
|
58
|
+
|
|
59
|
+
arr = zeros({"batch": 4})
|
|
60
|
+
assert arr.matches_axes(ht.f32["batch"]) # dtype and axes both match
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## FAQ
|
|
64
|
+
|
|
65
|
+
### Why not use `NamedArray` directly in type annotations?
|
|
66
|
+
|
|
67
|
+
Using `NamedArray` directly in type annotations doesn't work well with
|
|
68
|
+
type checkers like `mypy` or `pyright`. These tools expect types to be
|
|
69
|
+
subscripted with other types or forward references (which are strings).
|
|
70
|
+
Using `NamedArray` directly would lead to type errors.
|
|
71
|
+
|
|
72
|
+
### Why not use `jaxtyping` directly?
|
|
73
|
+
|
|
74
|
+
While `jaxtyping` is a powerful library for type annotations in JAX, it does not
|
|
75
|
+
support `NamedArray` objects directly. The `haliax.haxtyping` module extends
|
|
76
|
+
`jaxtyping` to include `NamedArray` support, allowing you to annotate functions
|
|
77
|
+
and methods that take or return `NamedArray` objects with specific axes and dtypes.
|
|
78
|
+
|
|
79
|
+
### Why do I have to specify the `NamedArray` type in the annotation?
|
|
80
|
+
|
|
81
|
+
I hate this, but it's the only way to get type checkers like `mypy` and `pyright` to understand that the type is
|
|
82
|
+
a `NamedArray`. Underneath the hood, during type checking, `jaxtyping.Float` (and `haxtyping.Float`) are
|
|
83
|
+
essentially type aliases of [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated)
|
|
84
|
+
with the `NamedArray` type. There's no other way I could find to get type checkers to understand that the type is a
|
|
85
|
+
`NamedArray` or to accept strings like `"batch embed ..."` as valid type annotations.
|
|
86
|
+
|
|
87
|
+
### How do I use single axes in type annotations with flake or ruff.
|
|
88
|
+
|
|
89
|
+
Like `jaxtyping`, you need to prepend a space before the axis name to use single axes in type annotations with
|
|
90
|
+
flake or ruff. For example, to use a single axis named `batch`, you would write:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
def foo(x: ht.Float[NamedArray, " batch"]):
|
|
94
|
+
...
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Then suppress F722 in your linter to suppress that error.
|
|
98
|
+
|
|
99
|
+
See the [jaxtyping documentation](https://docs.kidger.site/jaxtyping/faq/#flake8-or-ruff-are-throwing-an-error) for more
|
|
100
|
+
details on the workaround.
|
|
@@ -38,7 +38,8 @@ dev=["pytest >= 7.4.0", "mypy >= 0.910", "mkdocs >= 1.4.3", "mkdocs-material >=
|
|
|
38
38
|
"pymdown-extensions",
|
|
39
39
|
"pygments",
|
|
40
40
|
"pymdown-extensions",
|
|
41
|
-
"chex>=0.1.86"
|
|
41
|
+
"chex>=0.1.86",
|
|
42
|
+
"pre-commit",
|
|
42
43
|
]
|
|
43
44
|
|
|
44
45
|
|
|
@@ -72,6 +73,11 @@ src_paths = ["src", "tests"]
|
|
|
72
73
|
"Bug Tracker" = "https://github.com/stanford-crfm/haliax/issues/"
|
|
73
74
|
"Documentation" = "https://haliax.readthedocs.io/en/latest/"
|
|
74
75
|
|
|
76
|
+
[tool.ruff.lint]
|
|
77
|
+
ignore = [ "E203", "E501", "W605", "F821", "E266", "F722", "E731", "E741" ]
|
|
78
|
+
|
|
79
|
+
[tool.setuptools.package-data]
|
|
80
|
+
"haliax" = ["*.pyi"]
|
|
75
81
|
|
|
76
82
|
[tool.coverage.report]
|
|
77
83
|
exclude_also = [
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.4.dev366"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import typing
|
|
1
|
+
import typing as t
|
|
2
2
|
from typing import Optional, Sequence
|
|
3
3
|
|
|
4
4
|
import jax
|
|
@@ -42,11 +42,8 @@ from .axis import (
|
|
|
42
42
|
to_jax_shape,
|
|
43
43
|
)
|
|
44
44
|
from .core import (
|
|
45
|
-
Named,
|
|
46
45
|
NamedArray,
|
|
47
|
-
NamedArrayAxes,
|
|
48
|
-
NamedArrayAxesSpec,
|
|
49
|
-
NamedOrNumeric,
|
|
46
|
+
NamedArrayAxes, NamedArrayAxesSpec, NamedOrNumeric,
|
|
50
47
|
are_shape_checks_enabled,
|
|
51
48
|
broadcast_arrays,
|
|
52
49
|
broadcast_axis,
|
|
@@ -66,6 +63,7 @@ from .core import (
|
|
|
66
63
|
unflatten_axis,
|
|
67
64
|
updated_slice,
|
|
68
65
|
)
|
|
66
|
+
from .haxtyping import Named
|
|
69
67
|
from .hof import fold, map, scan, vmap
|
|
70
68
|
from .jax_utils import tree_checkpoint_name
|
|
71
69
|
from .ops import clip, isclose, pad_left, trace, tril, triu, where
|
|
@@ -83,8 +81,8 @@ from .wrap import (
|
|
|
83
81
|
)
|
|
84
82
|
|
|
85
83
|
|
|
86
|
-
T =
|
|
87
|
-
A =
|
|
84
|
+
T = t.TypeVar("T")
|
|
85
|
+
A = t.TypeVar("A", Scalar, NamedArray, jnp.ndarray)
|
|
88
86
|
|
|
89
87
|
|
|
90
88
|
# creation routines
|
|
@@ -148,11 +146,6 @@ def arange(axis: AxisSpec, *, start=0, step=1, dtype: Optional[DTypeLike] = None
|
|
|
148
146
|
```
|
|
149
147
|
|
|
150
148
|
"""
|
|
151
|
-
from haliax.jax_utils import to_jax_shape
|
|
152
|
-
from haliax.util import ensure_tuple
|
|
153
|
-
|
|
154
|
-
# if start is a tracer, we need to be a bit cleverer since arange doesn't support tracers
|
|
155
|
-
# return NamedArray(jnp.arange(start, stop, step, dtype=dtype), (axis,))
|
|
156
149
|
size = axis_size(axis)
|
|
157
150
|
|
|
158
151
|
arr = jax.lax.iota(dtype=dtype or jnp.result_type(start), size=size) * step + start
|
|
@@ -274,7 +267,7 @@ def concatenate(axis: AxisSelector, arrays: Sequence[NamedArray]) -> NamedArray:
|
|
|
274
267
|
if axis_index is None:
|
|
275
268
|
raise ValueError(f"Axis {aname} not found in 0th array {arrays[0]}")
|
|
276
269
|
|
|
277
|
-
axes:
|
|
270
|
+
axes: tuple[AxisSelector, ...] = arrays[0].axes
|
|
278
271
|
# we want to use the axis name for `axis`, because it's not uncommon for those to be different lengths in the arrays
|
|
279
272
|
axes = axes[:axis_index] + (aname,) + axes[axis_index + 1 :]
|
|
280
273
|
arrays = [a.rearrange(axes) for a in arrays]
|
|
@@ -931,9 +924,6 @@ __all__ = [
|
|
|
931
924
|
"make_axes",
|
|
932
925
|
"axis_name",
|
|
933
926
|
"axis_size",
|
|
934
|
-
"NamedArrayAxesSpec",
|
|
935
|
-
"NamedArrayAxes",
|
|
936
|
-
"Named",
|
|
937
927
|
"NamedArray",
|
|
938
928
|
"broadcast_to",
|
|
939
929
|
"broadcast_axis",
|
|
@@ -1106,4 +1096,14 @@ __all__ = [
|
|
|
1106
1096
|
"is_named_array",
|
|
1107
1097
|
"tree_checkpoint_name",
|
|
1108
1098
|
"ScanCheckpointPolicy",
|
|
1099
|
+
"quantization",
|
|
1100
|
+
"util",
|
|
1101
|
+
"einsum",
|
|
1102
|
+
"broadcast_arrays",
|
|
1103
|
+
"unflatten_axis",
|
|
1104
|
+
"ReductionFunction",
|
|
1105
|
+
"SimpleReductionFunction",
|
|
1106
|
+
"NamedArrayAxes",
|
|
1107
|
+
"NamedArrayAxesSpec",
|
|
1108
|
+
"Named",
|
|
1109
1109
|
]
|
|
@@ -4,7 +4,6 @@ import warnings
|
|
|
4
4
|
from typing import Dict, Optional, Tuple
|
|
5
5
|
|
|
6
6
|
import jax
|
|
7
|
-
import jax.numpy as jnp
|
|
8
7
|
|
|
9
8
|
import haliax
|
|
10
9
|
from haliax.axis import (
|
|
@@ -20,7 +19,6 @@ from haliax.axis import (
|
|
|
20
19
|
from haliax.core import NamedArray
|
|
21
20
|
from haliax.jax_utils import _jittable_dg_einsum
|
|
22
21
|
from haliax.types import DTypeLike, PrecisionLike
|
|
23
|
-
from haliax.util import ensure_tuple
|
|
24
22
|
|
|
25
23
|
|
|
26
24
|
# deprecated overload
|
|
@@ -15,8 +15,7 @@ from jaxtyping import PyTree
|
|
|
15
15
|
|
|
16
16
|
import haliax.partitioning as partitioning
|
|
17
17
|
from haliax._src.util import index_where
|
|
18
|
-
from haliax.
|
|
19
|
-
from haliax.core import NamedArray, flatten_axes, named
|
|
18
|
+
from haliax.core import NamedArray, named
|
|
20
19
|
from haliax.jax_utils import is_jax_array_like, is_scalarish
|
|
21
20
|
from haliax.tree_util import scan_aware_tree_map
|
|
22
21
|
|
|
@@ -209,14 +208,14 @@ def from_state_dict(tree: T, state_dict: StateDict, prefix: Optional[str] = None
|
|
|
209
208
|
array = named(array, tree.axes)
|
|
210
209
|
array = partitioning.auto_sharded(array)
|
|
211
210
|
|
|
212
|
-
return array
|
|
211
|
+
return array # type: ignore
|
|
213
212
|
elif is_jax_array_like(tree):
|
|
214
213
|
if prefix is None:
|
|
215
214
|
raise ValueError("Cannot extract a leaf value from a state dict without a prefix")
|
|
216
215
|
# TODO: add "strict" flag so we can return None in cases where it's just missing
|
|
217
216
|
return jnp.array(state_dict[prefix])
|
|
218
217
|
elif tree is None:
|
|
219
|
-
return None
|
|
218
|
+
return None # type: ignore
|
|
220
219
|
else:
|
|
221
220
|
if prefix is None:
|
|
222
221
|
return tree
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import contextlib
|
|
2
4
|
import functools as ft
|
|
3
5
|
import typing
|
|
@@ -32,7 +34,6 @@ from .axis import (
|
|
|
32
34
|
)
|
|
33
35
|
from .types import GatherScatterModeStr, IntScalar, PrecisionLike, Scalar
|
|
34
36
|
|
|
35
|
-
|
|
36
37
|
NamedOrNumeric = Union[Scalar, "NamedArray"]
|
|
37
38
|
NamedIndex = Union[int, slice_t, "NamedArray", dslice, list[int], jnp.ndarray]
|
|
38
39
|
|
|
@@ -181,19 +182,6 @@ def _parse_namedarray_axes(
|
|
|
181
182
|
raise TypeError(f"Invalid NamedArray typing spec: {item}")
|
|
182
183
|
|
|
183
184
|
|
|
184
|
-
class Named:
|
|
185
|
-
"""Type annotation helper for :class:`NamedArray`.
|
|
186
|
-
|
|
187
|
-
``Named["batch embed"]`` expands to ``Annotated[NamedArray, axes]`` so that
|
|
188
|
-
type checkers treat it as a ``NamedArray`` at static time while the axis
|
|
189
|
-
metadata is available at runtime via :func:`typing.get_args`.
|
|
190
|
-
"""
|
|
191
|
-
|
|
192
|
-
def __class_getitem__(cls, item: NamedArrayAxesSpec) -> typing.Any:
|
|
193
|
-
axes = _parse_namedarray_axes(item)
|
|
194
|
-
return typing.Annotated[NamedArray, axes]
|
|
195
|
-
|
|
196
|
-
|
|
197
185
|
class NamedArrayMeta(type):
|
|
198
186
|
def __getitem__(cls, item: NamedArrayAxesSpec) -> typing.Any:
|
|
199
187
|
axes = _parse_namedarray_axes(item)
|
|
@@ -2112,7 +2100,6 @@ def _convert_index_expr_to_dict(idx) -> dict[AxisSelector, NamedIndex]:
|
|
|
2112
2100
|
__all__ = [
|
|
2113
2101
|
"NamedArrayAxesSpec",
|
|
2114
2102
|
"NamedArrayAxes",
|
|
2115
|
-
"Named",
|
|
2116
2103
|
"NamedArray",
|
|
2117
2104
|
"named",
|
|
2118
2105
|
"slice",
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@dataclass(frozen=True)
|
|
7
|
+
class DTypeCategory:
|
|
8
|
+
"""Represents a dtype category such as ``float`` or ``int``."""
|
|
9
|
+
|
|
10
|
+
name: str
|
|
11
|
+
category: Any
|
|
12
|
+
|
|
13
|
+
def __repr__(self) -> str: # pragma: no cover - trivial
|
|
14
|
+
return self.name
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
# ── STATIC ONLY: re‑export jaxtyping’s aliases so mypy/Pyright/PyCharm see them
|
|
18
|
+
from jaxtyping import (
|
|
19
|
+
Float32 as f32, Float64 as f64, Float16 as f16, BFloat16 as bf16,
|
|
20
|
+
Int8 as i8, Int16 as i16, Int32 as i32, Int64 as i64,
|
|
21
|
+
UInt8 as u8, UInt16 as u16, UInt32 as u32, UInt64 as u64,
|
|
22
|
+
Bool as bool_, Complex64 as complex64, Complex128 as complex128,
|
|
23
|
+
Float as Float, Int as Int, UInt as UInt,
|
|
24
|
+
)
|
|
25
|
+
# axes‑only helper
|
|
26
|
+
from typing import Annotated as Named
|
|
27
|
+
|
|
28
|
+
else:
|
|
29
|
+
# ── RUNTIME: custom wrappers for NamedArray, plus delegation to jaxtyping ──
|
|
30
|
+
import jaxtyping as jt
|
|
31
|
+
import jax.numpy as jnp
|
|
32
|
+
from typing import Annotated
|
|
33
|
+
from dataclasses import dataclass, replace
|
|
34
|
+
|
|
35
|
+
from .core import (
|
|
36
|
+
NamedArray,
|
|
37
|
+
NamedArrayAxes,
|
|
38
|
+
NamedArrayAxesSpec,
|
|
39
|
+
_parse_namedarray_axes,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
def _with_dtype(axes: NamedArrayAxes, dtype):
|
|
43
|
+
"""Attach dtype to axes metadata if not already set."""
|
|
44
|
+
return axes if axes.dtype is not None else replace(axes, dtype=dtype)
|
|
45
|
+
|
|
46
|
+
def _make_dtype_wrapper(dtype):
|
|
47
|
+
"""Factory for f32, i32, etc."""
|
|
48
|
+
class _Wrapper:
|
|
49
|
+
def __class_getitem__(cls, item):
|
|
50
|
+
# two‑arg form: (BaseType, axes_spec)
|
|
51
|
+
if isinstance(item, tuple) and len(item) == 2:
|
|
52
|
+
base, axes_spec = item
|
|
53
|
+
else:
|
|
54
|
+
base, axes_spec = NamedArray, item
|
|
55
|
+
|
|
56
|
+
# Delegate non‑NamedArray to jaxtyping
|
|
57
|
+
if base is not NamedArray:
|
|
58
|
+
# e.g. use jt.Float32 for jnp.float32
|
|
59
|
+
jaxt = getattr(jt, f"Float{dtype.itemsize*8}") \
|
|
60
|
+
if hasattr(dtype, "itemsize") else jt.Float
|
|
61
|
+
return jaxt[base, axes_spec]
|
|
62
|
+
|
|
63
|
+
# Handle NamedArray path
|
|
64
|
+
axes = _parse_namedarray_axes(axes_spec)
|
|
65
|
+
return Annotated[NamedArray, _with_dtype(axes, dtype)]
|
|
66
|
+
|
|
67
|
+
return _Wrapper
|
|
68
|
+
|
|
69
|
+
# ── Build all dtype wrappers ─────────────────────────────────────────────
|
|
70
|
+
f32 = _make_dtype_wrapper(jnp.float32)
|
|
71
|
+
f64 = _make_dtype_wrapper(jnp.float64)
|
|
72
|
+
f16 = _make_dtype_wrapper(jnp.float16)
|
|
73
|
+
bf16 = _make_dtype_wrapper(jnp.bfloat16)
|
|
74
|
+
|
|
75
|
+
i8 = _make_dtype_wrapper(jnp.int8)
|
|
76
|
+
i16 = _make_dtype_wrapper(jnp.int16)
|
|
77
|
+
i32 = _make_dtype_wrapper(jnp.int32)
|
|
78
|
+
i64 = _make_dtype_wrapper(jnp.int64)
|
|
79
|
+
|
|
80
|
+
u8 = _make_dtype_wrapper(jnp.uint8)
|
|
81
|
+
u16 = _make_dtype_wrapper(jnp.uint16)
|
|
82
|
+
u32 = _make_dtype_wrapper(jnp.uint32)
|
|
83
|
+
u64 = _make_dtype_wrapper(jnp.uint64)
|
|
84
|
+
|
|
85
|
+
bool_ = _make_dtype_wrapper(jnp.bool_)
|
|
86
|
+
complex64 = _make_dtype_wrapper(jnp.complex64)
|
|
87
|
+
complex128 = _make_dtype_wrapper(jnp.complex128)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _make_category_wrapper(name: str, category):
|
|
93
|
+
"""Like _make_dtype_wrapper but matches any dtype in the JAX category."""
|
|
94
|
+
|
|
95
|
+
class _Wrapper:
|
|
96
|
+
def __class_getitem__(cls, item):
|
|
97
|
+
# same base/axes unpack logic
|
|
98
|
+
if isinstance(item, tuple) and len(item) == 2:
|
|
99
|
+
base, axes_spec = item
|
|
100
|
+
else:
|
|
101
|
+
base, axes_spec = NamedArray, item
|
|
102
|
+
|
|
103
|
+
# non‑NamedArray → delegate to jaxtyping’s category wrapper
|
|
104
|
+
if base is not NamedArray:
|
|
105
|
+
return getattr(jt, name)[base, axes_spec]
|
|
106
|
+
|
|
107
|
+
# NamedArray path
|
|
108
|
+
axes = _parse_namedarray_axes(axes_spec)
|
|
109
|
+
cat = DTypeCategory(name, category)
|
|
110
|
+
return Annotated[NamedArray, _with_dtype(axes, cat)]
|
|
111
|
+
|
|
112
|
+
return _Wrapper
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
# Build the category wrappers
|
|
116
|
+
Float = _make_category_wrapper("float", jnp.floating)
|
|
117
|
+
Complex = _make_category_wrapper("complex", jnp.complexfloating)
|
|
118
|
+
Int = _make_category_wrapper("int", jnp.signedinteger)
|
|
119
|
+
UInt = _make_category_wrapper("uInt", jnp.unsignedinteger)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
# ── Named: axes‑only helper ───────────────────────────────────────────────
|
|
123
|
+
class _NamedHelper:
|
|
124
|
+
@classmethod
|
|
125
|
+
def __class_getitem__(self, axes_spec_: tuple[type[NamedArray], NamedArrayAxesSpec]):
|
|
126
|
+
_, axes_spec = axes_spec_
|
|
127
|
+
axes = _parse_namedarray_axes(axes_spec)
|
|
128
|
+
return Annotated[NamedArray, axes]
|
|
129
|
+
|
|
130
|
+
Named = _NamedHelper
|
|
131
|
+
|
|
132
|
+
__all__ = [
|
|
133
|
+
"Named",
|
|
134
|
+
"f32", "f64", "f16", "bf16",
|
|
135
|
+
"i8", "i16", "i32", "i64",
|
|
136
|
+
"u8", "u16", "u32", "u64",
|
|
137
|
+
"bool_", "complex64", "complex128",
|
|
138
|
+
]
|
|
@@ -23,7 +23,7 @@ from .axis import Axis, AxisSelection, AxisSelector, axis_spec_to_shape_dict, ax
|
|
|
23
23
|
from .core import NamedArray
|
|
24
24
|
from .jax_utils import Static, broadcast_prefix, is_jax_array_like
|
|
25
25
|
from .partitioning import physical_axis_name
|
|
26
|
-
from .util import
|
|
26
|
+
from .util import is_named_array
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
def vmap(
|
|
@@ -11,7 +11,6 @@ import haliax.random as hrandom
|
|
|
11
11
|
from haliax.axis import Axis, AxisSelection, AxisSelector, AxisSpec, axis_name, axis_spec_to_shape_dict
|
|
12
12
|
from haliax.core import NamedArray
|
|
13
13
|
from haliax.types import PrecisionLike
|
|
14
|
-
from haliax.util import ensure_tuple
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
# With attention, we usually distinguish between the mask and the bias, though the former is just a special case of the
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import dataclasses
|
|
2
|
-
import math
|
|
3
2
|
import warnings
|
|
4
3
|
from typing import Optional
|
|
5
4
|
|
|
@@ -12,7 +11,6 @@ from ..axis import Axis, AxisSpec, concat_axes
|
|
|
12
11
|
from ..core import NamedArray
|
|
13
12
|
from ..jax_utils import named_call
|
|
14
13
|
from ..tree_util import resize_axis
|
|
15
|
-
from ..util import ensure_tuple
|
|
16
14
|
|
|
17
15
|
|
|
18
16
|
class Embedding(eqx.Module):
|
|
@@ -2,7 +2,7 @@ import dataclasses
|
|
|
2
2
|
import functools
|
|
3
3
|
import re
|
|
4
4
|
import warnings
|
|
5
|
-
from typing import Any, Dict, Generic,
|
|
5
|
+
from typing import Any, Dict, Generic, Optional, Protocol, Sequence, Type, TypeVar, cast
|
|
6
6
|
|
|
7
7
|
import equinox as eqx
|
|
8
8
|
import jax
|
|
@@ -169,7 +169,7 @@ class BlockSeq(ModuleWithStateDictSerialization, Generic[M]):
|
|
|
169
169
|
|
|
170
170
|
@staticmethod
|
|
171
171
|
def _slice_out(Block, i, x):
|
|
172
|
-
if haliax.
|
|
172
|
+
if isinstance(x, haliax.core.NamedArray):
|
|
173
173
|
if haliax.selects_axis(x.axes, Block):
|
|
174
174
|
return x[Block, i]
|
|
175
175
|
else:
|
|
@@ -411,7 +411,7 @@ class Stacked(ModuleWithStateDictSerialization, Generic[M]):
|
|
|
411
411
|
else:
|
|
412
412
|
return tuple(x for _ in range(self.Block.size))
|
|
413
413
|
|
|
414
|
-
leaves, structure = jax.tree_util.tree_flatten(self.stacked, is_leaf=haliax.is_named_array)
|
|
414
|
+
leaves, structure = jax.tree_util.tree_flatten(self.stacked, is_leaf=haliax.util.is_named_array)
|
|
415
415
|
unstacked_leaves = tuple(map(unbatch_leaf, leaves))
|
|
416
416
|
# now we need to transpose the leaves
|
|
417
417
|
unstacked_leaves = tuple(zip(*unstacked_leaves))
|
|
@@ -20,7 +20,7 @@ from .axis import Axis, AxisSelection, AxisSelector, axis_spec_to_shape_dict
|
|
|
20
20
|
from .core import NamedArray
|
|
21
21
|
from .jax_utils import Static, is_in_jit, is_jax_array_like, is_on_mac_metal
|
|
22
22
|
from .tree_util import hashable_combine, hashable_partition
|
|
23
|
-
from .util import StringHolderEnum
|
|
23
|
+
from .util import StringHolderEnum
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
PhysicalAxisSpec = Union[(str), Sequence[str]]
|