Это третья статья серии «AI без магии». В первой разобрали, что LLM — это огромный авторегрессивный предсказатель токенов. Во второй — что значит «думать по одному токену» и почему модель галлюцинирует. Теперь ныряем глубже: как именно текст превращается в числа, с которыми работает модель.
Зачем вообще нужны числа
Нейросеть умеет одно — умножать большие матрицы из чисел и применять к ним нелинейные функции. Буквы и слова она понимать не умеет. Поэтому первое, что делает любая LLM с вашим запросом, — переводит текст в числа. И не просто «buchstabe → ASCII код», а в два этапа.
Этап 1 — токенизатор: разбивает текст на куски (токены) и присваивает каждому целое число. «Привет, как дела?» → [Пр, ивет, ,, как, дела, ?] → [3914, 6128, 11, 1495, 1872, 30].
Этап 2 — эмбеддинг-слой: каждое число заменяется на длинный вектор из вещественных чисел длиной 768, 4096 или даже 12288. Эти векторы — вход для всей остальной модели.
То есть путь такой: текст → токены (целые числа) → векторы. Дальше с векторами уже разбирается attention и трансформер. Но сначала — про оба этапа по отдельности.
BPE: как появился словарь токенов
Здесь возникает первый дизайн-вопрос: на какие куски резать текст? Варианты:
— По буквам. Словарь крошечный (~30-100 символов), но цепочки получаются гигантские. Слово «strawberry» — 10 шагов модели вместо одного. Дорого.
— По словам. Цепочки короткие, но словарь раздувается до миллионов записей, и любая опечатка («strawbery») превращается в неизвестный токен.
— Что-то посередине. Частые слова — целиком, редкие — на куски. Это и есть BPE (Byte Pair Encoding) — алгоритм, на котором стоят GPT-2, GPT-3, GPT-4, Claude, Llama, почти всё.
Идея простая: не угадываем заранее, а смотрим на корпус текстов и итеративно склеиваем самые частые пары символов в один токен.
В реальности GPT-2 стартует с 256 байт (любой Unicode-символ можно представить как набор байт) и делает ~50000 таких слияний. Получается словарь из ~50257 токенов, где «the», «hello», «def» — целые токены, а слово «antidisestablishmentarianism» собирается из кусков.
Что на самом деле видит GPT
Давайте посмотрим на конкретные числа. Прогоняем через tiktoken (это официальная библиотека OpenAI) одну и ту же фразу на двух языках:
Это объясняет несколько практических вещей:
— Токены — единица оплаты. Один и тот же запрос по-русски стоит в API в 1.5-3 раза дороже, чем по-английски, и быстрее упирается в лимит контекста. Поэтому многие приложения внутри переводят запросы на английский.
— Эмодзи и редкие символы часто превращаются в 3-4 токена каждый. Один смайлик на эмодзи-стене может «съесть» десяток токенов.
— Проблема с буквами в словах (помните «сколько R в strawberry» из прошлого поста?) ровно отсюда: модель видит не последовательность букв s-t-r-a-w-b-e-r-r-y, а три токена [str][aw][berry]. Цепочка букв исчезает уже на этапе токенизации.
Новая кодировка o200k_base (GPT-4o, GPT-5) вдвое лучше работает с русским — на нашем пангаме 19 токенов вместо 36. Но даже она проигрывает английскому на ~2× по плотности.
Эмбеддинг: токен → вектор
Окей, текст превратили в список целых чисел: [3914, 6128, 11, 1495, 1872, 30]. Что с ними делать дальше? Просто скормить в матрицу — плохая идея: число 3914 ничем не лучше и не хуже числа 6128, между ними нет смысловой близости. ID — это просто адрес.
Поэтому первый слой LLM — embedding layer. Это огромная таблица:
— строк: размер словаря (~50000 для GPT-2, ~200000 для GPT-4o); — столбцов: размерность вектора (768 для маленького GPT-2, 12288 для GPT-3, ~16000+ для современных моделей).
Каждый токен ID заменяется на строку из этой таблицы — длинный вектор вещественных чисел. На старте обучения там просто случайные числа. Но в процессе тренировки эти числа подкручиваются вместе со всей моделью так, чтобы похожие по смыслу токены получали похожие векторы.
И тут начинается самое интересное.
Геометрия смысла
Если спроецировать обученные эмбеддинги в 2D (например, через t-SNE или UMAP), окажется, что слова кучкуются по смыслу. Птицы — рядом друг с другом. Страны — отдельным кластером. Времена года — своим. Эта картинка из учебника Раски стала классикой:
Это и есть самое знаменитое наблюдение про эмбеддинги, которое в 2013 году опубликовал Mikolov et al. в работе про word2vec: операции над векторами слов имеют смысл.
king − man + woman ≈ queen
Paris − France + Italy ≈ Rome
walking − walk + swim ≈ swimming
То есть в пространстве эмбеддингов есть устойчивые направления: «пол», «столица», «прошедшее время». И их можно складывать с любым словом.
Звучит как магия — но это не магия. Модель училась на миллиардах текстов, где встречалось «Paris is the capital of France» и «Rome is the capital of Italy». Чтобы научиться предсказывать такие фразы, ей пришлось закодировать отношение «столица» как воспроизводимое направление в векторном пространстве. Иначе бы она не справилась с задачей предсказания.
Маленькое честное уточнение: классический пример с king − man + woman = queen работает только потому, что алгоритм при поиске ближайшего вектора исключает исходные слова из ответа. Если этого не делать, ближайшим к king − man + woman окажется… сам king. Просто queen — на втором месте. Но идея — что направления имеют смысл — от этого не ломается.
Контекстные эмбеддинги: один токен — много векторов
Word2vec (и его наследники: GloVe, fastText) выдавал один вектор на слово. Слово «коса» — один вектор, что бы оно ни значило: волосы, инструмент или песчаную полосу. Это статические эмбеддинги.
Современные LLM работают иначе. Эмбеддинг-слой даёт стартовый вектор — но дальше этот вектор проходит через десятки слоёв трансформера, и на каждом слое смешивается с векторами окружающих токенов. К моменту, когда токен «коса» добирается до выхода модели, его вектор уже зависит от того, шла ли речь о парикмахерской, поле или пляже.
Это и есть контекстные эмбеддинги. Один и тот же токен — разные векторы в зависимости от соседей. Именно поэтому LLM так хорошо различает омонимы и понимает иронию.
А механизм, который делает это смешивание, называется attention. Это наша следующая статья.
Что мы теперь знаем
Соберём картину.
Модель не работает с буквами и словами — она работает с токенами (целые числа из словаря на ~50000-200000 записей) и с эмбеддингами (вектор из ~1000-15000 чисел на каждый токен). Словарь токенов строится один раз на корпусе текстов алгоритмом BPE: частые подстроки склеиваются в отдельные токены, редкие остаются разрезанными на куски.
Эмбеддинг — это просто строка в гигантской таблице, обучаемой вместе с моделью. После обучения в этой таблице обнаруживается красивая геометрия: похожие по смыслу слова — рядом, отношения между словами — повторяющиеся направления в пространстве. Это не задумывалось специально — это побочный эффект задачи «предскажи следующий токен».
Но статические эмбеддинги — это только начало. Дальше векторы должны поговорить друг с другом, чтобы каждый токен «увидел» контекст. Это делает attention — и в следующей статье мы посмотрим на него подробно.
- Implementing A Byte Pair Encoding (BPE) Tokenizer From Scratch Подробный разбор BPE с пошаговым примером и кодом.
- Efficient Estimation of Word Representations in Vector Space Оригинальная работа word2vec, откуда пошёл пример king − man + woman ≈ queen.
- King − Man + Woman = King? (а не Queen) Честное уточнение: трюк работает только потому, что алгоритм исключает исходные слова из ответа.