iT邦幫忙

2026 iThome 鐵人賽

DAY 10
0
ChatGPT & Codex

這隻 LINE Bot 不是我寫的:30 天讓 Codex 從零幫我做到上線系列 第 10

Day 10 - 收藏之後呢?我和 Codex 讓 Gemini 聽懂「下週六下午兩點」,再把咖啡行程放進 Google Calendar

  • 分享至 

  • xImage
  •  

上一篇,我記錄了怎麼用 Gemini Function Calling,讓 LINE Cafe Bot 聽懂「收藏第二間」,再透過確認按鈕把店家安全地存進 Firestore。

收藏功能完成後,我很自然地又想到下一句:

下週六下午兩點安排第二間。

如果 Bot 已經知道我說的是哪一間咖啡廳,那它能不能連時間一起聽懂,替我準備好行程?

這篇就把「加入行事曆」獨立拉出來,記錄我和 Codex 怎麼把自然語言時間、Gemini Function Calling,以及 Google Calendar 串成一條完整流程。


這次不只是找到店,還要理解「什麼時候去」

「收藏第二間」只需要知道兩件事:使用者想收藏,以及目標是推薦清單中的第二間。

但「下週六下午兩點安排第二間」多了時間資訊,而且使用者不一定會照固定格式輸入。

他可能會說:

這週六兩點去第二間
下星期日下午安排第一間
明天晚上想去第三間
幫我排第二間,停留兩個小時

如果全部依靠字串規則處理,很快就會碰到「這週」、「下週」、「下午」和不同語序的問題。

所以這次我讓 Gemini 負責把自然語言整理成一個 plan_cafe_visit Function Call:

{
  "name": "plan_cafe_visit",
  "args": {
    "cafe_number": 2,
    "start_time": "2026-08-29T14:00:00+08:00",
    "duration_minutes": 90
  }
}

後端不需要自己猜每種中文時間說法,只要接收固定欄位,再驗證店家編號、日期和活動長度。

這就是 Function Calling 在這個功能裡最實際的價值:使用者可以照平常的方式說話,程式仍然能拿到穩定的資料格式。


Gemini 能理解相對時間,但仍然需要清楚的基準

「下週六」不是一個永遠固定的日期,它會隨著今天是哪一天改變。

所以每次請 Gemini 判斷行程時,後端會一起提供:

  • 目前時間
  • 使用者時區 Asia/Taipei
  • 最近一批咖啡廳清單
  • 模糊時段的預設值

這一版把「早上」、「下午」和「晚上」分別預設成 10:00、14:00 與 19:00。如果使用者沒有說停留多久,就先使用 90 分鐘。

Gemini 回傳時間後,後端還會再次檢查:

  • 日期格式是否能解析
  • 時間是否在未來
  • 店家編號是否真的存在
  • 活動長度是否介於 30 到 480 分鐘

模型負責理解語意,程式負責守住合理範圍。這個分工和收藏功能一樣,不會因為 Gemini 已經回傳結構化資料,就省略後端驗證。


為什麼第一版沒有直接寫入 Google Calendar?

做到這裡,下一步看起來很直覺:直接呼叫 Google Calendar API,替使用者建立活動。

但這代表每位使用者都要先登入 Google 帳號並授權 Bot,後端還需要安全保存 OAuth token、處理 token 更新與撤銷。

對第一版 MVP 來說,這些工作會比行程功能本身更大。

我和 Codex 最後選擇先產生 Google Calendar 的活動預填連結:

https://calendar.google.com/calendar/render?action=TEMPLATE&...

連結裡會帶入:

  • 活動名稱
  • 開始與結束時間
  • 咖啡廳名稱
  • Google Maps 網址

使用者點擊 LINE 裡的「加入行事曆」後,會開啟已經填好內容的 Google Calendar 頁面,最後再由使用者自己按下儲存。

這樣不需要取得 Google 帳號權限,也不用保存任何 OAuth token,卻已經能讓「我想去這間店」順利走到「行程已經準備好」。


行程一樣要先確認,不讓模型直接執行

即使這一版沒有直接寫進 Google Calendar,Bot 仍然會先顯示確認:

請確認是否要收藏「咖啡廳名稱」,
並建立 2026/8/29 14:00 的行事曆活動?

[確認執行][取消]

這筆 pending action 會綁定原使用者與原對話,並在 10 分鐘後失效。

按下確認後,Firestore Transaction 會先檢查它是否有效、是否已經執行過,再收藏咖啡廳並回傳 Calendar 連結。

所以完整流程是:

「下週六下午兩點安排第二間」
                ↓
Gemini 選擇 plan_cafe_visit
                ↓
後端驗證店家、時間與長度
                ↓
LINE 顯示確認/取消
                ↓
確認後收藏店家
                ↓
顯示「加入行事曆」與「開啟地圖」

這也讓收藏篇建立的安全機制可以直接延伸,而不是每加一個 Action 就重新設計一次流程。

https://ithelp.ithome.com.tw/upload/images/20260821/201835566zQW1VJbRv.png


「加入行事曆」按鈕做了什麼,也沒有做什麼

目前這顆按鈕會:

  • 開啟 Google Calendar 活動頁面
  • 預填咖啡廳、日期、時間與 Maps 連結
  • 讓使用者確認後自行儲存

目前它不會:

  • 未經確認直接修改使用者的 Calendar
  • 取得或保存 Google OAuth token
  • 在指定時間主動傳送 LINE 提醒

最後一項是我想做的下一個階段。

未來可以透過 Cloud Tasks,在指定時間呼叫受保護的任務 endpoint,再使用 LINE Push Message 主動提醒。不過排程會牽涉到任務認證、重試與避免重複發送,我希望把它當成另一個完整題目,而不是匆忙附加在 Calendar 按鈕後面。

https://ithelp.ithome.com.tw/upload/images/20260821/201835560cmFSxGETT.png

從一句自然語言,走到一個真的能使用的行程

回頭看,「下週六下午兩點安排第二間」只是一句很日常的話。

但要把它真正變成功能,背後需要幾個角色一起配合:

  • Gemini 理解店家編號、相對日期和活動長度
  • 後端驗證時間與資料範圍
  • Firestore 保存待確認操作並避免重複執行
  • LINE 提供確認按鈕與 Calendar 入口
  • Google Calendar 預填連結把最後決定交還給使用者

Codex 在這次協作裡,幫我把原本一句模糊的需求拆成這幾層,再把它們接成可以實際在手機上操作的流程。

我很喜歡這一版的平衡:它沒有一開始就要求完整 OAuth,也沒有假裝 Bot 已經替使用者完成所有事情,而是在安全、開發範圍和使用體驗之間,先找到一個真的能用的版本。


本篇完整程式碼

GitHub:
https://github.com/zonawang/line-cafe-action-agent

更多 LINE Bot 與 AI 實作紀錄:
https://github.com/zonawang/zona-ai-learning-lab


上一篇
Day 9 - 我和 Codex 讓 LINE Cafe Bot 真的會做事:從「收藏第二間」開始的 Gemini Function Calling 實作
下一篇
Day 11 - 我收藏了咖啡廳,還是會忘記去:我和 Codex 讓 LINE Bot 在正確時間主動提醒我
系列文
這隻 LINE Bot 不是我寫的:30 天讓 Codex 從零幫我做到上線11
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言