Найти в Дзене
Артем Аполлон

4. Character-level tokenizer - Разработка языковой модели LLM с нуля на python

Character-level tokenizer: Python code: with open(‘wizard_of_oz_.txt’, ‘r’, encoding=’utf-8’) as f: text = f.read() chars = sorted(set(text)) print(chars) vocabulary_size = len(chars)
Токенизатор в контексте создания LLM с нуля Токенизатор — это компонент, который преобразует исходный текст в числовые токены (идентификаторы), понятные нейросети. В вашем примере реализован character-level tokenizer (побуквенный токенизатор), который работает на уровне отдельных символов. python
with open('wizard_of_oz.txt', 'r', encoding='utf-8') as f: text = f.read() python
chars = sorted(set(text)) python
vocabulary_size = len(chars) Исходный текст:
"Cat!" → Уникальные символы: ['!', 'C', 'a', 't'] → Словарь: text
{'!': 0, 'C': 1, 'a': 2, 't': 3} Токенизация:
"Cat!" → ``. Такой токенизатор — минимальная, но работоспособная основа для обучения LLM на уровне символов. В современных LLM (GPT, BERT) используются более сложные методы (Byte Pair Encoding), но character-level отлично подходит для уч
Оглавление


Character-level tokenizer:

Python code:

with open(‘wizard_of_oz_.txt’, ‘r’, encoding=’utf-8’) as f:

text = f.read()

chars = sorted(set(text))

print(chars)

vocabulary_size = len(chars)

Токенизатор в контексте создания LLM с нуля

Токенизатор — это компонент, который преобразует исходный текст в числовые токены (идентификаторы), понятные нейросети. В вашем примере реализован character-level tokenizer (побуквенный токенизатор), который работает на уровне отдельных символов.

Разбор кода:

python
with open('wizard_of_oz.txt', 'r', encoding='utf-8') as f: text = f.read()

  • Цель: Чтение исходного текста из файла wizard_of_oz.txt.
  • Результат: Весь текст сохраняется в переменную text как единая строка.

python
chars = sorted(set(text))

  • set(text): Создает множество уникальных символов из текста (удаляет дубликаты).
  • sorted(...): Сортирует символы в алфавитном порядке (например: ['\n', ' ', '!', 'A', 'B', ... 'z']).
  • Результат: Список chars содержит все уникальные символы из текста.

python
vocabulary_size = len(chars)

  • Цель: Рассчитывает размер словаря токенизатора.
  • Результат: vocabulary_size равен количеству уникальных символов в тексте (например, 65 для английского текста).

Как это работает в LLM

  1. Создание словаря:
    Каждому символу присваивается уникальный ID:python
    char_to_id = {char: idx
    for idx, char in enumerate(chars)} id_to_char = {idx: char for idx, char in enumerate(chars)}

    Пример: char_to_id['A'] = 12, id_to_char = 'A'.
  2. Токенизация текста:python
    tokens = [char_to_id[char]
    for char in text]
    Преобразует текст в последовательность чисел:
    "Hello" → ``.
  3. Обратное преобразование:python
    decoded_text = ''.join([id_to_char[id]
    for id in tokens])
    Восстанавливает текст из токенов.

Зачем это нужно?

  • Для нейросети: LLM обрабатывает только числа. Токенизатор переводит текст в числовую форму.
  • Character-level особенности:
    ✅ Простота реализации
    ✅ Работает с любыми символами (эмодзи, редкие алфавиты)
    ❌ Создает длинные последовательности (слово из 5 букв = 5 токенов)
    ❌ Хуже улавливает семантику слов (по сравнению с word-level или subword)

Пример работы

Исходный текст:
"Cat!" → Уникальные символы: ['!', 'C', 'a', 't'] → Словарь:

text
{'!': 0, 'C': 1, 'a': 2, 't': 3}

Токенизация:
"Cat!" → ``.

Такой токенизатор — минимальная, но работоспособная основа для обучения LLM на уровне символов. В современных LLM (GPT, BERT) используются более сложные методы (Byte Pair Encoding), но character-level отлично подходит для учебных моделей.

o4-mini

Токенизатор (tokenizer) в контексте разработки собственного языкового LLM — это компонент, который разбивает входной текст на минимальные единицы («токены») для последующей работы модели. Его основные задачи и особенности:

  1. Зачем нужен токенизатор
    Модели работают не с «сырой» строкой, а с числовыми представлениями токенов (ID).
    Токенизация позволяет стандартизировать вход: единообразно обрабатывать разные слова, символы и их сочетания.
  2. Виды токенизации
    Символьная (character-level): каждый символ — отдельный токен.
    Плюсы: простота, нет «неизвестных» токенов.
    Минусы: длинные последовательности, сложнее учить смысл.
    Словная (word-level): каждый словоформа — токен.
    Плюсы: интуитивно понятно.
    Минусы: огромный словарь, много «неизвестных» слов.
    Субсловная (subword-level): компромисс между двумя предыдущими.
    Например, алгоритмы Byte-Pair Encoding (BPE) или SentencePiece ( unigram ).
    Разбивают «редкие» слова на более мелкие куски, частые — оставляют целыми.
  3. Популярные алгоритмы субсловной токенизации
    BPE (Byte-Pair Encoding): многократно объединяет самые частые пары символов/субслов в один токен.
    WordPiece (используется в BERT): похож на BPE, но внутри модель считает частоты несколько иначе.
    SentencePiece (unigram model): строит словарь из возможных фрагментов и жёстко оптимизирует его по вероятности.
  4. Процесс работы токенизатора
    Предобработка текста: нормализация (нижний регистр, удаление лишних пробелов).
    Разбиение на предварительные «фрагменты» или символы.
    Применение модели (BPE/WordPiece/Unigram) для итоговой сборки наиболее частотных токенов.
    Преобразование токенов в числовые ID по заранее построенному словарю.
  5. Почему важно правильно выбрать/научить токенизатор
    Размер словаря: слишком маленький → модель «заточится» на частые фрагменты, но хуже поймёт редкие конструкции; слишком большой → высокие требования к памяти и вычислениям.
    Семантика: качественная токенизация позволяет модели легче улавливать морфологию, устойчивые сочетания и даже части смысловых «единиц» языка.
  6. Вывод
    Токенизатор — это мост между текстом и нейросетью. При самостоятельной сборке LLM нужно:
    решить, на каком уровне (символ/слово/субслово) токенизировать,
    подобрать или обучить алгоритм (BPE/WordPiece/SentencePiece),
    сохранить словарь токенов и обеспечить обратное преобразование (detokenization) для генерации текста.


