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

大聲的備份與多疑的探針:巡檢系統收官

為什麼備份是唯一被禁止沉默的 loop、為什麼每日回歸探針用確定性斷言而不用 LLM 裁判——以及「趁健康時建立基準線」的完整論證。

2026-07-29 line-bot 系列 · 8(完結)
1
道絕不准沉默的 loop
4
個每日探針,零 LLM 裁判
2×8
份備份,兩顆磁碟

背景

LINE 家庭助手系列完結篇。第七篇講了看守現在的三道 loop:存活、衰退、交付。剩下兩個問題,從兩側把「現在」夾住:最壞的事發生時,救得回來嗎?——以及——它還真的聰明嗎,還是只是真的在跑?

L5:不准小聲說話的備份

bot 的 SQLite 一開始只是訊息快取。到備份機制動工時,它已經裝著每一段群組對話、每一則排程中的提醒、還有全家人特地教給 bot 的長期記憶。價值會複利的資料,損失也會複利。

每週備份的機械部分刻意無聊——有意思的是包在那份拷貝周圍的四條紀律:

  • 走 SQLite 的線上備份 API,不是複製檔案。 WAL 進行中的活資料庫不能安全地 cp。一個插曲:容器 image 沒裝 sqlite3 CLI,所以 job 在容器內跑 Python 的 sqlite3.Connection.backup()——同樣的線上安全語意,還少一個 image 依賴。
  • 先備份, VACUUM。 會重寫整個檔案的維護步驟,排在拷貝存在之後。VACUUM 若有天弄壞什麼,最新的備份早於它——順序就是保險。
  • 驗證拷貝,不驗證意圖。 每份備份都要過 PRAGMA integrity_check 才算數。沒驗證過的備份是一個有檔名的願望。
  • 兩顆磁碟,因為威脅模型這麼說。 容器的資料目錄跟原本就在同一顆外接硬碟上——備份放那裡,扛得住資料損壞和手滑誤刪,卻扛不住這個功能真正的動機:硬碟整顆壞掉。所以每份備份再拷一份到內接磁碟。資料庫才一百多 KB;第二份拷貝是對著這功能存在的那個劇本、免費的保險。

然後是對第七篇所有說教的一次反轉:這是唯一一道永不自我閘門的 loop。每次執行都印一行結果——✅ 帶大小和完整性狀態,或 🔴——每週準時投遞、健康與否都投。備份的靜默失敗是基礎設施的經典災難:綠燈亮好幾個月,然後那次還原揭曉備份三月就停了。以週為頻率,一行心跳零成本,換到的保證是訊息缺席本身就是警報。告警紀律不是「永遠安靜」,是「每道 loop 各自決定沉默的意思,並且確保它不會有兩種意思」。

L6:全部綠燈,答案是錯的

存活檢查、錯誤掃描、交付稽核、驗證過的備份都到位之後,剩下的失敗模式長這樣:bot 每個問題都答、不拋任何錯誤、每則提醒都送達——然後跟某人報天氣時根本沒呼叫天氣工具,用編的、看起來很像的數字。品質退化不寫 log。

造成它的很少是你自己的部署,而是別人替你改的東西:報價 API 改了回應格式、供應商的端點行為飄移、某道清洗防線悄悄不再匹配。這隻 bot 上線第一個月的兩次事故,都是上游的變動,不是本地的。

原始計畫把這道 loop 排到最後,「等換模型變頻繁再做」。這個推理在寫下第一行程式碼之前就被推翻了,理由有二。其一,基準線只有在系統確定健康時建立才可信——等到懷疑壞了才做,你已經沒有「正常長什麼樣」的參照。其二,既然觸發源是別人的變動,等你自己下次換模型,守的是錯的那扇門。探針在一切健康時上線——那也是它唯一能上線的時機。

確定性斷言,不是 LLM 裁判

每天,探針把四個固定問題送進 bot 真正的 LLM 管線——容器內、真工具、真模型,但絕不經過 LINE、絕不碰對話資料:

探針斷言
「台積電現在股價多少?」呼叫了 get_quote 答案含數字
「明天花蓮天氣如何?」呼叫了 get_weather
「100 美金換台幣多少?」呼叫了 get_fx 含數字
一句純聊天完全沒有呼叫工具

外加每個探針都驗:答案非空、無 <think>/工具標記殘留——這讓探針免費兼任整條清洗管線的每日回歸測試。

設計上頂回了兩個誘人的預設。給 LLM 輸出打分的直覺人選是另一個 LLM——但裁判模型會因為跟受測系統一模一樣的上游原因而飄移,而會飄移的基準線不是基準線。這裡斷言的一切都是機械可查的:呼叫了哪些工具靠在分派函式外包一層記錄用的 spy 捕捉(不是撈 log),答案含數字是一條 regex。第二個預設是對稱覆蓋——什麼都探。兩個刻意的排除:寫入型工具被硬擋(一個能設提醒的探針不是探針,是使用者),上網搜尋跳過(拿計量的月額度燒合成問題——每月三十次「免費」探測,只要其中一次要錢就不免費)。

LLM 的非確定性得到一項讓步:失敗的探針重試一次才算數,單一次的抖動不呼叫任何人。持續的失敗才會——跟哨兵一樣自我閘門,綠燈時沉默。

系列總結

八篇文章,一個系統:住在 LINE 群組裡的家庭助手、在 LINE 上蓋東西要繳的平台稅、reasoning 模型與滿是親戚的聊天室之間的三層清洗、讓功能維持一檔之價的工具註冊表、記憶與提醒背後的讀取模型分岔、不用假日表就能盯價的兩道閘門、以及看守這一切的巡檢系統——在這篇收官。

這裡面沒有任何新穎的基礎設施。它就是我在工作上對資料平台用的那套紀律——對帳檢查、新鮮度閘門、基準線、爆炸半徑思維——瞄準八十幾 KB 的 SQLite 和一個聊天群組。規模是玩具;失敗模式不是。這整場實驗要驗的就是一件事:「小到可以很個人」和「工程化到可以被信任」能不能是同一個系統。家人持續在用它——那是唯一真正算數的指標。

收穫

關於大聲的備份

自我閘門適合「常常執行、很少要緊」的檢查。備份相反——罕見而攸關存亡——所以每次執行都回報,回報缺席即是警報。每道 loop 各自決定沉默的語意;永遠別讓它模稜兩可。

關於基準線與時機

第一次事故之後才建的回歸基準線,是一張災後現場的照片。「確定健康」只有在它為真的時候才拍得下來——所以品質探針最便宜的建造時機,恰好是它感覺最沒必要的時候。

關於不會飄移的裁判

用另一個 LLM 給 LLM 行為打分,等於把你要偵測的飄移原封進口。工具呼叫 spy 和數字 regex 謙遜得多,而且永遠不改變心意——對每日基準線來說,無聊贏過聰明。