trimbed 0.0.1__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.
- trimbed-0.0.1/.gitattributes +12 -0
- trimbed-0.0.1/.github/workflows/ci.yml +114 -0
- trimbed-0.0.1/.github/workflows/docs.yml +93 -0
- trimbed-0.0.1/.github/workflows/hub-tests.yml +57 -0
- trimbed-0.0.1/.github/workflows/publish.yml +35 -0
- trimbed-0.0.1/.gitignore +77 -0
- trimbed-0.0.1/.pre-commit-config.yaml +76 -0
- trimbed-0.0.1/.python-version +1 -0
- trimbed-0.0.1/CONTRIBUTING.md +103 -0
- trimbed-0.0.1/LICENSE +201 -0
- trimbed-0.0.1/Makefile +77 -0
- trimbed-0.0.1/PKG-INFO +141 -0
- trimbed-0.0.1/README.md +106 -0
- trimbed-0.0.1/codecov.yml +13 -0
- trimbed-0.0.1/docs/api/backends/base.md +3 -0
- trimbed-0.0.1/docs/api/backends/bpe.md +3 -0
- trimbed-0.0.1/docs/api/backends/registry.md +11 -0
- trimbed-0.0.1/docs/api/backends/unigram.md +3 -0
- trimbed-0.0.1/docs/api/backends/wordlevel.md +3 -0
- trimbed-0.0.1/docs/api/backends/wordpiece.md +3 -0
- trimbed-0.0.1/docs/api/bytelevel.md +3 -0
- trimbed-0.0.1/docs/api/cli/count.md +3 -0
- trimbed-0.0.1/docs/api/cli/inspect.md +3 -0
- trimbed-0.0.1/docs/api/cli/presets.md +3 -0
- trimbed-0.0.1/docs/api/cli/router.md +3 -0
- trimbed-0.0.1/docs/api/cli/trim.md +3 -0
- trimbed-0.0.1/docs/api/config.md +3 -0
- trimbed-0.0.1/docs/api/counting.md +3 -0
- trimbed-0.0.1/docs/api/exceptions.md +3 -0
- trimbed-0.0.1/docs/api/loading.md +3 -0
- trimbed-0.0.1/docs/api/model_trim.md +3 -0
- trimbed-0.0.1/docs/api/pipeline.md +3 -0
- trimbed-0.0.1/docs/api/presets.md +3 -0
- trimbed-0.0.1/docs/api/remap.md +3 -0
- trimbed-0.0.1/docs/api/report.md +3 -0
- trimbed-0.0.1/docs/api/selection.md +3 -0
- trimbed-0.0.1/docs/api/sidecar.md +3 -0
- trimbed-0.0.1/docs/api/spec.md +3 -0
- trimbed-0.0.1/docs/api/tokenizer_trim.md +3 -0
- trimbed-0.0.1/docs/api/verify.md +3 -0
- trimbed-0.0.1/docs/cli.md +100 -0
- trimbed-0.0.1/docs/configuration.md +103 -0
- trimbed-0.0.1/docs/examples.md +24 -0
- trimbed-0.0.1/docs/extending.md +62 -0
- trimbed-0.0.1/docs/hooks.py +139 -0
- trimbed-0.0.1/docs/index.md +88 -0
- trimbed-0.0.1/docs/output.md +66 -0
- trimbed-0.0.1/docs/overrides/main.html +8 -0
- trimbed-0.0.1/docs/overrides/python/material/_source_link.html.jinja +20 -0
- trimbed-0.0.1/docs/overrides/python/material/class.html.jinja +25 -0
- trimbed-0.0.1/docs/overrides/python/material/function.html.jinja +12 -0
- trimbed-0.0.1/docs/selection.md +92 -0
- trimbed-0.0.1/docs/trimming-a-model.md +78 -0
- trimbed-0.0.1/examples/01_inspect_tokenizer.py +58 -0
- trimbed-0.0.1/examples/02_trim_tokenizer_only.py +66 -0
- trimbed-0.0.1/examples/03_trim_with_corpus.py +89 -0
- trimbed-0.0.1/examples/04_custom_preset.py +84 -0
- trimbed-0.0.1/examples/05_low_level_api.py +68 -0
- trimbed-0.0.1/examples/README.md +27 -0
- trimbed-0.0.1/mkdocs.yml +212 -0
- trimbed-0.0.1/pyproject.toml +155 -0
- trimbed-0.0.1/src/trimbed/__init__.py +75 -0
- trimbed-0.0.1/src/trimbed/_logging.py +45 -0
- trimbed-0.0.1/src/trimbed/backends/__init__.py +84 -0
- trimbed-0.0.1/src/trimbed/backends/base.py +85 -0
- trimbed-0.0.1/src/trimbed/backends/bpe.py +63 -0
- trimbed-0.0.1/src/trimbed/backends/unigram.py +35 -0
- trimbed-0.0.1/src/trimbed/backends/wordlevel.py +17 -0
- trimbed-0.0.1/src/trimbed/backends/wordpiece.py +18 -0
- trimbed-0.0.1/src/trimbed/bytelevel.py +71 -0
- trimbed-0.0.1/src/trimbed/cli/__init__.py +7 -0
- trimbed-0.0.1/src/trimbed/cli/__main__.py +51 -0
- trimbed-0.0.1/src/trimbed/cli/count_tokens.py +85 -0
- trimbed-0.0.1/src/trimbed/cli/inspect_tokenizer.py +65 -0
- trimbed-0.0.1/src/trimbed/cli/list_presets.py +48 -0
- trimbed-0.0.1/src/trimbed/cli/trim_vocab.py +167 -0
- trimbed-0.0.1/src/trimbed/config.py +389 -0
- trimbed-0.0.1/src/trimbed/counting.py +260 -0
- trimbed-0.0.1/src/trimbed/exceptions.py +27 -0
- trimbed-0.0.1/src/trimbed/loading.py +164 -0
- trimbed-0.0.1/src/trimbed/model_trim.py +176 -0
- trimbed-0.0.1/src/trimbed/pipeline.py +290 -0
- trimbed-0.0.1/src/trimbed/presets.py +373 -0
- trimbed-0.0.1/src/trimbed/remap.py +133 -0
- trimbed-0.0.1/src/trimbed/report.py +267 -0
- trimbed-0.0.1/src/trimbed/selection.py +394 -0
- trimbed-0.0.1/src/trimbed/sidecar.py +112 -0
- trimbed-0.0.1/src/trimbed/spec.py +367 -0
- trimbed-0.0.1/src/trimbed/tokenizer_trim.py +150 -0
- trimbed-0.0.1/src/trimbed/verify.py +220 -0
- trimbed-0.0.1/tests/conftest.py +299 -0
- trimbed-0.0.1/tests/qwen3_chat_template.jinja +89 -0
- trimbed-0.0.1/tests/test_backends.py +129 -0
- trimbed-0.0.1/tests/test_chat_template.py +180 -0
- trimbed-0.0.1/tests/test_cli.py +258 -0
- trimbed-0.0.1/tests/test_config.py +172 -0
- trimbed-0.0.1/tests/test_counting.py +124 -0
- trimbed-0.0.1/tests/test_docs.py +92 -0
- trimbed-0.0.1/tests/test_errors_and_edges.py +250 -0
- trimbed-0.0.1/tests/test_examples.py +135 -0
- trimbed-0.0.1/tests/test_integration.py +371 -0
- trimbed-0.0.1/tests/test_loading.py +76 -0
- trimbed-0.0.1/tests/test_logging.py +42 -0
- trimbed-0.0.1/tests/test_model_trim.py +282 -0
- trimbed-0.0.1/tests/test_pipeline.py +271 -0
- trimbed-0.0.1/tests/test_presets.py +156 -0
- trimbed-0.0.1/tests/test_remap.py +55 -0
- trimbed-0.0.1/tests/test_report.py +124 -0
- trimbed-0.0.1/tests/test_selection.py +250 -0
- trimbed-0.0.1/tests/test_sidecar.py +73 -0
- trimbed-0.0.1/tests/test_spec.py +125 -0
- trimbed-0.0.1/tests/test_tokenizer_trim.py +162 -0
- trimbed-0.0.1/tests/test_verify.py +214 -0
- trimbed-0.0.1/uv.lock +2158 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Line-ending policy: LF in the repository, LF in every working tree.
|
|
2
|
+
#
|
|
3
|
+
# `text=auto` lets Git detect which files are text (binary content is left untouched),
|
|
4
|
+
# and `eol=lf` pins the checkout ending on every platform rather than following
|
|
5
|
+
# core.autocrlf. Without this, files committed from Windows keep their CRLF, which shows
|
|
6
|
+
# up as whole-file diffs and breaks tools that parse the repo's own config from a shell
|
|
7
|
+
# (hence the `tr -d '\r'` guard in the Makefile's `test-matrix` target).
|
|
8
|
+
* text=auto eol=lf
|
|
9
|
+
|
|
10
|
+
# Generated by uv and only ever rewritten wholesale; collapse it in diffs and keep it out
|
|
11
|
+
# of review noise.
|
|
12
|
+
uv.lock linguist-generated=true
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
paths:
|
|
8
|
+
- "**.py"
|
|
9
|
+
- "pyproject.toml"
|
|
10
|
+
- "uv.lock"
|
|
11
|
+
- ".pre-commit-config.yaml"
|
|
12
|
+
- ".github/workflows/ci.yml"
|
|
13
|
+
- "Makefile"
|
|
14
|
+
- "mkdocs.yml"
|
|
15
|
+
- "docs/**"
|
|
16
|
+
pull_request:
|
|
17
|
+
branches: [main]
|
|
18
|
+
paths:
|
|
19
|
+
- "**.py"
|
|
20
|
+
- "pyproject.toml"
|
|
21
|
+
- "uv.lock"
|
|
22
|
+
- ".pre-commit-config.yaml"
|
|
23
|
+
- ".github/workflows/ci.yml"
|
|
24
|
+
- "Makefile"
|
|
25
|
+
- "mkdocs.yml"
|
|
26
|
+
- "docs/**"
|
|
27
|
+
|
|
28
|
+
# Cancel any in-progress run for the same branch/PR when a new push arrives.
|
|
29
|
+
concurrency:
|
|
30
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
31
|
+
cancel-in-progress: true
|
|
32
|
+
|
|
33
|
+
jobs:
|
|
34
|
+
quality:
|
|
35
|
+
name: Code quality
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
steps:
|
|
38
|
+
# fetch-depth: 0 everywhere because hatch-vcs derives the version from the tags.
|
|
39
|
+
- uses: actions/checkout@v4
|
|
40
|
+
with:
|
|
41
|
+
fetch-depth: 0
|
|
42
|
+
|
|
43
|
+
- uses: astral-sh/setup-uv@v5
|
|
44
|
+
with:
|
|
45
|
+
enable-cache: true
|
|
46
|
+
python-version: "3.12"
|
|
47
|
+
|
|
48
|
+
- name: Install dependencies
|
|
49
|
+
run: uv sync --locked --group dev
|
|
50
|
+
|
|
51
|
+
# The hooks already cover ruff lint, ruff format and `uv lock --check`, so there is
|
|
52
|
+
# no separate lint step here. There is deliberately no type-checking step: type
|
|
53
|
+
# hints in this project are documentation, not a contract.
|
|
54
|
+
- name: Run pre-commit
|
|
55
|
+
run: uv run pre-commit run --all-files --show-diff-on-failure
|
|
56
|
+
|
|
57
|
+
# Validation only: builds the site into a throwaway directory and discards it. Nothing
|
|
58
|
+
# is published here -- docs.yml is the only workflow that touches gh-pages, and it only
|
|
59
|
+
# runs on a release. The point is to catch broken cross-references, dead anchors and
|
|
60
|
+
# missing nav entries on the pull request that introduces them rather than at release
|
|
61
|
+
# time.
|
|
62
|
+
docs:
|
|
63
|
+
name: Docs build
|
|
64
|
+
runs-on: ubuntu-latest
|
|
65
|
+
steps:
|
|
66
|
+
- uses: actions/checkout@v4
|
|
67
|
+
with:
|
|
68
|
+
fetch-depth: 0
|
|
69
|
+
|
|
70
|
+
- uses: astral-sh/setup-uv@v5
|
|
71
|
+
with:
|
|
72
|
+
enable-cache: true
|
|
73
|
+
python-version: "3.12"
|
|
74
|
+
|
|
75
|
+
- name: Install docs dependencies
|
|
76
|
+
run: uv sync --locked --group docs
|
|
77
|
+
|
|
78
|
+
- name: Build docs (strict)
|
|
79
|
+
run: uv run mkdocs build --strict --site-dir "${RUNNER_TEMP}/site"
|
|
80
|
+
|
|
81
|
+
test:
|
|
82
|
+
name: Tests (Python ${{ matrix.python-version }})
|
|
83
|
+
runs-on: ubuntu-latest
|
|
84
|
+
strategy:
|
|
85
|
+
fail-fast: false
|
|
86
|
+
matrix:
|
|
87
|
+
# Not 3.14: `datasets` pulls in `multiprocess`, which ships no cp314 wheels and
|
|
88
|
+
# fails to import there, and `datasets` is a hard runtime dependency.
|
|
89
|
+
python-version: ["3.12", "3.13"]
|
|
90
|
+
steps:
|
|
91
|
+
- uses: actions/checkout@v4
|
|
92
|
+
with:
|
|
93
|
+
fetch-depth: 0
|
|
94
|
+
|
|
95
|
+
- uses: astral-sh/setup-uv@v5
|
|
96
|
+
with:
|
|
97
|
+
enable-cache: true
|
|
98
|
+
python-version: ${{ matrix.python-version }}
|
|
99
|
+
|
|
100
|
+
- name: Install dependencies
|
|
101
|
+
run: uv sync --locked --group dev
|
|
102
|
+
|
|
103
|
+
# The offline suite: no Hub access, no real weights. See hub-tests.yml for those.
|
|
104
|
+
- name: Run tests
|
|
105
|
+
run: make test
|
|
106
|
+
|
|
107
|
+
- name: Upload coverage
|
|
108
|
+
uses: codecov/codecov-action@v5
|
|
109
|
+
with:
|
|
110
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
111
|
+
files: coverage.xml
|
|
112
|
+
fail_ci_if_error: true
|
|
113
|
+
disable_search: true
|
|
114
|
+
disable_telem: true
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
name: Publish docs to GitHub Pages
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
inputs:
|
|
8
|
+
release_tag:
|
|
9
|
+
description: Git tag to publish docs for, for example v0.3.0
|
|
10
|
+
required: true
|
|
11
|
+
type: string
|
|
12
|
+
|
|
13
|
+
# Cancel any in-progress docs deploy for the same branch when a new push arrives.
|
|
14
|
+
concurrency:
|
|
15
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
16
|
+
cancel-in-progress: true
|
|
17
|
+
|
|
18
|
+
permissions:
|
|
19
|
+
contents: write
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
deploy:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
with:
|
|
27
|
+
fetch-depth: 0
|
|
28
|
+
fetch-tags: true
|
|
29
|
+
|
|
30
|
+
- name: Resolve docs tag and version
|
|
31
|
+
id: docs_ref
|
|
32
|
+
run: |
|
|
33
|
+
if [ "${{ github.event_name }}" = "release" ]; then
|
|
34
|
+
DOCS_GIT_TAG="${{ github.event.release.tag_name }}"
|
|
35
|
+
else
|
|
36
|
+
DOCS_GIT_TAG="${{ inputs.release_tag }}"
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
if [ -z "${DOCS_GIT_TAG}" ]; then
|
|
40
|
+
echo "A release tag is required to publish docs." >&2
|
|
41
|
+
exit 1
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
if ! git rev-parse --verify "refs/tags/${DOCS_GIT_TAG}" >/dev/null 2>&1; then
|
|
45
|
+
echo "Git tag '${DOCS_GIT_TAG}' does not exist." >&2
|
|
46
|
+
exit 1
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
DOCS_VERSION="${DOCS_GIT_TAG#v}"
|
|
50
|
+
if [ -z "${DOCS_VERSION}" ] || [ "${DOCS_VERSION}" = "${DOCS_GIT_TAG}" ]; then
|
|
51
|
+
echo "Release tag must start with 'v'; got '${DOCS_GIT_TAG}'." >&2
|
|
52
|
+
exit 1
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
echo "docs_git_tag=${DOCS_GIT_TAG}" >> "$GITHUB_OUTPUT"
|
|
56
|
+
echo "docs_version=${DOCS_VERSION}" >> "$GITHUB_OUTPUT"
|
|
57
|
+
# docs/hooks.py reads this to point every "View source on GitHub" link at the
|
|
58
|
+
# tag these docs were built from instead of at main.
|
|
59
|
+
echo "DOCS_SOURCE_REF=${DOCS_GIT_TAG}" >> "$GITHUB_ENV"
|
|
60
|
+
|
|
61
|
+
- name: Check out docs tag
|
|
62
|
+
run: git checkout "${{ steps.docs_ref.outputs.docs_git_tag }}"
|
|
63
|
+
|
|
64
|
+
# Docs *content* comes from the tag; the tooling that renders it always comes from
|
|
65
|
+
# main, so a rendering fix reaches published docs without re-tagging. Pinned to main
|
|
66
|
+
# rather than GITHUB_SHA because GITHUB_SHA is the tag commit on a release but the
|
|
67
|
+
# branch tip on a workflow_dispatch, which would make a manual rerun build a
|
|
68
|
+
# different site than the release did.
|
|
69
|
+
- name: Use current docs build tooling from main
|
|
70
|
+
run: |
|
|
71
|
+
git checkout origin/main -- \
|
|
72
|
+
pyproject.toml uv.lock mkdocs.yml docs/hooks.py docs/overrides
|
|
73
|
+
|
|
74
|
+
- uses: astral-sh/setup-uv@v5
|
|
75
|
+
with:
|
|
76
|
+
enable-cache: true
|
|
77
|
+
|
|
78
|
+
- name: Install docs dependencies
|
|
79
|
+
run: uv sync --locked --group docs
|
|
80
|
+
|
|
81
|
+
- name: Configure git identity
|
|
82
|
+
run: |
|
|
83
|
+
git config user.name "github-actions[bot]"
|
|
84
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
85
|
+
|
|
86
|
+
- name: Fetch gh-pages branch for mike
|
|
87
|
+
run: git fetch origin gh-pages --depth=1 || true
|
|
88
|
+
|
|
89
|
+
- name: Deploy release docs (tag -> version + set as latest)
|
|
90
|
+
run: |
|
|
91
|
+
VERSION="${{ steps.docs_ref.outputs.docs_version }}"
|
|
92
|
+
uv run mike deploy --push --update-aliases "${VERSION}" latest
|
|
93
|
+
uv run mike set-default --push latest
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# The tests that reach the Hugging Face Hub, kept off the pull-request path on purpose: a
|
|
2
|
+
# Hub outage or a several-gigabyte download must never be what blocks a merge. Run them
|
|
3
|
+
# on a schedule and on demand instead.
|
|
4
|
+
name: Hub tests
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
schedule:
|
|
9
|
+
# Mondays, 05:40 UTC
|
|
10
|
+
- cron: "40 5 * * 1"
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
14
|
+
cancel-in-progress: true
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
tokenizers:
|
|
18
|
+
name: Hub tokenizer trims
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
with:
|
|
23
|
+
fetch-depth: 0
|
|
24
|
+
|
|
25
|
+
- uses: astral-sh/setup-uv@v5
|
|
26
|
+
with:
|
|
27
|
+
enable-cache: true
|
|
28
|
+
python-version: "3.12"
|
|
29
|
+
|
|
30
|
+
# --all-extras: the mT5 case needs trimbed[convert] to read a bare spiece.model.
|
|
31
|
+
- name: Install dependencies
|
|
32
|
+
run: uv sync --locked --all-extras --group dev
|
|
33
|
+
|
|
34
|
+
- name: Run Hub tokenizer tests
|
|
35
|
+
run: make test-network
|
|
36
|
+
|
|
37
|
+
models:
|
|
38
|
+
name: Hub model trims
|
|
39
|
+
runs-on: ubuntu-latest
|
|
40
|
+
# Minutes per case, and every one of them downloads a real checkpoint. A failure here
|
|
41
|
+
# is worth seeing but is not a reason to call the run red.
|
|
42
|
+
continue-on-error: true
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@v4
|
|
45
|
+
with:
|
|
46
|
+
fetch-depth: 0
|
|
47
|
+
|
|
48
|
+
- uses: astral-sh/setup-uv@v5
|
|
49
|
+
with:
|
|
50
|
+
enable-cache: true
|
|
51
|
+
python-version: "3.12"
|
|
52
|
+
|
|
53
|
+
- name: Install dependencies
|
|
54
|
+
run: uv sync --locked --all-extras --group dev
|
|
55
|
+
|
|
56
|
+
- name: Run Hub model tests
|
|
57
|
+
run: make test-slow
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
pypi-publish:
|
|
9
|
+
name: Build and Publish
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
|
|
12
|
+
environment: release
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
id-token: write
|
|
16
|
+
contents: read
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
# fetch-depth: 0 so hatch-vcs sees the tag and builds a released version rather
|
|
20
|
+
# than a development one.
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
with:
|
|
23
|
+
fetch-depth: 0
|
|
24
|
+
|
|
25
|
+
- name: Install uv
|
|
26
|
+
uses: astral-sh/setup-uv@v5
|
|
27
|
+
with:
|
|
28
|
+
enable-cache: true
|
|
29
|
+
|
|
30
|
+
- name: Build package
|
|
31
|
+
run: uv build
|
|
32
|
+
|
|
33
|
+
# Trusted publishing: the OIDC token above stands in for an API token.
|
|
34
|
+
- name: Publish to PyPI
|
|
35
|
+
run: uv publish
|
trimbed-0.0.1/.gitignore
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
.ruff_cache/
|
|
2
|
+
papers/
|
|
3
|
+
data/
|
|
4
|
+
configs/
|
|
5
|
+
|
|
6
|
+
# Python caches and bytecode
|
|
7
|
+
__pycache__/
|
|
8
|
+
*.py[cod]
|
|
9
|
+
*$py.class
|
|
10
|
+
|
|
11
|
+
# Virtual environments
|
|
12
|
+
.venv/
|
|
13
|
+
venv/
|
|
14
|
+
env/
|
|
15
|
+
# without slash because we are using a sym-link as the venv
|
|
16
|
+
# lives on scratch
|
|
17
|
+
.venv
|
|
18
|
+
|
|
19
|
+
# Build / packaging artifacts
|
|
20
|
+
build/
|
|
21
|
+
dist/
|
|
22
|
+
*.egg-info/
|
|
23
|
+
|
|
24
|
+
# Test / coverage artifacts
|
|
25
|
+
.pytest_cache/
|
|
26
|
+
.coverage
|
|
27
|
+
.coverage.*
|
|
28
|
+
coverage.xml
|
|
29
|
+
report.xml
|
|
30
|
+
htmlcov/
|
|
31
|
+
|
|
32
|
+
# uv's cache, relocated into the project directory by CI
|
|
33
|
+
.uv-cache/
|
|
34
|
+
|
|
35
|
+
# One venv per interpreter, written by `make test-matrix`
|
|
36
|
+
.venvs/
|
|
37
|
+
|
|
38
|
+
# mkdocs output; the published site lives on the gh-pages branch
|
|
39
|
+
/site
|
|
40
|
+
|
|
41
|
+
# Jupyter checkpoints
|
|
42
|
+
.ipynb_checkpoints/
|
|
43
|
+
|
|
44
|
+
# Training outputs and checkpoints
|
|
45
|
+
runs/
|
|
46
|
+
checkpoints/
|
|
47
|
+
|
|
48
|
+
# Model and large binary artifacts
|
|
49
|
+
*.pt
|
|
50
|
+
*.bin
|
|
51
|
+
*.safetensors
|
|
52
|
+
|
|
53
|
+
# System/editor files
|
|
54
|
+
.DS_Store
|
|
55
|
+
.vscode/
|
|
56
|
+
.idea/
|
|
57
|
+
|
|
58
|
+
# Logs
|
|
59
|
+
logs/
|
|
60
|
+
*.log
|
|
61
|
+
|
|
62
|
+
# Downloaded / derived data
|
|
63
|
+
data/dev_samples/
|
|
64
|
+
|
|
65
|
+
# Local planning notes
|
|
66
|
+
plan.md
|
|
67
|
+
|
|
68
|
+
# Claude Code local configuration
|
|
69
|
+
.claude/
|
|
70
|
+
CLAUDE.md
|
|
71
|
+
.agents/
|
|
72
|
+
|
|
73
|
+
# upstream bug reports
|
|
74
|
+
bugs/
|
|
75
|
+
|
|
76
|
+
# Trimmed artefacts (the default output_dir in README/examples)
|
|
77
|
+
trimmed/
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
3
|
+
rev: v6.0.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: check-added-large-files
|
|
6
|
+
- id: check-case-conflict
|
|
7
|
+
- id: check-merge-conflict
|
|
8
|
+
- id: check-toml
|
|
9
|
+
- id: check-yaml
|
|
10
|
+
# Backs up .gitattributes: that pins what lands in the index, this catches CRLF in
|
|
11
|
+
# the working tree before it gets there.
|
|
12
|
+
- id: mixed-line-ending
|
|
13
|
+
args: [--fix=lf]
|
|
14
|
+
- id: end-of-file-fixer
|
|
15
|
+
- id: trailing-whitespace
|
|
16
|
+
|
|
17
|
+
- repo: local
|
|
18
|
+
hooks:
|
|
19
|
+
# mkdocstrings renders docstrings as Markdown, so a Sphinx role survives as literal
|
|
20
|
+
# ":class:" text on the site. Use [`Name`][full.dotted.path].
|
|
21
|
+
- id: no-rst-roles
|
|
22
|
+
name: no Sphinx/RST roles in docstrings
|
|
23
|
+
language: pygrep
|
|
24
|
+
entry: ':(class|meth|func|mod|attr|obj|exc|data|ref):`'
|
|
25
|
+
types: [python]
|
|
26
|
+
files: ^src/trimbed/
|
|
27
|
+
# Griffe only documents an attribute that carries a real docstring, so a "#:"
|
|
28
|
+
# comment renders as nothing at all. Put a """docstring""" under the assignment.
|
|
29
|
+
- id: no-sphinx-attribute-comments
|
|
30
|
+
name: no Sphinx "#:" attribute comments
|
|
31
|
+
language: pygrep
|
|
32
|
+
entry: '^\s*#:'
|
|
33
|
+
types: [python]
|
|
34
|
+
files: ^src/trimbed/
|
|
35
|
+
# Only the staged files are passed in, restricted to our own source dirs by
|
|
36
|
+
# `files` below. Linting whole directories instead makes pre-commit's
|
|
37
|
+
# stash-and-restore of unstaged edits conflict with the hooks' own auto-fixes.
|
|
38
|
+
- id: ruff-lint
|
|
39
|
+
name: ruff lint
|
|
40
|
+
entry: uv run --frozen ruff check --fix --exit-non-zero-on-fix --force-exclude
|
|
41
|
+
language: system
|
|
42
|
+
types_or: [python, pyi]
|
|
43
|
+
files: ^(src/trimbed|tests|examples|docs)/
|
|
44
|
+
# ruff parallelises internally, so hand it the whole file list in one process
|
|
45
|
+
# rather than letting pre-commit fan it out across several.
|
|
46
|
+
require_serial: true
|
|
47
|
+
- id: ruff-format
|
|
48
|
+
name: ruff format
|
|
49
|
+
entry: uv run --frozen ruff format --force-exclude
|
|
50
|
+
language: system
|
|
51
|
+
# ruff formats the Python blocks inside Markdown too, which is what keeps the
|
|
52
|
+
# examples in docs/ from drifting out of the project's own style.
|
|
53
|
+
types_or: [python, pyi, markdown]
|
|
54
|
+
files: ^(src/trimbed|tests|examples|docs)/
|
|
55
|
+
require_serial: true
|
|
56
|
+
# `uv` is already on PATH and every other hook runs under `uv run --frozen`, so a
|
|
57
|
+
# pyproject.toml edit without a matching re-lock breaks all of them at once.
|
|
58
|
+
- id: uv-lock-check
|
|
59
|
+
name: uv lock check
|
|
60
|
+
entry: uv lock --check
|
|
61
|
+
language: system
|
|
62
|
+
files: ^(pyproject\.toml|uv\.lock)$
|
|
63
|
+
pass_filenames: false
|
|
64
|
+
|
|
65
|
+
# Pre-push only, and only when Python actually changed: runs the offline suite
|
|
66
|
+
# against every interpreter in the CI matrix, so version-specific breakage is caught
|
|
67
|
+
# here instead of by a red job after the push. Requires
|
|
68
|
+
# `pre-commit install --hook-type pre-push` once per clone; `pre-commit run
|
|
69
|
+
# --all-files` (what CI runs) skips it, since that defaults to the pre-commit stage.
|
|
70
|
+
- id: test-matrix
|
|
71
|
+
name: pytest on every CI Python version
|
|
72
|
+
entry: make test-matrix
|
|
73
|
+
language: system
|
|
74
|
+
stages: [pre-push]
|
|
75
|
+
types: [python]
|
|
76
|
+
pass_filenames: false
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Contributing to trimbed
|
|
2
|
+
|
|
3
|
+
## Setup
|
|
4
|
+
|
|
5
|
+
The project is managed with [uv](https://docs.astral.sh/uv/). One command gets you a
|
|
6
|
+
working environment with every development tool:
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
uv sync --locked --group dev
|
|
10
|
+
uv run pre-commit install
|
|
11
|
+
uv run pre-commit install --hook-type pre-push
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
The second `pre-commit install` is not optional if you want the matrix check below to run.
|
|
15
|
+
It is a separate hook stage, so it needs its own registration once per clone.
|
|
16
|
+
|
|
17
|
+
Python 3.12 or 3.13. Not 3.14 yet: `datasets` pulls in `multiprocess`, which has no cp314
|
|
18
|
+
wheels and fails to import there, so `requires-python` caps at `<3.14`.
|
|
19
|
+
|
|
20
|
+
Runtime dependencies are capped at the next minor rather than the next major, because
|
|
21
|
+
trimbed works against internals of `transformers`, `tokenizers`, `skeletoken` and `torch`
|
|
22
|
+
that move on minor releases. Raising a cap is its own change, with `make test-all` behind
|
|
23
|
+
it, not something to fold into an unrelated pull request.
|
|
24
|
+
|
|
25
|
+
## The checks
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
make style # ruff check --fix + ruff format
|
|
29
|
+
make quality # the non-mutating equivalent
|
|
30
|
+
make test # the offline suite, with coverage
|
|
31
|
+
make test-network # + the Hub tokenizer trims
|
|
32
|
+
make test-slow # + the Hub model trims; minutes per case
|
|
33
|
+
make test-all # everything
|
|
34
|
+
make build-docs # mkdocs build --strict
|
|
35
|
+
make serve-docs # live preview on localhost
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Run `make style`, `make test` and `make build-docs` before finishing any change.
|
|
39
|
+
|
|
40
|
+
The suite is offline by default and covers **100% of statements and branches**. Keep it
|
|
41
|
+
there. The gate is Codecov rather than a number in `pyproject.toml`: `codecov.yml` fails a
|
|
42
|
+
pull request whose project coverage drops more than 3% against the base branch, or whose
|
|
43
|
+
own changed lines are less than 90% covered. A handful of genuinely unreachable guards
|
|
44
|
+
carry `# pragma: no cover` with a comment saying which invariant makes them unreachable.
|
|
45
|
+
Prefer a real test over a new pragma.
|
|
46
|
+
|
|
47
|
+
`make test-matrix` runs the offline suite once per interpreter in the CI matrix. It reads
|
|
48
|
+
the version list out of `.github/workflows/ci.yml`, so the two cannot drift. It is also the
|
|
49
|
+
pre-push hook, which is why version-specific breakage is caught before it becomes a red job.
|
|
50
|
+
|
|
51
|
+
## Style
|
|
52
|
+
|
|
53
|
+
- Python 3.12+: `|` unions, `type` aliases, PEP 695 generics, `Self`.
|
|
54
|
+
- Concise Google-style docstrings on every public function, enforced by ruff's `D` rules.
|
|
55
|
+
- Type hints are documentation, not a contract. There is no mypy, no ruff `ANN` rules and
|
|
56
|
+
no `py.typed`, and none of the three is wanted.
|
|
57
|
+
- Raise built-in exceptions. `MissingDependencyError` is the only custom one, and it
|
|
58
|
+
subclasses `ImportError`.
|
|
59
|
+
- No `# noqa` in the source. A rule worth suppressing in more than one place is ignored in
|
|
60
|
+
`pyproject.toml`, with the reason next to it.
|
|
61
|
+
- Comments explain *why*, not what.
|
|
62
|
+
|
|
63
|
+
## Documentation
|
|
64
|
+
|
|
65
|
+
The site is MkDocs Material with mkdocstrings. Guides live in `docs/*.md`; the API
|
|
66
|
+
reference is one stub per module under `docs/api/`, each holding a title and a single
|
|
67
|
+
`::: trimbed.<module>` directive, and each listed in `mkdocs.yml`'s `nav`.
|
|
68
|
+
|
|
69
|
+
Two rules keep it navigable:
|
|
70
|
+
|
|
71
|
+
- **Cross-reference trimbed's own symbols** as ``[`Name`][trimbed.module.Name]``. Sphinx
|
|
72
|
+
roles (`` :class:`Name` ``) render as literal text on the site and are blocked by a
|
|
73
|
+
pre-commit hook. External names (`save_pretrained`, `tokenizers.Tokenizer`) stay as
|
|
74
|
+
plain backticks.
|
|
75
|
+
- **Document an attribute with a docstring**, not a `#:` comment. Griffe only picks up the
|
|
76
|
+
former; the latter renders as nothing at all. Also blocked by a pre-commit hook.
|
|
77
|
+
|
|
78
|
+
Adding a module means adding its stub page and its nav entry in the same pass.
|
|
79
|
+
`tests/test_docs.py` fails if either is missing, and `mkdocs build --strict` fails on any
|
|
80
|
+
cross-reference that does not resolve.
|
|
81
|
+
|
|
82
|
+
`examples/` and `tests/` must be kept in sync with `src/` the same way.
|
|
83
|
+
`tests/test_examples.py` executes every example against tiny in-process fixtures, so a
|
|
84
|
+
stale example fails the suite rather than rotting quietly.
|
|
85
|
+
|
|
86
|
+
## Pull requests
|
|
87
|
+
|
|
88
|
+
CI runs on every pull request to `main`: pre-commit over the whole tree, a strict docs
|
|
89
|
+
build, and the offline suite on Python 3.12 and 3.13 with coverage uploaded to Codecov.
|
|
90
|
+
The Hub tests are a separate scheduled workflow, deliberately off the pull-request path so
|
|
91
|
+
that a Hub outage or a several-gigabyte download never blocks a merge. You can run them on
|
|
92
|
+
demand from the Actions tab.
|
|
93
|
+
|
|
94
|
+
## Releases
|
|
95
|
+
|
|
96
|
+
Versions come from git tags through hatch-vcs; nothing is hand-edited.
|
|
97
|
+
|
|
98
|
+
1. Tag the commit `vX.Y.Z` and push the tag.
|
|
99
|
+
2. Publish a GitHub Release for it.
|
|
100
|
+
|
|
101
|
+
That fires two workflows in parallel: `publish.yml` builds and uploads to PyPI through
|
|
102
|
+
trusted publishing, and `docs.yml` deploys the docs for that version with mike and moves
|
|
103
|
+
the `latest` alias. The tag must start with `v`, which the docs workflow checks.
|