Приветствую! Последние несколько недель я занимался созданием проекта, который способствует улучшению усвоения информации на основе заметок. Мне хотелось сделать инструмент, которым смогу пользоваться не только я, но и другие. В ходе этой разработки я столкнулся с рядом проблем и процессом их решения, которые решил отобразить в этой статье. Изложенная здесь информация будет интересна тем, кто тоже хочет создать что‑то свое, но не знает с чего начать.

Несколько месяцев я нахожусь в такой среде, где постоянно создается что‑то новое. Также в моем инфополе имеются интересные ребята, которые делают свои проекты и делятся этим.

Мне стало интересно погрузиться в этот процесс самому, поэтому начал думать над идеями, которые мог бы реализовать.

Во время прочтения книги пришла очевидная мысль, что многое из того, что было прочитано и изучено очень легко забывается. На этой почве я решил создать инструмент, который бы решал эту проблему.

Это должен был быть простой инструмент, который способен запоминать и хранить информацию в виде заметок, предлагать какие‑то простые (которые возможно сделать дома) практические рекомендации для закрепления. Также для удобства можно было бы посмотреть выжимку из всех заметок, чтобы быстро их вспомнить. Еще вспомнился университет, где в качестве проверки знаний давали опросы по лекциям, что тоже помогало проверить качество усвоенных материалов.

Собрав все это воедино, решил сделать бота, который бы решал эти задачи.

Проработка технического задания и архитектуры

Вдохновившись идеями из книги Роберта Мартина «Чистая архитектура», мне не терпелось применить знания на практике. Поэтому перед написанием кода я занялся продумыванием требований, функционала приложения и его архитектурой.

Выделил следующие функции, которые должен делать бот:

Основные функции бота
Основные функции бота

Естественно, мне сразу же пришла идея внедрить туда технологии Text to Speech для озвучки заметок и Speech to Text для записи и сохранения заметок голосом. Эти пункты тоже попали в техническое задание (ТЗ).

После небольшого брейншторма, я опустился чуть глубже, а именно для каждой из перечисленных функций перечислил конкретные операции, которые нужно сделать для их выполнения.

Например:

Операции при выполнении функций
Операции при выполнении функций

После составления ТЗ, я перешел к продумыванию архитектуры приложения.
Взяв правило из книги "Чистая архитектура" про разделение бизнес‑логики от реализации, на основе ТЗ выделил основные компоненты, которые необходимы для системы:

Основные компоненты инструмента
Основные компоненты инструмента

Техническая реализация

Далее начал продумывать технологии, которые я могу применить.
В качестве языка программирования выбрал Python, потому что имею наибольший опыт работы с ним.

В качестве фреймворка для разработки Telegram-бота остановился на python‑telegram‑bot, потому что он имеет хорошую поддержку, а также простой интерфейс.

В качестве базы данных взял PostgreSQL, потому что имею опыт работы с ней и видел ее во многих проектах.

В качестве LLM, которая будет решать задачи NLP, остановился на GigaChat и библиотеке lagnchain‑gigachat для взаимодействия с ней (в ходе разработки и тестирования я перешел на OpenRouter, но об этом расскажу далее).

Далее я занимался анализом и небольшим тестированием различных библиотек для TTS, STT. Выбор оказался достаточно обширным, но я искал то, что можно запустить на небольшим железе. Для STT стоял выбор между Whisper и Vosk. Немного изучив различные инструменты и требования, остановился на библиотеке fast‑whisper, которая предоставляет простой интерфейс для транскрибации аудио и работает на CPU. Для TTS я выбрал библиотеку pyttsx3 (Но в дальнейшем я перешел на модель из transformers, расскажу ниже почему).

Выбранный стек технологий
Выбранный стек технологий

После того как я определился со стеком, я перешел к разработке.
В начале я написал так называемый core, который представлял основные интерфейсы для бизнес‑логики приложения.
- LLM: get_summarization, get_recommendation, get_survey
- input_notes: save_note, note_from_audio
- text_to_speech: text_to_audio
- speech_to_text: speech_to_text
- ...

После я перешел к реализации. Сначала я начал с небольшого изучения библиотеки python‑telegram‑bot. Попробовал написать простого echo-бота. В этот момент я решил ускорить процесс разработки и перешел в Cursor и большую часть кода писал через него (в процессе проверяя, что все, что он пишет, валидно). Важно было то, что агент в Cursor учитывал мои требования по архитектуре и старался делить компоненты как мне нужно, чтобы они были просто заменяемы.

Через пару дней я получил прототип со всем функционалом, который был в ТЗ .

Далее перешел к процессу развертывания. Обернул своего бота в Docker, арендовал сервер и разместил там приложение. Бот запускался и работал.

Во время тестирования я обнаружил, что при озвучке заметок, используя pyttsx3 появился механизированный набор звуков, который не могли нормально озвучить заметки. Немного покопавшись я обнаружил, что так как я перешел с Windows на своем домашнем компьютере, на Ubuntu на сервере, библиотека стала использовать другой движок воспроизведения (espeak). Именно из‑за этой смены у меня перестали нормально озвучиваться заметки.
Я начал искать другой инструмент, который был бы способен озвучивать заметки, работая при этом на слабом сервере с CPU. В последствии я остановился на tts_ru_free_hf_vits_low_multispeaker из библиотеки transformers, которая? не идеально, но смогла запускаться и озвучивать заметки на небольшом сервере.

