tuft 0.1.0__tar.gz → 0.1.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.
Files changed (87) hide show
  1. tuft-0.1.1/.gitattributes +3 -0
  2. tuft-0.1.1/.github/workflows/checks.yml +65 -0
  3. tuft-0.1.1/.github/workflows/docker/docker-compose.yml +72 -0
  4. tuft-0.1.1/.github/workflows/docker.yml +77 -0
  5. tuft-0.1.1/.github/workflows/install-script.yml +241 -0
  6. tuft-0.1.1/.github/workflows/publish.yml +56 -0
  7. tuft-0.1.1/.github/workflows/unittest.yml +103 -0
  8. tuft-0.1.1/.gitignore +72 -0
  9. tuft-0.1.1/.gitmodules +0 -0
  10. tuft-0.1.1/.pre-commit-config.yaml +51 -0
  11. tuft-0.1.1/.python-version +1 -0
  12. tuft-0.1.1/.secrets.baseline +152 -0
  13. {tuft-0.1.0 → tuft-0.1.1}/LICENSE +2 -2
  14. tuft-0.1.1/PKG-INFO +633 -0
  15. tuft-0.1.1/README.md +571 -0
  16. tuft-0.1.1/assets/countdown_rl.png +3 -0
  17. tuft-0.1.1/assets/test_nll_sft.png +3 -0
  18. tuft-0.1.1/assets/train_mean_nll_sft.png +3 -0
  19. tuft-0.1.1/assets/tuft-logo-colorful.svg +47 -0
  20. tuft-0.1.1/config/tuft_config.example.yaml +120 -0
  21. tuft-0.1.1/docker/Dockerfile +50 -0
  22. tuft-0.1.1/docs/chat_sft.md +322 -0
  23. tuft-0.1.1/docs/countdown_rl.md +300 -0
  24. tuft-0.1.1/docs/how_to_write_tests.md +238 -0
  25. tuft-0.1.1/examples/chat_sft.ipynb +783 -0
  26. tuft-0.1.1/examples/countdown_rl.ipynb +2013 -0
  27. tuft-0.1.1/pyproject.toml +112 -0
  28. tuft-0.1.1/scripts/install.sh +625 -0
  29. tuft-0.1.1/scripts/install_flash_attn.py +72 -0
  30. tuft-0.1.1/src/tuft/__init__.py +6 -0
  31. tuft-0.1.1/src/tuft/auth.py +35 -0
  32. tuft-0.1.1/src/tuft/backend.py +254 -0
  33. tuft-0.1.1/src/tuft/backends/__init__.py +10 -0
  34. tuft-0.1.1/src/tuft/backends/base_backend.py +112 -0
  35. tuft-0.1.1/src/tuft/backends/hf_training_model.py +404 -0
  36. tuft-0.1.1/src/tuft/backends/sampling_backend.py +253 -0
  37. tuft-0.1.1/src/tuft/backends/training_backend.py +327 -0
  38. tuft-0.1.1/src/tuft/checkpoints.py +193 -0
  39. tuft-0.1.1/src/tuft/cli.py +91 -0
  40. tuft-0.1.1/src/tuft/config.py +121 -0
  41. tuft-0.1.1/src/tuft/exceptions.py +138 -0
  42. tuft-0.1.1/src/tuft/futures.py +431 -0
  43. tuft-0.1.1/src/tuft/loss_fn/__init__.py +48 -0
  44. tuft-0.1.1/src/tuft/loss_fn/cispo.py +40 -0
  45. tuft-0.1.1/src/tuft/loss_fn/cross_entropy.py +26 -0
  46. tuft-0.1.1/src/tuft/loss_fn/dro.py +37 -0
  47. tuft-0.1.1/src/tuft/loss_fn/importance_sampling.py +33 -0
  48. tuft-0.1.1/src/tuft/loss_fn/ppo.py +43 -0
  49. tuft-0.1.1/src/tuft/persistence/__init__.py +32 -0
  50. tuft-0.1.1/src/tuft/persistence/file_redis.py +268 -0
  51. tuft-0.1.1/src/tuft/persistence/redis_store.py +488 -0
  52. tuft-0.1.1/src/tuft/sampling_controller.py +366 -0
  53. tuft-0.1.1/src/tuft/server.py +720 -0
  54. tuft-0.1.1/src/tuft/state.py +352 -0
  55. tuft-0.1.1/src/tuft/telemetry/__init__.py +17 -0
  56. tuft-0.1.1/src/tuft/telemetry/metrics.py +335 -0
  57. tuft-0.1.1/src/tuft/telemetry/provider.py +198 -0
  58. tuft-0.1.1/src/tuft/telemetry/tracing.py +43 -0
  59. tuft-0.1.1/src/tuft/training_controller.py +723 -0
  60. tuft-0.1.1/tests/__init__.py +1 -0
  61. tuft-0.1.1/tests/conftest.py +191 -0
  62. tuft-0.1.1/tests/data/models.yaml +19 -0
  63. tuft-0.1.1/tests/helpers.py +198 -0
  64. tuft-0.1.1/tests/test_checkpoints.py +55 -0
  65. tuft-0.1.1/tests/test_cli.py +67 -0
  66. tuft-0.1.1/tests/test_file_redis.py +49 -0
  67. tuft-0.1.1/tests/test_futures.py +83 -0
  68. tuft-0.1.1/tests/test_integration.py +350 -0
  69. tuft-0.1.1/tests/test_integration_persistence.py +213 -0
  70. tuft-0.1.1/tests/test_loss_fn.py +223 -0
  71. tuft-0.1.1/tests/test_persistence.py +727 -0
  72. tuft-0.1.1/tests/test_sampling_backend.py +103 -0
  73. tuft-0.1.1/tests/test_server.py +178 -0
  74. tuft-0.1.1/tests/test_state_controllers.py +491 -0
  75. tuft-0.1.1/tests/test_telemetry.py +493 -0
  76. tuft-0.1.1/tests/test_training_backend.py +307 -0
  77. tuft-0.1.0/PKG-INFO +0 -77
  78. tuft-0.1.0/README.md +0 -49
  79. tuft-0.1.0/pyproject.toml +0 -51
  80. tuft-0.1.0/setup.cfg +0 -4
  81. tuft-0.1.0/src/tuft/__init__.py +0 -3
  82. tuft-0.1.0/src/tuft.egg-info/PKG-INFO +0 -77
  83. tuft-0.1.0/src/tuft.egg-info/SOURCES.txt +0 -10
  84. tuft-0.1.0/src/tuft.egg-info/dependency_links.txt +0 -1
  85. tuft-0.1.0/src/tuft.egg-info/requires.txt +0 -7
  86. tuft-0.1.0/src/tuft.egg-info/top_level.txt +0 -1
  87. tuft-0.1.0/tests/test_tuft.py +0 -11
