Когда я выкладывал первую главу этого цикла статей в свой телеграм-канал (@laxcity_lead), Anthropic только-только выпустили Agent Skills. И уже буквально в момент появления скиллов у меня было ощущение, что это самая значимая штука, которую они сделали за последнее время. Возможно, даже посерьёзнее, чем в своё время были MCP. Хотя нет — справедливости ради, точно серьёзнее. Не зря мой маркетплейс для Claude сейчас на 99% состоит из скиллов. Ну а почему именно скиллы являются самой важной штукой и какую роль они сыграли в битве за контекст — расскажу в этом цикле статей.

Изначально я предполагал, что это будет одна статья с обзором того что такое скиллы. Но пока писал — решил заодно расширить и собственные знания о том, как вообще устроены LLM (они же БЯМ — Большие Языковые Модели), и рассказать читателям о результатах своих исследований. Потому что для того, чтобы хорошо и продуктивно работать с агентами — я сейчас с уверенностью могу сказать — максимально важно понимать, как эти модели работают.

1. Автокомплит на стероидах

Чтобы понять, что же такого важного было сделано в момент внедрения скиллов, начать нам придётся очень издалека — буквально с разбора того, как работают наши оверхайпнутые железные дровосеки.

Я буду стараться упрощать вещи по-максимуму, так что не ругайтесь если что-то покажется слишком грубым приближением. Ну а если найдёте неточность или захотите подискутировать — пишите в комментариях здесь или в Telegram.

Сказать, что все существующие модели подходят под одно определение — было бы неправильно. Но большинство из тех, которыми вы так или иначе пользовались — GPT, Claude, Llama, Gemini и так далее — это авторегрессивные трансформеры. Или, если развернуть аббревиатуру GPT — Generative Pre-trained Transformer. По сути, это статистические машины для предсказания следующего токена на основе набора входящих токенов. И бытующее понимание о “современном искусственном интеллекте” как о Т9 на максималках — не является ошибкой само по себе. Просто уровень статистики, которым оперируют эти модели, находится за пределами способности восприятия любого человека. А статистика в таких масштабах творит чудеса — недаром модели сейчас умеют и писать код, и анализировать данные, и делать, строго говоря, примерно всё, что может делать человек с текстом. Если пнуть под правильным углом.

Я сейчас обозначил одну из основополагающих штук и вещь, на тему которой трясутся все, кто сидит на pay-as-you-go планах. Токен. Токен — единица информации, с которой работают модели. Если провести аналогию с человеком — у нас есть алфавиты тех языков, на которых мы разговариваем: 26 букв в английском, 33 в русском, и так далее. Так вот, в отличие от человека, словарь модели может быть разительно шире — словари, которыми оперируют LLM, насчитывают десятки и сотни тысяч токенов. Но по аналогии с людьми — большинство моделей разговаривают на разных языках, и токены от одной модели не подойдут к другой.

Более того, в силу объёмности своего словаря, модель включает в себя токены сразу для многих натуральных языков. И именно поэтому, например, если общаться с моделью на русском, она будет расходовать в 2-3 раза больше токенов, чем на английском. Токенизаторы изначально заточены под английский, а кириллица с её сложной морфологией разбивается менее эффективно. Как результат — то же предложение на русском “весит” в 2-3 раза больше токенов, чем аналогичное на английском. Просто потому что статистика. Просто потому что морфология разных языков – испанцам, например, повезло куда меньше.

И в предыдущем абзаце я сказал вторую важную вещь. Модель. Под моделью правильно понимать только код, который отвечает за обработку входящих токенов и генерацию исходящих. Модель в процессе своей работы выполняет разные операции над входящими токенами, хитрым образом перемножает их с такой штукой как веса (о которых поговорим в следующих главах), и в результате генерирует один токен вывода. Потом берёт полученный результат и — не поверите — скармливает его себе обратно и генерирует следующий токен. И так до тех пор, пока модель не сгенерирует специальный токен, означающий конец вывода.

И да, вы прочитали верно — модели работают по принципу “сгенерировал один токен → скормил себе → сгенерировал следующий”. Отсюда все текущие проблемы с тем, что ресурсы не бесконечны, и отсюда же, например, закручивание лимитов со стороны Anthropic.

