Обучение правил и применение правил разделены
Во время encode новый текст не переобучает tokenizer. Строка превращается в UTF-8 bytes, затем ранее выученные пары применяются в порядке рангов. На decode IDs раскрываются в byte sequences, все bytes соединяются и декодируются одним UTF-8 проходом.
Почему нельзя декодировать каждый token отдельно и склеить строки? Некоторые tokens содержат лишь часть многобайтного знака. Подстановка Unicode replacement character U+FFFD необратимо повредит текст. Поэтому основная проверка:
Это равенство относится к допустимым Unicode-строкам нашего tokenizer без скрытой нормализации. Пробелы, line breaks и начальный BOM сохраняются. Пустая строка кодируется пустым списком и обратно; пустой training corpus для обучения merges отдельно отклоняется.
Эксперимент. Скопируйте полученные IDs в режим ручного decode. Измените один ID на неизвестный или сформируйте некорректную UTF-8 последовательность: должна появиться понятная ошибка, не ложный «успешный roundtrip». Byte fallback позволяет представлять любой валидный текст, но не гарантирует валидность произвольной случайной последовательности bytes.
Легко ошибиться. Decode произвольных IDs не обязан вернуть грамматичный текст. Decoder vocabulary и tokenizer vocabulary должны совпадать по содержимому и порядку. Если переобучить merges, сохранив старые веса embedding, соответствие строк может нарушиться.