@@ -0,0 +1,3 @@
1
+ assets/countdown_rl.png filter=lfs diff=lfs merge=lfs -text
2
+ assets/test_nll_sft.png filter=lfs diff=lfs merge=lfs -text
3
+ assets/train_mean_nll_sft.png filter=lfs diff=lfs merge=lfs -text
@@ -0,0 +1,65 @@
1
+ name: Checks
2
+
3
+ on:
4
+ push:
5
+ branches: [main, dev/**, feature/**]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ checks:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ['3.11', '3.12', '3.13']
15
+
16
+ services:
17
+ redis:
18
+ image: redis:7-alpine
19
+ ports:
20
+ - 6379:6379
21
+ options: >-
22
+ --health-cmd "redis-cli ping"
23
+ --health-interval 10s
24
+ --health-timeout 5s
25
+ --health-retries 5
26
+
27
+ env:
28
+ TEST_REDIS_URL: redis://localhost:6379/15
29
+
30
+ steps:
31
+ - name: Checkout code
32
+ uses: actions/checkout@v6
33
+
34
+ - name: Set up Python ${{ matrix.python-version }}
35
+ uses: actions/setup-python@v6
36
+ with:
37
+ python-version: ${{ matrix.python-version }}
38
+
39
+ - name: Install uv
40
+ uses: astral-sh/setup-uv@v7
41
+ with:
42
+ version: '0.9.21'
43
+
44
+ - name: Install dependencies
45
+ run: |
46
+ uv sync --extra dev
47
+
48
+ - name: Run ruff linter
49
+ run: uv run ruff check .
50
+
51
+ - name: Run ruff formatter check
52
+ run: uv run ruff format --check .
53
+
54
+ - name: Run nbqa-ruff on notebooks
55
+ run: uv run nbqa ruff --exclude .venv --exclude tinker .
56
+
57
+ - name: Run pyright type checker
58
+ run: uv run pyright
59
+
60
+ - name: Run pytest
61
+ run: uv run pytest
62
+
63
+ # - name: Check uv lockfile is up to date
64
+ # run: |
65
+ # uv lock --check
@@ -0,0 +1,72 @@
1
+ services:
2
+ # use 2 nodes to simulate a cluster environment
3
+ tuft-node-1:
4
+ image: tuft-unittest:20260123
5
+ pull_policy: never
6
+ command: bash -c "source /opt/venv/bin/activate && uv pip install -e .[dev,backend,persistence] && ray start --head --dashboard-host 0.0.0.0 --include-dashboard true --block"
7
+ environment:
8
+ - HF_ENDPOINT=https://hf-mirror.com
9
+ - RAY_ADDRESS=auto
10
+ - TUFT_CHECKPOINT_DIR=/mnt/checkpoints
11
+ - TUFT_TEST_MODEL=/mnt/models/Qwen3-0.6B
12
+ - TUFT_TEST_MODEL_1=/mnt/models/Qwen3-0.6B
13
+ - TUFT_TEST_MODEL_2=/mnt/models/Qwen3-1.7B
14
+ - TEST_REDIS_URL=redis://tuft-redis:6379
15
+ - VIRTUAL_ENV=/opt/venv
16
+ working_dir: /workspace
17
+ networks:
18
+ - tuft-network
19
+ volumes:
20
+ - tuft-volume:/mnt
21
+ - ../../..:/workspace
22
+ shm_size: "64G"
23
+ deploy:
24
+ resources:
25
+ reservations:
26
+ devices:
27
+ - driver: nvidia
28
+ device_ids: ['0', '1']
29
+ capabilities: [gpu]
30
+
31
+ tuft-node-2:
32
+ image: tuft-unittest:20260123
33
+ pull_policy: never
34
+ command: bash -c "source /opt/venv/bin/activate && uv pip install -e .[dev,backend,persistence] && ray start --address=tuft-node-1:6379 --block"
35
+ environment:
36
+ - HF_ENDPOINT=https://hf-mirror.com
37
+ - TUFT_CHECKPOINT_DIR=/mnt/checkpoints
38
+ - TUFT_TEST_MODEL=/mnt/models/Qwen3-0.6B
39
+ - TUFT_TEST_MODEL_1=/mnt/models/Qwen3-0.6B
40
+ - TUFT_TEST_MODEL_2=/mnt/models/Qwen3-1.7B
41
+ - TEST_REDIS_URL=redis://tuft-redis:6379
42
+ - VIRTUAL_ENV=/opt/venv
43
+ working_dir: /workspace
44
+ volumes:
45
+ - tuft-volume:/mnt
46
+ - ../../..:/workspace
47
+ depends_on:
48
+ - tuft-node-1
49
+ networks:
50
+ - tuft-network
51
+ shm_size: "64G"
52
+ deploy:
53
+ resources:
54
+ reservations:
55
+ devices:
56
+ - driver: nvidia
57
+ device_ids: ['2', '3']
58
+ capabilities: [gpu]
59
+
60
+ tuft-redis:
61
+ image: redis:7.0
62
+ command: ["redis-server", "--save", "60", "1", "--loglevel", "warning"]
63
+ networks:
64
+ - tuft-network
65
+
66
+ networks:
67
+ tuft-network:
68
+ driver: bridge
69
+
70
+ volumes:
71
+ tuft-volume:
72
+ external: true
@@ -0,0 +1,77 @@
1
+ name: Build and Publish Docker Image
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ workflow_dispatch:
8
+ inputs:
9
+ ref:
10
+ description: 'The git ref (branch or tag) to build the Docker image from.'
11
+ required: true
12
+ version:
13
+ description: 'Version tag for the Docker image (e.g., 0.1.0)'
14
+ required: true
15
+
16
+ env:
17
+ REGISTRY: ghcr.io
18
+ IMAGE_NAME: ${{ github.repository }}
19
+
20
+ jobs:
21
+ build-and-push-image:
22
+ runs-on: self-hosted # TODO: setup a self-hosted runner on a machine with sufficient resources
23
+ timeout-minutes: 360
24
+ # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
25
+ permissions:
26
+ contents: read
27
+ packages: write
28
+ attestations: write
29
+ id-token: write
30
+ steps:
31
+ - name: Checkout repository
32
+ uses: actions/checkout@v5
33
+ with:
34
+ ref: ${{ github.event.inputs.ref || github.ref }}
35
+ path: tuft-${{ github.run_id }}
36
+ # Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
37
+ - name: Log in to the Container registry
38
+ uses: docker/login-action@v2
39
+ with:
40
+ registry: ${{ env.REGISTRY }}
41
+ username: ${{ github.actor }}
42
+ password: ${{ secrets.GITHUB_TOKEN }}
43
+ # This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
44
+ - name: Extract metadata (tags, labels) for Docker
45
+ id: meta
46
+ uses: docker/metadata-action@v5
47
+ with:
48
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
49
+ tags: |
50
+ type=match,pattern=\d.\d.\d,enable=${{ github.event_name == 'release' }}
51
+ type=raw,value=${{ github.event.inputs.version }},enable=${{ github.event_name == 'workflow_dispatch' }}
52
+ # This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages.
53
+ # It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see [Usage](https://github.com/docker/build-push-action#usage) in the README of the `docker/build-push-action` repository.
54
+ # It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
55
+ - name: Build and push Docker image
56
+ id: push
57
+ uses: docker/build-push-action@v4
58
+ with:
59
+ context: tuft-${{ github.run_id }}
60
+ push: true
61
+ file: tuft-${{ github.run_id }}/docker/Dockerfile
62
+ shm-size: 128g
63
+ tags: ${{ steps.meta.outputs.tags }}
64
+ labels: ${{ steps.meta.outputs.labels }}
65
+
66
+ # This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see [Using artifact attestations to establish provenance for builds](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds).
67
+ - name: Generate artifact attestation
68
+ uses: actions/attest-build-provenance@v3
69
+ with:
70
+ subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
71
+ subject-digest: ${{ steps.push.outputs.digest }}
72
+ push-to-registry: true
73
+
74
+ - name: Cleanup workspace
75
+ if: always()
76
+ run: |
77
+ sudo rm -rf tuft-${{ github.run_id }} 2>/dev/null
@@ -0,0 +1,241 @@
1
+ name: Install Script
2
+
3
+ on:
4
+ push:
5
+ branches: [main, dev/**, feature/**]
6
+ paths:
7
+ - 'scripts/install.sh'
8
+ - '.github/workflows/install-script.yml'
9
+ pull_request:
10
+ branches: [main]
11
+ paths:
12
+ - 'scripts/install.sh'
13
+ - '.github/workflows/install-script.yml'
14
+
15
+ jobs:
16
+ test-install-script:
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ os: [ubuntu-latest, macos-latest]
21
+
22
+ runs-on: ${{ matrix.os }}
23
+
24
+ steps:
25
+ - name: Checkout code
26
+ uses: actions/checkout@v4
27
+
28
+ - name: Test install script syntax
29
+ run: bash -n scripts/install.sh
30
+
31
+ - name: Test install script help
32
+ run: bash scripts/install.sh --help
33
+
34
+ - name: Run install script (local source)
35
+ run: |
36
+ bash scripts/install.sh --local-source "$GITHUB_WORKSPACE"
37
+ env:
38
+ TUFT_HOME: ${{ runner.temp }}/tuft
39
+
40
+ - name: Verify tuft command exists
41
+ run: |
42
+ export PATH="${TUFT_HOME}/bin:$PATH"
43
+ which tuft
44
+ tuft --help
45
+ env:
46
+ TUFT_HOME: ${{ runner.temp }}/tuft
47
+
48
+ - name: Verify tuft version
49
+ run: |
50
+ export PATH="${TUFT_HOME}/bin:$PATH"
51
+ tuft version
52
+ env:
53
+ TUFT_HOME: ${{ runner.temp }}/tuft
54
+
55
+ - name: Verify Python environment
56
+ run: |
57
+ test -f "${TUFT_HOME}/venv/bin/python"
58
+ "${TUFT_HOME}/venv/bin/python" -c "import tuft; print('tuft imported successfully')"
59
+ env:
60
+ TUFT_HOME: ${{ runner.temp }}/tuft
61
+
62
+ - name: Test tuft (dry run - check config error)
63
+ run: |
64
+ export PATH="${TUFT_HOME}/bin:$PATH"
65
+ # Should fail with config error, not import error
66
+ tuft 2>&1 | grep -q "\-\-config" || tuft 2>&1 | grep -q "config"
67
+ env:
68
+ TUFT_HOME: ${{ runner.temp }}/tuft
69
+
70
+ - name: Clean up installation
71
+ run: rm -rf "${TUFT_HOME}"
72
+ env:
73
+ TUFT_HOME: ${{ runner.temp }}/tuft
74
+
75
+ test-install-default-with-backend:
76
+ runs-on: ubuntu-latest
77
+
78
+ steps:
79
+ - name: Checkout code
80
+ uses: actions/checkout@v4
81
+
82
+ - name: Run install script (default includes backend)
83
+ run: |
84
+ bash scripts/install.sh --local-source "$GITHUB_WORKSPACE"
85
+ env:
86
+ TUFT_HOME: ${{ runner.temp }}/tuft
87
+
88
+ - name: Verify backend dependencies installed
89
+ run: |
90
+ "${TUFT_HOME}/venv/bin/python" -c "import peft; print('peft imported successfully')"
91
+ "${TUFT_HOME}/venv/bin/python" -c "import redis; print('redis imported successfully')"
92
+ env:
93
+ TUFT_HOME: ${{ runner.temp }}/tuft
94
+
95
+ - name: Clean up installation
96
+ run: rm -rf "${TUFT_HOME}"
97
+ env:
98
+ TUFT_HOME: ${{ runner.temp }}/tuft
99
+
100
+ test-install-without-backend:
101
+ runs-on: ubuntu-latest
102
+
103
+ steps:
104
+ - name: Checkout code
105
+ uses: actions/checkout@v4
106
+
107
+ - name: Run install script without backend
108
+ run: |
109
+ bash scripts/install.sh --local-source "$GITHUB_WORKSPACE" --without-backend
110
+ env:
111
+ TUFT_HOME: ${{ runner.temp }}/tuft
112
+
113
+ - name: Verify minimal install (no peft)
114
+ run: |
115
+ # peft should NOT be installed in minimal mode
116
+ "${TUFT_HOME}/venv/bin/python" -c "import peft" 2>&1 && exit 1 || echo "peft not installed (expected)"
117
+ # tuft should still be importable
118
+ "${TUFT_HOME}/venv/bin/python" -c "import tuft; print('tuft imported successfully')"
119
+ env:
120
+ TUFT_HOME: ${{ runner.temp }}/tuft
121
+
122
+ - name: Clean up installation
123
+ run: rm -rf "${TUFT_HOME}"
124
+ env:
125
+ TUFT_HOME: ${{ runner.temp }}/tuft
126
+
127
+ test-wrapper-commands:
128
+ runs-on: ubuntu-latest
129
+
130
+ steps:
131
+ - name: Checkout code
132
+ uses: actions/checkout@v4
133
+
134
+ - name: Install tuft
135
+ run: bash scripts/install.sh --local-source "$GITHUB_WORKSPACE"
136
+ env:
137
+ TUFT_HOME: ${{ runner.temp }}/tuft
138
+
139
+ - name: Test help command
140
+ run: |
141
+ export PATH="${TUFT_HOME}/bin:$PATH"
142
+ tuft help
143
+ env:
144
+ TUFT_HOME: ${{ runner.temp }}/tuft
145
+
146
+ - name: Test version command
147
+ run: |
148
+ export PATH="${TUFT_HOME}/bin:$PATH"
149
+ tuft version
150
+ env:
151
+ TUFT_HOME: ${{ runner.temp }}/tuft
152
+
153
+ - name: Test upgrade command
154
+ run: |
155
+ export PATH="${TUFT_HOME}/bin:$PATH"
156
+ tuft upgrade
157
+ env:
158
+ TUFT_HOME: ${{ runner.temp }}/tuft
159
+
160
+ - name: Clean up installation
161
+ run: rm -rf "${TUFT_HOME}"
162
+ env:
163
+ TUFT_HOME: ${{ runner.temp }}/tuft
164
+
165
+ test-clean-install:
166
+ runs-on: ubuntu-latest
167
+
168
+ steps:
169
+ - name: Checkout code
170
+ uses: actions/checkout@v4
171
+
172
+ - name: Initial install
173
+ run: |
174
+ bash scripts/install.sh --local-source "$GITHUB_WORKSPACE" --without-backend
175
+ env:
176
+ TUFT_HOME: ${{ runner.temp }}/tuft
177
+
178
+ - name: Create marker file to verify clean
179
+ run: |
180
+ echo "marker" > "${TUFT_HOME}/marker.txt"
181
+ test -f "${TUFT_HOME}/marker.txt"
182
+ env:
183
+ TUFT_HOME: ${{ runner.temp }}/tuft
184
+
185
+ - name: Reinstall with --clean
186
+ run: |
187
+ bash scripts/install.sh --local-source "$GITHUB_WORKSPACE" --without-backend --clean
188
+ env:
189
+ TUFT_HOME: ${{ runner.temp }}/tuft
190
+
191
+ - name: Verify marker file was removed
192
+ run: |
193
+ # Marker file should be gone after --clean
194
+ test ! -f "${TUFT_HOME}/marker.txt"
195
+ # But tuft should still be installed
196
+ "${TUFT_HOME}/venv/bin/python" -c "import tuft; print('tuft imported successfully')"
197
+ env:
198
+ TUFT_HOME: ${{ runner.temp }}/tuft
199
+
200
+ - name: Clean up installation
201
+ run: rm -rf "${TUFT_HOME}"
202
+ env:
203
+ TUFT_HOME: ${{ runner.temp }}/tuft
204
+
205
+ test-install-backend-command:
206
+ runs-on: ubuntu-latest
207
+
208
+ steps:
209
+ - name: Checkout code
210
+ uses: actions/checkout@v4
211
+
212
+ - name: Install without backend first
213
+ run: |
214
+ bash scripts/install.sh --local-source "$GITHUB_WORKSPACE" --without-backend
215
+ env:
216
+ TUFT_HOME: ${{ runner.temp }}/tuft
217
+
218
+ - name: Verify peft is NOT installed
219
+ run: |
220
+ "${TUFT_HOME}/venv/bin/python" -c "import peft" 2>&1 && exit 1 || echo "peft not installed (expected)"
221
+ env:
222
+ TUFT_HOME: ${{ runner.temp }}/tuft
223
+
224
+ - name: Run install-backend command
225
+ run: |
226
+ export PATH="${TUFT_HOME}/bin:$PATH"
227
+ tuft install-backend
228
+ env:
229
+ TUFT_HOME: ${{ runner.temp }}/tuft
230
+
231
+ - name: Verify backend dependencies now installed
232
+ run: |
233
+ "${TUFT_HOME}/venv/bin/python" -c "import peft; print('peft imported successfully')"
234
+ "${TUFT_HOME}/venv/bin/python" -c "import redis; print('redis imported successfully')"
235
+ env:
236
+ TUFT_HOME: ${{ runner.temp }}/tuft
237
+
238
+ - name: Clean up installation
239
+ run: rm -rf "${TUFT_HOME}"
240
+ env:
241
+ TUFT_HOME: ${{ runner.temp }}/tuft
@@ -0,0 +1,56 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ ref:
7
+ description: 'Git ref to checkout (branch, tag, or commit SHA)'
8
+ required: true
9
+ default: 'main'
10
+ type: string
11
+
12
+ jobs:
13
+ build:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - name: Checkout code
17
+ uses: actions/checkout@v6
18
+ with:
19
+ ref: ${{ inputs.ref }}
20
+
21
+ - name: Set up Python
22
+ uses: actions/setup-python@v6
23
+ with:
24
+ python-version: '3.11'
25
+
26
+ - name: Install uv
27
+ uses: astral-sh/setup-uv@v7
28
+ with:
29
+ version: '0.9.21'
30
+
31
+ - name: Build package
32
+ run: uv build
33
+
34
+ - name: Upload build artifacts
35
+ uses: actions/upload-artifact@v4
36
+ with:
37
+ name: dist
38
+ path: dist/
39
+
40
+ publish:
41
+ needs: build
42
+ runs-on: ubuntu-latest
43
+ environment:
44
+ name: pypi
45
+ url: https://pypi.org/project/tuft/
46
+ permissions:
47
+ id-token: write
48
+ steps:
49
+ - name: Download build artifacts
50
+ uses: actions/download-artifact@v4
51
+ with:
52
+ name: dist
53
+ path: dist/
54
+
55
+ - name: Publish to PyPI
56
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,103 @@
1
+ name: unittest
2
+
3
+ on:
4
+ issue_comment:
5
+ types: [created]
6
+
7
+ permissions:
8
+ contents: write
9
+ checks: write
10
+ pull-requests: write
11
+
12
+ jobs:
13
+ unittest:
14
+ # only run on pull request
15
+ if: ${{ github.event.issue.pull_request && (startsWith(github.event.comment.body, '/unittest')) && (github.event.comment.author_association == 'COLLABORATOR' || github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'OWNER') }}
16
+ runs-on: self-hosted
17
+
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ with:
21
+ fetch-depth: 0
22
+ path: tuft-${{ github.run_id }}
23
+ ref: refs/pull/${{ github.event.issue.number }}/head
24
+
25
+ - name: Setup docker compose
26
+ working-directory: tuft-${{ github.run_id }}/.github/workflows/docker
27
+ run: |
28
+ docker compose up -d
29
+ sleep 15s
30
+
31
+ - name: Check ray status
32
+ working-directory: tuft-${{ github.run_id }}/.github/workflows/docker
33
+ run: |
34
+ MAX_RETRIES=20
35
+ RETRY_INTERVAL=5
36
+ for i in $(seq 1 $MAX_RETRIES); do
37
+ if docker compose exec tuft-node-1 bash -c "source /opt/venv/bin/activate && ray status" \
38
+ && docker compose exec tuft-node-2 bash -c "source /opt/venv/bin/activate && ray status"; then
39
+ break
40
+ fi
41
+ echo "Waiting for ray cluster to be ready... ($i/$MAX_RETRIES)"
42
+ sleep $RETRY_INTERVAL
43
+ if [ "$i" -eq "$MAX_RETRIES" ]; then
44
+ echo "Ray cluster failed to start after $MAX_RETRIES retries."
45
+ exit 1
46
+ fi
47
+ done
48
+
49
+ - name: Run unittest
50
+ working-directory: tuft-${{ github.run_id }}/.github/workflows/docker
51
+ # set a github env variable to indicate tests were run, so that subsequent steps can check it
52
+ run: |
53
+ echo "tests_run=true" >> $GITHUB_ENV
54
+ docker compose exec tuft-node-1 bash -c "source /opt/venv/bin/activate && pytest tests -v -s --gpu --basetemp /mnt/checkpoints --ctrf report.json"
55
+
56
+ - name: Convert report.json time to ms
57
+ working-directory: tuft-${{ github.run_id }}
58
+ if: env.tests_run == 'true' || failure()
59
+ run: |
60
+ REPORT=report.json
61
+ if [ -f "$REPORT" ]; then
62
+ jq '(.results.tests[] | .duration, .start, .stop) |= (. * 1000) | (.results.summary.start, .results.summary.stop) |= (. * 1000)' "$REPORT" > "$REPORT.tmp" && mv "$REPORT.tmp" "$REPORT"
63
+ fi
64
+
65
+ - name: Clean checkpoint dir
66
+ working-directory: tuft-${{ github.run_id }}/.github/workflows/docker
67
+ if: always()
68
+ run: |
69
+ docker compose exec tuft-node-1 rm -rf /mnt/checkpoints/*
70
+ continue-on-error: true
71
+
72
+ - name: Upload test results
73
+ if: env.tests_run == 'true' || failure()
74
+ uses: actions/upload-artifact@v4
75
+ with:
76
+ name: pytest-results
77
+ path: tuft-${{ github.run_id }}/report.json
78
+ continue-on-error: true
79
+
80
+ - name: Publish Test Report
81
+ if: env.tests_run == 'true' || failure()
82
+ uses: ctrf-io/github-test-reporter@v1
83
+ with:
84
+ report-path: tuft-${{ github.run_id }}/report.json
85
+ summary: true
86
+ pull-request: false
87
+ issue: ${{ github.event.issue.number }}
88
+ env:
89
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
90
+ continue-on-error: true
91
+
92
+ - name: Remove docker compose
93
+ working-directory: tuft-${{ github.run_id }}/.github/workflows/docker
94
+ if: always()
95
+ run: |
96
+ docker compose down --remove-orphans
97
+ continue-on-error: true
98
+
99
+ - name: Cleanup workspace
100
+ if: always()
101
+ run: |
102
+ rm -rf tuft-${{ github.run_id }} 2>/dev/null
103
+ continue-on-error: true
tuft-0.1.1/.gitignore ADDED
@@ -0,0 +1,72 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Distribution / packaging
7
+ .Python
8
+ build/
9
+ develop-eggs/
10
+ dist/
11
+ downloads/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ *.egg-info/
19
+ .installed.cfg
20
+ *.egg
21
+
22
+ # Virtual environments
23
+ .venv/
24
+ venv/
25
+ ENV/
26
+ .env
27
+ .env.*
28
+
29
+ # PyInstaller
30
+ *.manifest
31
+ *.spec
32
+
33
+ # Unit test / coverage reports
34
+ .coverage
35
+ .coverage.*
36
+ .cache
37
+ nosetests.xml
38
+ coverage.xml
39
+ *.cover
40
+ *.py,cover
41
+ .hypothesis/
42
+ .pytest_cache/
43
+
44
+ # Jupyter Notebook
45
+ .ipynb_checkpoints
46
+
47
+ # mypy
48
+ .mypy_cache/
49
+ .dmypy.json
50
+ dmypy.json
51
+
52
+ # Ruff
53
+ .ruff_cache/
54
+
55
+ # Pyright
56
+ pyrightconfig.json
57
+
58
+ # IDEs / editors
59
+ .vscode/
60
+ .idea/
61
+ *.swp
62
+ *~
63
+ .DS_Store
64
+
65
+ # Ignore uv lockfile
66
+ uv.lock
67
+
68
+ # Ignore rdb files
69
+ *.rdb
70
+
71
+ # Sync history
72
+ .sync_history
tuft-0.1.1/.gitmodules ADDED
File without changes