Немного забегая вперёд — веса. Веса — это результат обучения модели. Проще всего представить их как огромную многомерную таблицу, состоящую из миллиардов чисел. А для больших мейнстримовых моделей — сотен миллиардов и даже триллионов. Эти числа содержат в себе все “знания” модели. Каждое число определяет соответствие набора токенов какой-то характеристике, и именно комбинация всех этих весов даёт модели способность “понимать” контекст и генерировать подходящие токены в ответ на входящие. А обучение модели — вы наверняка слышали этот термин — это процесс подбора (именно подбора) этих самых весов, чтобы модель предсказывала следующий токен максимально правдоподобно и соответственно входящему корпусу текста.

Ну а принцип работы моделей остаётся один — трансформерная архитектура. Буква T в GPT. А вот конкретная реализация и веса уникальны для каждого вендора — OpenAI GPT-4, Claude Sonnet, Llama и так далее. Веса строго уникальны для каждой отдельной модели. И если кому-то сильно захочется, он сможет взять актуальную версию Llama (модель и веса - открытые), дать ей свои веса, полученные тренировкой на каком-то своём датасете, и в результате получить своё уникальное поведение, отличное от того, что предоставляет Meta. Код — один, веса — разные, и поведение, соответственно, тоже разное.

В дальнейшем, для краткости, я всё-таки примкну к массам и буду называть связку модель+веса просто моделью. Но когда в следующий раз в интернетах увидите фразу вида "Claude Opus (актуальная цфра) в кодинге лучше, чем GPT-5.5 — сможете включить режим душнилы и возразить: “вообще-то это их модель + веса + системный промпт лучше, а не просто модель!”.

Ну и как можно понять из вышесказанного — никакой магией и уж тем более разумностью такие модели не обладают. Удовлетворительный результат предсказания — это лишь производная супербольшой статистики, настолько большой, что уместить её объём в человеческое сознание попросту невозможно. А человек, по своей натуре, что не понимает — пытается либо мистифицировать, либо обозвать разумным. Отсюда и заблуждение про наличие какого-то сознания даже у нынешнего поколения моделей.

А если добавить сюда специализированные термины, перекочевавшие из других сегментов ML и AI — thinking, chain of thought, contemplation и прочее — так у неискушённого зрителя и вовсе может сложиться впечатление, что мы уже достигли так называемого AGI. Это ИИ, который наравне или превосходит человеческий интеллект. Но обманываться здесь не стоит — по факту мы всё ещё работаем с автокомплитом на стероидах.

А направить этот автокомплит в желаемое русло могут только вводные данные - то, что называется prompt.

2. Учение - свет

Но прежде чем погрузиться в разбор хитрых (и не очень) уловок, к которым прибегают разработчики и пользователи, с целью обуздания статистики, пробежимся по устройству некоторых важных для понимания концептов LLM.

2.1. Не все токены рождены равными

Почему вообще важно понимать, что такое токены и откуда они берутся?

Да всё просто — именно за токены с нас берут деньги провайдеры managed моделей. И даже если не поднимать финансовую часть вопроса — про токены важно знать просто потому, что именно через токены нас воспринимает модель. И именно токенами эта же модель и отвечает. Не текстом, который вы видите. В токенизации закопана, наверное, самая большая часть забавных багов поведения моделей. И, отчасти, токенизацией обусловлена дороговизна тренировки моделей.

Как уже говорил — модели не понимают сырой текст. Они вообще-то выполняют матричное умножение. А для того, чтобы делать матричное умножение, нужно работать с числами. Для этого и была придумана токенизация — процесс преобразования текстовой информации в числовые токены. По заранее определённому словарю, который известен модели, и с учётом как раз-таки этих токенов впоследствии будут составляться веса. И именно это одна из причин, почему веса от одной модели не подойдут к другой — они буквально будут разговаривать на разных “языках”. Токены разные, словари разные.

Так как же эти словари составляют?ф

На первый взгляд — просто возьми, сопоставь какое-то число с каждой буквой алфавита, да и дело с концом. Но так как мы всё-таки имеем дело с программой, это было бы банально неэффективно — ведь можно размечать не только буквы, но и слоги, слова и даже целые фразы. Чем больше единица токенизации, тем меньше токенов нужно для передачи того же объёма информации и, как следствие, смысла. А отсюда вытекает экономия — как в вычислениях, так и, банально, в транспорте.

Чем больше размер словаря, тем меньше токенов требуется для передачи информации. Контекстное окно модели (к этому термину мы вернёмся в следующих главах) используется более эффективно, в словарь можно упаковать большее количество языков, а сложные слова можно уместить целиком — без дробления как минимум на буквы, как максимум на слоги, а в идеале вообще целиком.

