Когда разработчики впервые открывают для себя контекст-инжиниринг, всё выглядит максимально прямолинейно: нашёл нужную информацию, засунул в промпт, получил адекватный ответ. Пока контекст умещается в пару параграфов или собирается руками — так оно и работает, вопросов нет.
Настоящий ад начинается в тот момент, когда сбор контекста отдаётся на откуп автоматике, которая парсит десятки файлов, баз данных и сторонних API.
Почему авто-сбор ломает то, что руками работало
Корень проблемы: автоматические скрипты собирают данные без осознания их смысла. Скрипт не знает, что именно он тащит, — он тащит всё, что подходит по формальному признаку. В результате в один промпт спокойно могут прилететь три вида мусора сразу.
Разные версии правды. Инструкция из документации 2021 года и фрагмент кода из обновления 2026 года, которые прямо противоречат друг другу. Оба валидны как «источник», оба попадают в контекст.
Взаимоисключающие вводные. Позавчерашний лог, где система говорит «пользователь заблокирован», и сегодняшняя запись из БД со статусом «активен». Скрипт подтянул обе записи, потому что обе про одного пользователя.
Шум и галлюцинации источника. Данные из разрозненных сервисов, использующие одинаковые термины для обозначения абсолютно разных вещей. Совпал термин — значит, релевантно, решает скрипт. А на деле — нет.
Если скармливать целевой LLM такой винегрет, она ведёт себя предсказуемо плохо. Модель начинает метаться от одной крайности к другой, выдавать взаимоисключающие решения на один и тот же запрос или пытаться «усреднить» то, что усреднению не подлежит. На выходе — сгенерированная с абсолютно уверенным видом ахинея, которую потом приходится разгребать часами. И самое неприятное: целевая модель отработала честно. Мусор на входе — мусор на выходе, претензий к самой LLM нет.
Прослоечный арбитраж: ещё один этап между сбором и решением
Чтобы не превращать целевую LLM в гадалку, в цепочку данных встраивается ещё один этап — модель-арбитр (Consistency Evaluator).
Парадигма простая: перед тем как собранный скриптом контекст уходит в основную модель для решения ключевой задачи, он прогоняется через отдельную, более быструю или заточенную под анализ логики LLM. Это не замена целевой модели и не усложнение промпта — это отдельная проверочная ступень между сбором и решением.
[Источники данных] ──> [Скрипт сбора] ──> [Модель-арбитр] ──┬──> (ОК) ──────> [Целевая LLM]
└──> (Конфликт) ─> [HITL Флаг]
Задача арбитра — не решать пользовательскую задачу, а оценить пригодность контекста для неё. Он делает три вещи:
Ищет логические дыры. Проверяет, не противоречит ли Фрагмент А Фрагменту Б.
Оценивает хронологию. Фильтрует устаревшие вводные, если в контексте есть более свежие данные по тому же вопросу.
Классифицирует конфликт. Определяет, является ли расхождение критическим блокером или просто мелким шумом, который можно отфильтровать на лету.
Вот эта классификация — ключевой момент. Не всякое расхождение стоит эскалации. Мелкий шум — одинаковые термины из разных сервисов, устаревшая строка при наличии свежей — арбитр снимает сам и пропускает чистый контекст дальше. А вот жёсткое противоречие, которое нельзя разрулить без потери смысла, — это уже не его зона ответственности.
Когда машине нужен человек
Самая важная часть схемы — своевременный HITL (Human-in-the-Loop).
Если модель-арбитр видит, что контекст содержит жёсткие противоречия, которые невозможно разрулить без потери смысла, она не пытается угадать правильный ответ. Целевая LLM в такой ситуации уверенно выберет что-нибудь и поедет дальше. Арбитр вместо этого моментально поднимает флажок — генерирует алерт, стопорит пайплайн и отправляет спорный кусок контекста человеку-оператору.
Оператор подтверждает правильную версию, которая ложится обратно в источники данных. Дальше контекст пересобирается, и если противоречий больше нет — только после этого чистый, непротиворечивый контекст уходит целевой модели. Важно, что фикс идёт в источник, а не в разовый промпт: разрешённое противоречие не всплывёт при следующем сборе по тому же вопросу.
Плата за спокойствие
Честный трейд-офф: да, это добавляет один лишний шаг в архитектуру. Пайплайн становится длиннее, появляется ещё один вызов модели, а при жёстком конфликте — ещё и пауза на человека.
Но арифметика тут не в пользу «прямой» схемы. Лучше потратить 200 миллисекунд и три копейки на вызов оценивающей модели, чем получить невалидный результат от дорогой LLM и отправить пользователю бред, сгенерированный на основе конфликтных данных. Один вызов арбитра стоит копейки и миллисекунды; часы на разгребание уверенной ахинеи стоят инженерного времени и доверия к системе.
Что ломается в схеме арбитража
Арбитр — не серебряная пуля. Поскольку сам работает на LLM, он унаследует те же пределы: галлюцинирует на длинных контекстах, может пропустить противоречие, которое вписывается в его слепую зону, или классифицировать жёсткий блокер как мелкий шум. Особенно это касается хронологии: если в контексте несколько источников без явных временных меток, арбитраж по дате создания файла или таймстампу записи может ошибиться в пользу не того источника. Поэтому конфигурация арбитра — отдельная инженерная задача: выбор модели, размера окна и порога уверенности, при котором конфликт считается подтверждённым.
Миф о «просто засунуть в промпт»
Контекст-инжиниринг — это не про поиск релевантных данных. Это про сборку контекста, в котором данные не противоречат друг другу. Скрипт сбора сигнализирует о релевантности по формальному признаку, и без арбитража в промпт идёт всё, что нашлось. Пока контекст собирает человек, он же держит смысл в голове и ловит противоречия на лету. Автоматика этого не умеет.
Если ваша целевая LLM уверенно генерирует ахинею — проверьте вход.