Skip to content

soroqn1/FoodShot

Repository files navigation

FoodShot

Telegram bot for people with diabetes: send a food photo, get carbs, calories, portion estimate, and an insulin bolus suggestion.

Python aiogram FastAPI PostgreSQL Redis Docker

OpenAI USDA Localization License


FoodShot is a practical Telegram assistant for meal estimation. A user sends a photo of food, the bot recognizes the dish, estimates the portion, fetches nutrition data, asks for current glucose if needed, and calculates a suggested insulin dose using the user's personal settings.

FoodShot gives estimates only. It is not a medical device and does not replace advice from a qualified healthcare professional.

Demo

The bot works directly inside Telegram:

  • recognizes the dish from a photo;
  • estimates portion weight and confidence;
  • calculates carbs and calories;
  • lets the user adjust the portion with inline buttons;
  • asks for current blood glucose or accepts /skip;
  • returns a bolus breakdown and saves the meal history.

FoodShot Telegram bot demo

How It Works

Photo in Telegram
  -> FastAPI webhook receives Telegram update
  -> aiogram handler downloads the image
  -> Vision AI detects dish, portion, confidence
  -> Nutrition service fetches macros
  -> User adjusts portion and enters glucose
  -> Calc engine computes bolus
  -> Result is sent back and saved to PostgreSQL

Features

Feature Description
Food photo analysis Detects dish name, estimated weight, and confidence level.
Nutrition lookup Gets carbs, calories, protein, and fat from nutrition data.
Portion correction Inline buttons let the user adjust grams before calculation.
Bolus calculation Uses ICR, ISF, target glucose, current glucose, and carbs.
Personal profile Stores insulin ratio, sensitivity, target glucose, insulin type, and language.
Meal history Saves meals and shows the last 10 logs via /history.
Localization Supports English and Ukrainian.
Docker setup Runs bot, PostgreSQL, and Redis with Docker Compose.

Architecture

FoodShot architecture

Layer Stack
Client Telegram
Bot runtime aiogram 3.x, FSM handlers
Web server FastAPI webhook endpoint
Vision OpenAI GPT-4o
Nutrition USDA FoodData Central
Calculation Custom bolus engine
State Redis
Database PostgreSQL, async SQLAlchemy
Deployment Docker, Docker Compose

Commands

Command Purpose
/start Register profile: ICR, ISF, target glucose, insulin type.
/settings Edit profile values and change language.
/history Show the last 10 meals.
/help Show a short usage hint.
/skip Skip current glucose during meal analysis.

Bolus Formula

FoodShot keeps the calculation transparent:

carb_dose  = carbs_g / icr
correction = (current_bg - target_bg) / isf
total      = carb_dose + correction

Correction is used only when the user provides current glucose and it is above the target.

Project Structure

.
├── api/
│   └── webhook.py          # FastAPI app and Telegram webhook
├── bot/
│   ├── handlers/           # start, photo, settings, history, help
│   ├── keyboards/          # reply and inline keyboards
│   ├── states.py           # aiogram FSM states
│   └── i18n_middleware.py  # language detection
├── core/
│   ├── config.py           # pydantic settings
│   └── i18n.py             # runtime translations
├── db/
│   ├── models.py           # SQLAlchemy models
│   ├── crud.py             # async DB operations
│   └── database.py         # engine and session setup
├── services/
│   ├── vision.py           # OpenAI vision wrapper
│   ├── nutrition.py        # nutrition data client
│   └── calc.py             # bolus calculation
├── doc/
│   ├── foodshot_architecture.svg
│   └── tg_fries.png
├── docker-compose.yml
├── Dockerfile
├── Taskfile.yml
└── pyproject.toml

Environment

Create .env from the example:

cp .env.example .env

Required values:

BOT_TOKEN=your_telegram_bot_token
OPENAI_API_KEY=your_openai_api_key
USDA_API_KEY=your_usda_api_key

POSTGRES_USER=foodshot
POSTGRES_PASSWORD=foodshot_pass
POSTGRES_DB=foodshot

DATABASE_URL=postgresql+asyncpg://foodshot:foodshot_pass@localhost:5432/foodshot
REDIS_URL=redis://localhost:6379/0

WEBHOOK_URL=https://your-ngrok-domain.ngrok-free.app/webhook
PORT=8000

For Docker Compose, the bot container overrides database and Redis hosts internally:

DATABASE_URL -> db:5432
REDIS_URL    -> redis:6379

That keeps .env convenient for local development while Docker services still talk to each other by service name.

Quick Start

Install dependencies:

task install

Start PostgreSQL and Redis only:

task infra

Run FastAPI locally with reload:

task dev

Run the full Docker stack:

task up

Show logs:

task logs

Stop services:

task down

Webhook Setup

Expose port 8000 with ngrok:

ngrok http 8000

Set the Telegram webhook URL in .env:

WEBHOOK_URL=https://your-ngrok-domain.ngrok-free.app/webhook

The app registers this URL on startup:

POST /webhook

If Telegram keeps calling an old URL, inspect it with:

curl -s "https://api.telegram.org/bot$BOT_TOKEN/getWebhookInfo"

Data Model

FoodShot stores:

  • users: Telegram id, username, ICR, ISF, target glucose, insulin type, language.
  • meal_logs: dish, portion, macros, suggested bolus, current glucose, photo id, timestamp.

Safety

Food recognition, portion estimation, nutrition databases, and insulin formulas can be wrong. FoodShot is an assistant for estimation, not a clinical decision system.

Always verify calculations before making insulin decisions and follow the treatment plan agreed with a qualified healthcare professional.

About

Telegram bot for people with diabetes: send a food photo, get carbs, calories, portion estimate, and an insulin bolus suggestion

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors