Преобразование запроса полезно, когда лечит конкретный сбой в поиске. В декоративный слой оно превращается в момент, когда его добавляют, потому что на схеме чего-то не хватало.
Точечное преобразование
Запрос меняется, чтобы исправить известную проблему поиска.
- лучше полнота на смутных вопросах
- лучше маршрутизация по корпусу
- измеримый выигрыш в качестве top-k
Преобразование ради галочки
Система добавляет шаги просто потому, что так выглядит «сложнее и умнее».
- растёт задержка
- сложнее разбирать сбои
- поиск по-прежнему промахивается по старым причинам
Преобразование запроса — это семейство, не приём
Часто говорят как об одном приёме. На деле это разные семейства. Переписать вопрос в более явный вид. Разложить один вопрос на несколько меньших. Сформировать более абстрактный step-back вопрос. Сгенерировать гипотетический ответ или документ (HyDE). Прогнать несколько вариантов поиска и слить результаты.
У них разная задача. Если складывать в одну корзину, выходит уверенная, но бессмысленная аналитика.
Rewrite, когда проблема в самом вопросе
Самый простой случай по-прежнему частый. Пользователь задал что-то коротко, смутно, с пропущенными сущностями.
Например.
- «Что изменилось после прошлого?»
- «Это вообще можно по политике?»
- «Сколько теперь длится?»
По таким формулировкам искать тяжело. Rewrite помогает восстановить недостающие объекты, сделать явными время и предмет запроса.
Это самый дешёвый шаг. И, наверное, самый лёгкий, чтобы им злоупотребить. Если исходный запрос и так конкретен, rewrite чаще добавляет задержку, чем сигнал.
Decomposition, когда ответ требует нескольких поисков
Полезно там, где пользователь думает, что задал один вопрос, а корпус требует нескольких lookup-шагов. Сравнить две политики. Ответить, где есть и основное правило, и исключение. Собрать ответ из нескольких фактов, лежащих в разных местах.
Один поисковый проход проигрывает, потому что у каждого подвопроса своя опорная точка.
Цена понятна. Больше проходов, больше задержки, больше мест, где можно случайно испортить итоговый контекст. Decomposition оправдан, когда задача и правда составная. Если проблема в плохом корпусе, он только добавит шума в красивом костюме.
Step-back для поиска по понятию
Step-back prompting устроен так. Система сначала формулирует более общий вопрос, потом ищет и по нему.
Полезно, когда прямой запрос слишком конкретен и проскакивает мимо понятия, которое управляет ответом. Узкий рабочий вопрос лучше ищется, если параллельно задать себе более общий вопрос про принцип правила или юридическую категорию.
Выигрыш — концептуальный recall. Цена — дополнительный модельный вызов и ещё одна поисковая ветка. Если корпус аккуратный, а сам вопрос хороший, step-back почти ничего не даёт. Если пользователь крутится вокруг понятия, которое сам не может назвать, помогает сильно.
HyDE — это поисковый трюк
HyDE строится так. Система сначала генерирует гипотетический ответ или документ, потом ищет по embedding этого синтетического текста.
Смысл прагматичный. Пользовательский вопрос бывает слишком коротким или неровным для семантического поиска, а гипотетический ответ даёт более полезную опорную точку.
Это может поднять recall. И при этом аккуратно увести поиск вокруг неправильной идеи, если гипотеза поплыла. Так что HyDE я держу в графе «поисковый инструмент», не в графе «усилитель мышления». Меряем качеством top-k, не восхищением.
Fusion, когда слабые взгляды складываются в сильный набор
Fusion-подходы запускают несколько поисковых веток, потом сливают результаты, часто через rank-based aggregation.
Разумно, когда разные варианты запроса находят разные, но полезные фрагменты.
Менее разумно, когда:
- все ветки в целом возвращают одно и то же
- корпус маленький, и одного хорошего прохода уже достаточно
- reranker и так вычищает почти всё полезное
Fusion умеет работать. Просто у него есть привычка выглядеть полезным заметно раньше, чем доказывать это в проде.
Считать пользу на миллисекунду задержки
Практический вопрос здесь не «сработала ли умная техника». Он скорее такой.
Сколько качества опорных фрагментов мы купили на каждую добавленную миллисекунду и на каждый новый сценарий сбоя?
Для каждой техники я хочу видеть качество top-k до и после, эффект на reranking, добавленную задержку, какие классы сбоев лечит, какие новые создаёт.
Без этого архитектура начинает казаться лучше только потому, что стала длиннее.
Большинству систем нужно меньше техник, чем им кажется
Если корпус подготовлен нормально, а пользовательские вопросы чаще всего вменяемые, дефолтный стек короткий.
- прямой поиск
- при необходимости rewrite для слабых формулировок
- reranking
- answer
Остальное стоит добавлять только тогда, когда есть устойчивый класс промахов, который иначе не лечится.
Привычный мне порядок такой.
- привести в порядок корпус
- улучшить базовый поиск
- добавить reranking
- и только потом избирательно тестировать отдельные техники
Менее зрелищно, чем диаграмма с пятью ветками. Зато гораздо легче дебажить.
Стартовая матрица
Если выбирать быстро, схема такая.
| Симптом | Первый ход |
|---|---|
| запрос расплывчатый или обрывочный | rewrite |
| ответ зависит от нескольких разных фактов | decomposition |
| прямой запрос не достаёт управляющее понятие | step-back |
| semantic recall слаб на коротких или неуклюжих вопросах | HyDE |
| разные варианты запроса вытаскивают разные полезные источники | fusion |
| поиск плохой, потому что корпус грязный | сначала чинить подготовку корпуса |
Последняя строчка тут делает почти всю работу. И правильно.
Что бы я внедрял первым
Я бы не строил сразу пять техник в надежде, что одна из них красиво спасёт систему.
Я бы:
- собрал реальные промахи поиска
- разметил их по классам ошибок
- протестировал по одной технике на каждый класс
- оставил только те шаги, которые действительно улучшают опорный набор настолько, что это оправдывает задержку
Системе не нужна более богатая теория промптов. Ей нужна честная причина для каждого лишнего шага.