У компанії з 500 осіб знання зберігаються у 7–12 системах одночасно: Confluence, SharePoint, Jira, корпоративна пошта, 1C, внутрішні CRM, файлові сервери. Співробітник витрачає в середньому 2,5 години на день на пошук інформації — це не метафора, це дані McKinsey Global Institute. Ключова проблема не в тому, що дані є, а в тому, що знайти їх через звичайний keyword-пошук неможливо: документ називається «Регламент_v3_final_FINAL2», а запит — «як оформити відрядження». Ми розробляємо AI Enterprise Search — систему, яка вирішує цю проблему через семантичне розуміння запиту та гібридний пошук по всіх джерелах одночасно.
Проблеми, які вирішуємо
Розрізненість даних — не єдина складність. Навіть якщо документ знайдено, він може бути неактуальним або не відповідати контексту. Типові сценарії:
- Низька точність keyword-пошуку: артикул «A-123» шукається як звичайне слово, без розуміння, що це номер деталі.
- Відсутність контексту: запит «бюджет на маркетинг» має враховувати, що користувач — керівник відділу, а не стажер.
- Порушення безпеки: співробітник бачить документи, до яких не має доступу, якщо ACL не впроваджено.
Чому AI Enterprise Search ефективніший за звичайний пошук?
Чистий векторний пошук добре працює на семантично схожих запитах, але погано — на точних збігах: артикулах, іменах, датах. Запит «договір з ТОВ "Ромашка" від 12 березня» дасть кращий результат через BM25, а «порядок дій при інциденті з витоком даних» — через векторний пошук. Гібридний підхід об'єднує сильні сторони обох методів.
| Тип пошуку | Сильні сторони | Слабкі сторони |
|---|---|---|
| Keyword (BM25) | Точні збіги, артикули, дати | Не розуміє синоніми, контекст |
| Векторний (Embeddings) | Семантика, синоніми, узагальнення | Погано на рідкісних термінах, "холодний старт" |
| Гібридний (наш) | Найкраще з двох світів, CrossEncoder реранкінг | Складніше в реалізації, вимагає тонкого налаштування |
from qdrant_client import QdrantClient
from rank_bm25 import BM25Okapi
from sentence_transformers import SentenceTransformer, CrossEncoder
import numpy as np
class HybridSearchEngine:
def __init__(self):
self.dense_model = SentenceTransformer("intfloat/multilingual-e5-large")
self.reranker = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-6-v2")
self.qdrant = QdrantClient(url="http://localhost:6333")
self.bm25_index = None
self.doc_store = {}
def search(self, query: str, top_k: int = 20, final_k: int = 5) -> list[dict]:
# Dense search
query_emb = self.dense_model.encode(
f"query: {query}", # E5-формат
normalize_embeddings=True
)
dense_results = self.qdrant.search(
collection_name="enterprise_docs",
query_vector=query_emb.tolist(),
limit=top_k
)
# Sparse search (BM25)
bm25_scores = self.bm25_index.get_scores(query.lower().split())
top_bm25_ids = np.argsort(bm25_scores)[-top_k:][::-1]
# Merge результатов (RRF - Reciprocal Rank Fusion)
merged = self._reciprocal_rank_fusion(dense_results, top_bm25_ids)
# Cross-encoder reranking
pairs = [(query, self.doc_store[doc_id]["text"]) for doc_id in merged[:top_k]]
rerank_scores = self.reranker.predict(pairs)
reranked = sorted(
zip(merged[:top_k], rerank_scores),
key=lambda x: x[1],
reverse=True
)
return [self.doc_store[doc_id] for doc_id, _ in reranked[:final_k]]
def _reciprocal_rank_fusion(self, dense: list, sparse: list, k: int = 60) -> list:
scores = {}
for rank, item in enumerate(dense):
doc_id = item.id
scores[doc_id] = scores.get(doc_id, 0) + 1 / (k + rank + 1)
for rank, doc_id in enumerate(sparse):
scores[doc_id] = scores.get(doc_id, 0) + 1 / (k + rank + 1)
return sorted(scores, key=scores.get, reverse=True)
Розуміння запиту та генерація відповіді
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
class EnterpriseSearchAssistant:
def __init__(self, search_engine: HybridSearchEngine):
self.search = search_engine
self.llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.1)
def answer(self, query: str, user_context: dict) -> dict:
# Расширение запроса для лучшего поиска
expanded_query = self._expand_query(query, user_context)
# Поиск по всем источникам
results = self.search.search(expanded_query, final_k=7)
if not results:
return {"answer": "Документи за вашим запитом не знайдено.", "sources": []}
# Генерация ответа с цитатами
context = "\n\n".join([
f"[{i+1}] {r['title']} ({r['source']})\n{r['text'][:500]}"
for i, r in enumerate(results)
])
prompt = f"""Дай відповідь на питання співробітника на основі документів компанії.
Використовуй лише надані документи. Цитуй джерела [1], [2] і т.д.
Якщо відповідь неповна — скажи про це.
Питання: {query}
Документи:
{context}"""
answer = self.llm.invoke(prompt).content
return {
"answer": answer,
"sources": [{"id": i+1, "title": r["title"], "url": r["url"]}
for i, r in enumerate(results)]
}
Індексація джерел
Для кожного джерела — окремий конектор з інкрементальним оновленням:
| Джерело | Конектор | Частота індексації | Особливості |
|---|---|---|---|
| Confluence | REST API (spaces, pages) | Кожні 30 хв | Обробка розмітки Confluence |
| SharePoint | Microsoft Graph API | Щогодини | Підтримка Word/PDF/PPTX |
| Jira | REST API | Кожні 15 хв | Тікети + коментарі |
| IMAP/Exchange | Realtime (webhooks) | Тільки відправлені/отримані | |
| Файловий сервер | Inotify / polling | При зміні | PDF, DOCX, XLSX, TXT |
Кейс з практики: виробничий холдинг, 1200 співробітників. Індексували 340 000 документів з Confluence, SharePoint та самописної СЕД. Час завантаження індексу — 18 годин (одноразово). Регулярне оновлення — дельта за 30 хвилин, ~200 документів, займає 4 хвилини. Середня точність топ-3 відповідей (оцінка HR-командою на вибірці 500 запитів): 78% релевантних результатів проти 41% у колишнього Elasticsearch keyword-пошуку. За рахунок автоматизації пошуку компанія отримала суттєву економію бюджету.
Як оцінюється точність пошуку?
Оцінка проводиться на реальних запитах співробітників. Ми формуємо вибірку з 300–500 типових питань, розмічаємо релевантні документи та рахуємо recall@k і precision@k. Ключовий інструмент — CrossEncoder, який ранжує кандидатів та підвищує точність топ-3 до 78%. Валідація виконується замовником на його даних.
Як ми забезпечуємо безпеку корпоративних даних?
Критична деталь enterprise-пошуку — користувач повинен бачити лише ті документи, до яких він має доступ. Реалізується через metadata-фільтри в Qdrant:
# При пошуку фільтруємо за правами користувача
results = qdrant.search(
collection_name="enterprise_docs",
query_vector=query_emb,
query_filter=Filter(
must=[
FieldCondition(
key="allowed_groups",
match=MatchAny(any=user_groups)
)
]
),
limit=20
)
Приклад налаштування прав доступу
ACL налаштовується через метадані документа: groups, roles, permissions. Векторна база Qdrant підтримує filtering на рівні точок (documents), що гарантує безпеку.Процес роботи
- Аналітика та аудит джерел: виявляємо, де зберігаються дані, оцінюємо обсяг та частоту змін.
- Проектування архітектури: обираємо модель ембеддингів, векторну БД, налаштовуємо пайплайн.
- Індексація даних: підключаємо конектори, проводимо пробну індексацію на 10% даних.
- Налаштування пошуку та реранжування: оптимізуємо параметри RRF, підбираємо пороги для CrossEncoder.
- Інтеграція UI та ботів: вбудовуємо пошук у веб-інтерфейс, Slack-бота, API.
- Тестування та налагодження: перевіряємо на реальних запитах співробітників, ітеративно покращуємо.
- Деплой та моніторинг: розгортаємо в production, налаштовуємо логи та метрики (latency p99, recall).
Що входить в роботу
- Документація архітектури та інструкції з експлуатації.
- Налаштовані конектори до всіх джерел.
- Веб-інтерфейс пошуку та інтеграція з корпоративним месенджером.
- Навчання команди (2-3 воркшопи).
- Гарантійна підтримка 3 місяці після запуску.
Строки та вартість
- Пілот (1-2 джерела, ~50 000 документів): 4–6 тижнів.
- Повна система (5–8 джерел + UI): 3–4 місяці.
- Налаштування ACL: +2–3 тижні.
Вартість розраховується індивідуально після аудиту. В середньому інвестиції окупаються за 6–12 місяців за рахунок скорочення часу на пошук. Замовте пілотний проект — перший етап займе не більше 2 днів на аналіз.
Чому обирають нас
- 5+ років на ринку AI-рішень для enterprise.
- 20+ проектів з впровадження семантичного пошуку в компаніях від 200 до 5000 співробітників.
- Гарантія SLA 99.9% та точності пошуку не нижче 75% за вашими критеріями.
- Сертифіковані інженери з MLOps та NLP.
Зв'яжіться з нами, щоб отримати консультацію по вашому проекту та попередню оцінку за 2 дні.







