Skip to content

Commit 4fb4af1

Browse files
authored
fix: add distillation duplicate guard (#350)
* feat: add distillation duplicate guard * add normalization to added tokens
1 parent 4271e59 commit 4fb4af1

3 files changed

Lines changed: 17 additions & 3 deletions

File tree

‎model2vec/distill/distillation.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import logging
44
import os
55
import re
6-
from typing import cast
6+
from typing import Sequence, cast
77

88
from huggingface_hub.hf_api import model_info
99
from skeletoken import TokenizerModel
@@ -24,7 +24,7 @@
2424
def distill_from_model(
2525
model: PreTrainedModel,
2626
tokenizer: PreTrainedTokenizerFast,
27-
vocabulary: list[str] | None = None,
27+
vocabulary: Sequence[str] | None = None,
2828
device: str | None = None,
2929
pca_dims: PCADimType = 256,
3030
sif_coefficient: float | None = 1e-4,

‎model2vec/tokenizer/tokenizer.py‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import logging
44
import re
5+
from typing import Sequence
56

67
from skeletoken import TokenizerModel
78

@@ -10,7 +11,7 @@
1011

1112
def clean_and_create_vocabulary(
1213
model: TokenizerModel,
13-
vocabulary_to_add: list[str],
14+
vocabulary_to_add: Sequence[str],
1415
token_remove_regex: re.Pattern[str] | None,
1516
) -> TokenizerModel:
1617
"""Clean a vocabulary by removing duplicates and tokens that were already in the vocabulary.
@@ -43,6 +44,7 @@ def clean_and_create_vocabulary(
4344
seen_tokens = set(internal_tokens)
4445
tokens_to_add: list[str] = []
4546
added_tokens_to_add: list[str] = []
47+
seen_added = set()
4648
for token in vocabulary_to_add:
4749
preprocessed = preprocessor.preprocess(token)
4850
if len(preprocessed) < 1:
@@ -58,7 +60,15 @@ def clean_and_create_vocabulary(
5860
if token in model.vocabulary:
5961
# If the unprocessed token (incorrectly) is in the vocabulary, we should remove it.
6062
model = model.remove_token_from_vocabulary(token)
63+
if preprocessor.normalizer:
64+
token = preprocessor.normalizer.normalize_str(token)
65+
# We need to strip because our AddedTokens also get stripped
66+
token = token.strip()
67+
if token in seen_added:
68+
logger.warning(f"Normalized added token '{token}' was in the added vocabulary twice.")
69+
continue
6170
added_tokens_to_add.append(token)
71+
seen_added.add(token)
6272
continue
6373
token = preprocessed[0]
6474
if token in seen_tokens:

‎tests/test_distillation.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,10 @@ def test__post_process_embeddings(
319319
# Case: Only empty token (""), should return an empty list
320320
([""], [], ["empty"]),
321321
(["multi word token"], ["multi word token"], []),
322+
# Case: duplicate multi-word token, should only be added once
323+
(["multi word token", "multi word token"], ["multi word token"], ["twice"]),
324+
# Case: multi-word tokens that normalize to the same string, should only be added once
325+
(["Multi Word Token", "multi word token"], ["multi word token"], ["twice"]),
322326
],
323327
)
324328
def test_clean_and_create_vocabulary(

0 commit comments

Comments
 (0)