October
15th,
2026
前情提要 我有一個自己每天在用的 LINE Bot,linebot-helper-python。日常拿來丟網址回摘要、丟 YouTube 連結針對影片內容追問、查地圖景點跟管書籤。在模型配置上,為了平衡回應速度與荷包,許多工作流先前陸續跑在 Gemini 3.5(像是負責高吞吐、低延遲分類與資料擷取的 gemini-3.5-flash-lite)以及 Gemini 3.6(負責多步驟工具呼叫與多模態推理的 gemini-3.6-flash)上。 十月中 Google 正式把 Gemini 4 Argon (gemini-4-argon) 推上 GA 穩定版(搭配 Python google-genai >= 2.30.1)。 看完官方公告與遷移文件,表面上最吸引人的是那些大數字:輸入、思考與輸出共用的 1M 統一 Token 視窗、單次呼叫自動接力跑到 100 萬輸出 Token 的 Long Decode、正式 GA 且省下 88% Token 的 Agentic Video Understanding,還有已經成為預設主流的 Interactions API (/v1beta/interactions)。 但如果你的目標跟我一樣,是想把現有 LINE Bot 裡面的 Gemini 3.5 / 3.6 升級(或部分切換)到 Gemini 4 Argon,千萬不要以為只是把 model="gemini-3.6-flash" 改成 model="gemini-4-argon" 就收工了。 這一代在參數規範、Token 預算計算方式、快取機制,甚至等待時間的假設上,都有幾個剛好打在 LINE Bot 痛點上的改變。這篇把從 3.5 / 3.6 轉移到 Gemini 4 需要注意的細節全部整理起來。 先看規格對照:3.5 Flash-Lite / 3.6 Flash vs. Gemini 4 Argon 在動手改設定之前,先把這三顆模型放在同一張表上看清楚它們的定位差異: 項目 gemini-3.5-flash-lite gemini-3.6-flash gemini-4-argon 定位 極速、低成本、高吞吐分類與結構化萃取 速度與多步驟 Agent / 多模態平衡 旗艦深度推理、複雜寫扣、長輸出與自主代理 Context Window 1,048,576 1,048,576 1,048,576(Input + Thinking + Output 共用) 單次最大輸出 65,536 65,536 generateContent:非串流 32,768 / 串流 65,536Interactions API:同步 65,536(Long Decode 最高皆可接續至 1M) 預設 thinking_level "minimal" "medium" "medium"(僅支援 low / medium / high) Context Caching 支援 支援 僅支援 Implicit Caching(呼叫 Explicit 會報錯) temperature / top_p / top_k 已棄用(忽略) 已棄用(忽略) 已棄用(忽略,官方要求移除) 定價 (Input /...
繼續閱讀
September
27th,
2026
前情提要 第一篇我用 Gemini 3.8 Flash TTS 做了 Song Lingo:貼 YouTube MV 網址,Gemini 轉錄歌詞、加上拼音翻譯文法,再由一位用 voice design 設計的老師逐句示範發音。第二篇把它部署到 Cloud Run,用 IAP 鎖到只有我自己能用。 部署完我在 GitHub 開了一份 roadmap,排了三件事:手機版面、跟讀評分、單字卡。手機版面已經做完了,這篇講的是第二件。 老師會示範,但我一直不知道自己念得對不對。聽十遍老師念,不如自己念一遍、被指出哪裡錯。這是 Song Lingo 從「聽歌看歌詞」變成「練發音」的關鍵一步。 Gemini 3.5 Transcribe 是什麼 Google 在 8/26 發布了 Gemini 3.5 Transcribe,是兩個專門做語音轉文字的模型: 模型 用途 gemini-3.5-transcribe 錄好的音檔,整段送出轉錄 gemini-3.5-transcribe-live 透過 Live API 的 WebSocket 即時串流,一邊講一邊出字 幾個重點功能: 85 種以上語言,會自動偵測,也能處理講到一半換語言的情況。 逐字時間戳:每個詞都有開始和結束時間(整段轉錄的版本才有)。 講者分辨:標出每句話是誰講的。 自訂詞彙:最多 1,000 個專有名詞,提高特殊用語的辨識率。 兩種模式:smart 會處理說話時的自我修正、拿掉語助詞、自動排版;verbatim 則是逐字照實轉錄。 官方部落格引用 Artificial Analysis 的測量:整段轉錄的平均字錯誤率(WER)2.6%,串流版 4.0%;和前一代 Chirp 3 比,拿到最終轉錄結果的時間快了 70%。價格沒有公布。 實際呼叫的方式和 TTS 一樣走 interactions API,但音檔要先用 Files API 上傳: uploaded = client.files.upload(file=audio_path, config={"mime_type": "audio/m4a"}) interaction = client.interactions.create( model="gemini-3.5-transcribe", input=[{"type": "audio", "uri": uploaded.uri, "mime_type": uploaded.mime_type}], generation_config={ "transcription_config": { "language_codes": ["ja-JP"], "mode": {"type": "verbatim", "timestamp_granularities": ["word"]}, } }, ) 支援的格式很多,其中 audio/webm 剛好是 Chrome 錄音的格式,audio/m4a 則對應 iPhone Safari 錄出來的 AAC。 選哪個模型 做跟讀評分,其實有三個候選: 模型 適合 用在跟讀 gemini-3.5-transcribe 錄完整段再轉錄 ✅ 有逐字時間戳,實測約 5 秒回來 gemini-3.5-transcribe-live 即時串流 一句歌詞只有幾秒,等念完再轉錄就夠了;要在 Cloud Run 和 IAP 後面維持 WebSocket 也麻煩得多 gemini-3.8-flash 這類多模態模型 直接聽錄音給文字講評 結果每次不一定一樣,也沒有保證的逐字時間戳,不適合當評分的主體 最後選了 gemini-3.5-transcribe。專門的語音轉文字模型,結果穩定,有逐字資訊,而且每次只用大約 40 個 token,不占 TTS 那每天 100 次的額度。...
繼續閱讀
September
26th,
2026
前情提要 上一篇我用 Gemini 3.8 Flash TTS 做了 Song Lingo:貼 YouTube MV 網址,Gemini 轉錄歌詞、加上拼音翻譯文法,再由一位用 voice design 設計出來的老師一句一句念給你聽。 它一直只跑在我自己的電腦上,但我希望拿起手機就能用。所以這篇要做的事很單純:把它搬上 Cloud Run,讓手機也能用。 但這個網站有一個特殊的地方:頁面上是完整的歌詞和翻譯。 需求:「只有我看得到」要多準確 一般的 side project 部署上去,被別人看到頂多有點尷尬。Song Lingo 不一樣,公開有兩個實際的後果: 版權:上一篇花了一整節講,這是個人學習工具,歌詞只存在我自己的電腦。網站一旦公開,性質就從「個人學習」變成「對外提供歌詞」。 費用:加一首歌會呼叫 Gemini Flash,第一次播放示範音會呼叫 TTS。任何人都能用,就等於任何人都能花我的額度。 所以目標不是「有登入功能」,而是從頭到尾每一層都確認過,只有我的帳號能碰到歌詞和 API。 我先比較了兩個方案: A. IAP + 程式內驗證 B. 不開放外部,用 gcloud run services proxy 能用的裝置 任何瀏覽器,包含手機 只有登入 gcloud 的電腦 設定難度 中等 低 出錯的可能 低 最低,根本沒有公開入口 B 是最安全的,但手機不能用,而手機正是這次部署的理由。所以選 A。 第一版設計的漏洞:簽署網址 我最初的規劃是這樣:音檔放 GCS,播放時由 API 產生一個短時效的簽署網址(signed URL),把瀏覽器重新導向過去。好處是音檔不經過 Cloud Run,省流量,GCS 本身也支援 Range 請求。 寫到一半重新想「怎樣才能準確地只有我看得到」時,才發現這是一個漏洞: 簽署網址在有效期限內,任何拿到網址的人都能直接下載,完全不經過 IAP。 它本質上是一張不記名的通行證。網址出現在瀏覽器歷史、被貼到哪裡、被某個擴充功能記下來,別人就能繞過前面所有的登入檢查。 原因與解法:「只有我能存取」是一整條鏈,強度取決於最弱的那一環。最後的做法是不使用簽署網址,音檔一律由 Cloud Run 讀出來再送給瀏覽器,每一次播放都要先通過 IAP 和程式內的驗證。一段音檔 250KB 左右,多繞一段路的流量成本可以忽略。 架構 部分 做法 容器 一個映像同時裝 Node 22 和 uv/Python,Next.js 直接呼叫原本的 Python 腳本 歌曲資料與音檔 私人的 Cloud Storage bucket,掛載成 /data 資料夾 API key Secret Manager,以環境變數提供 存取控制 IAP + 程式內驗證 IAP 的簽章 執行個體 最多 1 個,最少 0 個;CPU 持續分配 幾個決定的理由: 把 bucket 掛載成資料夾,而不是改寫成呼叫 GCS API。程式原本就是讀寫 output/ 資料夾,掛載之後只要把 SONG_DATA_DIR 指到 /data,幾乎不用改程式。 只跑 1 個執行個體。避免重複產生音檔、額度用完時暫停呼叫、加入新歌的進度,這些狀態都存在記憶體裡;掛載的 bucket 也沒有跨執行個體的鎖定。個人使用,1 個就夠,而且這樣上一篇那些防止重複計費的機制才會有效。 CPU 持續分配(--no-cpu-throttling)。「加入新歌」是在回應送出後繼續在背景跑轉錄和分析的,Cloud Run 預設會在回應送出後限制 CPU,背景工作會卡住。 四層防護 最後的存取控制是四層,任何一層單獨出錯,其他層還是擋得住: Cloud Run 權限:--no-allow-unauthenticated,只有 IAP 的服務帳號能呼叫這個服務。 IAP:只有被授予 roles/iap.httpsResourceAccessor...
繼續閱讀
September
25th,
2026
前情提要 每次看到 Gemini 出新功能,我第一個念頭都是「能不能接進我的 LINE Bot」。 9/22 的 Gemini API release notes 寫著 Gemini 3.8 Flash TTS 與 Gemini 3.8 Flash-Lite TTS 正式推出(GA),官方部落格同步發了 Gemini 3.8 Flash TTS and Gemini 3.8 Flash-Lite TTS。我照慣例先列了一排 LINE Bot 點子:爸媽聲音的睡前故事、把群組聊天變成廣播劇、早晨雙主持人 podcast⋯⋯ 列到一半我發現,這次最打動我的其實不是 bot,而是「逐句導演語氣」這件事特別適合拿來教發音。於是題目改成一個 Web App: 選一首歌,拿到歌詞,同步翻成中文。 如果是日文、韓文,就附上拼音,然後變身語言老師,一句一句教你怎麼念。 變成一個「用歌曲學語言」的工具。 結果做下來,TTS 本身的品質沒什麼好挑的,真正花時間的是它周邊那些文件沒寫的事。 Gemini 3.8 Flash TTS 是什麼 這次 GA 的是兩個模型: 模型 定位 gemini-3.8-flash-tts 旗艦款,重視聲音表現與角色塑造,可以逐句控制演出 gemini-3.8-flash-lite-tts 便宜、快,適合大量產生 跟前一代比,多了三個我覺得真正有用的東西: Voice design:用一段文字描述生出一個聲音,例如「一位 60 多歲、帶英國腔、語氣溫暖的天文學家」。生出來的聲音會拿到一個 voice_id,之後重複使用。 Voice replication:用 10–30 秒的錄音複製一個人的聲音。前提是聲音主人要親口錄一段同意聲明,產出的語音也會帶 SynthID 浮水印與 C2PA 標記。 逐句的演出控制:每一段文字都能附一個 style(例如「慢慢念、每個音節都念清楚」),也支援 <laughs>、<sigh> 這類標籤,以及最多兩人的對話。 實際呼叫的長相,跟過去的 generate_content 不一樣,改走 interactions 與 voices 兩組 API: # 用文字描述設計一個聲音(一次性,存起來重複用) voice = client.voices.create( store=True, voice={ "model": "gemini-3.8-flash-tts", "type": "prompted", "display_name": "Song Lingo Japanese Teacher", "gender": "female", "language_code": "ja-JP", "prompted": {"input": "A warm, patient Japanese language teacher in her early 30s from Tokyo..."}, }, ) # 用這個聲音念一句話,style 控制語氣與速度 interaction = client.interactions.create( model="gemini-3.8-flash-tts", input=[{ "type": "user_input", "content": [{ "type": "text", "text": "こんにちは。今日はいい天気ですね。", "annotations": [{"type": "speech_metadata", "style": "speaking slowly and clearly"}], }], }], response_format={"type": "audio"}, generation_config={"speech_config":...
繼續閱讀
September
15th,
2026
前情提要 我有一個自己每天在用的 LINE Bot,linebot-helper-python。丟網址回摘要跟社群文案,丟 YouTube 連結可以針對影片連續追問,還有書籤、地點查詢那些。其中一個功能是 LIFF 語音助理:開一個網頁,用 WebSocket 接 Gemini Live API,可以按住說話或免持對話,講完的內容會整理成一則訊息推回 LINE 聊天室。 九月中 Google 發了 Gemini 3.8 Live,看完之後我想做的事情,跟公告想賣的東西不太一樣。 公告在講能力:Speech to Speech Index 排第一(82.6 分)、Big Bench Audio 97.7%、97 種語言自動偵測且可以在對話中途切換、工具呼叫可以在背景執行而不中斷對話流、即時視覺輸入。還有一顆 Gemini 3.8 Live Extended Thinking,能一邊推理一邊出聲。 我第一個念頭是:這下我可以把那個 preview 例外拔掉了。 真正的動機:一個 preview 模型埋了兩次雷 上一篇寫 agentic video 的時候提過一件事:我的智慧對話功能壞了整段時間,沒有人發現。原因是 loader/chat_session.py 寫死了 gemini-3-pro-preview,那個模型從 Vertex AI 下架之後,真實路徑直接回 404,而那個檔案的例外處理是直接 raise。 修完之後我加了一組守衛,用測試強制「模型 ID 只能出現在 config/agent_config.py」「不准使用 preview 或實驗模型」。但那組守衛有兩個例外: # Live API 僅支援 gemini-3.1-flash-live-preview;TTS 是獨立模型家族。 # 這兩處必須維持 preview 模型,不在守衛範圍內。 EXEMPT_FILES = {"services/voice_live.py", "tools/tts_tool.py"} 語音那個例外的理由是「Live API 只有這一顆模型能用」。當時是真的。但那句話一旦寫進註解,就沒有人會再去查它還成不成立——同一類 bug 的最後一個缺口,就這樣光明正大掛在那裡好幾個月。 3.8 Live 的意義因此不只是能力升級。它的模型名稱不含 -preview,這代表那個例外可以縮掉。 先問 API,不要問文件 這次我沒有先讀文件,而是直接問 API 上實際存在哪些東西: curl -s "https://generativelanguage.googleapis.com/v1beta/models?key=$KEY&pageSize=200" \ | jq -r '.models[]?.name' | rg -i 'live' models/gemini-3.5-transcribe-live models/gemini-3.1-flash-live-preview models/gemini-3.8-live models/gemini-3.8-live-extended-thinking models/gemini-3.5-live-translate-preview 一行指令拿到五個確定存在的模型名稱,比在文件裡翻半天可靠。gemini-3.8-live 就在上面,名字乾淨。 順帶還撿到一個我本來不知道的 gemini-3.5-live-translate-preview。我原本在想「要不要做即時口譯模式」,看來那是一顆專門的模型,不是拿通用模型硬幹。這個之後再說。 再往下問 metadata: 3.1-flash-live-preview 3.8-live inputTokenLimit 131072 131072 outputTokenLimit 65536 65536 supportedGenerationMethods bidiGenerateContent bidiGenerateContent 數字一模一樣。到這裡我對「可以無痛換」有了初步信心,但這還只是 metadata,不是行為。 踩坑一:我警告了一個不存在的風險 我第一次評估這件事的時候,很嚴肅地提醒了一句:「公告沒提到 Vertex AI,而這個專案的決策是全面改用 Vertex,所以 3.8 Live 不確定拿不拿得到。」 聽起來很專業。然後我去翻自己的程式碼: client = live_genai.Client( api_key=GOOGLE_AI_API_KEY, vertexai=False, http_options={"api_version": "v1beta"}, ) vertexai=False。語音這條路徑從一開始就是走 Gemini API 加 AI Studio 的金鑰,根本不走 Vertex——而...
繼續閱讀
September
14th,
2026
最近翻 Google Cloud 的開發環境設定文件, 在一堆 gcloud CLI、Cloud Shell、Cloud Workstations 中間,多了一段以前沒有的東西: agy plugin install https://github.com/google/skills/plugins/cloud/google-cloud-developer agy 是 Google Antigravity CLI。但真正讓我停下來的不是這個新 CLI,而是後面那串網址: Google 開始把自家的產品知識,包成 agent plugin 放在 GitHub 上發佈。 結果我打開自己的 Claude Code 一看,這個 plugin 早就裝在機器上了。所以這篇不用先裝 Antigravity CLI, 直接拿現成的來實測,看看它到底做了什麼。 這個 plugin 裡面裝了什麼 先把它拆開看。整包其實不大,5 個 skill、1 份路由規則、1 個 MCP server,全部加起來 1549 行 markdown,沒有任何程式碼: skills/gcloud/ # gcloud 指令的安全護欄與語法驗證(272 行 + 340 行參考文件) skills/retrieving-developer-knowledge/ # 查官方文件(103 行 + 182 行參考文件) skills/finding-google-skills/ # 按需從遠端目錄撈技能(134 行) skills/google-cloud-recipe-onboarding/ # 新手開第一個專案(228 行) skills/google-cloud-recipe-auth/ # 憑證與 ADC 選擇(260 行) rules/google-cloud-discovery.md # 技能路由表(30 行) 有趣的是同一個目錄底下塞了四套 manifest: .claude-plugin/plugin.json # Claude Code .codex-plugin/plugin.json # Codex gemini-extension.json # Gemini CLI / Antigravity plugin.json # 通用格式 那份通用的 plugin.json 開頭是這樣: { "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "google-cloud-developer", "version": "1.1.2", "author": { "name": "Google LLC" }, "license": "Apache-2.0" } agent-plugins.org 是個跨工具的 plugin schema。Google 沒有為自己的 Antigravity 做一份專屬格式, 而是同一包東西讓四種 agent 都吃得下去。換句話說,你不裝 Antigravity CLI 也用得到這包東西。 安裝:三條路挑一條 Antigravity CLI(文件上寫的) agy plugin install https://github.com/google/skills/plugins/cloud/google-cloud-developer Claude Code claude plugin marketplace add google/skills claude plugin install google-cloud-developer@google-plugins...
繼續閱讀