Side Project · AI Product Builder 作品展示

WiPPY

用自然語言規劃活動訊息,AI 幫你寫好、排好、推出去。

AI 驅動的活動管理與訊息推播平台。透過 7 階段 Harness Pipeline, 讓每一次 LLM 呼叫都可觀測、可恢復,並透過 LINE Bot 自動推播給對的群組。

知識庫
Agent 對話
推播企畫
發送紀錄
知識庫
知識庫 · load_context
活動知識庫管理
儲存活動背景資料、選書哲學、氛圍調性。每次對話都會自動載入作為 LLM 的 system prompt context。
  • 手動或 AI 萃取新增知識條目
  • 知識內容注入 Stage 1 load_context
  • 目標群組同頁管理,已選 2 個

給活動規劃者

不需要技術背景,只要會打字,就能讓 AI 幫你規劃好所有推播時間與內容。

適合對象:活動規劃者、社群管理者,無需程式知識
前置條件
已登入 WiPPY 平台帳號
WiPPY LINE Bot 已被邀請進入目標群組
「活動目標群組」頁面可看到你的 LINE 群組
操作流程
01
建立活動
填入名稱、日期、目標群組
02
設定知識庫
活動背景、語氣設定、注意事項
03
Agent 對話
用自然語言描述需求,AI 生成草稿
04
審核批准
到「推播企畫」確認並批准
05
自動發送
時間到,系統自動推播到 LINE 群組
對話示範
Agent 對話 · 五月露營活動
我有一個漂書活動,五個朋友,五月一號要在匹客球場換書。我想在換書前這幾天(大概從今天到五一當天)在 LINE 群組裡推一些東西,讓大家進入狀態,因為這個活動的氣氛很重要——不是那種很熱鬧的活動,是比較安靜、有點文學感的東西。

我大概有幾個想法:
想提醒大家帶書、帶小卡,但不要太直白,感覺太像通知
想推一些有氣氛的東西,比如書摘或句子,讓大家慢慢有感覺
AI Agent

要創造這種「安靜且有文學感」的氛圍,關鍵在於「留白」「隱喻」。不要把這當成一個「活動」,而是一場「默契的約定」。以下我為你設計了從 4/27 到 4/30 (活動前一天) 的引導邏輯與文案範例。這些內容請用一種「隨手分享」的口吻發在群組裡。


預熱時間表

4/27(一):關於「書架上的安靜」
  • 目的:讓大家開始意識到要帶書,但不說「請帶書」。
  • 文案:(發一張你書架的照片,或是網路上很有意境的閱讀角落圖)
    「這幾天整理書櫃,發現有些書讀完後,在架子上站了很久,安靜得像是在等什麼。突然想到,也許它們也在期待一趟新的旅行,去看看誰會是下一個翻開它們的人。」
4/28(二):關於「對話的痕跡」
  • 目的:隱晦帶出「小卡」的意義。
  • 文案:(分享一段書摘)
    「以前看書,總喜歡在空白處寫下當時的註解。後來覺得,如果能把這些心情留給下一個讀者,就像是和未來的某個朋友跨越時空對話。如果這兩天有人挑選書的話,不妨也留下一張小卡吧,算是給這本書的一點告別,或是給下一站的祝福。」
4/29(三):關於「流動的意義」
  • 目的:連結匹客球場與環境,強調靜謐感。
  • 文案:「這幾天一直在想,我們選在球場旁見面,在那種甚至還聽得見遠處揮拍聲的環境裡,讀著這些交換來的文字,應該會有一種很特別的沈澱感。書本像水一樣,就是要流動,才會有生命。」
4/30(四):關於「不期而遇的懸念」
  • 目的:為明天的「規則」埋下伏筆。
  • 文案:「明天要見面了。關於這些書怎麼到下一個人手中,我心裡有個小想法,想試著讓過程多一點點不確定性,讓一切順著當時的直覺發生。明天見面時再和你們說。」

你覺得這個節奏符合你們的朋友圈嗎?
確認沒問題的話,請讓我知道。

