Представьте, что вы разговариваете с невероятно умным и эрудированным собеседником. Только очень странным. Несмотря на весь свой интеллект и тысячи фактов, которые он непринужденно рассказывает, он не может ничего запомнить. Ваш диалог с ним каждый раз как бы начинается заново. Вы даете ему вводные, задаете вопросы, что-то уточняете, а он, на основе всего этого, выдает ответ.
Однако, стоит вам задать следующий вопрос, как собеседник напрочь забывает все, о чем вы говорили. И чтобы отвечать более-менее связно, ему приходится сначала перечитать весь ваш диалог и снова загрузить в себя. А заодно и все служебные инструкции, которые идут в довесок к диалогу и не всегда очевидны даже для вас.
Звучит странно? Возможно. Однако именно так работает большинство современных LLM. А разработчики, пытаясь нивелировать эту особенность, добавляют нейронкам различные обвязки и ухищрения, заметно усложняя логику для рядового пользователя.
Чтобы лучше понимать, что происходит, давайте погрузимся в тему. И подробнее познакомимся с такой штукой, как «контекстное окно».

Вспомнить все
Давайте сразу договоримся о терминах. Когда я говорю «нейросеть» в этой статье, я имею в виду большую языковую модель (LLM) архитектуры Transformer (Decoder-only). Сейчас это самая популярная реализация и большинство чат-ботов, которые вы используете, работает на основе этой архитектуры.
Только вот беда. У этой архитектуры есть досадное ограничение — полное отсутствие памяти в человеческом понимании. Когда чат-бот не теряет нить разговора с вами, это всего лишь программный трюк с подстановкой сообщения в промпт. Рабочая схема, но с каждым новым сообщением в диалоге она работает все хуже. Чтобы понять суть происходящего, нам надо вспомнить, как модель вообще общается с внешним миром.
Когда вы отправляете в чат любое сообщение (например, «Расскажи мне, что такое контекстное окно»), то это сообщение нарезается на токены, кусочки текста, которыми умеет мыслить модель.
Важно. Токен — это не слово и не буква, а технический кусочек текста из словаря токенизатора. Иногда он похож на слово, иногда на часть слова, иногда на знак препинания или фрагмент вместе с пробелом. Поэтому подтягивать токен к привычным категориям вроде «буква», «слог» или «слово» нельзя. Ибо в рамках каждой конкретной модели нарезка происходит по-разному и зависит от обучения токенизатора. Например, слово «нейросеть» может быть представлено как [Нейро] + [сеть], а можно — [Нейрос] + [еть].
Чтобы хоть к чему-то привязаться, можно взять оценку OpenAI из документации: один токен — примерно четыре символа, около ¾ слова; 100 токенов — примерно 75 слов. Важная оговорка. Большинство популярных моделей изначально обучались в основном на английских текстах. Поэтому английские куски модель «знает» крупными блоками, а другие языки крошит мельче.
Грубый пример. Английское the — это один токен. А наше «несвоевременность» легко разваливается на четыре-пять токенов. Модель просто не видела его достаточно часто, чтобы запомнить целиком, и собирает из обрезков — приставка, корень, пара суффиксов, окончание.

Отсюда вывод: один и тот же по смыслу текст на русском почти всегда весит в токенах заметно больше, чем на английском. Иногда в полтора-два раза. Точные коэффициенты гуляют от модели к модели. Но порядок такой: на английском один токен это в среднем около четырех символов. На русском — ближе к двум-трем. Разница, увы, не в нашу пользу.
Почему это важно? Потому что после токенизации модель работает уже не с буквами и словами в человеческом смысле, а с их числовыми представлениями. Каждый токен превращается в вектор-эмбеддинг — набор чисел, который кодирует не значение слова в словарном смысле, а набор признаков, полезных модели для продолжения текста.
Для простоты это часто описывают как «координаты в многомерном пространстве смыслов». Метафора не идеальная, но полезная: близкие по употреблению и контекстам фрагменты текста обычно оказываются в этом пространстве ближе друг к другу, чем совершенно разные вещи. Поэтому слово «король» будет связано с властью, монархией, человеком, мужчиной, наследником, троном и кучей других признаков. А похожий по написанию «королек» — совсем с другим набором контекстов.