Но и особо усердствовать, понятное дело, не стоит. Нет смысла создавать какой-то убер-словарь, содержащий в себе все мыслимые и немыслимые фразы. Увеличение размера словаря очевидным образом приведёт к росту требований по памяти, усложнит процесс обучения и, что самое значительное, увеличит вычислительную сложность — в связи с увеличением размера эмбеддинга, а это в свою очередь увеличит стоимость и так недешёвого исходящего токена. Для понимания масштаба: исходящий токен обычно примерно в 5-10 раз дороже входящего.

С увеличением вычислительных мощностей и ростом требований к результатам работы моделей размер словарей постепенно увеличивается. На ранних этапах использовали словари размером от 32 до 50 тысяч токенов — GPT-2/3 около 50 тысяч, LLaMA 2 — 32 тысячи. Современные модели используют словари уже из сотен тысяч токенов: GPT-3.5/4 перешли на 100 тысяч, LLaMA 3 — 128 тысяч, GPT-4o и далее — уже 200 тысяч (да и все кроме Anthropic, в итоге, перешли на tiktoken - словарь OpenAI). Anthropic же размер словаря своих моделей не публикует — по реверс-инжинирингу на этапе поколения Claude 2/3 посчитали, что используется всего лишь около 65 тысяч токенов. Но актуальные данные есть только у ребят из Anthropic, и, например, для Claude 4.7 размер словаря доподлинно неизвестен, потому что токенизация происходит на стороне серверов Anthropic.

Однако размер словаря — это только часть истории. Не менее важно, как именно эти токены получаются — потому что от этого зависит, что эти токены значат. В основе токенизации лежат разные алгоритмы, которые по-разному разбивают текст и определяют, что считать “единицей смысла”.

Наиболее распространённых по принципу работы можно выделить три подхода:

  • Byte Pair Encoding (BPE) — полностью частотный метод. BPE отвечает на вопрос “Какие последовательности символов чаще всего встречаются вместе?”. Таким образом, часто встречающиеся наборы символов, слова или даже фразы кодируются одним токеном, что уменьшает общее количество токенов. Используется в GPT-2+, LLaMA 3+ да и в большинстве современных моделей. Справедливости ради — именно поэтому их и называют статистическими генераторами. Всё буквально, на уровне “словаря”, основано на статистике.

  • WordPiece — гибрид частотного BPE и языкового подхода. В отличие от BPE, который просто ищет частые пары, WordPiece пытается максимизировать правдоподобие (likelihood) данных. Грубо говоря, он не просто пытается ответить на вопрос “как часто”, он ещё и оценивает “насколько вероятно, что эти символы появятся вместе в осмысленном контексте”, понятное дело, начинает зависеть от корпуса обучения. Используется, например, в BERT (Bidirectional Encoder Representations from Transformers) и его производных — к слову, последняя буква в BERT та же, что и в GPT. Transformers. BERT как раз-таки является прародителем GPT, а его корпуса обучения легли в основу тренировки последующих поколений моделей.

  • SentencePiece — строго говоря, он не то чтобы отдельный — он объединяет в себе алгоритмы BPE и Unigram (если интересно, погуглите отдельно – trigram, кро работал, отсюда же) с целью достижения языковой независимости. Работает напрямую с сырым текстом, не строго побайтово, как BPE, без предварительной токенизации по пробелам. Это делает его особенно эффективным для языков без явных разделителей слов — например, китайский, японский и многие другие “многобайтовые” группы языков — или для языков с богатой морфологией, например. Используется в T5, XLNet и многих других мультиязычных моделях, о которых вы, скорее всего, даже и не слышали.

Ну и наконец, помимо “обычных” токенов, которые получаются путём сбора статистики, в словари включают так называемые * системные токены*. Это служебные элементы, которые модель воспринимает как неделимые — правильнее всего относиться к ним как к управляющим последовательностям. Они не зависят от обучающих данных и располагаются в самом хвосте словаря — например, для tiktoken o200k_base специальные токены начинаются с позиции 199999, а для cl100k_base — с 100257.

В обычном тексте такие последовательности очевидным образом встретиться не могут — они заранее определены и зарезервированы. Но активно используются внутри API, безотносительно входящего или исходящего текста. Если вы работали с OpenAI-моделями напрямую, то наверняка видели в документации или даже в выводе маркеры вроде <|im_start|>, <|im_end|> и другие управляющие последовательности, обозначающие начало и конец сообщений.

