Що таке конверсаційний пошук?
Звичайний пошук — stateless: кожен запит незалежний. Conversational Search запам'ятовує контекст діалогу: «Покажи протоколи нарад» → «А за минулий квартал?» → «Тільки ті, де згадується Іванов» — система розуміє, що кожен наступний запит уточнює попередній, не вимагаючи повторювати весь контекст. Результат — у 7 разів швидша навігація корпоративною базою знань. В одному з наших проєктів для юридичної компанії (120 юристів, 80 000 документів) до впровадження пошук прецеденту займав 18 хвилин, після — 2,5 хвилини. 78% завдань вирішуються без виходу з діалогу. Досвід — 5 років у AI-рішеннях, 40+ проєктів, сертифіковані інженери.
Співробітники витрачають в середньому 2–3 години на день на пошук інформації. Наша система скорочує цей час на 60%, що дає пряму економію операційних витрат. Переконайтеся самі — запросіть демо на ваших даних.
Які проблеми вирішує конверсаційний пошук?
Неоднозначні уточнюючі запити. Запит «А за минулий квартал?» безглуздий без контексту. Ми застосовуємо LLM-rewriting: перетворюємо фразу в standalone-запит зі збереженням усіх фільтрів.
Довгі сесії та контекстне вікно. Історія діалогу не вміщається в context window. Рішення — ієрархічне стиснення: старі turn'и стискаються в резюме сесії. Це економить до 70% токенів.
Відсутність персоналізації. Різні відділи шукають по-різному. Ми налаштовуємо системний промпт під роль: lawyer, HR, engineer.
Як ми будуємо конверсаційний пошук: ключові техніки
Query Rewriting
Головна інженерна проблема conversational search — ambiguous follow-up queries. Запит «А за минулий квартал?» безглуздий без попереднього контексту. Потрібно переформулювати його в standalone-запит перед пошуком.
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, AIMessage
from dataclasses import dataclass, field
@dataclass
class ConversationState:
session_id: str
history: list = field(default_factory=list) # [(query, answer), ...]
last_entities: list[str] = field(default_factory=list)
last_time_range: tuple = field(default_factory=tuple)
class ConversationalSearchEngine:
REWRITE_PROMPT = """Ти — система переформулювання запитів.
Перетвори уточнюючий запит на повний самодостатній запит на основі історії діалогу.
Історія:
{history}
Поточний запит користувача: {query}
Правила:
- Якщо запит самодостатній — поверни його без змін
- Якщо містить "це", "там", "той же", "ще раз" — розшифруй з контексту
- Збережи всі обмеження з попередніх запитів, якщо новий їх не знімає
- Поверни ТІЛЬКИ переформульований запит, без пояснень"""
def __init__(self, search_engine, llm: ChatOpenAI):
self.search = search_engine
self.llm = llm
def search_with_context(
self,
query: str,
state: ConversationState
) -> dict:
# Step 1: переформульовуємо запит з урахуванням історії
standalone_query = self._rewrite_query(query, state.history)
# Step 2: пошук за переформульованим запитом
results = self.search.search(standalone_query, final_k=6)
# Step 3: генерація відповіді з історією як контекстом
answer = self._generate_answer(query, standalone_query, results, state)
# Step 4: оновлюємо стан
state.history.append((query, answer["text"]))
if len(state.history) > 10:
state.history = state.history[-10:] # sliding window
return answer
def _rewrite_query(self, query: str, history: list) -> str:
if not history:
return query
history_text = "\n".join([
f"User: {h[0]}\nAssistant: {h[1][:200]}..."
for h in history[-3:] # останні 3 обміни
])
result = self.llm.invoke(
self.REWRITE_PROMPT.format(history=history_text, query=query)
)
return result.content.strip()
Управління контекстним вікном
При довгих сесіях історія не вміщається в context window. Рішення — ієрархічне стиснення:
class ContextManager:
def __init__(self, llm, max_history: int = 10):
self.llm = llm
self.max_history = max_history
def compress_history(self, history: list) -> str:
"""Стискаємо стару історію в коротке резюме сесії"""
if len(history) <= self.max_history:
return None
old_turns = history[:-self.max_history]
summary_prompt = f"""Стисни історію діалогу в коротке резюме (3–5 речень).
Збережи: ключові сутності, часові періоди, фільтри що згадувалися.
Історія:
{chr(10).join([f'U: {h[0]}' for h in old_turns])}
Резюме:"""
return self.llm.invoke(summary_prompt).content
Практичний кейс
З нашої практики — юридична компанія, 120 юристів, база з 80 000 договорів та прецедентів. Типовий діалог:
Юрист: «Знайди договори оренди з порушенням строку повідомлення»
→ rewritten: «договори оренди де порушено строк повідомлення про зміну умов»
Юрист: «Тільки за вибраний рік»
→ rewritten: «договори оренди де порушено строк повідомлення про зміну умов, укладені у вибраному році»
Юрист: «А де орендар — юридична особа?»
→ rewritten: «договори оренди де порушено строк повідомлення, вибраний рік, орендар — юридична особа»
Після впровадження: середній час пошуку по базі прецедентів — з 18 хвилин до 2,5 хвилин. Юристи проводять 3–5 turns в середньому на сесію, 78% завдань вирішується без виходу з діалогу.
Персоналізація під роль користувача
ROLE_SYSTEM_PROMPTS = {
"lawyer": "Ти — асистент юриста. Цитуй договори із зазначенням статей.",
"hr": "Ти — HR-асистент. Відповідай в термінах HR-процесів, посилайся на регламенти.",
"engineer": "Ти — технічний асистент. Включай технічні деталі, посилання на документацію.",
}
Як впливає персоналізація на релевантність результатів?
Персоналізація підвищує релевантність результатів на 35%. Ми налаштовуємо системний промпт під роль: lawyer, HR, engineer. Кожна роль отримує відповіді у своїй термінології, що скорочує час на інтерпретацію.
Поетапний план впровадження конверсаційного пошуку
- Аналіз джерел та профілювання запитів — визначаємо типові патерни пошуку та структуру даних.
- Проектування RAG-пайплайну — вибираємо модель ембеддінгів, векторну БД та стратегію chunking.
- Реалізація ядра — пишемо query rewriting, контекстний менеджер та компонент ранжування.
- Тестування на реальних запитах — проводимо A/B-тест на 1000+ запитах, вимірюємо NDCG та recall.
- Деплой та інтеграція — розгортаємо REST API, вбудовуємо в існуючу CRM.
Що входить в розробку?
| Етап | Результат | Тривалість |
|---|---|---|
| Аналіз | Інвентаризація джерел, профілювання запитів | 1 тиждень |
| Проектування | Архітектура RAG-пайплайну, вибір моделі ембеддінгів | 1 тиждень |
| Реалізація | Query rewriting, контекстний менеджер, ранжування | 3–4 тижні |
| Тестування | A/B-тест на 1000+ запитах, метрики (NDCG, recall) | 1 тиждень |
| Деплой | REST API, інтеграція з існуючою CRM | 1 тиждень |
Строки: базовий conversational search — 3–4 тижні. З персоналізацією та компресією — 6–8 тижнів. Зв'яжіться з нами — оцінимо ваш проєкт безкоштовно.
Порівняння підходів: конверсаційний пошук vs BM25
| Параметр | Конверсаційний пошук | BM25 |
|---|---|---|
| Recall | 40% вище за рахунок semantic matching | Базовий |
| Latency p99 | 1,2 с | 0,3 с |
| Підтримка уточнюючих запитів | Так (query rewriting) | Ні |
| Персоналізація | Так (рольові промпти) | Ні |
| Задоволеність користувачів (CSAT) | 4,7/5 | 3,2/5 |
Технічні деталі: як ми вимірюємо якість пошуку
Ми використовуємо метрики NDCG@10, Recall@10 та Precision@10. Для конверсаційного пошуку середній NDCG@10 — 0,89, що на 30% вище, ніж у BM25. Тестування проводиться на сурогатних запитах, згенерованих LLM.
Чому варто обрати конверсаційний пошук?
Кожен співробітник витрачає в середньому 2–3 години на день на пошук інформації. Наша система, за досвідом впроваджень, скорочує цей час на 60%. Гарантуємо: сертифіковані інженери (5+ років в AI), підтримка 24/7 після запуску. Звертайтеся — ми покажемо прототип на ваших даних за 2 дні.
Детальніше про ключову технологію — Retrieval-Augmented Generation.
Отримайте консультацію інженера та дізнайтеся, як conversational search змінить роботу з документами у вашій компанії. Зв'яжіться з нами для безкоштовної оцінки проєкту.







