JavaRush/Java блог/Random/Как устроена большая языковая модель
Dr-John Zoidberg
16 уровень

Как устроена большая языковая модель

Статья из группы Random
участников

Вы отправляете запрос, и через секунду в терминале начинает набираться ответ. Не появляется целиком, а именно набирается: кусочек за кусочком, будто кто-то печатает его прямо сейчас. Иногда перед этим на экране висит Thinking, ответ приходит заметно позже, зато толковее.

Всё это следствия одного механизма. Разберём, как устроена большая языковая модель: что она делает с вашим текстом, чем меряет его длину, откуда у неё знания и что происходит в те секунды, пока она думает. Ни один из этих фактов не нужен, чтобы нажать Enter. Зато вместе они заметно меняют то, чего вы от ответа ждёте.

Комикс: человек красит забор и показывает роботу, как это делается, а робот повторяет узор мазков вместо того, чтобы покрасить каждую доску
Насколько всё это упрощено

Материал намеренно упрощён. Так он читается быстро и отвечает на вопрос, что происходит у вас на экране. Точного разбора здесь нет и быть не может - на один только блок трансформера уходит отдельная работа.

Языковая модель оценивает продолжение

Начнём с предмета. Большая языковая модель, она же LLM, от large language model, - это не программа с окном и кнопками и не чат. Это механизм, к которому обращаются: ему отдают текст разговора, он возвращает продолжение. Claude Code, веб-чат, подсказки в редакторе - всё это обвязка вокруг такого обращения, и обвязка у всех разная.

Умеет модель при этом одно: по началу текста оценить, какое продолжение вероятнее. Не найти правильный ответ, а именно оценить вероятность, причём не для одного варианта, а для каждого, какой есть в её словаре.

Легче всего поймать это на короткой фразе. Продолжите вслух: "кофе я пью без..." Первым в голову лезет "сахара", следом "молока", а вот "интернета" туда не встаёт совсем, хотя грамматически всё в порядке. Вы прикинули это за долю секунды и не задумываясь. Модель делает то же самое, только формально и до конца: проходит по всему словарю и каждому кандидату выставляет число.

Модель оценивает варианты продолжения фразы: после "кофе я пью без" вариант "сахара" очень вероятен, "молока" тоже встречается, "интернета" почти никогдаНачало фразыКофе я пью безсахараочень вероятномолокатоже бываетинтернетапочти никогда
У каждого варианта своя оценка. Пометки "верно" нет ни у одного из них

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

Чем LLM отличается от чата и агента

Эти три слова часто используют как синонимы, хотя они описывают разные слои системы.

  • LLM - сама языковая модель. Получает контекст и генерирует следующее сообщение.
  • Чат - интерфейс и программа вокруг LLM. Он хранит историю, собирает запрос, отправляет его модели и показывает ответ.
  • Агент - LLM с целью, циклом работы и инструментами. Он может попросить приложение прочитать файл, выполнить поиск или запустить тест, посмотреть результат и выбрать следующий шаг.
Упрощённая схема трёх вложенных слоёв: внутри агента находится чат, а внутри чата языковая модель. LLM генерирует сообщение, чат добавляет историю и интерфейс, агент добавляет цель, цикл работы, инструменты и разрешенияАгентцель · цикл работы · инструменты · разрешенияЧатинтерфейс · история · сборка контекстаLLMконтекст → следующее сообщениеКаждый внешний слой добавляет возможности вокруг модели
LLM - ядро; чат и агент добавляют вокруг модели свои возможности

Коротко: LLM предлагает решение, чат организует разговор, агент связывает решения модели с действиями во внешнем мире.

Токены, а не слова

К схеме выше нужна поправка: слова стоят на ней целиком только ради наглядности. На самом деле модель разбирает текст на токены - куски из собственного словаря. Токеном бывает целое слово, часть слова или знак препинания, а пробел обычно уезжает внутрь следующего токена и отдельной единицей не считается.

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

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

Одна и та же мысль на двух языках: английская фраза coffee every morning разбивается на три токена, русская кофе каждое утро при тех же трёх словах - на пять. Пробел показан серым прямоугольником внутри токена, перед которым он стоялАнглийский3 слова, 3 токенаРусский3 слова, а токенов уже 5coffeeeverymorningкофекаждоеутро
Серый прямоугольник это пробел: он никуда не девается, а уезжает внутрь следующего токена. Разбивка примерная, у каждой модели свой словарь

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

