Модель не знает ваших документов, и рассказать ей о них можно двумя путями. Либо отправить текст целиком вместе с вопросом, либо построить поиск, который достанет только подходящий фрагмент. Работают оба. Ломаются и стоят они по-разному.
Чем один подход отличается от другого
Длинный контекст: берёте документы, склеиваете и отправляете модели вместе с вопросом. Что из всего этого важно, она решает сама.
RAG (retrieval-augmented generation) устроен иначе. Заранее тексты режутся на куски, и каждый кусок превращается в embedding, вектор, в котором закодирован смысл. Когда приходит вопрос, система ищет куски, ближайшие к нему по смыслу, и в промпт уходит только эта выборка. Корпус остаётся снаружи.
С виду разница небольшая. Счёт и качество ответов показывают обратное.
Как это отражается на счёте
В длинном контексте каждый вызов оплачивает весь корпус как входные токены. Вопрос про один абзац из тысячи страниц обходится как вопрос про все страницы сразу. Корпус вырос, и цена каждого запроса выросла вместе с ним, линейно и без потолка.
Кеширование промпта частично спасает. Если один и тот же большой контекст используется снова и снова в пределах окна кеша, полную цену платите один раз, дальше вход дешевле. Но когда вопросы разные, а корпус меняется, кеш не спасает.
У RAG цена запроса зависит не от размера корпуса, а от размера выборки, которую вы отдаёте модели. База может вырасти до миллиона документов, а в промпт всё равно уйдёт горстка кусков. За это платите другим: нужны векторная база, пайплайн эмбеддингов, а иногда и ещё один вызов модели, чтобы переранжировать кандидатов.
Как это отражается на точности
Слабое место длинного контекста известно: детали из середины большого текста модель удерживает хуже, чем из начала и конца. Чем длиннее контекст, тем выше шанс, что нужный факт утонет в шуме.
У RAG слабость иная. Точность упирается в качество поиска. Нарезка грубая, нужный фрагмент не попал в выборку, и модель отвечает уверенно и неверно, потому что данных не видела вообще. Ошибка тихая. Ни записи в логе, ни извинения, только неправильный ответ.
Что приходится поддерживать
Длинный контекст прост по конструкции: отдельного пайплайна нет, ночью ломаться нечему. Расплата за простоту такая: бюджет токенов на вас, а если корпус растёт, рано или поздно вы упрётесь в окно модели.
RAG это целая система. Нужно выбрать стратегию нарезки, закрепить версию модели эмбеддингов, пересобирать индекс при каждом обновлении контента и проверять, что поиск находит именно то, что нужно. Любое звено способно деградировать молча. Узнаёте вы об этом обычно не из алерта, а из жалоб пользователей на странные ответы.
Гибрид, к которому приходит большинство
Выбрать одно из двух в чистом виде удаётся редко. Небольшой стабильный корпус, документацию одного проекта или базу знаний команды, обычно кладут в контекст целиком, особенно когда доступно кеширование.
Растущий или неоднородный корпус обычно уходит в RAG, но с одной поправкой: поиск возвращает не короткие обрывки, а целые релевантные документы, и уже они целиком попадают в контекст. Выходит точность поиска плюс способность модели рассуждать по полному тексту, а не по вырванной фразе.
Пример. Бот поддержки на пяти статьях справки спокойно живёт на длинном контексте: все пять влезают в промпт с запасом. Тот же бот на трёхстах страницах документации API, где раздел про аутентификацию правится каждую неделю, обычно переезжает на поиск. Весь корпус в контекст уже не уместить так, чтобы модель не путалась в деталях.
Как выбрать под свою задачу
Большинство случаев решают три вопроса.
Первый: насколько велик корпус и как быстро он растёт. Если он целиком помещается в контекст с запасом и почти не меняется, поиск не нужен.
Второй: как часто меняются данные. Контент обновляется каждый день, значит, и индекс придётся пересобирать каждый день, а это деньги и время команды.
Третий: нужен точный факт или синтез по многим источникам. Точный факт лучше найти поиском и процитировать. Синтез по большому массиву материалов чаще проще делать на полном контексте.
Разницу в деньгах посчитать проще, чем кажется. Калькулятор codexkey на сайте прикинет цену запроса при разных размерах контекста, а результат можно сравнить с ценой пары вызовов, которые обычно нужны RAG, переранжирование включая.
Коротко
Длинный контекст проще и на среднем объёме точнее, но счёт растёт вместе с корпусом. RAG держит счёт ровным при любом объёме, зато тянет за собой инфраструктуру и риск не найти нужный кусок. Небольшой стабильный корпус: контекст. Растущий и разнородный: поиск, который отдаёт модели целые документы, а не обрывки.