家族共享行程提醒 LINE bot:邀請碼加入 + 一句話建行程 + 自動提醒
生活自動化
家裡每個人的行程各記各的 — 誰幾點回診、小孩幾點補習、誰要去機場接人。用嘴講會忘、丟家族群組刷一下就洗掉 真的到那天才發現「啊我忘了」。我不想要又一個沒人會開的行事曆 app — 是直接在大家本來就在用的 LINE 裡:一句話建行程 到點 bot 自動跳出來提醒相關的人。
先講重點
家人在 LINE 一句話「明天 3 點 媽媽 醫院回診 提前 1 小時」,bot 自動 parse、存資料庫、到點 push 提醒相關人。架構是 FastAPI + Supabase + Render + cron-job.org 三件套全免費。刻意不接 LLM (regex parser),省 API 費也避開家人輸入隱私上傳。已上線給家人用 2 個月。
卡點:家人的行程各記各的 到點才發現忘了
每個人的行程散在各自腦袋裡 — 回診、補習、接送、繳費。口頭講會忘 丟群組會被洗掉 共用 Google 日曆又沒人真的會去開。家庭工具的死亡點就是「要另外開一個 app」。所以這個 bot 的前提是:不另開介面 就活在 LINE 裡 — 大家本來就整天掛在上面。
關鍵決策:這種 bot 刻意不接 LLM
很多人一聽「LINE bot」就想接 GPT 讓它聊天。我故意不接。一個家族行程 bot 要做的事很固定:建行程、查行程、刪行程、提醒。這種有限指令集 用 keyword 比對 + 一句話規則解析就 100% 搞定 — 不接 LLM 的好處是:零 API 成本、回應即時、而且行為可預測(LLM 偶爾自由發揮 家裡長輩會被搞糊塗)。AI 是好工具 但不是每個 bot 都該塞 —— 判斷「哪裡不用 AI」跟「哪裡用 AI」一樣重要。下面是它怎麼不靠 LLM 也聽得懂:
# 不用 LLM 也能讓 bot「聽懂」:keyword → 狀態機 → 一句話解析 → fallback
async def route_message(session, user, text):
t = text.strip()
if t in CANCEL_KEYWORDS: return [msg.text("已取消")]
if t in HELP_KEYWORDS: return [msg.text(help_message())]
if user.family_id is None: # 還沒加入家族
return await onboarding.handle(session, user, t) # → 走邀請碼流程
if t in LIST_KEYWORDS: return await list_events.handle(session, user)
if t in NEW_KEYWORDS: return await create_event.start_guided(session, user)
state = await repo.get_state(session, user.line_user_id)
if state.state in EVENT_CREATION_STATES: # 多步驟新增中
return await create_event.step(session, user, t) # → 繼續對話狀態機
one_liner = await create_event.try_one_liner(session, user, t) # 試一句話解析
if one_liner is not None:
return one_liner
return [msg.text(help_fallback())] # 都不中 → 給指令清單
建行程兩種方式:一句話 或 引導式問答
懶人版(我自己用):直接打「明天下午3點 媽媽 醫院回診 提前1小時提醒」 bot 用規則解析出時間 / 對象 / 事由 / 提前量 直接建好。新手版(長輩用):打「新增行程」 bot 進入引導式狀態機 一步一步問(標題 → 開始時間 → 結束 → 參加的人 → 提前多久提醒 → 確認)。狀態機的進度存在 conversation_states 表 中途隨時打「取消」跳出。兩種輸入對應兩種人 — 同一個 bot 不強迫所有人用同一種方式。
提醒的雷:cron 每分鐘跑 怎麼不重複發
提醒是一個 cron job 每分鐘呼叫一次 /api/cron/dispatch(帶 secret header 防外部亂打)。它撈出 notify_time 已過、而且 notified 還是 false 的行程 push 給所有參加的人 然後立刻把 notified 標成 true — 這個 flag 是避免「下一分鐘又撈到同一筆 重複發」的關鍵。還有個細節:就算 push 給其中一個人失敗 我也不重試整筆(會害已經收到的人收第二次)只記 log。寧可漏記一個 也不要全家被疲勞轟炸。
本機 SQLite、線上 Postgres,同一套 code
開發時我不想為了測一個小功能就連雲端資料庫。所以資料層用 SQLAlchemy + 兩個自訂 TypeDecorator(UUID 跟 JSONB)讓同一份 model code 在本機跑 SQLite、上線跑 Supabase Postgres 不用改一行。本機 sqlite 隨開隨測 線上 asyncpg 接 Supabase schema 用 Alembic 管 migration。這樣「本機測完直接上線」不會踩到資料庫差異的雷。
整段複製給 AI agent,你就有這個 workflow
把下面整段複製貼給你的 AI agent,它就能照著幫你把這個「家族共享行程提醒 LINE bot」從零建起來 — 邀請碼加入家族、一句話建行程、到點自動提醒,你不用自己摸。
我要你幫我做一個「家族共享行程提醒 LINE bot」,活在家人本來就在用的 LINE 裡,不另外開 app。技術棧請用 Python FastAPI 接 LINE Messaging API 收訊息與 push,資料庫用 Supabase Postgres,但開發階段我要能在本機跑 SQLite、上線跑 Postgres 用同一套程式碼,所以資料層請用 SQLAlchemy 加自訂 TypeDecorator 把 UUID 與 JSONB 在兩邊抹平,migration 用 Alembic 管。
功能我要這些:第一,邀請碼加入家族 — 第一個人建家族當 admin,其他家人輸入邀請碼加入當 member。第二,建行程要兩種方式並存:懶人版用一句話(像是「明天下午三點 媽媽 醫院回診 提前一小時提醒」),請用規則解析出時間、對象、事由、提前量,不要接任何 LLM;新手版用引導式問答,做一個對話狀態機一步步問標題、開始時間、結束、參加的人、提前多久,過程中的草稿存進 conversation_states 表的 JSONB 欄位,中途打「取消」可隨時跳出。第三,提醒用一個 cron job 每分鐘呼叫一次派送端點,撈出提醒時間已過且尚未通知的行程,push 給所有參加的人。
請務必避開這些我已知的雷:cron 派送端點一定要驗 secret header,防外部亂打;每筆行程要有一個 notified 旗標,push 完立刻標成已通知,不然下一分鐘會重複撈到同一筆狂發;就算 push 給其中一個人失敗也不要重試整筆,只記 log,否則已經收到的家人會被重複轟炸;訊息路由請走 keyword 比對加狀態機加一句話解析加 fallback 的順序,刻意不接 LLM,因為指令集很固定、要回應即時又行為可預測,長輩才不會被搞糊塗。
開工前請先確認我的環境:我有沒有 LINE 官方帳號與 channel token、Supabase 專案、Python 版本、本機要不要先用 SQLite 跑通。然後一步一步建,每完成一步就停下來跟我確認再繼續,不要一次全寫完。
把上面整段複製貼給 agent 就好,它會先問你 LINE token、Supabase 這些環境細節再動工,你只要回答、卡住時補充環境資訊就行。
完整 SOP 清單
上面把「為什麼刻意不接 LLM」「一句話 vs 引導式建行程」「cron 提醒怎麼不重複發」「本機線上同一套 code」都寫出來了。下面是完整元件對照:
- FastAPI webhook + LINE Messaging API 收訊息 / push 完整接法
- 不接 LLM 的訊息路由(keyword → 對話狀態機 → 一句話解析 → fallback)
- 一句話建行程的規則解析(時間 / 對象 / 事由 / 提前量)
- 引導式新增的對話狀態機(draft 存 JSONB + 中途取消)
- 邀請碼 onboarding(建家族 + 家人用 code 加入 + admin / member 角色)
- cron 提醒去重(notify_time + notified flag + partial failure 不重試)
- cross-db 資料層(同 code 跑本機 SQLite / 線上 Supabase Postgres)+ Alembic migration
看完這篇之前先確認:
- 家人 LINE 群已經很活躍想加智能助手
- 想用永久免費三件套 (FastAPI + Supabase + Render) 學端到端架構
- 想學「自然語言 parser 該不該全交給 AI」的決策思路
- 想做商用 LINE OA (要走 verified 路線跟付費方案)
- 家人 LINE 不熟悉就要硬推 bot 加入
- 已經有付費月費方案的人 (這個架構是給「不付月費也要能跑」的)
- LINE 後台 Auto-reply 沒關 — 內建自動回覆會蓋掉 bot 真正的回應
- Render 2025 砍了 free tier cron — 必須改用 cron-job.org 外部觸發
- 自然語言 parser 全交給 AI 結果月燒 $30 API 費 — 改成 regex 抓常見句型,LLM 只做 fallback
▸ 常見問題
這個 bot 用 LLM 嗎?為什麼說「刻意不接」?
主流程不接 LLM。家人句子格式很固定 (「明天 3 點 媽媽 醫院」),regex 抓「日期 + 時間 + 人 + 事」就夠,跑 100 次成功率 95%+。LLM 只當 fallback (regex 抓不到才丟給 Claude Haiku)。理由:省 API 費加上避開家人隱私上傳第三方。
Supabase / Render 免費額度夠嗎?
夠。Supabase free tier 500MB DB 加上 50K monthly active users,家族 5-10 人遠低於上限。Render free tier 750 hr/month 加上自動 sleep 後 cold start 30 秒,有 cron-job.org 每 14 分鐘 ping 一次保持活著。
一定要用 LINE 嗎?Telegram / Discord 不行?
可以換。FastAPI handler 那段抽掉,換 Telegram Bot API / Discord webhook 即可,parser 加上資料庫加上 cron 三段通用。台灣家人最常用 LINE 所以我做 LINE,換平台約 30 分鐘工程。
家人不會用 LINE bot 怎麼辦?
我家用法是「不解釋,直接示範」 — 我自己在群組打「明天 3 點 媽媽 醫院回診」bot 跳出提醒,家人看 1 次就會用。bot 不要寫指令說明書,要寫個範例觸發後跳第一個成功案例。
名詞解釋
- 機器人(bot)
- 自動執行特定任務的程式,例如 LINE bot 自動回訊息、發文 bot 每天定時發貼文。
- 大型語言模型(LLM, Large Language Model)
- ChatGPT、Claude 這類 AI 背後的技術:讀過海量文字後,學會理解與生成人類語言的模型。
- 排程(cron)
- 讓程式「每天 8 點」「每小時」自動執行的定時器。自動發文、定期抓資料都靠它。
- API(應用程式介面)
- 程式跟程式之間溝通的窗口。例如你的程式透過 LINE 的 API 自動發訊息、透過 Google 的 API 讀試算表。
- Supabase
- 免費起步的雲端資料庫服務,提供資料庫+登入驗證+API,個人專案很夠用。
- LINE Bot
- 在 LINE 裡自動回覆、主動推播訊息的機器人。台灣家庭幾乎人人用 LINE,是自動化通知的最佳入口。
- Render
- 雲端程式代管服務,免費方案能跑小型後端程式(例如 LINE bot)。免費版 15 分鐘沒流量會休眠,喚醒要 15-50 秒。
- Webhook
- 「事件發生時,A 服務自動通知 B 服務」的機制。例如有人傳訊息給你的 LINE bot,LINE 就透過 webhook 把訊息轉給你的程式處理。
- 資料庫(database)
- 專門儲存、查詢大量資料的系統。網站的會員、留言、紀錄都放這裡。