
職前訓練結束,師爺(平安)正式上工!
第一個任務,是陪長輩和家人「一起說畫」。
「一起說畫」來自衛福部《失智症診療手冊》非藥物治療方式:
藝術創作團體讓成員一同創作、一起說「畫」。
健口動一動參考這個做法,
透過 Gemini API : Live + Nano Banana 實踐:
長輩和家人說畫裡要有什麼,師爺整理好,再把它畫出來。
今天讓我們「一起說畫」:你們說,平安來畫。
一場大約 8 分鐘,在一條連線裡做完(Day21):
| 步驟 | 誰說話 | 平安做什麼 |
|---|---|---|
| ① 開場 | 平安 | 叫大家的暱稱打招呼,說今天的日期 |
| ② 選主題 | 平安 | 先問二選一,例如:要畫以前的家,還是最喜歡去的地方? |
| ③ 說內容 | 長輩、家人 | 問誰、在哪裡、在做什麼、什麼顏色 |
| ④ 整理確認 | 平安 | 三句以內說出目前的內容,問還需要修改嗎 |
| ⑤ 畫圖 | 平安 | 先問「要開始畫了嗎?」,有人說好才畫 |
| ⑥ 說畫裡的故事 | 長輩、家人 | 一次問一題,也請家人說說他們記得的 |
| ⑦ 修改 | 家人 | 最多改 2 次;圖畫好時,平安先溫柔地說明 |
| ⑧ 結尾 | 平安 | 說說今天的故事,祝大家平平安安 |