2.1.1. Пример составления словаря BPE

Для наглядности давайте на примере попытаемся составить словарь формата BPE.

Составление словаря — не только для BPE — начинается с составления так называемого тренировочного корпуса. Корпус — большой объём текстовых данных, относящихся к одному “смыслу”: корпус литературы, корпус кода и так далее. Такую информацию размечать максимально просто — не нужно размечать каждый отдельный источник. Достаточно знать происхождение текста: всё из библиотеки — литературный текст, всё из GitHub — код. Конкретно за счёт этого GPT-модели и взлетели — исключён самый дрогой процесс - рпзметка каждой единицы текста. Именно отсутствие необходимости кропотливой разметки каждой единицы текста позволило набрать колоссальные объёмы тренировочных данных.

На основе такого репрезентативного набора для того или иного домена — “английский язык”, “китайский язык”, “язык программирования Go” — и строится словарь. В качестве примера рассмотрим простенький корпус eat eats eating eaten. Для понимания масштаба: настоящие корпуса обычно ограничиваются не одним томом произведений Шекспира, а целой библиотекой. Но нам для демонстрации хватит и четырёх слов — статистика здесь наиболее наглядна.

Для начала BPE разобьёт весь наш текст на слова путём замены пробела и символов пунктуации на системный токен </w>, обозначающий конец слова. В итоге мы получим: eat</w>eats</w>eating</w>eaten</w>.

Далее алгоритм разбивает корпус на отдельные символы, получая начальный набор токенов: e a t </w> e a t s </w> e a t i n g </w> e a t e n </w>. При этом системный токен </w> считается одним символом. Отсюда мы уже можем получить первичный словарь для данного корпуса, если его дедуплицируем: Vocab = {e, a, t, s, i, n, g, </w>}.

И тут начинается итеративный и самый времяёмкий (после получения весов) процесс — поиск наиболее частых пар токенов и их объединение в новые токены, иначе — фаза слияния (merge).

Важной частью классического алгоритма BPE является запрет слияния с токеном </w> — то есть оригинальный BPE не подразумевает токенизации фраз или включения пробельных и пунктуационных символов внутрь словаря. И тут важно: пунктуация в контексте BPE — всякие точки с запятыми, запятые и прочее — являются разделителями слов. Они попросту не учитываются, и поэтому, например, классический BPE работает с языками программирования как минимум неэффективно.

Каждый цикл итерации будет выглядеть следующим образом:

  1. Составляем список всех возможных слияний в текущем состоянии словаря и считаем количество вхождений в нашем корпусе.

  2. Берем самую популярную комбинацию - для первой итерации на нашем корпусе это (e, a), важно отметить что комбинация (a, t) имеет то же количество вхождений, но выбрать можно любую, на валидность это не повлияет.

  3. Добавляем в словарь новый токен ea.

  4. Заменяем все вхождения в корпусе на новый токен.

  5. Повторяем процесс до тех пор, пока не достигнем желаемого размера словаря или пока не исчерпаем все возможные слияния.

Например, для нашего корпуса, мы могли бы получить такие итерации:

  1. Vocab = {e, a, t, s, i, n, g, </w>, ea} Corp = [ea t</w>, ea t s</w>, ea t i n g</w>, ea t e n</w>]

  2. Vocab = {e, a, t, s, i, n, g, </w>, ea, eat} Corp = [eat</w>, eat s</w>, eat i n g</w>, eat e n</w>]

  3. Vocab = {e, a, t, s, i, n, g, </w>, ea, eat, in} Corp = [eat</w>, eat s</w>, eat in g</w>, eat e n</w>]

  4. Vocab = {e, a, t, s, i, n, g, </w>, ea, eat, in, en} Corp = [eat</w>, eat s</w>, eat in g</w>, eat en</w>]

  5. Vocab = {e, a, t, s, i, n, g, </w>, ea, eat, in, en, ing, eats, eating, eaten} Corp = [eat</w>, eats</w>, eating</w>, eaten</w>]

В данном примере поворотной точкой, служил выбор слияния (e, a), а не (a, t), если бы был выбран токен at, то результат мог бы быть, например, таким: Vocab = {e, a, t, s, i, n, g, </w>, at, eat, eats, eate, eaten, ng, ing, eating} Corp = [eat</w>, eats</w>, eating</w>, eaten</w>]