Всё это проще один раз увидеть, чем прочитать. Откройте The Tokenizer Playground, вставьте туда пару своих обычных запросов, а следом тот же текст по-английски - и сразу видно, на какие куски разваливается строка и сколько их вышло. Оговорка одна: токенизатор там принадлежит конкретной модели, и у той, с которой работаете вы, разбивка будет своя. Идти туда стоит за явлением, а не за точным числом.

Практическое следствие у этого неожиданное. Модель видит не буквы, а куски, и вопросы про буквы даются ей заметно хуже, чем вопросы про смысл. Попросите посчитать, сколько букв "о" в длинном слове, и ответ вполне может оказаться неверным. Не потому, что задача сложная, а потому, что слово доехало до модели двумя кусками и отдельных букв внутри них для неё нет.

Как из токенов собирается ответ

Теперь соберём механизм целиком, и он окажется проще, чем можно подумать. Модель оценивает варианты, один из них выбирается и дописывается в конец текста. После этого всё начинается заново - с тем же текстом, только на один токен длиннее.

Три шага генерации подряд: к фразе кофе я пью без добавляется токен сахара, к получившейся фразе - токен уже, затем токен десятьЧто уже написаноСледующий токенКаждый выбранный токен возвращается в условие следующего шагаКофе я пью безКофе я пью без сахараКофе я пью без сахара ужесахараужедесять
Ответ не берётся готовым: он вырастает по одному токену, и каждый новый влияет на следующий

Готовый ответ нигде не лежал и ниоткуда не доставался - он собран за столько шагов, сколько в нём токенов. Заканчивается это тоже не по таймеру: в какой-то момент самым вероятным продолжением оказывается специальный токен со смыслом "здесь конец", и генерация останавливается.

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

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

Что происходит в терминале

То, как ответ проступает в окне Claude Code, - не индикатор загрузки, а сами шаги генерации: модель отдаёт токены по мере того, как выбирает их, а программа тут же выводит их на экран. Поэтому длинный ответ и появляется постепенно, а не возникает целиком после паузы.

Почему модель называют большой

Слово "большая" описывает не вес файла, который где-то лежит. За ним стоят два совсем других масштаба, и оба полезно представлять себе честно.

Первый - объём текста, через который модель прошла при обучении: книги, статьи, документация, форумы, код, и всё это в количествах, которые человеку не прочитать за несколько жизней. Второй - число параметров. Параметр это одно число внутри модели, одна из настроек, которые подстраивались во время обучения. Их миллиарды. У открытых моделей это число прямо выносят в имя: 7B, 14B, 70B, где B значит billion, миллиард.

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

И ещё одна вещь, которая на таком масштабе получается словно сама собой. Чтобы складно продолжить фразу про упавший тест, недостаточно знать, какие слова обычно стоят рядом. Нужно уловить ещё и то, как тесты устроены. Модель училась угадывать слова, а попутно в её параметрах закрепилось то, что этими словами описано. Отсюда и берётся ощущение осведомлённости, хотя механизм не поменялся ни на шаг.

Откуда у модели знания

Источников ровно два, и путать их выходит дорого.

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

Второй - то, что прямо сейчас лежит в разговоре: ваш запрос, всё сказанное до него, содержимое открытых файлов, вывод запущенных команд. Этот источник точный, но короткоживущий. В параметры он не переезжает, и следующий разговор про него уже ничего не знает.

Всё прочее, что хочется назвать отдельным источником, - файл памяти, найденная документация, ответ стороннего сервиса, - приходит этим же путём: сначала попадает в разговор и только потом влияет на ответ. Своей двери в проект или в интернет у модели нет.

У первого источника есть дата, и у неё есть имя - knowledge cutoff. Это ориентир, до какого момента встроенные знания модели обычно актуальны. О библиотеке, вышедшей после этой даты, модель знает столько, сколько успели положить в текущий разговор.

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

И маленькое, но полезное. Узнавать cutoff у самой модели - затея так себе: на этот вопрос она ответит генерацией, то есть подберёт правдоподобное. Точная дата живёт в документации конкретной версии, и у соседних моделей одного семейства она вполне может отличаться.

Что означает Thinking

