Привет, Хабр!
Сегодня предлагаю обсудить Managed OpenSearch Yandex Cloud. Поговорим о том, как автоматизировать управление кластером, чтобы сократить расходы на разработку, и как улучшить качество поиска на русском языке, используя доступные в сервисе инструменты морфологии.
Некоторые вопросы использования Managed OpenSearch в Yandex Cloud
Managed Open Search в минимальной (неотказоустойчивой) конфигурации стоит около 15 тысяч рублей в месяц.
Для окружения разработки можно останавливать кластер Open Search на ночь, чтобы немного сэкономить. Достаточно просто создать два cron-триггера, вызывающих Cloud Function с payload “start” и ”stop”. Моя Cloud Function на Python использует REST API для остановки и запуска кластера. Функция может получать Bearer token от сервисного аккаунта, под которым она запускается из контекста вызова через context.token["access_token"]}. Сервисному аккаунту функции нужна соответствующая роль для остановки и запуска кластера Open Search. Разумеется, не стоит делать эту функцию публичной. Как вариант, Bash-функция может использовать yc для запуска и остановки кластера. Сказать по правде, не помню, почему я остановился именно на Python. (Кстати, оставляйте комментарии, если интересуют какие-то детали и пояснения.)
Ещё можно сэкономить, отказавшись от публично доступного узла DASHBOARD.Чаще всего в нём используют notebook-like клиент DevTools. Вместо этого запросы можно отправлять на DATA-хосты (включив публичный доступ) с помощью curl-like клиента, например Insomnia или мой любимый. Не забудьте установить хороший пароль и создать пользователей с необходимыми полномочиями!
Кстати, насчёт пароля. Кажется, более правильный способ подключения к кластеру уже предоставлен в UI-консоли управления, но он ещё полностью не задокументирован. Ссылка ведёт на Metadata Hub. Я напишу об этом отдельный пост, когда познакомлюсь с ним.
Лемматизатор
Из интересных плагинов в Yandex Cloud можно упомянуть yandex-lemmer, предоставляющий морфологию русского языка. Это позволяет искать нормальные начальные формы слов вместо посимвольного сравнения. Следующий пост, кстати, будет посвящён альтернативному решению проблемы «поиска по смыслу, а не по буквам».
Тем не менее, если включить yandex lemmer plugin в настройках кластера, можно сравнить его с примитивным стеммером. Выберем наиболее трудные случаи для стеммера. Кстати, мой любимый случай «фланцы–фланец», но, пожалуй, приберегу на следующий раз.
// тест классического алгоритмического стеммера
POST /_analyze?filter_path=tokens.token
{
"tokenizer": "standard",
"filter": [
"russian_stem"
],
"text": "бежит письмо пеку переоформляющих радио"
}
// ответ - неправильные стеммы в yaml формате
tokens:
- token: "беж"
- token: "письм"
- token: "пек"
- token: "переоформля"
- token: "рад"
// тест лемматизатора с морфологией
POST /_analyze?filter_path=tokens.token
{
"tokenizer": "standard",
"filter": [
"yandex_lemmer"
],
"text": "бежит письмо пеку переоформляющих радио"
}
// ответ: морфологически правильные леммы
tokens:
- token: "бежит"
- token: "бежать"
- token: "письмо"
- token: "пеку"
- token: "пек"
- token: "печь"
- token: "переоформляющих"
- token: "переоформлять"
- token: "радио"
Как исключить исходные токены из потока, я найти не смог.
Давайте сравним этот лемматизатор с заслуженным морфологическим анализатором hunspell со словарями LibreOffice. К сожалению, пока невозможно использовать hunspell в YC Managed OpenSearch, так как нет возможности скопировать файлы словарей. см. ниж.
Он бесплатно доступен для тех, кто пока не пользуется Managed OpenSearch. Если скопировать ru_RU.aff, ru_RU.dic в каталог config/hunspell/ru_RU на локально запущенном OpenSearch, получим отличное качество стемм (ну или лемм):
GET http://localhost:9200/_analyze?filter_path=tokens.token
Content-Type: application/json
Accept: application/yaml
{
"tokenizer": "standard",
"filter": [
{
"type": "hunspell",
"lang": "ru_RU"
}
],
"text": "бежит письмо пеку переоформляющих радио"
}
tokens:
- token: "бежать"
- token: "письмо"
- token: "пек"
- token: "печь"
- token: "переоформляющий"
- token: "радио"
Что ж, отдав должное заслуженным NLP методам, в следующем посте перейдём к использованию языковых моделей, ну а на сегодня у меня все. Надеюсь, эта информация оказалась для вас полезной. Если остались вопросы по коду или настройке — спрашивайте в комментариях.
Спасибо за внимание!