惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
L
LINUX DO - 最新话题
罗磊的独立博客
IT之家
IT之家
阮一峰的网络日志
阮一峰的网络日志
WordPress大学
WordPress大学
Security Archives - TechRepublic
Security Archives - TechRepublic
H
Hacker News: Front Page
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
The Hacker News
The Hacker News
Recent Commits to openclaw:main
Recent Commits to openclaw:main
大猫的无限游戏
大猫的无限游戏
PCI Perspectives
PCI Perspectives
Hugging Face - Blog
Hugging Face - Blog
博客园 - 【当耐特】
Application and Cybersecurity Blog
Application and Cybersecurity Blog
P
Proofpoint News Feed
NISL@THU
NISL@THU
小众软件
小众软件
S
Security Affairs
腾讯CDC
人人都是产品经理
人人都是产品经理
C
Check Point Blog
The GitHub Blog
The GitHub Blog
有赞技术团队
有赞技术团队
Forbes - Security
Forbes - Security
Project Zero
Project Zero
G
Google Developers Blog
博客园 - 三生石上(FineUI控件)
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
博客园_首页
Jina AI
Jina AI
The Cloudflare Blog
C
Cisco Blogs
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
L
Lohrmann on Cybersecurity
Y
Y Combinator Blog
W
WeLiveSecurity
V
Visual Studio Blog
Scott Helme
Scott Helme
N
News | PayPal Newsroom
I
Intezer
C
CXSECURITY Database RSS Feed - CXSecurity.com
Attack and Defense Labs
Attack and Defense Labs
Spread Privacy
Spread Privacy
Webroot Blog
Webroot Blog
T
Threatpost
雷峰网
雷峰网
MongoDB | Blog
MongoDB | Blog
N
News and Events Feed by Topic

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Большие модели, маленькие токены. ЛЛМ - битва за контекст (ч.1)
xobotyi · 2026-05-09 · via Все публикации подряд на Хабре

Когда я выкладывал первую главу этого цикла статей в свой телеграм-канал (@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.