Важно не понимать это буквально. Модель не открывает карту смыслов и не ищет на ней готовый ответ. Она прогоняет токены через слои нейросети и на каждом шаге считает, какой следующий токен наиболее уместен с учетом всего входа. Но именно такие числовые представления позволяют ей работать не только с буквальным совпадением слов, а с контекстом, ролью и смысловыми связями.
Отсюда становится понятнее, зачем в промпте задают роль и рамку ответа: «Ты — опытный инженер», «объясни как для новичка», «пиши в стиле технической статьи». Это не включает внутри модели отдельный режим «генерить с премиум-качеством», но меняет условия задачи. Модель начинает продолжать текст так, как если бы перед ней уже был фрагмент разговора в нужной роли, стиле и уровне детализации.
После того как мы порезали наш запрос на токены, векторизировали его и загрузили в модель, в игру вступает (внимание!) механизм внимания.
Self-Attention
Self-attention — это механизм, при котором для каждого токена вычисляется, какие другие токены во входной последовательности важнее учитывать. Допустим, у нас есть предложение: «Петя положил ноутбук в рюкзак, потому что он боялся дождя». Кто здесь боится дождя, Петя или ноутбук?
Чтобы понять, к чему относится «он», модели нужно связать местоимение с Петей, а существительное «дождь» — с причиной действия. Или учесть контекст выше (например, статью про бесстрашного, но практичного мальчика и вред воды для техники) и связать «он» уже с ноутбуком.
В длинном диалоге задача такая же, только масштабы другие. Когда вы пишете: «сделай как в первом варианте, но без того странного допущения», модели надо найти, что было первым вариантом и какое допущение вы раньше называли странным.
Классический механизм self-attention сравнивает токены друг с другом. В грубом виде это дает квадратичную зависимость по длине последовательности: если токенов стало в 10 раз больше, взаимодействий стало примерно в 100 раз больше. Это можно сравнить с рукопожатиями. Если в комнате 10 человек, то чтобы каждый пожал каждому руку, нужно 45 рукопожатий. Когда в комнате 100 человек, уникальных рукопожатий станет уже 4950. Рост в десять раз вызвал лавину приветствий, увеличив ее более чем в сто раз.
Современные модели, конечно, не просто сравнивают все со всем. Есть разные ухищрения, вроде KV-cache, grouped-query attention, sliding attention, sparse attention, RoPE-масштабирование, оптимизации памяти и железа. Но базовая физика никуда не делась: длинный запрос требует больше памяти, больше вычислений и больше времени.
И вот теперь главная мысль.
Она вас не помнит
У языковой модели нет памяти о вашем разговоре. Вообще нет. Звучит странно, понимаю. Вы же своими глазами видите, как она отвечает на третий вопрос с оглядкой на первый. Знает, как вас зовут. Подхватывает шутку, которую вы бросили в самом начале. Как же «нет памяти»?
Все очень просто. Сама модель — это, по сути, чистая функция. Подали на вход текст — получили на выходе продолжение. И все. Между двумя вызовами она не хранит ничего. Как stateless-эндпоинт без сессии: каждый запрос самодостаточен, сервер между обращениями не помнит, кто вы и о чем спрашивали минуту назад.
Но где же тогда живет «память» о беседе? Эта память живет не в самой модели, а в прослойке. В том самом чате или приложении, через которое вы с моделью общаетесь. Эта прослойка копит всю вашу переписку и при каждом новом сообщении подкладывает ее обратно — целиком.
Когда вы пишете третье сообщение, модель не «вспоминает» первые два. Ей просто передают первое, второе и третье разом — как один сплошной кусок текста — и говорят: продолжай. Она дочитывает до конца и выдает четвертое. После чего все повторяется заново, но уже с прицепом из пятого сообщения. И так далее.
Кстати, в этом потоке токенов есть еще кое-что, чего вы не видите. Это служебная инструкция или системный промпт, который задает рамку общения. Его к общей массе пристегивает не пользователь, а разработчик приложения. И промпт тоже занимает место в общем объеме. Если совсем грубо представить, что улетает модели на вашем третьем сообщении, выйдет примерно такая простыня: служебная инструкция, потом ваше первое сообщение, потом ее первый ответ, потом ваше второе, ее второй ответ, ваше третье — и в конце запрос. Все это склеено в один поток токенов.
Так что когда модель обращается к вам по имени, это всего лишь значит, что вашему имени хватило места в той простыне токенов, которую ей отправили в этот конкретный раз. Или в невидимом системном промпте автоматически подкладывается ваше имя для персонализации.
Осознаем этот факт и снова вспомним о механизме внимания. Представьте, НАСКОЛЬКО каждое следующее сообщение в диалоге усложняет его. Представили? Тогда идем дальше.
Место в окне
Размер контекстного окна, то есть максимальное число токенов, подаваемых на вход, — это одна из базовых характеристик модели. Для примера, у далеко не самого нового GPT-4.1, по официальному анонсу OpenAI, контекст был до 1 млн токенов.
Скрытый текст
Кажется, что это приличный объем и забить его не так просто. Но ниже мы увидим, что окно забивается куда быстрее, чем хотелось бы.
Что произойдет, когда место кончится? А произойдет одно из двух. И зависит это, что характерно, не от модели, а от того, каким способом вы с ней общаетесь.
Если вы дергаете модель напрямую, через API, своими руками — она просто упрется и вернет ошибку. Что-то вроде «превышена максимальная длина контекста, столько токенов за один раз я не возьму». Грубовато, зато честно: вы сразу знаете, что не влезло, и идете разбираться.
А вот чат-приложения и ассистенты ведут себя «вежливее». И оттого коварнее. Ошибку они вам не покажут. Они молча выкинут самое старое.
Вспомните ту простыню токенов из прошлой главы. Системный промпт, первое сообщение, ответ, второе, ответ — и так до самой свежей реплики. Когда эта простыня перестает влезать в окно, приложение начинает отрезать ее с начала. Самые старые сообщения тихо уползают за край и перестают существовать для модели.
Обратите внимание на формулировку. Модель не забыла начало разговора, забыть она не может, потому что забывать нечего — мы это уже выяснили. Начало разговора ей просто физически не дали. Его отрезали еще до того, как простыня попала на вход.
Такое поведение часто называют «rolling context» или просто обрезкой истории. Не путайте это со «sliding window attention» внутри некоторых моделей: там речь уже об архитектуре attention, а здесь — о том, что приложение решило не передавать старую часть переписки.
Почему приложения выбирают именно тихое выбрасывание, а не ошибку? Из соображений удобства, понятное дело. Представьте чат-бота, который посреди задушевной беседы вдруг падает с сообщением «ошибка: превышена длина контекста». Большинство пользователей такое не простит. Куда практичнее незаметно подрезать начало и сделать вид, что ничего не случилось. Беседа продолжается, никто не пугается. А то, что модель уже не видит первой трети разговора, всплывет потом и не так очевидно. Удобно для интерфейса, коварно для вас.
И вот тут начинаются те самые странности, ради которых разработчики городят обвязки, а пользователи строчат гневное: «ты что, тупой, я же тебе ВЫШЕ написал».
Самое неприятное, что про это выбрасывание вам не сообщают. Нет ни всплывашки «внимание, начало беседы выгружено», ни даже сноски мелким шрифтом. Разговор внешне тот же, прокрутка наверх работает, вы своими глазами видите первое сообщение — и предполагаете, что и модель его видит. А она давно нет. Вы листаете историю в интерфейсе, модель листает совсем другую, куда более короткую стопку у себя на входе.
Классика жанра — длинная ролевая игра или большой текст, который пишут по частям. На двадцатом сообщении вы зафиксировали, что у героя зеленые глаза. На сто двадцатом он внезапно кареглазый. Потому что абзац про зеленые глаза давно уехал за край окна, и свериться ей уже не с чем, кроме того, что лежит перед моделью прямо сейчас.
Особенно весело это вылезает у кодовых ассистентов и агентов, которые сами лазают по вашим файлам. Дали такому задачу — он открыл первый файл, второй, третий, залез в десятый. Каждый прочитанный файл лег в контекст. К десятому окно забито под завязку, а первый файл — с описанием какого-нибудь важного интерфейса — уже вытеснен за край. Агент бодро пишет код, который дергает функцию из того первого файла. И дергает неправильно, потому что описания функции он больше не видит.
Как понять, что вы столкнулись именно с этим? Увы, чаще всего только косвенно. Прямого индикатора в большинстве приложений нет. Так что ориентир один: если модель в длинном разговоре вдруг уверенно игнорирует то, о чем вы точно договаривались в самом начале, — с большой вероятностью это начало уже за краем окна.
Тут стоит сделать отступление и сказать, что если вы пользуетесь не родным интерфейсом, а сидите через агрегатора, то вам может оказаться доступнее больше инструментов. В том числе счетчик тех самых токенов. К примеру, у BotHub он есть. И это важный аргумент в пользу агрегаторов: им-то скрывать проблемы моделей незачем.

