老闆說想要把產品從「老闆操作 → 系統反應」進化成「AI 主動建議 → 老闆審核」。 這份提案不會直接寫 code,而是先盤點 codebase + 資料 + 風險, 讓老闆看完知道值不值得往 Phase 2 走。
我整理過去 2 週的 dogfood 紀錄,發現我們的系統會做事,但不會主動想事:
• 訂位網頁壞了 → 老闆要打開報告才知道
• 收銀機零用金低了 → 一直到關帳才被發現
• 客人 no-show 一直發生 → 沒人追蹤趨勢
• 海邊小巫每週四 lunch 客流總是冷 → 沒人提醒
• 庫存某項目快用完 → 廚師臨時才發現
這些不是「沒做 feature」,是沒有一個會主動觀察、會記住、會提醒的角色。 傳統 POS 系統的天花板就是這。
如果我們花時間把架構打好,這個角色(我)就可以變成餐廳的「數位副店長」, 老闆睡覺時我幫看數據、發 anomaly 警示、產出明天的建議。
但這件事不能急。先 Phase 1 盤點,看看現在的 codebase 多接近這個目標。
— Claude (AI 員工),2026-05-16 提案
今天 ChefsMate 的資料流長這樣(粗略畫,省略很多細節):
我們有很完整的「事情發生 → 寫進 DB」的能力, 但沒有「事情發生 → 觸發 AI 思考」的能力。 這是兩種完全不同的架構哲學。
CLAUDE.md 規定所有商業邏輯都要走 Route → Orchestrator → Gate + Primitive + Repository。 這個架構對 AI 化非常有利,因為 AI 可以呼叫 Orchestrator 像呼叫 API 一樣, 不需要重寫 UI。但 80% 的 codebase 還沒搬完(PO 重構才到 Step 1.4-B)。
Realtime channel 訂閱 36+ 表 → 任何 INSERT/UPDATE 都會推送。 這就是 event 的雛形!但我們把它當推播用,沒存進 event_log 表, 所以 AI 看不到「過去發生了什麼」。
客人面:只有訂位 / 取消 / 修改記錄。
POS 面:訂位 + 訂單 + 結帳 + 桌位移動 + 廚房狀態 + 員工出勤 + 損益。
→ AI 的「世界模型」建立應該從 POS 端開始,客人端是輔助。
例如:TablePredictionService(預測哪桌坐哪組客人)、
cloudSmartService(呼叫 Edge Function 算開放時段)、
autoExpireOverdueReservations(cron 自動 no-show)。
這些都是「規則式 AI」,只差一個共同的「AI brain」入口。
整個 codebase grep 過了:0 個 OpenAI / Anthropic SDK 引用、0 個 pgvector / Pinecone 整合。
完全乾淨的 greenfield。
好處:沒有歷史包袱。壞處:每個模組都要自己接。
我把 POS 主要模組依「AI 化價值 / 困難度」分數列出來:
| 模組 | AI 化價值 | 實作難度 | 推薦動工順序 | 具體 use case |
|---|---|---|---|---|
| 訂位 / 候位 | ⭐⭐⭐⭐⭐ | 中 | 1 | 「明天 7 點客流預測 / no-show 風險 / 桌位安排建議」 |
| 菜單 / 銷售分析 | ⭐⭐⭐⭐⭐ | 中 | 2 | 「下週要打哪個菜的折扣?哪個菜該下架?」 |
| 記帳 / 報表 | ⭐⭐⭐⭐ | 易 | 3 | 「這週成本超支 8%,主因是哪幾個品項?」 |
| 客人關係(CRM) | ⭐⭐⭐⭐ | 中 | 4 | 「VIP 妮妮 30 天沒來,要不要寄優惠券?」 |
| 採購 / 庫存 | ⭐⭐⭐ | 難 | 5 | 「下週叫貨建議單」 |
| 員工排班 | ⭐⭐⭐ | 難 | 6 | 「下週四 lunch 客流預估 → 應該排幾個外場?」 |
| 結帳 / 廚房 KDS | ⭐⭐ | 易 | 不急 | 低決策含量,不需要 AI |
| 外場座位佈局 | ⭐⭐ | 難 | 不急 | 一次性設定,不需要 AI 持續介入 |
先做訂位 + 銷售分析 + 記帳。這 3 個模組共同特性:
(1)資料已經結構化在 supabase
(2)有時序性(適合 trend / anomaly 分析)
(3)老闆每天都要花時間看,最直接省力
要做 AI,需要 AI 「看得到的歷史」。我盤點下來缺這些:
| 缺什麼 | 為什麼需要 | 多難補 |
|---|---|---|
| event_log 表 | 記錄所有操作的時序,AI 看歷史用 | 易(一張表 + 一個觸發器) |
| 天氣資料 | 客流預測強相關(下雨人少) | 易(接 OpenWeather API) |
| 國定假日 / 行事曆 | 連假前後客流模式不同 | 易(一張靜態表) |
| 附近活動 / 演唱會 | 大型活動會湧入或抽光客流 | 中(要爬蟲 + 人工 curation) |
| 外送平台訂單 | UberEats / Foodpanda 訂單也算營收 | 中(要整合 API 或人工輸入) |
| AI 對話記憶 | 讓 AI 記得老闆的偏好 / 過去討論 | 中(pgvector + summarization pipeline) |
| 明確的「重要程度」標記 | 讓 AI 知道哪些事件值得提醒 (event importance scoring) | 中(需要設計 scoring rules) |
「event 化」= 把這件事的發生時間 + 內容 + 因果關係寫成一筆 row, 以後可以查、可以彙總、AI 可以摘要。今天我們很多地方只改了 state 沒留 event, AI 看到「訂位現在是 cancelled」但不知道什麼時候、為什麼、誰按的。
需要 event 化的重點操作(依優先序):
這是我想像中老闆 Phase 2 之後會用到的 UI(傳統 dashboard → 對話式):
每個 AI 講的話都來自3 件事:
(1) 從 event_log 拉最近資料 → (2) 加上 context(天氣 / 假日) → (3) 餵 LLM 出建議卡片
UI 是 SwiftUI Chat + 動態渲染卡片。卡片按鈕直接呼叫既有 orchestrator(補錢 / 寄信 etc)。
產出本文件 + 老闆綠燈 / 紅燈決策。不寫 code。
• 建 event_log 表 + 觸發器(POS 內所有寫操作自動 log)
• 接天氣 / 假日 API(cron 每天拉)
• 整合 Claude API(Edge Function 包一層)
• 第一個 use case:「每日異常摘要」(cron 跑,結果存 daily_ai_summary 表,POS 開機顯示)
• POS 加「🤖 AI 副店長」tab(chat UI)
• AI 能查資料 + 起草 action(不能直接執行,要老闆按確認)
• 第一批主動建議:低庫存 / 高 no-show 訂位 / VIP 久未來 / 零用金低
• 老闆把信任的 action 設為「不用問我」(白名單)
• AI 在白名單範圍內可自己執行(例:低庫存自動下叫貨單草稿、no-show 客人自動扣信用分)
• 所有自動行為都進 event_log,老闆可隨時 audit
→ 月成本 ~ $100-180 USD(單一餐廳)。 若多店,token 成本線性成長但 infra 固定。
例如 AI 建議寄折扣券給某 VIP,但其實該 VIP 已經是黑名單。 對策:所有 AI 建議都要老闆按 confirm, Phase 4 自動執行白名單也要設「最大金額 / 最大頻率」上限。
若沒節制,AI 對話 / 摘要可能燒掉每月 $500+。 對策:(1) prompt caching;(2) 短期記憶用 small model(Haiku),長期 reasoning 用 Sonnet;(3) 設定每日 budget alarm。
AI 不能直接 SQL,必須走 orchestrator。 對策:建一個「AI tool library」當 orchestrator 的 wrapper,AI 只能呼叫白名單 tool。
例:員工不小心觸發「AI 建議補貨」,下了大單但其實不需要。 對策:白名單只給老闆角色,員工角色只能看不能執行。
整個 stack 黏住兩家公司。 對策:tool library 抽象 LLM 介面,未來換 OpenAI / Gemini 不用重寫業務 code。
• ❌ 不要一開始就建 multi-agent system(複雜度爆炸)
• ❌ 不要試圖讓 AI 替代老闆做最終決策
• ❌ 不要直接接 voice assistant(先做好文字版)
• ❌ 不要做 generative menu design(沒有市場驗證)
(點完按鈕請告訴 AI 你選了哪個,AI 會依此安排排程。
也可以在 老闆報告 → 許願池 補充想法。)
以下為 Phase 2 落地時的具體技術設計,給後續實作參考。本 section 預設讀者熟悉 supabase / Next.js / Swift。
CREATE TABLE event_log (
id BIGSERIAL PRIMARY KEY,
ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
restaurant_id UUID NOT NULL REFERENCES restaurants(id),
event_type TEXT NOT NULL, -- e.g. "reservation.cancelled"
entity_table TEXT NOT NULL, -- "reservations"
entity_id UUID NOT NULL,
actor_user_profile_id UUID, -- nullable for system events
actor_role TEXT, -- "owner" / "staff" / "customer" / "system"
payload JSONB NOT NULL, -- { from, to, reason, ... }
importance SMALLINT DEFAULT 5, -- 0-10, AI scoring use
correlation_id UUID, -- 串連 multi-step 操作
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_event_log_restaurant_ts ON event_log(restaurant_id, ts DESC);
CREATE INDEX idx_event_log_entity ON event_log(entity_table, entity_id);
CREATE INDEX idx_event_log_type_ts ON event_log(event_type, ts DESC);
CREATE INDEX idx_event_log_high_importance ON event_log(restaurant_id, ts DESC) WHERE importance >= 7;
Orchestrator 完成時手動 emit event(已有 eventBus 雛形)eventBus.publish() → subscriber 寫 event_log(async, non-blocking)supabase/functions/ai-brain/
├── index.ts # 入口:接 /ai/chat 或 /ai/summarize
├── tools/ # tool library (AI 能呼叫的 orchestrator wrappers)
│ ├── query.ts # SELECT-only queries
│ ├── action.ts # POST orchestrator(要求 confirm token)
│ └── registry.ts # tool 白名單 + role gating
├── context/ # 餵給 LLM 的 context builder
│ ├── recent_events.ts
│ ├── weather.ts
│ ├── holidays.ts
│ └── memory.ts # short-term + long-term memory retrieval
└── llm/ # Anthropic SDK wrapper + prompt cache
├── client.ts
└── prompts.ts
| 層級 | 儲存 | 取出策略 | 例子 |
|---|---|---|---|
| Short-term | 當前對話 context window | 直接帶 | 「剛才老闆問的客流」 |
| Working | event_log 最近 7 天 | SQL filter by ts + importance | 「上週 no-show 統計」 |
| Long-term | ai_memory_summaries 表 (pgvector) | semantic search by embedding | 「老闆討厭外帶單」 |
| Structured | 既有 supabase 表 | tool call | 「妮妮的消費紀錄」 |
// 每日 03:00 跑(避開營業時段)
POST /api/ai/cron/daily-summary
├── 拉昨日 event_log(filter importance >= 5)
├── 拉昨日 orders 統計
├── 拉天氣 + 假日
├── 餵 Claude Sonnet → JSON output: { highlights[], anomalies[], suggestions[] }
├── INSERT INTO daily_ai_summary (date, content_json)
└── 老闆 POS 開機時 GET /api/ai/summary/today 顯示卡片
voyage-3-lite ($0.02/M tokens)// tool registry 範例
const TOOLS = {
query_reservations: { role: ['owner','staff'], readonly: true },
query_orders: { role: ['owner','staff'], readonly: true },
send_email: { role: ['owner'], readonly: false, max_per_day: 50, requires_confirm: true },
create_purchase_order: { role: ['owner'], readonly: false, max_amount: 5000, requires_confirm: true },
// ❌ never expose direct SQL / DDL
}
讓老闆能驗收 Phase 2 的東西:
Phase 2 通過 = 老闆說「我每天確實會看 AI 摘要」→ Phase 3 啟動。
// 必要的 metric - ai_call_count_per_day - ai_call_token_in / token_out (per restaurant) - ai_call_latency_p95 - ai_tool_invocation_count by name - ai_action_confirm_rate (老闆按 confirm vs reject 比例 → 訊號 AI 對不對) - daily_summary_generation_success_rate