Этот процесс продолжается до тех пор, пока не будет достигнут желаемый размер словаря или пока не исчерпаются все возможные слияния.

В реальных сценариях тренировочные корпуса значительно больше и сложнее, что очевидным образом приводит к гораздо более обширным и разнообразным словарям. И словари эти в процессе дополняются. После генерации словаря, например, на английском языке — который для популярных моделей является основополагающим — у нас остаётся место в желаемом объёме токенов. И это место начинает заполняться: сначала составили словарь на основе английского, потом дополняем его корпусом русского языка, потом корпусом какого-то языка программирования — и так далее, до тех пор пока не закончится пространство токенов.

2.1.2. Токенизация текста

В итоге у нас на руках имеется полностью составленный словарь — допустим, tiktoken o200k_base на 200 тысяч токенов. После этого мы можем использовать его для токенизации входящих текстов.

Процесс токенизации обычно включает следующие шаги:

  1. Претокенизация — нормализация текста: приведение к нижнему регистру, удаление лишних пробелов и специальных символов.

  2. Итеративное слияние — используя составленный словарь, текст разбивается на токены. Алгоритм ищет в тексте самые длинные последовательности символов, которые соответствуют токенам в словаре, и заменяет их на соответствующие токены. Идя от больших к меньшим — сначала какие-то сегменты преобразуются в самые длинные токены, потом всё меньше и меньше, и в итоге в идеале весь текст представлен токенами.

  3. Вывод токенов — полученный набор токенов используется в качестве входных данных для модели. Ну и соответственно, тот текст, который мы видим в качестве вывода от LLM — это процесс обратного преобразования токенов в человекочитаемый текст.

Например, возьмём текст eating apples.

  1. Претокенизация: текст уже нормализован, никаких изменений не требуется.

  2. Итеративное слияние:

    • Начинаем с отдельных символов: e a t i n g a p p l e s

    • Ищем самые длинные совпадения в словаре:

      • eating → токен eating

      • apples → токен apples

    • В итоге получаем токены: [eating, apples] — естественно, не сами слова, а их числовые представления согласно словарю.

Интересности начинаются, когда токенайзер встречает слова или символы, которых нет в его словаре. В таких случаях токенайзер разбивает неизвестные слова на более мелкие части, которые уже есть в словаре. И я не говорю о ситуациях “нет целикового слова” — в лучшем случае токенайзер может разнести строку на более мелкие токены. Речь про случай, когда входящая последовательность вообще вне пределов даже базового алфавита — то есть её по идее невозможно разбить даже на базовые токены.

Например, если в словаре нет иероглифов, символов редких языков или экзотических Unicode-комбинаций — токенайзер начнёт делить строку буквально по отдельным байтам. Результат — огромное количество токенов, бешеная стоимость инференса и, как правило, абсолютно бессмысленный контекст для модели. Ну и в силу того, что бессмысленный вход для модели означает бессмысленный выход — для неё это будет просто последовательность чего-то абсолютно непонятного, а значит, вероятность сгенерировать адекватный ответ буквально стремится к нулю.

Схематично это выглядит примерно так:

Input: "𐍈"  (готская буква)
Tokenizer output: [220, 393, 177, 61, 113, 12, 5, 2]

И самое забавное — для нас эта последовательность чисел ничего не значит. И для модели тоже. Она буквально не понимает, что с этим делать. Модель не знает, что это за символ — ведь в её мире нет понятия “готская буква”. Она просто видит восемь чисел подряд и делает то, что умеет — пытается предсказать следующее. Отсюда и рождаются легендарные примеры, когда LLM “сходит с ума” при встрече буквально одного редкого символа — древней письменности или битого Unicode. Всё последующее теряет смысл, и модель очевидным образом не может предсказать, что должно быть дальше.

Да и более того — такая ситуация может возникнуть и с совершенно обычными, как минимум для нас, словами. Если токенайзер был обучен на другом языке или домене — например, английский токенайзер спокойно проглотит optimization, но при встрече с венгерским megszentségteleníthetetlenségeskedéseitekért просто сдастся и разорвёт его на 23 отдельных токена (проверено на токенайзере GPT-3, более свежий GPT-4o справляется чуть лучше — 17 токенов). И каждый из них будет для модели почти что бессмысленным в комплексе, потому что в обучении она не видела абсолютно ничего подобного — нет ни одной последовательности в обучении, связанной с этим набором токенов.

