yum-slop/TaSTT
Free self-hosted STT for VRChat.
git clone https://git.yummers.dev/yum-slop/TaSTT
f6b93a2
master
1from math import ceil ,floor 2from PIL import Image 3from unidecode import unidecode 4import sentencepiece as spm 5 6IMG_RES = 512 # square image 7 8def get_tokenizer (): 9use_sentencepiece = True 10 11if not use_sentencepiece : 12from tokenizers import Tokenizer 13tokenizer_json = "./custom_wordpiece_tokenizer_65k/tokenizer.json" 14f"Loading Tokenizers library tokenizer from: { tokenizer_json } " ) 15return Tokenizer .from_file (tokenizer_json ) 16else : 17model_path = "./custom_unigram_tokenizer_65k/unigram.model" 18f"Loading SentencePiece tokenizer from: { model_path } " ) 19sp = spm .SentencePieceProcessor () 20sp .load (model_path ) 21f"Successfully loaded SentencePiece model. Vocab size: { sp . get_piece_size () } " ) 22return sp 23 24def get_words (): 25tokenizer = get_tokenizer () 26 27f"vocabulary size: { tokenizer . get_piece_size () } " ) 28# sp_space = sentencepiece space. 29# A special character sentencepiece uses to represent spaces before words. 30sp_space = chr (9601 ) 31words = [] 32 33# Accumulate words into a list, indexed by the token number. Sanitize them as 34# you go. 35for i in range (tokenizer .get_piece_size ()): 36word = tokenizer .id_to_piece (i ) 37tok = i 38#print(f" Original token ({tok}): {repr(word)} ({' '.join(str(ord(c)) for c in word)})") 39word_sanitized = "" 40# Dirty hack: convert non-ASCII characters to nearest ASCII equivalent 41for c in word : 42if ord (c )> 127 and c != sp_space : 43c_plain = unidecode (c ) 44f" Resolved { c } to { c_plain } " ) 45word_sanitized += c_plain 46else : 47word_sanitized += c 48# Replace sp_space with ' ' 49word_sanitized = word_sanitized .replace (sp_space ,' ' ) 50#print(f" {tok}: {word_sanitized}") 51words .append (word_sanitized ) 52 53# Special word: empty string. SentencePiece doesn't support this natively. 54words .append ('' ) 55 56return words 57 58# Fold a flat index into a IMG_RESxIMG_RES box. Return the (x,y) coordinate of 59# the folded index. 60def fold_idx (flat_idx ): 61return (flat_idx % IMG_RES ,int (floor (flat_idx / IMG_RES ))) 62 63def unfold_idx (coord ): 64return coord [0 ]+ coord [1 ]* IMG_RES 65 66assert unfold_idx (fold_idx (1533125 ))== 1533125 67assert unfold_idx (fold_idx (8538235 ))== 8538235 68assert fold_idx (unfold_idx ((192 ,235 )))== (192 ,235 ) 69assert fold_idx (unfold_idx ((83 ,388 )))== (83 ,388 ) 70 71def generate_lut (words ,filename ): 72# Write the texture header. 73black = (0 ,0 ,0 ,255 ) 74img = Image .new ('RGBA' , (IMG_RES ,IMG_RES ),black ) 75 76# The header is `len(words)` slots long. Thus the actual LUT content starts at 77# the index `len(words)`. 78pixel_data = img .load () 79lut_ptr = len (words ) 80for i in range (0 ,len (words )): 81# Get pointer to the actual word data. 82tok_ptr = lut_ptr 83tok_len = len (words [i ]) 84rgba = ((tok_ptr >> 0 )& 0xFF , 85 (tok_ptr >> 8 )& 0xFF , 86 (tok_ptr >> 16 )& 0xFF , 87tok_len ) 88f"Writing { rgba } to { i } / { fold_idx ( i ) } " ) 89idx_x ,idx_y = fold_idx (i ) 90pixel_data [idx_x ,idx_y ]= rgba 91 92for j in range (0 ,ceil (tok_len / 4.0 )): 93quad_ptr = tok_ptr + j 94tok_0 = ord (words [i ][j * 4 ]) 95tok_1 = ord (words [i ][j * 4 + 1 ]if tok_len > j * 4 + 1 else ' ' ) 96tok_2 = ord (words [i ][j * 4 + 2 ]if tok_len > j * 4 + 2 else ' ' ) 97tok_3 = ord (words [i ][j * 4 + 3 ]if tok_len > j * 4 + 3 else ' ' ) 98rgba = (tok_0 ,tok_1 ,tok_2 ,tok_3 ) 99idx_x ,idx_y = fold_idx (quad_ptr ) 100f" Writing { rgba } to { quad_ptr } / { fold_idx ( quad_ptr ) } " ) 101pixel_data [idx_x ,idx_y ]= rgba 102 103# Advance the LUT ptr. Since we store 4 chars per pixel (RGBA), we advance 104# it by ceil(tok_len/4). 105lut_ptr += int (ceil (tok_len / 4.0 )) 106 107pretty = False 108if pretty : 109for y in range (0 ,IMG_RES ): 110for x in range (0 ,IMG_RES ): 111rgba = pixel_data [x ,y ] 112pixel_data [x ,y ]= (rgba [0 ],rgba [1 ],rgba [2 ],255 ) 113 114f"Saving to { filename } " ) 115img .save (filename ) 116 117if __name__ == "__main__" : 118words = get_words () 119generate_lut (words ,"bpe_lut.png" )