Кстати, держите в голове еще одну вещь, про которую почти все забывают. В окно помещается не только ваша переписка. Туда входит вообще все сразу: невидимый системный промпт, приложенные вами файлы, вся история диалога — и, внимание, место под ответ модели. Это один общий бюджет на всех.
Закинули в чат стостраничный PDF? Прекрасно, он занял половину окна, и на переписку с ответом осталась вторая половина. Вот почему после большого вложенного документа модель иногда вдруг становится туповатой и отвечает куце — ей банально негде развернуться.
Скрытый текст
Про место под ответ есть забавная асимметрия. На вход модель готова проглотить хоть целый роман, а вот выдать за один раз способна заметно меньше — потолок ответа обычно в разы ниже потолка входа. Так что «прочитать книгу» и «написать книгу в ответ» — для нее совсем не одинаковые по сложности задачи. Прочитать — пожалуйста. Выдать столько же одним куском — нет.
Почему просто не сделать окно побольше
Логичный вопрос, который тут возникает у каждого: ну так раздуйте это окно до небес, и половина костылей не понадобится. Память нынче недорогая, диски большие — в чем проблема показать модели хоть десять миллионов токенов разом?
Проблема в той самой квадратичной зависимости, про которую шла речь в главе про attention. Напомню: удвоили длину входа — и работа по сведению токенов друг с другом выросла не вдвое, а вчетверо. Утроили — в девять раз. Внимание растет квадратом от длины, и никаким железом это не обходится.
Сколько это вообще в привычных единицах, кстати? Очень грубо: окно на двести тысяч токенов — это примерно увесистый роман, целиком уместившийся на входе. Сто двадцать восемь тысяч — книжка потоньше. Миллион — небольшая полка. А статья, которую вы сейчас читаете, — порядка десятка тысяч токенов. То есть «огромное окно» оказывается не таким уж огромным, стоит начать пихать в него документацию целиком.
Из всего этого следуют две неприятности, и обе бьют по карману.
Первая — деньги и время на вычисления. Чем шире окно, тем больше пар надо перемолоть на каждый сгенерированный токен. Ответ приходит медленнее, счет от владельца модели — выше. За токены, напомню, платят и на входе, и на выходе. Длинный диалог дорожает с каждым сообщением просто потому, что та самая простыня, которую перечитывают с нуля, становится все толще. А у некоторых компаний за длинный контекст и вовсе берут с наценкой: перевалил за определенный порог токенов — и тариф за все подскакивает.
Вторая неприятность — память. И вот про нее обычно забывают. Чтобы не пересчитывать все заново на каждый новый токен, модель кэширует промежуточные результаты для уже прочитанного — это и есть тот самый KV-cache, который мелькал выше в списке ухищрений. Удобно. Беда в том, что этот кэш растет вместе с длиной контекста и живет в видеопамяти. И ест ее прожорливо. Знакомая история у всех, кто гоняет открытые модели локально.
Сама модель в видеокарту влезает спокойно, а стоит задрать контекст подлиннее — кэш отжирает остаток памяти, карта говорит «мест нет», и разговор обрывается на полуслове. Лечится либо урезанием окна, либо покупкой карты пожирнее. Оптимизации вроде FlashAttention делают вычисление внимания быстрее и экономнее по памяти, а разреженные схемы внимания могут уменьшать объем связей между токенами. Но длинный контекст все равно не становится бесплатным.
Вот поэтому окно и конечное. Потому что каждый лишний токен стоит вычислений, времени и видеопамяти — причем по нарастающей. Длинный контекст — это не бесплатная возможность, которую нам подарили по доброте душевной. За каждый лишний лист на входе кто-то платит. Чаще всего — вы.
Слепое пятно посередине
Казалось бы, вывод напрашивается простой: следи, чтобы все влезало в окно — и проблема решена. Влезло — значит, модель все видит и помнит одинаково хорошо.
Если бы.
Тут есть вторая засада, и она хитрее первой. Допустим, вся ваша переписка уместилась в окно. Ничего не вытеснено, все на месте. Так вот, даже в этом случае модель норовит запороть ровно то, что лежит в середине.
Есть такое исследование — стэнфордское, 2023 года, с говорящим названием «Lost in the Middle», «потерянные в середине». Идея эксперимента простая. Берем модель с длинным контекстом, прячем внутрь нужный факт — то в начало, то в середину, то ближе к концу. А потом задаем вопрос, ответить на который можно, только если этот факт найти и пустить в дело.
Результат вышел интересный. Факт, лежавший в начале и в конце, модель доставала уверенно. А вот закопанный в середину — вылавливала заметно хуже. Будто внимание у нее острое по краям, а к центру замыливается.
Важно. Это не байка и не единичный казус. Замеры последних лет картину подтверждают. На длинных окнах точность по середине у разных моделей проседает где-то на десять-двадцать пять процентов по сравнению с краями. Конкретные цифры гуляют от модели к модели, но тенденция устойчивая.
И это важно помнить. Чем шире окно — тем больше у вас этой самой середины, в которой есть где утонуть.
Аналогия простая. Представьте, что вас заставили за один присест прочитать роман на шестьсот страниц, а потом спросили про мелкую деталь со страницы триста. Начало вы помните — с него начинали. Концовку помните — она свежая. А середина расплылась в кашу. У модели ровно так же. Только она не признается, что не помнит, а начнет галлюцинировать. И поди отличи это от правды.

