Что такое конверсационный поиск?
Обычный поиск — 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 изменит работу с документами в вашей компании. Свяжитесь с нами для бесплатной оценки проекта.







