Як я розгріб техборг свого Telegram-бота: retries, fallback-системи, кешування та TUI

💡 Усі статті, обговорення, новини про AI — в одному місці. Приєднуйтесь до AI спільноти!

Привіт! Місяць тому я розповідав на DOU про створення FoodShot — медичного Telegram-бота для діабетиків, який розпізнає їжу по фото та рахує дозу інсуліну. Тоді я детально описав своє головне архітектурне рішення (чому ШІ не має рахувати макроси) і чесно перелічив купу «технічного боргу»: відсутність кешування, нульовий error handling та парсинг JSON через regex.

Сьогодні — робота над помилками. Розповім, як я перетворив нестабільний MVP на fault-tolerant систему і навіщо написав термінальну адмінку для бекенда. Трошки нижче додав демо

1. Перемога над ретраями Telegram

У першій версії бот страждав від класичної хвороби важких Telegram-ботів. Якщо GPT-4o Vision обробляв фотографію довше 3–4 секунд, Telegram вважав, що мій бекенд «лежить», і починав автоматично слати дублікати того ж запиту (retries). Результат — скажений спам дуже дорогими запитами до OpenAI та кілька однакових відповідей користувачу.

Рішення: Я перевів архітектуру на асинхронне виконання. Тепер FastAPI-вебхук приймає апдейт, кидає важку логіку (vision + USDA) у BackgroundTasks і миттєво віддає Телеграму заповітний HTTP 200. Щоб остаточно захиститися від фантомних дублів, я додав кешування update_id у Redis. Якщо ідентифікатор уже є в кеші — запит просто ігнорується.

2. Fallback-системи: коли OpenAI лежить

Минулого разу я зізнався, що якщо API впаде — бот мовчки крашнеться. Для медичного застосунку це неприпустимо.

Тепер у проєкті реалізовано каскадний fallback. Якщо OpenAI не відповідає або падає з 500-ю помилкою, запит непомітно для користувача перемикається на Gemini. Те ж саме стосується бази нутрієнтів: якщо урядова USDA FoodData Central лягла на профілактику (що буває), запит автоматично підхоплює запасний Nutritionix API. Надійність виросла в рази.

3. Кешування та смерть regex

Тепер усе переписано на Pydantic: модель зобов’язана повертати суворий JSON інакше запит не пройде валідацію.

Крім того, я нарешті додав кешування. Оскільки база USDA не змінюється щомиті, я кешую відповіді в Redis на 7 днів за нормалізованими ключами. Якщо один юзер сфотографував «carbonara», наступний отримає макроси миттєво з кешу, без очікування відповіді від повільного зовнішнього API.

4. Архітектура

Концепція адміністрування

Оскільки в мене немає веб-фронтенду, керувати користувачами (наприклад, видавати Premium) та моніторити логи через базу даних — це суцільний біль. Писати окрему React-адмінку не хотілося. Тому я взяв фреймворк Textual і написав повноцінний дашборд прямо в терміналі (TUI). Тепер я просто заходжу по SSH на сервер, пишу команду task ops — і маю красивий консольний інтерфейс з графіками та логами бази. Ніколи не думав, що термінальні інтерфейси можуть бути настільки зручними для Ops-рутини.

Що далі?

Для мене це серйозна частина мого інженерного життя, тому код проєкту повністю відкритий. Релізна версія бота вже працює в Telegram, але робота не зупиняється. У планах додати розпізнавання кількох страв на одному фото (Plate Splitter) та прикрутити інтеграцію з моніторингами глюкози (CGM).

GitHub проєкту: github.com/soroqn1/FoodShotСам бот: t.me/foodshot_bot

Невеличкий P.S.

FoodShot досі не завершений. І, мабуть, це найцікавіше. Дуже важко описати сотні годин роботи, баги з нескінченними ретраями Telegram або міграції БД в одній статті, бо доведеться використати занадто багато літер.

Тому, якщо вас зацікавила моя історія, підхід до архітектури або ви просто хочете покритикувати мій код — пишіть у коментарях, з радістю відповім. Буду радий порадам чи новим ідеям. Дякую за приділений час!

👍ПодобаєтьсяСподобалось0
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Підписатись на коментарі