iT邦幫忙

2026 iThome 鐵人賽

DAY 21
0
ChatGPT & Codex

AI 時代的輕量化開發:ChatGPT 打造 LINE 多模態記帳與續訂預警 Agent系列 第 21

[Day 21] 別再手動改帳!讓 SubWise 用 AI 自動找到並修改錯誤紀錄

  • 分享至 

  • xImage
  •  

前言

前幾天的 SubWise 已經可以做到「新增記帳」「查詢資料」與「消費分析」。但做到這裡,開始遇到一個很自然的問題:如果我剛剛記錯了怎麼辦?

例如原本記了一筆「2026-08-20 / Food / NT$100」,結果後來發現其實應該是交通費。理想中的使用方式應該很簡單:「把 2026-08-20 那筆 100 元分類為 Other 的消費改成 Transport」,然後 SubWise 幫我找到正確紀錄並直接修改 Google Sheets。這就是 Day 21 想完成的事情:讓 SubWise 不只是「會記帳」,而是開始具備修改既有資料的能力。


今日實作實錄

一、讓 AI 分得出「新增」與「修改」

這其實比想像中困難,因為「今天花 100 元買午餐」跟「把今天那筆 100 元改成午餐」這兩句話裡都有日期、金額、消費項目,如果只看關鍵字很容易被誤判成同一種意圖。因此第一個重要工作,是重新整理 Gemini 的意圖分類,在原本的 expensesubscriptionqueryanalysischat 之外,新增 expense_update,代表「使用者正在修改已經存在的消費,而不是建立新的消費」。

SYSTEM_PROMPT 裡加入判斷規則:只要句子出現「改成」「修改」「記錯」「分類改成」「剛剛記錯了」這類操作詞,就優先判斷為 expense_update 而不是 expense。這個規則很重要,因為 SubWise 的核心不是單純讓 Gemini「分類文字」,而是讓 Gemini 成為一個真正的意圖解析器

二、定義 expense_update 的資料格式

把修改既有消費的 JSON 格式定義清楚:

{
    "type": "expense_update",
    "date": "2026-07-31",
    "amount": 55,
    "field": "category",
    "value": "Transport"
}

dateamount 用來定位是哪一筆資料,field 是要修改哪個欄位,value 是要改成什麼。這樣 Python 就不需要理解自然語言,只需要執行 Gemini 已經解析好的結構化指令。

三、加入不支援分類的防呆

如果使用者說「把 55 元改成 Drink」,SubWise 不能直接把 Drink 寫進 Google Sheets,因為系統只支援 FoodTransportEntertainmentShoppingBillsHealthEducationSubscriptionOther 九種分類。因此新增 invalid_category 類型,讓 Gemini 能區分合法分類與不支援分類,由 Python 顯示友善提示:

⚠️「Drink」不是目前支援的消費分類。

目前分類有:
🍜 Food|餐飲 🚇 Transport|交通 🎮 Entertainment|娛樂
🛍️ Shopping|購物 💡 Bills|生活帳單 ❤️ Health|醫療保健
📚 Education|學習 🔔 Subscription|訂閱 📦 Other|其他

請問你想把它改成哪一個分類?

這代表 SubWise 並不是「AI 說什麼,我就寫什麼」,而是AI 負責理解使用者,程式負責守住系統規則

四、建立 edit_expense(),真正修改 Google Sheets

完成 edit_expense(),先透過日期加金額找到可能符合的消費,再根據 field 決定要修改哪一欄:

column_map = {
    "category": 2,
    "amount": 3,
    "item": 4,
    "note": 5
}

這讓自然語言最後真的可以轉成 Google Sheets 的實際修改操作。


今天踩到的坑

坑一:AI 把「修改」當成「新增」
一開始在 LINE 測試「把 2026-08-20 那筆 100 元分類為 Other 的消費改成 Transport」,Gemini 卻回傳 type: expense,SubWise 因此又新增了一筆消費,而不是修改原本的資料。這是一個非常典型的 AI Agent 問題:AI 有理解文字,但沒有理解「操作語意」,因此才有了前面重新設計 Gemini 意圖判斷規則的過程。