很好,放進排程
AI Agent
✅ 已將 4 則推播訊息加入排程!請到「推播企畫」分頁確認後點「批准」,訊息就會在指定時間自動發出。
常見問題
訊息到了時間卻沒發出去,怎麼辦?
最常見原因是忘記點「批准」。請到「推播企畫」分頁確認審核狀態是否為「已批准」。若已批准仍未發送,請確認 LINE Bot 是否仍在目標群組中,並到「發送紀錄」查看錯誤訊息。
AI 產出的內容不夠精準,怎麼改善?
在「知識庫」分頁補充更多背景資訊:活動特色、注意事項、目標受眾、語氣要求等。知識庫越詳細,AI 產出的內容就越符合期待。
可以針對不同群組發送不同內容嗎?
可以。在 Agent 對話中直接說明:「A 群組收到○○,B 群組收到△△」,AI 會幫你分開建立兩組排程。

為什麼要做 WiPPY?

讓活動主辦方專注於活動本身,僅需審查 AI 規劃的不同群組的客製推播文案、推播時機

Pain Points

  • 手動撰寫推播文案,耗時且難以維持一致性
  • 排程邏輯散落各處,缺乏可觀測性
  • 知識庫與歷史對話沒有系統性管理

WiPPY 的解法

  • 自然語言輸入,Agent 自動產生訊息計畫
  • 7 階段 Pipeline,每步可觀測、可恢復
  • Firestore 知識庫 + 對話歷史,context 有記憶

(非常簡陋的) Harness Pipeline

7 階段有狀態執行器。每次執行都建立一筆 harnessRun, 記錄當前 stage、LLM 呼叫次數與狀態,讓 debug 不靠猜。

01
load_context
平行查詢 Firestore,撈活動資料、知識庫、現有排程、歷史對話,組成 ContextEnvelope
展開詳情
負責檔案
contextBuilder.ts
待優化
  • 不同群組間調性不同,未來可從對話等紀錄各群組風格
  • 知識庫架構待擴充,以提供 LLM 更多活動相關資訊
  • 知識庫筆數過多,context 超過 token 限制
02
build_prompt
將 ContextEnvelope 注入 system prompt,拼接最近 10 輪對話,組成送給 LLM 的 messages 陣列
展開詳情
負責檔案
harnessOrchestrator.ts
待優化
  • 對話歷史過長,超過模型 context window
  • 待優化 System Prompt 中所有 Constraints 條件,使 llm 回覆合規合理內容
  • 三種 intent 共用同一 prompt,指令干擾
03
run_planner
呼叫 LLM;每次 run 最多 3 次呼叫(含 repair),捕捉 429 轉為結構化 llm_rate_limit_error
展開詳情
負責檔案
llmProvider.ts
待優化
  • 429 rate limit,轉為結構化錯誤後 run 失敗
  • LLM 回傳空字串或格式完全不符預期
  • max_llm_calls_exceeded(repair 耗盡 3 次配額)
04
parse_output
從 raw reply 推斷 intent:能解析 JSON 陣列 → plan_messages;含 EXTRACTED_KNOWLEDGE: 區塊 → extract_knowledge;否則 → general_chat
展開詳情
負責檔案
harnessOrchestrator.ts
待優化
  • LLM 同時輸出 JSON + EXTRACTED_KNOWLEDGE,intent 判斷衝突
  • intent 事後推斷,無法事前分流控制輸出格式
05
validate_output
驗證 plan_messages 欄位合法性(ISO datetime、sequenceOrder 不重複、content 非空);失敗自動送回 LLM repair,repair 後仍失敗整個 run 標記 failed
展開詳情
負責檔案
planValidator.ts
待優化
  • repair 後 LLM 仍回傳相同錯誤格式 → repair_failed
  • extract_knowledge 路徑不經過此 validator
  • validateExtractedKnowledge() 已實作但尚未接入
06
persist_effects
批次寫入訊息排程與知識庫(每批 ≤ 499 ops);所有寫入帶 runId 確保可追溯;session history 保留最近 20 筆
展開詳情
負責檔案
persistenceAdapter.ts
待優化
  • 多批 batch.commit() 無原子性,中途失敗導致部分寫入
  • Firestore 寫入配額超限(499 ops/batch)
  • 目前無補償邏輯,僅靠 runId 事後追溯