Отсюда же, кстати, растет популярный способ проверять модели — тест «иголка в стоге сена». В длиннющий текст прячут одну нелепую фразу, что-нибудь вроде «секретный код: банан-77», в случайном месте. А потом спрашивают: какой был секретный код? Выловила из любой точки окна — молодец. Нашла по краям, а в середине промахнулась — вот вам та самая середина в действии.
Вывод из всего этого такой. Заявленный размер окна и реально надежная работа по всему этому окну — разные вещи. Миллион токенов означает, что модель технически может принять такой объем, но не гарантирует, что она одинаково надежно использует каждую деталь внутри него. Дальше — как повезет. Так что не стоит закидывать в окно целый роман и ждать, что модель удержит в голове каждую деталь со страницы триста. Начало и конец удержит. Середину — расплывчато.
Окно набивается быстрее, чем кажется
Есть еще один неочевидный момент. Вы привыкли думать, что окно наполняете вы — своими сообщениями. Напечатали реплику, она легла в контекст, и так помаленьку. На деле в современных ассистентах окно набивается куда быстрее, и львиную долю туда кладете вовсе не вы.
Смотрите, что попадает в окно помимо вашего текста.
Во-первых, ответы самой модели — они тоже остаются в переписке и тоже занимают место.
Во-вторых, если ассистент умеет ходить в инструменты — результаты инструментов тоже занимают контекст. Иногда это полный текст страницы или файла, иногда — выбранные фрагменты, summary или результаты поиска по документу. Но для пользователя это почти невидимо: он написал короткий вопрос, а под капотом в окно могли попасть тысячи токенов служебного текста.
В-третьих, у «думающих» моделей есть отдельная цепочка рассуждений перед ответом, и она тоже отъедает бюджет. Плюс приложенные файлы, плюс невидимый системный промпт, плюс подложенные memory и RAG-куски.
Сложите все это — и окажется, что после пары вызовов поиска и одного прикрепленного PDF от вашего якобы огромного окна остались рожки да ножки. Вы написали три коротких сообщения, а контекст уже под завязку. Просто набили его не вы — набили инструменты и обвязка.
Вот почему «у меня же совсем короткий диалог, чего ему не хватает?» — ощущение обманчивое. Короткий он только на вид. Под капотом туда могло уехать в десятки раз больше токенов, чем вы напечатали своими руками.
Костыли вместо памяти
Итак, что мы имеем. Памяти у модели нет. Окно конечное, лишнее вытесняется за борт. Да еще и середину окна модель читает вполуха. На первый взгляд — катастрофа. На такой штуке невозможно построить нормального ассистента, который помнит ваши прошлые разговоры и не путается в длинной беседе.
Но ассистенты-то работают. И помнят. Как?
А вот тут начинается самое интересное — зоопарк костылей. Раз у модели нет памяти, а окно не резиновое, всю «память» приходится строить снаружи. Подпорками. За последние пару лет их накопилось прилично, пройдусь по главным — от самой тупой к самой хитрой. Сразу оговорюсь: они все про одно и то же — как половчее распорядиться тем местом в окне, которое есть. Фундаментальную архитектуру они не изменяют.
Костыль нулевой, самый примитивный — обрезка истории. Это ровно то скользящее окно, о котором я уже говорил выше. Окно заполнилось — выкидываем самые старые сообщения, и все. Дешево, быстро, тупо. Минус очевиден: теряете начало без разбора, заодно со всеми важными договоренностями. Плюс — работает мгновенно и ничего не стоит.
Суммаризация, она же «summary». Идея такая: вместо того чтобы тупо выбрасывать старье, давайте его сожмем. Берем первые, скажем, тридцать реплик, отдаем их модели (часто — модели попроще и подешевле) с задачей «перескажи коротко, о чем тут договорились». Получаем абзац-выжимку. Тридцать реплик убираем, абзац кладем на их место. Места он занимает в разы меньше, а суть вроде бы сохранилась. Это как заменить толстую пачку черновиков одной страничкой конспекта.
Удобно. Но есть нюанс. Конспект может выкинуть ровно ту деталь, которая вам понадобится через двадцать сообщений. Или, что хуже, переврать ее. Модель-конспектатор ведь тоже не идеальна — она подвержена всему, о чем мы говорим в этой статье. Свернула «делаем на Python» в обтекаемое «обсуждали выбор языка» — и дальше ассистент с чистой совестью предлагает примеры на чем попало. А вы потом гадаете, с чего это он сорвался с языка, который вы вроде бы зафиксировали полчаса назад.
Следующая подпорка — память, «memory». Работает так. Приложение выдергивает из ваших разговоров не все подряд, а долгоживущие факты лично про вас. «Пишет на русском». «Зовут так-то». «Терпеть не может вот этот формат ответов». Складывает их в отдельный блокнотик, к конкретному диалогу отношения не имеющий. И в следующий раз — даже если вы открыли абсолютно новый, чистый чат — эти факты первым делом подкладываются в окно.
Хорошая житейская аналогия — официант в кафе, куда вы ходите годами. Он не помнит ваши прошлые разговоры дословно. Но твердо знает, что вы всегда берете без лука. Этот факт он держит в голове отдельно от любого конкретного заказа и применяет каждый раз. Вот memory — это про «без лука». Только, опять же, не модель помнит про лук. Это блокнотик помнит, а приложение услужливо подкладывает страничку из него в окно перед началом разговора.
Скрытый текст
Тут стоит держать в голове одну вещь. Раз где-то ведется блокнотик с фактами про вас — значит, эти факты где-то лежат. Иногда это именно то, что нужно, удобно же. Иногда — то, что неплохо бы периодически чистить. Загляните как-нибудь в этот раздел настроек у вашего любимого ассистента и посмотрите, сколько он успел про вас записать между делом. Даже жутковато станет.
И, наконец, самый мощный из костылей. RAG.
RAG, или курьер за нужной страницей
Расшифровывается это как retrieval-augmented generation — «генерация с подтягиванием нужного». Звучит страшновато, но идея простая.
Смысл вот в чем. Не надо тащить в окно всю библиотеку. Пусть библиотека стоит на полках, отдельно. А когда придет вопрос — мы пошлем за нужными страницами курьера, и он принесет в окно только их. Остальное останется на полках и место не займет.