Далее во время тестирования я обнаружил, что если делать большое количество запросов на STT и TTS, то мой сервер с 4 ГБ ОЗУ не справлялся с нагрузкой и просто падал.

Я пришел к выводу, что если сразу несколько пользователей начнут пользоваться этими фичами, то слабый сервер не будет выдерживать такой нагрузки. На основе этого принял решения реализовать очередь, в которую будут помещаться все запросы TTS, STT и которые будут обрабатываться каждый последовательно.

Для реализации очереди был применен стек Celery + Redis, где Celery выступает в роли воркера, а Redis — брокера сообщений.

Очередь Celery + Redis
Очередь Celery + Redis

Во время реализации очереди я столкнулся с проблемами, связанными с несовместимостью Celery и python‑telegram‑bot, которые не позволяли после обработки задач сразу отправлять сообщения пользователям. Немного покопавшись, я остановился на реализации, когда в Celery после обработки задачи я отправляю ответ напрямую в чат, используя request и Telegram API, указав соответствующий чат и креды для бота.
В конечном итоге задачи TTS и STT у меня отрабатывали последовательно, и, соответственно, сервер мог выдержать такую нагрузку.

Далее я пришел к мысли, что пользователи могу использовать такие функции, как TTS, STT, суммаризация, генерация практической рекомендации и составление опроса без ограничений на количество запросов, а также на размер используемых данных. Это означало, что пользователь мог загрузить "Войну и мир" в заметки и делать ее суммаризацию большое количество раз, либо же записать аудио на несколько часов отправить его на транскрибирование . Такие моменты могли вывести из строя работоспособность бота, а также потратить все средства в сервисе с LLM. Я принял решение ввести ограничения для каждого пользователя на ежедневное использование таких функций. (На все перечисленные выше по 5 запросов на каждую). Также я добавил ограничение на размер текста, который может приниматься LLM и TTS, и ввел ограничение на длительность голосового сообщения, которое может загружать пользователь. Эти действия помогли мне защитить свой сервис от спама, перегрузки сервера и траты средств на использование LLM.

Далее во время тестирования я обнаружил, что? используя API от GigaChat (использовал личное пространство, не корпоративное) я мог обрабатывать запросы на суммаризацию, генерацию рекомендации и составление опроса только в 1 потоке. То есть, если пользователей будет больше — API просто не даст им выполнить действия.

На этом шаге я решил также перенести запросы в Celery для последовательной обработки. Но мне хотелось увеличить количество потоков, не прибегая к покупке корпоративной подписки на GigaChat (в ней дается больше потоков для работы).

Я перешел на OpenRouter, в котором также по API можно получить доступ к моделям.
В связи с удобной архитектурой, которая была продумана в начале, я смог безболезненно заменить формат работы с LLM c GigaChat на OpenRouter. Все работало.

Подготовка к релизу

Мои товарищи дали обратную связь по боту, указав на то, что не всегда понятно, что в нём нужно делать (нет инструкции), а также на моменты, связанные с тем, что при генерации рекомендации и опросника ИИ считает, будто для любой заметки можно сделать практическую рекомендацию и опросник, но, например, для «В 15:00 психолог» такие вещи не сделаешь. Я записал это в будущий бэклог как фичу: классификация запросов. Идей было много, что можно добавить и доработать, но я решил на основе комментариев составить определенное превью для бота, которое показывало его функционал и в целом то, что оно умеет и как.

Я снял пару небольших демонстрационных видео: от создания и озвучки заметки до составления опроса. Объединил это все через встроенный в Windows Clipchamp, добавил текста, переходов, и получил простое превью приложения.

Скриншоты из бота
Скриншоты из бота

Самого бота можно попробовать здесь: @your_smart_notes_bot

Заключение

Данный бот не идеален, есть много улучшений которые можно сделать:

  • Провести рефакторинг кода и написать тесты;

  • Улучшенные транскрибация аудио и озвучка текста;

  • RAG, который позволит задавать вопросы по базе заметок и получать ответы;

  • Суммаризация не всех заметок, а только определенных групп;

  • ... идей много.

В этом проекте я выделил некоторые сложности и нюансы, которые могут возникать во время создания проекта. Я получил интересный опыт, который буду использовать в дальнейшем на других проектах, чтобы делать более устойчивые и рабочие решения.

Подписывайтесь на мой Telegram канал, в котором я рассказываю интересные вещи об IT и AI технологиях.

Комментарии (1)


  1. pol_pot
    23.11.2025 14:29

    Во время реализации очереди я столкнулся с проблемами, связанными с несовместимостью Celery и python‑telegram‑bot, которые не позволяли после обработки задач сразу отправлять сообщения пользователям. Немного покопавшись, я остановился на реализации, когда в Celery после обработки задачи я отправляю ответ напрямую в чат, используя request и Telegram API, указав соответствующий чат и креды для бота.

    Что за несовместимость?

    Зачем вообще телеграм, почему не веб сайт, у веб сайта нет ограничений типа нельзя закачать в бота больше чем 20мб файл или показать юзеру текст больше 4к без разрывов.