曹德偉
Production 2 個月運作 架構

Brain — 跑了 2 個月的私人知識系統。

每天都在用,每天都在改——很多功能是壞了一次才補上去的。

2 個月運作
24/7全天候運作
天天在用
4+1OSS 產出
TL;DR
  • 入口:Telegram Bot / REST API / MCP server。
  • 核心:SQLite + FTS5 + 向量混合搜尋 + 熱度衰減記憶層。
  • 部署:CF Workers + EC2 + GitHub Actions,全部上線運作。
  • 產出:從 Brain 抽出 4 個 production muscle(forget-rag、smart-restart、mcp-fts5-starter、mcp-fts5-starter-gemini),另有 1 個 Claude Code 生態延伸(claude-ui-designer)。

01 系統架構

Brain 跑了 2 個月。沒掛過。其實不是因為我寫得多好——很多東西是壞了一次才補上去的(譬如有一次 frontmatter 整批被多包了一層引號,41 篇壞掉,累積一個多月才發現)。

我現在就只盯三件事:多入口(手機、桌機、Claude Code session 都進得來)、單一真相(vault + SQLite 是唯一真相,其他都是衍生視圖)、以及不會壞(cron + GitHub Actions 是骨幹,real-time push 是奢侈品)。聽起來很像廢話,但天天在跑的東西能不變廢話,已經是很奢侈的事。

三層架構 — Entry / Core / Storage + 橫切監控
[入口層] [核心層] [儲存層] Telegram Bot 主入口 REST API PWA / 排程 MCP Server Claude Code 知識處理器(Python) 資料攝取.解析.關聯.混合搜尋.每日摘要 Vault(Obsidian 內的 .md 檔案) + SQLite(FTS5 + 向量索引) + forget-rag 三層梯度 [監控管線] 採集 儲存 偵測 判斷 告警 → 完整故事看 MCP Monitoring Retrospective

三個入口都直連核心層,不經過彼此。這是刻意排的——任何一個入口掛了,其他兩個還能用。

系統掛了我就得開電腦修——而我懶得每天為這件事開電腦。所以才有三個入口、所以才有 cron 排程、所以才有後面那些設計。多數設計其實都是這樣,從「我不想每天遇到這個」回推出來的。

02 6 個關鍵設計選擇

下面 6 個選擇,每一個都是取捨,每一個都在過去 2 個月裡被我自己用爛過——有些用爛了才知道當初選對,有些用爛了才知道當初選錯(後者比較多)。

Choice 01

底層為什麼用 SQLite + FTS5

啟動成本低、樹莓派跑得動、不用 docker compose 起 4 個服務。FTS5 解掉 80% 的搜尋場景;剩下 20% 才接 Gemini embeddings 做混合。決策原則一句話:先從跑得動的最簡單方案開始。如果哪天 SQLite 撐不住——譬如資料突然漲十倍——那是個好問題。第 60 天我還沒遇到(其實是還早得很)。
放到團隊裡,這代表我會先問:現在真的需要重型架構,還是只是我們想用看起來比較厲害的東西?

Choice 02

為什麼讓舊筆記自然淡出

跑兩個月之後,RAG 開始撈出 2024 年的東西。是那種我自己都忘了寫過的舊草稿,半成品,方向已經改過三次的那種。它撈出來打斷我,我才想起來——對,這篇我那時候沒寫完。舊筆記不會自己變新,可是 RAG 不知道(也沒理由要知道)。所以做了 L1(熱)/ L2(溫)/ L3(歸檔)三層儲存——舊資料不刪掉,只是 RAG 預設只看 L1+L2,要搜到 L3 得明確指定。原則簡單到我跑了兩個月才意識到不做不行——這個模組後來抽出來變成 forget-rag
放到團隊裡,這代表我不會只追求「資料越多越好」,我會追問哪些資料會讓模型變吵、變舊、變不準。

Choice 03

主入口為什麼是 TG Bot

我在哪、Bot 在哪。手機上、辦公室、家裡——同一個對話視窗。Web UI 要設計 UX、處理 session、做認證;Bot 直接用 Telegram 的基礎建設,省 90% 的工。代價是一次只能服務我一個人(但 Brain 本來就是私人系統,這個代價對我來說等於零)。我每次想做 Web UI 的衝動,最後都被「也才我一個人用」說服回來。
放到團隊裡,這代表我會先選能驗證核心價值的入口,不會為了完整產品外觀先燒掉一輪 UI 成本。

Choice 04

Bot 接到訊息後,為什麼還要再過一層 hybrid router

