hndl 0.1.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.
- hndl-0.1.0/CONTRIBUTING.md +70 -0
- hndl-0.1.0/IMPLEMENTATION.md +204 -0
- hndl-0.1.0/LICENSE +21 -0
- hndl-0.1.0/MANIFEST.in +4 -0
- hndl-0.1.0/PKG-INFO +461 -0
- hndl-0.1.0/README.md +422 -0
- hndl-0.1.0/SPEC.md +793 -0
- hndl-0.1.0/docs/ADDING_OPERATORS.md +135 -0
- hndl-0.1.0/docs/networks.md +601 -0
- hndl-0.1.0/docs/operators/adaptive_avg_pool.md +136 -0
- hndl-0.1.0/docs/operators/adaptive_norm.md +91 -0
- hndl-0.1.0/docs/operators/add.md +53 -0
- hndl-0.1.0/docs/operators/attention.md +136 -0
- hndl-0.1.0/docs/operators/avg_pool.md +111 -0
- hndl-0.1.0/docs/operators/batch_norm.md +148 -0
- hndl-0.1.0/docs/operators/clamp.md +106 -0
- hndl-0.1.0/docs/operators/cls_token.md +112 -0
- hndl-0.1.0/docs/operators/concat.md +74 -0
- hndl-0.1.0/docs/operators/conv.md +127 -0
- hndl-0.1.0/docs/operators/conv1d.md +128 -0
- hndl-0.1.0/docs/operators/cross_attention.md +121 -0
- hndl-0.1.0/docs/operators/deconv.md +86 -0
- hndl-0.1.0/docs/operators/dropout.md +133 -0
- hndl-0.1.0/docs/operators/elu.md +105 -0
- hndl-0.1.0/docs/operators/embedding.md +117 -0
- hndl-0.1.0/docs/operators/feed_forward.md +138 -0
- hndl-0.1.0/docs/operators/flatten.md +47 -0
- hndl-0.1.0/docs/operators/gather_token.md +121 -0
- hndl-0.1.0/docs/operators/gelu.md +115 -0
- hndl-0.1.0/docs/operators/global_avg_pool.md +110 -0
- hndl-0.1.0/docs/operators/group_norm.md +54 -0
- hndl-0.1.0/docs/operators/hardswish.md +105 -0
- hndl-0.1.0/docs/operators/hopfield.md +169 -0
- hndl-0.1.0/docs/operators/identity.md +108 -0
- hndl-0.1.0/docs/operators/index.md +123 -0
- hndl-0.1.0/docs/operators/instance_norm.md +120 -0
- hndl-0.1.0/docs/operators/layer_norm.md +114 -0
- hndl-0.1.0/docs/operators/leaky_relu.md +46 -0
- hndl-0.1.0/docs/operators/linear.md +93 -0
- hndl-0.1.0/docs/operators/max_pool.md +107 -0
- hndl-0.1.0/docs/operators/mean.md +134 -0
- hndl-0.1.0/docs/operators/mish.md +105 -0
- hndl-0.1.0/docs/operators/moe.md +122 -0
- hndl-0.1.0/docs/operators/mul.md +97 -0
- hndl-0.1.0/docs/operators/pad.md +140 -0
- hndl-0.1.0/docs/operators/patch_embed.md +120 -0
- hndl-0.1.0/docs/operators/permute.md +126 -0
- hndl-0.1.0/docs/operators/pixel_shuffle.md +107 -0
- hndl-0.1.0/docs/operators/pool_tokens.md +139 -0
- hndl-0.1.0/docs/operators/pos_embed.md +90 -0
- hndl-0.1.0/docs/operators/pretrained.md +90 -0
- hndl-0.1.0/docs/operators/quick_gelu.md +103 -0
- hndl-0.1.0/docs/operators/relu.md +46 -0
- hndl-0.1.0/docs/operators/resblock.md +127 -0
- hndl-0.1.0/docs/operators/reshape.md +117 -0
- hndl-0.1.0/docs/operators/rms_norm.md +118 -0
- hndl-0.1.0/docs/operators/scale.md +104 -0
- hndl-0.1.0/docs/operators/sigmoid.md +100 -0
- hndl-0.1.0/docs/operators/silu.md +102 -0
- hndl-0.1.0/docs/operators/softmax.md +111 -0
- hndl-0.1.0/docs/operators/softplus.md +108 -0
- hndl-0.1.0/docs/operators/split.md +80 -0
- hndl-0.1.0/docs/operators/sub.md +98 -0
- hndl-0.1.0/docs/operators/sum.md +134 -0
- hndl-0.1.0/docs/operators/swiglu.md +111 -0
- hndl-0.1.0/docs/operators/tanh.md +46 -0
- hndl-0.1.0/docs/operators/transformer_block.md +167 -0
- hndl-0.1.0/docs/operators/transpose.md +107 -0
- hndl-0.1.0/docs/operators/upsample.md +135 -0
- hndl-0.1.0/docs/pretrained.md +97 -0
- hndl-0.1.0/examples/adaptive_normalization.py +58 -0
- hndl-0.1.0/examples/networks/README.md +8 -0
- hndl-0.1.0/examples/networks/autoencoder.hndl +18 -0
- hndl-0.1.0/examples/networks/autoencoder.json +8 -0
- hndl-0.1.0/examples/networks/dcgan_discriminator.hndl +25 -0
- hndl-0.1.0/examples/networks/dcgan_discriminator.json +8 -0
- hndl-0.1.0/examples/networks/dcgan_generator.hndl +26 -0
- hndl-0.1.0/examples/networks/dcgan_generator.json +8 -0
- hndl-0.1.0/examples/networks/gpt_tiny.hndl +17 -0
- hndl-0.1.0/examples/networks/gpt_tiny.json +9 -0
- hndl-0.1.0/examples/networks/hopfield_classifier.hndl +16 -0
- hndl-0.1.0/examples/networks/hopfield_classifier.json +8 -0
- hndl-0.1.0/examples/networks/lenet5.hndl +22 -0
- hndl-0.1.0/examples/networks/lenet5.json +8 -0
- hndl-0.1.0/examples/networks/mlp.hndl +8 -0
- hndl-0.1.0/examples/networks/mlp.json +8 -0
- hndl-0.1.0/examples/networks/moe_transformer.hndl +29 -0
- hndl-0.1.0/examples/networks/moe_transformer.json +9 -0
- hndl-0.1.0/examples/networks/resnet18.hndl +31 -0
- hndl-0.1.0/examples/networks/resnet18.json +8 -0
- hndl-0.1.0/examples/networks/unet_small.hndl +46 -0
- hndl-0.1.0/examples/networks/unet_small.json +8 -0
- hndl-0.1.0/examples/networks/vit_tiny.hndl +20 -0
- hndl-0.1.0/examples/networks/vit_tiny.json +8 -0
- hndl-0.1.0/pyproject.toml +55 -0
- hndl-0.1.0/setup.cfg +4 -0
- hndl-0.1.0/src/hndl/__init__.py +12 -0
- hndl-0.1.0/src/hndl/_parser_worker.py +213 -0
- hndl-0.1.0/src/hndl/_version.py +3 -0
- hndl-0.1.0/src/hndl/capture.py +238 -0
- hndl-0.1.0/src/hndl/config.py +248 -0
- hndl-0.1.0/src/hndl/docs.py +198 -0
- hndl-0.1.0/src/hndl/errors.py +18 -0
- hndl-0.1.0/src/hndl/operator.py +619 -0
- hndl-0.1.0/src/hndl/operators/__init__.py +31 -0
- hndl-0.1.0/src/hndl/operators/_pooling.py +57 -0
- hndl-0.1.0/src/hndl/operators/_relations.py +65 -0
- hndl-0.1.0/src/hndl/operators/adaptive_avg_pool.py +91 -0
- hndl-0.1.0/src/hndl/operators/adaptive_norm.py +49 -0
- hndl-0.1.0/src/hndl/operators/add.py +19 -0
- hndl-0.1.0/src/hndl/operators/attention.py +184 -0
- hndl-0.1.0/src/hndl/operators/avg_pool.py +65 -0
- hndl-0.1.0/src/hndl/operators/batch_norm.py +85 -0
- hndl-0.1.0/src/hndl/operators/clamp.py +65 -0
- hndl-0.1.0/src/hndl/operators/cls_token.py +67 -0
- hndl-0.1.0/src/hndl/operators/concat.py +62 -0
- hndl-0.1.0/src/hndl/operators/conv.py +96 -0
- hndl-0.1.0/src/hndl/operators/conv1d.py +104 -0
- hndl-0.1.0/src/hndl/operators/cross_attention.py +109 -0
- hndl-0.1.0/src/hndl/operators/deconv.py +52 -0
- hndl-0.1.0/src/hndl/operators/dropout.py +73 -0
- hndl-0.1.0/src/hndl/operators/elu.py +54 -0
- hndl-0.1.0/src/hndl/operators/embedding.py +69 -0
- hndl-0.1.0/src/hndl/operators/feed_forward.py +108 -0
- hndl-0.1.0/src/hndl/operators/flatten.py +24 -0
- hndl-0.1.0/src/hndl/operators/gather_token.py +98 -0
- hndl-0.1.0/src/hndl/operators/gelu.py +63 -0
- hndl-0.1.0/src/hndl/operators/global_avg_pool.py +49 -0
- hndl-0.1.0/src/hndl/operators/group_norm.py +36 -0
- hndl-0.1.0/src/hndl/operators/hardswish.py +51 -0
- hndl-0.1.0/src/hndl/operators/hopfield.py +135 -0
- hndl-0.1.0/src/hndl/operators/identity.py +45 -0
- hndl-0.1.0/src/hndl/operators/instance_norm.py +86 -0
- hndl-0.1.0/src/hndl/operators/layer_norm.py +63 -0
- hndl-0.1.0/src/hndl/operators/leaky_relu.py +18 -0
- hndl-0.1.0/src/hndl/operators/linear.py +41 -0
- hndl-0.1.0/src/hndl/operators/max_pool.py +58 -0
- hndl-0.1.0/src/hndl/operators/mean.py +105 -0
- hndl-0.1.0/src/hndl/operators/mish.py +51 -0
- hndl-0.1.0/src/hndl/operators/moe.py +137 -0
- hndl-0.1.0/src/hndl/operators/mul.py +30 -0
- hndl-0.1.0/src/hndl/operators/pad.py +148 -0
- hndl-0.1.0/src/hndl/operators/patch_embed.py +105 -0
- hndl-0.1.0/src/hndl/operators/permute.py +95 -0
- hndl-0.1.0/src/hndl/operators/pixel_shuffle.py +86 -0
- hndl-0.1.0/src/hndl/operators/pool_tokens.py +85 -0
- hndl-0.1.0/src/hndl/operators/pos_embed.py +70 -0
- hndl-0.1.0/src/hndl/operators/pretrained.py +117 -0
- hndl-0.1.0/src/hndl/operators/quick_gelu.py +49 -0
- hndl-0.1.0/src/hndl/operators/relu.py +17 -0
- hndl-0.1.0/src/hndl/operators/resblock.py +157 -0
- hndl-0.1.0/src/hndl/operators/reshape.py +69 -0
- hndl-0.1.0/src/hndl/operators/rms_norm.py +83 -0
- hndl-0.1.0/src/hndl/operators/scale.py +39 -0
- hndl-0.1.0/src/hndl/operators/sigmoid.py +40 -0
- hndl-0.1.0/src/hndl/operators/silu.py +41 -0
- hndl-0.1.0/src/hndl/operators/softmax.py +84 -0
- hndl-0.1.0/src/hndl/operators/softplus.py +59 -0
- hndl-0.1.0/src/hndl/operators/split.py +67 -0
- hndl-0.1.0/src/hndl/operators/sub.py +30 -0
- hndl-0.1.0/src/hndl/operators/sum.py +107 -0
- hndl-0.1.0/src/hndl/operators/swiglu.py +80 -0
- hndl-0.1.0/src/hndl/operators/tanh.py +15 -0
- hndl-0.1.0/src/hndl/operators/transformer_block.py +204 -0
- hndl-0.1.0/src/hndl/operators/transpose.py +91 -0
- hndl-0.1.0/src/hndl/operators/upsample.py +93 -0
- hndl-0.1.0/src/hndl/pretrained.py +290 -0
- hndl-0.1.0/src/hndl/py.typed +0 -0
- hndl-0.1.0/src/hndl/registry.py +126 -0
- hndl-0.1.0/src/hndl/resolver.py +410 -0
- hndl-0.1.0/src/hndl/settings.py +104 -0
- hndl-0.1.0/src/hndl/torch.py +488 -0
- hndl-0.1.0/src/hndl/types.py +222 -0
- hndl-0.1.0/src/hndl.egg-info/PKG-INFO +461 -0
- hndl-0.1.0/src/hndl.egg-info/SOURCES.txt +242 -0
- hndl-0.1.0/src/hndl.egg-info/dependency_links.txt +1 -0
- hndl-0.1.0/src/hndl.egg-info/requires.txt +16 -0
- hndl-0.1.0/src/hndl.egg-info/top_level.txt +1 -0
- hndl-0.1.0/tests/operators/__init__.py +0 -0
- hndl-0.1.0/tests/operators/conftest.py +45 -0
- hndl-0.1.0/tests/operators/test_adaptive_avg_pool.py +115 -0
- hndl-0.1.0/tests/operators/test_all_operators.py +150 -0
- hndl-0.1.0/tests/operators/test_attention.py +199 -0
- hndl-0.1.0/tests/operators/test_avg_pool.py +127 -0
- hndl-0.1.0/tests/operators/test_batch_norm.py +137 -0
- hndl-0.1.0/tests/operators/test_clamp.py +99 -0
- hndl-0.1.0/tests/operators/test_cls_token.py +84 -0
- hndl-0.1.0/tests/operators/test_conv1d.py +161 -0
- hndl-0.1.0/tests/operators/test_conv_down2.py +101 -0
- hndl-0.1.0/tests/operators/test_cross_attention.py +168 -0
- hndl-0.1.0/tests/operators/test_dropout.py +158 -0
- hndl-0.1.0/tests/operators/test_elu.py +57 -0
- hndl-0.1.0/tests/operators/test_embedding.py +102 -0
- hndl-0.1.0/tests/operators/test_feed_forward.py +123 -0
- hndl-0.1.0/tests/operators/test_gather_token.py +141 -0
- hndl-0.1.0/tests/operators/test_gelu.py +79 -0
- hndl-0.1.0/tests/operators/test_global_avg_pool.py +92 -0
- hndl-0.1.0/tests/operators/test_hardswish.py +57 -0
- hndl-0.1.0/tests/operators/test_hopfield.py +207 -0
- hndl-0.1.0/tests/operators/test_identity.py +58 -0
- hndl-0.1.0/tests/operators/test_instance_norm.py +114 -0
- hndl-0.1.0/tests/operators/test_layer_norm.py +94 -0
- hndl-0.1.0/tests/operators/test_max_pool.py +110 -0
- hndl-0.1.0/tests/operators/test_mean.py +104 -0
- hndl-0.1.0/tests/operators/test_mish.py +58 -0
- hndl-0.1.0/tests/operators/test_moe.py +165 -0
- hndl-0.1.0/tests/operators/test_mul.py +78 -0
- hndl-0.1.0/tests/operators/test_pad.py +150 -0
- hndl-0.1.0/tests/operators/test_patch_embed.py +113 -0
- hndl-0.1.0/tests/operators/test_permute.py +91 -0
- hndl-0.1.0/tests/operators/test_pixel_shuffle.py +108 -0
- hndl-0.1.0/tests/operators/test_pool_tokens.py +91 -0
- hndl-0.1.0/tests/operators/test_pos_embed.py +86 -0
- hndl-0.1.0/tests/operators/test_quick_gelu.py +67 -0
- hndl-0.1.0/tests/operators/test_resblock.py +190 -0
- hndl-0.1.0/tests/operators/test_rms_norm.py +120 -0
- hndl-0.1.0/tests/operators/test_scale.py +73 -0
- hndl-0.1.0/tests/operators/test_sigmoid.py +57 -0
- hndl-0.1.0/tests/operators/test_silu.py +58 -0
- hndl-0.1.0/tests/operators/test_softmax.py +104 -0
- hndl-0.1.0/tests/operators/test_softplus.py +65 -0
- hndl-0.1.0/tests/operators/test_sub.py +70 -0
- hndl-0.1.0/tests/operators/test_sum.py +104 -0
- hndl-0.1.0/tests/operators/test_swiglu.py +115 -0
- hndl-0.1.0/tests/operators/test_transformer_block.py +218 -0
- hndl-0.1.0/tests/operators/test_transpose.py +87 -0
- hndl-0.1.0/tests/operators/test_upsample.py +117 -0
- hndl-0.1.0/tests/test_adaptive_normalization.py +161 -0
- hndl-0.1.0/tests/test_capture.py +195 -0
- hndl-0.1.0/tests/test_config.py +219 -0
- hndl-0.1.0/tests/test_construction_settings.py +175 -0
- hndl-0.1.0/tests/test_custom_operator.py +656 -0
- hndl-0.1.0/tests/test_examples.py +86 -0
- hndl-0.1.0/tests/test_golden_plans.py +94 -0
- hndl-0.1.0/tests/test_network_examples.py +67 -0
- hndl-0.1.0/tests/test_package.py +16 -0
- hndl-0.1.0/tests/test_parameter_settings.py +282 -0
- hndl-0.1.0/tests/test_plans.py +168 -0
- hndl-0.1.0/tests/test_pretrained.py +224 -0
- hndl-0.1.0/tests/test_rank_dtype.py +135 -0
- hndl-0.1.0/tests/test_registry.py +108 -0
- hndl-0.1.0/tests/test_resolver.py +138 -0
- hndl-0.1.0/tests/test_settings_frontends.py +247 -0
- hndl-0.1.0/tests/test_torch.py +310 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Developing HNDL
|
|
2
|
+
|
|
3
|
+
Use Python 3.11–3.14 on Linux. Create an environment and install the editable
|
|
4
|
+
package with its development tools:
|
|
5
|
+
|
|
6
|
+
```sh
|
|
7
|
+
python -m venv .venv
|
|
8
|
+
. .venv/bin/activate
|
|
9
|
+
python -m pip install -e '.[dev]'
|
|
10
|
+
python -m pytest
|
|
11
|
+
ruff check src tests examples
|
|
12
|
+
python -m hndl.docs --check
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
PyTorch is a dependency. CUDA tests run when a CUDA device is available; CPU
|
|
16
|
+
CI does not establish GPU correctness. Operator documentation under
|
|
17
|
+
`docs/operators` is generated from the `@operator` declarations; regenerate it
|
|
18
|
+
with `python -m hndl.docs` after changing one. See
|
|
19
|
+
[docs/ADDING_OPERATORS.md](docs/ADDING_OPERATORS.md) to add an operator.
|
|
20
|
+
|
|
21
|
+
Changes go through pull requests. CI tests the CPU backend on Python 3.11 and
|
|
22
|
+
3.14, testing PyTorch 2.6 on Python 3.11 and the latest supported 2.x version
|
|
23
|
+
on Python 3.14. Keep the explicit activation and implicit
|
|
24
|
+
current-tensor behavior consistent between declarative configurations and
|
|
25
|
+
trusted Python callables. Configuration input must never be executed as Python.
|
|
26
|
+
|
|
27
|
+
Build release candidates with:
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
python -m build
|
|
31
|
+
python -m twine check --strict dist/*
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The distribution version lives in `pyproject.toml` and
|
|
35
|
+
`src/hndl/_version.py`; update both together, and record the release in
|
|
36
|
+
`CHANGELOG.md`. Building a distribution does not publish it to PyPI.
|
|
37
|
+
|
|
38
|
+
## Publishing
|
|
39
|
+
|
|
40
|
+
Releases are published by `.github/workflows/publish.yml` when a GitHub
|
|
41
|
+
release is published. The release tag must be `v<version>`, matching
|
|
42
|
+
`pyproject.toml`. The workflow checks the tag, builds the distributions, installs
|
|
43
|
+
the wheel in a clean environment with the CPU backend, runs the test suite and
|
|
44
|
+
the documentation check against it, and only then uploads. A failure at any
|
|
45
|
+
step prevents publishing. The wheel and source archive are retained as workflow
|
|
46
|
+
artifacts either way.
|
|
47
|
+
|
|
48
|
+
The upload authenticates in one of two ways; the first one that applies wins.
|
|
49
|
+
|
|
50
|
+
1. **API token secret.** Create a PyPI API token and store it as the
|
|
51
|
+
repository secret `PYPI_API_TOKEN` (or as a secret on the GitHub `pypi`
|
|
52
|
+
environment). Until the project exists on PyPI the token must be
|
|
53
|
+
account-scoped; after the first upload it can be replaced with a token
|
|
54
|
+
scoped to `hndl`.
|
|
55
|
+
2. **Trusted Publishing.** With no secret set, the workflow uses PyPI's
|
|
56
|
+
short-lived OIDC credentials. Register a [pending trusted publisher](https://docs.pypi.org/trusted-publishers/creating-a-project-through-oidc/)
|
|
57
|
+
for project `hndl`, owner `HyperGAN`, repository `HNDL`, workflow
|
|
58
|
+
`publish.yml`, environment `pypi`. This is PyPI account configuration, not
|
|
59
|
+
a repository secret.
|
|
60
|
+
|
|
61
|
+
The `pypi` GitHub environment is created on first use; add release reviewers
|
|
62
|
+
to it if publishing should require approval.
|
|
63
|
+
|
|
64
|
+
To rehearse without publishing, run the workflow manually from the Actions tab
|
|
65
|
+
(`workflow_dispatch`). The manual run builds and tests the distributions and
|
|
66
|
+
uploads them as artifacts; the publish job is skipped.
|
|
67
|
+
|
|
68
|
+
To release: update the version in `pyproject.toml` and `src/hndl/_version.py`,
|
|
69
|
+
record the release in `CHANGELOG.md`, merge, then create a GitHub release with
|
|
70
|
+
tag `v<version>` on `master`. Publishing the release triggers the workflow.
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# Implementation notes: 0.1.0
|
|
2
|
+
|
|
3
|
+
This release implements the contract in [SPEC.md](SPEC.md). [README.md](README.md)
|
|
4
|
+
introduces the APIs with examples; the [operator catalog](docs/operators/index.md)
|
|
5
|
+
and the [authored networks](docs/networks.md) are generated from the code.
|
|
6
|
+
|
|
7
|
+
## Available
|
|
8
|
+
|
|
9
|
+
- Declarative source and bounded UTF-8 file loading: `resolve`, `resolve_file`,
|
|
10
|
+
`network`, and `network_file`.
|
|
11
|
+
- Trusted Python authoring: `ops`, `resolve_callable`, and
|
|
12
|
+
`network_from_callable`, with one capture per construction.
|
|
13
|
+
- Implicit current tensor, explicit tensor arguments, assignments, comments,
|
|
14
|
+
names, split/remainder, branches, and explicit joins.
|
|
15
|
+
- Bidirectional inference for widths, reshape products, convolution and pooling
|
|
16
|
+
arithmetic, split/concat extents, sequence lengths, and the exact `up2` and
|
|
17
|
+
`down2` policies. Contradictions fail; the resolver does not choose arbitrary
|
|
18
|
+
missing sizes.
|
|
19
|
+
- One `@operator` declaration per operation, on the `nn.Module` that
|
|
20
|
+
implements it: alias and version, a shape relation written as
|
|
21
|
+
`x[B, C, H, W], params[B, 2*C] -> out[B, C, H, W]` (shared symbols, integer
|
|
22
|
+
scales, literals, `...` for shared middle axes, `x*` variadic inputs, port
|
|
23
|
+
dtypes) or a relation function over a bounded node view, scalar arguments
|
|
24
|
+
with help text, runnable examples, and hooks for positional rest arguments,
|
|
25
|
+
policies, validation, and finalization. Built-ins are discovered from
|
|
26
|
+
`hndl.operators`; custom operators use the same decorator on a `Registry`.
|
|
27
|
+
See [docs/ADDING_OPERATORS.md](docs/ADDING_OPERATORS.md).
|
|
28
|
+
- Fifty-nine operators across activation, arithmetic, shape, normalization,
|
|
29
|
+
convolution, spatial, sequence, vision, memory, regularization, and
|
|
30
|
+
pretrained categories, each with tests against PyTorch references.
|
|
31
|
+
- `pretrained(source)`: a generic loader for transformers and timm checkpoints
|
|
32
|
+
from local paths or `hf://` repositories. See [docs/pretrained.md](docs/pretrained.md).
|
|
33
|
+
- PyTorch modules, shape tables, name lookup, sequence indexing and shared
|
|
34
|
+
slices, ordinary autograd, state dictionaries, and CPU/CUDA construction in
|
|
35
|
+
float32, float16, or bfloat16.
|
|
36
|
+
- Persisted constant parameter initialization and trainability overrides,
|
|
37
|
+
shared by both frontends and applied when building or rebuilding a plan.
|
|
38
|
+
- Immutable resolved graph data, canonical JSON plan persistence, digests,
|
|
39
|
+
exact operator-version checks, and `build(plan)` without recapturing an
|
|
40
|
+
author function. JSON is a persistence format, not an authoring language.
|
|
41
|
+
- Generated documentation (`python -m hndl.docs`, checked in CI), MIT license,
|
|
42
|
+
wheel/source builds, CI, and a release publishing workflow.
|
|
43
|
+
|
|
44
|
+
## Runtime and operation arguments
|
|
45
|
+
|
|
46
|
+
The supported platform is Linux, on Python 3.11–3.14. Config parsing uses a
|
|
47
|
+
Python 3.11 grammar with an explicit AST allowlist in an isolated Linux worker.
|
|
48
|
+
Unsupported platforms fail instead of falling back to in-process parsing.
|
|
49
|
+
Native authoring executes trusted Python; it is not sandboxed.
|
|
50
|
+
|
|
51
|
+
The backend requires PyTorch 2.6 or newer in the 2.x series. Tensors have
|
|
52
|
+
rank two `[B, F]`, rank three `[B, T, D]` (a sequence of `T` positions with
|
|
53
|
+
`D` features; `linear`, normalizations, and activations act on the last axis),
|
|
54
|
+
or rank four `[B, C, H, W]`. One-dimensional convolution and pooling use rank
|
|
55
|
+
three as `[B, C, L]`; `transpose(1, 2)` moves between the conventions. Only
|
|
56
|
+
the batch axis may be symbolic (`"B"`). Other dimensions and runtime batch
|
|
57
|
+
sizes must be positive integers. The device is always caller-selected.
|
|
58
|
+
|
|
59
|
+
Plans carry a compute `dtype` of `float32` (default), `float16`, or
|
|
60
|
+
`bfloat16`; parameters are constructed in that dtype and every floating tensor
|
|
61
|
+
port must match it at runtime. Operators can declare integer ports, such as
|
|
62
|
+
`embedding`'s `ids[B, T]:int64` input; pass `input_dtype="int64"` when the
|
|
63
|
+
graph input is integer. Edge dtypes are checked at resolution (`E_DTYPE`), so
|
|
64
|
+
an integer tensor cannot reach a floating-point port. Reduced precision is
|
|
65
|
+
qualified on CUDA.
|
|
66
|
+
|
|
67
|
+
Built-in unary operations take an optional leading tensor or `x=`. Custom
|
|
68
|
+
unary operations use their declared input-port keyword. Every operator's
|
|
69
|
+
arguments, defaults, bounds, shape relation, and examples are listed in
|
|
70
|
+
[docs/operators](docs/operators/index.md). Convolution spatial arguments
|
|
71
|
+
accept an integer or a pair of integers. Split/concat axes are positive,
|
|
72
|
+
non-batch indices; negative axes are rejected. `name=` sets a stable node ID
|
|
73
|
+
independently of Python variable names. Operator aliases are reserved names
|
|
74
|
+
in configurations.
|
|
75
|
+
|
|
76
|
+
`dropout` is stochastic in training mode using PyTorch's global RNG, the one
|
|
77
|
+
documented deviation from the rule that forward passes draw no hidden
|
|
78
|
+
randomness. `pretrained` reads its checkpoint's `config.json` (downloading it
|
|
79
|
+
for `hf://` sources) and traces the architecture on the meta device during
|
|
80
|
+
resolution, the one documented exception to allocation-free resolution.
|
|
81
|
+
|
|
82
|
+
## Loading and allocation limits
|
|
83
|
+
|
|
84
|
+
Both string and file loading use the same parser worker. The fixed parser
|
|
85
|
+
limits are 64 KiB of UTF-8 source, 4,096 lines, 16,384 AST nodes, nesting depth
|
|
86
|
+
96, 1,024 items per literal container, 16 KiB per string literal, and 256 bits
|
|
87
|
+
per integer literal. Worker address space is capped at 256 MiB and CPU time
|
|
88
|
+
at two seconds; the parent also enforces a wall-clock timeout. The worker
|
|
89
|
+
protocol is bounded at 2 MiB. Parsing never invokes `eval`, `exec`, or a
|
|
90
|
+
configuration-provided import or callback.
|
|
91
|
+
|
|
92
|
+
The resolver and builder additionally bound graph size, dimensions, element
|
|
93
|
+
counts, and registered parameter/buffer storage. Defaults are 4,096 nodes,
|
|
94
|
+
16,384 input edges, 1,048,576 per dimension, 268,435,456 elements per
|
|
95
|
+
example, 1 GiB of registered state, and 256 solver iterations. Pass a
|
|
96
|
+
`limits` dictionary to resolution or construction to override these limits
|
|
97
|
+
explicitly; keys are `max_nodes`, `max_edges`, `max_dimension`,
|
|
98
|
+
`max_elements`, `max_state_bytes`, and `max_iterations`. Storage is measured
|
|
99
|
+
by constructing every module on PyTorch's allocation-free `meta` device before
|
|
100
|
+
real construction; `build_receipt["state_bytes"]` records the total. These
|
|
101
|
+
bounds do not estimate peak training memory or bound arbitrary native Python
|
|
102
|
+
authoring code.
|
|
103
|
+
|
|
104
|
+
## Custom operation scope
|
|
105
|
+
|
|
106
|
+
`@operator` declarations are data: registration parses the shape string and
|
|
107
|
+
argument schema without constructing modules. Shared dimension names impose
|
|
108
|
+
equality within one node, `2*C` imposes an exact integer multiple in either
|
|
109
|
+
direction, literals fix an axis, and `...` shares a run of middle axes across
|
|
110
|
+
the ports that use it. Rules the string cannot express use a `relation`
|
|
111
|
+
function over a bounded node view; relations are trusted code. See
|
|
112
|
+
[docs/ADDING_OPERATORS.md](docs/ADDING_OPERATORS.md) and the
|
|
113
|
+
[technical contract](SPEC.md#8-custom-operators-and-minimal-graphs).
|
|
114
|
+
|
|
115
|
+
Each declaration permits at most 32 input ports, 32 output ports, 64 scalar
|
|
116
|
+
arguments, and 64 distinct dimension symbols. Port, argument, and dimension
|
|
117
|
+
names are limited to 64 characters. Dimension literals and scales are capped
|
|
118
|
+
at `2**31 - 1`; the usually lower runtime `max_dimension` still applies to
|
|
119
|
+
resolved extents. Integer scalar arguments are bounded by `abs(value) <=
|
|
120
|
+
2**63 - 1`, and string arguments by 16,384 UTF-8 bytes. Float values must be
|
|
121
|
+
finite. Schemas may apply tighter numeric bounds. Omitted scalar arguments
|
|
122
|
+
need an explicit default unless marked `inferable`, in which case a shape
|
|
123
|
+
symbol or relation must determine them.
|
|
124
|
+
|
|
125
|
+
## Saving a resolved plan
|
|
126
|
+
|
|
127
|
+
Use the plan alongside the model's ordinary PyTorch state dictionary:
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
from pathlib import Path
|
|
131
|
+
from hndl import ResolvedPlan
|
|
132
|
+
from hndl.torch import build
|
|
133
|
+
|
|
134
|
+
Path("architecture.json").write_text(model.plan.to_json(), encoding="utf-8")
|
|
135
|
+
plan = ResolvedPlan.from_json(
|
|
136
|
+
Path("architecture.json").read_text(encoding="utf-8")
|
|
137
|
+
)
|
|
138
|
+
restored = build(plan, device="cpu")
|
|
139
|
+
restored.load_state_dict(model.state_dict())
|
|
140
|
+
# build() returns the lower-level named-input/dictionary-output module:
|
|
141
|
+
result = restored(x=batch)["output"]
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Custom plans require the matching explicit registry at restore/build time.
|
|
145
|
+
Saved data cannot import its own implementations. Restoration verifies the
|
|
146
|
+
saved concrete equations, dimensions, and operator versions without executing
|
|
147
|
+
source or an author function. The ordinary PyTorch state dictionary does not
|
|
148
|
+
contain the architecture; keep both together. Plans that use `pretrained`
|
|
149
|
+
record the resolved checkpoint revision and fail to restore if the source has
|
|
150
|
+
changed.
|
|
151
|
+
|
|
152
|
+
Schema 1 uses sorted JSON object keys, compact separators, UTF-8 without ASCII
|
|
153
|
+
escaping, arrays for tuples, finite numbers, and SHA-256 digests. Node order,
|
|
154
|
+
identities, arguments, shapes, dtypes, initialization, and trainability
|
|
155
|
+
participate in the semantic digest. Source/frontend metadata and argument
|
|
156
|
+
provenance affect the artifact digest but not the semantic digest. Plan JSON
|
|
157
|
+
is limited to 16 MiB. Restoring arbitrary third-party artifacts is not the
|
|
158
|
+
same isolation boundary as loading declarative source.
|
|
159
|
+
|
|
160
|
+
## Construction settings
|
|
161
|
+
|
|
162
|
+
`init={"weight": 0, "bias": 0}` selects constant parameter overrides after
|
|
163
|
+
normal module construction. `trainable=False` freezes all parameters in the
|
|
164
|
+
operation, while `trainable={"weight": False}` changes only named parameters.
|
|
165
|
+
Omitting either option preserves the constructor's values or `requires_grad`
|
|
166
|
+
flags. Empty mappings have the same meaning as omission. Explicit `None` is
|
|
167
|
+
not supported. Both options are reserved frontend metadata, alongside `name`
|
|
168
|
+
and `policy`, and are never passed as operator constructor arguments.
|
|
169
|
+
|
|
170
|
+
Targets are exact, relative parameter paths (including nested paths such as
|
|
171
|
+
`projection.weight`), with at most 256 entries per mapping and 256 characters
|
|
172
|
+
per path. Buffers and nonexistent targets are rejected at build time.
|
|
173
|
+
Constants must be numbers other than booleans and must round to finite
|
|
174
|
+
float32 values; the plan stores those rounded values and fills them into the
|
|
175
|
+
parameter's dtype. Trainability values must be booleans. Aliased parameters
|
|
176
|
+
cannot receive conflicting declarations. Constant targets cannot share storage
|
|
177
|
+
with a distinct parameter or a registered buffer.
|
|
178
|
+
|
|
179
|
+
Initialization overrides run under `no_grad` after parameters are materialized.
|
|
180
|
+
`initialization_seed=None` uses the caller's RNG; an explicit seed isolates
|
|
181
|
+
construction and restores the caller's RNG afterward. Freezing affects
|
|
182
|
+
parameter gradients, not input gradients or train/eval mode.
|
|
183
|
+
|
|
184
|
+
## Limits of this release
|
|
185
|
+
|
|
186
|
+
- Custom shape relations beyond the DSL are trusted Python functions; there is
|
|
187
|
+
no declarative form for arithmetic relations, and inferable custom scalars
|
|
188
|
+
must be bound to a shape symbol or set by a relation.
|
|
189
|
+
- Weight tying between graph nodes is unsupported; `pretrained` loads tied
|
|
190
|
+
checkpoints correctly because the wrapped model ties them internally.
|
|
191
|
+
- Vision checkpoints load at their native resolution only.
|
|
192
|
+
- Full derivation chains for every inferred value, published machine-readable
|
|
193
|
+
plan schemas, and strict checkpoint-compatibility tooling beyond ordinary
|
|
194
|
+
PyTorch state loading remain future work.
|
|
195
|
+
- Training loops, metric optimization, optimizer state, and complete experiment
|
|
196
|
+
recovery remain owned by the application.
|
|
197
|
+
|
|
198
|
+
## Development and publication
|
|
199
|
+
|
|
200
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for local checks and publishing setup.
|
|
201
|
+
CI tests the CPU backend on Python 3.11 and 3.14, checks that the generated
|
|
202
|
+
documentation is current, checks the built distributions, and exercises a
|
|
203
|
+
wheel installation outside the checkout. CUDA and network-dependent tests run
|
|
204
|
+
locally; CPU CI does not qualify CUDA execution or checkpoint downloads.
|
hndl-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 HNDL contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
hndl-0.1.0/MANIFEST.in
ADDED