Когда на экране появляется Thinking, модель не переключилась в какой-то другой режим сознания. Ей просто дали место подумать до того, как она начнёт отвечать. Технически это ровно та же генерация: сначала модель пишет черновик для себя - разбирает задачу, прикидывает варианты, спорит сама с собой, - и только потом выдаёт финальный текст. Сколько именно думать, современные модели во многом решают сами: на простом вопросе черновик короткий или его нет вовсе, на запутанном длиннее.

Один запрос может сразу перейти к быстрому ответу или пройти через разбор задачи и проверку перед финальным ответомОдин запрос - разный бюджет до ответаБыстроЗапросБыстрый ответThinkingЗапросРазборПроверкаОтветВторой путь тратит больше времени и токенов до финального ответа
Один и тот же запрос может получить быстрый ответ или дополнительное время на разбор и проверку

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

Первое объяснение вообще нередко оказывается не тем. Оно правдоподобное, но правдоподобие и было критерием, по которому механизм его выбрал.

Теперь про то, когда дополнительное рассуждение окупается. Стоит оно времени, и включать его на каждую мелочь незачем.

Обычно хватает быстрого ответаСтоит дать место рассуждению
объяснить, что делает кусок кода на экраненайти причину падения теста, когда задействовано несколько файлов
поправить опечатку или форматсравнить два решения вместе с их ограничениями
пересказать текст, который вы только что далиспланировать переделку, где шаги зависят друг от друга

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

И честная граница. Показанное рассуждение - не точная запись того, что происходило внутри; часто это пересказ, собранный для читателя. Длинная и стройная цепочка вполне может вырасти из неверной предпосылки и от этого выглядеть надёжнее, чем есть. Бывает и обратное: ответ уже найден, но модель продолжает сомневаться, ходит по кругу и запутывает сама себя. У этого даже есть название - overthinking.

Что работает лучше, чем "подумай как следует"

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

Чего модель не умеет

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

  • Гарантировать, что факт верный. Механизм выбирает вероятное продолжение, а не сверяет утверждение с источником. Выдуманные, но правдоподобные подробности называют галлюцинациями.
  • Не зависеть от формулировки. Переставленные слова и добавленное уточнение меняют ответ, потому что всё решает текст, стоящий перед этим местом.
  • Узнавать новое сама. Без внешних источников встроенные знания не обновляются: про вчерашний релиз библиотеки модель знает только то, что ей показали.
  • Повторяться слово в слово. Один и тот же запрос может дать разный результат, и это свойство механизма, а не сбой.
  • Быть свободной от перекосов исходных текстов. Что там было описано однобоко или не описано вовсе, то и в ответах отзовётся.

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

Что это объясняет в поведении агента

Вот что из этого механизма видно прямо на экране Claude Code:

  • ответ набирается по кусочку, потому что так он и создаётся. Это процесс, а не оформление;
  • два одинаковых запроса дали разные ответы - так и должно быть, генерация не повторяет себя дословно. Нужен прежний результат - надёжнее вернуться к уже полученному, чем переспрашивать;
  • Thinking даёт место на черновик, а не гарантию правильности. На разборе многошаговой задачи оно окупается, на переименовании переменной чаще мешает;
  • пока агент не прочитал файл, ответ про этот файл держится на общих закономерностях. Всё, что попало в разговор, весит больше, чем всё, что закрепилось в параметрах;
  • про свежие версии библиотек модель по умолчанию знает мало, и поправить это проще всего документацией, положенной в разговор;
  • если ответ поехал не туда, добавить недостающее полезнее, чем повторить просьбу теми же словами. Механизм строится на тексте перед ответом, а не на настойчивости.

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

Видео: та же механика в картинках

У канала 3Blue1Brown есть короткий ролик, который собирает основное в одну наглядную анимацию: токены, вероятности следующего слова, внимание и то, откуда вообще берутся параметры модели. Называется он Large Language Models explained briefly.

Оригинал на английском, но у ролика есть несколько аудиодорожек с переводом, переключаются они в настройках плеера. Если дорожки нужного языка нет, откройте видео на самом YouTube: в веб-плеере выбор шире.

Этим роликом канал не ограничивается. Там же лежит целая серия про нейросети, трансформеры и attention - те же идеи, только подробнее и с математикой. Если после статьи захочется понять не "что происходит", а "почему это вообще работает", начинать стоит оттуда.

Комментарии
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
У этой страницы еще нет ни одного комментария