Skip to content
This repository was archived by the owner on Jun 3, 2025. It is now read-only.

Commit 6614ef1

Browse files
committed
Merge branch 'prompt-mask' of github.com:neuralmagic/sparseml into prompt-mask
2 parents 5b76267 + 7273529 commit 6614ef1

File tree

6 files changed

+114
-79
lines changed

6 files changed

+114
-79
lines changed

.github/workflows/build-wheel.yml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
name: Build PyPi Wheel
2+
on:
3+
pull_request:
4+
types: [opened, synchronize, reopened]
5+
branches:
6+
- main
7+
- 'release/[0-9]+.[0-9]+'
8+
push:
9+
branches:
10+
- main
11+
release:
12+
types: [created, published]
13+
schedule:
14+
- cron: '0 0 * * *'
15+
16+
permissions:
17+
id-token: write
18+
contents: read
19+
20+
concurrency:
21+
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
22+
cancel-in-progress: true
23+
24+
# if not dev or release, will create a nightly build
25+
# everything is pushed to internal unless created through a nightly scheduled cron job which creates the build or
26+
# missing release tag workflow/needs to be added in
27+
env:
28+
INTERNAL: ${{ github.event_name != 'schedule' && github.event_name != 'release'}}
29+
RELEASE: ${{ github.event_name =='release' || (startsWith(github.base_ref, 'release/') && github.event_name == 'pull_request')}}
30+
DEV: ${{ github.base_ref == 'main' && github.event_name == 'pull_request'}}
31+
NAME: ${{ github.event.number }}
32+
33+
jobs:
34+
build_and_push:
35+
runs-on: ubuntu-latest
36+
outputs:
37+
wheel: ${{ steps.push-wheel.outputs.wheel }}
38+
steps:
39+
- name: Checkout code
40+
uses: actions/checkout@v3
41+
- name: Login to s3
42+
uses: aws-actions/configure-aws-credentials@v2
43+
with:
44+
role-to-assume: ${{ secrets.AWS_WEBIDENTITY_FOR_GITHUB_ACTIONS }}
45+
aws-region: us-east-1
46+
- name: Build PyPi Wheel
47+
id: build-wheel
48+
uses: neuralmagic/nm-actions/actions/pypi_build@main
49+
with:
50+
dev: $DEV
51+
release: $RELEASE
52+
name: $NAME
53+
- name: Push to s3 bucket
54+
id: push-wheel
55+
uses: neuralmagic/nm-actions/actions/s3_push@main
56+
with:
57+
filename: dist/*.whl
58+
internal: $INTERNAL

_scratch/mask.py

Lines changed: 0 additions & 72 deletions
This file was deleted.

setup.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
# default variables to be overwritten by the version.py file
2222
is_release = None
23+
is_dev = None
2324
version = "unknown"
2425
version_major_minor = version
2526

@@ -28,7 +29,12 @@
2829
print(f"loaded version {version} from src/sparseml/version.py")
2930
version_nm_deps = f"{version_major_minor}.0"
3031

31-
_PACKAGE_NAME = "sparseml" if is_release else "sparseml-nightly"
32+
if is_release:
33+
_PACKAGE_NAME = "sparseml"
34+
elif is_dev:
35+
_PACKAGE_NAME = "sparseml-dev"
36+
else:
37+
_PACKAGE_NAME = "sparseml-nightly"
3238

3339
_deps = [
3440
"setuptools<=59.5.0",

src/sparseml/transformers/finetune/runner.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,11 @@
4040
)
4141
from sparseml.transformers.finetune.model_args import ModelArguments
4242
from sparseml.transformers.finetune.training_args import TrainingArguments
43-
from sparseml.utils.fsdp.helpers import is_fsdp_model, unwrap_and_export_model
43+
from sparseml.utils.fsdp.helpers import (
44+
find_and_move_state_dicts_to_cpu,
45+
is_fsdp_model,
46+
unwrap_and_export_model,
47+
)
4448

4549

4650
_LOGGER: logging.Logger = logging.getLogger(__name__)
@@ -175,6 +179,15 @@ def one_shot(self, stage: Optional[str] = None):
175179
output_dir=self._output_dir,
176180
tokenizer=self.tokenizer,
177181
)
182+
# only allow the main process move the state
183+
# dicts to cpu
184+
if self.trainer.accelerator.is_main_process:
185+
# assuming quantization is the last step
186+
# we no longer need the original model
187+
# and can safely delete it to save memory
188+
del self.trainer.model
189+
find_and_move_state_dicts_to_cpu(self._output_dir)
190+
178191
else:
179192
save_model_and_recipe(
180193
model=self.trainer.model,

src/sparseml/utils/fsdp/helpers.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import logging
1516
import operator
17+
from pathlib import Path
1618
from typing import Optional, Union
1719

1820

@@ -25,6 +27,7 @@
2527
except ImportError:
2628
FullyShardedDataParallel = None
2729

30+
import torch
2831
from torch.nn import Module
2932

3033
from sparseml.core.model import ModifiableModel
@@ -39,8 +42,11 @@
3942
"unwrap_and_export_model",
4043
"save_pretrained_fsdp",
4144
"get_fsdp_parent",
45+
"find_and_move_state_dicts_to_cpu",
4246
]
4347

48+
_LOGGER = logging.getLogger(__name__)
49+
4450

4551
def is_fsdp_model(model: Module) -> bool:
4652
"""
@@ -113,6 +119,27 @@ def unwrap_and_export_model(model, accelerator, output_dir, tokenizer):
113119
)
114120

115121

122+
def find_and_move_state_dicts_to_cpu(output_dir: str):
123+
"""
124+
Looks for state dicts in the output directory and overwrites them
125+
with cpu state dicts.
126+
127+
this is needed for quantized models trained with FSDP as the state dict
128+
contains device information, which can cause issues when loading the model
129+
using transformers AutoModel.from_pretrained(...) if the device information
130+
is not removed, assumes the state dicts are named pytorch_model*.bin
131+
"""
132+
133+
for model_file in Path(output_dir).rglob("pytorch_model*.bin"):
134+
loaded_dict = torch.load(model_file)
135+
for key, value in loaded_dict.items():
136+
if isinstance(value, torch.Tensor):
137+
loaded_dict[key] = value.cpu()
138+
139+
torch.save(loaded_dict, model_file)
140+
_LOGGER.info(f"Moved state dict {model_file} to cpu")
141+
142+
116143
def save_pretrained_fsdp(model, accelerator, output_dir, save_safetensors: bool = True):
117144
full_state_dict_config = FullStateDictConfig(offload_to_cpu=True, rank0_only=True)
118145
"""

src/sparseml/version.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,17 @@
2121

2222
version_base = "1.7.0"
2323
is_release = False # change to True to set the generated version as a release version
24+
is_dev = False
25+
dev_number = None
2426

2527

2628
def _generate_version():
27-
return (
28-
version_base
29-
if is_release
30-
else f"{version_base}.{date.today().strftime('%Y%m%d')}"
31-
)
29+
if is_release:
30+
return version_base
31+
elif is_dev:
32+
return f"{version_base}.dev{dev_number}"
33+
else:
34+
return f"{version_base}.{date.today().strftime('%Y%m%d')}"
3235

3336

3437
__all__ = [

0 commit comments

Comments
 (0)