坑二:Python 測試成功,LINE 卻失敗
直接測試 edit_expense() 這個函式本身完全正常,能成功修改資料。但實際在 LINE 測試時,SubWise 又新增了一筆消費而不是修改。往上追查後才發現,真正的問題出在 Gemini 的意圖判斷(也就是坑一),而不是 edit_expense() 本身。這次除錯讓整個架構的概念變得更清楚:測試單一函式成功,只能證明那個函式成功,真正的 Agent 功能必須從 LINE → Gemini → Python → Google Sheets 整條鏈路測試。


完整測試

修正 Gemini 意圖判斷後,測試四種不同的修改情境,全部成功:

  • 修改分類:「把 2026-08-20 那筆 100 元分類為 Other 的消費改成 Transport」→ 分類已修改為 Transport
    https://ithelp.ithome.com.tw/upload/images/20260822/20178527pBvT4qyuWV.png

  • 修改金額:「把 2026-07-31 那筆 55 元改成 120 元」→ 金額已修改為 120
    https://ithelp.ithome.com.tw/upload/images/20260822/20178527Ba6TpB7fdk.png

  • 修改成不存在的分類:「把 2026-07-31 那筆 120 元改成 Drink」→ 成功阻止,顯示分類不支援提示
    https://ithelp.ithome.com.tw/upload/images/20260822/20178527F9Gh2fJTFw.png

  • 修改消費項目:「把 2026-07-31 那筆 120 元改成午餐」→ 項目已修改為午餐
    https://ithelp.ithome.com.tw/upload/images/20260822/2017852766GwvOzswR.png


意外發現:刪除功能已經有一半可以動了

測試修改功能時,自然聯想到「那如果想直接刪掉呢?」測試輸入「把 2026-07-31 那筆 120 元刪掉」,先單獨測 Gemini,發現它已經能正確理解成:

{'type': 'expense_delete', 'date': '2026-07-31', 'keyword': None, 'old_amount': 120}

也就是說,目前 Gemini 意圖判斷跟 Google Sheets 的刪除邏輯都已經準備好,只差 app.py 還沒有把 expense_delete 這個 type 接起來。

但今天決定先停在這裡,因為如果現在繼續做刪除功能,還需要測試「找不到資料」「多筆相同金額」「防止誤刪」等情境,因此決定把它留到 Day 22,讓今天的成果聚焦在「修改」這一個主題上。


今日完成

  • 新增 Gemini expense_update 意圖,區分「新增消費」與「修改既有消費」
  • 定義 expense_update JSON 格式(date / amount / field / value)
  • 加入 invalid_category 防呆,阻擋不支援的分類寫入
  • 建立 edit_expense(),完成 Google Sheets 實際欄位修改
  • 完整測試:修改分類 / 修改金額 / 修改項目 / 不支援分類防呆
  • 確認 Gemini 已能正確判斷 expense_delete 意圖(實作留到 Day 22)

目前修改既有消費的完整流程:
使用者「把 2026-07-31 那筆 55 元改成 120 元」
→ Gemini(expense_update)
→ Python(找到指定日期+金額的資料)
→ Google Sheets(修改 Amount)
→ LINE(✏️ 記帳修改成功!)


明日預告

今天讓 SubWise 學會「改錯」,明天 Day 22 要完成的是「刪掉」——把今天已經驗證過、Gemini 能正確判斷的 expense_delete 意圖,正式接進 app.py,並處理找不到資料、多筆符合、防止誤刪等情境,讓 SubWise 補齊消費資料管理的最後一塊拼圖。


上一篇
[Day 20] 從「你說我記」到「你拍我記」:打造能看懂發票的 LINE 記帳 Agent
系列文
AI 時代的輕量化開發:ChatGPT 打造 LINE 多模態記帳與續訂預警 Agent21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言