June
20th,
2026
緣起:聊天打到一半,那張梗圖到底在哪? 每個重度聊天的人手機與電腦裡都存了一堆迷因圖,但真正要用的時候——對話進行到一半、想丟一張「謝謝再聯絡」或「我就爛」——卻怎麼也翻不到。檔名是 IMG_4821.jpg,相簿沒有分類,搜尋更是無從下手。 我先看到一個很棒的開源專案 ShiQu1218/MemeTalk,它用 Python + Streamlit + SQLite 打造了一套本地迷因語意搜尋系統,會掃描你本機的迷因資料夾、用 OCR 與向量嵌入建立索引,再做多路召回。功能完整,但偏研究取向、要開瀏覽器跑 Streamlit。 我想要的是更貼近「日常順手工具」的東西: 一個原生 Mac App,一個搜尋框,打我想找的內容,就跳出相關的梗圖,點一下直接複製到剪貼簿。 於是有了 MemeFinder。這篇文章紀錄它從零到「選單列常駐 + 全域快捷鍵」的開發過程,以及途中幾個很有代表性的坑。 系統設計與架構 核心概念很單純:指定一個本機迷因資料夾 → 用 Gemini 幫每張圖建立索引 → 打字做語意搜尋 → 點圖複製。 技術選型上我做了三個關鍵決定: 原生 SwiftUI App,而不是 Electron。剪貼簿複製圖片、全域快捷鍵、選單列常駐,這些用 AppKit 都是一級公民。 Gemini 負責兩件事:用視覺模型 gemini-3-flash-preview 讀出圖中文字、生成繁中描述與情緒標籤;用 gemini-embedding-2 把這些語意轉成 768 維向量。 語意向量 + 關鍵字混合搜尋。純關鍵字對中文召回太差;語意向量才能做到「打相關敘述就找到圖」。 系統架構流向 graph TD A[使用者指定迷因資料夾] -->|掃描 jpg/png/webp| B[Indexer 索引器] B -->|每張圖| C[Gemini 視覺模型 gemini-3-flash-preview] C -->|OCR文字 + 描述 + 標籤 + 情緒| D[Gemini 嵌入 gemini-embedding-2] D -->|768 維向量| E[本機索引檔 index.json] F[使用者打字查詢] -->|⌃⌘M 選單列浮窗| G[Gemini 嵌入查詢字串] G -->|cosine 相似度 + 關鍵字加權| E E -->|排序結果| H[縮圖牆] H -->|點圖| I[NSPasteboard 複製到剪貼簿] 整個專案刻意拆成兩個 Swift Package target: Target 類型 內容 MemeFinder library 邏輯、模型、服務、ViewModel(全部有單元測試) MemeFinderApp executable SwiftUI 畫面 + 選單列殼(薄殼,依賴上面的函式庫) 這個拆分不是裝飾——它直接決定了測試能不能順利跑,後面「踩坑二」會講到為什麼。 核心實作 1. 用 Gemini 視覺模型自動標註迷因圖 索引時,每張圖會送進視覺模型,要求它只輸出 JSON:圖中文字、繁中描述、標籤、情緒。responseMimeType 設成 application/json 來穩定輸出格式: public static func annotateRequest(apiKey: String, imageData: Data, mimeType: String) -> URLRequest { let prompt = """ 你是迷因圖標註助手。請閱讀這張圖,輸出 JSON,欄位: ocr_text(圖中所有文字), description(用繁體中文描述畫面與梗), tags(3-8 個繁體中文關鍵字陣列), emotion(單一情緒詞)。只輸出 JSON。 """ let...
繼續閱讀
June
13th,
2026
異步處理的利器:Gemini Batch API & Webhooks 在開發基於 LLM 的應用程式時,我們常常需要處理大量的數據分析任務——例如一次性分析數十家餐廳的評論、對大量文章進行分類、或是批次生成翻譯。如果採用傳統的同步 API(即時呼叫),不僅會面臨嚴重的 Rate Limit (速率限制) 阻塞,更會因為網路連線逾時(Timeout)與極高的運算成本而宣告失敗。 為了打破這個限制,Google 推出了 Gemini Batch API 與 Webhook API: Gemini Batch API:允許開發者將大量的請求打包成一個 JSONL 檔案一次性上傳。Gemini 會在後台進行非同步的排程運算,不佔用您日常的即時 API 額度(Rate Limits),且其運算成本通常只有即時 API 的一半,是處理非緊急大數據的完美選擇。 Webhook API:傳統的 Batch 任務需要我們在本機不斷寫輪詢(Polling)去檢查狀態。而透過 Webhook,當 Gemini 完成 Batch 運算後,會主動向您指定的 URL 發送一個 HTTP POST 回呼,即時通知任務已完成,讓系統架構變得更加優雅與節能。 這篇文章將紀錄我們如何將這兩項強大的 API 整合進我們的 LINE Bot 餐廳分析助手,實現在行動端一鍵對特定餐廳進行深度評論與招牌菜大數據分析的開發經歷。 系統設計與優化架構 原本的餐廳分析功能是當用戶發送位置時,Bot 會列出附近餐廳,並提供一個通用的「深度評論分析 (Batch)」按鈕,點下去會一次性把附近所有餐廳送去分析。然而這帶來了不好的 UX:分析所有餐廳耗時過長,且用戶往往只想針對他感興趣的某一家特定餐廳進行深挖。 因此,我們將功能優化為動態 Quick Reply 按鈕: 用戶傳送定位,Bot 透過 Google Maps Grounding 搜尋附近餐廳。 用戶端獲得餐廳純文字列表後,Bot 自動以 Gemini 擷取評分最高的前 3 家餐廳名稱。 產生 3 個客製化的 Quick Reply 按鈕(例如:🍴 分析 鼎泰豐)。 用戶點擊特定餐廳按鈕後,Bot 立即回覆「處理中」以避免 LINE 逾時,並在背景提交該單一餐廳的 Batch 任務,待 Gemini 運算完畢後主動推播專屬大數據報告。 系統架構流向 graph TD A[用戶傳送定位] -->|Location Message| B[Google Maps Grounding 搜尋] B -->|餐廳純文字列表| C[Gemini-2.5-flash 擷取前三名餐廳] C -->|動態生成 Quick Reply| D[LINE Bot 回覆 3 個客製化分析按鈕] D -->|用戶點擊特定分析| E[FastAPI Background Task] E -->|立即 Reply ACK| F[LINE 聊天室訊息] E -->|打包 JSONL 並上傳| G[Gemini Batch API 提交] G -->|運算完成 Webhook/Polling 回呼| H[主動 Push 深度報告給用戶] 核心實作 1. 使用 Gemini 從 Grounding 文字中精準提取餐廳名 在 tools/maps_tool.py 中,地圖搜尋返回的是一段富含格式與說明的純文字。我們使用 Gemini-2.5-flash 的...
繼續閱讀
June
12th,
2026
(活動:Google I/O Extended 2026 Taipei / 簡報:SpeakerDeck) 前情提要:Gemini API 已經不是「多打一個 prompt」而已 如果你對 Gemini API 的印象還停留在「選一個 model,送一段 prompt,拿回一段文字」,那你看到 2026 年這一輪更新時,很可能會突然意識到一件事: Gemini API 已經從單純的 API 介面,變成一個可以拿來搭應用、搭代理、搭非同步流程的完整平台。 這篇內容整理自我在 Google I/O Extended 2026 Taipei 的分享「在 Gemini API 家族中建構應用程式」。LINE 台灣開發者關係部技術總監 Evan Lin 在現場反覆強調的核心觀察是:開發者現在真正該思考的,不再只是 「我要用 Pro 還是 Flash?」,而是 「我要怎麼把模型、檢索、代理、回呼與成本控制串成一套系統?」。 換句話說,重點正在從 call API,轉向 design system。 先看全景圖:2026 Gemini API 家族到底多了什麼? 如果把 2026 年的 Gemini API 當成一張 capability map 來看,大致可以拆成三層。 第一層:核心模型 Gemini 3.5 Pro:最強推理能力,適合複雜規劃、進階分析與多步驟任務。 Gemini 3.5 Flash:主力模型,速度、成本與能力最平衡,適合多數產品流量。 Flash-Lite:高頻率、低成本場景的意圖判斷器與前置分類器。 Gemini Embedding 2:不只文本,也能支援多模態向量化需求。 第二層:關鍵能力模組 Retrieval:File Search、Google Search Grounding、URL Context。 Agent / Async:Agents API、Webhook、Deep Research agent。 Infrastructure:Context caching、Batch API、Live API。 第三層:系統設計方式 這一層反而最重要。因為當上面那幾個能力被做成平台服務之後,很多以前得自己補的「中間層」突然不見了: 不一定要自己搭一套 RAG pipeline。 不一定要自己養 agent loop。 不一定要用 polling 卡住主伺服器等結果。 核心觀察:Gemini API 的升級不只是「模型變強」,而是 Google 把原本屬於應用層的麻煩事,往平台層往下吃掉了。這會直接改變我們設計 AI 系統的方式。 架構轉折點:三個工具,三次思維切換 這場分享裡最值得反覆消化的,是這三個工具背後代表的架構變化。 1. File Search:從手刻 RAG,轉向 Managed RAG 以前講到企業知識問答,大家直覺就是: 切 chunk。 做 embedding。 存進 vector DB。 寫 retrieval code。 再自己補 citation 與權限控管。 現在 File Search 出現後,開發者可以把更多力氣放在「文件怎麼治理、權限怎麼分、回答怎麼呈現」,而不是一直重複寫那套基礎設施。 更重要的是,它不是只會查文字。 為什麼這次的 File Search 特別值得注意? 圖文同空間:PDF 裡的截圖、圖表、圖文混排,不再只是附件,而是模型可理解的內容。 Metadata 過濾:可以依部門、系統、文件類型做過濾,這對企業內部知識檢索非常重要。 精確引用:能回到具體頁數與 grounding metadata,讓回答更能被信任。 這代表一件很實際的事:很多企業過去花在 LangChain、向量庫與 chunking 策略上的時間,現在可以大幅往 權限設計、UX、內容治理 轉移。...
繼續閱讀
June
10th,
2026
寫在前面:開發者的全新協同模式 想像一下這個場景:你正在開發一個結合 macOS 底層音訊(CoreAudio/ScreenCaptureKit)與 Gemini Live API WebSocket 的即時會議翻譯 App。在測試階段,程式突然報錯閃退,且音訊串流出現全 0 的大靜音。 過去,你的排錯流程可能是: 打開終端機,撈出 log 檔案。 複製整段報錯與相關程式碼。 切換到瀏覽器,打開 AI 聊天視窗,貼上並詢問原因。 得到修改建議後,複製回編輯器,手動測試。 重複以上步驟,直到修復,然後手動寫 README.md、寫部落格、建立 GitHub 倉庫、提交代碼並推送。 而在這一次的開發中,我們採用了 Google DeepMind 設計的 AGY CLI (Antigravity-CLI) 代理人。我們驚訝地發現,上述所有繁瑣的上下文切換,都可以在終端機內透過與智慧代理的對話全自動完成。這篇文章將還原真實的 Prompt 對話流,分享我們如何與 AGY CLI 協作,從零打造出一個 macOS 會議翻譯 App。 階段一:靈感碰撞與架構設計 一切源自於一個開發想法與一份 Google 新釋出的 API 文件。開發者在終端機對 AGY CLI 貼上了網址,並拋出第一個核心問題: User: 跟著這個範例,可能打造出一個 Mac OS App 可以收取電腦裡面的聲音,然後即時翻譯成其他語言? 開始幫我思考該怎麼做,我主要目的是要可以拿來開會 zoom / google meet 直接翻譯其他國家的語言成繁體中文。 這邊有其他文件給你參考:https://ai.google.dev/gemini-api/docs/live-api/live-translate?hl=zh-tw 收到指令後,AGY CLI 發揮了架構師的角色,迅速分析並給出了一套 macOS 原生的解決方案: 不用安裝虛擬音效卡:推薦使用 Apple 在 macOS 13+ 推出的 ScreenCaptureKit 框架,直接以 Sandbox 安全模式擷取選定應用程式(如 Zoom 或 Chrome)的純淨音軌。 即時音訊重採樣:利用 AVAudioConverter 將多聲道/立體聲的 48kHz 音訊,實時重採樣為 Gemini Live 支援的 16kHz 單聲道 PCM 格式。 雙向 WebSocket 通訊:利用 Swift 的 URLSessionWebSocketTask 實作雙向長連接,一邊傳送 PCM 音訊塊,一邊接收繁體中文翻譯結果與播報音訊。 階段二:環境配置與編譯焦慮消除 在開始動手寫 Swift 代碼前,開發者對於 macOS 的編譯環境提出了疑問: User: 我是不是一定要有 xcode 才能 compile? User: 幫我跑 xcode-select –install 面對開發者的環境焦慮,AGY CLI 給出了解答: 雖然建立標準的 macOS SwiftUI GUI 應用程式包最好使用 Xcode,但我們並不一定需要手動開啟 Xcode IDE。 AGY CLI 協助撰寫了一個自動建置腳本 build_app.sh,直接調用終端機的 swiftc 命令列工具來編譯所有 .swift 原始檔,並自動打包成完整的 .app 目錄結構。 同時,對於開發者要求安裝 Command Line Tools 的請求,AGY CLI 主動呼叫了權限工具,直接在本地運行了 xcode-select --install,自動配置好 Swift 編譯環境。 階段三:連線排障與音訊...
繼續閱讀
June
9th,
2026
全新 API 亮相:Gemini 3.5 Live Translate 在 2026 年 6 月 9 日,Google 正式釋出了全新的語音即時翻譯模型 —— Gemini 3.5 Live Translate。這是 Google 在 AI 語音翻譯技術上的又一重大突破,目前已在 Google AI Studio、Gemini Live API 提供開發者公開預覽,並同步導入 Google Translate 與 Google Meet 等服務。 Gemini 3.5 Live Translate 的核心特點包括: 流暢自然的雙向語音翻譯:支援高達 70 種以上的語言,能自動偵測輸入語音的語言種類,不需人工設定。 連續串流生成(而非單句輪替):不同於以往必須等說話者完全說完才進行翻譯的 turn-by-turn 系統,Gemini 3.5 Live Translate 會一邊聆聽一邊實時生成翻譯,在上下文理解與即時性之間取得平衡,翻譯僅落後說話者數秒,完全避免了尷尬的停頓。 語調與節奏保留:生成的語音不僅通順,還能保留原說話者的語氣、抑揚頓挫與說話節奏。 強健的抗噪能力:在嘈雜或不穩定的環境下,依舊能準確擷取並辨識語音。 這篇文章將紀錄我們如何使用 Swift 開發一款 native macOS 應用程式 MeetingTranslator,串接這款強大的新 API,實現將特定 App 音訊即時翻譯為繁體中文語音與字幕的實戰經歷。 系統設計與架構 我們的目標是開發一款 Native SwiftUI 應用程式,它無須安裝像 BlackHole 這樣的虛擬音效卡,而是利用 Apple 官方的 ScreenCaptureKit 框架,直接擷取選定應用程式(如 Google Chrome 的 YouTube 或線上會議)的音訊流,並透過 Gemini Live WebSocket API,實現超低延遲的語音對話式翻譯。 系統架構流向 graph TD A[ScreenCaptureKit <br>擷取應用程式音訊] -->|48kHz Stereo Float32| B[AVAudioConverter <br>重採樣與聲道轉換] B -->|16kHz Mono Int16 PCM| C[Gemini Live API <br>WebSocket 連線] C -->|實時辨識字幕| D[SwiftUI Subtitle HUD <br>繁體中文雙語字幕] C -->|24kHz Mono Int16 PCM 翻譯音訊| E[AudioPlaybackManager <br>AVAudioEngine 播放器] 核心實作一:ScreenCaptureKit 擷取與重採樣 macOS 13 推出的 ScreenCaptureKit 讓開發者免去了過去依賴核心音訊虛擬設備的痛苦,能精準過濾並錄製特定應用程式的畫面與音訊。 1. 篩選與過濾目標 App 我們使用 SCShareableContent 獲取系統目前正在運作的應用程式,並篩選掉沒有名稱的背景服務及系統自帶服務: func fetchShareableApps() async -> [SCRunningApplication] { do { let content = try await SCShareableContent.current return content.applications.filter { app in let...
繼續閱讀
June
6th,
2026
升級前情提要 在完成了基於 Vertex AI ADK 的代理人重構後,我們的 LINE 名片助理機器人 (linebot-namecard-python) 進入了實際生產環境進行測試。然而,在真實的使用情境下,我們很快發現了三個影響體驗與安全性的核心痛點: OCR 解析 JSON 不穩定:使用一般的 JSON Mode 配合 Prompt,Gemini 偶爾還是會輸出 Markdown 標記,或者漏掉欄位,造成 parser 報錯。 搜尋結果過多導致 LINE API 400 錯誤:LINE 限制單次只能發送最多 5 個訊息。當搜尋結果包含 5 張卡片加上 Agent 的文字回覆,總數為 6,就會直接被 LINE 拒絕並已讀不回。 AI 誤觸修改:使用者若是提及修改,Agent 在沒有二次確認的情況下會直接寫入 Firebase,容易因為聽錯或幻覺而造成資料被污染。 這篇文章將專注於分享我們如何針對上述痛點進行第二波升級,實作 Structured Outputs、消歧義清單、二次確認機制,以及我們在運維部署時所踩到的環境變數搶救大坑! 優化一:擁抱 Gemini Structured Outputs 結構化輸出 以往在呼叫 gemini-3-flash-preview 進行名片圖片解析時,我們是透過在 Prompt 中命令並手動 parse JSON。為了達到 100% 的格式保障,我們導入了 Vertex AI API 原生的 Structured Outputs (結構化輸出) 功能。 1. 定義名片 Schema 在 app/gemini_utils.py 中,我們定義了名片物件的約束 Schema,強迫 Gemini 嚴格依循此格式輸出: NAMECARD_SCHEMA = { "type": "OBJECT", "properties": { "name": { "type": "STRING", "description": "聯絡人姓名,如果看不出來,請填寫 N/A" }, "title": { "type": "STRING", "description": "職稱或頭銜,如果看不出來,請填寫 N/A" }, "company": { "type": "STRING", "description": "公司名稱,如果看不出來,請填寫 N/A" }, "address": { "type": "STRING", "description": "公司或聯絡地址,如果看不出來,請填寫 N/A" }, "phone": { "type": "STRING", "description": ( "電話號碼,格式為 #886-0123-456-789,1234。" "沒有分機就忽略 ,1234。如果看不出來,請填寫 N/A" ) }, "email": { "type": "STRING", "description": "電子郵件信箱,如果看不出來,請填寫 N/A" } }, "required": ["name", "title", "company", "address", "phone", "email"] } 2. 套用至 Generation Config 我們只需要在實例化...
繼續閱讀