# Based on code from ComfyUI-Florence2 by Jukka Seppänen (kijai), MIT License
import os
from tokenizers import Tokenizer, AddedToken
class Florence2Tokenizer:
def __init__(self, model_path):
tokenizer_path = os.path.join(model_path, "tokenizer.json")
self.tokenizer = Tokenizer.from_file(tokenizer_path)
self._add_special_tokens()
# Standard token IDs
self.pad_token_id = 1
self.bos_token_id = 0
self.eos_token_id = 2
def _add_special_tokens(self):
"""Add Florence2-specific special tokens."""
special_tokens = ['', '', '', '']
special_tokens += [f'' for x in range(1000)]
special_tokens += [
'', '', '', '', '', '',
'', '', '', '', '',
'', '', '',
'', '', '',
'', '', ''
]
added = [AddedToken(t, special=True) for t in special_tokens]
self.tokenizer.add_special_tokens(added)
def encode(self, text):
"""Encode text to token ids. Returns dict with 'input_ids' tensor."""
import torch
encoding = self.tokenizer.encode(text)
return {"input_ids": torch.tensor([encoding.ids], dtype=torch.long)}
def decode(self, token_ids, skip_special_tokens=False):
"""Decode token ids to text."""
if hasattr(token_ids, 'tolist'):
token_ids = token_ids.tolist()
if isinstance(token_ids[0], list):
token_ids = token_ids[0]
return self.tokenizer.decode(token_ids, skip_special_tokens=skip_special_tokens)
def batch_decode(self, token_ids_batch, skip_special_tokens=False):
"""Decode a batch of token id sequences."""
results = []
if hasattr(token_ids_batch, 'tolist'):
token_ids_batch = token_ids_batch.tolist()
for ids in token_ids_batch:
results.append(self.tokenizer.decode(ids, skip_special_tokens=skip_special_tokens))
return results
@property
def all_special_tokens(self):
"""Return set of all special token strings. Needed by post-processor."""
added = self.tokenizer.get_added_tokens_decoder()
tokens = set()
for token_obj in added.values():
tokens.add(str(token_obj))
# Also add the built-in ones
tokens.update({'', '', '', '', ''})
return tokens
@property
def vocab_size(self):
return self.tokenizer.get_vocab_size()