5 個正交 intent——meeting / clipping / chat / memo / search——每一個要做的事完全不同:存逐字稿、抓網頁、撈舊筆記、寫備忘、跑 Claude session。如果每次都直接丟 LLM 分類,單次成本是浪費、延遲也沒必要。
所以 router 分兩階段。先用 regex 抓不會搞錯的 pattern(URL、會議記錄前綴),這層完全不付 LLM 錢就分流完;剩下模糊的才丟 Gemini Flash 判意圖,confidence < 0.5 還要 fallback 回 regex。會付 LLM 錢的最後只剩 chat / search——它們本來就要呼叫核心模型。
副作用是這個 router 變成 source-agnostic:TG Bot 跟 PWA REST API 共用同一份 routing 邏輯,靠 RouteContext dataclass 和 Runner Protocol 把 transport 細節剝乾淨。換 channel 不用重寫 router。
放到團隊裡,這代表我會先問兩件事:哪些訊息根本不該過 LLM?哪些抽象能讓你之後換 channel 不必重寫業務邏輯?

Choice 05

骨幹為什麼是 cron 排程

日報 / 週報 / 維護任務全是 cron。即時推送要處理 backpressure、retry、dead letter queue——三個東西每一個壞了都會 cascade;cron 只要「失敗重試」就好。出錯面積差一個數量級。代價是延遲,但個人知識系統不需要毫秒級回應,我寧可慢但穩。兩個月跑下來,cron 任務的恢復成本接近零;real-time push 一壞,就會搞掉我一個下午(之前在別的專案踩過,所以這次直接避開)。
放到團隊裡,這代表我會把可靠性放在炫技前面:如果產品不需要即時,就不要先把自己綁進即時系統的維護成本。

Choice 06

為什麼上線 MCP 監控但 14 天後砍計畫

Phase 0 上線後跑稽核,數字出來——監控只抓到 0.22% 的流量。剩下 99.78% 走 Bot / REST 直呼核心,根本不過 MCP 那一層。
當下我有兩個選擇:花一個月修監控架構;或承認假設錯,砍掉 Phase 1 的 BQML 計畫,把這 14 天寫成回顧文。我選後者——其實當下心情很差,但回頭看是好的決定。
我現在每一個新自動化專案都會留一個「第 14 天稽核」當硬性交付物。這個原則就是上次砍出來的。
放到團隊裡,這代表我不會用沉沒成本保護自己的方案;數字說假設錯了,我會改方向。

完整故事看 MCP 監控回顧

03 這個系統證明我能在 AI 新創做什麼

Portfolio 的工作只有一件事:把「我能做什麼」翻譯成「你可以驗證的主張」。其他都是裝飾。

Brain 跑了 2 個月,下面三條是它幫我證明的事——每一條都附證據(也都附我自己踩過的坑):

主張 01 設計上線級的 AI 基礎建設。 2 個月真的在跑,不是 demo。多入口、單一真相、cron 撐骨幹,從頭自己設計、自己上線、自己維護。
主張 02 在成本與複雜度之間取捨。 SQLite 又老又土,但這個選擇是對的。向量資料庫 / Kubernetes / 微服務都是「之後再說」的奢侈品;個人系統的合理預設是從最小開始
主張 03 上線後願意稽核自己。 MCP 監控的回顧文就是證據。14 天後跑覆蓋率稽核、發現自己假設錯、砍掉原本的計畫——整個過程心情很差,但我寧可砍掉重來,也不要假裝它有效。
如果你正在徵人 · If you're hiring

凌晨 3 點,你的 LLM 功能 health check 全綠。
但你睡不著——因為你不知道它有沒有在做正確的事。

Brain 跑了 2 個月——多入口、混合搜尋、熱度衰減、cron 撐骨幹,全自己設計、自己上線。沒掛過一次,但中途壞過好幾次(最嚴重那次累積了 41 篇 frontmatter 被多包一層引號的筆記,整整一個月沒發現)。它不躺在 GitHub 上等 star,每天都在我手上用。

「程式在跑」≠「系統有效」——這是 Brain 跑這 2 個月教我的事。
如果你需要有人會把 demo 推上線、然後每隔 14 天回頭問「這東西真的在做事嗎」——我們可以聊聊。

我的定位不是 ML researcher,而是 AI system delivery / solution architecture。
我擅長的是把模糊 AI 需求推到上線,然後用稽核、日誌、使用行為回頭檢查它到底有沒有做事。
寫了三天的方案,發現方向錯了,隔天早上重來——這件事我已經練得很熟。


zx2241384@gmail.com · 開放遠端 / 台北