Поэтому хорошая токенизация — это баланс между универсальностью и эффективностью. Слишком узкий словарь — и всё ломается на редких символах. Слишком широкий — и модель по факту тонет в сложности, а весов не хватает, чтобы адекватно выучить все комбинации.

Именно поэтому современные токенайзеры стараются быть мультиязычными и байтовыми одновременно — чтобы на случай любой неожиданности иметь возможность хотя бы как-то закодировать текст, не взрывая счётчик токенов и не сваливаясь в абракадабру на выходе.

2.1.3. Специфика токенайзеров

Конкретные имплементации токенизаторов могут иметь и свои особенности, и, понятное дело, отличия от базового алгоритма, которые кардинальным образом повлияют на конечный результат.

Например, в словаре GPT-3 появились отдельные токены для типичных паттернов: пробелов, отступов и переводов строк — следствие тренировки BPE на больших объёмах кода, где эти паттерны встречаются постоянно. А tiktoken — сейчас самый популярный токенайзер — хоть и базируется на BPE, не использует системный токен </w>. Вместо него tiktoken использует стратегию с пробелом-префиксом ( hello вместо hello</w>), что меняет способ кодирования границ слов. В сочетании с большим словарём (от 100 до 200 тысяч токенов) это позволяет более эффективно обрабатывать длинные подслова — мелочь, а поведение уже абсолютно другое.

Регистр: apple или Apple? Токенизаторы могут по-разному обращаться с регистром. Для них Apple и apple — это два разных слова. Очевидным образом кодировка по байтам будет разной. С одной стороны, это помогает отличить фрукт от названия компании. С другой — словарь начинает раздуваться, и вместе с ним растёт риск того, что одно и то же слово в немножечко другом контексте будет воспринято совсем иначе. То же касается, например, python и Python — в словаре tiktoken 200k это разные токены. И вот тебе пример: Python — это животное, в начале предложения, или язык программирования?

Glitch tokens — токены-глюки Иногда в словарь попадают случайные токены, которые почти не встречались в обучающих данных. Веса под них натренированы слабо, и модель при их встрече ведёт себя… своеобразно.

Классический пример — токен davidjl (номер 23282 в словаре GPT-2, который унаследовал GPT-3). Это просто никнейм пользователя Reddit, попавший в словарь. Если упомянуть его в запросе — начинается выдача абсолютнейшей белиберды.

Похожая история — SolidGoldMagikarp. Реддит, покемоны, тоже магия глючных токенов. Старые версии ChatGPT реагировали на него, как на древнее заклинание, что наглухо сводило их с ума.

Пре-токенизация и её сюрпризы Разные токенайзеры по-разному обрабатывают пробелы, дефисы и пунктуацию. В одних пробел входит в токен ( hello), в других — живёт отдельно, а где-то заменяется на символ (привет, SentencePiece).

Или вот ещё примеры:

  • don't может токенизироваться иначе, чем do n't;

  • state-of-the-art и state of the art дадут абсолютно разные наборы токенов, хотя по сути являются одним и тем же смыслом;

  • URL и email рубятся на куски — хотя сами по себе цельные конструкции, но токенов-то соответствующих нет. И как понять — здесь у нас URL или раздельные слова?

  • код, отступы и скобки токенизируются и вовсе непредсказуемо, особенно если табы и пробелы перепутаны (я прям нарываюсь на холивар про спейсы и табы, Python и конфиги в YAML — но пожалуй оставим это за скобками 🤭).

Эмодзи и числа — отдельный уровень ада для LLM Один “смайлик” может занимать от одного до нескольких байт. А если мы возьмём флаг или эмодзи с оттенком кожи — он начинает представлять из себя несколько эмодзи, каждый из которых, напомню, состоит из нескольких байт. В итоге в одном токенайзере это один токен, в другом — в лучшем случае три.

С числами засада ещё хлеще. И именно тут зарыта собака невозможности заставить LLM считать по-нормальному. Число 2025 вообще-то может быть токенизировано как [“20”, “25”], или как [“2”, “025”], или остаться целиком. И в зависимости от этого модель будет по-разному интерпретировать это число — как год, как строку или просто как набор цифр без смысла.

Токенизация становится не просто технической деталью, а важной частью архитектуры, влияющей буквально на всё — на то, как модель “понимает” контекст, на конечную стоимость инференса и даже на то, какие глюки мы впоследствии наблюдаем в поведении LLM.


Подписывайтесь на телегу — Я туда, бывает, что-то умное пишу🤭