
上一篇文章,分享了啟動 PetParser 的 MVP 思維,以及如何在資源有限的情況下,將核心風險鎖定在「驗證 AI 語意理解」上。
這週,我們進入最磨人、也最有趣的階段:實作。
這是我第一個嘗試導入 AI 的開發專案。老實說,這並不是一段「下了 Prompt 就能收割成果」的順遂旅程,而是一場 程式邏輯與 AI 隨機性之間的拉鋸戰。Gemini 就像是一個非常有創意,但完全沒有生活常識的「資優實習生」。
有時他會混淆人類口語的意思,還會自作聰明地在回傳格式上出各種問題。我將這段反覆試錯、逐漸「馴服」AI 的過程,總結為四道在開發過程中陸續設下的邏輯防線:
第一道防線:建立「通用時間規格」— 從人用藥單找靈感
開發初期,我就撞牆了。
我讓 AI 判斷用藥時間,它很自然地套用「三餐」的框架。這對高齡寵物照護來說太天真了。有的藥要「睡前服用」,有的是「一天四次」,還有「每 X 天一次」的可能性。如果侷限在三餐框架,根本無法應對多變的用藥需求。
為了讓 AI 能正確翻譯,我開始思考:到底什麼才是「通用的用藥時間結構」?
我翻出了大醫院的「人用藥單」,觀察上面那些制式的勾選框與圖示,發現人用醫學領域早有一套運作數十年的標準化溝通範本。
參考這套範本,我重構用藥時間框架為:Frequency 與 Anchors 兩個維度。前者界定頻率(例如:每日一次、每日兩次);後者定義時間點(例如:早餐、午餐、晚餐、睡前)。
這套規格決定了系統的「大腦」如何看待用藥時間,解決單一場景與情境限制,建立了涵蓋所有可能性和可擴充性的通用框架。
第二道防線:賦予 AI 「轉譯權限」— 將模糊語意推向資料落地
時間框架定好了,但進入實作後,我馬上撞到第二個難題:AI 雖然「讀懂」了規格,但它給我的資料,程式依然無法執行。
在初始階段,我請 AI 「提取」醫囑頻率,它給了我 frequency: "早晚各一次"。這對人類來說很好理解,但對排程系統來說,這是一串無法運算的「文字資料」。我意識到,要讓資料真正落地,AI 不能只是「提取文字」,它必須具備 「判斷與轉譯權限」。
為了讓排程真正能落地,我將原本的規格進一步擴展為更精確的標準代碼:
- 「頻率」擴展為「頻率代碼」
採用醫學標準代碼,我建立了一套 Mapping 字典,強迫 AI 進行轉譯。當它看到「早晚各一次」或「每日兩次」,必須映射為標準代碼 BID;看到「每日一次」則是 QD,「每日三次」則是 TID。有了代碼,程式才能精確啟動對應的邏輯。 - 「時間點」細分為兩種情境
- 事件錨點 (Event Anchors):這是用戶自定義的日常事件(如:睡前、晚餐後)。只要醫囑中有對應到事件關鍵字,AI 就會優先 mapping 到這些錨點時間。
- 系統預設時間 (Default Timing):如果醫囑沒有對應到 Event Anchors,則代表它與日常事件無關,為了讓排程不中斷,系統會根據頻率代碼 (每日X次) 自動帶入預設時間。這是最關鍵的「容錯設計」,真正解決了「排不出時間表」的窘境。
- 事件錨點 (Event Anchors):這是用戶自定義的日常事件(如:睡前、晚餐後)。只要醫囑中有對應到事件關鍵字,AI 就會優先 mapping 到這些錨點時間。

頻率代碼 與 時間點列表
透過這套規格擴展,成功將 AI 的產出從「感性描述」進化為「精確的規格化資料」。
第三道防線:劃分「系統職責」邊界 — AI 負責語意,JS 負責運算
這是我在專案初期就在思考的原則:不該為了用 AI 而用 AI。
AI 產品的本質,應該是讓 AI 處理它最擅長的「非結構化口語資料」—這是傳統工程難以攻克的領域。至於「排程計算」這種追求 100% 精準、不能有一絲容錯的邏輯,交給 JavaScript 處理的效果遠比 AI 優秀且穩定。
我明確劃分了兩者的界線:
- AI 翻譯官:僅負責將「模糊的自然語言」轉譯為符合規格的「JSON 資料」。它的任務在輸出 JSON Schema 那一刻就結束了。
- JS 執行官:接手 AI 產出的靜態資料,拿著頻率代碼去查表(例如:BID),拿著醫囑關鍵字(例如:睡前)去對齊用戶事件錨點,執行 「確定性的運算」並產出最終排程。

