# Как безопасно делать AI-оценку калорий и БЖУ по фото еды

Автор: [t.me/sexyllm](https://t.me/sexyllm)  
Дата: 30 июня 2026

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

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

## Короткая архитектура

Лучший паттерн для MVP:

```text
Фото еды
→ AI распознаёт продукты и примерные порции
→ база питания даёт БЖУ на 100 г
→ приложение считает итог
→ пользователь проверяет и сохраняет
```

Важно: модель не должна быть источником правды по БЖУ. Она хорошо подходит для
разбора картинки: "похоже на рис, курицу и салат, риса примерно 120-180 г".
А вот калории и БЖУ лучше брать из нормальной базы питания: USDA FoodData
Central, Open Food Facts, локальная база продуктов или сохранённые блюда
пользователя.

## Пример стека

Для первого прототипа можно взять:

- vision-модель: `gpt-5.4-mini` или аналогичный multimodal API;
- изображение: ужать на клиенте до `1024px` по длинной стороне, JPEG `0.75`,
  удалить EXIF;
- ответ модели: строгий JSON, без длинного текста;
- питание: USDA FoodData Central для обычных продуктов, Open Food Facts для
  упаковок и barcode-сценариев, локальная база для сохранённых продуктов;
- UX: показать черновик, дать поправить граммы и углеводы, сохранить только
  после подтверждения.

## Пример стоимости

На текущих публичных ценах `gpt-5.4-mini` стоит примерно:

- input: `$0.75` за 1M токенов;
- cached input: `$0.075` за 1M токенов;
- output: `$4.50` за 1M токенов.

Для одного food-photo scan при сжатом изображении и коротком JSON-ответе
получается примерно:

| Объём | Примерная цена |
|-------|----------------|
| 1 скан | `$0.003-$0.008` |
| 1000 сканов | `$3-$8`, ориентир около `$5` |
| 10000 сканов | `$30-$80`, ориентир около `$50` |

Если модель отвечает слишком длинно, стоимость быстро растёт: output-токены
дороже input. Поэтому для production лучше держать `max_output_tokens` в районе
`600-900`, а `1500-2000` оставлять для отладки и benchmark.

Цены API меняются, поэтому перед публикацией и запуском их надо перепроверять.

## Где AI ошибается

Ожидаемый разброс в реальном продукте:

| Тип еды | Риск ошибки по углеводам |
|---------|--------------------------|
| Яблоко, банан, кусок хлеба, йогурт | примерно `±5-15 г` |
| Обычная тарелка: гарнир + мясо + овощи | примерно `±10-25 г` |
| Плов, паста, суп, рагу, салат с соусом | может быть `±20-50 г+` |
| Десерты, напитки, панировка, скрытый сахар | высокий риск |

Проблема не только в распознавании еды. Модель может понять, что это рис, но не
знать, 120 г его там или 240 г. Камера не даёт точных весов.

## Safety для диабет-приложений

AI-оценку еды в диабет-контексте стоит делать не "калькулятором", а
генератором черновика.

Хорошие формулировки:

```text
Estimated carbs: 45-70 g
Photo estimates can be inaccurate. Review before saving.
```

Плохие формулировки:

```text
Detected 57.3 g carbs
Use this for your insulin dose
```

Минимальные guardrails:

- показывать диапазон, а не точное число;
- всегда требовать подтверждение пользователя;
- давать быстро поправить граммы, углеводы и блюдо;
- не рассчитывать дозу инсулина;
- не писать "bolus", "dose", "correction", "therapy";
- для супов, рагу, соусов, напитков и скрытых ингредиентов включать ручной
  режим;
- сохранять результат как "оценку по фото", а не как verified nutrition.

## JSON-контракт

Полезно сразу требовать от модели не свободный текст, а короткий JSON:

```json
{
  "mode": "estimate",
  "items": [
    {
      "name": "cooked white rice",
      "category": "grain",
      "estimated_grams_min": 120,
      "estimated_grams_max": 180,
      "confidence": 0.72,
      "risk_flags": ["portion_scale_unclear"],
      "search_terms": ["rice cooked white"]
    }
  ],
  "portion_uncertainty": "medium",
  "manual_required": false,
  "warnings": ["portion_estimate_only"]
}
```

Для рискованного блюда:

```json
{
  "mode": "manual_required",
  "items": [
    {
      "name": "mixed stew",
      "category": "mixed_dish",
      "estimated_grams_min": null,
      "estimated_grams_max": null,
      "confidence": 0.45,
      "risk_flags": [
        "hidden_ingredients",
        "soup_or_stew",
        "portion_scale_unclear"
      ],
      "search_terms": []
    }
  ],
  "portion_uncertainty": "high",
  "manual_required": true,
  "warnings": ["manual_entry_recommended"]
}
```

`mode` лучше делать явным:

- `estimate`: можно показать черновик;
- `manual_required`: еда есть, но оценка слишком рискованная;
- `non_food`: еды не видно.

## Как экономить

Пять простых рычагов обычно дают большую часть экономии:

1. Сжимать фото до разумного размера.
2. Просить только JSON, не prose.
3. Жёстко ограничивать `max_output_tokens`.
4. Сначала проверять локальную базу, barcode и сохранённые блюда.
5. Кэшировать повторные nutrition lookup, но не хранить фото еды без причины.

Хорошая цель для MVP: удерживать среднюю цену около `$0.005` за скан и отдельно
смотреть p95, потому что дорогие хвосты часто прячутся в длинных ответах модели.

## Privacy и legal

Terms of Service нужны, но сами по себе они не делают функцию безопасной.

Нужны ещё продуктовые и технические ограничения:

- понятное first-use предупреждение;
- отсутствие автосохранения;
- отсутствие связи с дозами инсулина;
- отсутствие логирования фото, названий еды и БЖУ;
- stateless proxy между приложением и AI provider;
- настройки вроде `store: false`, если provider их поддерживает;
- отключённое использование API data для обучения/улучшения, если это возможно;
- kill switch на случай проблем с ценой, точностью или безопасностью.

Для health/diabetes-приложений wording особенно важен. Лучше писать
"food diary draft" или "photo estimate", а не "medical-grade nutrition scanner".

## Минимальный Phase 1

Если делать прототип, я бы ограничил scope так:

1. Фото → resize/compress/strip EXIF.
2. Stateless proxy → multimodal model.
3. Structured JSON: еда, диапазон граммов, confidence, risk flags.
4. Nutrition lookup через USDA / Open Food Facts / локальную базу.
5. Review screen: editable carbs, grams, calories, protein, fat.
6. Сохранение только после user tap.
7. Логи только технические: latency, status, token bucket, cost bucket.

Никакой дозировки, никакой терапии, никакого "точного" результата.

## Главный вывод

AI по фото еды можно запускать дёшево и быстро, если воспринимать его как
черновик, а не как истину. Для обычного calorie tracker это вопрос UX и
стоимости. Для диабет-приложения это ещё и вопрос безопасности: диапазоны,
ручное подтверждение и запрет на медицинские выводы должны быть частью продукта,
а не мелким disclaimer внизу экрана.

---

Автор: [t.me/sexyllm](https://t.me/sexyllm)

## Sources

- [OpenAI pricing](https://developers.openai.com/api/docs/pricing)
- [OpenAI GPT-5.4 mini model docs](https://developers.openai.com/api/docs/models/gpt-5.4-mini)
- [OpenAI image and vision docs](https://developers.openai.com/api/docs/guides/images-vision)
- [USDA FoodData Central API guide](https://fdc.nal.usda.gov/api-guide)
- [Open Food Facts API docs](https://openfoodfacts.github.io/openfoodfacts-server/api/)
