EN 中文
← 回文章列表
Self-hosting · LLM

住在 LINE 群組裡的家庭 AI 助手

為什麼我為家人自架一個 LINE bot,而不是叫大家去裝聊天 App——架構、四個關鍵設計決策,以及界線畫在哪裡。

2026-07-08 line-bot 系列 · 1
14
個 function calling 工具
2
個容器(api + tunnel)
$0
每則訊息邊際成本

背景

在台灣,家庭的日常協調發生在 LINE 群組——不是 Telegram、不是 Discord,也不是任何你「選」的聊天軟體。LINE 是家人本來就在的地方,再多句「你裝一下這個 App」都改變不了這件事。

到 2026 年中,我的個人自動化已經整套收攏在自架的 agent runtime 上、推播走我自己的 Telegram:內容 pipeline、市場研究、憑證自動刷新、還有從 n8n 搬回本機的家庭行程提醒。那套東西運作得很好,但它是單人模式:家人用不到、也不該需要學,而且上面跑的一部分東西(投資組合分析、工作自動化)本來就不該給我以外的人看到。

所以缺的從來不是「我需要一個 LLM」,而是一個入口:全家人都能直接開口、就在他們本來就在用的群組裡、答案帶著真實資料。一個 LINE bot,自架在跟其他服務同一台機器上。

先畫界線,再寫程式

動手前我先拍板了一條分工原則,之後每個功能決策都被它框住:

寫下來很理所當然,實際上誘惑無所不在:個人那套已經有投資資料、bot 已經有 LLM——把兩邊接起來只差一個工具的距離。拒絕搭這座橋本身就是一個功能。家庭群組是廣播媒介:bot 說得出口的話,所有人都讀得到。

架構

家裡的 MacBook server 上兩個容器,部署方式跟機器上其他 stack 一致(compose 檔進版控 repo、密鑰走 gitignore 的 .env):

1
LINE Platform
有人在群組發話,LINE 把事件 POST 到 webhook URL。
2
Cloudflare Tunnel
不開 port 就有公開 HTTPS——家裡網路本來是 Tailscale 私網孤島。tunnel 容器純外連,沒有任何東西連進來。
3
FastAPI webhook
驗 X-Line-Signature、立刻回 200、事件丟背景處理。LINE 對慢的 webhook 會重送,而重送的 LLM 呼叫就是重複回覆。
4
SQLite + LLM
每則訊息都存下來當脈絡;只有被叫喚才觸發 LLM。Function calling(14 個工具)查真實資料,回覆走免費的 reply API。

LLM 走 OpenAI 相容端點,換供應商只是三個 .env 變數的事——這隻 bot 跑過 Gemini 免費層(太小:一天 20 次,晚餐前就死)、現在跑買斷制供應商。買斷制才是「群組再怎麼聊、邊際成本真的是零」的原因,而不是「便宜,直到它不便宜」。

撐起整套系統的四個設計決策

1. 每則都存、被叫才答。 群組所有訊息進 SQLite;LLM 只在 bot 被叫喚時觸發。這是「助手」跟「已讀騷擾」的分界——被問到時它帶著完整對話脈絡(「媽媽剛剛說週六怎麼決定?」),平常一句不插。

2. 關鍵字觸發,因為 @ 選單會騙人。 LINE 對官方帳號的 mention 選單在電腦版經常不出現(手機正常——不是付費限制,就是平台怪癖)。如果「能被 @」是唯一觸發方式,家裡一半的裝置會叫不動 bot。所以訊息開頭是觸發詞也算,前綴在丟給 LLM 前會被去掉。

3. 引用回覆是一等公民。 使用者用「回覆」功能時,LINE 會帶 quotedMessageId。bot 存每則訊息時連 LINE message id 一起存,所以「對一大段長文按回覆 + @bot 幫我整理」撈得到被引用的那一則當主要處理對象。少了這個,「整理這個」的意思會變成「整理隨便哪則最近的訊息」。

4. 接受歷史從入群那天開始。 LINE 沒有 API 能撈 bot 入群之前的訊息——脈絡從第一天開始累積,不是從三十天前。順著這個限制設計(而不是假裝沒有),下游的功能(聊天回顧、引用回覆)才能各自把界線講清楚,而不是神秘地失敗。

決策 2–4 背後的平台怪癖——加上 UTF-16 mention 偏移和一次性 replyToken——完整版在第二篇:LINE Messaging API 不會警告你的五個坑

它現在會做什麼

工具註冊表是這隻 bot 從「聊天機器人」變成「家庭公用設施」的地方。每個工具是一個小模組——一份 JSON schema 加一個 async run()——由 LLM 自己決定何時呼叫:

  • 查詢類——天氣(附要不要帶傘的結論)、匯率換算、股票/加密貨幣/指數報價、網址摘要、帶來源的上網搜尋
  • 時間位移類——提醒(一次性與循環,到點發真 @ 通知)、到價警報(「2328 跌破 50 叫我」——只在交易時段輪詢,加一道報價新鮮度閘門,假日的舊報價不會誤觸發)
  • 脈絡類——聊天回顧(「這週大家聊了什麼?」)、長期記憶(「記住我住花蓮」——之後每次回覆自動帶著)、看圖與短影片、貼圖情緒
  • 呈現類——結構化結果附 LINE Flex 卡片(報價紅綠漲跌、天氣降雨機率、提醒清單每筆一顆取消鈕),加上一鍵追問 chip,全部走免費 reply API

每一項背後都有自己的傷疤——reasoning 模型的輸出要洗三層才配進純文字頻道、到價警報用兩道閘門躲掉維護假日表、記憶的讀取模型刻意設計成跟提醒相反。這些各自是一篇文章(這是系列文,發布後連結會補回這裡)。

看住一隻沒辦法看住自己的 bot

Webhook bot 最糟的失敗模式是沉默:Docker 重啟、tunnel 掉線、LLM 供應商抽風——bot 就這樣安靜地停了,直到家人 @ 它沒回應才被發現。LINE 還會雪上加霜:連續失敗的 webhook 會被暫停推送,「壞掉」因此自我延長。

所以這隻 bot 外面包了六道獨立的巡檢 loop——從 Docker 外面打的存活探針、每日健康摘要、揪出「說好會提醒卻沒送」的交付稽核、每週驗證過完整性的備份、還有每天驗「答案品質」而不只是「有沒有答案」的回歸探針。這套系統花的設計功夫不比 bot 本體少,它是這個系列接下來幾篇的主角。

收穫

關於入口

模型可以替換,入口不行。一個住在家人本來就在聊天的地方的助手,會被「永遠不會去裝 AI App 的人」天天使用——我的家人每天問它天氣、設提醒,而沒有任何人需要學任何新東西。

關於先畫界線再做功能

「私密的留在私密那套」在動工前就決定,讓之後每個功能請求都有一句話就能回答的答案。反過來——每個功能在「可是很方便」的壓力下個案決定——那個棘輪只會往一個方向轉。

關於聊天場景要用買斷制 LLM

群組聊天是一種你控制不了的用量模式——你總不能對自己家人限流。免費層一個晚上就死;計量計價讓每一則訊息都變成成本決策。買斷制才讓「就放給大家用」成為一個理智的預設值。