Python code:
with open(‘wizard_of_oz_.txt’, ‘r’, encoding=’utf-8’) as f:

text = f.read()

chars = sorted(set(text))

print(chars)

vocabulary_size = len(chars)

string_to_int = {ch:i for i,ch in enumerate(chars)}

int_to_string = {i:ch for i,ch in enumerate(chars)}

encode = lambda s: [string_to_int[c] for c in s]

decode = lambda l: ''.join([int_to_string[i] for i in l])

Вот детальное объяснение каждого компонента кода для character-level токенизатора:

1. Чтение и подготовка данных

python
with open('wizard_of_oz.txt', 'r', encoding='utf-8') as f: text = f.read()

  • Цель: Чтение текстового файла в переменную text
  • Особенности:
    Файл открывается в режиме чтения ('r')
    Используется кодировка UTF-8 для поддержки любых символов
    text становится строкой со всем содержимым файла

python
chars = sorted(set(text))

  • set(text): Создает множество уникальных символов (убирает дубликаты)
  • sorted(...): Сортирует символы в алфавитном/числовом порядке
  • Результат: chars - отсортированный список уникальных символов (например: ['\n', ' ', '!', 'A', ... 'z'])

python
vocabulary_size = len(chars)

  • Цель: Расчет размера словаря токенизатора
  • Значение: Количество уникальных символов в тексте (например, 65 для английского текста)

2. Создание словарей преобразования

python
string_to_int = {ch:i
for i,ch in enumerate(chars)}

  • Структура: Генератор словаря (dictionary comprehension)
  • Логика:
    enumerate(chars) создает пары (индекс, символ)
    Для каждого символа ch в chars назначается индекс i
  • Результат:python
    {'\n': 0, ' ': 1, '!': 2, 'A': 3, ... 'z': 64}
  • Назначение: Преобразование символа → числовой ID

python
int_to_string = {i:ch
for i,ch in enumerate(chars)}

  • Обратное преобразование:
    Ключи: индексы i
    Значения: символы ch
  • Результат:python
    {0: '\n', 1: ' ', 2: '!', 3: 'A', ... 64: 'z'}
  • Назначение: Преобразование числового ID → символ

3. Функции кодирования/декодирования

python
encode =
lambda s: [string_to_int[c] for c in s]

  • Тип: Лямбда-функция (анонимная функция в одну строку)
  • Параметр: s - входная строка
  • Логика:
    Итерирует по каждому символу c в строке s
    Для каждого c находит соответствующий ID в string_to_int
    Создает список ID
  • Пример:python
    encode("Hello") → [40, 53, 57, 57, 62]

python
decode =
lambda l: ''.join([int_to_string[i] for i in l])

  • Параметр: l - список числовых ID
  • Логика:
    Для каждого ID i в списке l находит соответствующий символ
    Объединяет символы в строку с помощью ''.join()
  • Пример:python
    decode([40,53,57,57,62]) → "Hello"

4. Принцип работы токенизатора

  1. Кодирование текста:
    Текст разбивается на отдельные символы
    Каждый символ заменяется на уникальный числовой ID
    Результат: список чисел (токенов)
  2. Декодирование:
    Каждый числовой ID преобразуется обратно в символ
    Символы объединяются в исходную строку
  3. Особенности character-level:
    Каждый символ = 1 токен
    "Hello" (5 символов) → 5 токенов
    Пробелы, знаки препинания, спецсимволы - тоже токены

5. Полный цикл работы

python
# Исходный текст original = "Hello!"
# Кодирование encoded = encode(original) # [40,53,57,57,62,2]
# Декодирование decoded = decode(encoded) # "Hello!"
# Проверка original == decoded # True

6. Значение для LLM

  1. Числовое представление: Нейросети работают только с числами
  2. Словарь (vocabulary):
    chars - алфавит модели
    vocabulary_size - размер входного/выходного слоя нейросети
  3. Обратимость: Декодирование позволяет:
    Интерпретировать выход модели
    Преобразовать предсказания в текст
  4. Минимализм: Простейший способ токенизации, идеален для обучения основам

Этот токенизатор - фундаментальный компонент любой языковой модели, преобразующий текст в числовую форму, понятную нейросети, и обратно.