А теперь — помните те самые эмбеддинги из начала статьи? Векторы, координаты в пространстве смыслов, где «король» рядом с «мужчиной», но далеко от «королька»? Вот где они разворачиваются по-крупному.
Все ваши документы заранее рубятся на небольшие куски. Каждый кусок прогоняется через модель-эмбеддер и превращается в такой вектор — координаты его смысла. Все векторы складываются в специальную базу. Когда вы задаете вопрос, он тоже превращается в вектор. И система ищет в базе те куски, чьи координаты по смыслу ближе всего к вопросу. Находит три-четыре самых подходящих абзаца — и кладет в окно только их, рядом с вашим вопросом.
Скрытый текст
Отдельная боль тут — на какие именно куски рубить документ. Разрежешь слишком мелко — и нужная мысль окажется разорвана пополам между двумя кусками, ни один из которых сам по себе на вопрос не отвечает. Разрежешь слишком крупно — в окно поедет много лишнего, да еще и середина каждого куска утонет ровно по тем же законам, что мы разбирали выше.
Универсального правильного размера нет, под каждый тип документов его подбирают индивидуально. Так что когда RAG-ассистент отвечает мимо, дело нередко не в модели, а в том, что документ порезали неудачно.
Заметьте, в чем фокус. Поиск идет не по ключевым словам, а по смыслу. Поэтому RAG находит нужный абзац, даже если вы спросили совсем другими словами, чем было написано в документе. Запрос «как вернуть деньги за заказ» подтянет абзац про «процедуру возврата средств», хотя ни одного общего слова там нет.
Так ассистент умудряется «знать» содержимое ваших пятисот страниц, ни разу не положив эти пятьсот страниц в окно целиком. Он кладет только те абзацы, что относятся к делу. Умный человек ведь тоже не помнит наизусть всю энциклопедию — он помнит, на какой полке какой том, и умеет быстро дойти до нужного.
Но и тут есть оговорка. RAG работает ровно настолько хорошо, насколько хорошо курьер находит нужную страницу. Притащил не тот абзац — и модель уверенно сочинит ответ по неподходящему материалу, даже не моргнув. Промахи поиска — главная головная боль всех RAG-систем.
В жизни эти костыли редко работают поодиночке. Нормальный современный ассистент тащит сразу несколько: свежую переписку держит как есть, что постарше — сжимает в summary, факты про вас хранит в memory, а по большим документам ходит через RAG. Выходит многоэтажная подпорка, где каждый этаж прикрывает слабое место предыдущего. Четыре костыля, примотанные к тому самому окну, которое как было на свои N токенов, так и осталось.
И каждый из этих костылей, заметьте, добавляет свою точку отказа. Суммаризатор может переврать. Поиск в RAG — промахнуться. Memory — подсунуть устаревший факт про вас. Скользящее окно — отрезать лишнее. Когда ассистент в итоге отвечает невпопад, причина может прятаться в любом из этажей этой конструкции, и со стороны не всегда поймешь, в каком именно. Тем занятнее, что вся эта шаткая башня в большинстве случаев все-таки работает — и работает достаточно прилично, чтобы рядовой пользователь вообще не подозревал о ее существовании.
И это, пожалуй, главное, что стоит унести из этой главы. Ни один из костылей не дал модели память. Памяти у нее как не было, так и нет. Просто люди научились хитрее управлять тем, что в каждый конкретный момент лежит у модели на входе.
Поднимай базу данных!
Тут напрашивается логичное возражение. Ребята, ну хватит костылей. Подключите модели нормальную базу данных, пусть пишет туда все подряд и достает, когда надо. Вечная память, проблема закрыта.
Вот только если присмотреться — это и есть RAG с memory. Та самая база, тот самый курьер за нужной страницей. Других вариантов, по большому счету, и нет. Рассуждать модель умеет только над тем, что лежит у нее на входе здесь и сейчас. Все «долгосрочное» обязано в нужный момент попасть в окно — иначе для рассуждения его попросту не существует. А окно, мы помним, конечное.
То есть «бесконечная память» упирается вовсе не в объем хранилища. Хранилище-то дешевое, диски нынче огромные. Она упирается в две другие вещи. Первая — что именно из этого огромного хранилища достать прямо сейчас и положить в окно? Достанешь не то — получишь уверенную чушь. Это все та же проблема поиска, что и у RAG. Вторая — даже если достал правильное, оно должно влезть в окно рядом со всем остальным и не утонуть в середине.
И заметьте, обе эти проблемы мы уже разбирали по ходу статьи. Это не какие-то новые препятствия — это ровно те же грабли: точность поиска и конечное, да еще и мутное по центру окно. Внешняя память не обходит их стороной, она об них же и спотыкается, только в профиль.
«А просто дообучить модель на нашей переписке?» — спросит кто-нибудь. Дообучение — это вообще про другое. Оно меняет веса модели или отдельный адаптер конкретной версии. Это долго, дорого и не оперативно. Никто не станет дообучать модель после каждой вашей реплики. Так что и этот путь упирается ровно туда же: к моменту ответа все нужное обязано оказаться в окне. Других вариантов у модели просто нет. Поэтому и живем на костылях. И, подозреваю, поживем еще.
Что с этим делать вам
Ладно, с устройством разобрались. Теперь практика — что лично вы можете сделать, чтобы разговор не рассыпался раньше времени. Откровений не будет, все довольно скучно и приземленно. Но работает.
Держите важное в начале и в конце, не в середине. Раз модель проседает по центру — ключевые требования стоит держать там, где она их точно увидит. В первом сообщении и продублировать ближе к концу.
Повторяйте важное, не надейтесь на «я же говорил выше». Если требование критично — впишите его в каждое крупное сообщение заново. Да, чувствуешь себя занудой. Зато оно гарантированно лежит в свежей части окна, а не утонуло где-то в глубине.
Не валите все в один бесконечный чат. Новая тема — новый диалог. Старая переписка, которая к делу уже не относится, только занимает место и вытесняет то, что вам сейчас реально нужно. К тому же, помните, длинный чат вы еще и оплачиваете дороже на каждом шаге — за токены-то платят. Привычка плодить отдельные чаты под отдельные задачи поначалу кажется неудобной, а потом экономит и нервы, и деньги.
Долгоживущие вещи выносите в настройки, а не в переписку. Почти у всех больших сервисов теперь есть отдельное поле — «инструкции», «о себе», системный промпт. То, что вы туда впишете, подкладывается в окно само и в начале каждого разговора. Если вы каждый раз заново объясняете, что отвечать надо по-русски и без воды — перестаньте. Впишите это один раз туда, где оно переживет любую обрезку истории.
Делайте конспект сами, не дожидаясь, пока за вас это сделает суммаризатор и переврет. Раз в десяток-другой сообщений можно попросить: «подведи короткий итог тому, о чем мы договорились». Получите свою выжимку — и ее удобно скормить в свежий чат, начав с чистого, но не пустого окна.
Не пихайте гигантские логи и книги целиком, если вам нужен из них один кусок. Даже если влезет — середина утонет, а заплатите вы за все токены до единого. Лучше вырезать нужный фрагмент и дать только его.
Следите за тревожным звоночком. Если модель вдруг «поглупела» сразу после того, как вы вкинули большой файл или разговор заметно затянулся, — это почти наверняка не модель сломалась. Это окно переполнилось. Лечится новым чатом или выкидыванием того, что вы туда зря навалили. Чем раньше заметите — тем меньше потом разгребать за ассистентом, который успел напороть дел на вытесненном контексте.
И вопрос, и большой текст лучше располагать так, чтобы сам вопрос шел в конце. Если вставляете объемный кусок и просите с ним что-то сделать — пишите задание после него, внизу. Так оно ложится на свежий край окна, где внимание острее, а не тонет в начале под весом полотна.
Последнее. Большое окно — не панацея. «Миллион токенов» звучит круто, спору нет. Но платите вы за каждый токен, точность по центру все равно гуляет, а ответ от длины замедляется. Берите окно под свою реальную задачу, а не максимальное из доступных. Если ваши разговоры в среднем короткие — разница между окном на сто тысяч и на миллион вам вообще ни о чем, кроме счета.
Вечное сегодня
Вернемся к тому странному собеседнику с амнезией, с которого мы начали.
Теперь-то понятно, что он ничего не забывает — потому что нечего забывать. Каждый раз ему заново подсовывают пачку листов и просят: дочитай и ответь на последний. Что в пачку положили — то он и видит. Что из пачки убрали или что не поместилось — того для него не существует. У него нет «вчера». Есть только то, что прямо сейчас лежит перед глазами.
И когда мы в сердцах пишем ассистенту «ты что, забыл, о чем мы говорили?» — вопрос, если вдуматься, неправильный. Забыть можно только то, что когда-то помнил. А он не помнил. Никогда. Правильный вопрос звучит иначе: «а это вообще еще влезает в окно?»
Раньше, до появления всяких ухищрений проблему переполнения можно было легко диагностировать. Сегодня ситуация изменилась, и то, что контекст кончился от вас будут прятать до последнего. Я описал только самые популярные механики оптимизаций, на самом деле их куда больше. И каждая из них может вызвать очень странное и нетиповое поведение модели в каком-то узком случае.
Понимать это полезно и нужно. Только в этом случае вы сможете правильно истолковать галлюцинации и пересобрать свой план действий, чтобы от них избавиться. Надеюсь, что эта статья вам поможет в этом нелегком деле.





















