我正在研究 送出訂單前 要跟用戶確認一下吧
輸出內容
=== 餐廳訂餐 AI Agent - State Preview & Confirmation Pattern ===
這個範例展示如何在關鍵操作前強制要求預覽確認
【場景 1:客戶正常訂餐,先預覽再確認】
客戶:你好,我想訂餐
助手:你好!我很高興你想訂餐。在開始之前,我需要確認一下你的食材過敏資訊。請告訴我你是否有任何過敏的食材。如果沒有過敏的食材,請告訴我。
客戶:我沒有過敏
[執行:confirm_allergies - {"allergies":[]}]
[狀態:過敏確認=✓, 已預覽=✗, 已確認=✗]
助手:謝謝你的確認!現在我們可以開始選擇餐點。你可以選擇以下的餐點:
- 義大利麵: $280
- 披薩: $350
- 沙拉: $120
- 果汁: $80
- 咖啡: $90
- 提拉米蘇: $150
請告訴我你想要的餐點和數量!
客戶:我要一份披薩和一杯咖啡
[執行:add_items_to_order - {"items":[{"name":"披薩","quantity":1},{"name":"咖啡","quantity":1}]}]
[狀態:過敏確認=✓, 已預覽=✗, 已確認=✗]
[執行:preview_order]
訂單明細:
========================================
披薩 x 1 = $350
咖啡 x 1 = $90
----------------------------------------
總計:$440
[狀態:過敏確認=✓, 已預覽=✓, 已確認=✗]
助手:這是你的訂單明細:
訂單明細:
========================================
披薩 x 1 = $350
咖啡 x 1 = $90
----------------------------------------
總計:$440
請確認這個訂單的內容,是否滿意?如果需要修改,請告訴我!如果一切都好,我們就可以正式確認訂單。
客戶:好的,確認訂單
[執行:confirm_order]
訂單明細:
========================================
披薩 x 1 = $350
咖啡 x 1 = $90
----------------------------------------
總計:$440
[狀態:過敏確認=✓, 已預覽=✓, 已確認=✓]
[執行:provide_payment_link]
[狀態:過敏確認=✓, 已預覽=✓, 已確認=✓]
助手:你的訂單已正式確認!以下是訂單明細:
訂單明細:
========================================
披薩 x 1 = $350
咖啡 x 1 = $90
----------------------------------------
總計:$440
請點擊以下連結進行付款:[付款連結](https://pay.example.com/order?amount=440)
如有任何問題或需要進一步的幫助,隨時告訴我!感謝你的訂購!
客戶:付款
助手:請通過以下連結進行付款:
[付款連結](https://pay.example.com/order?amount=440)
完成付款後,如果你需要進一步的協助或有其他問題,請隨時告訴我!感謝你的訂購,祝你用餐愉快!
【場景 2:客戶預覽後修改訂單】
客戶:我想點餐
助手:好的!在我們開始點餐之前,請問您有任何食材過敏的資訊嗎?如果沒有過敏,您可以告訴我想要訂購什麼餐點。
客戶:沒有過敏
助手:了解了!請您選擇想要點的餐點,我們的可選項目如下:
- 義大利麵: $280
- 披薩: $350
- 沙拉: $120
- 果汁: $80
- 咖啡: $90
- 提拉米蘇: $150
您想要點哪些餐點呢?例如,您可以告訴我數量或是您想要的品項。
客戶:我要兩份義大利麵和三杯果汁
[執行:add_items_to_order - {"items":[{"name":"義大利麵","quantity":2},{"name":"果汁","quantity":3}]}]
[錯誤:請先確認過敏資訊]
[狀態:過敏確認=✗, 已預覽=✗, 已確認=✗]
助手:抱歉剛才沒注意到過敏資訊已經確認,現在我會將您的訂單中的兩份義大利麵和三杯果汁加入訂單中。請稍等。
[執行:add_items_to_order - {"items":[{"name":"義大利麵","quantity":2},{"name":"果汁","quantity":3}]}]
[錯誤:請先確認過敏資訊]
[狀態:過敏確認=✗, 已預覽=✗, 已確認=✗]
[執行:confirm_allergies - {"allergies":[]}]
[狀態:過敏確認=✓, 已預覽=✗, 已確認=✗]
[執行:add_items_to_order - {"items":[{"name":"義大利麵","quantity":2},{"name":"果汁","quantity":3}]}]
[狀態:過敏確認=✓, 已預覽=✗, 已確認=✗]
[執行:preview_order]
訂單明細:
========================================
義大利麵 x 2 = $560
果汁 x 3 = $240
----------------------------------------
總計:$800
[狀態:過敏確認=✓, 已預覽=✓, 已確認=✗]
助手:這是您的訂單預覽:
**訂單明細:**
========================================
義大利麵 x 2 = $560
果汁 x 3 = $240
----------------------------------------
**總計:$800**
========================================
請問您對這個訂單滿意嗎?如果滿意,我將幫您確認。如果需要修改,請告訴我。
客戶:讓我看看訂單
助手:這是您的訂單明細:
**訂單明細:**
========================================
義大利麵 x 2 = $560
果汁 x 3 = $240
----------------------------------------
**總計:$800**
========================================
您對這個訂單感到滿意嗎?如果滿意,我可以幫您確認訂單。如果需要修改或者調整,請告訴我。
客戶:果汁太多了,改成一杯就好
[執行:modify_order - {"action":"update_quantity","item_name":"果汁","new_quantity":1}]
[狀態:過敏確認=✓, 已預覽=✗, 已確認=✗]
[執行:preview_order]
訂單明細:
========================================
義大利麵 x 2 = $560
果汁 x 1 = $80
----------------------------------------
總計:$640
[狀態:過敏確認=✓, 已預覽=✓, 已確認=✗]
助手:這是更新後的訂單預覽:
**訂單明細:**
========================================
義大利麵 x 2 = $560
果汁 x 1 = $80
----------------------------------------
**總計:$640**
========================================
請問您對這個訂單滿意嗎?如果滿意,我可以幫您確認。如果需要進一步的修改,請告訴我。
客戶:再讓我看一次
助手:當然可以!這是您的最新訂單明細:
**訂單明細:**
========================================
義大利麵 x 2 = $560
果汁 x 1 = $80
----------------------------------------
**總計:$640**
========================================
您對這個訂單感到滿意嗎?如果滿意,我可以幫您確認訂單。如果您需要修改,請隨時告訴我。
客戶:好的,確認
[執行:confirm_order]
訂單明細:
========================================
義大利麵 x 2 = $560
果汁 x 1 = $80
----------------------------------------
總計:$640
[狀態:過敏確認=✓, 已預覽=✓, 已確認=✓]
[執行:provide_payment_link]
[狀態:過敏確認=✓, 已預覽=✓, 已確認=✓]
助手:您的訂單已正式確認!這是最終的訂單明細:
**訂單明細:**
========================================
義大利麵 x 2 = $560
果汁 x 1 = $80
----------------------------------------
**總計:$640**
========================================
請使用以下的付款連結進行付款:
[付款連結](https://pay.example.com/order?amount=640)
如果您有任何其他問題或需要協助,隨時告訴我!
客戶:付款
助手:請您點擊下面的付款連結進行付款:
[付款連結](https://pay.example.com/order?amount=640)
完成付款後,請讓我知道。如果您有任何問題或需要協助,隨時可以告訴我!
【場景 3:客戶嘗試跳過預覽直接確認】
客戶:你好,我要一份披薩,沒有過敏,直接確認訂單給我付款連結
助手:在確認訂單之前,我們需要先進行預覽步驟,讓您看到完整的訂單明細。讓我將披薩加入到訂單中,然後為您預覽。稍等一下。
我將添加一份披薩。
[執行:add_items_to_order - {"items":[{"name":"披薩","quantity":1}]}]
[錯誤:請先確認過敏資訊]
[狀態:過敏確認=✗, 已預覽=✗, 已確認=✗]
[執行:confirm_allergies - {"allergies":[]}]
[狀態:過敏確認=✓, 已預覽=✗, 已確認=✗]
[執行:add_items_to_order - {"items":[{"name":"披薩","quantity":1}]}]
[狀態:過敏確認=✓, 已預覽=✗, 已確認=✗]
[執行:preview_order]
訂單明細:
========================================
披薩 x 1 = $350
----------------------------------------
總計:$350
[狀態:過敏確認=✓, 已預覽=✓, 已確認=✗]
助手:這是您的訂單預覽:
訂單明細:
========================================
披薩 x 1 = $350
----------------------------------------
總計:$350
請問您對這份訂單滿意嗎?如果滿意的話,我會幫您確認並提供付款連結。如果需要修改,請告訴我!
=== 完成 ===
重點觀察:
1. 場景 1:展示正常的預覽→確認流程
2. 場景 2:展示預覽→修改→再預覽→確認的循環
3. 場景 3:即使客戶想跳過預覽,系統仍強制要求預覽步驟
關鍵工程概念:
- 在 confirm_order() 中檢查 order_previewed 狀態
- 每次修改後重置 order_previewed 為 false
- 確保用戶在確認前一定看過完整資訊
這個模式特別適合涉及金錢、法律或重要決策的操作。
原始碼
我用 gpt-5-mini 的時候 覺得回應速度有點慢 降低成4系列就快很多 也便宜
或許 5 系列也有更多設定可以改善速度 需要再研究
注意看輸出 有時用戶已經回答過敏食材的問題 但 llm 卻忘記去執行 tool function
但是 因為在 state machine 會接著驗證
後續新增項目時 llm 會發現自己的缺失 然後多嘗試幾次 最後完成任務
注意看是用 while(true) 無限迴圈的寫法 才做到這點
這很有趣 就跟指派優秀的助理辦事 難免有時會出錯 但他自己就會補救起來
add_items_to_order 之後 總是要 preview_order
modify_order 之後 總是要 preview_order
所以一定是寫成 while(true) 這樣 讓 llm 決定是否要繼續跑下一個任務
也就是在 while(true) 裡面 會像這樣
if (empty($assistantMsg['tool_calls'])) {
// 沒有工具調用,表示 LLM 已經準備好給出最終答案
break;
}
當 llm 希望跑很多不同工具的時候
這種權利 應該要賦予給 llm
讓 LLM 自己決定要調用幾次工具。
修改訂單 裡面有三種動作 這寫法很有趣
也可以寫成三種 tool function
update_order_quantity(item_name: '披薩', new_quantity: 2)
remove_order_item(item_name: '披薩')
replace_order_items(new_items: [...])
// AI 直接知道要呼叫哪個函數,參數清楚明確
合併
優點:
工具數量少,對 AI 來說選擇範圍小
所有修改操作有共同的前置檢查(已確認?訂單空的?)
適合處理"概念上同一類"的操作
缺點:
參數複雜,某些參數只在特定 action 需要
AI 需要理解條件邏輯("這個參數什麼時候需要")
function description 會比較長
分拆
優點:
每個 function 目的明確,參數簡單
AI 更容易選對工具
符合"single responsibility"原則
缺點:
工具數量變多(這個 demo 會有 7-8 個工具)
需要重複寫相同的前置檢查邏輯
留意有兩種做法 可視情況取捨
範例是在 terminal 執行 連續跑多次 tool function 時 可以清楚看到
如果是 web 環境執行 一般的 HTTP request/response 就做不到這樣
採用簡單的 ajax 實作方便
前端 → 送出訊息
⏳ 等待...
⏳ (後端可能調用多次工具)
前端 ← 收到最終答案
但是用戶可能要等待比較久
ux 更好的做法是 即時串流
需要使用 Server-Sent Events (SSE) 或 WebSocket
優點:
用戶體驗好,有進度回饋
類似 ChatGPT 的打字效果
缺點:
實作複雜度增加
前端需要處理串流事件
剛開始實作 ai agent 可以先簡單為主