English translation is not available yet. Showing Russian content.
Как вы делаете query rewriting и query expansion в RAG?
Краткий тезис
Query rewriting и query expansion — техники предобработки пользовательского запроса перед этапом retrieval в RAG. Rewriting переформулирует запрос для устранения неоднозначности и приведения к стилю документов, expansion добавляет синонимы, связанные термины или варианты запроса. Обе техники повышают recall (полноту поиска) и качество retrieval, особенно для коротких, разговорных или нечётких запросов. В современных RAG-системах эти операции часто выполняются с помощью LLM или специализированных моделей.
1. Термины: Query Rewriting и Query Expansion
Query rewriting — изменение формулировки запроса без изменения его смысла. Цель — сделать запрос более подходящим для поиска в векторной БД: убрать местоимения, добавить контекст, исправить грамматику, перевести на формальный язык.
Query expansion — добавление к исходному запросу дополнительных терминов (синонимов, гипонимов, связанных понятий). Цель — увеличить вероятность совпадения с релевантными документами, даже если в них используются другие слова.
| Характеристика | Query Rewriting | Query Expansion |
|---|---|---|
| Суть | Переформулировка | Дополнение |
| Длина запроса | Может уменьшиться или остаться той же | Увеличивается |
| Влияние на precision | Может повысить (точнее соответствует документам) | Может снизить (шум от лишних терминов) |
| Влияние на recall | Повышает (лучше покрывает смысл) | Повышает (больше совпадений) |
| Типичный инструмент | LLM (zero-shot/few-shot) | LLM, тезаурус, PRF |
2. Зачем нужны эти техники в RAG?
Пользовательские запросы в реальных системах часто:
- Короткие («погода» — что именно? где? когда?)
- Неоднозначные («яблоко» — фрукт или компания?)
- Разговорные («а что там с тем проектом?» — без контекста)
- Содержат опечатки («нейронка» вместо «нейронная сеть»)
- Не совпадают по лексике с документами (пользователь говорит «автомобиль», а в документах «машина»)
Без обработки запроса retrieval может пропустить релевантные чанки, что приведёт к плохому ответу LLM. Rewriting и expansion — дешёвый способ улучшить recall без изменения индекса или эмбеддингов.
3. Query Rewriting: подходы
3.1 LLM-based rewriting (наиболее распространённый)
Используется LLM (часто та же, что и для генерации ответа, или более лёгкая) для переформулировки запроса. Пример промпта:
Перепиши запрос пользователя так, чтобы он был более конкретным и подходил для поиска по технической документации. Если запрос неоднозначен, уточни его, используя контекст диалога.
Пользователь: {query}
Переписанный запрос:
Zero-shot — без примеров. Few-shot — с 2-3 примерами в промпте.
3.2 Rule-based rewriting
Простые правила: удаление стоп-слов, исправление опечаток (через словарь или Levenshtein), замена местоимений на полные формы (если есть история диалога). Менее гибко, но быстро и без затрат на LLM.
3.3 Multi-step rewriting (HyDE, Rewrite-Retrieve-Read)
- HyDE (Hypothetical Document Embeddings): LLM генерирует гипотетический документ-ответ на запрос, затем этот документ используется как запрос для поиска. Фактически rewriting в виде целого документа.
- Rewrite-Retrieve-Read: сначала переписать запрос, потом найти документы, потом прочитать и ответить. Популярная архитектура из статьи «Rewrite-Retrieve-Read» (2023).
4. Query Expansion: методы
4.1 Synonym expansion (синонимическое расширение)
Использование тезаурусов (WordNet, ConceptNet) или списков синонимов для добавления эквивалентных терминов. Пример: запрос «нейронная сеть» → «нейронная сеть, искусственная нейронная сеть, deep learning, neural network».
4.2 Embedding-based expansion
Поиск в векторном пространстве терминов, близких к эмбеддингу запроса. Можно использовать предобученные word embeddings (Word2Vec, FastText) или эмбеддинги из той же модели, что и для документов. Добавляются top-k ближайших слов.
4.3 LLM-generated expansion
LLM генерирует варианты запроса или дополнительные ключевые слова. Промпт:
Сгенерируй 5 вариантов запроса, которые передают тот же смысл, но используют другие слова. Исходный запрос: {query}
Полученные варианты объединяются с исходным запросом (например, через OR в булевом поиске или как отдельные запросы с агрегацией результатов).
4.4 Pseudo-relevance feedback (PRF)
Классический метод информационного поиска:
- Выполнить поиск по исходному запросу.
- Взять top-k документов (предположительно релевантных).
- Извлечь из них наиболее значимые термины (TF-IDF, BM25).
- Добавить эти термины к запросу.
В RAG PRF может быть реализован с помощью LLM: после первого раунда retrieval LLM выделяет ключевые понятия из найденных чанков и добавляет их в запрос для второго раунда.
5. Сравнение Rewriting vs Expansion
| Критерий | Rewriting | Expansion |
|---|---|---|
| Цель | Уточнить смысл | Расширить покрытие |
| Риск | Потеря исходного намерения | Зашумление запроса |
| Сложность реализации | Средняя (промптинг) | Низкая-средняя |
| Влияние на latency | +1 LLM вызов | +0..+1 LLM вызов |
| Типичное улучшение recall | +5-15% | +10-25% |
| Типичное влияние на precision | +5-10% | -5-10% (возможно снижение) |
На практике часто комбинируют: сначала rewriting, затем expansion к переписанному запросу.
6. Практическая реализация: пример кода (Python + LangChain)
from langchain_community.llms import OpenAI
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
# Инициализация LLM (можно заменить на локальную модель)
llm = OpenAI(model="gpt-3.5-turbo-instruct", temperature=0)
# 1. Query Rewriting
rewrite_prompt = PromptTemplate(
input_variables=["query"],
template="Перепиши запрос для поиска по документации. Сделай его конкретным и формальным.\nЗапрос: {query}\nПереписанный запрос:"
)
rewrite_chain = LLMChain(llm=llm, prompt=rewrite_prompt)
# 2. Query Expansion
expand_prompt = PromptTemplate(
input_variables=["query"],
template="Сгенерируй 3 дополнительных варианта этого запроса, используя синонимы и близкие термины.\nИсходный запрос: {query}\nВарианты (каждый с новой строки):"
)
expand_chain = LLMChain(llm=llm, prompt=expand_prompt)
def process_query(user_query: str) -> str:
# Шаг 1: переписываем
rewritten = rewrite_chain.run(user_query).strip()
# Шаг 2: расширяем
expansions = expand_chain.run(rewritten).strip().split('\n')
# Объединяем: исходный переписанный + варианты
all_queries = [rewritten] + expansions
# Для векторного поиска можно выполнить каждый запрос отдельно и объединить результаты
# Или склеить через OR для BM25
final_query = " OR ".join(all_queries)
return final_query
# Пример
user_input = "расскажи про нейронки"
processed = process_query(user_input)
print(processed)
# Вывод: "расскажи про нейронные сети OR нейронные сети OR глубокое обучение OR искусственные нейронные сети"
7. Оценка эффективности
Для оценки влияния rewriting/expansion на RAG используют:
- Offline метрики: recall@k, MRR, NDCG до и после обработки запроса. Сравнивают на тестовом наборе запросов с gold standard.
- Online метрики: faithfulness, answer relevance (через RAGAS), user satisfaction (A/B тест).
- Ablation study: убирают rewriting/expansion и смотрят, как меняются метрики.
Пример результатов (гипотетические):
| Конфигурация | Recall@5 | MRR | Faithfulness |
|---|---|---|---|
| Без обработки | 0.65 | 0.72 | 0.80 |
| Только rewriting | 0.72 | 0.78 | 0.82 |
| Только expansion | 0.78 | 0.75 | 0.79 |
| Rewriting + expansion | 0.82 | 0.80 | 0.81 |
Expansion может снизить faithfulness из-за шума, поэтому важно тестировать.
8. Продвинутые техники: Agentic Rewriting
В контексте Agentic RAG (вопросы 371-380) rewriting может быть итеративным:
- Агент выполняет поиск, получает результаты, анализирует их (например, через LLM).
- Если результаты нерелевантны, агент переписывает запрос с учётом полученной информации и делает второй поиск.
- Цикл повторяется до достижения порога уверенности или лимита шагов.
Пример: пользователь спрашивает «последние новости про ИИ». Агент сначала ищет «последние новости про ИИ», получает общие статьи, затем уточняет «новости про ИИ за март 2025» и т.д.
9. Риски и ограничения
- Over-expansion: слишком много добавленных терминов размывают запрос, precision падает.
- Увеличение latency: каждый LLM-вызов добавляет 0.5-2 секунды. Для real-time систем критично.
- Зависимость от качества LLM: если LLM плохо переписывает, можно ухудшить retrieval.
- Потеря контекста: при rewriting без учёта истории диалога можно потерять важные детали.
- Стоимость: частые вызовы LLM увеличивают затраты (токены).
10. Когда использовать, а когда нет?
| Ситуация | Рекомендация |
|---|---|
| Короткие запросы (1-3 слова) | Обязательно rewriting + expansion |
| Длинные, хорошо сформулированные запросы | Можно без обработки или только лёгкое expansion |
| Разговорный стиль (чат-бот) | Rewriting обязателен |
| Высокие требования к latency | Использовать лёгкие модели (например, DistilBERT) или rule-based |
| Ограниченный бюджет на LLM | Использовать PRF или synonym expansion без LLM |
| Тематическая область с узкой терминологией | Expansion через тезаурус домена |
Пет-проект для закрепления
Задача: Реализовать модуль query preprocessing для RAG-системы, который поддерживает rewriting через LLM и expansion через WordNet.
Инструменты: Python, NLTK (WordNet), LangChain (или openai), FAISS (для векторного поиска), небольшой датасет документов (например, статьи из Википедии).
Шаги:
- Загрузите 100-200 документов по одной теме (например, машинное обучение).
- Разбейте на чанки, создайте векторный индекс (FAISS + sentence-transformers).
- Напишите функцию
rewrite_query(query)с использованием LLM (можно использовать бесплатный API или локальную модель через Ollama). - Напишите функцию
expand_query(query)через WordNet: для каждого существительного найдите синонимы и добавьте их. - Объедините:
processed_query = expand_query(rewrite_query(query)). - Сравните recall@5 для 10 тестовых запросов с обработкой и без.
- Визуализируйте результаты (таблица/график).
Ожидаемый результат: Вы увидите, что recall повышается на 10-30% для коротких запросов, но может незначительно снизиться precision. Пет-проект демонстрирует trade-off и практическую пользу техник.
Связь с другими вопросами
| Вопрос | Тема |
|---|---|
| 5 | Оценка качества retrieval в RAG |
| 7 | Уменьшение latency RAG-системы |
| 9 | Обновление документов в RAG |
| 10 | Self-RAG и его применение |
| 15 | Стратегии chunking |
| 20 | HyDE (гипотетические документы) |
Навигация
- Предыдущий: 373
- Следующий: 375
- Индекс: 00. Индекс разборов