Впровадження Multi-Query RAG для поліпшення якості витягу
Multi-Query RAG — це техніка поліпшення retrieval, при якій вихідний запит автоматично перефразується кількома способами, кожний варіант запускається в пошуку, а результати об'єднуються. Це зменшує залежність якості відповіді від конкретної формулювання запиту та поліпшує повноту витягу.
Проблема, яку розв'язує Multi-Query
Векторні embedding-моделі чутливі до формулювання запиту. Одне й те ж питання, задане по-різному, може дати різні top-K результати:
- "Як оформити відпустку?" → знаходить статті про заяви
- "Процедура отримання щорічної відпустки" → знаходить розділ регламенту
- "Правила надання днів відпустки" → знаходить політику HR
Multi-Query об'єднує всі три та отримує повніший контекст.
Впровадження з LangChain
from langchain.retrievers.multi_query import MultiQueryRetriever
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import Qdrant
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
base_retriever = Qdrant.from_documents(
documents=docs,
embedding=embeddings,
collection_name="documents",
url="http://localhost:6333",
).as_retriever(search_kwargs={"k": 5})
retriever = MultiQueryRetriever.from_llm(
retriever=base_retriever,
llm=llm
)
results = retriever.invoke("Як подати запит на відпустку?")
Кастомна Multi-Query з контролем промпту
from langchain.prompts import PromptTemplate
from langchain_core.output_parsers import BaseOutputParser
import json
class LineListOutputParser(BaseOutputParser):
def parse(self, text: str) -> list:
lines = text.strip().split("\n")
return [line.strip() for line in lines if line.strip()]
multi_query_prompt = PromptTemplate(
input_variables=["question"],
template="""Ти — асистент AI мовної моделі. Твоє завдання — генерувати 3
різних версій даного запиту користувача для витягу релевантних документів з векторної бази даних.
Надай ці альтернативні запитання, розділені новим рядком.
Оригінальне питання: {question}
Альтернативні запитання:"""
)
def multi_query_retrieval(query: str, retriever, llm) -> list:
# Генеруємо запити
queries = llm.invoke(multi_query_prompt.format(question=query))
query_list = [queries.content] + [query]
# Витягуємо з кожного
unique_docs = set()
all_docs = []
for q in query_list:
docs = retriever.invoke(q)
for doc in docs:
doc_id = doc.metadata.get("id")
if doc_id not in unique_docs:
unique_docs.add(doc_id)
all_docs.append(doc)
return all_docs
Практичний кейс: асистент з HR документацією
Завдання: асистент для HR політик, що охоплює відпустку, хворобу, бізнес-подорож, бонуси.
Результати:
| Метрика | Стандартний RAG | Multi-Query RAG |
|---|---|---|
| Context Recall | 0.71 | 0.89 |
| Answer Completeness | 0.68 | 0.87 |
| Задоволення користувачів | 0.74 | 0.91 |
| Latency | 400ms | 1.1s (3× запити паралельно) |
Multi-Query поліпшив context recall на 25% зберігаючи прийнятний latency.
Терміни
- Впровадження генератора multi-query: 1–2 дні
- Тестування та оптимізація промпту: 1–2 дні
- Оцінка та настроювання: 2–3 дні
- Всього: 1 тиждень