07
finalize_response
截掉回覆中的 EXTRACTED_KNOWLEDGE 區塊;若成功寫入排程則替換為固定確認文案;將 HarnessRun 寫為 completed
展開詳情
負責檔案
harnessOrchestrator.ts
待優化
  • EXTRACTED_KNOWLEDGE 區塊截取 regex 邊界條件
  • confirm 文案寫死,無法反映實際寫入結果差異
HarnessRun · 可觀測性
statusqueued → running → completed | failed
currentStageload_context → build_prompt → … → finalize_response
llmCallCount1 – 3(含 repair)
intentTypeplan_messages | extract_knowledge | general_chat
lastErrorrepair_failed / max_llm_calls_exceeded / …

Output Intent

parse_output 階段事後推斷 intent,決定後續行為。每種 intent 對應不同的副作用。

plan_messages

訊息排程計畫

產生訊息排程,寫入 Firestore 並準備推播至目標 LINE 群組。

副作用 → 寫入排程 + 觸發推播
extract_knowledge

知識萃取

從對話中萃取結構化知識,更新群組知識庫,供下次 context 載入使用。

副作用 → 更新知識庫
general_chat

一般問答

回答使用者的問題,純文字回覆,不觸發任何 Firestore 寫入。

副作用 →

v0.5 (preview) Known Issues

以下是程式碼層級已確認的限制,不是警告,是下個版本的優先工單。

v0.5 (preview)
2026-04-28
Known Issues — 程式碼層級已確認,非假設
knowledge validator 未接入
validateExtractedKnowledge() 已實作且有測試,但 orchestrator 只 import validateMessagePlan。knowledge 寫入前僅做 type 白名單過濾,不檢查 title / content 是否為空。
Phase 2
單一 prompt 承擔三種 intent
buildSystemPrompt() 只有一個,三種 intent 共用同一組 system prompt。intent 在 parse_output 事後推斷,而非事前分流,prompt 品質受限。
Phase 3
跨批寫入無原子性
persistEffects() 分批 batch.commit(),若第一批成功、第二批失敗,資料部分寫入,目前無補償邏輯,僅靠 runId 事後追溯。
Phase 2

Roadmap

分為技術強化與功能擴充兩條軸線,持續迭代。

技術強化
Phase 2 Recovery 與 Safety 強化
validateExtractedKnowledge() 接進 orchestrator 的 validate_output stage
建立分層錯誤分類(context_load_error / llm_rate_limit_error / persistence_error),每類有明確 retry 策略
persist_effects 多批寫入加補償邏輯,依 runId 重試未完成的批次
Scheduler / send path 套入相同的 retry + structured failure policy
Phase 3 LangGraph-ready
每種 intent 有獨立 prompt mode(plan_messages / extract_knowledge / general_chat 各自的 system prompt)
將每個 stage 顯式化為 tool contract(name、input/output schema、timeout、retry policy),為接 LangGraph 做準備
ContextEnvelope 生成器替換為 retrieval-augmented 版本,召回相關知識而非全量載入
明確標註 pause hook(pause_before_persistpause_after_validate)對應 LangGraph human-in-the-loop 中斷點
功能優化及擴充
Phase 2 知識庫與 Prompt 優化
優化知識庫可輸入類型及輸入方式,擴增不同格式檔案及串接方式
優化現有 System Prompt 的約束條件、產出格式、錯誤處理
Phase 3 個人化風格與意圖判斷
增加各群組個人化風格蒐集及紀錄機制,以供 LLM 針對不同群組產出不同調性的推播內容
設計意圖判斷機制,判斷後以使用不同 System Prompt

Tech Stack

全端 TypeScript,GCP 原生部署。

Backend

Node.js 18+ TypeScript Express Firebase Admin SDK Firestore Google Genai SDK LINE Bot SDK Cloud Tasks date-fns-tz

Frontend

React 19 TypeScript Vite 8 Tailwind CSS 4 React Router 7 Firebase SDK 12

Infrastructure

Google Cloud Run Firebase Hosting Firestore Cloud Tasks LINE Messaging API