В основном, про Firebase рассказывают в контексте создания приложений под IOS или Android. Однако, данный инструмент можно использовать и в других областях разработки, например при создании Telegram ботов. В этой статье хочу рассказать и показать насколько Firebase простой и удобный инструмент (а ещё и бесплатный, при разумных размерах проекта). Ровно посередине апреля я очнулся от работы и вдруг вспомнил, что у меня ещё не написан диплом, а сдавать его через месяц - полтора. У меня была заброшенная научная статья на достаточно скучную тему, делать на её базе диплом мне уж совсем не хотелось. Нужен был глоток свежего воздуха - какой-нибудь новый проект. В середине февраля я с ребятами из веб студии обсуждал идею создания приложения по подбору квартир с рекомендательной системой, которая анализировала бы изображения интерьеров и подстраивалась под предпочтения пользователя. Так как мой диплом должен быть на тему Computer Vision, то я решил развить эту тему. Да, и было придумало прикольное название - Flinder (Flats Tinder). Если погружаться в детали,  то для создания рекомендательной системы, работающей с изображениями, необходимо построить пайплайн конструирования эмбедингов на базе изображений. Эмбединг - это вектор,  содержащий в себе информацию о изображении и являющийся результатом работы нейронной сети.  В частности, меня вдохновила одна научная статья про  DeViSE: A Deep Visual-Semantic Embedding Model.  Мне было интересно попробовать такие эмбединги. Если кратко, то авторы статьи обучили нейронную сеть предсказывать не конкретные классы изображений, по типу "кошка", "собака", а векторные представления названий классов. Это те самые векторные представления, для которых "King - Man + Woman =  Queen".  Такой подход, объединяет визуальное представление нейросети об изображении со структурой языка. Это приводит, например, к тому что модель может предсказать класс, которого не было в датасете, но который семантически близок к классу из датасета. Для рекомендательной системы важно настроить алгоритм сбора данных о взаимодействии пользователей с контентом. В такой ситуации сложно придумать что-то более быстрое в разработке, чем телеграм бот. Итак, телеграм бот:  Присылает пользователю изображение и просит его оценить  Получает оценку от пользователя  Сохраняет оценку пользователя в базу данных  *киллер фича* - удаляет изображение из диалога, если оно не понравилось пользователю  На первом этапе работы бот присылает пользователю случайные изображения. Но при последующем развитии проекта и интеграции рекомендательной системы бот будет присылает всё более и более релевантные фотографии.  Да, также важно раздобыть контент, который пользователи будут оценивать. Немного заморочившись я скачал сразу 20.000 изображений с интерьерами с Pinterest. Это были и запросы как «скандинавский интерьер квартиры» так и «готический интерьер дома».  Старался собрать как можно более разнообразный (репрезентативный) набор изображений.  Изображения добывал с помощью библиотечки pinterest-image-scraper (Там есть баги и она не супер удобная, но мне её хватило). Меня немного смущал момент отправки изображений телеграм ботом. Получившаяся база изображений в 20.000 штук весила примерно 1.5 гигабайта и мучаться с переносом её на сервер мне уж совсем не хотелось.  Тут я подумал о том, что было бы классно выложить все фотографии на какой-нибудь облачный сервис, и дальше в телеграмм боте использовать только ссылки на изображения, а не сами изображения. А ссылки на изображения (или идентификаторы изображений) и оценки пользователей можно хранить в Firebase Realtime Database.  Перед этим я быстро проверил, поддерживает ли библиотека pyTelegramBotAPI отправку изображений ссылками. Метод send_photo спокойно работал с ссылками на изображения, так что я решил дальше использовать этот подход. Прежде я работал только с Firebase Realtime Database, но про удобство Firebase Storage был наслышан.  Итак, чтобы начать работать с Firebase вам необходимо зарегистрироваться на этом сервисе и создать там проект.  После чего у вас откроется вкладка Project Overview.  Для того чтобы получить доступ к функциям Firebase из кода необходимо скачать ключи доступа к проекту. Сделать это можно нажав на значок шестерёнки в верхнем левом углу, справа от надписи Project Overview, и выбрать пункт Project Settings. Затем, на открывшемся экране нужно выбрать Service Accounts и нажать Generate new private key.  После чего, выбрав в левой вкладке меню Realtime Database и Storage можно создать соотвествующие базы данных. В проект на питоне подключить эти базы данных можно следующим способом. Где правые части внутри выражения initialize_app есть условные ссылки на названия ваших баз данных внутри проекта в Firebase. После инициализации у вас будут доступны две базы данных  db - объект Realtime Database. Данные хранятся в виде одного JSON дерева. В случае работы с питоном - это по сути объект dict. bucket - объект Storage, по сути, обёртка над Google Storage, позволяющая по API загружать и скачивать объекты. Далее покажу несколько примеров использования этих двух баз данных. Обожаю эту базу данных и готов петь ей дифирамбы. Она очень удобная, быстрая, надёжная, а главное - никакого SQL! Это JSON based Database. Но хватит похвалы, давайте посмотрим, как с ней работать. Например, у нас есть несколько пользователей, которые хранятся в users_database.  Добавить их в в Realtime Database мы можем так: Также мы можем добавить и следующего пользователя таким вот образом: Этот код добавит user_3 в users_database  Получить данные можно так. Это вернет объекты формата Python dict  Стоит отметить, что массивы в Realtime database хранятся в следующем виде. То есть также в формате json  И ещё один нюанс, Realtime Database не хранит объекты None и  То есть код  Приведёт к ошибке  А код Удалит данные user_3 Также стоит добавить, что если внутри вашего объекта в питоне есть какое-либо поле, значение которого есть None или , то в объекте, загруженном в Realtime Database этих полей не будет. То есть: На самом деле, методами get() и set() всё не ограничивается. По ссылке вы можете посмотреть документацию по firebase_admin.db Вернёмся к Firebase Storage. Допустим, у нас на локальном диске хранится изображение по пути image_path Следующий код добавит это изображение в Storage. Где image_id - уникальный идентификатор изображения. С получением доступа к изображению всё чуточку сложнее.  blob имеет формат  Где есть selfLink и mediaLink, однако доступ к изображению по этим ссылкам - ограничен и доступен только при наличии определенных прав доступа, которые настраиваются в консоли Firebase. В своём проекте я постарался сделать всё максимально просто и поэтому воспользовался методом blob.generate_signed_url(...). Этот метод генерирует ссылку, которая имеет определённое время жизни. Время жизни ссылки является параметром метода.  Следующий метод генерирует ссылку, живущую 10 минут.  Не буду вдаваться в подробности написания телеграм ботов, так как на эту тему статей много (простой туториал, супер подробная статья). Пройдусь только по основным моментам.  В своём проекте на pyTelegramBotAPI я использовал InlineKeyboardButton, состоящую из эмоджи и callback_query_handler, обрабатывающий нажатия на кнопки.   Пока писал статью столкнулся с тем, что редактор статей Хабр в браузере Safari не переваривает эмоджи внутри вставок с кодом. Если что, в моём боте кнопки имеют такой вот вид, ниже скрин кода. Реакции пользователей я храню в Realtime Database. Добавляю их туда следующим образом. База данных Firebase Realtime Database имеет следующий вид  users - база данных пользователей.  Для каждого пользователя в разделе interactions мы храним взаимодействия пользователя с изображениями. last_image_id и last_message_id - элементы логики работы телеграмм бота. Что-то типо конечного автомата. Да, и идентификаторы пользователей в базе данных - это telegram id пользователей (chat_id  для библиотеки telebot). interiors_images - база идентификаторов изображений. В ней хранятся метаданные изображений, а также дублируются реакции пользователей. Ну и images_uuids в Realtime Database - это просто массив с уникальными идентификаторами изображений. Своего рода костыль, чтобы было откуда выбирать идентификаторы изображений.  Собственно говоря сам костыль.  Да, на первом этапе, изображения, отправляемые пользователю, выбираются случайным образом. Firebase Storage выглядит таким вот образом. Можно заметить, что названия изображений в Storage есть просто идентификаторы изображений + их расширение. Также, огромным плюсом облачных баз данных является то, что можно хранить состояния взаимодействия пользователя с ботом. И если вдруг сервер решит перезапустить код бота, то это состояние сохранится. (Хотя если пользоваться обычной базой данных состояние тоже сохранится, так что это такой, притянутый за уши плюс) Вообще, из недостатков библиотеки pyTelegramBotAPI - это то, что она медленная. И под напором сообщений от большого количества пользователей что-то вполне может пойти не так. Так что в будущем я планирую использовать другую, более мощную библиотеку. Проект в нынешнем виде - это буквально один вечер работы и поэтому я использовал знакомые мне инструменты, с которыми я уже работал. Последнее время я стал адептом докера, поэтому и этот свой проект я размещал на сервер с помощью докера. Пройдусь по основным моментам, которые я использовал в проекте. Dockerfile  Где src  - это место монтирования docker volume, который я создал до этого командой  После чего собрал образ и запустил контейнер следующим образом, где флаг-v монтирует созданные ранее flinder_volume в директорию src внутри докер контейнера. Ну и полезное замечание, что у команды  docker run можно указать прекрасный параметр  --restart always, который обеспечит постоянную работу бота на сервере. До этого я делал через systemctl, что было сложнее и менее удобно.  Надеюсь, моя статья была полезна. Хочу привнести в сообщество программистов такую идею, что работать с Firebase - это очень просто, приятно и удобно, а главное - бесплатно, при разумных размерах проекта.  Более того, использование Firebase не ограничивается Телеграм ботами, недавно я сделал целый промышленный парсер инстаграмма на основе Firebase Realtime Database, о чём я тоже планирую написать статью.  Касательно моего проекта, буду благодарен, если вы повзаимодейтсвуете с моим ботом, там собраны классные фотографии интерьеров. Несколько часов сидел на Пинтересте и выбирал наиболее эстетичные категории. Добавил даже интерьеры квартир с двойным светом и интерьеры домов в стиле шале. С помощью бота планирую собрать данные для того чтобы проверить гипотезу о том, что эмбединги DeViSE работают эффективнее обычных эмбедингов изображений в контексте рекомендательных систем.  По поводу других проектов, оставлю свой телеграм канал. Периодически пишу туда про проекты, которыми занимаюсь (а их много, есть даже нейросети для театра). Более того, если вам вдруг нужен сайт или приложение с продвинутым бэкендом, то милости прошу, моя веб студия. Занимаемся проектами любой сложности. Business Strategy & Operations at Revolut Crypto