[Gemini實戰][RAG] Gemini API File Search 多模態大升級全解析:Embedding 2、Metadata 過濾、頁級引用,附 LINE Bot 開源實作

(圖片來源: Google Blog - Gemini API File Search is now multimodal: build efficient, verifiable RAG) 前情提要:RAG 終於不用自己拼樂高了 過去這幾年只要做 RAG(Retrieval-Augmented Generation),開發者腦袋裡浮現的元件清單大概都長這樣: 一個 chunker(langchain?自己寫?) 一個 embedding model(OpenAI text-embedding-3?Cohere?BGE?) 一個向量資料庫(ChromaDB、FAISS、pgvector、Pinecone…挑哪個都要打架) 一個檢索 + rerank 的流程 然後才是 LLM 更別說多模態 RAG 還要再多一層:圖片怎麼 embed?要不要先 OCR?要不要切兩個 store 文字一個圖片一個?文圖混搜怎麼算分?光是這幾題就能耗掉一個 sprint。 這幾天 Google 在開發者部落格丟出 Expanded Gemini API File Search for multimodal RAG,把上面這條冗長的 pipeline 變成「呼叫一個 managed API」的事,而且圖片是原生支援的。 本文會做兩件事: 把新功能拆開講清楚,包含背後的 Gemini Embedding 2 在做什麼。 用一隻已開源的 LINE Bot(kkdai/linebot-multimodal-rag)當作活生生的示範,看新功能怎麼在實際 production code 裡組合起來 — 順便把我除錯時撞到的兩個典型坑分享給大家避雷。 新功能三大重點 依照官方部落格,這次升級的核心就三件事: 1. 真.多模態檔案搜尋(Native Multimodal File Search) 過去的 File Search 是純文字檢索,圖片只能靠 OCR 變成文字才能進 store。 “File Search now processes images and text together. Powered by the Gemini Embedding 2 model, the tool understands native image data.” 現在你可以直接把圖片丟進 File Search Store,跟文字一起被索引。背後的引擎是 Gemini Embedding 2 —— 文字、圖片、影片、音訊、文件共用同一個向量空間,所以你可以「拿圖找文字」、「拿文字找圖」、或者「拿圖找圖」,不用自己對齊空間。 對我們做產品的人來說,這代表: 文圖混搜不再是研究題目,是一個 API call。 不用維護兩個 store(一個給文字 chunks、一個給 CLIP-style image embeddings)。 科學圖表、UI screenshot、報表、相簿…這些以前 OCR 之後損失大半語意的東西,現在能保留原始視覺資訊去檢索。 2. Custom Metadata 與 Server-side 過濾 每一份你丟進 store 的檔案,現在都可以掛上 key-value 標籤: {"key": "user_id", "string_value": "U1234abcd..."} {"key": "department", "string_value": "Legal"} {"key": "status", "string_value":...
繼續閱讀

[GCP 實戰][BwAI] AI 賦能開發:使用 Gemini CLI 快速部署 LINE Bot 雲端備份神器

前情提要 在即將到來的 Build With AI 2026 的工作坊中,我們帶來了一個非常實用的專案:LINE Bot 檔案備份機器人。它可以讓你把 LINE 聊天室裡的圖片、檔案直接丟上 Google Drive,還會按月份自動幫你建資料夾整理得服服貼貼。 傳統上,要把這樣一個包含 OAuth 授權、Firestore 資料庫、Cloud Run 容器部署的專案放上雲端,新手往往會對著落落長的 gcloud 指令發愁。 但這次不一樣,我們有秘密武器:Gemini CLI。 這篇文章將紀錄我們如何把 AI 當作 DevOps 工程師,透過「講話」的方式完成整個複雜的部署流程,當然,也包含了過程中踩到的各種真實坑洞。 準備工作:召喚 AI 助手 在開始之前,除了基本的 gcloud 安裝與登入,你只需要安裝 Gemini CLI。 準備好以下「機密參數」(本文皆已 Mock 處理): PROJECT_ID: your-cool-project-id LINE Channel Secret: YOUR_LINE_SECRET_XXXX LINE Access Token: YOUR_LINE_TOKEN_XXXX 進入專案資料夾後,我只對 Gemini CLI 說了一句話: 「幫我使用 gcloud 部署到 Cloud Run,如果需要任何資料,請停下來問我。參考 repo…」 接下來,就是見證奇蹟(與修 bug)的時刻。 實戰部署流程:AI 帶路 Gemini CLI 非常聰明地分析了 Dockerfile 與 main.go,馬上列出了一套作戰計畫。 第一步:環境檢測與 API 啟用 AI 首先幫我確認了 gcloud 當前的專案設定,並一鼓作氣啟用了必要的服務: gcloud services enable firestore.googleapis.com \ cloudbuild.googleapis.com \ run.googleapis.com \ artifactregistry.googleapis.com 第二步:建立 Firestore 資料庫 (遇到第一個坑) 我們的 Bot 需要記錄 OAuth 的 State 防偽造標記,所以需要 Firestore。 AI 嘗試執行了指令,但我們馬上遇到錯誤。(詳見後文踩坑紀錄) 修正後,正確的指令是: gcloud firestore databases create --location=asia-east1 --type=firestore-native 第三步:先上車後補票的 Cloud Run 部署 這是一個經典的「雞生蛋、蛋生雞」問題:Google OAuth 需要知道你的 Cloud Run 網址 (Redirect URI),但你的 Cloud Run 部署又需要填寫 OAuth 的 Client ID 和 Secret。 Gemini CLI 的策略很棒:先用佔位符部署! gcloud run deploy linebot-backup-service \ --source . \ --region asia-east1 \ --set-env-vars "GOOGLE_CLOUD_PROJECT=your-cool-project-id,ChannelSecret=YOUR_LINE_SECRET_XXXX,ChannelAccessToken=YOUR_LINE_TOKEN_XXXX,GOOGLE_CLIENT_ID=PENDING,GOOGLE_CLIENT_SECRET=PENDING,GOOGLE_REDIRECT_URL=PENDING" \ --allow-unauthenticated \ --quiet 部署成功後,我們拿到了一串香噴噴的網址:https://linebot-backup-service-xxxxx.a.run.app。 第四步:完成...
繼續閱讀

[GCP 實戰] 打造持久化 AI 助手:在 GCE 部署 Hermes Agent 並接軌 Telegram

前情提要 在解決了 LINE Bot 的 Vertex AI 遷移後,我開始思考:能不能有一個「更具主動性」且「擁有長期記憶」的 AI 助手?這時候我盯上了 NousResearch 開源的 Hermes Agent 。 不同於一般的 Chatbot,Hermes 被設計成一個「會呼吸的操作系統」,它能自己執行 Shell 指令、寫 Python 腳本、管理長期記憶,甚至能透過不同的 Gateway (Telegram, Discord) 隨時與你保持聯繫。 為了讓它能 24/7 待命,我選擇將它部署在 Google Compute Engine (GCE) 上。這篇文章將紀錄從零開始的部署過程,以及我在配置最新的 Gemini 2.5 Flash 模型時踩過的那些坑。 環境參數預備 在開始之前,請確保你手手上這這些必要的參數: PROJECT_ID: YOUR_PROJECT_ID LOCATION: global GOOGLE_API_KEY: YOUR_GOOGLE_API_KEY (Google AI Studio 取得) 第一步:建立 GCE 實例 Hermes Agent 需要一點運算能力來處理工具調用(Tool Use),建議使用 e2-medium 規格。 gcloud compute instances create hermes-agent-vm \ --project=YOUR_PROJECT_ID \ --zone=us-central1-a \ --machine-type=e2-medium \ --image-family=ubuntu-2204-lts \ --image-project=ubuntu-os-cloud \ --boot-disk-size=30GB \ --metadata=startup-script='#!/bin/bash apt-get update apt-get install -y git curl python3-pip python3-venv nodejs npm ' 第二步:安裝 Hermes Agent SSH 進入 VM 後,直接使用官方提供的一鍵安裝腳本。 進入 VM: gcloud compute ssh hermes-agent-vm --zone=us-central1-a 執行安裝: curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash source ~/.bashrc 第三步:配置 Gemini 2.5 Flash (SOP 實戰) 這是整場演習最容易踩坑的地方。Hermes 預設可能會指向不存在或過期的模型標識符。 建立配置文件: 在 ~/.hermes/config.yaml 中,我們必須精確指定 Gemini 2.5 Flash,且 不可帶 google/ 前綴。 model: provider: gemini default: "gemini-2.5-flash" terminal: backend: local gateway: provider: telegram auxiliary: # ⚠️ 非常重要:Hermes 內部會硬編碼輔助模型,必須手動覆寫 title_generation: { provider: gemini,...
繼續閱讀

[GCP 實戰] OpenAB 部署筆記:在 GCE 上打造支援 Telegram 的 Gemini ACP 橋接器

前情提要 最近為了讓 AI 編碼助理(如 Claude Code 或 Gemini CLI)能直接在聊天平台上使用,我開始研究 OpenAB **。這是一個強大的橋接器,能將 Slack、Discord 或 Telegram 對接到符合 **ACP (Agent Client Protocol) 標準的 CLI 工具。 這篇文章紀錄了我將 OpenAB 部署在 Google Cloud 上的完整實戰過程,特別是如何繞過認證限制、處理 Telegram 的 HTTPS 需求,以及解決容器化部署中的路徑與權限問題。 OpenAB 參考文件: https://openabdev.github.io/openab/ OpenAB Repo: https://github.com/openabdev/openab 部署決策:為什麼選 GCE 而不是 Cloud Run? 雖然 Cloud Run 是我的首選,但在處理 OpenAB 時,Google Compute Engine (GCE) 才是最佳解決方案。原因有二: Stateful Session (狀態化對話):OpenAB 會為每個對話 thread 啟動一個子進程(如 Gemini CLI)。這些進程必須長期駐留以維持對話上下文。Cloud Run 的自動縮減機制會殺死這些進程,導致對話中斷。 認證持久化:AI CLI 的 Token 需要儲存在本地磁碟。GCE 配合 Persistent Disk 能保證重啟後登入狀態不消失。 實戰步驟:Step-by-Step 部署過程 第一步:撰寫自動化啟動腳本 (Startup Script) 為了讓部署標準化,我們撰寫了一個 setup-openab.sh。其核心任務是安裝 Docker、建立持久化目錄,並動態生成 config.toml。 最關鍵的部分是 自定義 Docker Image。由於 OpenAB 官方鏡像不一定包含所有 AI 工具,我們透過 Dockerfile 現場安裝 Node.js 與 @google/gemini-cli: FROM ghcr.io/openabdev/openab:latest USER root RUN apt-get update && apt-get install -y curl && \ curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \ apt-get install -y nodejs && \ npm install -g @google/gemini-cli USER 1000 第二步:使用 gcloud 建立 GCE 實例 我們選擇 e2-medium 規格,並透過 Metadata 傳遞敏感資訊(如 Bot Token),避免寫死在腳本中。 gcloud compute instances create openab-server \ --project=your-project-id \ --zone=asia-east1-b \...
繼續閱讀

[GCP 實戰] LINE Bot 遷移大作戰:從 AI Studio 轉向 Vertex AI 解決 429 額度危機

前情提要 最近我們部署在 Google Cloud Run 上的 LINE 名片助理機器人 (linebot-namecard-python) 突然罷工了。透過 gcloud logging read 查了一下日誌,迎面而來的是這個無情的錯誤: google.api_core.exceptions.ResourceExhausted: 429 Your billing account has exceeded its monthly spending cap. 這是一個慘痛的教訓:我們當初為了快速開發,直接使用了 Google AI Studio 提供的 API Key(走 google.generativeai 套件)。隨著流量增加,我們很快就撞上了 Google AI Studio Tier 1 的 429 限制(Rate Limit / Quota 爆炸),結果默默把每月的免費額度給打爆了。 為了徹底解決這個問題,我們決定將所有依賴 AI Studio Gemini API Key 的應用程式,全面轉換成 Google Cloud Vertex AI,直接走 GCP 的企業級架構與計費系統。 這篇文章就來分享這次遷移的完整過程,以及途中發現「Vertex AI 的資訊實在太少,導致模型設定常常踩坑」的各種血淚經驗。 身份驗證升級:推薦使用 Workload Identity 在遷移的過程中,最重要的一環就是身分驗證。過去我們習慣在環境變數塞一個 GEMINI_API_KEY,簡單粗暴但充滿資安隱患。 來到 GCP 的世界,很多人第一直覺是去開一個 Service Account(服務帳戶),然後把 JSON 金鑰載下來放進程式裡。但強烈建議不要走 Service Account 金鑰這條路! 搭配 gcloud cli,其實可以很快速地為 Cloud Run 設定 Workload Identity。程式碼中不需要任何金鑰,只要在執行環境中賦予該 Identity 對應的 Vertex AI User 權限,Google Cloud SDK 就會自動取得憑證。這樣不僅大幅降低金鑰外洩的風險,管理起來也更輕鬆。 程式碼升級:從 AI Studio 轉向 Vertex AI 要將專案從 Google AI Studio SDK 遷移到 Vertex AI,主要有三個步驟: 替換依賴套件: 在 requirements.txt 中,移除舊的 google.generativeai,換成 google-cloud-aiplatform。 更新環境變數設定: 在 config.py 中,我們不再需要 API Key,而是改用 GCP 的 PROJECT_ID 和 LOCATION: PROJECT_ID = os.getenv("PROJECT_ID", None) LOCATION = os.getenv("LOCATION", "global") # 預設使用 global 核心程式碼改寫 (gemini_utils.py): Vertex AI 的 SDK 介面雖然類似,但對於多模態(如圖片)的處理稍微嚴格一點。我們需要將 PIL.Image 轉換成 vertexai.generative_models.Part 格式: import vertexai from...
繼續閱讀

[Gemini 3.1] Gemini-3.1-flash TTS 實戰:更簡單、更強大的朗讀摘要功能

前情提要 在上一篇實戰中,我們利用 Gemini 3.1 Flash Live 實現了語音辨識,並透過 Gemini 2.5 Live API 的「側擊」方式勉強達成了朗讀摘要(TTS)功能。 但就在 2026 年 4 月,Google 正式發佈了 Gemini 3.1 Flash TTS。這是一個專門為語音輸出設計的原生模型,不再需要掛載 Live WebSocket,直接透過標準的 generate_content 流程就能輸出高品質音訊。 身為開發者,有更優雅、更原生的方案當然要立刻跟上。這篇文章就來分享如何把 LINE Bot 的朗讀摘要功能升級到 Gemini 3.1 Native TTS,以及過程中踩到的「異步大坑」。 技術升級:從 Live API 轉向 Native TTS 之前的朗讀功能是利用 Gemini 2.5 Live API 模擬出來的,雖然可用,但有幾個缺點: 複雜度高:需要管理 WebSocket 連線生命週期。 模型限制:必須使用特定的 native-audio 模型,且主要支援在 us-central1。 回傳格式固定:採樣率通常固定在 16kHz。 Gemini 3.1 Flash TTS 的出現改變了這一切: 模型名稱:gemini-3.1-flash-tts-preview。 介面一致:使用熟悉的 generate_content_stream。 動態參數:支援從回傳的 MIME type 自動偵測採樣率(通常提升到了 24kHz,音質更好)。 核心程式碼進化(tools/tts_tool.py) 新的實作變得更加簡潔,重點在於 response_modalities=["audio"] 這個設定: async def text_to_speech(text: str) -> tuple[bytes, int]: client = genai.Client(api_key=GOOGLE_AI_API_KEY, http_options={"api_version": "v1beta"}) contents = [ types.Content( role="user", parts=[ # 加入在地化指令,讓語氣更自然 types.Part.from_text(text=f"請使用台灣用語的繁體中文,以親切且自然的語氣朗讀以下摘要內容。## Transcript:\n{text}"), ], ), ] config = types.GenerateContentConfig( response_modalities=["audio"], speech_config=types.SpeechConfig( voice_config=types.VoiceConfig( prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name="Zephyr") ) ), ) pcm_chunks = [] sample_rate = 24000 # 預設值 try: # ⚠️ 這裡就是那個差點讓我修到天亮的大坑 response_stream = await client.aio.models.generate_content_stream( model="gemini-3.1-flash-tts-preview", contents=contents, config=config, ) async for chunk in response_stream: if chunk.parts: for part in chunk.parts: if part.inline_data: pcm_chunks.append(part.inline_data.data) # 從 MIME type 動態取得採樣率(例如 audio/L16;rate=24000) if part.inline_data.mime_type: sample_rate...
繼續閱讀