以「資料合約」為界:隔離 AI 的語意理解與 JS 的精準運算。
把 AI 限制在它擅長的語意理解,並將核心邏輯隔離開來。我認為這才是確保產品穩定的關鍵。
第四道防線:捍衛 Data Contract — 用層層過濾的策略,建立系統容錯邊界
即便有了前三道防線,AI 的隨機性依然是開發中的最大變數。最典型的挑戰就是「鍵名爭奪戰」。
在開發初期,因為 Prompt 指令較為寬鬆,導致 AI 產出的 JSON Key 經常隨意跳動。明明約定好是 meds,它回傳的卻可能是 prescriptions 或 drug_list。這種格式的不穩定,會直接導致前端渲染時因為找不到對應的 Key 而讓頁面崩潰。
為了守住 Data Contract 這條底線,我建立了一套 Defense in Depth 架構,由內而外層層過濾 AI 的隨機性:
- Prompt Engineering 的軟性約束:我在 System Prompt 中強制定義了「鍵名白名單」,嚴格禁止 AI 自創欄位。同時導入 Null Principle:如果醫囑資訊缺失,一律回傳
null而非空字串,這不僅是為了讓資料結構完整,更是為了讓前端在存取資料時,能有一致且可預期的邏輯。
透過 Prompt Engineering,AI 輸出的準確率顯著提高,也極少出現非預期的鍵名欄位。 - Data Adapter 的硬性攔截:即便 Prompt 再嚴謹,LLM 本質上仍是機率模型。因此,我在系統設計上定義了一層 Data Adapter 作為最後的容錯底線。即便 AI 真的因為那 1% 的隨機性而輸出了錯誤格式,這道機制也會即時攔截,將非預期的鍵名自動對齊回標準格式。
藉由「軟約束 + 硬攔截」的雙重機制,解決了 Data Contract 的穩定性問題。
番外篇:Rollback 的智慧 — 在不確定性中堅持「版控」紀律
最後,我想分享一個關於「紀律」的小插曲。
在開發過程中,我經歷過幾次「只是想修個 bug ,結果原本運作正常的功能瞬間壞掉」的慘劇。看著救不回來的程式碼,那種失控的焦慮感瞬間爆棚。
當時我使用的開發環境 Gemini 並沒有 Git 的版本控制功能,身為 PM 的本能告訴我:我需要一個 Baseline。
雖然方法很笨,但我開始手動將每個穩定版本的程式碼備份到 .txt 檔,並紀錄每一版完成的主要功能。
當後續版本徹底失控時,這份 .txt 檔成了我果斷 Rollback 的唯一依據。這段經驗讓我深刻體會到:在 AI 協作這種充滿高度不確定性的環境中,能隨時回到「上一個穩定版本」的防呆機制,比追求華麗的新功能更重要。這不是技術問題,而是對開發紀律的堅持。
結語: PM 的實作體察
這段馴服 AI 的過程,讓我意識到 PM 的角色已從「開規格」轉向「邏輯控場」。回頭檢視這場實驗, PM 擔任了幾項核心的任務:
- 定義規格:建立一套適用所有情境的時間規格協議。
- 推動轉譯:賦予 AI 判斷權,將模糊語意轉為程式可執行的代碼。
- 守護邊界:劃清職責分工,建立系統最後的容錯防火牆。
- 維護紀律:堅持版本管控原則,確保開發過程始終處於可控狀態。
這說明了,無論技術或工具如何改變,回歸 PM 定義規格、劃分職責與堅持紀律 的本質,才是讓產品穩定落地的核心關鍵。
下篇文章,我們換個視角,聊聊「市場觀察與商業思考」:如何從解決自家的冰箱藥單出發,觀察這類 AI 工具在市場上的潛力與挑戰。











