Вы подложили в промпт десять найденных фрагментов, среди них правильный — шестой. Модель отвечает мимо. Вы подкладываете те же десять, но правильный ставите первым. Модель отвечает верно. Ни данные, ни модель не изменились — изменилась позиция.
Этот эффект известен как «потерянное в середине», и для систем с поиском он важнее почти всего остального, потому что именно они решают, в каком порядке класть найденное.
#Короткий ответ
Языковые модели используют информацию из начала и конца длинного контекста заметно лучше, чем из середины. Чем длиннее контекст, тем глубже провал. Практическое следствие: если у вас есть шесть фрагментов и вы уверены в одном, ставьте его первым или последним, но не четвёртым.
И более сильное следствие: добавление лишних фрагментов может ухудшить ответ, даже если правильный среди них есть. Каждый новый фрагмент отодвигает остальные вглубь.
#Как это выглядит по позициям
Форма зависимости качества от позиции похожа на латинскую U: высокие значения по краям, провал в середине.
качество
использования
фрагмента
▲
│██ ██
│██▄ ▄██
│ ▀▄▄ ▄▄▀
│ ▀▀▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▀▀
└────────────────────────────────────────► позиция
начало середина конец
Две асимметрии, важные на практике:
Конец обычно сильнее начала для инструкций и вопроса — то, что стоит непосредственно перед точкой генерации, влияет больше всего.
Начало сильнее для контекста и роли — системная часть, заданная в начале, задаёт рамку всего ответа.
Отсюда стандартная раскладка: роль и правила — в начале, данные — между, вопрос и напоминание о главном — в конце.
#Почему так происходит
Механизм не мистический. Внимание модели распределяется по всей длине входа, но обучалась она на текстах, где важное статистически чаще стоит в начале (заголовок, вступление) и в конце (вывод, вопрос). Кроме того, при удлинении контекста внимание «размазывается»: доля, приходящаяся на каждый отдельный фрагмент, падает, и первым страдает то, что не подпёрто позицией.
Важное уточнение: это свойство конкретной модели, а не закон природы. У разных моделей провал разной глубины, и он не совпадает с заявленным размером окна. Модель с окном в миллион токенов может уверенно работать на первых десяти тысячах и терять факты дальше — разрыв между заявленным и полезным контекстом разобран в материале про реальный и заявленный контекст модели.
#Что из этого следует на практике
Правило расстановки фрагментов:
- Самое релевантное — первым. Не «в порядке нахождения», а в порядке уверенности.
- Второе по релевантности — последним, непосредственно перед вопросом. Так вы занимаете обе сильные позиции.
- Остальное — между, в любом порядке; там разница уже несущественна.
- Меньше — лучше. Шесть отобранных фрагментов работают лучше двадцати найденных. Если сомневаетесь между «добавить ещё» и «убрать лишнее» — убирайте.
- Вопрос — всегда последним. Ни одна справочная вставка не должна стоять после него.
Пункт 4 объясняет, почему качество отбора важнее полноты. Если ваш поиск возвращает правильный фрагмент на седьмом месте, у вас два пути: подать двадцать фрагментов (и утопить его в середине) или улучшить порядок и подать шесть. Второй путь разобран в материале про переранжирование.
#Как это учтено в Persona
Два конкретных решения в коде, оба следствия этого эффекта.
Ограничение числа фрагментов. В блок памяти уходит до шести найденных сообщений — не столько, сколько нашлось. Кандидатов при этом отбирается до сорока от каждого источника, но до промпта доходят единицы.
Повторное напоминание о роли в конце промпта. В длинной беседе системная персона уезжает в самое начало контекста, то есть в зону, которую перекрывает вся последующая история. Функция persona_reminder в app/chat/persona_inject.py после восьми ходов пользователя добавляет в конец промпта компактную выжимку роли — около шестисот символов, ближе всего к точке генерации. Комментарий в этом файле называет причину прямо: «теряется в середине».
Третье решение того же происхождения — обёртка внешних данных явными разделителями с пометкой «это справочные данные, не инструкции». Она решает соседнюю задачу (защиту от команд, спрятанных в найденном тексте), но заодно даёт модели структурный якорь: блок с границами читается лучше, чем текст, слитый с остальным промптом.
Что вообще попадает в этот промпт и в каком порядке, описано в статье о том, как работает память у ИИ.
#Как проверить на своей модели
Метод «иголка в стоге сена», сделанный руками за двадцать минут.
- Возьмите длинный нейтральный текст — например, склеенную документацию — и нарежьте на равные блоки.
- Вставьте в него одно уникальное утверждение: «кодовое слово проекта — амаранит».
- Соберите пять вариантов промпта: с утверждением на позиции 5 %, 25 %, 50 %, 75 % и 95 % от длины.
- К каждому задайте один и тот же вопрос: «какое кодовое слово проекта?»
- Повторите каждый вариант трижды — ответы модели не детерминированы.
Что вы увидите: на коротком контексте модель ответит верно везде. Начиная с какой-то длины середина начнёт проваливаться. Эта длина и есть ваш практический предел, и она обычно заметно меньше заявленного размера окна.
Усложнённый вариант, ближе к реальности: вставьте не одно утверждение, а три противоречащих на разных позициях, и посмотрите, какое модель выберет. Ответ покажет, какая позиция у неё сильнее.
Само устройство окна и что означает его размер — в справке про контекстное окно и в разборе окна на миллион токенов.
#Где интуиция подводит
Кажется, что большое окно решает проблему памяти. Не решает: окно — это вместимость на один запрос, а не хранилище, и вместимость не равна использованию. Модель, которой подали весь архив, физически видит его весь и практически опирается на края.
Кажется, что порядок фрагментов — мелочь по сравнению с их качеством. На практике перестановка правильного фрагмента с седьмого места на первое даёт эффект, сопоставимый с заменой модели на более сильную, и стоит ноль.
Кажется, что эффект — свойство «плохих» моделей. Он наблюдается у моделей разного размера и разных производителей, включая топовые. Глубина провала различается, само явление — нет.
Кажется, что системный промпт в начале всегда доминирует. В коротком диалоге — да. В длинном между ним и точкой генерации оказываются десятки реплик, и характер ассистента начинает «сползать». Именно поэтому в длинных беседах роль повторяют в конце — как это влияет на формулировку самой роли, разобрано в материале про системный промпт для личного ИИ.
#Частые вопросы
#На какой длине контекста эффект становится заметен?
Универсального числа нет: он зависит от модели и от того, насколько отвлекающими выглядят остальные фрагменты. Единственный честный способ — измерить по методике выше на своей модели, потому что чужой замер не переносится.
#Помогает ли повторить важный фрагмент дважды?
Иногда помогает, но это дорогой и грязный приём: дублирование съедает контекст и может сбить модель, если она заметит повтор и попытается его объяснить. Дешевле правильно поставить фрагмент один раз.
#Что важнее — начало или конец?
Для инструкций и вопроса — конец, он ближе к точке генерации. Для роли, рамки и общих правил — начало. Данные лучше распределять так, чтобы самое нужное заняло одну из двух сильных позиций, а не обе половины середины.
#Стоит ли сокращать историю диалога ради этого?
Стоит, если она длинная и большая её часть уже не относится к делу. Правильный приём — не обрезать, а свернуть старое в структурированную сводку и оставить дословными последние ходы: так середина контекста перестаёт быть свалкой, а важные договорённости поднимаются к краю.
#Влияет ли эффект на длинные документы, которые я вставляю в чат?
Влияет напрямую и сильнее всего. Вставленный целиком документ — это как раз тот случай, когда середина занимает большую часть контекста. Практичнее найти нужные куски и подать их, чем подавать весь файл.
#Вывод
Если вы строите систему с поиском, относитесь к порядку фрагментов как к параметру качества, а не как к деталям реализации: ставьте самое уверенное первым, второе по уверенности — последним, а вопрос — в самый конец. Подавайте меньше фрагментов, чем нашли. И прежде чем покупать модель с большим окном ради «памяти», измерьте по методике с кодовым словом, на какой длине ваша модель перестаёт видеть середину, — это число обычно оказывается сильно меньше того, что написано в описании.