LLM поверх поиска: как усилить Elasticsearch и контролировать расходы
LLM не обязана заменять Elasticsearch: классический поиск формирует кандидатов, а модель понимает смысл запроса и улучшает ранжирование. Разбираем архитектуру, метрики, пример API и котировки Протока.
Поиск по каталогу услуг редко сводится к простому совпадению слов. Пользователь может написать «починить стиральную машину недорого», «репетитор по математике для ОГЭ» или «снять боль в спине». В каждом запросе есть намерение, ограничения и контекст, которые не всегда выражены терминами из каталога.
Языковая модель хорошо понимает такие формулировки, но это не означает, что ей стоит передавать весь поиск целиком. На практике более устойчивый подход — разделить задачу на этапы: быстрый классический поиск формирует кандидатов, а LLM помогает уточнить смысл запроса, переразместить результаты или объяснить выбор.
Почему LLM не должна заменять поисковый движок
Классический поисковый движок эффективен там, где нужны скорость, предсказуемость и работа с большим индексом. Он умеет:
- находить совпадения по словам и словоформам;
- учитывать фильтры, категории, регион и другие поля;
- сортировать результаты по заданным сигналам;
- быстро работать с кешем;
- обеспечивать стабильное время ответа.
LLM решает другую задачу. Она может сопоставить пользовательское описание с услугой, даже если формулировки сильно отличаются. Например, запрос «подготовить ребёнка к экзамену после школы» может быть связан с категорией репетиторов, хотя слово «ОГЭ» в запросе отсутствует.
При этом модель не обязана знать весь каталог и не всегда одинаково трактует пограничные случаи. Передача ей тысяч объектов на каждый запрос увеличивает задержку и стоимость, а также усложняет контроль качества. Поэтому разумнее использовать LLM как дополнительный слой над уже работающей поисковой системой.
Практическая архитектура из нескольких слоёв
Базовый конвейер может выглядеть так:
- Сервис принимает исходный запрос.
- Нормализатор исправляет очевидные опечатки и выделяет параметры.
- Elasticsearch или другой поисковый индекс формирует набор кандидатов.
- Фильтры убирают неподходящие категории, регионы и условия.
- LLM анализирует запрос и короткий список кандидатов.
- Финальный ранжировщик возвращает пользователю наиболее релевантные варианты.
Такое разделение позволяет не тратить токены на заведомо неподходящие документы. Модель получает не весь каталог, а компактный контекст: запрос, названия услуг, ключевые атрибуты и, при необходимости, признаки предыдущего ранжирования.
LLM можно подключать в разных местах. На этапе понимания запроса она выделяет намерение и параметры: тип услуги, объект работы, уровень подготовки, срочность и географию. На этапе ранжирования она сравнивает несколько кандидатов между собой. В интерфейсе она может сформировать краткое объяснение, почему результат соответствует запросу.
Где особенно заметен эффект от модели
Синонимы и разговорные формулировки
Пользователь не обязан знать структуру каталога. Он пишет так, как думает: «настроить вай-фай», «перевести договор», «подтянуть английский перед поездкой». LLM помогает связать бытовую фразу с формализованной услугой.
Неявные ограничения
В запросе могут быть условия, выраженные не в виде фильтра: «занятия вечером», «без выезда», «для начинающего», «срочно сегодня». Часть таких признаков можно извлечь моделью и передать в фильтрацию или ранжирование.
Смешанные запросы
Фраза может содержать несколько задач: «настроить ноутбук и перенести фотографии». Модель способна определить, что это один комплексный сценарий или два направления, которые нужно показать отдельно.
Как не потерять контроль над качеством
LLM в поиске нужно оценивать не только по впечатлению команды. Полезно собрать тестовый набор реальных запросов и разметить для каждого релевантные результаты. Затем сравнивать несколько вариантов:
- классический поиск без модели;
- классический поиск с LLM-извлечением параметров;
- классический поиск с LLM-переранжированием;
- комбинацию извлечения параметров и переранжирования.
Для измерения подойдут precision@k, recall@k, NDCG@k, доля запросов без результата и среднее время ответа. Отдельно стоит отслеживать стоимость одного поиска: число входных и выходных токенов, долю запросов с повторным использованием кеша, количество обращений к модели.
Тестировать нужно не только лучшие сценарии. В выборку стоит включить опечатки, короткие запросы, длинные описания, неоднозначные формулировки, редкие категории и запросы с несколькими ограничениями. Если модель меняет порядок результатов, важно понимать, почему это произошло, а не оценивать систему только по отдельным примерам.
Котировки моделей и выбор режима
Для разных этапов поиска подходят разные модели. На дату публикации в Протоке доступны, например, такие котировки за 1M токенов:
- GLM-5.2 — 3,66 ₽ за вход и 11,50 ₽ за выход;
- GPT-5.6 Luna — 5,98 ₽ за вход и 35,88 ₽ за выход;
- GPT-5.6 Terra — 8,42 ₽ за вход и 50,49 ₽ за выход;
- GPT-5.6 Sol — 13,60 ₽ за вход и 81,58 ₽ за выход;
- GLM-5.3 — 20,47 ₽ за вход и 64,34 ₽ за выход.
Для массового извлечения параметров из коротких запросов можно начать с GLM-5.2: у него самая низкая из перечисленных котировок входных и выходных токенов. Для более сложного переранжирования имеет смысл сравнить несколько моделей на одном наборе данных. GPT-5.6 Luna и GPT-5.6 Terra позволяют проверить, как меняется качество при другой конфигурации расходов, а GLM-5.3 и GPT-5.6 Sol — использовать в более требовательных сценариях.
Считать нужно не цену одного вызова, а стоимость поискового сценария целиком. Если в запрос передаётся длинный список кандидатов, входных токенов станет больше. Если модель возвращает развёрнутый текст вместо короткого структурированного ответа, растёт расход на выход. Поэтому для ранжирования лучше просить компактный JSON с идентификаторами и оценками, а пользовательское описание генерировать отдельным, необязательным шагом.
Пример запроса через API Протока
OpenAI-совместимый клиент можно подключить, изменив base_url на https://dualchat.pro/v1. Ключ создаётся в кабинете Протока, в разделе «Ключи». В параметре model указывается slug модели из котировок, а не её отображаемое имя.
from openai import OpenAI
client = OpenAI(
api_key="sk-dc-...",
base_url="https://dualchat.pro/v1",
)
response = client.chat.completions.create(
model="glm-5.2",
temperature=0,
messages=[
{
"role": "system",
"content": (
"Выдели намерение и ограничения поискового запроса. "
"Верни только JSON без пояснений."
),
},
{
"role": "user",
"content": "Нужен репетитор по математике для ОГЭ вечером онлайн",
},
],
)
print(response.choices[0].message.content)
В продакшене стоит ограничивать максимальный размер ответа, проверять JSON по схеме и предусмотреть запасной путь: если модель недоступна или превысила тайм-аут, поиск продолжает работать на классическом слое.
Как начать эксперимент без перестройки системы
Начните с одного узкого сценария, например извлечения категории и ограничений. Соберите контрольную выборку, зафиксируйте метрики и стоимость, затем сравните несколько моделей через единый API Протока. После этого можно добавить LLM-переранжирование только для запросов, где классический поиск возвращает мало результатов или низкую уверенность.
Такой подход снижает риск: основная поисковая система сохраняет скорость и предсказуемость, а модель используется там, где она действительно добавляет смысловую ценность. Расходы остаются прозрачными — оплата в Протоке списывается по факту за каждый запрос, доступны пополнение картой онлайн, по счёту для организации и через СБП.
Вывод
LLM и Elasticsearch не обязательно конкурируют. Классический движок быстро находит кандидатов и применяет строгие ограничения, а языковая модель помогает понять сложный запрос и улучшить порядок результатов. Наиболее практичная архитектура — использовать их последовательно, измерять качество на реальных данных и выбирать модель под конкретную операцию.
Сравнить модели и актуальные котировки можно в Протоке. Документация API доступна по адресу https://dualchat.pro/docs?utm_source=blog&utm_medium=article&utm_campaign=llm-poverh-poiska-elasticsearch, а полный список моделей и цен — на странице https://dualchat.pro/models?utm_source=blog&utm_medium=article&utm_campaign=llm-poverh-poiska-elasticsearch. Попробуйте подключить один поисковый сценарий, сравните качество и стоимость на своей выборке, а затем масштабируйте только подтверждённые решения.