Что за экспатские группы?
Тривиальный факт: в Клубе полно людей, которые хотя бы раз в своей жизни переехали в другую страну. Я тоже к таким отношусь с некоторых пор, и все мы знаем, что на новом месте приходится искать, где купить гречку, как уехать на такси, а также разбираться, где и как происходит разнообразная бюрократия, что такое термин или сита (одно и то же, кстати), и т. п. Всей этой информацией переселенцы делятся в группах и чатах, о которых и пойдёт речь.
А новый бот зачем? Мало их понаделали?
Сейчас будет история.
В январе 2022 года я переехал из Сибири в Галисию (это в Испании) и, таким образом, кардинально сменил обстановку чуть раньше, чем это стало мейнстримом. Через некоторое время в соседнем городе вписался Николай @NiGuLa, осмотрелся и говорит: а чё у нас тут до сих пор нет нормальной русскоязычной группы взаимопомощи?
Мы сделали группу, и в неё начали приходить люди с обычными в подобной ситуации вопросами. А где купить привычные продукты? А как записать ребёнка в школу? А здесь есть парикмахер, который говорит по-русски? Ответы на вопросы «где купить» и «как сделать» Николай собирал в закреплённых сообщениях, а русскоязычные парикмахеры нашлись прямо в группе и отвечали «я парикмахер», и тут мне в голову пришла идея. Я же инженер, надо автоматизировать процесс! Сделаем список услуг, где люди смогут сами регистрироваться, и чтобы любой участник мог этот список посмотреть и связаться напрямую с парикмахером, а не спрашивать в группе каждый раз.
Так появилась идея сделать бота, который сидел бы в нашей группе и помогал участникам находить друг друга, не прибегая к поиску и расспросам. На программирование прототипа ушёл месяц, после чего мы добавили бота в группу и начали публичное тестирование.
И чё, полетело?
Ещё как.
Базовая функция — книга услуг, с которой всё и началось. Вскоре после запуска мы научили бота реагировать, когда в группу приходит новый участник, и писать «привет, как дела, загляни в наши закрепы», а в тех закрепах у нас есть ссылка «полезные контакты», которая переводит на диалог с ботом. Заодно выгнали бота-вахтёра, который непонятно, где работает и непонятно, кому сливает списки участников. Сейчас у нас в группе примерно шестьсот человек, и в книге услуг около сорока записей — как будто неплохо.
Бота запустили в марте 2024 года — на следующей неделе день рождения будет — и с тех пор запрограммировали ещё несколько функций.
Контроль языка
Иногда нашу публичную группу находят какие-нибудь галисийцы, заходят и начинают балаболить по-испански. А что за группа у вас такая, а с кем можно познакомиться, а вы вообще на каком языке говорите? Бывает смешно, но чаще раздражает, а главное — польза, за редкими исключениями, нулевая.
Мы на уровне правил группы приняли стандартный язык общения и сделали, чтобы бот определял язык каждой реплики. Если прошло подряд слишком много реплик на нестандартном языке, бот вмешивается и напоминает, что нужно следовать принятым правилам.
Случается такое нечасто, впрочем.
Антиспам
Горячая тема, да, и по факту эта функция теперь — самая важная и работает постоянно. Пока наша группа была маленькой, всё было спокойно, но настал тот момент, после которого уже не было ни дня, чтобы не зашёл хотя бы один спамер. Хотя нет, в каникулы было затишье.
Бороться решили самостоятельно. Первый подход сделали с простым поиском по ключевым словам, но в современном мире это работает плохо, так что Николай накрутил модель OpenAI, которая справляется намного лучше. Иногда спамеры всё-таки пробиваются, тогда мы удаляем мусор вручную и дообучаем модель.
Смешной эпизод произошёл под новый 2025 год. Накатила волна жуликов, которые писали свои объявления при помощи «пользовательских эмодзи» в Телеграме. Эти «эмодзи» только так называются, в буквы они никак не конвертируются, так что обычные приёмы борьбы со спамом, которые анализируют текст, оказываются бессильны. Несколько дней было жарко, потом нашли против этих хитрецов асимметричный ответ, а самих хитрецов прозвали «эмо-спамерами».
Глоссарий
Только сегодня запустили.
Когда живёшь в многоязычной среде, слова из разных языков потихоньку перемешиваются в голове, и чем дальше, тем больше. В группе то и дело возникают забавные диалоги, примерно такие:
— (новичок) Я тут в поликлинику записываюсь, мне сказали, не хватает какой-то бумажки.
— (местный) Наверное, они ваш падрон хотели.
— (другой местный) Да, точно, без падрона они всех посылают, надо получить. Вы не волнуйтесь, это просто, там дел на пятнадцать минут, и ситы есть каждый день на сайте аюнтамьенто. И ещё им будет нужен ваш нумеро сегуридад.
— (третий местный) В аюнтамьенто и без ситы можно, только возьмите контрато де алкилер обязательно. А вообще, если у вас есть клаве дихиталь, вам и ходить никуда не надо, скачайте падрон в PDF.
— (новичок) Ч Т О 🤯
Тем, кто давно в теме, всё понятно, но группа-то создана для взаимопомощи, и тем, кому эта помощь нужнее всего, приходится в дополнение к своим хлопотам разбираться с кучей новых словечек. Рассказывает Артём:
Зачем столько заимствований? Живой язык срезает лингвистические «углы», как пешеходы протаптывают тропинки по газону: так удобнее, и неважно, что рядом дорожка из брусчатки. Если можно затратить меньше усилий на передачу информации или выразить мысль точнее, язык сделает это, даже в ущерб красоте и собственным правилам.
В диаспорах это проявляется в полной мере. Заимствования из окружающей языковой среды проникают в повседневную речь, адаптируя родной язык к местному быту. Это может раздражать, сбивать с толку новичков, но это неизбежно.
Вместо борьбы с испанскими ветряными мельницами (а сегодня это грозные ветрогенераторы) мы сделали собственный словарь локальных испанизмов — заимствований, не выходящих за рамки русскоязычной среды в Испании. Некоторые из них не имеют прямых аналогов в русском и могут прижиться, как в своё время гитара, табак и карамель. Другие останутся сленгом эмигрантов, а третьи вполне могут выйти из обихода: одна из задач словаря — напомнить, что сальмон не вкуснее лосося, а карточка платит не хуже тархеты.
Словарь испанизмов превратился в отдельный проект, который заслуживает собственной публикации, но здесь я рассказываю про бота, к которому и вернёмся. Мы дали боту копию глоссария, и теперь можно у него запросить справку — буквально, спросить, что такое падрон или тархета. Ещё бот читает дискуссию, и если замечает что-то из своего словаря — добавляет к реплике реакцию-эмодзи, а если в реплике сразу несколько таких словечек — даёт справку по всем ним, не дожидаясь явного запроса.
Подходы, технологии и прочие подробности
Главный принцип — «чем проще и лаконичнее, тем лучше». Бота можно написать на интерпретируемом языке и запускать прямо в терминале? Отлично, наш выбор. Нестандартные пакеты используем только при необходимости. База данных — SQLite, локализация — gettext
. Был момент, когда попробовали применить лемматизатор для поиска с учётом словоформ, но в итоге отказались в пользу обычных регулярных выражений.
Бот написан на Python, каркас — python-telegram-bot
. В БД с таблицами хранятся только книга услуг и данные антиспама, структура достаточно проста и компактна, чтобы не пришлось заморачиваться со сложными обёртками, обходимся прямыми SQL-запросами. Прочие данные, которые не меняются постоянно в результате обычной активности участников — файлы в разнообразных форматах, которые мы исправляем на коленке и загружаем на хостинг через бота.
Бот работает на любой машине с подключением к интернету, вычислительные потребности минимальны, в теории я мог бы просто у себя дома его держать, но я выключаю компьютер на ночь, так что мы выбрали в качестве хостинга pythonanywhere.com. Пока что хватает бесплатного тарифа, хотя я поглядываю на самый простой платный, пять евро в месяц, там побольше квота на CPU, и можно настроить автозапуск.
Для определения спама используем OpenAI. Рассказывает Николай:
Наблюдения показали, что спамеры палятся в первом же сообщении и спамят на довольно легко каталогизируемый список тем. На данный момент к нам залетают три группы: «быстрый заработок на крипте» (старая уже тема), «обменяю крипту на нал», а также вроде ещё сейчас наклевывается «продам билеты на Меладзе».
Поэтому задача довольно тривиальная в итоге: сделать проверялку, которая будет смотреть на первое сообщение в группе, и если проверялка триггернулась, то удалять сообщение.
Конечно, мы могли бы совсем облениться и просто написать промпт «Посмотри, не спам ли это», но переквалифицированность в этом вопросе повела нас немного более комплексной, хотя всё ещё не супер-сложной дорожкой. По сути, мы просто отслеживаем тренды входящего спама, собираем его в единый файл, из которого делаем трейн и тест-сплит, векторизуем всё это дело через OpenAI-embeddings и обучаем сверху бинарный SVC-классификатор. Такая штука отрабатывает довольно хорошо, за уже почти девять месяцев работы проскочило, может быть, 5—10 «уродцев», учитывая 5—10 спам-сообщений каждый день. А учитывая дешевизну векторов по сравнению с вызовом LLM и то, что спамеры не рассчитывают на такой заслон, такая история может работать о-о-очень долго и требует разве что просто посматривать, не появился ли какой новый тренд (пока что быстрый заработок на крипте существенно перекрывает всех остальных).
В общем плане антиспам — это единственная функция, которая обращается к стороннему сервису, и единственная, которая требует иногда закинуть долор. Вот бы её тоже сделать полностью автономной, только тогда бесплатного тарифа на хостинге точно перестанет хватать. С другой стороны, перестанем кормить OpenAI.
Над проектом активно работает три человека: я (программирую основную часть), Николай @NiGuLa (специалист по языковым моделям, настраивает модели против спамеров) и Артём (редактор текстов, советник по UX и главный по глоссарию). Также нас консультирует по общим вопросам Олег, а Наталья нарисовала для бота картинки.
Нужны ли какие-то советы или помощь Клуба?
Помощь? Ну-у-у…
С разработкой мы как будто справляемся сами. Это всё — наше хобби, задача в целом несложная, изобретать ничего не приходится, играем в такое Лего, получаем удовольствие и никуда не торопимся. Редкая возможность делать продукт для себя самих в комфортном темпе и не париться про сроки и монетизацию, потому что всё для души.
У нас пока нет никаких тестов, но это мы тоже как-нибудь сами.
Можно сделать переводы на другие языки, только непонятно, насколько это нужно. У нас сейчас есть русский и английский (который, на мой взгляд, обязан быть в публичном проекте на GitHub, и документация наша тоже вся на английском), в теории можем сделать сами ещё испанский. Но, если раз взяться, потом не спрыгнешь, придётся регулярно поддерживать, обновлять тексты всякий раз, когда мы что-то добавляем или меняем в строках, так что нужно, чтобы язык был действительно востребован, иначе это будет пустая трата времени.
Что будет действительно классно, это если наш бот пригодится в других сообществах эмигрантов, экспатов и вынужденных переселенцев! Ждём от вас отзывов и идей для новых функций, ну и если заметите ошибку, тоже будет хорошо!
Напоследок отмечу, что Николай @NiGuLa нашёл меня через Клуб, и очень вероятно, что иначе этот проект не состоялся бы — значит, Клуб уже помог!