Уявіть: корпоративна пошукова система має працювати по п'яти різних сховищах — Confluence (5200 сторінок), SharePoint (3800 документів), JIRA, GitHub та внутрішня CRM-документація. Монолітний векторний індекс з єдиним розміром чанків неминуче втрачає точність: для коротких FAQ потрібні маленькі чанки, для довгих регламентів — великі. У нашій практиці ми часто стикаємося з такими запитами, і рішення — Multi-Index RAG (визначення див. у Wikipedia). Ця архітектура дозволяє об'єднати кілька окремих індексів (векторних сховищ) в єдиний потік пошуку, зберігаючи індивідуальні налаштування для кожного типу даних та домену. Multi-Index RAG — це реалізація корпоративного пошуку AI, яка поєднує RAG з кількох джерел та забезпечує ізоляцію даних.
Коли потрібен Multi-Index RAG?
Різні типи даних: структуровані FAQ (короткі відповіді) та довгі регламенти потребують різних розмірів чанків та стратегій retrieval. Різні домени: юридична документація, технічна документація, продуктові описи — семантичні простори слабо перетинаються, окремі індекси дають більш точний retrieval. Різні джерела: Confluence, SharePoint, Notion, GitHub — кожне потребує свого парсера та має специфічні метадані. Ізоляція даних за безпекою: дані різних відділів зберігаються в різних індексах з контролем доступу.
Чому Multi-Index RAG ефективніший за монолітний індекс?
Основна ідея — створити окремі індекси для кожного типу/джерела, налаштувати їх параметри (розмір чанка, модель ембендінгів) індивідуально, а потім використовувати LLM-роутер для вибору релевантних індексів під конкретний запит. Паралельний асинхронний пошук по вибраних індексах та подальший reranking об'єднаних результатів дають високу точність. В одному з проектів впровадження Multi-Index RAG підвищило Context Recall з 0.71 до 0.88 — приріст на 24%. Multi-Index RAG на 24% точніший за монолітний індекс. Економія часу співробітників на пошук інформації склала до 2 годин на тиждень, що еквівалентно €500 на місяць для невеликої команди. Вартість впровадження від €15,000.
| Тип даних | Оптимальний розмір чанка | Стратегія чанкінгу |
|---|---|---|
| FAQ | 200-300 токенів | За питаннями |
| Регламенти | 1000-1500 токенів | За розділами |
| Код | 500-800 токенів | За функціями |
Архітектура Multi-Index RAG
Код архітектури Multi-Index RAG
from typing import Optional
from langchain_community.vectorstores import Qdrant
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain.schema import Document
import asyncio
class MultiIndexRAG:
def __init__(self, embeddings, llm):
self.embeddings = embeddings
self.llm = llm
self.indexes: dict[str, Qdrant] = {}
self.router_llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
def add_index(self, name: str, collection: str, description: str):
"""Реєструємо індекс з описом для роутера"""
self.indexes[name] = {
"retriever": Qdrant.from_existing_collection(
embeddings=self.embeddings,
collection_name=collection,
url="http://localhost:6333",
).as_retriever(search_kwargs={"k": 5}),
"description": description,
}
def route_query(self, query: str) -> list[str]:
"""LLM-роутер визначає релевантні індекси"""
index_descriptions = "\n".join([
f"- {name}: {info['description']}"
for name, info in self.indexes.items()
])
response = self.router_llm.invoke(f"""
Визнач, в яких із наступних індексів потрібно шукати для відповіді на запит.
Поверни JSON-список імен індексів.
Доступні індекси:
{index_descriptions}
Запит: {query}
Відповідь (JSON список):""")
import json
try:
return json.loads(response.content)
except:
return list(self.indexes.keys()) # Fallback: всі індекси
async def _search_index(self, index_name: str, query: str) -> tuple[str, list]:
"""Асинхронний пошук в одному індексі"""
retriever = self.indexes[index_name]["retriever"]
docs = await asyncio.to_thread(retriever.invoke, query)
return index_name, docs
async def retrieve(self, query: str) -> dict[str, list]:
"""Паралельний пошук по релевантних індексах"""
relevant_indexes = self.route_query(query)
tasks = [
self._search_index(idx, query)
for idx in relevant_indexes
if idx in self.indexes
]
results = await asyncio.gather(*tasks)
return dict(results)
def build_context(self, search_results: dict[str, list]) -> str:
"""Збираємо контекст з кількох індексів"""
context_parts = []
for index_name, docs in search_results.items():
if docs:
context_parts.append(f"## Джерело: {index_name}\n")
for doc in docs:
context_parts.append(f"- {doc.page_content}\n")
return "\n".join(context_parts)
Налаштування індексів для корпоративної бази знань
rag = MultiIndexRAG(
embeddings=OpenAIEmbeddings(model="text-embedding-3-small"),
llm=ChatOpenAI(model="gpt-4o", temperature=0),
)
rag.add_index(
name="legal",
collection="legal_contracts",
description="Договори, угоди, юридичні висновки",
)
rag.add_index(
name="hr",
collection="hr_policies",
description="Політики HR: відпустки, відрядження, найм, звільнення",
)
rag.add_index(
name="it",
collection="it_procedures",
description="IT-процедури: доступи, обладнання, інформаційна безпека",
)
rag.add_index(
name="finance",
collection="finance_regulations",
description="Фінансові регламенти: бюджет, закупівлі, авансові звіти",
)
rag.add_index(
name="faq",
collection="general_faq",
description="Загальні часто задавані питання співробітників",
)
Reranking об'єднаних результатів
Після збору результатів з кількох індексів важливо виконати ранжування результатів та переранжувати:
from flashrank import Ranker, RerankRequest
ranker = Ranker(model_name="ms-marco-MiniLM-L-12-v2")
def rerank_multi_index_results(
query: str,
search_results: dict[str, list[Document]],
top_n: int = 6,
) -> list[Document]:
"""Об'єднує та переранжує результати з різних індексів"""
# Збираємо всі документи
all_docs = []
for docs in search_results.values():
all_docs.extend(docs)
if not all_docs:
return []
# Reranking
passages = [{"id": i, "text": doc.page_content} for i, doc in enumerate(all_docs)]
rerank_req = RerankRequest(query=query, passages=passages)
ranked = ranker.rerank(rerank_req)
return [all_docs[r["id"]] for r in ranked[:top_n]]
Практичний кейс: корпоративний асистент з 5 джерел
В одному з проектів ми впровадили Multi-Index RAG для великої компанії з п'ятьма джерелами: Confluence (5200 сторінок), SharePoint (3800 документів), JIRA (експорт задач), GitHub (wiki, README), внутрішня CRM-документація. Інтеграція Confluence, SharePoint, JIRA, GitHub та CRM — стандартний сценарій.
Проблема монолітного індексу: різні типи контенту мають різні оптимальні розміри чанків. README з GitHub оптимально індексувати по-функціонально (блоки коду + опис), Confluence-сторінки — за розділами, CRM-документацію — за відповідями.
Конфігурація Multi-Index:
- 5 окремих колекцій в Qdrant
- LLM-роутер на GPT-4o-mini (~15 мс overhead)
- Паралельний пошук (async) скорочує latency з 5×T до 1.2×T
| Метрика | Монолітний індекс | Multi-Index |
|---|---|---|
| Context Recall | 0.71 | 0.88 |
| Precision@5 | 0.74 | 0.86 |
| Latency P95 | 1.2 с | 1.5 с |
| Routing accuracy | — | 91% |
Failure cases: 9% запитів потрапляють у неправильний набір індексів — переважно крос-доменні питання. Рішення: при низькому router confidence запускати пошук по всіх індексах з threshold відсікання за score.
Федеративний пошук з access control
def retrieve_with_permissions(
query: str,
user_id: str,
permission_service,
) -> dict[str, list]:
"""Пошук тільки по дозволених для користувача індексах"""
allowed_indexes = permission_service.get_allowed_indexes(user_id)
relevant_indexes = [
idx for idx in route_query(query)
if idx in allowed_indexes
]
return {idx: search(idx, query) for idx in relevant_indexes}
Що входить в роботу
- 5+ років досвіду в NLP та AI
- Аудит джерел даних та контенту
- Проектування Multi-Index архітектури під ваші сценарії
- Розробка ingestion пайплайнів для кожного джерела
- Налаштування LLM-роутера та reranking
- Інтеграція з існуючою інфраструктурою (Qdrant, Pinecone, pgvector)
- Документація архітектури та конфігурацій
- Навчання команди замовника
- Пост-релізна підтримка протягом 3 місяців
Процес роботи
Ми виконуємо проекти під ключ: від аудиту до деплою.
- Аналітика: вивчаємо типи даних, їх обсяги, вимоги до безпеки.
- Проектування: вибираємо стэк (векторні БД, моделі ембендінгів, LLM-роутер).
- Розробка: пишемо парсери, налаштовуємо чанкінг, індексацію, роутинг.
- Тестування: оцінюємо метрики Recall, Precision, latency.
- Деплой: розгортаємо на інфраструктурі замовника (on-prem або хмара).
Строки орієнтовно
- Проектування Multi-Index архітектури: 1 тиждень
- Розробка ingestion пайплайнів (5 джерел): 3–4 тижні
- LLM-роутер та інтеграція: 1 тиждень
- Reranking та оцінка: 1 тиждень
- Разом: 6–8 тижнів
Напишіть нам для консультації та оцінки вашого проекту. Оцінимо проект безкоштовно. Замовте впровадження Multi-Index RAG — отримайте точний пошук по всіх ваших джерелах. Наш досвід в RAG-архітектурах та 20+ реалізованих проектів гарантують високу якість.







