はじめに
カロリー記録アプリは便利ですが、自分は続きませんでした。
理由は単純で、入力までの導線が重かったからです。
- アプリを開く
- 入力画面へ移動する
- 食品を検索する
- 量を調整する
- 保存する
最近では写真入力やAI機能が付いているものもありますが、それでも自動入力後に量の調整を手動で入れる必要が出たり、自炊料理ではブレが大きかったりしました。
しっかり管理したい人には合っていますが、日常の食事記録としては少し面倒でした。
一方で、ChatGPT は普段からよく使っています。
ダイエットメニューを聞いたり、昼食べたものを教えたうえで夜どんなものを食べると良いかアドバイスをもらったり…
だったら、食事内容を自然文で送り、必要なときだけ記録する形のほうが続けやすいのではと思い、
カスタムGPT + GPT Actions + GAS + Google スプレッドシートで食事記録ワークフローを作りました。
これは独自UIを持つアプリというより、ChatGPTを入口にした記録フローです。
何を作ったのか
流れはシンプルです。
- ChatGPT で食事内容を自然文で送る
- カスタムGPT が食材・量・推定カロリーを整理する
- 「保存して」と言ったときだけ GPT Action を実行する
- GAS 経由で Google スプレッドシートに保存する
- スプレッドシート側で集計・可視化する
たとえば、こんな入力を想定しています。
朝ごはんは無糖ヨーグルト100g、バナナ半分、目玉焼き、塩パン
ポイントは、毎回自動保存せず、保存したいときだけ保存することです。
構成
ユーザー
↓
カスタムGPT
↓
GPT Actions
↓
Google Apps Script
↓
Google スプレッドシート
役割はこんな分担です。
-
カスタムGPT: 自然文の解釈、カロリー推定、保存用JSONの組み立て
-
GPT Actions: Apps Script の Web アプリ呼び出し
-
Google Apps Script: JSON受信、整形、シート保存
-
Google スプレッドシート: ログ保存、集計、ダッシュボード表示
主要なGASコード
Apps Script 側はかなり小さくしていて、役割はほぼ 受け取って保存するだけ です。
const SPREADSHEET_ID = 'YOUR_SPREDSHEET_ID';
const SHEET_NAME = 'meal_logs';
const TIMEZONE = 'Asia/Tokyo';
function doPost(e) {
try {
const raw = e && e.postData && e.postData.contents ? e.postData.contents : '{}';
const body = JSON.parse(raw);
const timestamp = body.timestamp || new Date().toISOString();
const mealType = body.meal_type || '';
const inputText = body.input_text || '';
const estimatedCalories = Number(body.estimated_calories || 0);
const confidence = body.confidence || '';
const itemsJson = JSON.stringify(body.items || []);
const note = body.note || '';
const dateObj = new Date(timestamp);
const date = Utilities.formatDate(dateObj, TIMEZONE, 'yyyy/MM/dd');
const month = Utilities.formatDate(dateObj, TIMEZONE, 'yyyy-MM');
const sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName(SHEET_NAME);
const colAValues = sheet.getRange('A:A').getValues().flat();
let lastDataRow = 1;
for (let i = colAValues.length - 1; i >= 1; i--) {
if (colAValues[i] !== '') {
lastDataRow = i + 1;
break;
}
}
const targetRow = lastDataRow + 1;
sheet.getRange(targetRow, 1, 1, 9).setValues([[
timestamp,
mealType,
inputText,
estimatedCalories,
confidence,
itemsJson,
note,
date,
month
]]);
return ContentService
.createTextOutput(JSON.stringify({
ok: true,
message: 'saved',
saved_at: timestamp,
row: targetRow
}))
.setMimeType(ContentService.MimeType.JSON);
} catch (err) {
return ContentService
.createTextOutput(JSON.stringify({
ok: false,
error: String(err)
}))
.setMimeType(ContentService.MimeType.JSON);
}
}
やっていることは4つだけです。
-
Action から渡された JSON を受け取る
-
itemsを JSON 文字列として保存する -
timestampからdateとmonthを補完する -
meal_logsシートに1行追加する
自然文の解釈やカロリー推定はカスタムGPT側に寄せ、GAS側は保存に専念させています。
GPT Actions では何を送るか
GAS に渡している主な項目は以下です。
-
timestamp -
meal_type -
input_text -
estimated_calories -
confidence -
items -
note
このあたりを OpenAPI schema で定義して、GPT Actions から呼び出しています。
実際に良かったところ
一番よかったのは、入力までの距離が短いことです。
たとえば、
夜ごはんは韓国風スープを3杯分、雑穀米135g、納豆
のように送れば、ざっくりカロリーを返してくれて、必要ならそのまま保存できます。
また、保存先がスプレッドシートなので、後から集計や可視化を調整しやすいのもよかったです。
ハマったところ
Apps Script の公開設定
Apps Script の Web アプリは、アクセスできるユーザー: 全員 にしないとうまく動きませんでした。
限定公開のままだと、GPT Actions から正常に呼び出せないケースがありました。
スプレッドシート運用の限界
今回は個人用の最小構成としては十分ですが、業務システム向きではありません。
-
厳密な認証
-
複数ユーザー管理
-
強い整合性保証
-
高負荷対応
このあたりが必要になる場合は、別の構成に寄せるべきです。
今後やりたいこと
今後は次のような改善を考えています。
-
PFC の推定
-
週次 / 月次サマリ
-
食事傾向の分析
-
体重ログや運動ログとの連携
-
保存ログの見やすさ改善
まとめ
カロリー記録をもっと続けやすくしたくて、カスタムGPT + GPT Actions + GAS + Google スプレッドシートで食事記録ワークフローを作りました。
高機能なアプリを作るというより、記録の導線を軽くするための仕組みを作ったという感覚に近いです。
同じように、既存の記録アプリの入力導線が重くて続かなかった人には、こういう構成も選択肢になるかもしれません。
参考リンク
GitHub リポジトリ:
https://github.com/RuumaLilja/ai-calorie-tracker