實測影片:
https://youtu.be/mrciCvjIrPg
App 為了回音消除,用通話模式播放平安的聲音;
這次用 iPhone 內建的螢幕錄影錄不到聲音,所以改用另一支手機拍。
喇叭放出平安的聲音,可能又被麥克風收回去;
Live 若把它當成有人在說話,平安就可能自己打斷自己。
所以收音和播放寫在同一個原生外掛裡,
讓系統的回音消除,拿得到平安的聲音當參考:
| 平台 | 做法 |
|---|---|
| iOS | AVAudioEngine 開 voice processing,平安的聲音從同一個引擎播 |
| Android | 麥克風用 VOICE_COMMUNICATION,播放用通話用途,切到通話模式 |
實機(iPhone)上做了三個測試:
| 測試 | 怎麼做 | 結果 |
|---|---|---|
| 平安說話時,大家不出聲 | 請它介紹三合院,說長一點 | 沒有自己打斷自己 |
| 平安說到一半,大聲叫它 | 說「平安,等一下」 | 停下來回應 |
| 手機音量開到最大 | 再做一次第一項 | 沒有自己打斷自己 |
這次實機上,平安沒有被自己的聲音打斷;說到一半叫它,它也聽得到。
實機上還有一個問題:開場和前幾句只有字幕、沒有聲音,
沒有按音量鍵,後面的回答就有聲音了。
把原生端的狀態印出來看:
[AUDIO] 啟動:輸出=Speaker、模式=AVAudioSessionModeVoiceChat
[AUDIO] 路由變更(原因 3):輸出=Speaker
[AUDIO] 路由變更(原因 8):輸出=Speaker
[AUDIO] 引擎設定變更,重新啟動:輸出=Speaker
[DRAW] 收到平安的第一段聲音
[DRAW] 開始播平安的聲音
修法:引擎設定變更之後,把播放器重設、重新接線再啟動;
每次播放前,也先確認引擎和播放器真的在跑。
修改之後,實機開場就有聲音了。
Day21 定了通則,今天加上一起說畫的段落,
一樣由 Cloud Functions 組好、鎖進權杖。
節錄:
# 今天的活動:一起說畫
目標:讓{長輩暱稱}多說,和家人一起決定要畫什麼。
畫得像不像不重要,大家一起說「畫」最重要。
# 流程(一步完成,才到下一步)
1. 開場(照通則)。
2. 開場後的第一個問題就用二選一。
3. 請{長輩暱稱}說畫裡要有什麼:誰、在哪裡、
在做什麼、什麼顏色、什麼天氣;也請家人補充。
4. 大家安靜下來,或收到「[App] 家人按了整理重點」:
用三句以內說出目前的內容,
再問「還需要修改內容嗎?」
5. 修改:照大家說的改,再整理一次。
6. 問大家「要開始畫了嗎?」問完就停下來等。
有人說好,或收到「[App] 家人按了開始畫」,
才呼叫 draw_picture。
7. 等圖的時候:不說話。
還沒收到 draw_picture 的結果,不要說「畫好了」。
8. 收到結果:說「畫好了,大家看看!
想改的地方也可以跟我說,最多可以改兩次喔。」
9. 說畫裡的故事:一次問一題;也請家人說說他們記得的。
10. 想修改:先複述要改的地方,有人說好
才呼叫 edit_picture;最多改兩次。
11. 結尾(照通則),提醒大家可以把畫存起來。
# 什麼時候結束
- 只有收到「[App] 請收尾」,或家人說「結束」,才結尾。
- 大家說「好漂亮」,是在稱讚這張畫,不是要結束:
先謝謝大家,再問一個畫裡的故事。
# 護欄
- 不畫可怕、暴力、裸露、歧視的內容,也不畫真實名人。
- 畫裡不放文字。
守則不是一次寫好的,每跑一場就改一次:
| 實測看到的 | 怎麼改 |
|---|---|
| Day21 有一場長輩停 3 秒,平安把「(安靜等待阿嬤慢慢說)」念了出來 | 通則的「安靜等,不催」改成「不出聲,等他說完再接話」,再加上「不要說括號裡的動作或旁白」 |
| 開場問「今天想跟我們聊聊什麼呢?」 | 開場後的第一個問題就用二選一 |
| 家人一說要改,平安沒有複述就修圖 | 先複述要改的地方 |
| 改完一次圖、長輩說「好漂亮」,平安就說再見 | 加上「什麼時候結束」 |
| 收到「[App] 剩下兩分鐘」,平安就結束活動 | 通則改成「提醒還有兩分鐘,這時還不要結尾」;實機再測,平安提醒大家分享,到第 8 分鐘才結尾 |
| 實機上,大家還在補充內容,平安就自己去畫了 | 最終確認改成問句「要開始畫了嗎?」,問完先停下來等(App 也會擋) |
| 家人在問阿嬤問題時,平安說了一句英文:「The user is chatting with the elder. I will wait for them to finish.」 | 通則加上「決定不開口的時候,就完全不出聲:不要說出你在等……也不要說英文」 |
| 實機上一直聊別的(請它介紹三合院),平安沒有帶回畫畫;到「剩下兩分鐘」還沒畫,就直接請大家分享 | 守則加上「帶回畫畫」;App 第 4 分鐘還沒畫圖就提醒,第 6 分鐘改送「剩下兩分鐘,還沒畫圖」;實機再測,平安會把話題帶回畫畫 |
| 家人說「等一下」,平安就一直等到活動結束,沒有畫 | 剩下三分鐘還沒畫圖,平安要明講:時間到還沒說「開始畫」或按「開始畫」,今天就畫不出來(還沒驗證) |
守則之外,Live API 的設定也由 Cloud Functions 組好、一起鎖進權杖(Day21),
App 連線時只送模型名稱。一起說畫調了這幾個:
const config = {
responseModalities: ["AUDIO"],
// 平安的聲音
speechConfig: {
voiceConfig: {prebuiltVoiceConfig: {voiceName: "Autonoe"}},
},
systemInstruction: buildSystemInstruction(session),
// 平安說的話轉成字幕
outputAudioTranscription: {},
// 畫圖、修圖、結束活動(第四節)
tools: [{functionDeclarations: TOOLS.draw}],
// 停頓 2 秒才算說完(Day21)
realtimeInputConfig: {automaticActivityDetection: {
endOfSpeechSensitivity: "END_SENSITIVITY_LOW",
silenceDurationMs: 2000,
}},
};
| 設定 | 為什麼這樣設 |
|---|---|
聲音 |
在 AI Studio 試聽,Autonoe 跟其他聲音比起來,比較像台灣口音 |
字幕 |
只轉平安說的話;轉錄另外計費(第六節) |
實機測了三場,我用台語回答,平安的反應不穩定,看起來不太聽得懂;
Live API 官方列出的 99 種語言裡,沒有台語。
其他可以調整的參數:
- 情感對話、主動音訊、思考深度(依模型而定):Live API 功能
- 連線斷掉之後續接:工作階段管理
- 30 種預設聲音:語音生成
Live API 也有函式呼叫(function calling):
官方說明,它讓 Live API 可以跟外部的資料和程式互動。
做法是先在連線設定裡宣告函式;
即時對話進行到一半,平安決定呼叫時,App 會收到 toolCall,
執行完再把結果回覆給 Live,平安接著聊。一起說畫就是這樣畫圖:大家同意開始畫,平安就呼叫 draw_picture。
一起說畫有兩個工具,跟 Day21 的 end_activity 一樣鎖在權杖上:
const DRAW_PICTURE = {
name: "draw_picture",
description: "把大家確認好的內容畫成一張圖。" +
"Invocation Condition: 只在你問過「要開始畫了嗎?」" +
"而且有人明確同意(或收到「[App] 家人按了開始畫」)" +
"之後呼叫;大家還在補充內容時不要呼叫;" +
"「可以再修改嗎?」這類問句或想再改的話,不是同意;" +
"一次活動只呼叫一次。",
parameters: {
type: Type.OBJECT,
properties: {
prompt: {type: Type.STRING,
description: "畫的內容,繁體中文"},
title: {type: Type.STRING,
description: "這張畫的標題,10 個字以內"},
summary: {type: Type.STRING,
description: "一句話說明畫的內容"},
},
required: ["prompt", "title", "summary"],
},
};
官方建議在描述裡寫清楚什麼時候該呼叫(Invocation Condition)。
| 順序 | 誰送 | 內容 |
|---|---|---|
| ① | Live | toolCall:draw_picture,附上提示詞、標題、一句說明 |
| ② | App | 呼叫 Cloud Functions 的 drawPicture |
| ③ | Cloud Functions | 請 Nano Banana 畫圖,把圖傳回 App |
| ④ | App | 顯示圖,回覆 toolResponse:「畫好了」 |
| ⑤ | Live | 平安:「畫好了,大家看看!」 |
實測時,平安自己寫的提示詞:
夏天傍晚,鄉下的紅色屋頂瓦片房子,門口有一隻黃色的小狗坐在那裡,
房子旁邊是一大片綠色的稻田,前面有一棵巨大茂盛的榕樹。
大家說過的內容,平安會自己整理成畫圖的提示詞。
上一節,平安在對話中呼叫了 draw_picture;
收到之後,App 要真的把圖畫出來。
App 不直接找 Nano Banana,而是先呼叫 Cloud Functions,
由 Cloud Functions 帶著 API 金鑰去畫,再把圖傳回 App。
Day21 的暫時性權杖,目前只能用在 Live API;
畫圖要用 API 金鑰,金鑰不能放進 App。
所以畫圖跟 Day15 一樣:
App 呼叫 Cloud Functions(有 App Check 把關),由它帶著金鑰去畫。
Day15 在 Cloud Functions 呼叫 Gemini,用的是 generateContent;
這次畫圖改用 Interactions API。
官方說明,
Interactions API 是呼叫 Gemini 的新標準介面,
2026 年 6 月已經是正式版(GA),建議新專案使用;
之後的新模型、新功能,也都會在 Interactions API 推出。
原本的 generateContent 列為舊版,但仍然完整支援。
它也能在伺服器上記住對話:預設會保存每一次的請求,付費層 55 天、免費層 1 天;下一輪帶上前一輪的 ID(previous_interaction_id),就能接著聊。
一起說畫聊的是家裡的回憶,所以設成 store: false,不保存。
const interaction = await ai.interactions.create({
model: "gemini-3.1-flash-image",
input: job.input,
// 不保存這次的請求和回應
store: false,
response_format: {
type: "image",
mime_type: "image/jpeg",
aspect_ratio: "1:1",
image_size: "1K",
},
});
const image = interaction.output_image;
補充:response_format 還可以選解析度(512px~4K)、
長寬比(例如 3:4、16:9),也能接 Google 搜尋、放最多 14 張參考圖,見圖片生成。
設成 store: false,就不能用 previous_interaction_id 接著上一輪改圖;
修圖時,App 要把上一張圖一起送回去:
// store: false 不能接著上一輪,上一張圖跟修改意見一起送
const input = [
{type: "text", text: `${EDIT_STYLE}\n修改:${instruction}`},
{type: "image", mime_type: "image/jpeg", data: previous},
];
兩個模型的速度、價格,Day19 在 AI Studio 比過;
這次要看的是:同一張圖連續改兩次。
官方說明,2 Lite 沒有針對多輪連續修圖最佳化。
同一段提示詞,兩個模型各畫一張,再照同樣的意見改兩次:
| 比較 | Nano Banana 2 Lite | Nano Banana 2 |
|---|---|---|
| 每張(經 Cloud Functions) | 4.1~4.9 秒 | 9.9~10.8 秒 |
| 改第 1 次:天空改成黃昏的橘紅色 | 整張圖都變成橘色 | 只有天空變色 |
| 改第 2 次:小狗坐到阿嬤的腳邊 | 小狗移到孫女前面 | 小狗坐到阿嬤腳邊 |
| 價格頁換算(1K 一張) | 約 0.034 美元 | 約 0.067 美元 |

