GemmaTokenizerFast inconsistent with Sentencepiece tokenizer
Author: jedreky
Pull request: no
Labels: name: bug

### System Info

Python3.12
Output of pip freeze:
```
certifi==2025.10.5
charset-normalizer==3.4.4
filelock==3.20.0
fsspec==2025.9.0
hf-xet==1.2.0
huggingface-hub==0.36.0
idna==3.11
numpy==2.3.4
packaging==25.0
protobuf==6.33.0
PyYAML==6.0.3
regex==2025.10.23
requests==2.32.5
safetensors==0.6.2
sentencepiece==0.2.1
tokenizers==0.22.1
tqdm==4.67.1
transformers==4.57.1
typing_extensions==4.15.0
urllib3==2.5.0
```

### Who can help?

@ArthurZucker @itazap 

### Information

- [ ] The official example scripts
- [x] My own modified scripts

### Tasks

- [ ] An officially supported task in the `examples` folder (such as GLUE/SQuAD, ...)
- [x] My own task or dataset (give details below)

### Reproduction

I have trained a small tokenizer using the sentencepiece library (https://github.com/google/sentencepiece). As output I got a .model and .vocab file. Then I wanted to instantiate the GemmaTokenizerFast using the .model file, but I got some unexpected results.
Perhaps I'm using in a wrong manner, but I expected that the input/output behaviour of GemmaTokenizerFast will be equivalent to the original sentence piece tokenizer, but this is not the case.

I have written this script to compare the behaviours:
```
import sentencepiece as spm
from transformers.models.gemma.tokenization_gemma_fast import GemmaTokenizerFast


print("Sentencepiece processor")
sp = spm.SentencePieceProcessor(model_file=f"test_tokenizer.model")
text = " HI my NamE"
out = sp.encode(text)
print(f"Encoded: {out}")

out_str = sp.encode(text, out_type=str)
print(f"Encoded as str: {out_str}")

decoded = sp.decode(out)
print(f"Decoded: {decoded}\n\n")


print("GemmaTokenizerFast")
tokenizer = GemmaTokenizerFast(vocab_file=f"test_tokenizer.model")
print(tokenizer)
out = tokenizer.encode(text)
print(f"Encoded: {out}")
decoded = tokenizer.decode(out)
print(f"Decoded: {decoded}")
```

And this is the output:
```
Sentencepiece processor
Encoded: [5, 33, 8, 5, 0, 5, 14, 0, 4]
Encoded as str: ['▁', 'H', 'I', '▁', 'my', '▁', 'N', 'am', 'E']
Decoded: HI  ⁇  N ⁇ E


GemmaTokenizerFast
GemmaTokenizerFast(name_or_path='', vocab_size=128, model_max_length=1000000000000000019884624838656, is_fast=True, padding_side='left', truncation_side='right', special_tokens={'bos_token': '<bos>', 'eos_token': '<eos>', 'unk_token': '<unk>', 'pad_token': '<pad>'}, clean_up_tokenization_spaces=False, added_tokens_decoder={
        0: AddedToken("<pad>", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),
        1: AddedToken("<eos>", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),
        2: AddedToken("<bos>", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),
        128: AddedToken("
", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),
        129: AddedToken("
", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),
        130: AddedToken("<unk>", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),
}
)
Encoded: [2, 5, 33, 8, 5, 3, 5, 14, 3, 4]
Decoded: <bos> HI S NSE
```

The first observation is that GemmaTokenizerFast instead of using the BOS/EOS tokens defined in .model file introduces its own ones. Ok, that's confusing but perhaps inconsequential.
But what I find really strange is that GemmaTokenizerFast doesn't handle the unk_token correctly. Basically, unknown pieces of text are mapped to token number 3, which gets decoded to "S" (which is the first non-special token in my dictionary).

Again, I'm not sure whether this is a bug or just I'm using the GemmaTokenizerFast in an incorrect manner, but the docstring for GemmaTokenizerFast reads:
```
Args:
        vocab_file (str, optional):
            [SentencePiece](https://github.com/google/sentencepiece) file (generally has a .model extension) that
            contains the vocabulary necessary to instantiate a tokenizer.
```
which I interpreted as "you can just plug in the .model file produced by sentencepiece".

I've attached the .vocab file for completeness.

[test_tokenizer.vocab.txt](https://github.com/user-attachments/files/23148347/test_tokenizer.vocab.txt)

### Expected behavior

I expected the behaviour of Sentenepiece tokenizer and GemmaTokenizerFast to be the same, but it's not.

Comments:
Btw, if this is not a bug, then perhaps someone could advise me how to use the output of sentenpiece to instantiate a tokenizer in Transformers 🙏 

This issue has been automatically marked as stale because it has not had recent activity. If you think this still needs to be addressed please comment on this thread.

Please note that issues that do not follow the [contributing guidelines](https://github.com/huggingface/transformers/blob/main/CONTRIBUTING.md) are likely to be ignored.