一起說畫用 Nano Banana 2:改的範圍,比較接近大家描述的。
2 Lite 比較快、比較便宜,只畫一次、不用修圖的地方很適合。
Live 每一輪,都會回報這一輪的用量(usageMetadata)。
第 4 場(連線 8 分 14 秒)的幾個時間點:
| 輪 | 第幾秒 | 文字輸入 | 聲音輸入 | 這一輪約 |
|---|---|---|---|---|
| 1 | 8.8 | 2,460 | 222 | 0.008 美元 |
| 5 | 45.0 | 2,593 | 1,134 | 0.008 美元 |
| 10 | 83.6 | 2,766 | 1,624 | 0.009 美元 |
| 17 | 378.8 | 3,000 | 2,894 | 0.012 美元 |
這就是 Day20 引用的官方說明:每一輪都會把前面的對話一起計算。
官方說明,開了轉錄,轉出來的文字另外計費。
App 只顯示平安的字幕,所以只轉平安說的話,長輩說的話不轉(Day21 兩邊都轉)。
| 項目 | 第 4 場(腳本) | 實機一場 |
|---|---|---|
| Live | 17 輪,約 0.15 美元 | 38 輪,約 0.80 美元 |
| 畫圖 | 畫 1 張+改 1 次,約 0.13 美元 | 畫 1 張,約 0.07 美元 |
| 估計合計 | 約 0.29 美元 | 約 0.87 美元 |
Live 用 usageMetadata 照價格頁換算;
畫圖照價格頁,Nano Banana 2 一張約 0.067 美元。
腳本測試時,畫圖和聊天的錢差不多;實機時,聊天的錢多了很多。
實機那場有 38 輪,每一輪重算的對話,從 3,710 token 漲到 14,720 token。
跑第 4 場的前後,各截一次 AI Studio 的 Spend 頁,
這段時間沒有其他人用這個專案:

| Spend | 金額 |
|---|---|
| 跑之前 | NT$156.78 |
| 跑完、等帳單更新之後 | NT$166.53 |
| 增加 | NT$9.75 |
照 Day19 的換算(250 美元=NT$7,945),NT$9.75 約 0.31 美元,
比估計的 0.29 美元多一點。
估計裡沒有算到的:最後收尾那一輪(連線結束前沒收到用量),
還有轉錄出來的文字。
我在 AI Studio 設了每月上限 NT$300。
實機又跑了幾場,22:40 的 Spend 是 NT$303.20,超過上限一點:

這時再開一場,權杖照常拿得到;
連上 Live 時,伺服器用代碼 1011 關掉連線:
Your project has exceeded its monthly spending cap.
App 等了 15 秒逾時,畫面上看起來像沒有反應。
把上限調高到 NT$400 之後,又可以正常跑。

你們說,師爺來畫;畫完,換大家說說畫中的回憶與故事。
明天是第二個活動:時光寶盒。我們的好時光、家中尋寶:一起看照片、一起找寶物。
感謝有緣看到這邊的你~
希望佛菩薩也祝福你:🌟開心自在 平安健康🌟
南無觀世音菩薩🍀 南無地藏菩薩🏠 南無阿彌陀佛☀️