<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Gemini on KnightLi的博客</title>
        <link>https://knightli.com/zh-tw/tags/gemini/</link>
        <description>Recent content in Gemini on KnightLi的博客</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-tw</language>
        <lastBuildDate>Sun, 24 May 2026 08:43:24 +0800</lastBuildDate><atom:link href="https://knightli.com/zh-tw/tags/gemini/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Gemini 3.5 Flash 的定位及優勢：為什麼它更適合高頻、多模態和低延遲場景</title>
        <link>https://knightli.com/zh-tw/2026/05/24/gemini-35-flash-positioning-advantages-low-latency-multimodal/</link>
        <pubDate>Sun, 24 May 2026 08:43:24 +0800</pubDate>
        
        <guid>https://knightli.com/zh-tw/2026/05/24/gemini-35-flash-positioning-advantages-low-latency-multimodal/</guid>
        <description>&lt;p&gt;&lt;code&gt;Gemini 3.5 Flash&lt;/code&gt; 的關鍵詞不是「最強」，而是「高頻、快速、便宜、好接入」。它更像是 Gemini 系列裡的主力工作模型：不一定負責最難的推理題，但適合承接大量真實業務請求，例如問答、摘要、客服、內容處理、多模態理解、輕量程式碼輔助和自動化工作流。&lt;/p&gt;
&lt;p&gt;理解 Flash 的關鍵，是不要把它當成 Pro 類旗艦模型的替代品，而要把它當成一個面向吞吐量和響應速度優化的模型層。對開發者和企業來說，很多 AI 應用真正的成本不在單次最強能力，而在每天成千上萬次請求的延遲、穩定性、價格和上下文處理能力。&lt;/p&gt;
&lt;h2 id=&#34;flash-的產品定位&#34;&gt;Flash 的產品定位
&lt;/h2&gt;&lt;p&gt;Gemini 系列通常會把模型拆成不同層級：旗艦模型負責更複雜的推理、規劃和高難度任務；Flash 模型則強調速度、成本和規模化呼叫。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Gemini 3.5 Flash&lt;/code&gt; 的定位可以概括為：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;比 Pro 更適合高頻呼叫。&lt;/li&gt;
&lt;li&gt;比輕量小模型更適合複雜輸入。&lt;/li&gt;
&lt;li&gt;面向低延遲和高吞吐。&lt;/li&gt;
&lt;li&gt;適合多模態輸入和長上下文處理。&lt;/li&gt;
&lt;li&gt;更適合作為應用裡的預設模型，而不是只在少數困難任務中呼叫。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這類模型最適合做「每天都要跑很多次」的任務。它的價值不只是單次回答品質，而是能否在成本可控的前提下穩定處理大量文字、圖片、音訊、影片或結構化資訊。&lt;/p&gt;
&lt;h2 id=&#34;為什麼-flash-很重要&#34;&gt;為什麼 Flash 很重要
&lt;/h2&gt;&lt;p&gt;AI 產品落地時，經常會遇到一個現實問題：最強模型很好，但不是每個請求都值得用最強模型。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用者問一個普通客服問題。&lt;/li&gt;
&lt;li&gt;系統要總結一段會議記錄。&lt;/li&gt;
&lt;li&gt;後台要分類一批工單。&lt;/li&gt;
&lt;li&gt;App 要解釋一張圖片。&lt;/li&gt;
&lt;li&gt;自動化流程要從郵件裡抽取欄位。&lt;/li&gt;
&lt;li&gt;Agent 要先讀一批文件，再決定下一步。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這些任務需要模型可靠、便宜、快，但不一定需要旗艦模型的全部推理能力。Flash 的意義就在這裡：它把「夠強」和「夠快」放在同一個位置上。&lt;/p&gt;
&lt;p&gt;如果一個 AI 應用要面向大量使用者，預設模型往往不能只看峰值能力，而要看平均請求成本、響應速度、併發能力和失敗率。Flash 就是這種應用層模型。&lt;/p&gt;
&lt;h2 id=&#34;主要優勢一低延遲和高吞吐&#34;&gt;主要優勢一：低延遲和高吞吐
&lt;/h2&gt;&lt;p&gt;Flash 最直觀的優勢是速度。&lt;/p&gt;
&lt;p&gt;對聊天產品、搜尋增強、客服機器人、即時寫作輔助和 Agent 工作流來說，延遲會直接影響體驗。使用者不一定知道模型參數或 benchmark，但能感覺到「是不是等得煩」。&lt;/p&gt;
&lt;p&gt;低延遲帶來的價值包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;對話更像即時互動。&lt;/li&gt;
&lt;li&gt;多輪工具呼叫更不容易拖慢。&lt;/li&gt;
&lt;li&gt;Agent 可以更頻繁地做中間判斷。&lt;/li&gt;
&lt;li&gt;後台批處理能更快跑完。&lt;/li&gt;
&lt;li&gt;產品可以把 AI 能力放進更多細小流程裡。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;尤其是 Agent 類應用，模型不是只回答一次，而是要反覆判斷、呼叫工具、讀上下文、生成下一步動作。單次延遲降低後，整條鏈路的體驗會明顯改善。&lt;/p&gt;
&lt;h2 id=&#34;主要優勢二成本更適合規模化&#34;&gt;主要優勢二：成本更適合規模化
&lt;/h2&gt;&lt;p&gt;Flash 的另一個核心價值是成本。&lt;/p&gt;
&lt;p&gt;企業和開發者真正上線 AI 應用時，通常會關心三個問題：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每次呼叫多少錢。&lt;/li&gt;
&lt;li&gt;每天總呼叫量是多少。&lt;/li&gt;
&lt;li&gt;峰值併發時成本和延遲是否可控。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果一個任務每天跑幾十萬次，哪怕單次差價很小，長期成本也會被放大。Flash 這類模型的定位，就是讓更多請求不必直接打到最貴、最重的模型上。&lt;/p&gt;
&lt;p&gt;常見做法是分層呼叫：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;普通請求預設走 Flash。&lt;/li&gt;
&lt;li&gt;難題、複雜規劃、長鏈路推理再升級到 Pro。&lt;/li&gt;
&lt;li&gt;簡單分類、固定格式抽取也可以進一步下沉到更輕量模型。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這樣可以讓 AI 系統既保留上限，又控制日常成本。&lt;/p&gt;
&lt;h2 id=&#34;主要優勢三多模態輸入更適合真實應用&#34;&gt;主要優勢三：多模態輸入更適合真實應用
&lt;/h2&gt;&lt;p&gt;Gemini 系列一直強調多模態能力。Flash 的優勢在於，它不是只服務文字請求，也適合處理圖片、音訊、影片和文件等輸入。&lt;/p&gt;
&lt;p&gt;這對真實產品很重要。很多業務資料並不是純文字：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用者上傳截圖諮詢問題。&lt;/li&gt;
&lt;li&gt;客服要理解一張故障照片。&lt;/li&gt;
&lt;li&gt;教育產品要看題目圖片。&lt;/li&gt;
&lt;li&gt;內容平台要處理影片片段。&lt;/li&gt;
&lt;li&gt;辦公場景要讀取 PDF、表格和簡報。&lt;/li&gt;
&lt;li&gt;電商場景要分析商品圖和使用者描述。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果多模態能力只能依賴昂貴的旗艦模型，很多高頻場景就很難鋪開。Flash 的意義在於，把多模態理解下放到更適合規模化呼叫的模型層。&lt;/p&gt;
&lt;h2 id=&#34;主要優勢四長上下文讓它適合讀材料&#34;&gt;主要優勢四：長上下文讓它適合讀材料
&lt;/h2&gt;&lt;p&gt;長上下文是 Gemini 系列的重要能力之一。對 Flash 來說，長上下文的價值不是「把所有東西塞進去就完事」，而是讓它能承擔更多資訊整理型任務。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;總結長文件。&lt;/li&gt;
&lt;li&gt;閱讀產品手冊。&lt;/li&gt;
&lt;li&gt;分析會議紀要。&lt;/li&gt;
&lt;li&gt;整理多頁 PDF。&lt;/li&gt;
&lt;li&gt;對比多份合約或方案。&lt;/li&gt;
&lt;li&gt;給 Agent 提供較大的任務背景。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;長上下文和低成本結合起來，適合做「先讀大量材料，再給出可操作結果」的工作流。它不一定每次都要做極難推理，但能把更多上下文納入同一次處理，這對辦公、客服、知識庫、研發輔助都很有用。&lt;/p&gt;
&lt;h2 id=&#34;主要優勢五適合作為預設模型&#34;&gt;主要優勢五：適合作為預設模型
&lt;/h2&gt;&lt;p&gt;很多 AI 產品需要一個「預設模型」。這個模型不一定是最貴最強，但要滿足幾個條件：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;大多數問題回答品質穩定。&lt;/li&gt;
&lt;li&gt;響應足夠快。&lt;/li&gt;
&lt;li&gt;成本可控。&lt;/li&gt;
&lt;li&gt;多模態輸入能處理。&lt;/li&gt;
&lt;li&gt;長上下文能力夠用。&lt;/li&gt;
&lt;li&gt;容易接入 API 和既有產品鏈路。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;Gemini 3.5 Flash&lt;/code&gt; 的優勢正是在這裡。它適合做預設入口：先承接大多數請求，如果遇到複雜任務，再路由到更強模型。&lt;/p&gt;
&lt;p&gt;這種模式會越來越常見。未來很多 AI 系統不是「只選一個模型」，而是「Flash 做主力，Pro 做升級，輕量模型做邊緣任務」。&lt;/p&gt;
&lt;h2 id=&#34;適合哪些場景&#34;&gt;適合哪些場景
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Gemini 3.5 Flash&lt;/code&gt; 更適合這些場景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;客服問答和知識庫檢索後的回答生成。&lt;/li&gt;
&lt;li&gt;長文件摘要、報告整理、會議紀要。&lt;/li&gt;
&lt;li&gt;圖片、截圖、PDF、影片片段的多模態理解。&lt;/li&gt;
&lt;li&gt;App 內即時 AI 助手。&lt;/li&gt;
&lt;li&gt;內容審核、分類、標籤生成。&lt;/li&gt;
&lt;li&gt;郵件、工單、表單的資訊抽取。&lt;/li&gt;
&lt;li&gt;Agent 工作流中的中間判斷和上下文壓縮。&lt;/li&gt;
&lt;li&gt;程式碼解釋、輕量修復建議、文件生成。&lt;/li&gt;
&lt;li&gt;教育產品裡的題目解析和學習輔助。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這些場景共同特點是：請求量大、使用者等待時間敏感、輸入類型複雜，但不一定每次都需要旗艦級深度推理。&lt;/p&gt;
&lt;h2 id=&#34;不適合只用-flash-的場景&#34;&gt;不適合只用 Flash 的場景
&lt;/h2&gt;&lt;p&gt;Flash 不是萬能模型。它更適合高頻和低延遲，不代表所有問題都應該只用它。&lt;/p&gt;
&lt;p&gt;以下場景仍然更適合使用更強的 Pro 類模型，或至少採用分層路由：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;複雜數學和嚴謹證明。&lt;/li&gt;
&lt;li&gt;長鏈路規劃和多步驟策略推理。&lt;/li&gt;
&lt;li&gt;高風險法律、醫療、金融判斷。&lt;/li&gt;
&lt;li&gt;大型程式碼庫的深度重構方案。&lt;/li&gt;
&lt;li&gt;需要極高可靠性的複雜 Agent 任務。&lt;/li&gt;
&lt;li&gt;對幻覺容忍度極低的專業報告。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;更穩妥的策略是：Flash 先處理、判斷和整理；當任務複雜度升高時，再升級到更強模型。&lt;/p&gt;
&lt;h2 id=&#34;和-pro-類模型的關係&#34;&gt;和 Pro 類模型的關係
&lt;/h2&gt;&lt;p&gt;Flash 和 Pro 的關係，不應該理解成「誰取代誰」，而應該理解成「分工不同」。&lt;/p&gt;
&lt;p&gt;Flash 更像日常主力：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;快。&lt;/li&gt;
&lt;li&gt;成本友好。&lt;/li&gt;
&lt;li&gt;適合高併發。&lt;/li&gt;
&lt;li&gt;適合多模態和長上下文應用。&lt;/li&gt;
&lt;li&gt;適合放在產品預設鏈路裡。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pro 更像高難任務模型：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;更適合複雜推理。&lt;/li&gt;
&lt;li&gt;更適合困難規劃。&lt;/li&gt;
&lt;li&gt;更適合高價值請求。&lt;/li&gt;
&lt;li&gt;更適合少量但重要的深度分析。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;好的 AI 產品通常會把兩者組合起來，而不是二選一。&lt;/p&gt;
&lt;h2 id=&#34;開發者應該怎麼用&#34;&gt;開發者應該怎麼用
&lt;/h2&gt;&lt;p&gt;如果要在產品裡接入 Gemini 3.5 Flash，可以考慮這幾種用法：&lt;/p&gt;
&lt;p&gt;第一，把它作為預設模型。大部分普通請求先走 Flash，既保證速度，也控制成本。&lt;/p&gt;
&lt;p&gt;第二，設計模型路由。當 Flash 判斷任務複雜、風險高、需要深度推理時，再把請求升級到 Pro。&lt;/p&gt;
&lt;p&gt;第三，用它做上下文壓縮。Agent 在執行任務前，可以先讓 Flash 總結文件、抽取關鍵事實、生成結構化上下文。&lt;/p&gt;
&lt;p&gt;第四，把多模態輸入納入常規流程。圖片、截圖、PDF、音訊、影片不要只作為邊緣功能，而可以成為產品預設輸入的一部分。&lt;/p&gt;
&lt;p&gt;第五，用評測來決定邊界。不要只看官方 benchmark，要拿自己的客服問題、文件、程式碼、圖片和業務流程做測試，判斷哪些任務 Flash 足夠，哪些必須升級。&lt;/p&gt;
&lt;h2 id=&#34;小結&#34;&gt;小結
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Gemini 3.5 Flash&lt;/code&gt; 的核心定位，是一個面向高頻真實應用的多模態主力模型。它的優勢不在於取代 Pro 類旗艦模型，而在於把速度、成本、長上下文和多模態能力放到一個更適合規模化呼叫的位置上。&lt;/p&gt;
&lt;p&gt;對開發者來說，Flash 最值得關注的不是單個 benchmark，而是產品架構變化：預設模型可以更快、更便宜、更能讀複雜輸入；複雜任務再升級給更強模型。這樣既能保證體驗，也能控制成本。&lt;/p&gt;
&lt;p&gt;如果說 Pro 是處理難題的重型工具，那麼 Flash 更像每天都在生產線上運轉的主力工具。真正做 AI 產品時，後者往往更接近使用者每天實際感受到的體驗。&lt;/p&gt;
&lt;p&gt;參考資料：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Google 官方部落格：&lt;a class=&#34;link&#34; href=&#34;https://blog.google/innovation-and-ai/models-and-research/gemini-models/gemini-3-5/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://blog.google/innovation-and-ai/models-and-research/gemini-models/gemini-3-5/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Google DeepMind Gemini Flash：&lt;a class=&#34;link&#34; href=&#34;https://deepmind.google/en/models/gemini/flash/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://deepmind.google/en/models/gemini/flash/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;使用者提供的知乎討論連結：&lt;a class=&#34;link&#34; href=&#34;https://www.zhihu.com/question/2040529179641385344/answer/2040531897613285214&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://www.zhihu.com/question/2040529179641385344/answer/2040531897613285214&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Google I/O 之後，GPT 和 Gemini 訂閱怎麼選？普通使用者與開發者對比</title>
        <link>https://knightli.com/zh-tw/2026/05/21/gpt-vs-gemini-subscription-after-google-io-2026/</link>
        <pubDate>Thu, 21 May 2026 08:33:14 +0800</pubDate>
        
        <guid>https://knightli.com/zh-tw/2026/05/21/gpt-vs-gemini-subscription-after-google-io-2026/</guid>
        <description>&lt;p&gt;Google I/O 2026 之後，很多人的 AI 訂閱選擇變複雜了。&lt;/p&gt;
&lt;p&gt;以前問題比較簡單：寫作、問答、編程、文件分析，大多數人優先看 ChatGPT；如果深度使用 Google 搜尋、Android、Gmail、Docs、YouTube，再考慮 Gemini。現在不一樣了。Google 在 I/O 上把 Gemini 3.5 Flash、Gemini Omni、Antigravity 2.0、Gemini API Managed Agents、Google AI Studio 和 AI Ultra 訂閱一起推出來，Gemini 生態開始從「可選項」變成「強競爭主線」。&lt;/p&gt;
&lt;p&gt;這篇文章不做抽象模型跑分，而是回答一個實際問題：普通使用者、開發者、內容創作者和企業使用者，到底該訂閱 GPT / ChatGPT，還是 Gemini / Google AI？&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;注意：AI 訂閱價格、額度、地區和模型可用性變化很快。本文寫作時間是 2026 年 5 月 21 日，正式訂閱前應以 OpenAI 與 Google 當前頁面為準。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;先說結論&#34;&gt;先說結論
&lt;/h2&gt;&lt;p&gt;如果你只想選一個主力訂閱，可以按這個邏輯：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;日常寫作、問答、文件分析、泛辦公、中文英文混合使用：優先 ChatGPT Plus。&lt;/li&gt;
&lt;li&gt;高頻編程、需要 Codex、複雜推理、專案級程式碼任務：優先 ChatGPT Plus / Pro，再按額度決定是否升級。&lt;/li&gt;
&lt;li&gt;深度使用 Google 生態、Gmail、Docs、Drive、Android、Search：優先 Gemini / Google AI Pro。&lt;/li&gt;
&lt;li&gt;重點做影片、AI 影像、Google Flow、YouTube Shorts、Gemini Omni：優先 Google AI Pro / Ultra。&lt;/li&gt;
&lt;li&gt;需要 Antigravity、Gemini API Managed Agents、AI Studio 到 Android 的工作流：重點看 Google AI Pro / Ultra。&lt;/li&gt;
&lt;li&gt;企業團隊：不要只看個人訂閱，重點看 Business / Enterprise、Workspace、權限、審計和資料邊界。&lt;/li&gt;
&lt;li&gt;預算有限：一個主力付費訂閱 + 另一個平台免費層或按量 API，通常比同時訂兩個高階套餐更划算。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一句話：GPT 更像通用生產力和程式碼助手主力；Gemini 在 Google I/O 之後更像 Google 生態裡的系統級 AI 套件。&lt;/p&gt;
&lt;h2 id=&#34;google-io-之後gemini-發生了什麼變化&#34;&gt;Google I/O 之後，Gemini 發生了什麼變化
&lt;/h2&gt;&lt;p&gt;Google I/O 2026 讓 Gemini 的價值不再只取決於 Gemini App 本身。&lt;/p&gt;
&lt;p&gt;幾個關鍵變化：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Gemini 3.5 Flash&lt;/code&gt;：Google 把它定位為從 prompt 到 action 的高速模型，面向真實 Agent 工作流。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Gemini Omni&lt;/code&gt;：從任意輸入創作內容，當前重點從影片開始，支援多模態創作和自然語言多輪編輯。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Google Antigravity 2.0&lt;/code&gt;：Agent-first development platform，面向開發者的多 Agent 編排與編程平台。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Gemini API Managed Agents&lt;/code&gt;：透過 API 建立可推理、可用工具、可執行程式碼的託管 Agent。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Google AI Studio&lt;/code&gt;：從 prompt playground 走向行動端、Android 原生應用生成和 Antigravity 專案匯出。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Google AI Ultra&lt;/code&gt;：I/O 後新增 $100/月檔位，並面向開發者、技術負責人、知識工作者和高階創作者。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;更重要的是，Google 把 Gemini App 的使用額度從傳統每日 prompt 限制，轉向 &lt;code&gt;compute-used&lt;/code&gt; 模型。複雜影片、程式碼和長上下文任務會消耗更多額度，簡單文字任務消耗更少；額度每 5 小時刷新，直到達到週限制。&lt;/p&gt;
&lt;p&gt;這說明 Google 正在把 Gemini 訂閱做成「模型 + 應用 + 創作 + 開發工具 + Google 生態」的打包入口。&lt;/p&gt;
&lt;h2 id=&#34;chatgpt--gpt-訂閱現在適合誰&#34;&gt;ChatGPT / GPT 訂閱現在適合誰
&lt;/h2&gt;&lt;p&gt;ChatGPT 的優勢依然很強，尤其適合把 AI 當作日常工作主力的人。&lt;/p&gt;
&lt;p&gt;根據 OpenAI 當前價格頁和幫助文件，ChatGPT Free 可以使用 GPT-5.5 Instant 等基礎能力；Plus 提供 GPT-5.5 Thinking、更多訊息和上傳額度、更強圖像生成、deep research、agent mode、專案、任務、自訂 GPT 和擴展 Codex 使用；Pro 則提供更高額度、GPT-5.5 Pro、更高 Codex 使用量、最大 deep research 和 agent mode。&lt;/p&gt;
&lt;p&gt;更適合 ChatGPT 的場景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;寫作、總結、翻譯、改稿。&lt;/li&gt;
&lt;li&gt;複雜問答和結構化分析。&lt;/li&gt;
&lt;li&gt;文件上傳、表格分析、研究報告。&lt;/li&gt;
&lt;li&gt;編程問答、程式碼審查、重構建議。&lt;/li&gt;
&lt;li&gt;使用 Codex 做程式碼庫任務。&lt;/li&gt;
&lt;li&gt;多語言內容生產。&lt;/li&gt;
&lt;li&gt;對模型品質和回答穩定性要求高，但不強依賴 Google 產品。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你是普通使用者，ChatGPT Plus 仍然是最穩的主力訂閱。它覆蓋面廣，學習成本低，中文和英文任務都比較均衡。&lt;/p&gt;
&lt;p&gt;如果你是開發者，ChatGPT 的關鍵不只是聊天，而是 Codex。OpenAI 幫助文件說明，Codex 可隨符合條件的 ChatGPT 計畫使用，額度隨計畫不同而變化。也就是說，如果你大量使用 Codex 做程式碼修改、PR、重構、測試修復，訂閱選擇要把 Codex 額度一起算進去。&lt;/p&gt;
&lt;h2 id=&#34;gemini--google-ai-訂閱現在適合誰&#34;&gt;Gemini / Google AI 訂閱現在適合誰
&lt;/h2&gt;&lt;p&gt;Gemini 的優勢在 Google I/O 之後更清晰：它和 Google 生態綁定更深。&lt;/p&gt;
&lt;p&gt;Google AI 訂閱現在不只是 Gemini App 裡的模型額度，還包括 Gemini Omni、Google Flow、Antigravity、AI Studio、部分 YouTube Premium / Lite 權益、Workspace / Android / Search 生態能力等。Google 官方還把 AI Ultra 擴成 $100 與更高階檔位，強調開發者、技術負責人、知識工作者和高階創作者。&lt;/p&gt;
&lt;p&gt;更適合 Gemini 的場景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你深度使用 Gmail、Docs、Drive、Sheets、Slides、Android。&lt;/li&gt;
&lt;li&gt;你想把 AI 放進 Google Search、YouTube、Workspace 生態。&lt;/li&gt;
&lt;li&gt;你關注 Gemini Omni、Google Flow、影片生成和影片編輯。&lt;/li&gt;
&lt;li&gt;你想試 Antigravity、Gemini API Managed Agents、AI Studio mobile。&lt;/li&gt;
&lt;li&gt;你需要超長上下文文件理解。&lt;/li&gt;
&lt;li&gt;你做 Google 生態應用、Android 原生應用、Workspace 自動化。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Google 官方幫助頁顯示，Gemini Apps 的上下文視窗會隨訂閱提高：無 AI plan 為 32K，AI Plus 為 128K，AI Pro 和 AI Ultra 為 1 million。AI Pro / Ultra 也會提供更高使用限制、更多特性和部分早期功能。&lt;/p&gt;
&lt;p&gt;如果你的工作環境已經在 Google 生態裡，Gemini 的價值會被放大。否則，單獨把 Gemini 當作「另一個聊天機器人」來訂閱，性價比就不一定比 ChatGPT 更穩。&lt;/p&gt;
&lt;h2 id=&#34;普通使用者怎麼選&#34;&gt;普通使用者怎麼選
&lt;/h2&gt;&lt;p&gt;普通使用者最容易踩的坑，是因為新模型發布就同時訂多個平台。&lt;/p&gt;
&lt;p&gt;更理性的選法是先看主場景。&lt;/p&gt;
&lt;p&gt;如果你主要做這些事：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;寫文章。&lt;/li&gt;
&lt;li&gt;查資料。&lt;/li&gt;
&lt;li&gt;做總結。&lt;/li&gt;
&lt;li&gt;讀 PDF。&lt;/li&gt;
&lt;li&gt;寫郵件。&lt;/li&gt;
&lt;li&gt;改履歷。&lt;/li&gt;
&lt;li&gt;學習語言。&lt;/li&gt;
&lt;li&gt;日常問答。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;優先選 ChatGPT Plus。它的通用性更好，任務邊界更清楚，不需要你深度綁定某個生態。&lt;/p&gt;
&lt;p&gt;如果你主要做這些事：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gmail / Docs / Drive / YouTube / Android 高頻使用。&lt;/li&gt;
&lt;li&gt;希望 AI 直接進入 Google 生態。&lt;/li&gt;
&lt;li&gt;想體驗 Gemini App、Daily Brief、Google Search AI、YouTube 內容問答。&lt;/li&gt;
&lt;li&gt;需要長上下文讀取 Google 文件。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;優先選 Google AI Pro。&lt;/p&gt;
&lt;p&gt;如果你只是輕量使用者，兩個平台都先用免費層，等明確遇到限制再付費。不要為了「可能用到」而訂閱高階套餐。&lt;/p&gt;
&lt;h2 id=&#34;開發者怎麼選&#34;&gt;開發者怎麼選
&lt;/h2&gt;&lt;p&gt;開發者要分兩類。&lt;/p&gt;
&lt;p&gt;第一類是以程式碼問答、修 bug、寫腳本、讀程式碼庫為主。優先看 ChatGPT Plus / Pro + Codex。&lt;/p&gt;
&lt;p&gt;理由是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Codex 和 ChatGPT 帳號打通。&lt;/li&gt;
&lt;li&gt;ChatGPT 對程式碼解釋、重構、測試、錯誤分析比較穩。&lt;/li&gt;
&lt;li&gt;Plus 已經覆蓋很多日常開發任務。&lt;/li&gt;
&lt;li&gt;Pro 更適合高頻、長時間、複雜程式碼庫任務。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;第二類是面向 Google 生態、Agent 平台、Android、Workspace 或 Gemini API 開發。優先看 Google AI Pro / Ultra。&lt;/p&gt;
&lt;p&gt;理由是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gemini 3.5 Flash 是 Google I/O 後 Agent 工作流重點模型。&lt;/li&gt;
&lt;li&gt;Antigravity 2.0 是 Google 的 Agent-first 開發平台。&lt;/li&gt;
&lt;li&gt;Managed Agents 能透過 API 建立帶工具和隔離 Linux 環境的 Agent。&lt;/li&gt;
&lt;li&gt;AI Studio 可以和 Android、Workspace、Antigravity 更自然銜接。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你是全端開發者，最務實的組合通常是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ChatGPT Plus 作為日常程式碼與文件主力。&lt;/li&gt;
&lt;li&gt;Gemini 免費層或 AI Pro 用於 Google 生態、長上下文和影片/Agent 新能力。&lt;/li&gt;
&lt;li&gt;API 按量使用，不要把個人訂閱誤當生產 API 預算。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;內容創作者怎麼選&#34;&gt;內容創作者怎麼選
&lt;/h2&gt;&lt;p&gt;內容創作者的選擇取決於你做什麼內容。&lt;/p&gt;
&lt;p&gt;如果你主要做：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;文案。&lt;/li&gt;
&lt;li&gt;標題。&lt;/li&gt;
&lt;li&gt;腳本。&lt;/li&gt;
&lt;li&gt;文章。&lt;/li&gt;
&lt;li&gt;圖文內容。&lt;/li&gt;
&lt;li&gt;資料整理。&lt;/li&gt;
&lt;li&gt;多語言改寫。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ChatGPT Plus 依然很穩。&lt;/p&gt;
&lt;p&gt;如果你主要做：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;影片生成。&lt;/li&gt;
&lt;li&gt;短影片創意。&lt;/li&gt;
&lt;li&gt;AI 影像。&lt;/li&gt;
&lt;li&gt;YouTube Shorts。&lt;/li&gt;
&lt;li&gt;Google Flow 工作流。&lt;/li&gt;
&lt;li&gt;多模態素材整合。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Gemini / Google AI Pro 或 Ultra 更值得關注。I/O 之後，Gemini Omni 和 Google Flow 是 Google 在創作場景裡的核心牌。&lt;/p&gt;
&lt;p&gt;如果預算有限，可以先訂一個文字主力，再用另一個平台的免費層或短期訂閱測試影片能力。影片模型的額度、排隊、時長、解析度和地區限制變化很快，不建議一開始就按長期生產服務規劃。&lt;/p&gt;
&lt;h2 id=&#34;企業和團隊怎麼選&#34;&gt;企業和團隊怎麼選
&lt;/h2&gt;&lt;p&gt;企業不要按個人使用者思路選。&lt;/p&gt;
&lt;p&gt;企業真正要看的不是「哪個模型這週更強」，而是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;資料是否用於訓練。&lt;/li&gt;
&lt;li&gt;是否有 SSO、MFA、RBAC。&lt;/li&gt;
&lt;li&gt;是否有審計日誌。&lt;/li&gt;
&lt;li&gt;是否支援內部知識連接。&lt;/li&gt;
&lt;li&gt;是否能控制外掛、連接器和 Agent 權限。&lt;/li&gt;
&lt;li&gt;是否符合組織的合規要求。&lt;/li&gt;
&lt;li&gt;是否能和現有辦公套件打通。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果企業已經重度使用 Google Workspace，Gemini 企業方案自然更值得評估。如果團隊已經圍繞 ChatGPT、Codex、OpenAI API 和內部工具鏈搭建流程，OpenAI Business / Enterprise 更自然。&lt;/p&gt;
&lt;p&gt;對工程團隊來說，還要單獨評估 Codex、Antigravity、Gemini API Managed Agents、MCP、CI/CD、程式碼權限、倉庫存取和審計。&lt;/p&gt;
&lt;h2 id=&#34;什麼時候需要-pro--ultra&#34;&gt;什麼時候需要 Pro / Ultra
&lt;/h2&gt;&lt;p&gt;很多人其實不需要高階檔位。&lt;/p&gt;
&lt;p&gt;你需要 ChatGPT Pro 的典型信號：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每天長時間使用 ChatGPT。&lt;/li&gt;
&lt;li&gt;Plus 額度經常不夠。&lt;/li&gt;
&lt;li&gt;高頻使用 Codex。&lt;/li&gt;
&lt;li&gt;經常跑 deep research、agent mode、複雜推理。&lt;/li&gt;
&lt;li&gt;需要 GPT-5.5 Pro 這類更高階模型。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;你需要 Google AI Ultra 的典型信號：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;高頻使用 Gemini、Flow、Antigravity。&lt;/li&gt;
&lt;li&gt;需要更高 Gemini / Antigravity 使用額度。&lt;/li&gt;
&lt;li&gt;做影片創作、AI 影像、長上下文研究。&lt;/li&gt;
&lt;li&gt;深度依賴 Google 生態和新功能優先體驗。&lt;/li&gt;
&lt;li&gt;需要 Gemini Spark、Project Genie 或更高級訂閱權益。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你只是每天問幾次問題、偶爾寫文章或改程式碼，Plus / Pro、AI Pro / Ultra 這類高階檔位可能都不是剛需。&lt;/p&gt;
&lt;h2 id=&#34;最省錢的訂閱策略&#34;&gt;最省錢的訂閱策略
&lt;/h2&gt;&lt;p&gt;更推薦這種組合：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先選一個主力付費訂閱。&lt;/li&gt;
&lt;li&gt;另一個平台先用免費層。&lt;/li&gt;
&lt;li&gt;真正需要 API 時再按量付費。&lt;/li&gt;
&lt;li&gt;影片、Agent、深度研究類高消耗功能按月開關，不要全年盲訂。&lt;/li&gt;
&lt;li&gt;每月復盤一次：本月有沒有真的用滿額度？&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;幾個常見組合：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;普通辦公：ChatGPT Plus + Gemini 免費層。&lt;/li&gt;
&lt;li&gt;Google 生態使用者：Google AI Pro + ChatGPT 免費層。&lt;/li&gt;
&lt;li&gt;開發者：ChatGPT Plus/Pro + Gemini API/AI Studio 按需。&lt;/li&gt;
&lt;li&gt;影片創作者：Google AI Pro/Ultra + ChatGPT 免費層或 Plus。&lt;/li&gt;
&lt;li&gt;企業團隊：不要用個人套餐拼，直接評估 Business / Enterprise / Workspace 方案。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;訂閱前檢查清單&#34;&gt;訂閱前檢查清單
&lt;/h2&gt;&lt;p&gt;付費前先確認這些問題：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你的地區是否支援目標套餐？&lt;/li&gt;
&lt;li&gt;你要用的模型是否包含在該套餐裡？&lt;/li&gt;
&lt;li&gt;Codex、Antigravity、Flow、Omni 是否真的可用？&lt;/li&gt;
&lt;li&gt;影片功能是否有地區、年齡、排隊或解析度限制？&lt;/li&gt;
&lt;li&gt;API 呼叫是否包含在訂閱裡，還是單獨計費？&lt;/li&gt;
&lt;li&gt;文件上傳、上下文視窗、agent mode、deep research 是否有額度限制？&lt;/li&gt;
&lt;li&gt;資料隱私設定是否符合你的專案要求？&lt;/li&gt;
&lt;li&gt;你是否已經有 Google One、Workspace、ChatGPT Business 或學校/公司帳號權益？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;尤其要注意：個人訂閱不等於 API 免費，不等於商用無限額度，也不等於企業合規。&lt;/p&gt;
&lt;h2 id=&#34;小結&#34;&gt;小結
&lt;/h2&gt;&lt;p&gt;Google I/O 之後，Gemini 的競爭力明顯增強，尤其是在影片、多模態、Google 生態、Android、AI Studio 和 Antigravity 方向。但 ChatGPT 仍然是更穩的通用主力，特別是在日常寫作、複雜問答、文件分析、程式碼輔助和 Codex 工作流裡。&lt;/p&gt;
&lt;p&gt;最簡單的判斷是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不知道選哪個：先選 ChatGPT Plus。&lt;/li&gt;
&lt;li&gt;深度 Google 使用者：選 Google AI Pro。&lt;/li&gt;
&lt;li&gt;高頻開發者：看 Codex 和 Antigravity 誰更貼近你的工作流。&lt;/li&gt;
&lt;li&gt;影片創作者：優先看 Gemini Omni、Flow 和 Google AI Pro / Ultra。&lt;/li&gt;
&lt;li&gt;企業使用者：按合規、權限、審計和現有辦公生態選，而不是按模型熱度選。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI 訂閱不是越多越好。真正划算的方式，是明確一個主力工作流，再把其他平台作為補充，而不是為每一場發布會都多開一個長期訂閱。&lt;/p&gt;
&lt;p&gt;參考來源：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://chatgpt.com/pricing/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;OpenAI：ChatGPT Pricing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://help.openai.com/en/articles/11369540-using-codex-with-your-chatgpt-plan&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;OpenAI Help：Using Codex with your ChatGPT plan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://blog.google/products-and-platforms/products/google-one/google-ai-subscriptions/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Google Blog：Everything new in Google AI subscriptions from I/O 2026&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://blog.google/innovation-and-ai/technology/developers-tools/google-io-2026-developer-highlights/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Google Blog：I/O 2026 developer highlights&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://support.google.com/gemini/answer/16275805&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Google Help：Gemini Apps limits and upgrades for Google AI subscribers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Google I/O 2026 主要內容總結：Gemini 3.5、Omni、Antigravity 與系統級 Agent</title>
        <link>https://knightli.com/zh-tw/2026/05/21/google-io-2026-gemini-agentic-ai-summary/</link>
        <pubDate>Thu, 21 May 2026 00:07:06 +0800</pubDate>
        
        <guid>https://knightli.com/zh-tw/2026/05/21/google-io-2026-gemini-agentic-ai-summary/</guid>
        <description>&lt;p&gt;Google I/O 2026 的主線很清楚：Google 正在把 Gemini 從「模型」和「聊天助手」推進到一個更完整的 Agent 生態。它不只是回答問題，而是要進入搜尋、Android、開發工具、影片創作、購物、Workspace、硬體和企業平台，幫助使用者完成更長鏈路的任務。&lt;/p&gt;
&lt;p&gt;本文按官方發布資訊和開發者視角，整理 Google I/O 2026 的主要內容。實際開發時仍應以 Google、Android Developers 和 Gemini API 官方文件為準。&lt;/p&gt;
&lt;h2 id=&#34;一句話總結&#34;&gt;一句話總結
&lt;/h2&gt;&lt;p&gt;Google I/O 2026 的關鍵詞是 &lt;code&gt;agentic Gemini era&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;Google 發布或強化了幾條線：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Gemini 3.5 Flash&lt;/code&gt;：強調速度、行動能力和 Agent 工作流。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Gemini Omni&lt;/code&gt;：從任意輸入生成內容，重點從影片創作和編輯開始。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Gemini app&lt;/code&gt;：從聊天助手走向主動、全天候、可執行任務的個人 Agent。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Google Antigravity 2.0&lt;/code&gt;：從 AI 編程工具升級為 Agent 優先的開發平台。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Gemini API Managed Agents&lt;/code&gt;：透過 API 建立能推理、用工具、執行程式碼的託管 Agent。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Google AI Studio&lt;/code&gt;：擴展到行動端、Android 原生支援和專案匯出到 Antigravity。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Search&lt;/code&gt;、&lt;code&gt;Shopping&lt;/code&gt;、&lt;code&gt;YouTube&lt;/code&gt;、&lt;code&gt;Workspace&lt;/code&gt;、&lt;code&gt;Android&lt;/code&gt;：都在接入更強的 Gemini 和 Agent 能力。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;換句話說，Google 不再只展示「模型有多聰明」，而是在展示「模型如何進入產品、工具和系統，真正替使用者執行任務」。&lt;/p&gt;
&lt;h2 id=&#34;gemini-35-flash從提示詞走向行動&#34;&gt;Gemini 3.5 Flash：從提示詞走向行動
&lt;/h2&gt;&lt;p&gt;Gemini 3.5 是 Google 在 I/O 2026 推出的新一代模型系列，首個公開重點是 &lt;code&gt;Gemini 3.5 Flash&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;Google 對它的定位不是單純「更快的聊天模型」，而是用於真實 Agent 工作流的高速引擎。官方開發者文章提到，3.5 Flash 結合前沿智能和高速度，用來支撐從 prompt 到 action 的轉變。&lt;/p&gt;
&lt;p&gt;它的主要意義在於：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;面向 Agent 和 coding 場景最佳化。&lt;/li&gt;
&lt;li&gt;支援更長鏈路任務和工具呼叫。&lt;/li&gt;
&lt;li&gt;在 Antigravity、Gemini API、Google AI Studio、Android Studio、Gemini Enterprise 等入口提供。&lt;/li&gt;
&lt;li&gt;更適合需要快速回應、多輪執行和頻繁工具呼叫的應用。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;對開發者來說，Gemini 3.5 Flash 不只是一個模型選項，而是 Google 新 Agent 工具鏈的預設動力源之一。&lt;/p&gt;
&lt;h2 id=&#34;gemini-omni影片和世界模型能力成為重點&#34;&gt;Gemini Omni：影片和世界模型能力成為重點
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Gemini Omni&lt;/code&gt; 是 I/O 2026 另一個核心發布。Google 對它的描述是：從任意輸入創作內容，目前重點從影片開始。&lt;/p&gt;
&lt;p&gt;它的看點主要有三類：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;多模態輸入：文字、圖像、影片、音訊等都可以作為參考。&lt;/li&gt;
&lt;li&gt;影片編輯：使用者可以用自然語言多輪修改影片，而不是一次性生成後就結束。&lt;/li&gt;
&lt;li&gt;世界理解：強調物理、場景、動作、敘事和視聽一致性。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這意味著 AI 影片工具的方向正在從「輸入一句提示詞生成短片」走向「像和剪輯師溝通一樣逐輪修改」。對創作者來說，真正有價值的不是一次生成，而是可控、可追蹤、可迭代的編輯流程。&lt;/p&gt;
&lt;h2 id=&#34;gemini-app從聊天助手變成全天候個人-agent&#34;&gt;Gemini App：從聊天助手變成全天候個人 Agent
&lt;/h2&gt;&lt;p&gt;Google 也把 Gemini app 明確推向更 Agent 化的方向。官方文章提到，Gemini app 正在變得更主動，提供日常簡報和全天候幫助。&lt;/p&gt;
&lt;p&gt;幾個重點包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Gemini 3.5 Flash&lt;/code&gt; 進入 Gemini app。&lt;/li&gt;
&lt;li&gt;新 UI 和更動態的互動體驗。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Gemini Spark&lt;/code&gt; 這類個人 AI Agent 概念。&lt;/li&gt;
&lt;li&gt;Proactive daily briefs，主動整理使用者每天需要關注的資訊。&lt;/li&gt;
&lt;li&gt;更強調 7×24 小時背景協助，而不是使用者每次都主動發起聊天。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這部分對普通使用者影響最大。過去 Gemini 更像「你問我答」的助手；I/O 2026 之後，Google 想讓它更像能持續跟進任務、主動提醒、跨產品協同的個人智能體。&lt;/p&gt;
&lt;h2 id=&#34;antigravity-20開發者工具轉向-agent-優先&#34;&gt;Antigravity 2.0：開發者工具轉向 Agent 優先
&lt;/h2&gt;&lt;p&gt;開發者側最重要的發布之一是 &lt;code&gt;Google Antigravity 2.0&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;Google 將 Antigravity 定位為 agent-first development platform。I/O 2026 之後，它不只是幫助寫程式碼，而是要幫助開發者從想法、原型、Agent 編排到生產應用交付。&lt;/p&gt;
&lt;p&gt;官方列出的核心變化包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Antigravity 2.0 獨立桌面應用。&lt;/li&gt;
&lt;li&gt;支援多 Agent 並行編排。&lt;/li&gt;
&lt;li&gt;支援動態 subagents。&lt;/li&gt;
&lt;li&gt;支援背景定時任務。&lt;/li&gt;
&lt;li&gt;與 Google AI Studio、Android、Firebase 等生態整合。&lt;/li&gt;
&lt;li&gt;提供 Antigravity CLI，面向終端機使用者。&lt;/li&gt;
&lt;li&gt;提供 Antigravity SDK，用於自訂 Agent 行為和部署。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這說明 AI 編程工具正在從「程式碼補全 / 對話生成」進入下一階段：開發者要管理的是多個可執行 Agent，而不只是一個聊天視窗。&lt;/p&gt;
&lt;h2 id=&#34;gemini-api-managed-agents把-agent-託管成-api-能力&#34;&gt;Gemini API Managed Agents：把 Agent 託管成 API 能力
&lt;/h2&gt;&lt;p&gt;Google 還推出了 &lt;code&gt;Managed Agents in the Gemini API&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;官方描述中，這類 Agent 可以透過一次 API 呼叫建立，具備推理、工具使用和在隔離 Linux 環境中執行程式碼的能力，並且由 Antigravity agent harness 提供支援。&lt;/p&gt;
&lt;p&gt;這件事對開發者很關鍵：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不必自己搭完整 Agent 執行環境。&lt;/li&gt;
&lt;li&gt;可以獲得持久、隔離的執行環境。&lt;/li&gt;
&lt;li&gt;多輪互動可以保留檔案和狀態。&lt;/li&gt;
&lt;li&gt;可以用 markdown 技能、自訂指令和模板擴展 Agent。&lt;/li&gt;
&lt;li&gt;可透過 Interactions API 和 Google AI Studio 使用。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果這條線成熟，Agent 平台會越來越像雲服務：開發者不再只呼叫模型，而是呼叫一個帶狀態、工具、執行環境和安全邊界的 Agent。&lt;/p&gt;
&lt;h2 id=&#34;google-ai-studio從-prompt-playground-走向應用生成入口&#34;&gt;Google AI Studio：從 prompt playground 走向應用生成入口
&lt;/h2&gt;&lt;p&gt;I/O 2026 中，Google AI Studio 的定位也更進一步。&lt;/p&gt;
&lt;p&gt;重點變化包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Google AI Studio mobile app，可在行動端捕捉想法和生成原型。&lt;/li&gt;
&lt;li&gt;Workspace API 整合，讓 Agent 能更自然地接入 Google Workspace。&lt;/li&gt;
&lt;li&gt;專案可匯出到 Antigravity，帶著上下文繼續本地開發和生產化。&lt;/li&gt;
&lt;li&gt;增加 Android 原生支援，可以用 prompt 構建 Android 應用。&lt;/li&gt;
&lt;li&gt;支援對接 Google Play Console，把應用發布到測試軌道。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這讓 AI Studio 從「調提示詞和試模型」變成「從想法到應用」的入口。它和 Antigravity 的關係也更清楚：AI Studio 適合快速構思和生成，Antigravity 適合繼續開發、編排、除錯和交付。&lt;/p&gt;
&lt;h2 id=&#34;android-與-appfunctions行動端-agent-的關鍵接口&#34;&gt;Android 與 AppFunctions：行動端 Agent 的關鍵接口
&lt;/h2&gt;&lt;p&gt;Android 系統級 Agent 是這次值得單獨看的方向，但需要用更準確的接口和產品邊界來理解。&lt;/p&gt;
&lt;p&gt;目前最值得關注的是 Android 官方的 &lt;code&gt;AppFunctions&lt;/code&gt;。官方文件說明，AppFunctions 是一種 Android 平台 API，並帶有 Jetpack 庫，可以讓應用把自身能力暴露給智能體、助手和其他有權限的呼叫方。它還簡化了 Android MCP 整合。&lt;/p&gt;
&lt;p&gt;它的意義在於：行動端自動化不再只能依賴截圖、OCR、模擬點擊和 UI 控件定位。&lt;/p&gt;
&lt;p&gt;傳統行動端自動化路徑是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;識別螢幕。&lt;/li&gt;
&lt;li&gt;找按鈕。&lt;/li&gt;
&lt;li&gt;模擬點擊。&lt;/li&gt;
&lt;li&gt;等待頁面變化。&lt;/li&gt;
&lt;li&gt;出錯後重試。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AppFunctions 的方向是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;應用聲明自己能做什麼。&lt;/li&gt;
&lt;li&gt;Agent 在授權下呼叫這些能力。&lt;/li&gt;
&lt;li&gt;系統負責權限、呼叫邊界和安全約束。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這會影響 Android 應用設計。未來應用不只要做給人看的 UI，還要把核心功能設計成可被 Agent 呼叫的能力接口。&lt;/p&gt;
&lt;h2 id=&#34;search購物和內容產品也在-agent-化&#34;&gt;Search、購物和內容產品也在 Agent 化
&lt;/h2&gt;&lt;p&gt;Google I/O 2026 的變化不只在模型和開發者工具裡，搜尋和消費產品也在同步變化。&lt;/p&gt;
&lt;p&gt;官方 I/O 彙總中提到：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Search 進入新的 AI Search 階段。&lt;/li&gt;
&lt;li&gt;Information agents 出現在搜尋場景中。&lt;/li&gt;
&lt;li&gt;Gemini Spark 和 Daily Brief 進入 Gemini app。&lt;/li&gt;
&lt;li&gt;Universal Cart 讓購物車更智能。&lt;/li&gt;
&lt;li&gt;Ask YouTube 讓影片內容可以被對話式查詢和跳轉。&lt;/li&gt;
&lt;li&gt;Gemini 能力繼續擴展到更多產品和形態。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這些發布說明 Google 的 Agent 方向不是單點產品，而是橫向鋪到搜尋、影片、購物、辦公、行動和硬體場景中。&lt;/p&gt;
&lt;h2 id=&#34;對開發者的實際影響&#34;&gt;對開發者的實際影響
&lt;/h2&gt;&lt;p&gt;Google I/O 2026 對開發者最大的影響，不是「又多了一個模型」，而是開發對象變了。&lt;/p&gt;
&lt;p&gt;以前開發者主要構建：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;App。&lt;/li&gt;
&lt;li&gt;網站。&lt;/li&gt;
&lt;li&gt;API。&lt;/li&gt;
&lt;li&gt;外掛。&lt;/li&gt;
&lt;li&gt;自動化腳本。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;接下來還要構建：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可被 Agent 呼叫的應用能力。&lt;/li&gt;
&lt;li&gt;多 Agent 工作流。&lt;/li&gt;
&lt;li&gt;有狀態的工具執行環境。&lt;/li&gt;
&lt;li&gt;可稽核的自動化流程。&lt;/li&gt;
&lt;li&gt;人在回路確認機制。&lt;/li&gt;
&lt;li&gt;與 MCP、AppFunctions、Workspace API、Playwright、Firebase 等工具的整合。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;軟體會越來越像「能力集合」，而不僅是「介面集合」。誰能把自己的能力清晰、可靠、安全地開放給 Agent，誰就更容易進入使用者的自動化任務鏈。&lt;/p&gt;
&lt;h2 id=&#34;對行動端自動化的影響&#34;&gt;對行動端自動化的影響
&lt;/h2&gt;&lt;p&gt;行動端自動化會從「GUI 優先」逐步變成「接口優先，GUI 兜底」。&lt;/p&gt;
&lt;p&gt;短期看，截圖識別、OCR、模擬點擊、瀏覽器自動化仍然有價值，因為大量舊應用沒有標準接口。&lt;/p&gt;
&lt;p&gt;長期看，只要 Android AppFunctions、MCP 和系統級權限模型成熟，穩定的任務執行會更偏向：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;優先呼叫應用聲明的能力。&lt;/li&gt;
&lt;li&gt;必要時呼叫系統接口。&lt;/li&gt;
&lt;li&gt;再必要時用 GUI 自動化兜底。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這會改變 RPA、行動端 Agent、測試工具和應用生態。應用越願意開放能力，越容易被系統級 Agent 呼叫；不開放能力的應用，可能仍然只能被「看螢幕、點螢幕」的舊方式操作。&lt;/p&gt;
&lt;h2 id=&#34;安全權限和稽核會成為硬約束&#34;&gt;安全、權限和稽核會成為硬約束
&lt;/h2&gt;&lt;p&gt;Agent 能力越強，風險越大。&lt;/p&gt;
&lt;p&gt;如果 Agent 可以跨應用執行任務、呼叫支付、修改設定、存取檔案和讀取上下文，就必須有清晰的安全邊界：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;權限分級。&lt;/li&gt;
&lt;li&gt;使用者明確授權。&lt;/li&gt;
&lt;li&gt;敏感操作二次確認。&lt;/li&gt;
&lt;li&gt;沙箱隔離。&lt;/li&gt;
&lt;li&gt;操作日誌。&lt;/li&gt;
&lt;li&gt;可撤銷和可回滾。&lt;/li&gt;
&lt;li&gt;企業稽核與合規。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這也是為什麼 Google 會強調託管 Agent 的隔離環境、AppFunctions 的權限要求、企業平台和可控部署。Agent 的未來不是「無所不能」，而是在安全邊界內可執行、可追蹤、可治理。&lt;/p&gt;
&lt;h2 id=&#34;小結&#34;&gt;小結
&lt;/h2&gt;&lt;p&gt;Google I/O 2026 的主要內容可以概括為一句話：Google 正在把 Gemini 打造成橫跨模型、應用、系統、開發工具和硬體的 Agent 平台。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Gemini 3.5 Flash&lt;/code&gt; 提供速度和行動能力，&lt;code&gt;Gemini Omni&lt;/code&gt; 把多模態創作推向影片和世界理解，&lt;code&gt;Gemini app&lt;/code&gt; 走向主動個人助手，&lt;code&gt;Antigravity 2.0&lt;/code&gt; 和 &lt;code&gt;Managed Agents&lt;/code&gt; 把開發者工具推向 Agent 原生，&lt;code&gt;AppFunctions&lt;/code&gt; 則讓 Android 應用開始為智能體暴露能力。&lt;/p&gt;
&lt;p&gt;對開發者來說，接下來要關注的不只是模型參數，而是：如何把應用能力結構化、如何接入 Agent 工具鏈、如何設計權限和稽核，以及如何讓自己的產品在系統級 Agent 生態裡被安全可靠地呼叫。&lt;/p&gt;
&lt;p&gt;參考來源：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://blog.google/innovation-and-ai/technology/developers-tools/google-io-2026-collection/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Google Blog：Google I/O 2026 新聞與發布彙總&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://blog.google/innovation-and-ai/technology/developers-tools/google-io-2026-developer-highlights/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Google Blog：I/O 2026 developer highlights&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://blog.google/innovation-and-ai/products/gemini-app/next-evolution-gemini-app/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Google Blog：The Gemini app becomes more agentic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://developer.android.com/ai/appfunctions?hl=zh-cn&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Android Developers：AppFunctions 概覽&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Gemini 3.5 Flash 和 Gemini Omni 怎麼免費用：普通使用者與開發者入口整理</title>
        <link>https://knightli.com/zh-tw/2026/05/20/gemini-3-5-flash-omni-free-access/</link>
        <pubDate>Wed, 20 May 2026 23:13:35 +0800</pubDate>
        
        <guid>https://knightli.com/zh-tw/2026/05/20/gemini-3-5-flash-omni-free-access/</guid>
        <description>&lt;p&gt;Google 發布 Gemini 3.5 Flash 和 Gemini Omni 後，最實際的問題不是 benchmark，而是普通使用者和開發者到底怎麼用，哪些入口免費，哪些入口只是低門檻試用。&lt;/p&gt;
&lt;p&gt;先說結論：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;想聊天、寫作、看圖、日常問答：優先用 Gemini app。&lt;/li&gt;
&lt;li&gt;想測試 Gemini 3.5 Flash 參數、提示詞和多模態輸入：用 Google AI Studio。&lt;/li&gt;
&lt;li&gt;想寫程式呼叫 Gemini 3.5 Flash：用 AI Studio 產生 API key。&lt;/li&gt;
&lt;li&gt;想在終端機裡免費試用：可以看 Gemini CLI。&lt;/li&gt;
&lt;li&gt;想體驗 Gemini Omni 的影片編輯：優先看 Gemini app 和 Google Flow。&lt;/li&gt;
&lt;li&gt;想做正式生產：不要依賴免費額度，應該轉到付費 API 或 Vertex AI。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;注意：免費額度、地區開放、訂閱層級和模型下拉選單會隨時間變化。本文寫作時間是 2026 年 5 月 20 日，正式使用前要以 Google 當前頁面為準。&lt;/p&gt;
&lt;h2 id=&#34;gemini-35-flash-免費用法一gemini-app&#34;&gt;Gemini 3.5 Flash 免費用法一：Gemini app
&lt;/h2&gt;&lt;p&gt;最簡單的入口是 Gemini app：&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://gemini.google.com/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://gemini.google.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;使用方式很直接：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;打開 Gemini。&lt;/li&gt;
&lt;li&gt;登入 Google 帳號。&lt;/li&gt;
&lt;li&gt;在模型選擇裡找 &lt;code&gt;3.5 Flash&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;直接開始對話。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;這個入口適合普通使用者。你可以用它做寫作、總結、圖片理解、檔案內容分析、日常問答和簡單規劃。根據公開報導，Gemini 3.5 Flash 已面向全球使用者開放，並可在 Gemini 的模型下拉選單中選擇。&lt;/p&gt;
&lt;p&gt;限制也很明確：免費使用者通常會有每日訊息數量、地區和功能限制。如果超過限制，就需要等待額度刷新或升級訂閱。&lt;/p&gt;
&lt;h2 id=&#34;gemini-35-flash-免費用法二google-ai-studio&#34;&gt;Gemini 3.5 Flash 免費用法二：Google AI Studio
&lt;/h2&gt;&lt;p&gt;如果你不是只想聊天，而是想調提示詞、看參數、測試結構化輸出，Google AI Studio 更合適：&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://aistudio.google.com/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://aistudio.google.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;基本流程：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;登入 Google AI Studio。&lt;/li&gt;
&lt;li&gt;新建 prompt。&lt;/li&gt;
&lt;li&gt;在模型下拉選單裡選擇 &lt;code&gt;gemini-3.5-flash&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;輸入提示詞並執行。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;AI Studio 的好處是控制能力更強。你可以調溫度、系統指令、結構化輸出、多圖輸入，還能把測試好的提示詞匯出成程式碼或 API 呼叫。&lt;/p&gt;
&lt;p&gt;對開發者來說，AI Studio 是免費的試驗台。先在這裡把提示詞和輸入格式調好，再進入 API 接入，會少浪費很多額度。&lt;/p&gt;
&lt;h2 id=&#34;gemini-35-flash-免費用法三免費-api-key&#34;&gt;Gemini 3.5 Flash 免費用法三：免費 API key
&lt;/h2&gt;&lt;p&gt;開發者最關心的是 API。AI Studio 可以建立 Gemini API key，用來呼叫 &lt;code&gt;gemini-3.5-flash&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;基本流程：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;打開 Google AI Studio。&lt;/li&gt;
&lt;li&gt;找到 &lt;code&gt;Get API key&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;選擇或建立專案。&lt;/li&gt;
&lt;li&gt;建立 API key。&lt;/li&gt;
&lt;li&gt;把 key 儲存到本機環境變數。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Python 範例：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;google&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;genai&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;client&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;genai&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Client&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;api_key&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;environ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;GEMINI_API_KEY&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;response&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;models&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;generate_content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;gemini-3.5-flash&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;contents&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;用三句話解釋 Gemini 3.5 Flash 適合什麼場景。&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Node.js 範例：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;GoogleGenAI&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;@google/genai&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;ai&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;GoogleGenAI&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;apiKey&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;process&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;env&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;GEMINI_API_KEY&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;ai&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;models&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;generateContent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;gemini-3.5-flash&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;contents&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;用三句話解釋 Gemini 3.5 Flash 適合什麼場景。&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;curl&lt;/code&gt; 範例：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://generativelanguage.googleapis.com/v1beta/models/gemini-3.5-flash:generateContent&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -H &lt;span class=&#34;s2&#34;&gt;&amp;#34;x-goog-api-key: &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$GEMINI_API_KEY&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -H &lt;span class=&#34;s2&#34;&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -d &lt;span class=&#34;s1&#34;&gt;&amp;#39;{&amp;#34;contents&amp;#34;:[{&amp;#34;parts&amp;#34;:[{&amp;#34;text&amp;#34;:&amp;#34;Hello Gemini 3.5 Flash&amp;#34;}]}]}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;公開資料顯示，AI Studio 免費層通常會給 Gemini Flash 模型一定的每日請求額度。不同時間、地區和帳號狀態可能不同，常見說法包括每天約 1,500 次請求、每分鐘請求數限制和 token 限制。不要把這些數字寫死進生產計畫，正式上線前要查看 Google AI 當前定價和限制頁面。&lt;/p&gt;
&lt;h2 id=&#34;gemini-35-flash-免費用法四gemini-cli&#34;&gt;Gemini 3.5 Flash 免費用法四：Gemini CLI
&lt;/h2&gt;&lt;p&gt;如果你喜歡命令列，可以看 Gemini CLI。它適合臨時腳本、程式碼庫摘要、檔案讀取和終端機裡的快速問答。&lt;/p&gt;
&lt;p&gt;安裝方式通常是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npm install -g @google/gemini-cli
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然後執行：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gemini
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;CLI 更適合個人開發者日常使用，不適合生產整合。生產環境還是應該使用 API key、服務帳號、權限控制和可稽核的呼叫方式。&lt;/p&gt;
&lt;h2 id=&#34;gemini-omni-免費或低門檻用法gemini-app-和-google-flow&#34;&gt;Gemini Omni 免費或低門檻用法：Gemini app 和 Google Flow
&lt;/h2&gt;&lt;p&gt;Gemini Omni 是面向影片創作和編輯的多模態模型。它的核心能力不是普通文字問答，而是用自然語言多輪修改影片，並引用圖像、文字、影片、音訊等輸入。&lt;/p&gt;
&lt;p&gt;Google DeepMind 頁面給出的入口包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gemini app。&lt;/li&gt;
&lt;li&gt;Google Flow。&lt;/li&gt;
&lt;li&gt;YouTube Shorts。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;頁面也說明，需要 Google AI 訂閱，功能會因訂閱層級和地區不同而變化。因此，Gemini Omni 的「免費用法」要更謹慎理解：有些入口可能允許免費使用者看到或試用部分能力，但完整影片編輯能力可能需要訂閱、地區開放或產品灰度。&lt;/p&gt;
&lt;p&gt;如果你只是想體驗，建議按這個順序試：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先打開 Gemini app，查看是否有 Gemini Omni 或相關影片編輯入口。&lt;/li&gt;
&lt;li&gt;再打開 Google Flow：&lt;a class=&#34;link&#34; href=&#34;https://flow.google/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://flow.google/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;如果你做短影片內容，再關注 YouTube Shorts 裡是否出現 Omni 相關編輯能力。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果入口不可見，通常不是你操作錯了，而是帳號、地區、訂閱層級或灰度範圍暫時不滿足。&lt;/p&gt;
&lt;h2 id=&#34;gemini-omni-適合怎麼用&#34;&gt;Gemini Omni 適合怎麼用
&lt;/h2&gt;&lt;p&gt;Gemini Omni 更適合創作者，而不是普通聊天。&lt;/p&gt;
&lt;p&gt;你可以嘗試這些方向：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;上傳或選擇一段影片，讓它改變風格。&lt;/li&gt;
&lt;li&gt;讓影片中的某個動作變得更誇張。&lt;/li&gt;
&lt;li&gt;用一張參考圖替換場景裡的物體或角色。&lt;/li&gt;
&lt;li&gt;分多輪修改鏡頭、動作、環境和風格。&lt;/li&gt;
&lt;li&gt;把草圖、參考圖、音訊或影片組合成一個新輸出。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;提示詞可以寫得像給剪輯師提要求：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;保持原影片的人物和房間結構不變，把鏡子觸碰後的效果改成液體波紋，動作要自然，光線不要突然變化。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;多輪編輯時，不要一次塞太多要求。更穩妥的做法是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先改主體動作。&lt;/li&gt;
&lt;li&gt;再改風格。&lt;/li&gt;
&lt;li&gt;再改鏡頭角度。&lt;/li&gt;
&lt;li&gt;最後調節聲音、文字和節奏。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;這樣更容易保持一致性，也更容易定位是哪一步出了問題。&lt;/p&gt;
&lt;h2 id=&#34;免費使用時最容易踩的坑&#34;&gt;免費使用時最容易踩的坑
&lt;/h2&gt;&lt;p&gt;第一，免費額度不是生產額度。免費 API key 適合測試、個人工具和原型，不適合承諾穩定服務。&lt;/p&gt;
&lt;p&gt;第二，不要把敏感資料發到免費或第三方入口。尤其是未公開程式碼、客戶資料、合約、密鑰、財務表格和內部文件。&lt;/p&gt;
&lt;p&gt;第三，注意資料使用設定。免費層可能有不同的資料使用策略，使用前要查看 AI Studio 或 Google 帳號裡的相關設定。&lt;/p&gt;
&lt;p&gt;第四，影片能力通常比文字能力更受限。Gemini Omni 這類影片編輯功能可能受訂閱、地區、排隊、時長、解析度和內容安全策略影響。&lt;/p&gt;
&lt;p&gt;第五，第三方「無限免費 API」要謹慎。很多閘道會限速、轉發請求、記錄日誌，甚至要求不透明的支付方式。敏感任務不建議走這類入口。&lt;/p&gt;
&lt;h2 id=&#34;應該選哪個入口&#34;&gt;應該選哪個入口
&lt;/h2&gt;&lt;p&gt;如果你是普通使用者：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gemini 3.5 Flash：用 Gemini app。&lt;/li&gt;
&lt;li&gt;Gemini Omni：先看 Gemini app，再看 Google Flow。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你是創作者：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用 Google Flow 體驗 Omni 影片工作流。&lt;/li&gt;
&lt;li&gt;用 Gemini app 做腳本、分鏡、提示詞和素材說明。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你是開發者：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用 AI Studio 除錯提示詞。&lt;/li&gt;
&lt;li&gt;用 API key 接入 &lt;code&gt;gemini-3.5-flash&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;用 Gemini CLI 做個人終端機工作流。&lt;/li&gt;
&lt;li&gt;生產環境考慮 Vertex AI 或付費 API。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你是企業：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不要依賴免費額度。&lt;/li&gt;
&lt;li&gt;重點看權限、日誌、稽核、資料駐留、合規和密鑰管理。&lt;/li&gt;
&lt;li&gt;影片生成和編輯還要補充浮水印、內容審核和版權流程。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;小結&#34;&gt;小結
&lt;/h2&gt;&lt;p&gt;Gemini 3.5 Flash 的免費使用路徑比較清楚：Gemini app、Google AI Studio、AI Studio API key、Gemini CLI 都可以作為低門檻入口。它適合聊天、寫作、編程、Agent 原型和多模態測試。&lt;/p&gt;
&lt;p&gt;Gemini Omni 的重點是影片編輯和多模態創作，入口主要在 Gemini app、Google Flow 和 YouTube Shorts，但完整能力更可能受訂閱和地區限制。它適合創作者先做體驗和概念驗證，不適合一開始就按穩定生產服務來規劃。&lt;/p&gt;
&lt;p&gt;最穩妥的策略是：文字和程式碼任務先用 Gemini 3.5 Flash 免費層試通；影片創作先用 Gemini Omni 在 Gemini app 或 Flow 裡驗證效果；真正要上線，再轉向可稽核、可計費、可控權限的正式方案。&lt;/p&gt;
&lt;p&gt;參考來源：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://deepmind.google/models/gemini/flash/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Google DeepMind：Gemini 3.5 Flash&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://deepmind.google/models/gemini-omni/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Google DeepMind：Gemini Omni&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://apidog.com/blog/how-to-use-gemini-3-5-for-free/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Apidog：How to Use Gemini 3.5 Flash for Free&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.freedidi.com/24249.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;freedidi 原文連結&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Gemini 3.5 正式發布：Flash 先行，Google 把重點放在 Agent 和長任務執行</title>
        <link>https://knightli.com/zh-tw/2026/05/20/google-gemini-3-5-flash-agent-coding/</link>
        <pubDate>Wed, 20 May 2026 22:51:31 +0800</pubDate>
        
        <guid>https://knightli.com/zh-tw/2026/05/20/google-gemini-3-5-flash-agent-coding/</guid>
        <description>&lt;p&gt;Google 在 2026 年 5 月 20 日正式發布 Gemini 3.5 系列。第一款開放使用的是 Gemini 3.5 Flash，定位不是單純的聊天模型，而是面向 Agent、程式碼生成和長時間複雜任務執行的模型。&lt;/p&gt;
&lt;p&gt;從這次公告看，Google 對 Gemini 3.5 的敘事很明確：模型不只要回答問題，還要能規劃、執行、檢查，並在多步驟任務中持續推進工作。&lt;/p&gt;
&lt;h2 id=&#34;gemini-35-flash-先行&#34;&gt;Gemini 3.5 Flash 先行
&lt;/h2&gt;&lt;p&gt;Gemini 3.5 Flash 已經面向多類使用者開放：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一般使用者可以透過 Gemini 應用程式和 Google 搜尋中的 AI 模式體驗。&lt;/li&gt;
&lt;li&gt;開發者可以透過 Google Antigravity、Google AI Studio、Android Studio 中的 Gemini API 使用。&lt;/li&gt;
&lt;li&gt;企業使用者可以透過 Gemini Enterprise Agent Platform 和 Gemini Enterprise 使用。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Google 同時提到，Gemini 3.5 Pro 仍在開發中，已經在 Google 內部使用，計畫在下個月推出。&lt;/p&gt;
&lt;p&gt;這說明 3.5 系列會繼續保留 Flash 與 Pro 的分層：Flash 更強調速度、成本和可規模化執行，Pro 則更可能面向更複雜、更高能力需求的場景。&lt;/p&gt;
&lt;h2 id=&#34;重點是-agent-和程式碼任務&#34;&gt;重點是 Agent 和程式碼任務
&lt;/h2&gt;&lt;p&gt;Google 把 Gemini 3.5 Flash 稱為目前最強的 Agent 與程式碼編寫模型之一。公告中提到，它在多項程式碼和 Agent 基準測試中超過 Gemini 3.1 Pro 的部分成績，例如 Terminal-Bench 2.1、GDPval-AA、MCP Atlas 和 CharXiv Reasoning。&lt;/p&gt;
&lt;p&gt;這些指標本身不是一般使用者最需要關心的內容。更重要的是，Google 正在把模型能力往「可執行工作流」上集中：不僅能寫程式碼，還能處理舊專案遷移、複雜應用開發、財務報表整理、資料分析和持續測試。&lt;/p&gt;
&lt;p&gt;在 Antigravity 開發架構中，Gemini 3.5 Flash 可以透過多個協作子代理處理大型任務。Google 展示的例子包括解析 AlphaZero 論文並實作可玩的遊戲、把舊版程式碼轉換為 Next.js、並行生成城市景觀和 UI 方案。&lt;/p&gt;
&lt;p&gt;這類能力的方向很清楚：AI 編程工具正在從「生成一段程式碼」走向「組織多個 Agent 完成一個專案」。&lt;/p&gt;
&lt;h2 id=&#34;多模態-ui-與圖形能力增強&#34;&gt;多模態 UI 與圖形能力增強
&lt;/h2&gt;&lt;p&gt;Gemini 3.5 Flash 繼承了 Gemini 3 的多模態基礎。Google 強調它可以生成更豐富的網頁 UI、互動動畫和圖形內容。&lt;/p&gt;
&lt;p&gt;公告中給出的應用場景包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;為研究論文生成互動式動畫。&lt;/li&gt;
&lt;li&gt;根據文字描述生成互動式硬體模型。&lt;/li&gt;
&lt;li&gt;為學校募款活動生成完整品牌概念。&lt;/li&gt;
&lt;li&gt;在短時間內為結帳流程生成多種 UX 方案。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這部分對開發者和產品團隊很有意義。模型不再只是輸出文字說明，而是能參與前端原型、互動設計和視覺化內容生成。&lt;/p&gt;
&lt;h2 id=&#34;企業場景把耗時流程自動化&#34;&gt;企業場景：把耗時流程自動化
&lt;/h2&gt;&lt;p&gt;Google 在公告中列舉了多個合作夥伴案例。Shopify 使用子代理分析複雜資料並預測商家成長；Macquarie Bank 測試用 3.5 Flash 閱讀超過 100 頁的複雜文件，加速開戶流程；Salesforce 將其整合到 Agentforce；Ramp 用它改進複雜發票 OCR；Xero 用 AI 代理處理行政流程；Databricks 用自動化工作流監控資料異常並給出修復建議。&lt;/p&gt;
&lt;p&gt;這些案例共同指向一個趨勢：企業採用大模型時，關注點正在從單次問答轉向流程自動化。模型是否便宜、快、能長時間穩定執行，會比單次回答是否驚豔更重要。&lt;/p&gt;
&lt;h2 id=&#34;gemini-spark個人-ai-代理&#34;&gt;Gemini Spark：個人 AI 代理
&lt;/h2&gt;&lt;p&gt;Google 還公布了 Gemini Spark。它是由 Gemini 3.5 Flash 驅動的個人 AI 代理，目標是在使用者引導下長期運行並主動執行任務。&lt;/p&gt;
&lt;p&gt;Gemini Spark 已經開始面向受信任測試人員推出，Google 計畫在下週向美國 Google AI Ultra 訂閱使用者開放 Beta 測試。&lt;/p&gt;
&lt;p&gt;這部分值得關注。Google 搜尋、Gemini 應用程式、Android、Workspace 和瀏覽器生態本來就覆蓋大量個人數位生活場景。如果個人 Agent 能與這些入口結合，影響可能比單獨的聊天機器人更大。&lt;/p&gt;
&lt;h2 id=&#34;安全機制繼續前移&#34;&gt;安全機制繼續前移
&lt;/h2&gt;&lt;p&gt;Google 表示 Gemini 3.5 按照 Frontier Safety Framework 開發，並強化了資訊安全和 CBRN 相關防護。公告還提到使用可解釋性工具，在模型給出回答前協助檢查和理解推理過程。&lt;/p&gt;
&lt;p&gt;這說明前沿模型的發布已經不只是能力競賽。越是強調 Agent、自動執行和長任務，安全控制、誤拒率、有害輸出防護和可解釋性就越重要。&lt;/p&gt;
&lt;h2 id=&#34;怎麼看-gemini-35&#34;&gt;怎麼看 Gemini 3.5
&lt;/h2&gt;&lt;p&gt;Gemini 3.5 Flash 的意義不只是「又一個新模型發布」。它更像是 Google 對下一階段 AI 產品形態的集中押注：模型要能調用工具、拆分任務、協作執行、生成 UI，並進入個人和企業工作流。&lt;/p&gt;
&lt;p&gt;對開發者來說，值得關注的是 Google Antigravity、AI Studio、Gemini API 和 Android Studio 中的實際體驗。對企業來說，重點是它能否在真實流程中穩定減少人工操作，而不是只看 benchmark。&lt;/p&gt;
&lt;p&gt;Gemini 3.5 Pro 還沒有正式開放。等 Pro 發布後，Flash 與 Pro 在能力、價格、速度和上下文處理上的差異，才會決定它們各自更適合哪些生產場景。&lt;/p&gt;
&lt;p&gt;參考來源：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://blog.google/intl/zh-tw/products/explore-get-answers/gemini-3-5/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Google Blog：Gemini 3.5 正式登場&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Google Gemini Spark 爆料解讀：一個 24 小時在線的 Gemini Agent 可能要來了</title>
        <link>https://knightli.com/zh-tw/2026/05/17/google-gemini-spark-ai-agent-leak/</link>
        <pubDate>Sun, 17 May 2026 11:58:08 +0800</pubDate>
        
        <guid>https://knightli.com/zh-tw/2026/05/17/google-gemini-spark-ai-agent-leak/</guid>
        <description>&lt;p&gt;Google 還沒有正式發布 &lt;code&gt;Gemini Spark&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;目前關於它的資訊，主要來自 Gemini Web 內部測試介面、社群截圖、TestingCatalog 報導，以及 36Kr / 新智元對相關爆料的整理。比較一致的說法是：&lt;code&gt;Gemini Spark BETA&lt;/code&gt; 可能是 Google 正在準備的全天候 AI Agent，定位不再只是聊天助手，而是能在後台處理郵件、線上任務和多步驟工作流的「日常 AI 代理」。&lt;/p&gt;
&lt;p&gt;所以這篇文章先把邊界說清楚：這是爆料解讀，不是 Google 官方發布稿。所有功能、命名和上線時間，都要等 Google 正式公告確認。&lt;/p&gt;
&lt;h2 id=&#34;先說結論&#34;&gt;先說結論
&lt;/h2&gt;&lt;p&gt;從目前曝光的資訊看，Gemini Spark 有三個重點：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;它可能是 Gemini 體系裡的 24 小時在線 Agent，而不是普通聊天模型。&lt;/li&gt;
&lt;li&gt;它會調用更廣泛的個人上下文，包括 Google 應用、聊天記錄、任務、登入網站和位置資訊等。&lt;/li&gt;
&lt;li&gt;它的風險和吸引力一樣大，因為它可能涉及資訊分享、遠端瀏覽器資料、購買動作和第三方服務調用。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果 Google 真把 Spark 推出來，Gemini 的定位會發生變化：從「回答問題的 AI」變成「替你持續處理事務的 AI」。&lt;/p&gt;
&lt;h2 id=&#34;gemini-spark-是什麼&#34;&gt;Gemini Spark 是什麼
&lt;/h2&gt;&lt;p&gt;TestingCatalog 在 2026 年 5 月 14 日報導，Google 正在 Gemini Web 中測試 &lt;code&gt;Gemini Spark BETA&lt;/code&gt;。曝光的歡迎文案把它描述成一個 everyday AI agent，可以 24/7 幫使用者處理 inbox、online tasks 和更多多步驟工作。&lt;/p&gt;
&lt;p&gt;36Kr / 新智元的文章也提到，Spark 被扒出後，外界看到的是一個「全時 Agent」方向：它可以全天候待命，處理收件匣、執行線上任務，甚至可能涉及購買和資訊分享。&lt;/p&gt;
&lt;p&gt;這意味著 Spark 不是一個單純的新模型名。它更像是 Gemini 產品層的一次升級：讓 Gemini 從對話窗口裡走出來，進入使用者的郵件、網頁、日程、任務和跨應用工作流。&lt;/p&gt;
&lt;h2 id=&#34;它可能怎麼工作&#34;&gt;它可能怎麼工作
&lt;/h2&gt;&lt;p&gt;根據 TestingCatalog 披露的隱藏 onboarding 文案，Gemini Spark 會從多種來源取得上下文，包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Connected Apps。&lt;/li&gt;
&lt;li&gt;skills。&lt;/li&gt;
&lt;li&gt;chats。&lt;/li&gt;
&lt;li&gt;tasks。&lt;/li&gt;
&lt;li&gt;使用者登入過的網站。&lt;/li&gt;
&lt;li&gt;Personal intelligence。&lt;/li&gt;
&lt;li&gt;location。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這些資訊會幫助 Spark 理解使用者想完成什麼，並在執行任務時調用必要的上下文。文案還提到，為了完成某些動作，Gemini 可能會把必要資訊分享給第三方，例如姓名、聯絡方式、文件、偏好，以及使用者可能認為敏感的資訊。&lt;/p&gt;
&lt;p&gt;如果這些描述最終屬實，Spark 的工作方式會更接近「帶上下文的代理系統」，而不是一次性問答。它不是只看當前一句 prompt，而是可能綜合長期偏好、連接應用、瀏覽器狀態和任務歷史。&lt;/p&gt;
&lt;h2 id=&#34;為什麼它重要&#34;&gt;為什麼它重要
&lt;/h2&gt;&lt;p&gt;Gemini Spark 的關鍵，不在於多一個聊天入口，而在於 Google 有天然的生態入口。&lt;/p&gt;
&lt;p&gt;OpenAI 和 Anthropic 可以做很強的 Agent，但它們很難天然擁有 Gmail、Calendar、Drive、Chrome、Android、Workspace 這條完整鏈路。Google 如果把 Spark 接進這些產品，使用者不需要額外搭建太多工作流，就能讓 Agent 進入日常事務。&lt;/p&gt;
&lt;p&gt;這會帶來三個變化。&lt;/p&gt;
&lt;p&gt;第一，Gemini 會從被動問答變成主動執行。使用者不再只是問「幫我總結這封郵件」，而是可能讓它持續整理 inbox、追蹤任務和執行後續動作。&lt;/p&gt;
&lt;p&gt;第二，Agent 會更依賴個人上下文。它越懂你的郵件、日程、文件、瀏覽器狀態和偏好，越可能給出有用結果。&lt;/p&gt;
&lt;p&gt;第三，權限邊界會變得更敏感。能做更多事，也意味著需要更清楚地知道它什麼時候能做、能做到哪一步、是否需要確認。&lt;/p&gt;
&lt;h2 id=&#34;風險點在哪裡&#34;&gt;風險點在哪裡
&lt;/h2&gt;&lt;p&gt;TestingCatalog 披露的文案裡，有幾處很值得關注。&lt;/p&gt;
&lt;p&gt;第一，Spark 是 experimental。也就是說，即便它上線，也不應被當成完全成熟、無需監督的系統。&lt;/p&gt;
&lt;p&gt;第二，雖然系統設計上會在敏感操作前徵求許可，但文案也提示，它可能會在未經詢問的情況下分享資訊或完成購買。&lt;/p&gt;
&lt;p&gt;第三，為了保持會話連續性，Gemini 會保存 remote browser data，比如登入細節和 remote code execution data。使用者可以在 Settings 中清除這些資料，也可以關閉 Connected Apps 和 Personal intelligence 相關能力。&lt;/p&gt;
&lt;p&gt;這幾個點合在一起，說明 Spark 的產品方向很激進：它要做真正能執行任務的 Agent，而不是只生成建議。但越接近真實執行，越需要嚴格的權限、稽核、確認和回滾機制。&lt;/p&gt;
&lt;h2 id=&#34;和-remyai-ultra-的關係&#34;&gt;和 Remy、AI Ultra 的關係
&lt;/h2&gt;&lt;p&gt;TestingCatalog 提到，Spark 可能是此前內部代號 &lt;code&gt;Remy&lt;/code&gt; 的 agentic Gemini upgrade 的重命名版本，也與面向 Google AI Ultra 訂閱使用者的 Gemini Agent 方向有關。&lt;/p&gt;
&lt;p&gt;如果這個線索成立，Spark 可能不是憑空出現的新專案，而是 Google 把此前較高階、較封閉的 Agent 能力重新包裝，並準備推向更大範圍使用者。&lt;/p&gt;
&lt;p&gt;36Kr / 新智元也把它描述成從 “Remy” 到 “Spark” 的升級：Gemini Agent 不再只是一個功能，而是要走向 24/7 的數位生活管家。&lt;/p&gt;
&lt;p&gt;不過這仍然是基於爆料資訊的判斷。Google 是否會使用 &lt;code&gt;Spark&lt;/code&gt; 這個正式名稱、是否只面向 AI Ultra、是否推出更輕量訂閱層，還要等官方確認。&lt;/p&gt;
&lt;h2 id=&#34;mcpskills-和工具生態&#34;&gt;MCP、skills 和工具生態
&lt;/h2&gt;&lt;p&gt;同一批社群截圖裡，還出現了 &lt;code&gt;MCP Tool Testing&lt;/code&gt; 這類模型選擇器入口。36Kr 文章認為，這可能暗示新 Gemini 會原生支援 MCP 第三方工具接入，Thinking 模式也會重構。&lt;/p&gt;
&lt;p&gt;這條線索和 Spark 放在一起看，很有意思。&lt;/p&gt;
&lt;p&gt;如果 Spark 只是「會聊天的助手」，skills 和 MCP 的意義有限。但如果 Spark 是一個長期運行的 Agent，它就需要可靠地調用工具、存取網頁、執行任務、讀寫上下文，並把結果交付給使用者。&lt;/p&gt;
&lt;p&gt;也就是說，Spark 可能不是單點功能，而是 Google Agent 工具生態的一部分：模型負責理解和規劃，skills / MCP / connected apps 負責執行和擴展。&lt;/p&gt;
&lt;h2 id=&#34;對普通使用者意味著什麼&#34;&gt;對普通使用者意味著什麼
&lt;/h2&gt;&lt;p&gt;如果 Gemini Spark 真的發布，普通使用者最直接的變化可能是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;郵件不只是被總結，而是可以被分類、跟進和轉成任務。&lt;/li&gt;
&lt;li&gt;網頁任務不只是給建議，而是可能在遠端瀏覽器中持續執行。&lt;/li&gt;
&lt;li&gt;日程、位置、偏好和歷史對話會變成 Agent 的長期上下文。&lt;/li&gt;
&lt;li&gt;購買、預訂、表單填寫等動作可能進入 AI 執行範圍。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這聽起來很方便，但使用者需要建立新的習慣：不再只看 AI 說了什麼，還要看 AI 準備做什麼、已經做了什麼、能不能撤回、有沒有記錄。&lt;/p&gt;
&lt;p&gt;未來 AI Agent 的體驗好不好，可能不只取決於模型聰不聰明，還取決於權限提示是否清楚、任務日誌是否可查、錯誤操作能不能恢復。&lt;/p&gt;
&lt;h2 id=&#34;對開發者和團隊意味著什麼&#34;&gt;對開發者和團隊意味著什麼
&lt;/h2&gt;&lt;p&gt;對開發者來說，Spark 的意義在於 Google 可能正在把 Agent 從「展示產品」推向真實工作流平台。&lt;/p&gt;
&lt;p&gt;如果 Spark 能穩定連接 Google 應用、第三方工具和瀏覽器狀態，那麼開發者會關心：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;API 或擴展機制是否開放。&lt;/li&gt;
&lt;li&gt;MCP 或 skills 是否可由第三方接入。&lt;/li&gt;
&lt;li&gt;企業管理員能否控制權限、資料留存和稽核。&lt;/li&gt;
&lt;li&gt;Agent 執行失敗時是否有可追蹤日誌。&lt;/li&gt;
&lt;li&gt;是否支援沙盒、審批流和敏感操作確認。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;對團隊來說，Spark 可能會先從 Gmail、Calendar、Docs、Drive、Chrome 這類高頻場景切入。它未必一開始就適合完全自動化高風險業務，但很適合作為 inbox triage、會議跟進、資料整理、市場研究和輕量營運任務的助手。&lt;/p&gt;
&lt;h2 id=&#34;現在應該怎麼看&#34;&gt;現在應該怎麼看
&lt;/h2&gt;&lt;p&gt;這條消息適合用「高可信方向，低確定細節」來理解。&lt;/p&gt;
&lt;p&gt;高可信方向是：Google 確實在推進更主動、更長期運行、更深度接入生態的 Gemini Agent。TestingCatalog 報導的 Gemini Web 測試文案、社群截圖和 36Kr 整理的多方爆料，都指向同一個方向。&lt;/p&gt;
&lt;p&gt;低確定細節是：正式名稱、上線時間、權限規則、訂閱層級、可用地區、是否開放 API、是否真的叫 Gemini Spark，都還不能下結論。&lt;/p&gt;
&lt;p&gt;所以現在最穩妥的判斷是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不要把 Spark 當成已經發布的正式產品。&lt;/li&gt;
&lt;li&gt;可以把它視為 Google 下一階段 AI Agent 路線的強訊號。&lt;/li&gt;
&lt;li&gt;真正值得等的是官方如何解釋權限、隱私、第三方資料分享和遠端瀏覽器資料保存。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;總結&#34;&gt;總結
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Gemini Spark&lt;/code&gt; 如果最終發布，可能會是 Gemini 從聊天助手走向全天候 Agent 的關鍵一步。它不只是換一個模型，而是把 Gemini 放進 Google 生態的郵件、網頁、任務、位置、個人智能和第三方服務裡。&lt;/p&gt;
&lt;p&gt;它的潛力很大：更主動、更貼近真實工作流，也更容易借助 Google 的生態分發給大量使用者。它的風險也同樣大：一旦 AI 能分享資訊、保存瀏覽器狀態、執行購買和調用第三方服務，權限邊界就必須非常清楚。&lt;/p&gt;
&lt;p&gt;所以 Gemini Spark 最值得關注的不是「它有多聰明」，而是 Google 準備怎樣讓一個 24 小時在線的 AI Agent 變得可控、可稽核、可信任。&lt;/p&gt;
&lt;p&gt;參考連結：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.testingcatalog.com/google-prepares-gemini-spark-ai-agent-ahead-of-i-o-launch/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;TestingCatalog：Google prepares Gemini Spark AI Agent ahead of I/O launch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://36kr.com/p/3810432812162816&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;36Kr：Gemini 3.5 Pro 全網首曝，編程追平 GPT-5.5，谷歌終於狠起來了&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Gemini 3.5 Pro 曝光：代號 Cappuccino，Google 想在編程和 Agent 上追回節奏</title>
        <link>https://knightli.com/zh-tw/2026/05/17/gemini-35-pro-cappuccino-spark-leak/</link>
        <pubDate>Sun, 17 May 2026 11:47:27 +0800</pubDate>
        
        <guid>https://knightli.com/zh-tw/2026/05/17/gemini-35-pro-cappuccino-spark-leak/</guid>
        <description>&lt;p&gt;Google 還沒有正式發布 &lt;code&gt;Gemini 3.5 Pro&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;目前能看到的資訊，主要來自開發者社群截圖、匿名跑分、爆料人消息和媒體轉述。36Kr / 新智元在 2026 年 5 月 15 日整理稱，新一代 Gemini 檢查點內部代號可能是 &lt;code&gt;Cappuccino&lt;/code&gt;，相關模型已經在社群和評測平台中提前曝光。&lt;/p&gt;
&lt;p&gt;這類資訊還不能等同於官方發布，但它透露出一個清晰方向：Google 正在試圖同時補上兩塊短板，一塊是編程和推理能力，另一塊是全天候 AI Agent。&lt;/p&gt;
&lt;h2 id=&#34;先說結論&#34;&gt;先說結論
&lt;/h2&gt;&lt;p&gt;這次爆料可以拆成三層來看：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Gemini 3.5 Pro&lt;/code&gt; 尚未正式發布，&lt;code&gt;Cappuccino&lt;/code&gt; 更像是內部檢查點或候選版本代號。&lt;/li&gt;
&lt;li&gt;曝光資訊顯示，新 Gemini 在程式碼生成、SVG / 互動式 Web 生成、多模態輸出上有明顯提升。&lt;/li&gt;
&lt;li&gt;Google 同步測試的 &lt;code&gt;Gemini Spark&lt;/code&gt;，可能比模型本身更關鍵，因為它指向 24 小時運行的個人 AI Agent。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;換句話說，這不是一條簡單的「模型跑分新聞」。它更像是 Google 在 I/O 前釋放出的產品路線訊號：模型要追趕 GPT-5.5，Agent 要搶占使用者工作流入口。&lt;/p&gt;
&lt;h2 id=&#34;cappuccino-是什麼&#34;&gt;Cappuccino 是什麼
&lt;/h2&gt;&lt;p&gt;36Kr 文章提到，網友 Lentils 放出的消息顯示，代號 &lt;code&gt;Cappuccino&lt;/code&gt; 的 &lt;code&gt;Gemini 3.5 Pro&lt;/code&gt; 檢查點已經開始產出。此前社群還在討論 &lt;code&gt;Gemini 3.2&lt;/code&gt;，但最新曝光直接跳到了 &lt;code&gt;3.5&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;如果這個命名最終屬實，說明 Google 可能希望把下一代 Gemini 包裝成一次更大的版本躍遷，而不是普通小版本更新。&lt;/p&gt;
&lt;p&gt;需要注意的是，&lt;code&gt;Cappuccino&lt;/code&gt; 現在仍應被視為爆料中的內部代號。它不等於 Google 已經公開上線的正式模型，也不代表最終發布名一定就是 &lt;code&gt;Gemini 3.5 Pro&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id=&#34;編程能力為什麼是焦點&#34;&gt;編程能力為什麼是焦點
&lt;/h2&gt;&lt;p&gt;這次爆料裡最受關注的點，是新 Gemini 的編程能力。&lt;/p&gt;
&lt;p&gt;36Kr 引述的社群截圖和跑分資訊顯示，新模型在以下任務上表現更強：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;生成 SVG 與視覺元件。&lt;/li&gt;
&lt;li&gt;生成互動式 Web 應用。&lt;/li&gt;
&lt;li&gt;處理動畫、3D、可調參數面板等複雜前端輸出。&lt;/li&gt;
&lt;li&gt;邏輯推理和程式碼生成能力有所提升。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;文章還提到，Abacus.AI CEO Bindu Reddy 轉述的說法是，&lt;code&gt;3.2 Flash&lt;/code&gt; 在編碼和推理上接近 &lt;code&gt;GPT-5.5&lt;/code&gt; 的水準，同時成本更低。另有媒體信源則認為，新款 Gemini 的整體性能大致追平 &lt;code&gt;GPT-5.5&lt;/code&gt;，但未必能帶來質變。&lt;/p&gt;
&lt;p&gt;這也是為什麼要謹慎看待「追平 GPT-5.5」這句話。它更像是不同爆料源和匿名評測中的相對判斷，而不是 Google 官方給出的基準測試結論。&lt;/p&gt;
&lt;h2 id=&#34;為什麼-google-急著補編程&#34;&gt;為什麼 Google 急著補編程
&lt;/h2&gt;&lt;p&gt;AI 編程已經從開發者工具變成了大模型競爭的核心戰場。&lt;/p&gt;
&lt;p&gt;OpenAI 有 Codex，Anthropic 有 Claude Code。它們不只服務工程師，也在把產品經理、設計師、營運人員帶進「自然語言生成可運行產品」的工作流裡。&lt;/p&gt;
&lt;p&gt;相比之下，Google 雖然有 Gemini 和 Antigravity，但在開發者心智裡一直沒有形成同等強度的預設入口。36Kr 文章也提到，Antigravity 在外部市場還沒有真正突圍，定價、額度提醒和體驗穩定性都曾引發社群討論。&lt;/p&gt;
&lt;p&gt;所以新 Gemini 如果要證明自己，編程會是最直接的戰場。它不一定只比拼「會不會寫程式碼」，還要比拼能不能穩定產出完整介面、理解複雜需求、調用工具、修復錯誤並融入真實開發流程。&lt;/p&gt;
&lt;h2 id=&#34;spark-可能比-35-pro-更重要&#34;&gt;Spark 可能比 3.5 Pro 更重要
&lt;/h2&gt;&lt;p&gt;同一波爆料裡，&lt;code&gt;Gemini Spark BETA&lt;/code&gt; 也被扒出。&lt;/p&gt;
&lt;p&gt;根據 TestingCatalog 等資訊源的說法，Spark 的定位接近「全天候 AI Agent」：它可以處理收件匣、執行線上任務、管理多步驟工作流，並連接 Google 應用、技能模組、聊天記錄、定時任務、登入網站、位置資訊等上下文。&lt;/p&gt;
&lt;p&gt;這意味著 Spark 不是一個普通聊天入口，而是一個可能長期在線、持續讀取上下文並替使用者執行任務的系統。&lt;/p&gt;
&lt;p&gt;它的吸引力很明顯：如果 Google 能把 Gmail、Calendar、Chrome、Android、Workspace 和 Gemini 串起來，Spark 會天然擁有 OpenAI 和 Anthropic 很難複製的分發優勢。&lt;/p&gt;
&lt;p&gt;但風險也同樣明顯。36Kr 文章提到，Spark 相關說明中出現了「可能在未經詢問的情況下分享資訊或完成購買」的表述。哪怕系統設計上會在敏感操作前徵求許可，這類 Agent 仍然會帶來隱私、授權邊界和誤操作風險。&lt;/p&gt;
&lt;h2 id=&#34;這對普通使用者意味著什麼&#34;&gt;這對普通使用者意味著什麼
&lt;/h2&gt;&lt;p&gt;如果你只是普通 Gemini 使用者，這次爆料真正值得關注的不是模型名，而是三個變化：&lt;/p&gt;
&lt;p&gt;第一，Google 可能會繼續強化「生成完整結果」的能力。以前使用者經常吐槽 Gemini 在視覺生成、SVG、前端頁面上容易偷懶，如果新模型能一次給出多個完整方案，體驗會明顯改善。&lt;/p&gt;
&lt;p&gt;第二，編程能力會繼續下放到更輕量的模型。爆料裡反覆提到 Flash 版本在編碼、推理和互動式生成上的提升，這意味著未來不一定只有 Pro 模型才能處理複雜任務。&lt;/p&gt;
&lt;p&gt;第三，Agent 會變得更主動。Spark 如果發布，Gemini 可能不再只是回答問題，而是開始長期接管郵件、網頁、購買、日程和跨應用任務。&lt;/p&gt;
&lt;p&gt;這對效率是好消息，對權限管理則是新挑戰。&lt;/p&gt;
&lt;h2 id=&#34;這對開發者意味著什麼&#34;&gt;這對開發者意味著什麼
&lt;/h2&gt;&lt;p&gt;開發者更應該關注兩個問題。&lt;/p&gt;
&lt;p&gt;第一個問題是工具生態。36Kr 文章提到，社群從模型選擇器裡看到了 &lt;code&gt;MCP Tool Testing&lt;/code&gt; 這類未公開入口。如果 Gemini 原生支援 MCP 或第三方工具測試，那麼它會更容易接入開發者自己的工具鏈。&lt;/p&gt;
&lt;p&gt;第二個問題是成本和穩定性。即便新 Gemini 在某些基準上追平 GPT-5.5，開發者最終還是會看三件事：實際程式碼品質、上下文穩定性、價格和額度是否可預期。&lt;/p&gt;
&lt;p&gt;過去一年，AI 編程工具競爭已經證明，模型能力只是門票。真正讓開發者留下來的，是能不能在日常專案裡持續可靠地改程式碼、跑測試、讀上下文、處理邊界條件。&lt;/p&gt;
&lt;h2 id=&#34;現在應該如何看待這條消息&#34;&gt;現在應該如何看待這條消息
&lt;/h2&gt;&lt;p&gt;這條消息適合用「強訊號、弱確認」來理解。&lt;/p&gt;
&lt;p&gt;強訊號在於：多個社群線索都指向 Google 正在準備更強的新 Gemini，以及更主動的 Gemini Spark Agent。&lt;/p&gt;
&lt;p&gt;弱確認在於：&lt;code&gt;Gemini 3.5 Pro&lt;/code&gt; 還沒有官方發布，&lt;code&gt;Cappuccino&lt;/code&gt; 仍是爆料代號，所謂「追平 GPT-5.5」的說法也需要等 Google 官方基準、第三方評測和真實使用者測試來驗證。&lt;/p&gt;
&lt;p&gt;所以現在最穩妥的判斷是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不要把它當成已發布產品。&lt;/li&gt;
&lt;li&gt;可以把它當成 Google 下一階段 Gemini 路線的提前預告。&lt;/li&gt;
&lt;li&gt;重點關注 I/O 或後續官方活動中是否會確認模型命名、API 可用性、價格、上下文窗口、工具調用和 Agent 權限邊界。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;總結&#34;&gt;總結
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Gemini 3.5 Pro / Cappuccino&lt;/code&gt; 的曝光說明，Google 可能正在為下一代 Gemini 做一次更強勢的版本推進。它要補的不是單一能力，而是整個 AI 工作流：模型要更會寫程式碼、生成介面和處理複雜推理，Spark 則要把 Gemini 推向全天候 Agent。&lt;/p&gt;
&lt;p&gt;但在官方發布前，所有跑分和截圖都只能作為線索。真正決定 Gemini 3.5 Pro 能否翻身的，不是代號是否好聽，而是它能否在真實開發、真實辦公和真實多步驟任務裡穩定勝出。&lt;/p&gt;
&lt;p&gt;參考連結：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://m.36kr.com/p/3810432812162816&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;36Kr：Gemini 3.5 Pro 全網首曝，編程追平 GPT-5.5，谷歌終於狠起來了&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.testingcatalog.com/google-prepares-gemini-spark-ai-agent-ahead-of-i-o-launch/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;TestingCatalog：Google prepares Gemini Spark AI agent ahead of I/O launch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://x.com/alexeheath/status/2054747125616169229&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;X：Alex Heath 關於新 Gemini 與 GPT-5.5 的爆料&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://x.com/Lentils80/status/2054628116094501377&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;X：Lentils 關於 Gemini 3.5 / Cappuccino 的爆料&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Gemini Intelligence on Android 解讀：Google 正在把手機變成主動式 AI 系統</title>
        <link>https://knightli.com/zh-tw/2026/05/17/google-gemini-intelligence-android/</link>
        <pubDate>Sun, 17 May 2026 09:13:32 +0800</pubDate>
        
        <guid>https://knightli.com/zh-tw/2026/05/17/google-gemini-intelligence-android/</guid>
        <description>&lt;p&gt;Google 在 2026 年 5 月 12 日發布了《A smarter, more proactive Android with Gemini Intelligence》，介紹 Gemini Intelligence on Android。它不是一個單獨的聊天 App，而是把 Gemini 能力放進 Android 系統、Chrome、Gboard、Autofill、widgets 和多設備體驗裡，讓手機從「等使用者點按鈕」變成「能主動幫使用者完成任務」的智能系統。&lt;/p&gt;
&lt;p&gt;簡單說，Google 想讓 Android 從 operating system 走向 intelligence system。手機不只是打開應用、顯示通知、運行設定，而是可以理解螢幕、應用、語音和個人上下文，在使用者確認下完成更複雜的操作。&lt;/p&gt;
&lt;h2 id=&#34;先說結論&#34;&gt;先說結論
&lt;/h2&gt;&lt;p&gt;Gemini Intelligence on Android 主要包含五個方向：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;多步任務自動化：讓 Gemini 在應用之間完成叫車、購物、找資料等流程。&lt;/li&gt;
&lt;li&gt;Chrome 智能瀏覽：在 Android 上總結網頁、比較資訊，並處理部分重複性網頁任務。&lt;/li&gt;
&lt;li&gt;Autofill 升級：結合 Gemini 和個人上下文，幫使用者填寫更複雜的表單。&lt;/li&gt;
&lt;li&gt;Rambler：把自然口語整理成更清楚、更專業的文字訊息。&lt;/li&gt;
&lt;li&gt;自然語言小工具：使用者用一句話描述需求，Android 生成自訂 widgets。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這些功能會從 2026 年夏天開始分批推出，先到部分 Samsung Galaxy 和 Google Pixel 手機，之後擴展到更多 Android 設備，包括手錶、汽車、眼鏡和筆電。&lt;/p&gt;
&lt;h2 id=&#34;多步任務自動化從建議變成執行&#34;&gt;多步任務自動化：從建議變成執行
&lt;/h2&gt;&lt;p&gt;Google 這次最重要的方向，是讓 Gemini 幫使用者跨應用完成多步任務。&lt;/p&gt;
&lt;p&gt;原文舉了幾個例子：使用者可以讓 Gemini 訂健身單車課程、從 Gmail 裡找到課程大綱並把需要的書加入購物車，或者看到一張旅遊宣傳圖後，直接讓 Gemini 在 Expedia 上尋找類似行程。&lt;/p&gt;
&lt;p&gt;這類能力的關鍵不只是「理解一句話」，而是要同時理解：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用者目前螢幕或圖片裡的內容。&lt;/li&gt;
&lt;li&gt;使用者授權範圍內的應用資訊。&lt;/li&gt;
&lt;li&gt;下一步應該打開哪個應用。&lt;/li&gt;
&lt;li&gt;哪些步驟可以自動執行。&lt;/li&gt;
&lt;li&gt;哪些步驟必須停下來讓使用者確認。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Google 特別強調，Gemini 會在使用者指令下行動，並在任務完成時停止，最終確認仍由使用者控制。這說明它不是完全自動代理，而是帶有人類確認環節的移動端 agent。&lt;/p&gt;
&lt;h2 id=&#34;螢幕和圖片上下文變得更重要&#34;&gt;螢幕和圖片上下文變得更重要
&lt;/h2&gt;&lt;p&gt;這次更新裡，一個值得注意的變化是 screen context 和 image context。&lt;/p&gt;
&lt;p&gt;以前手機助手更多依賴語音命令和應用內固定介面。Gemini Intelligence 則更強調「看見目前螢幕」。例如使用者在備忘錄裡有一份購物清單，可以長按電源鍵喚起 Gemini，讓它根據清單建立配送購物車。&lt;/p&gt;
&lt;p&gt;這意味著 Android AI 不只是聊天機器人，而是在嘗試理解使用者眼前的操作環境。未來手機 AI 的競爭，可能不只誰的模型回答更好，還包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;能不能理解目前螢幕。&lt;/li&gt;
&lt;li&gt;能不能跨應用執行。&lt;/li&gt;
&lt;li&gt;能不能在後台追蹤任務進度。&lt;/li&gt;
&lt;li&gt;能不能在關鍵節點可靠地讓使用者確認。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這也是移動端 AI 和網頁聊天 AI 的重要區別。&lt;/p&gt;
&lt;h2 id=&#34;chrome-智能瀏覽從搜尋到網頁任務代理&#34;&gt;Chrome 智能瀏覽：從搜尋到網頁任務代理
&lt;/h2&gt;&lt;p&gt;Google 表示，從 2026 年 6 月下旬開始，Android 設備會獲得更智能的 Gemini in Chrome。&lt;/p&gt;
&lt;p&gt;它可以幫助使用者研究、總結和比較網頁內容，也可以透過 Chrome auto browse 處理一些重複性網頁任務，比如預約、預訂停車位等。&lt;/p&gt;
&lt;p&gt;這說明 Gemini in Chrome 不只是「網頁摘要」功能，而是在向瀏覽器代理發展。瀏覽器本來就是使用者完成網頁任務的入口，如果 Gemini 能理解網頁、填寫資訊、比較選項並執行部分步驟，Chrome 就會從瀏覽工具變成任務執行介面。&lt;/p&gt;
&lt;p&gt;不過，這類功能也會面對幾個現實問題：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;網站結構複雜，自動操作容易失敗。&lt;/li&gt;
&lt;li&gt;表單、支付、登入和驗證碼等環節需要謹慎處理。&lt;/li&gt;
&lt;li&gt;使用者需要知道 Gemini 到底做了什麼。&lt;/li&gt;
&lt;li&gt;最終提交、付款或預訂最好仍保留人工確認。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以，真正的難點不只是模型能力，而是瀏覽器自動化、安全邊界和使用者信任。&lt;/p&gt;
&lt;h2 id=&#34;autofill從自動填密碼到自動填複雜表單&#34;&gt;Autofill：從自動填密碼到自動填複雜表單
&lt;/h2&gt;&lt;p&gt;Autofill with Google 原本更多是密碼、地址、付款資訊等基礎便利功能。現在 Google 想把它升級成更智能的表單助手。&lt;/p&gt;
&lt;p&gt;原文說，借助 Gemini 的 Personal Intelligence，Android 可以用連接應用中的相關資訊，自動填寫更多複雜表單欄位，包括 Chrome 裡的表單。&lt;/p&gt;
&lt;p&gt;這類能力很實用。移動端填寫複雜表單一直很痛苦，螢幕小、欄位多、經常需要從郵件、日曆、聊天和文件裡複製資訊。如果 Gemini 能在使用者授權下自動整理並填寫，會節省很多時間。&lt;/p&gt;
&lt;p&gt;但 Google 也強調，連接 Gemini 和 Autofill with Google 是嚴格 opt-in。也就是說，使用者自己選擇是否連接，之後也可以在設定裡隨時開關。&lt;/p&gt;
&lt;p&gt;這點很重要，因為 Autofill 涉及個人資料、地址、帳號、支付、工作資訊和敏感表單。越是有用，越需要明確授權和可控退出。&lt;/p&gt;
&lt;h2 id=&#34;rambler把口語變成可發送文本&#34;&gt;Rambler：把口語變成可發送文本
&lt;/h2&gt;&lt;p&gt;Rambler 是這次更新裡比較有意思的新功能。&lt;/p&gt;
&lt;p&gt;Gboard 已經可以把語音轉文字，但人說話時常常會有重複、停頓、語氣詞和自我修正。Rambler 的目標是把自然說話整理成更清楚、更適合發送的文本。&lt;/p&gt;
&lt;p&gt;它適合這些場景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你想快速口述一段訊息，但不想逐字修改。&lt;/li&gt;
&lt;li&gt;你說話時夾雜停頓、重複和語氣詞。&lt;/li&gt;
&lt;li&gt;你需要把隨口想法整理成更專業的簡訊、郵件或聊天內容。&lt;/li&gt;
&lt;li&gt;你在多語言之間切換，希望系統理解上下文。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Google 還提到，Rambler 會清楚顯示使用者何時啟用了它，音訊只用於即時轉寫，不會被保存。這是對隱私和透明度的回應。&lt;/p&gt;
&lt;p&gt;從產品角度看，Rambler 其實是把「語音輸入」升級成「語音寫作」。它不只是記錄你說了什麼，而是幫你把口語變成可發送的文字。&lt;/p&gt;
&lt;h2 id=&#34;自然語言建立小工具&#34;&gt;自然語言建立小工具
&lt;/h2&gt;&lt;p&gt;Gemini Intelligence 還會帶來 Create My Widget。使用者可以直接用自然語言描述想要的小工具，比如「每週推薦三份高蛋白備餐食譜」，系統就生成一個可以放在主螢幕上的自訂 widget。&lt;/p&gt;
&lt;p&gt;這代表 Android 在嘗試 generative UI：使用者不再只從固定模板裡選擇小工具，而是描述自己想看的資訊和展示方式。&lt;/p&gt;
&lt;p&gt;如果這個方向成熟，手機主螢幕可能會變得更個人化。天氣、日程、健康、通勤、飲食、學習、工作提醒，都可以變成按使用者需求生成的動態模組。&lt;/p&gt;
&lt;p&gt;不過，生成式 UI 也需要解決穩定性問題。小工具不是一次性聊天回覆，而是長期顯示在桌面上，必須可靠、可讀、可配置，並且不能亂占螢幕空間。&lt;/p&gt;
&lt;h2 id=&#34;material-3-expressive-與智能-ui&#34;&gt;Material 3 Expressive 與智能 UI
&lt;/h2&gt;&lt;p&gt;Google 還提到，Gemini Intelligence 會帶來基於 Material 3 Expressive 的更新設計語言。&lt;/p&gt;
&lt;p&gt;這部分不是單純美化介面，而是讓 UI 動畫和互動更有目的感，減少干擾，讓使用者更專注於任務。換句話說，當 AI 開始主動處理任務時，介面需要清楚表達：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AI 正在做什麼。&lt;/li&gt;
&lt;li&gt;哪些步驟已經完成。&lt;/li&gt;
&lt;li&gt;哪些地方需要使用者確認。&lt;/li&gt;
&lt;li&gt;使用者如何取消或修改。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;主動式 AI 如果沒有清晰 UI，很容易讓使用者感到失控。所以設計語言本身也會成為 AI 產品體驗的一部分。&lt;/p&gt;
&lt;h2 id=&#34;可用性和節奏&#34;&gt;可用性和節奏
&lt;/h2&gt;&lt;p&gt;根據 Google 原文，Gemini Intelligence 功能會從最新 Samsung Galaxy 和 Google Pixel 手機開始，在 2026 年夏天分批推出。之後會擴展到更多 Android 設備，包括手錶、汽車、眼鏡和筆電。&lt;/p&gt;
&lt;p&gt;這說明它不是一次性全球全量上線，而是分批 rollout。具體可用性可能取決於設備、地區、語言、應用支援和帳號設定。&lt;/p&gt;
&lt;p&gt;如果你想體驗這些功能，最現實的預期是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;先關注 Pixel 和 Samsung 旗艦機。&lt;/li&gt;
&lt;li&gt;關注 2026 年夏季後的系統更新。&lt;/li&gt;
&lt;li&gt;留意 Gemini、Chrome、Gboard、Autofill 和 Android 設定中的新開關。&lt;/li&gt;
&lt;li&gt;不同地區和語言可能不會同時支援所有功能。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;這對-android-意味著什麼&#34;&gt;這對 Android 意味著什麼
&lt;/h2&gt;&lt;p&gt;Gemini Intelligence on Android 的意義，不是又加了幾個 AI 小功能，而是 Android 產品定位的變化。&lt;/p&gt;
&lt;p&gt;過去的手機系統主要負責管理應用、通知、權限、檔案和硬體。現在 Google 想讓系統理解使用者意圖，並在應用之間完成任務。這個方向如果成功，Android 的競爭點會從「系統功能和生態應用」擴展到「能不能主動幫使用者做事」。&lt;/p&gt;
&lt;p&gt;這也會讓移動端 AI 競爭進入新階段：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Apple 會強調本地化、隱私和系統整合。&lt;/li&gt;
&lt;li&gt;Google 會強調 Gemini、搜尋、Chrome、Android 和多設備生態。&lt;/li&gt;
&lt;li&gt;第三方 AI App 會更難和系統級入口競爭。&lt;/li&gt;
&lt;li&gt;應用開發者需要考慮自己的 App 如何被 AI 代理呼叫。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;未來幾年，手機上的 AI 可能不再只是一個聊天入口，而是變成系統級執行層。&lt;/p&gt;
&lt;h2 id=&#34;總結&#34;&gt;總結
&lt;/h2&gt;&lt;p&gt;Google 這次發布的 Gemini Intelligence on Android，核心不是「手機裡多了一個 Gemini 聊天框」，而是把 AI 放進 Android 的操作流程裡。多步任務自動化、Chrome 智能瀏覽、Autofill、Rambler 和自然語言小工具，都是在讓手機從被動工具變成主動助手。&lt;/p&gt;
&lt;p&gt;它能不能真正改變使用者習慣，取決於幾個關鍵因素：自動化是否可靠、隱私開關是否清楚、跨應用操作是否順暢、使用者是否始終保留最終控制權。至少從這次發布看，Google 已經把 Android 的下一階段定義為主動式 AI 系統，而不只是傳統移動操作系統。&lt;/p&gt;
&lt;p&gt;參考連結：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://blog.google/products-and-platforms/platforms/android/gemini-intelligence/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Google Blog：A smarter, more proactive Android with Gemini Intelligence&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Gemini 3.5 Pro 提前曝光：Google 想用 Spark Agent 搶回 AI 編程入口</title>
        <link>https://knightli.com/zh-tw/2026/05/15/gemini-35-pro-spark-agent-ai-coding-race/</link>
        <pubDate>Fri, 15 May 2026 23:45:34 +0800</pubDate>
        
        <guid>https://knightli.com/zh-tw/2026/05/15/gemini-35-pro-spark-agent-ai-coding-race/</guid>
        <description>&lt;p&gt;Gemini 3.5 Pro 還沒正式發布，相關爆料已經開始升溫。&lt;/p&gt;
&lt;p&gt;這輪資訊裡有幾個關鍵詞：Gemini 3.5 Pro、代號 Cappuccino、Gemini Spark、AI 編程、MCP 工具接入。它們指向同一個方向：Google 不只是想更新一個聊天模型，而是想把模型、工具、Agent 和 Google 生態入口重新綁在一起。&lt;/p&gt;
&lt;p&gt;不過，在正式發布前，這些資訊都應該按「爆料」看待。真正值得關注的不是某一張截圖或某一個跑分，而是 Google 接下來可能要補的幾塊短板。&lt;/p&gt;
&lt;h2 id=&#34;gemini-35-pro-為什麼值得關注&#34;&gt;Gemini 3.5 Pro 為什麼值得關注
&lt;/h2&gt;&lt;p&gt;從曝光資訊看，Gemini 3.5 Pro 可能是一次跳級命名。&lt;/p&gt;
&lt;p&gt;此前外界還在討論 Gemini 3.2，隨後又出現 Gemini 3.5 Pro 的說法。如果命名屬實，說明 Google 想在新一輪發布裡講一個更大的版本故事，而不是只做常規小更新。&lt;/p&gt;
&lt;p&gt;目前流出的重點主要集中在三方面：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;編程和推理能力繼續提升；&lt;/li&gt;
&lt;li&gt;SVG、互動式頁面、動畫和 3D 生成能力增強；&lt;/li&gt;
&lt;li&gt;新的 Agent 產品 Gemini Spark 可能進入前台。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這些方向並不意外。Gemini 系列一直強調多模態，Google 也有足夠強的分發渠道。真正的問題是，它能不能在開發者工具和 Agent 工作流上趕上 OpenAI、Anthropic 的節奏。&lt;/p&gt;
&lt;h2 id=&#34;編程能力是-google-最需要補的課&#34;&gt;編程能力是 Google 最需要補的課
&lt;/h2&gt;&lt;p&gt;大模型競爭進入 2026 年後，編程已經不只是「模型能力測試項」，而是最直接的產品入口。&lt;/p&gt;
&lt;p&gt;原因很簡單：AI 編程工具有高頻使用場景，也能產生大量可回饋的資料。開發者每天讓模型讀程式碼、改程式碼、跑測試、修 bug，這些互動天然會推動下一代模型和工具鏈繼續進化。&lt;/p&gt;
&lt;p&gt;過去一年，Claude Code 在開發者群體裡聲量很高，OpenAI 也持續強化 Codex 與 ChatGPT 的協同。相比之下，Google 雖然有 Antigravity 等產品，但外部存在感並不算強。&lt;/p&gt;
&lt;p&gt;這也是 Gemini 3.5 Pro 被重點觀察的原因。如果它只是聊天更強、回答更快，意義有限；如果它能真正改善程式碼理解、跨檔案修改、工具呼叫和長任務執行，才可能改變開發者工作流。&lt;/p&gt;
&lt;h2 id=&#34;gemini-spark-可能是更大的變數&#34;&gt;Gemini Spark 可能是更大的變數
&lt;/h2&gt;&lt;p&gt;比模型本身更激進的，是傳聞中的 Gemini Spark。&lt;/p&gt;
&lt;p&gt;按照曝光描述，Spark 的定位不是普通聊天助手，而是全天候運行的 AI Agent。它可能接入郵件、日程、網頁、任務、帳號狀態和個人上下文，幫助使用者處理多步驟工作流。&lt;/p&gt;
&lt;p&gt;這類產品的想像空間很大。比如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自動整理收件箱；&lt;/li&gt;
&lt;li&gt;幫使用者跟進任務；&lt;/li&gt;
&lt;li&gt;在網頁上執行操作；&lt;/li&gt;
&lt;li&gt;處理跨應用流程；&lt;/li&gt;
&lt;li&gt;根據個人偏好安排日常事務。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;但風險也同樣明顯。一個全天候 Agent 如果能存取登入狀態、瀏覽器資料、檔案、位置和第三方服務，就必須回答幾個問題：什麼時候需要使用者確認？哪些操作必須禁止自動執行？資料會不會被分享給第三方？遠端瀏覽器和憑證如何隔離？&lt;/p&gt;
&lt;p&gt;所以 Spark 真正的看點，不只是「能不能幫你幹活」，而是 Google 能否把權限、稽核、確認機制和使用者控制做得足夠清楚。&lt;/p&gt;
&lt;h2 id=&#34;mcp-工具接入說明什麼&#34;&gt;MCP 工具接入說明什麼
&lt;/h2&gt;&lt;p&gt;爆料裡還提到，新的 Gemini 選擇器可能出現 MCP 相關模型或測試入口。&lt;/p&gt;
&lt;p&gt;如果這部分最終落地，說明 Google 也在把模型從「問答系統」推向「工具操作系統」。模型不再只是生成文字，而是要能呼叫外部工具、存取業務系統、讀寫檔案、執行命令，並在多個步驟之間保持任務狀態。&lt;/p&gt;
&lt;p&gt;這和 OpenAI、Anthropic 的方向是一致的。誰能讓模型更穩定地呼叫工具，誰就更容易把 AI 嵌進真實工作流。&lt;/p&gt;
&lt;p&gt;不過，MCP 接入本身不是終點。真正難的是穩定性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;模型能否正確選擇工具；&lt;/li&gt;
&lt;li&gt;參數是否可靠；&lt;/li&gt;
&lt;li&gt;失敗後能不能恢復；&lt;/li&gt;
&lt;li&gt;權限邊界是否明確；&lt;/li&gt;
&lt;li&gt;使用者能不能追蹤每一步操作。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果這些問題沒解決，工具越多，出錯面也越大。&lt;/p&gt;
&lt;h2 id=&#34;多模態仍然是-google-的優勢牌&#34;&gt;多模態仍然是 Google 的優勢牌
&lt;/h2&gt;&lt;p&gt;Google 最有機會打出差異化的地方，仍然是多模態。&lt;/p&gt;
&lt;p&gt;從曝光的 SVG、互動式頁面、動畫和視覺生成案例看，Gemini 可能繼續強化「從提示詞生成可互動內容」的能力。相比單純寫一段程式碼，這更接近產品原型生成：使用者描述一個想法，模型直接給出可操作、可調節、可預覽的介面。&lt;/p&gt;
&lt;p&gt;這條路線很適合 Google。它既能承接 Gemini 的多模態能力，也能和 Android、Chrome、Workspace、搜尋、廣告、雲服務等入口結合。&lt;/p&gt;
&lt;p&gt;如果 Google 想避免只在「誰的程式碼模型更強」上硬拼，它很可能會把重點放到更完整的多模態 Agent 系統上。&lt;/p&gt;
&lt;h2 id=&#34;三家公司的打法正在分化&#34;&gt;三家公司的打法正在分化
&lt;/h2&gt;&lt;p&gt;現在的大模型競爭已經不是單一模型排行榜競爭。&lt;/p&gt;
&lt;p&gt;OpenAI 的優勢在產品迭代和分發節奏，Codex、ChatGPT、企業工具和 API 之間的聯動越來越緊。&lt;/p&gt;
&lt;p&gt;Anthropic 的優勢在開發者心智和程式碼模型品質，Claude Code 已經成了很多人預設的 AI 編程入口。&lt;/p&gt;
&lt;p&gt;Google 的優勢則是生態入口。Gmail、Docs、Chrome、Android、搜尋、YouTube、地圖和雲服務構成了一個巨大的個人與企業資料網路。只要 Agent 能安全接入這些入口，Google 就有機會從「模型追趕者」變成「工作流入口控制者」。&lt;/p&gt;
&lt;p&gt;這也是 Gemini Spark 值得關注的原因。它不一定需要在所有基準測試上第一，但只要能進入日常工作流，就可能形成自己的護城河。&lt;/p&gt;
&lt;h2 id=&#34;普通使用者該怎麼看&#34;&gt;普通使用者該怎麼看
&lt;/h2&gt;&lt;p&gt;對普通使用者來說，短期不必被每一次爆料牽著走。&lt;/p&gt;
&lt;p&gt;更實用的觀察點有三個：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Gemini 3.5 Pro 的編程能力是否真的改善，尤其是複雜倉庫、長上下文和工具呼叫。&lt;/li&gt;
&lt;li&gt;Gemini Spark 是否預設安全，敏感操作前是否有明確確認和可追蹤記錄。&lt;/li&gt;
&lt;li&gt;Google 是否給出清晰價格、額度和企業權限管理，而不是只展示演示效果。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果只是生成幾張漂亮截圖，價值有限。能不能穩定接入真實工作流，才是這一輪 AI Agent 產品的分水嶺。&lt;/p&gt;
&lt;h2 id=&#34;對開發者意味著什麼&#34;&gt;對開發者意味著什麼
&lt;/h2&gt;&lt;p&gt;開發者最應該關注的不是「哪個模型贏了」，而是自己的工作流是否可遷移。&lt;/p&gt;
&lt;p&gt;現在 Claude Code、Codex、Gemini、Antigravity、Cursor、Windsurf 等工具都在搶入口。如果把所有流程都綁死在某一個平台上，未來成本、額度、模型策略或權限規則一變，遷移會很痛。&lt;/p&gt;
&lt;p&gt;更穩妥的做法是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;重要專案保留標準 Git 工作流；&lt;/li&gt;
&lt;li&gt;自動修改後必須看 diff；&lt;/li&gt;
&lt;li&gt;關鍵任務用測試和 CI 兜底；&lt;/li&gt;
&lt;li&gt;不把生產憑證交給不透明 Agent；&lt;/li&gt;
&lt;li&gt;能用開放協議接工具時，優先選擇可替換方案。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;模型會繼續變強，但工程紀律不會過時。&lt;/p&gt;
&lt;h2 id=&#34;小結&#34;&gt;小結
&lt;/h2&gt;&lt;p&gt;Gemini 3.5 Pro 的爆料說明，Google 正在加速補齊 AI 編程和 Agent 入口。模型能力提升是一部分，Gemini Spark 這類全天候 Agent 可能才是更大的戰略動作。&lt;/p&gt;
&lt;p&gt;但越是能幫使用者「自動幹活」的系統，越需要嚴格的權限邊界和可驗證流程。對 Google 來說，真正的挑戰不只是追上 GPT-5.5 或 Claude，而是把強模型、安全機制和生態入口組合成一個可信的日常工作流。&lt;/p&gt;
&lt;p&gt;如果這一步做成，Gemini 不一定要在每個榜單上第一，也可能重新拿回一部分 AI 入口主動權。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Codex 怎麼接入國產大模型？用 CCX 統一管理 OpenAI 相容 API</title>
        <link>https://knightli.com/zh-tw/2026/05/13/ccx-ai-api-proxy-gateway/</link>
        <pubDate>Wed, 13 May 2026 23:20:40 +0800</pubDate>
        
        <guid>https://knightli.com/zh-tw/2026/05/13/ccx-ai-api-proxy-gateway/</guid>
        <description>&lt;p&gt;CCX 是一個 AI API 代理與協定轉換閘道。它把 Claude Messages、OpenAI Chat Completions、OpenAI Images、Codex Responses 和 Gemini API 放到同一個服務入口下，同時提供 Web 管理介面，用來配置渠道、金鑰、模型映射、優先級、故障轉移和流量監控。&lt;/p&gt;
&lt;p&gt;如果你平時同時使用 Claude、OpenAI、Gemini、Codex，或維護多個相容 OpenAI API 的上游服務，CCX 的價值就在於統一入口和統一管理。客戶端只需要連接一個服務地址，後面的上游渠道由 CCX 負責調度。&lt;/p&gt;
&lt;p&gt;專案地址：&lt;a class=&#34;link&#34; href=&#34;https://github.com/BenedictKing/ccx&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/BenedictKing/ccx&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;ccx-解決什麼問題&#34;&gt;CCX 解決什麼問題
&lt;/h2&gt;&lt;p&gt;多個 AI API 混用時，最容易遇到幾個問題：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每個供應商的介面路徑、鑑權方式、請求格式都不一樣。&lt;/li&gt;
&lt;li&gt;同一類模型可能有多個上游，需要手動切換 base URL 和 API key。&lt;/li&gt;
&lt;li&gt;某個 key 或渠道失敗後，客戶端通常不會自動換備用渠道。&lt;/li&gt;
&lt;li&gt;團隊使用時，很難集中管理模型白名單、代理、自訂請求標頭和呼叫日誌。&lt;/li&gt;
&lt;li&gt;想同時接 Claude、Gemini、OpenAI Chat、圖像介面和 Codex Responses 時，配置會越來越分散。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CCX 的思路是把這些差異收斂到一個代理層。前端工具、腳本或業務服務只存取 CCX；CCX 再根據介面類型、模型、渠道狀態、優先級和健康情況，把請求轉發到合適的上游。&lt;/p&gt;
&lt;h2 id=&#34;支援哪些介面&#34;&gt;支援哪些介面
&lt;/h2&gt;&lt;p&gt;CCX 對外提供一個統一後端入口，預設連接埠是 &lt;code&gt;3000&lt;/code&gt;。主要路徑包括：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;GET  /                         -&amp;gt; Web 管理介面
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;GET  /health                   -&amp;gt; 健康檢查
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/api/*                         -&amp;gt; 管理 API
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;POST /v1/messages              -&amp;gt; Claude Messages 代理
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;POST /v1/chat/completions      -&amp;gt; OpenAI Chat 代理
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;POST /v1/responses             -&amp;gt; Codex Responses 代理
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;POST /v1/images/generations    -&amp;gt; OpenAI Images 生成
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;POST /v1/images/edits          -&amp;gt; OpenAI Images 編輯
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;POST /v1/images/variations     -&amp;gt; OpenAI Images 變體
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;GET  /v1/models                -&amp;gt; 模型清單
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;POST /v1beta/models/*          -&amp;gt; Gemini 代理
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;也就是說，它不是只代理一種協定，而是把常見 AI API 分成 Messages、Chat、Responses、Gemini、Images 幾類渠道分別管理。不同協定之間不會共用同一套健康狀態和日誌空間，這對排查問題很重要。&lt;/p&gt;
&lt;h2 id=&#34;架構思路&#34;&gt;架構思路
&lt;/h2&gt;&lt;p&gt;CCX 使用 Go 後端加 Vue 3 前端。前端建置產物會嵌入後端二進位檔，因此可以做單連接埠部署：同一個服務既提供 Web UI，也提供管理 API 和代理 API。&lt;/p&gt;
&lt;p&gt;一次請求大致會經過這樣的鏈路：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Client -&amp;gt; Auth Middleware -&amp;gt; Route Handler -&amp;gt; Channel Scheduler -&amp;gt; Provider / Converter -&amp;gt; Upstream API -&amp;gt; Metrics / Channel Logs -&amp;gt; Client Response
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;幾個核心模組的分工可以這樣理解：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;handlers&lt;/code&gt;：接收不同協定的請求和管理操作。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;providers&lt;/code&gt;：封裝上游 API 的請求和回應處理。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;converters&lt;/code&gt;：處理 Responses 等場景下的協定轉換。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scheduler&lt;/code&gt;：根據優先級、促銷期、健康狀態、熔斷狀態和會話親和性選擇渠道。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;metrics&lt;/code&gt;：記錄請求量、成功率、延遲、日誌和熔斷狀態。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;config&lt;/code&gt;：維護執行時配置，支援熱重載和備份。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這個設計的重點不是「把所有介面強行變成一種格式」，而是按協定類型分別代理，再在管理、調度、日誌和認證層做統一。&lt;/p&gt;
&lt;h2 id=&#34;ccx-和-codexbridge-有什麼區別&#34;&gt;CCX 和 CodexBridge 有什麼區別
&lt;/h2&gt;&lt;p&gt;CCX 和 CodexBridge 都和 Codex、OpenAI 相容介面有關，但它們解決的問題不一樣。&lt;/p&gt;
&lt;p&gt;CodexBridge 更像一個專門的 Codex 橋接器。它的核心目標是把 Codex CLI/SDK 封裝成 OpenAI 相容的 &lt;code&gt;/v1/chat/completions&lt;/code&gt; 服務，讓 OpenWebUI、Cherry Studio、腳本或其他 OpenAI 相容客戶端可以呼叫本地 Codex。也就是說，CodexBridge 的重點是「把 Codex 接出來」。&lt;/p&gt;
&lt;p&gt;CCX 更像一個統一 AI API 閘道。它不只處理 Codex Responses，還同時支援 Claude Messages、OpenAI Chat、OpenAI Images 和 Gemini API，並提供 Web 管理介面、渠道優先級、故障轉移、日誌監控和多 key 管理。也就是說，CCX 的重點是「把多個模型和多個供應商統一管起來」。&lt;/p&gt;
&lt;p&gt;簡單對比：&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;對比項&lt;/th&gt;
          &lt;th&gt;CodexBridge&lt;/th&gt;
          &lt;th&gt;CCX&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;核心定位&lt;/td&gt;
          &lt;td&gt;Codex 本地橋接器&lt;/td&gt;
          &lt;td&gt;多協定 AI API 閘道&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;主要目標&lt;/td&gt;
          &lt;td&gt;讓 Codex 變成 OpenAI 相容介面&lt;/td&gt;
          &lt;td&gt;統一管理 Claude、OpenAI、Gemini、Codex 等渠道&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;管理介面&lt;/td&gt;
          &lt;td&gt;側重 API 服務本身&lt;/td&gt;
          &lt;td&gt;提供 Web 管理介面&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;多渠道調度&lt;/td&gt;
          &lt;td&gt;不是重點&lt;/td&gt;
          &lt;td&gt;支援渠道優先級、故障轉移和日誌監控&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;適合場景&lt;/td&gt;
          &lt;td&gt;本機或單服務呼叫 Codex&lt;/td&gt;
          &lt;td&gt;團隊、多 key、多供應商、多協定統一入口&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;如果只是想把 Codex 接進 OpenWebUI 或 Cherry Studio，CodexBridge 更直接；如果想同時管理 Codex、Claude、Gemini、DeepSeek、Qwen、Kimi 等多個上游，CCX 更合適。&lt;/p&gt;
&lt;h2 id=&#34;快速部署&#34;&gt;快速部署
&lt;/h2&gt;&lt;p&gt;最簡單的方式是下載二進位檔。下載後，在同目錄建立 &lt;code&gt;.env&lt;/code&gt;：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-env&#34; data-lang=&#34;env&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PROXY_ACCESS_KEY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;your-proxy-access-key
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PORT&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;3000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;ENABLE_WEB_UI&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;APP_UI_LANGUAGE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;zh-CN
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;啟動後存取：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;http://localhost:3000
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果在 Windows 下從 WSL、Docker、PowerShell 或其他環境存取 &lt;code&gt;localhost&lt;/code&gt; 不通，可以改用 Windows 主機的區域網路 IPv4 地址，例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;http://192.168.1.23:3000
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;CCX 預設透過 &lt;code&gt;:PORT&lt;/code&gt; 監聽所有網卡地址，所以暴露到區域網路時要注意存取控制。&lt;/p&gt;
&lt;h2 id=&#34;docker-部署&#34;&gt;Docker 部署
&lt;/h2&gt;&lt;p&gt;Docker 方式適合長期執行：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker run -d &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --name ccx &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -p 3000:3000 &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -e &lt;span class=&#34;nv&#34;&gt;PROXY_ACCESS_KEY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;your-proxy-access-key &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -e &lt;span class=&#34;nv&#34;&gt;APP_UI_LANGUAGE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;zh-CN &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -v &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;pwd&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;/.config:/app/.config &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  crpi-i19l8zl0ugidq97v.cn-hangzhou.personal.cr.aliyuncs.com/bene/ccx:latest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果倉庫裡已經有 &lt;code&gt;docker-compose.yml&lt;/code&gt;，也可以直接：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;需要自動更新時，可以疊加 Watchtower 配置：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker compose -f docker-compose.yml -f docker-compose.watchtower.yml up -d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;部署完成後，&lt;code&gt;.config&lt;/code&gt; 目錄會保存執行時配置和持久化資料，建議掛載到宿主機，避免容器重建後配置遺失。&lt;/p&gt;
&lt;h2 id=&#34;原始碼執行&#34;&gt;原始碼執行
&lt;/h2&gt;&lt;p&gt;開發或自訂建置可以走原始碼方式：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git clone https://github.com/BenedictKing/ccx
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; ccx
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cp backend-go/.env.example backend-go/.env
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;make run
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;常用命令：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;make dev
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;make run
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;make build
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;make frontend-dev
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;前端單獨開發：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; frontend
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun install
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun run dev
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;後端單獨開發：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; backend-go
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;make dev
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;關鍵環境變數&#34;&gt;關鍵環境變數
&lt;/h2&gt;&lt;p&gt;最小可用配置通常包括：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-env&#34; data-lang=&#34;env&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PORT&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;3000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;ENV&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;production
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;ENABLE_WEB_UI&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PROXY_ACCESS_KEY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;your-proxy-access-key
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;ADMIN_ACCESS_KEY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;your-admin-secret-key
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;APP_UI_LANGUAGE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;zh-CN
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;LOG_LEVEL&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;info
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;REQUEST_TIMEOUT&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;300000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;其中：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;PROXY_ACCESS_KEY&lt;/code&gt; 用於代理 API，是必須修改的金鑰。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ADMIN_ACCESS_KEY&lt;/code&gt; 用於 Web 管理介面和 &lt;code&gt;/api/*&lt;/code&gt;，建議和代理金鑰分開。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ENABLE_WEB_UI&lt;/code&gt; 控制是否啟用管理介面。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;REQUEST_TIMEOUT&lt;/code&gt; 控制請求逾時時間，長上下文或圖像任務可以適當調大。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;LOG_LEVEL&lt;/code&gt; 控制日誌級別，生產環境一般用 &lt;code&gt;info&lt;/code&gt; 或 &lt;code&gt;warn&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果需要限制請求體大小，可以關注：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-env&#34; data-lang=&#34;env&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;MAX_REQUEST_BODY_SIZE_MB&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;50&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;圖像編輯、base64 圖片、多模態請求都可能讓請求體變大。&lt;/p&gt;
&lt;h2 id=&#34;渠道編排和故障轉移&#34;&gt;渠道編排和故障轉移
&lt;/h2&gt;&lt;p&gt;CCX 的管理介面可以配置多個渠道，並為每個渠道設定：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;上游服務類型。&lt;/li&gt;
&lt;li&gt;API key 或多 key 輪換。&lt;/li&gt;
&lt;li&gt;代理地址。&lt;/li&gt;
&lt;li&gt;自訂請求標頭。&lt;/li&gt;
&lt;li&gt;模型白名單。&lt;/li&gt;
&lt;li&gt;路由前綴。&lt;/li&gt;
&lt;li&gt;優先級。&lt;/li&gt;
&lt;li&gt;健康檢查與熔斷恢復。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;調度時會綜合考慮渠道狀態、優先級、促銷期、Trace 親和性、熔斷狀態和可用 key。簡單理解：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;正常情況下，優先級高的渠道先被使用。&lt;/li&gt;
&lt;li&gt;某個渠道失敗後，可以故障轉移到備用渠道。&lt;/li&gt;
&lt;li&gt;熔斷機制會避免持續打到明顯不可用的上游。&lt;/li&gt;
&lt;li&gt;Trace 親和性會盡量讓同一類會話保持在合適的渠道上。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這類能力適合有多個 key、多個供應商或多個地區上游的場景。個人輕量使用時，也可以只配置一個渠道，把 CCX 當成帶 Web UI 的代理層。&lt;/p&gt;
&lt;h2 id=&#34;日誌和監控&#34;&gt;日誌和監控
&lt;/h2&gt;&lt;p&gt;CCX 提供渠道指標和請求日誌，可以看到：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;請求量。&lt;/li&gt;
&lt;li&gt;成功率。&lt;/li&gt;
&lt;li&gt;失敗率。&lt;/li&gt;
&lt;li&gt;平均延遲。&lt;/li&gt;
&lt;li&gt;按模型統計的歷史資料。&lt;/li&gt;
&lt;li&gt;渠道狀態和熔斷情況。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;生產環境建議使用相對克制的日誌配置：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-env&#34; data-lang=&#34;env&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;ENV&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;production
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;LOG_LEVEL&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;info
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;ENABLE_REQUEST_LOGS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;ENABLE_RESPONSE_LOGS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;這樣可以保留基本請求資訊，又避免把完整回應內容寫入日誌。排查問題時可以臨時打開更詳細的日誌，但完成後應恢復，尤其不要在生產環境長期輸出請求體和回應體。&lt;/p&gt;
&lt;h2 id=&#34;安全建議&#34;&gt;安全建議
&lt;/h2&gt;&lt;p&gt;CCX 是代理閘道，裡面會保存上游 API key，所以部署時不要只追求「能跑起來」。至少要注意這些點：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不要使用預設或過短的 &lt;code&gt;PROXY_ACCESS_KEY&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;建議單獨設定 &lt;code&gt;ADMIN_ACCESS_KEY&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;不要把 Web 管理介面直接暴露到公網。&lt;/li&gt;
&lt;li&gt;如果必須公網存取，建議放在反向代理、VPN、存取控制或單點登入之後。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.env&lt;/code&gt;、&lt;code&gt;.config&lt;/code&gt;、日誌檔案都不要提交到 Git 倉庫。&lt;/li&gt;
&lt;li&gt;生產環境不要長期啟用完整請求體和回應體日誌。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;可以用下面的方式產生隨機金鑰：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PROXY_ACCESS_KEY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;openssl rand -base64 32&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;ADMIN_ACCESS_KEY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;openssl rand -base64 32&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;適合誰使用&#34;&gt;適合誰使用
&lt;/h2&gt;&lt;p&gt;CCX 更適合這些場景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;同時維護 Claude、OpenAI、Gemini、Codex 或圖像介面。&lt;/li&gt;
&lt;li&gt;有多個 API key，需要輪換、分流和故障轉移。&lt;/li&gt;
&lt;li&gt;想用 Web UI 管理上游渠道，而不是手動改配置檔。&lt;/li&gt;
&lt;li&gt;想觀察每個渠道的成功率、延遲和請求日誌。&lt;/li&gt;
&lt;li&gt;想給團隊提供一個統一 AI API 入口。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你只是本機偶爾呼叫一個模型，直接用官方 SDK 或單一 OpenAI 相容代理會更簡單。CCX 的優勢主要在多渠道、多協定和統一維運。&lt;/p&gt;
&lt;h2 id=&#34;小結&#34;&gt;小結
&lt;/h2&gt;&lt;p&gt;CCX 的定位是 AI API 閘道，而不是某個模型的客戶端。它把 Claude Messages、OpenAI Chat、OpenAI Images、Codex Responses 和 Gemini 放到一個代理層裡，並提供渠道編排、故障轉移、日誌監控和 Web 管理介面。&lt;/p&gt;
&lt;p&gt;對個人使用者來說，它可以減少切換 API 地址和金鑰的麻煩；對團隊或長期執行的服務來說，它更像一個輕量級 AI 閘道。真正上線前，重點不只是配置模型，還要配置好金鑰、管理入口、日誌級別、渠道優先級和故障轉移策略。&lt;/p&gt;
&lt;h2 id=&#34;參考&#34;&gt;參考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;GitHub 專案：&lt;a class=&#34;link&#34; href=&#34;https://github.com/BenedictKing/ccx&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/BenedictKing/ccx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;架構說明：&lt;a class=&#34;link&#34; href=&#34;https://github.com/BenedictKing/ccx/blob/main/ARCHITECTURE.md&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/BenedictKing/ccx/blob/main/ARCHITECTURE.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;環境變數說明：&lt;a class=&#34;link&#34; href=&#34;https://github.com/BenedictKing/ccx/blob/main/ENVIRONMENT.md&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/BenedictKing/ccx/blob/main/ENVIRONMENT.md&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>ChatGPT、Claude Code 和 Gemini 的記憶機制有什麼不同？</title>
        <link>https://knightli.com/zh-tw/2026/05/07/chatgpt-claude-code-gemini-memory-comparison/</link>
        <pubDate>Thu, 07 May 2026 14:47:17 +0800</pubDate>
        
        <guid>https://knightli.com/zh-tw/2026/05/07/chatgpt-claude-code-gemini-memory-comparison/</guid>
        <description>&lt;p&gt;AI 產品裡的「記憶」正在變得越來越重要。它標誌著 AI 從「單次對話工具」走向「長期協作夥伴」：不用每次重新介紹背景，不用反覆解釋偏好，也不用讓模型一次次重新理解項目。&lt;/p&gt;
&lt;p&gt;但不同產品裡的記憶並不是一回事。&lt;code&gt;ChatGPT&lt;/code&gt;、&lt;code&gt;Claude Code&lt;/code&gt; 和 &lt;code&gt;Gemini&lt;/code&gt; 都在解決「AI 如何記得更久」的問題，但它們的設計目標、儲存位置、透明度和適用場景差異很大。&lt;/p&gt;
&lt;p&gt;截至 2026 年 5 月 7 日，可以把它們粗略理解成三類：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ChatGPT 更像「個人助理記憶」。&lt;/li&gt;
&lt;li&gt;Claude Code 更像「工程項目記憶」。&lt;/li&gt;
&lt;li&gt;Gemini 更像「Google 生態上下文」。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;chatgpt圍繞人的長期偏好&#34;&gt;ChatGPT：圍繞人的長期偏好
&lt;/h2&gt;&lt;p&gt;ChatGPT 的記憶機制主要面向個人協作。它關心的是「你是誰」「你偏好什麼」「你長期在做什麼」。&lt;/p&gt;
&lt;p&gt;OpenAI 目前把 ChatGPT 的記憶分成兩類：&lt;code&gt;saved memories&lt;/code&gt; 和 &lt;code&gt;chat history&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;saved memories&lt;/code&gt; 是 ChatGPT 保存下來的重要資訊，比如你的名字、偏好、目標、常用技術棧、寫作習慣等。你可以直接要求它記住某件事，它也可能在對話中自動保存它認為未來有用的資訊。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;chat history&lt;/code&gt; 則是讓 ChatGPT 在回答時參考過去聊天。它不等於把每一段聊天都完整變成記憶，而是在需要時從過往對話裡找相關上下文。&lt;/p&gt;
&lt;p&gt;所以 ChatGPT 的核心邏輯是：跨會話理解同一個使用者。&lt;/p&gt;
&lt;p&gt;典型例子包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;「以後給我程式碼示例時盡量簡潔。」&lt;/li&gt;
&lt;li&gt;「我主要使用 Python 和 TypeScript。」&lt;/li&gt;
&lt;li&gt;「我正在寫一個關於 AI 工具的 Hugo 部落格。」&lt;/li&gt;
&lt;li&gt;「我喜歡先看結論，再看細節。」&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這些記憶不是綁定某個單獨項目，而是跟隨帳號和個人使用習慣。&lt;/p&gt;
&lt;h2 id=&#34;memory-sources讓個性化來源更可見&#34;&gt;Memory Sources：讓個性化來源更可見
&lt;/h2&gt;&lt;p&gt;OpenAI 在 2026 年 5 月的更新中強調了 &lt;code&gt;Memory sources&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;它的作用不是新增另一種記憶，而是讓使用者看到 ChatGPT 在個性化回答時參考了哪些來源。根據 OpenAI 幫助文件，Memory Sources 可能顯示：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;過去聊天。&lt;/li&gt;
&lt;li&gt;保存記憶。&lt;/li&gt;
&lt;li&gt;自定義指令。&lt;/li&gt;
&lt;li&gt;文件庫中的文件。&lt;/li&gt;
&lt;li&gt;已連接 Gmail 中的郵件。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;其中，文件和 Gmail 的可見範圍會受到計畫、地區和連接狀態限制。OpenAI 也明確說明，Memory sources 不一定展示影響回答的所有因素，而是幫助使用者理解和管理個性化。&lt;/p&gt;
&lt;p&gt;這一步很重要。因為 AI 越會「記住你」，使用者越需要知道它到底根據什麼在回答。否則個性化很容易變成黑箱：你感覺它好像知道你，但不知道它為什麼知道。&lt;/p&gt;
&lt;p&gt;ChatGPT 的優勢是跨會話、跨主題持續理解個人偏好；風險是記憶容易過期，或者使用者忘了某條舊記憶還在影響回答。因此，適合定期清理 saved memories 和舊聊天。&lt;/p&gt;
&lt;h2 id=&#34;claude-code圍繞程式碼庫和工程規則&#34;&gt;Claude Code：圍繞程式碼庫和工程規則
&lt;/h2&gt;&lt;p&gt;Claude Code 的記憶機制更偏工程協作。它關心的不是「使用者平時愛喝什麼咖啡」，而是「這個程式碼庫應該怎麼改」。&lt;/p&gt;
&lt;p&gt;Claude Code 有兩類容易混在一起的記憶：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;顯式項目記憶：&lt;code&gt;CLAUDE.md&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;自動項目記憶：Auto Memory。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt; 是最基礎、最穩定的項目記憶文件。它可以放在項目根目錄，也可以在子目錄中存在。Claude Code 會讀取這些文件，把它們作為項目說明和操作規則。&lt;/p&gt;
&lt;p&gt;適合寫進 &lt;code&gt;CLAUDE.md&lt;/code&gt; 的內容包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;常用構建、測試、lint 命令。&lt;/li&gt;
&lt;li&gt;程式碼風格和命名規則。&lt;/li&gt;
&lt;li&gt;項目架構說明。&lt;/li&gt;
&lt;li&gt;模組邊界和危險區域。&lt;/li&gt;
&lt;li&gt;團隊約定和提交流程。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果 &lt;code&gt;CLAUDE.md&lt;/code&gt; 放在程式碼庫裡，它可以提交到 Git，成為團隊共享的 agent 說明書。這一點和 ChatGPT 的雲端個人記憶完全不同。&lt;/p&gt;
&lt;h2 id=&#34;claude-code-auto-memory自動累積項目經驗&#34;&gt;Claude Code Auto Memory：自動累積項目經驗
&lt;/h2&gt;&lt;p&gt;Claude Code 現在也有 &lt;code&gt;Auto Memory&lt;/code&gt;。它的目標是讓 Claude 在多個會話之間自動累積項目經驗，而不要求使用者每次手寫說明。&lt;/p&gt;
&lt;p&gt;根據 Claude Code 文件，Auto Memory 會讓 Claude 在工作過程中為自己保存筆記，例如構建命令、調試發現、架構說明、程式碼風格偏好和工作流習慣。它不會每個會話都保存，而是判斷哪些資訊未來可能有用。&lt;/p&gt;
&lt;p&gt;這裡有一個容易誤解的點：Auto Memory 預設不是把內容寫到項目根目錄的 &lt;code&gt;.claude/memory.md&lt;/code&gt;。官方文件說明，每個項目會在使用者目錄下擁有自己的 memory 目錄，路徑類似：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;~/.claude/projects/&amp;lt;project&amp;gt;/memory/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;其中 &lt;code&gt;MEMORY.md&lt;/code&gt; 會在每次對話開始時載入前 200 行或前 25KB，詳細內容則可能被拆到其他主題文件裡。Auto Memory 文件是本機本地的 Markdown 文件，使用者可以透過 &lt;code&gt;/memory&lt;/code&gt; 查看、編輯或刪除。&lt;/p&gt;
&lt;p&gt;這讓 Claude Code 的記憶更像「本機上的項目經驗庫」。它比 ChatGPT 的個人記憶更貼近程式碼庫，也比單純的 &lt;code&gt;CLAUDE.md&lt;/code&gt; 更動態。&lt;/p&gt;
&lt;p&gt;但要注意，Auto Memory 是機器本地的，不會天然跟隨程式碼庫同步到其他機器或雲環境。如果要團隊共享穩定規則，仍然應該優先寫進項目中的 &lt;code&gt;CLAUDE.md&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id=&#34;gemini圍繞-google-生態上下文&#34;&gt;Gemini：圍繞 Google 生態上下文
&lt;/h2&gt;&lt;p&gt;Gemini 的記憶邏輯又不同。&lt;/p&gt;
&lt;p&gt;Gemini 也有保存資訊和參考過去聊天的能力。Google 幫助文件提到，使用者可以保存關於生活、工作或偏好的資訊，也可以讓 Gemini 在回答前參考過去聊天。Gemini 使用這些資訊時，可能會在回答底部的來源區域顯示 &lt;code&gt;Your saved info&lt;/code&gt; 或 &lt;code&gt;Previous chats&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;但 Gemini 的差異化不只在「保存幾條偏好」，而在 Google 生態整合。&lt;/p&gt;
&lt;p&gt;在使用者授權和功能可用的前提下，Gemini 可以透過連接的 Google 應用獲取上下文，例如 Gmail、Google Drive、Docs、Sheets 等。它的優勢不是讓使用者一條條教它記住什麼，而是把已有的 Google 帳號資料變成可檢索的工作上下文。&lt;/p&gt;
&lt;p&gt;典型區別是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ChatGPT 記得：「我最近在做 LTO 磁帶機修復。」&lt;/li&gt;
&lt;li&gt;Gemini 可能可以從 Gmail 找到購買確認郵件，或從 Drive 裡讀取相關維修筆記。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;當然，這不代表 Gemini 可以無條件讀取你所有 Google 資料。它取決於帳號類型、地區、權限、連接應用、Keep Activity 設定和具體產品可用性。對企業或學校帳號，還可能受 Google Workspace 管理員控制。&lt;/p&gt;
&lt;p&gt;所以更準確地說，Gemini 的記憶不是一個單純的「備忘錄」，而是「保存資訊 + 過去聊天 + Google 生態連接」的組合。&lt;/p&gt;
&lt;h2 id=&#34;三者核心差異&#34;&gt;三者核心差異
&lt;/h2&gt;&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;維度&lt;/th&gt;
          &lt;th&gt;ChatGPT&lt;/th&gt;
          &lt;th&gt;Claude Code&lt;/th&gt;
          &lt;th&gt;Gemini&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;核心對象&lt;/td&gt;
          &lt;td&gt;人和偏好&lt;/td&gt;
          &lt;td&gt;項目和程式碼庫&lt;/td&gt;
          &lt;td&gt;Google 帳號與生態資料&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;典型記憶&lt;/td&gt;
          &lt;td&gt;偏好、背景、長期目標&lt;/td&gt;
          &lt;td&gt;架構、命令、規範、調試經驗&lt;/td&gt;
          &lt;td&gt;saved info、過去聊天、Gmail/Drive/Docs 上下文&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;儲存形態&lt;/td&gt;
          &lt;td&gt;OpenAI 帳戶內的記憶和聊天上下文&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt;、&lt;code&gt;MEMORY.md&lt;/code&gt;、本地 Markdown 文件&lt;/td&gt;
          &lt;td&gt;Google 帳號活動、保存資訊、連接應用資料&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;透明度&lt;/td&gt;
          &lt;td&gt;Memory sources 可見一部分來源&lt;/td&gt;
          &lt;td&gt;Markdown 文件可直接查看和編輯&lt;/td&gt;
          &lt;td&gt;透過來源提示、Gemini Apps Activity 和 Google 設定管理&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;跨項目能力&lt;/td&gt;
          &lt;td&gt;強，跟隨使用者帳號&lt;/td&gt;
          &lt;td&gt;弱，主要跟隨項目或本機項目 memory&lt;/td&gt;
          &lt;td&gt;強，取決於 Google 生態資料和權限&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;團隊共享&lt;/td&gt;
          &lt;td&gt;不適合直接共享&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt; 可隨 Git 共享&lt;/td&gt;
          &lt;td&gt;主要依賴 Workspace 和權限體系&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;最適合&lt;/td&gt;
          &lt;td&gt;個人偏好和長期助理&lt;/td&gt;
          &lt;td&gt;長期程式碼項目和 agent 協作&lt;/td&gt;
          &lt;td&gt;Google Workspace 資料檢索和跨工具工作&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;該怎麼選擇和使用&#34;&gt;該怎麼選擇和使用
&lt;/h2&gt;&lt;p&gt;如果你想讓 AI 記住「我是誰、我喜歡什麼風格、我長期怎麼工作」，ChatGPT 的記憶更合適。&lt;/p&gt;
&lt;p&gt;它適合保存個人偏好，例如寫作風格、常用技術棧、回答格式、職業背景、長期項目方向。它的重點是減少自我介紹成本，讓每次新對話更快進入狀態。&lt;/p&gt;
&lt;p&gt;如果你想讓 AI 記住「這個程式碼庫怎麼改、哪些命令能跑、哪些坑不能踩」，Claude Code 更合適。&lt;/p&gt;
&lt;p&gt;穩定規則寫進 &lt;code&gt;CLAUDE.md&lt;/code&gt;，團隊共享；動態經驗交給 Auto Memory 輔助累積；關鍵決策最好仍然整理進文件或 &lt;code&gt;CLAUDE.md&lt;/code&gt;，避免只停留在本機自動記憶裡。&lt;/p&gt;
&lt;p&gt;如果你的資料大量存在 Gmail、Drive、Docs、Sheets 裡，Gemini 的生態上下文更有優勢。&lt;/p&gt;
&lt;p&gt;它適合查找過去郵件、整理 Google Drive 文件、聯動日曆和辦公資料。使用 Gemini 的關鍵，不是反覆在聊天裡提醒它，而是確保相關應用連接、權限和活動設定正確。&lt;/p&gt;
&lt;h2 id=&#34;一個實用分工&#34;&gt;一個實用分工
&lt;/h2&gt;&lt;p&gt;可以把三者這樣分工：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ChatGPT 記住「我的通用偏好」。&lt;/li&gt;
&lt;li&gt;Claude Code 記住「這個倉庫的工程知識」。&lt;/li&gt;
&lt;li&gt;Gemini 檢索「我在 Google 生態裡的資料」。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;也就是說，ChatGPT 更像私人秘書，Claude Code 更像項目裡的資深工程同事，Gemini 更像 Google 帳號裡的資料索引員。&lt;/p&gt;
&lt;p&gt;這三種記憶沒有絕對高低，只是目標不同。&lt;/p&gt;
&lt;p&gt;最需要警惕的是把它們混為一談。個人偏好不一定適合寫進項目記憶；項目架構不一定適合存在雲端個人記憶；Google 生態檢索也不等於模型真正「長期理解」了你。&lt;/p&gt;
&lt;h2 id=&#34;簡短判斷&#34;&gt;簡短判斷
&lt;/h2&gt;&lt;p&gt;AI 記憶的下一階段，不是簡單地「記得越多越好」，而是記憶要分層、可見、可控。&lt;/p&gt;
&lt;p&gt;ChatGPT 的重點是跨會話個人化，Claude Code 的重點是程式碼項目連續性，Gemini 的重點是 Google 生態上下文。真正好用的長期 AI 協作，不是把所有資訊塞進一個黑箱，而是讓不同類型的記憶待在合適的位置。&lt;/p&gt;
&lt;p&gt;個人偏好放在個人記憶裡，工程規則放在程式碼庫裡，歷史資料放在原本的文件和郵件系統裡。AI 要做的，是在需要時準確呼叫這些上下文，而不是把所有東西混成一團。&lt;/p&gt;
&lt;h2 id=&#34;相關連結&#34;&gt;相關連結
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;OpenAI Memory FAQ：&lt;a class=&#34;link&#34; href=&#34;https://help.openai.com/en/articles/8590148-memory-faq&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://help.openai.com/en/articles/8590148-memory-faq&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ChatGPT Release Notes：&lt;a class=&#34;link&#34; href=&#34;https://help.openai.com/en/articles/6825453-chatgpt-release-notes&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://help.openai.com/en/articles/6825453-chatgpt-release-notes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Claude Code Memory：&lt;a class=&#34;link&#34; href=&#34;https://code.claude.com/docs/en/memory&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://code.claude.com/docs/en/memory&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Gemini Saved info：&lt;a class=&#34;link&#34; href=&#34;https://support.google.com/gemini/answer/15637730&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://support.google.com/gemini/answer/15637730&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Gemini Apps Privacy Hub：&lt;a class=&#34;link&#34; href=&#34;https://support.google.com/gemini/answer/13594961&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://support.google.com/gemini/answer/13594961&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Gemini Embedding 2：把文字、圖像、影片和音訊放進同一個向量空間</title>
        <link>https://knightli.com/zh-tw/2026/05/04/gemini-embedding-2-multimodal-rag/</link>
        <pubDate>Mon, 04 May 2026 06:01:10 +0800</pubDate>
        
        <guid>https://knightli.com/zh-tw/2026/05/04/gemini-embedding-2-multimodal-rag/</guid>
        <description>&lt;p&gt;Google Developers Blog 介紹了 Gemini Embedding 2 的開發用法。這個模型已經透過 Gemini API 和 Gemini Enterprise Agent Platform 進入 GA，重點不只是「新的 embedding 模型」，而是把文字、圖像、影片、音訊和文件映射到同一個語義空間。&lt;/p&gt;
&lt;p&gt;這會讓檢索系統的邊界變寬。過去很多 RAG 流程需要先把圖片、影片、音訊拆成文字或中繼資料，再分別建立索引；Gemini Embedding 2 則可以直接處理多模態輸入，讓代理、搜尋和分類系統更容易圍繞真實業務材料工作。&lt;/p&gt;
&lt;p&gt;原文連結：&lt;a class=&#34;link&#34; href=&#34;https://developers.googleblog.com/building-with-gemini-embedding-2/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Building with Gemini Embedding 2: Agentic multimodal RAG and beyond&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;模型能力&#34;&gt;模型能力
&lt;/h2&gt;&lt;p&gt;Gemini Embedding 2 支援 100 多種語言。單次請求可以處理：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;最多 8,192 個文字 token&lt;/li&gt;
&lt;li&gt;最多 6 張圖片&lt;/li&gt;
&lt;li&gt;最多 120 秒影片&lt;/li&gt;
&lt;li&gt;最多 180 秒音訊&lt;/li&gt;
&lt;li&gt;最多 6 頁 PDF&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;它的關鍵點是「統一語義空間」。開發者可以把不同模態的內容放在同一套向量表示裡，用同一種檢索、聚類或重排序邏輯處理。&lt;/p&gt;
&lt;p&gt;例如，文字描述和圖片可以放在同一次 embedding 請求裡：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;google&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;genai&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;google.genai&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;types&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;client&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;genai&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Client&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;dog.png&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;rb&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;image_bytes&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;models&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;embed_content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;gemini-embedding-2&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;contents&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;An image of a dog&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;types&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Part&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;from_bytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;image_bytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;image/png&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;embeddings&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果你希望每個輸入分別得到 embedding，而不是聚合成一個向量，可以使用 Batch API。原文也提到，Agent Platform 對這類批次支援還在跟進中。&lt;/p&gt;
&lt;h2 id=&#34;對-rag-的意義&#34;&gt;對 RAG 的意義
&lt;/h2&gt;&lt;p&gt;多模態 embedding 對代理式 RAG 很有用。一個 AI agent 可能需要同時檢查程式碼倉庫、PDF、截圖、圖表、音訊會議紀錄和產品圖片。如果所有資料都能進入同一個語義空間，檢索鏈路就不必為每種材料單獨設計一套入口。&lt;/p&gt;
&lt;p&gt;Google 建議根據任務使用 task prefix，讓 embedding 更貼近檢索目標。例如問答、事實核查、程式碼檢索和搜尋結果，可以使用不同前綴：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Generate embedding for your task&amp;#39;s query:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;prepare_query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;task: question answering | query: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# return f&amp;#34;task: fact checking | query: {content}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# return f&amp;#34;task: code retrieval | query: {content}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# return f&amp;#34;task: search result | query: {content}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Generate embedding for document of an asymmetric retrieval task:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;prepare_document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;title&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;title&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;none&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;title: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; | text: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;這種前綴適合非對稱檢索：使用者查詢往往很短，文件內容往往很長。把 &lt;code&gt;query&lt;/code&gt; 和 &lt;code&gt;document&lt;/code&gt; 分別按任務格式整理，可以改善短查詢到長文件之間的匹配。&lt;/p&gt;
&lt;p&gt;原文給了兩個落地回饋：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Harvey 在法律檢索基準上，Recall@20 precision 相比上一代 embedding 提升 3%。&lt;/li&gt;
&lt;li&gt;Supermemory 在 Recall@1 搜尋準確率上提升 40%，並把它用於記憶、索引、搜尋和問答管線。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這些數字不代表所有場景都會同幅度提升，但說明多模態 embedding 已經不只是展示能力，而是在真實檢索產品中產生效果。&lt;/p&gt;
&lt;h2 id=&#34;視覺搜尋&#34;&gt;視覺搜尋
&lt;/h2&gt;&lt;p&gt;Gemini Embedding 2 也適合做以圖搜圖、圖文混合搜尋和商品識別。原文提到服裝租賃公司 Nuuly 用它匹配倉庫中未打標籤的服裝照片，使 Match@20 從 60% 提升到接近 87%，整體成功識別率從 74% 提升到 90% 以上。&lt;/p&gt;
&lt;p&gt;這類場景的關鍵不是生成內容，而是理解「這張圖片和哪個庫存、文件或商品紀錄最接近」。如果你的業務裡有大量圖片、影片片段或掃描件，多模態 embedding 會比純文字索引更自然。&lt;/p&gt;
&lt;h2 id=&#34;檢索重排序&#34;&gt;檢索重排序
&lt;/h2&gt;&lt;p&gt;Embedding 還可以用於 rerank。常見做法是先用基礎檢索拿到一批候選結果，再計算候選結果和使用者查詢之間的相似度，把更相關的內容排到前面：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 1. Define a function to calculate the dot product (cosine similarity)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;dot_product&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ndarray&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ndarray&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;array&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;@&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;array&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 2. Retrieve your embeddings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# (Assuming &amp;#39;summaries&amp;#39; is your list of search results)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;search_res&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_embeddings&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;summaries&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;embedded_query&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_embeddings&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 3. Calculate similarity scores&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sim_value&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dot_product&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;search_res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;embedded_query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 4. Select the most relevant result&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;best_match_index&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argmax&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sim_value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;原文還提到一種思路：先讓模型根據內部知識生成一個假設答案，再把這個假設答案做 embedding，與候選內容比較相似度，用來挑出語義更貼近的結果。這對問答型 RAG 尤其有用。&lt;/p&gt;
&lt;h2 id=&#34;聚類分類和異常檢測&#34;&gt;聚類、分類和異常檢測
&lt;/h2&gt;&lt;p&gt;除了檢索，embedding 也適合聚類、分類和異常檢測。和前面的問答檢索不同，這些屬於對稱任務，&lt;code&gt;query&lt;/code&gt; 和 &lt;code&gt;document&lt;/code&gt; 可以使用同一種任務前綴：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Generate embedding for query &amp;amp; document of your task.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;prepare_query_and_document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# return f&amp;#39;task: clustering | query: {content}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# return f&amp;#39;task: sentence similarity | query: {content}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# return f&amp;#39;task: classification | query: {content}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;這類任務可以用於輿情分類、內容審核、相似資產歸類、異常樣本發現，也可以幫助 agent 對大量上下文材料先做整理，再進入後續推理。&lt;/p&gt;
&lt;h2 id=&#34;儲存和成本&#34;&gt;儲存和成本
&lt;/h2&gt;&lt;p&gt;Gemini Embedding 2 預設輸出 3,072 維向量。它使用 Matryoshka Representation Learning，因此可以透過 &lt;code&gt;output_dimensionality&lt;/code&gt; 把向量截斷到更小維度。Google 推薦在效率優先時使用 1,536 或 768 維：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;models&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;embed_content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;gemini-embedding-2&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;contents&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;What is the meaning of life?&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;config&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;output_dimensionality&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;768&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;向量可以存到 Agent Platform Vector Search、Pinecone、Weaviate、Qdrant、ChromaDB 等系統裡。成本方面，原文提到 Batch API 可提供更高吞吐，並達到預設 embedding 價格的 50%。&lt;/p&gt;
&lt;h2 id=&#34;開發者該怎麼用&#34;&gt;開發者該怎麼用
&lt;/h2&gt;&lt;p&gt;如果你已有文字 RAG，可以先從兩類增量改造開始：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;把 PDF、截圖、圖片說明和文字文件放入同一個索引，測試查詢召回是否更穩定。&lt;/li&gt;
&lt;li&gt;給不同任務加 task prefix，例如問答、事實核查、程式碼檢索、商品搜尋，不要把所有內容都按同一種 embedding 方式處理。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果你在做新產品，可以優先考慮這些方向：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;企業知識庫：同時檢索文件、圖表、簡報截圖和會議材料。&lt;/li&gt;
&lt;li&gt;視覺搜尋：用圖片、文字或混合輸入查找商品、資產、設計稿和檔案。&lt;/li&gt;
&lt;li&gt;Agent 工具鏈：讓 coding agent、研究 agent 或客服 agent 檢索多種格式的業務材料。&lt;/li&gt;
&lt;li&gt;內容治理：對文字、圖片、影片片段做統一分類、聚類和異常檢測。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Gemini Embedding 2 的價值在於把多模態材料變成同一套可檢索資產。對開發者來說，這會減少「先轉文字再檢索」的中間層，也讓 RAG 系統更接近真實世界的資料形態。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Gemini 進入 Google built-in 汽車：車載語音助理開始變得更像真正的 AI 助理</title>
        <link>https://knightli.com/zh-tw/2026/05/01/gemini-cars-with-google-built-in/</link>
        <pubDate>Fri, 01 May 2026 06:09:57 +0800</pubDate>
        
        <guid>https://knightli.com/zh-tw/2026/05/01/gemini-cars-with-google-built-in/</guid>
        <description>&lt;p&gt;Google 在 2026 年 4 月 30 日宣布，&lt;code&gt;Gemini&lt;/code&gt; 開始進入搭載 &lt;code&gt;Google built-in&lt;/code&gt; 的汽車，作為 Google Assistant 的升級版本陸續推送。&lt;/p&gt;
&lt;p&gt;這件事的重點不只是「車裡多了一個 AI 助理」，而是車載語音互動正在從固定命令，轉向更自然的連續對話。使用者不需要嚴格記住指令格式，可以像和一般助理交流一樣，讓 Gemini 幫忙導航、處理訊息、查詢車輛資訊，甚至控制部分車內設定。&lt;/p&gt;
&lt;h2 id=&#34;先從美國英語使用者開始&#34;&gt;先從美國英語使用者開始
&lt;/h2&gt;&lt;p&gt;根據 Google 的說明，這次更新會涵蓋新車和既有車輛，前提是車輛支援 &lt;code&gt;Google built-in&lt;/code&gt;，並且使用者已經在車機裡登入 Google 帳號。&lt;/p&gt;
&lt;p&gt;rollout 會先從美國英語使用者開始，之後再擴展到更多語言和國家。符合條件的使用者會在車內看到升級到 Gemini 的提示。升級後，可以透過以下方式喚起 Gemini：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;說出 &lt;code&gt;Hey Google&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;點擊主畫面上的麥克風&lt;/li&gt;
&lt;li&gt;使用方向盤上的語音按鈕&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這說明 Google 沒有把 Gemini 做成一個需要重新學習的新入口，而是延續原本的車載語音入口，只是把底層助理換成更強的 Gemini。&lt;/p&gt;
&lt;h2 id=&#34;車載語音不再只靠固定命令&#34;&gt;車載語音不再只靠固定命令
&lt;/h2&gt;&lt;p&gt;過去車載語音助理常見的問題是：能做的事不少，但使用者必須說得很「標準」。一旦表達稍微複雜，助理就容易聽不懂，或者只能執行最基礎的動作。&lt;/p&gt;
&lt;p&gt;Gemini 進入車機後，Google 強調的是自然對話能力。比如使用者可以直接說：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I need to grab lunch, find some highly rated sit-down restaurants along the way. I&amp;rsquo;m not in a rush, oh, and I’d like to eat outside.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Gemini 會結合 Google Maps 找沿途合適的餐廳。使用者還可以繼續追問停車情況、是否有素食選項等，不需要重新發起一輪完整搜尋。&lt;/p&gt;
&lt;p&gt;這種互動更符合駕駛場景。人在開車時很難像使用手機一樣反覆篩選、點擊和修改條件，語音助理如果能理解更完整的意圖，就能明顯減少分心。&lt;/p&gt;
&lt;h2 id=&#34;地圖訊息和音樂會變得更順手&#34;&gt;地圖、訊息和音樂會變得更順手
&lt;/h2&gt;&lt;p&gt;Google 給出的幾個例子，基本都圍繞駕駛時最常見的需求。&lt;/p&gt;
&lt;p&gt;第一類是路線和地點搜尋。&lt;/p&gt;
&lt;p&gt;Gemini 可以根據 Google Maps 資訊尋找沿途餐廳、景點或充電站，也可以回答和目前路線相關的問題。比如經過體育場附近時，使用者可以問附近是否有活動、是否會影響交通。&lt;/p&gt;
&lt;p&gt;第二類是訊息處理。&lt;/p&gt;
&lt;p&gt;使用者可以讓 Gemini 總結新簡訊，再根據上下文回覆。比如讓它回覆朋友「我在路上，並附上預計到達時間」。如果臨時想改內容，也可以繼續補充，不必從頭開始。&lt;/p&gt;
&lt;p&gt;第三類是音樂和氛圍。&lt;/p&gt;
&lt;p&gt;使用者不一定需要知道電台名或具體歌單，可以直接描述想聽的內容。例如播放爵士電台，或者在 YouTube Music 裡播放適合山路駕駛的歡快 70 年代 folk-rock，並跳過慢歌。&lt;/p&gt;
&lt;p&gt;這些功能本身並不新，但 Gemini 的價值在於把多個條件合在一句自然語言裡處理，而不是把使用者逼回固定命令。&lt;/p&gt;
&lt;h2 id=&#34;gemini-live-讓車裡也能邊走邊聊&#34;&gt;Gemini Live 讓車裡也能邊走邊聊
&lt;/h2&gt;&lt;p&gt;Google 還提到，&lt;code&gt;Gemini Live&lt;/code&gt; 也會進入車載場景，目前處於 beta。使用者可以點擊 Gemini Live 按鈕，或者說 &lt;code&gt;Hey Google, let&#39;s talk&lt;/code&gt; 開始更自由的對話。&lt;/p&gt;
&lt;p&gt;這類場景更像「開車時的陪伴式學習和腦力激盪」。例如開車去 Lake Tahoe 時，可以讓 Gemini 講當地歷史和趣聞；聽到感興趣的內容後，可以隨時打斷追問。也可以讓 Gemini 幫忙規劃到達目的地後的徒步路線和活動安排。&lt;/p&gt;
&lt;p&gt;這和傳統車載助理的差異很明顯。傳統助理更像工具按鈕，Gemini Live 則更像一個可以連續交流的語音介面。&lt;/p&gt;
&lt;h2 id=&#34;車輛說明書和即時車況是關鍵差異&#34;&gt;車輛說明書和即時車況是關鍵差異
&lt;/h2&gt;&lt;p&gt;更值得注意的是，Gemini 不只是回答通用問題。Google 表示，他們和車廠合作，把 Gemini 更深入地接入車輛系統。&lt;/p&gt;
&lt;p&gt;這帶來幾類更貼近汽車本身的能力。&lt;/p&gt;
&lt;p&gt;第一，使用者可以詢問車輛功能。&lt;/p&gt;
&lt;p&gt;比如「自動洗車前我應該怎麼準備？」或者「我的車庫天花板太低，後車廂門會碰到，怎麼設定後車廂不要完全打開？」Gemini 會根據車廠提供的車主手冊，給出適配具體車型的答案。不同品牌和車型能提供的資訊細節會有所差異。&lt;/p&gt;
&lt;p&gt;第二，電動車使用者可以詢問即時電量和續航。&lt;/p&gt;
&lt;p&gt;例如目前電量、到達目的地時預計剩餘電量，或者讓 Gemini 查找附近充電站。它還可以結合 Google Maps，幫使用者找充電附近的咖啡店等地點。&lt;/p&gt;
&lt;p&gt;第三，部分車內設定可以透過自然語言調整。&lt;/p&gt;
&lt;p&gt;Google 舉的例子是使用者說「車裡又起霧又冷」，Gemini 可以理解背後的意圖，調高暖風並打開除霧。&lt;/p&gt;
&lt;p&gt;這類能力比單純把聊天機器人搬進車機更實際。汽車是一個有明確狀態、硬體能力和安全邊界的環境，AI 助理如果能理解車輛上下文，價值會比普通問答更高。&lt;/p&gt;
&lt;h2 id=&#34;車載-ai-的邊界也更重要&#34;&gt;車載 AI 的邊界也更重要
&lt;/h2&gt;&lt;p&gt;車內場景對 AI 的要求和手機、網頁不同。&lt;/p&gt;
&lt;p&gt;開車時使用者不能頻繁看螢幕，也不能花太多注意力糾正 AI。助理需要足夠簡潔、可靠，並且不能在關鍵場景裡製造新的負擔。&lt;/p&gt;
&lt;p&gt;所以 Gemini 進入汽車並不意味著所有複雜任務都適合在車裡完成。更合理的方向是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;降低導航和資訊查詢的操作成本&lt;/li&gt;
&lt;li&gt;用自然語言替代多層選單&lt;/li&gt;
&lt;li&gt;幫使用者快速理解車輛功能&lt;/li&gt;
&lt;li&gt;在不分散注意力的前提下處理訊息和媒體&lt;/li&gt;
&lt;li&gt;給 EV 使用者更順滑的充電與路線資訊&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;反過來，高風險操作仍然需要清晰邊界。比如影響駕駛安全的設定、需要確認的訊息發送、涉及車輛控制的動作，都應該有足夠明確的確認流程。&lt;/p&gt;
&lt;h2 id=&#34;小結&#34;&gt;小結
&lt;/h2&gt;&lt;p&gt;Gemini 進入 &lt;code&gt;Google built-in&lt;/code&gt; 汽車，是 AI 助理從手機和網頁繼續向日常環境擴展的一步。&lt;/p&gt;
&lt;p&gt;它的意義不在於車裡終於可以「聊天」，而在於車載語音助理開始理解更複雜的意圖，並能結合地圖、訊息、音樂、車輛說明書和部分車況資訊來完成任務。&lt;/p&gt;
&lt;p&gt;如果 rollout 順利，車載語音互動可能會從「記住命令」逐漸變成「描述需求」。這對開車場景很重要，因為真正好的車載 AI，不應該要求駕駛者為它分配太多注意力。&lt;/p&gt;
&lt;p&gt;參考連結：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://blog.google/products-and-platforms/platforms/android/cars-with-google-built-in-gemini-tips-2026/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Your car with Google built-in is about to get smarter, thanks to Gemini - Google Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>ChatGPT、Claude、Gemini 怎麼分工：日常對話、程式開發與特殊能力該怎麼選</title>
        <link>https://knightli.com/zh-tw/2026/04/25/chatgpt-claude-gemini-task-selection/</link>
        <pubDate>Sat, 25 Apr 2026 10:51:19 +0800</pubDate>
        
        <guid>https://knightli.com/zh-tw/2026/04/25/chatgpt-claude-gemini-task-selection/</guid>
        <description>&lt;p&gt;現在很多人不再只用一個模型，而是會在 &lt;code&gt;ChatGPT&lt;/code&gt;、&lt;code&gt;Claude&lt;/code&gt; 和 &lt;code&gt;Gemini&lt;/code&gt; 之間來回切換。問題也因此變得很實際：&lt;strong&gt;到底什麼任務該交給誰？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;這件事之所以容易讓人糾結，不是因為三家都不夠強，而是因為它們已經強到開始「分工不同」。如果還是用「誰更聰明」這種非常籠統的標準去選，反而更容易選錯。&lt;/p&gt;
&lt;p&gt;如果先講一個簡化版結論，可以大致這樣理解：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;日常對話和綜合型任務，很多人會先想到 &lt;code&gt;ChatGPT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;命令列程式開發、長上下文協作、持續推進型任務，&lt;code&gt;Claude&lt;/code&gt; 往往更順手&lt;/li&gt;
&lt;li&gt;需要依賴 Google 生態、搜尋、多模態入口或某些產品級特殊能力時，&lt;code&gt;Gemini&lt;/code&gt; 更有存在感&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下面分三塊來講。&lt;/p&gt;
&lt;h2 id=&#34;1-日常對話為什麼很多人還是先打開-chatgpt&#34;&gt;1. 日常對話：為什麼很多人還是先打開 &lt;code&gt;ChatGPT&lt;/code&gt;
&lt;/h2&gt;&lt;p&gt;對大多數一般使用情境來說，&lt;code&gt;ChatGPT&lt;/code&gt; 仍然很像「預設入口」。&lt;/p&gt;
&lt;p&gt;這裡說的不是某一個 benchmark，而是整體體驗：&lt;br&gt;
當你臨時想問一個問題、整理一個思路、寫一段文案、做一份初稿、總結一篇資料時，&lt;code&gt;ChatGPT&lt;/code&gt; 通常給人的感覺會比較均衡。&lt;/p&gt;
&lt;p&gt;它的優勢往往體現在幾個地方：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;回答風格比較穩定&lt;/li&gt;
&lt;li&gt;一般使用者上手門檻低&lt;/li&gt;
&lt;li&gt;多數綜合型任務不需要太多額外調教&lt;/li&gt;
&lt;li&gt;產品完成度高，適合高頻日常使用&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以如果你的任務是下面這種：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;幫我整理一個主題&lt;/li&gt;
&lt;li&gt;把一段想法寫成結構化內容&lt;/li&gt;
&lt;li&gt;總結一篇長文&lt;/li&gt;
&lt;li&gt;腦力激盪幾個方案&lt;/li&gt;
&lt;li&gt;把表達潤飾得更清楚&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;那 &lt;code&gt;ChatGPT&lt;/code&gt; 往往就是一個很自然的起點。&lt;/p&gt;
&lt;p&gt;這並不代表它在所有專業任務裡都一定最強，而是它在「廣譜通用」這件事上，通常更像一個預設工作台。&lt;/p&gt;
&lt;h2 id=&#34;2-命令列程式開發與長任務為什麼很多人更偏向-claude&#34;&gt;2. 命令列程式開發與長任務：為什麼很多人更偏向 &lt;code&gt;Claude&lt;/code&gt;
&lt;/h2&gt;&lt;p&gt;一旦任務從「聊一聊」切換成「把事情持續做完」，很多人的偏好就會開始轉向 &lt;code&gt;Claude&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;尤其是在這些場景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;命令列程式開發&lt;/li&gt;
&lt;li&gt;大型專案上下文理解&lt;/li&gt;
&lt;li&gt;多檔案協作修改&lt;/li&gt;
&lt;li&gt;長鏈路除錯&lt;/li&gt;
&lt;li&gt;一邊讀程式碼一邊推進任務&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這類任務的關鍵，往往不是單輪回答有多驚艷，而是模型能不能在更長的任務鏈裡保持穩定。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Claude&lt;/code&gt; 經常被偏愛的原因，通常不是「它一句話比別人更會說」，而是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;對長上下文任務更耐用&lt;/li&gt;
&lt;li&gt;連續讀檔案、讀日誌、讀規則時體驗更穩定&lt;/li&gt;
&lt;li&gt;更適合逐步推進複雜編碼任務&lt;/li&gt;
&lt;li&gt;在命令列與 agent 工作流裡更常被當成主力模型&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你是在做 &lt;code&gt;vibe coding&lt;/code&gt;、命令列修 bug、理解專案結構，或跨多個檔案改功能，&lt;code&gt;Claude&lt;/code&gt; 的優勢會更容易體現出來。&lt;/p&gt;
&lt;p&gt;簡單說，&lt;code&gt;Claude&lt;/code&gt; 比較像那種適合一起「幹活」的模型，而不只是適合問一句答一句。&lt;/p&gt;
&lt;h2 id=&#34;3-gemini-的優勢往往不在跟別人正面拼一切&#34;&gt;3. &lt;code&gt;Gemini&lt;/code&gt; 的優勢往往不在「跟別人正面拼一切」
&lt;/h2&gt;&lt;p&gt;很多人討論 &lt;code&gt;Gemini&lt;/code&gt; 時，容易把問題問成：它到底是不是三家裡最強。&lt;/p&gt;
&lt;p&gt;但從實際使用體驗來看，更有用的問題通常不是這個，而是：&lt;strong&gt;它在哪些情境裡特別值得單獨拿出來用。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Gemini&lt;/code&gt; 的價值，往往更容易體現在這些方向：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Google 生態整合&lt;/li&gt;
&lt;li&gt;搜尋與資料取得&lt;/li&gt;
&lt;li&gt;多模態入口&lt;/li&gt;
&lt;li&gt;某些產品側功能聯動&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你的工作流本來就和 Google 的工具鏈很近，例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;搜尋&lt;/li&gt;
&lt;li&gt;文件&lt;/li&gt;
&lt;li&gt;郵件&lt;/li&gt;
&lt;li&gt;瀏覽器側使用&lt;/li&gt;
&lt;li&gt;手機端入口&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;那 &lt;code&gt;Gemini&lt;/code&gt; 的實際便利性可能會高於單純的模型分數對比。&lt;/p&gt;
&lt;p&gt;也就是說，&lt;code&gt;Gemini&lt;/code&gt; 的可用性很多時候來自「它在哪裡更順手接入你的工作流」，而不只是「它單輪回答是不是贏了誰」。&lt;/p&gt;
&lt;h2 id=&#34;4-真正有用的選法不是問誰最強而是問任務類型&#34;&gt;4. 真正有用的選法，不是問誰最強，而是問任務類型
&lt;/h2&gt;&lt;p&gt;把三家模型放在一起比較時，最容易踩的坑就是試圖找出一個「唯一最強」。&lt;/p&gt;
&lt;p&gt;但現實裡的任務差異太大了：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;有的是一次性問答&lt;/li&gt;
&lt;li&gt;有的是長對話陪跑&lt;/li&gt;
&lt;li&gt;有的是程式碼工程&lt;/li&gt;
&lt;li&gt;有的是資訊檢索&lt;/li&gt;
&lt;li&gt;有的是多模態處理&lt;/li&gt;
&lt;li&gt;有的是工具鏈協作&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以更有效的選法，通常是按任務類型來分：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;需要一個綜合型、日常高頻、打開就能用的助手：先看 &lt;code&gt;ChatGPT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;需要長上下文、命令列、程式開發協作、持續推進複雜任務：優先試 &lt;code&gt;Claude&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;需要借力 Google 生態、搜尋、多模態入口或某些產品聯動能力：重點看 &lt;code&gt;Gemini&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這樣分工，比硬要爭一個總冠軍更接近真實使用。&lt;/p&gt;
&lt;h2 id=&#34;5-為什麼很多重度使用者會同時訂三家&#34;&gt;5. 為什麼很多重度使用者會同時訂三家
&lt;/h2&gt;&lt;p&gt;從輕度使用者視角來看，同時訂三家模型服務很容易顯得「重複」。&lt;br&gt;
但從重度使用者視角來看，這更像是在為不同任務配不同工具。&lt;/p&gt;
&lt;p&gt;原因很簡單：&lt;br&gt;
如果三家的長處已經開始明顯分化，那麼同時使用它們，本質上就不是重複付費，而是在降低任務切換成本與試錯成本。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;日常整理和綜合問答，用 &lt;code&gt;ChatGPT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;程式開發主任務，用 &lt;code&gt;Claude&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;某些檢索、多模態或 Google 相關鏈路，用 &lt;code&gt;Gemini&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這種組合方式的邏輯，和設計師同時裝多個軟體、開發者同時使用多個 IDE，並沒有本質差別。&lt;/p&gt;
&lt;h2 id=&#34;6-什麼時候不要來回切太多模型&#34;&gt;6. 什麼時候不要來回切太多模型
&lt;/h2&gt;&lt;p&gt;當然，模型多也不一定總是更好。&lt;/p&gt;
&lt;p&gt;如果你本身還在建立穩定工作流，過早在三個模型之間頻繁橫跳，反而可能讓自己更亂。常見問題包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;同一個任務來回重複講三遍&lt;/li&gt;
&lt;li&gt;不同模型給出不同建議，自己更難判斷&lt;/li&gt;
&lt;li&gt;上下文斷裂，協作成本反而更高&lt;/li&gt;
&lt;li&gt;還沒形成自己的使用邊界，就先被工具選擇拖住&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以更穩的方式通常是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先給每個模型一個主場景&lt;/li&gt;
&lt;li&gt;在主場景裡連續用一段時間&lt;/li&gt;
&lt;li&gt;再逐步形成自己的分工習慣&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;這樣你會更容易得到真正可複用的經驗，而不是永遠停留在「今天換這個試試」的階段。&lt;/p&gt;
&lt;h2 id=&#34;7-可以先這樣記住&#34;&gt;7. 可以先這樣記住
&lt;/h2&gt;&lt;p&gt;如果只想先記一個夠用的版本，可以直接記這張口語化分工表：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ChatGPT&lt;/code&gt;：更像通用型預設助手&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Claude&lt;/code&gt;：更像長任務和程式開發協作主力&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Gemini&lt;/code&gt;：更像在搜尋、多模態和 Google 生態裡更有優勢的工具&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這不是絕對規則，也不是說三者彼此不能替代，而是一個更接近真實使用體驗的起點。&lt;/p&gt;
&lt;p&gt;真正重要的不是選出「宇宙最強模型」，而是盡快知道：&lt;br&gt;
&lt;strong&gt;你手上的這類任務，用哪個模型最省時間、最省心、最容易做出結果。&lt;/strong&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Google App 桌面版體驗：把 AI 搜尋放進 Windows</title>
        <link>https://knightli.com/zh-tw/2026/04/18/google-app-desktop-ai-search-windows/</link>
        <pubDate>Sat, 18 Apr 2026 11:08:00 +0800</pubDate>
        
        <guid>https://knightli.com/zh-tw/2026/04/18/google-app-desktop-ai-search-windows/</guid>
        <description>&lt;p&gt;Google 把一個更輕量的搜尋入口放到了 Windows 桌面上：不用每次先打開瀏覽器，只要按下快捷鍵，就能直接調出一個搜尋框，輸入問題、上傳圖片、分析檔案、圈選螢幕內容，甚至繼續追問。&lt;/p&gt;
&lt;p&gt;這款工具的官方名稱是 &lt;strong&gt;Google app for desktop&lt;/strong&gt;。它的定位不是再做一個傳統瀏覽器，而是把 Google Search、AI Mode、Google Lens、螢幕分享、電腦檔案搜尋和 Google Drive 搜尋整合到一個桌面入口裡。&lt;/p&gt;
&lt;p&gt;如果你平時經常查資料、總結文件、識別截圖內容，或者希望像呼叫啟動器一樣快速搜尋電腦裡的東西，這個桌面版 Google App 會比較適合嘗試。&lt;/p&gt;
&lt;h2 id=&#34;支援條件&#34;&gt;支援條件
&lt;/h2&gt;&lt;p&gt;根據 Google 官方頁面，目前桌面版 Google App 的要求如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用者需年滿 13 歲。&lt;/li&gt;
&lt;li&gt;裝置需要執行 Windows 10 或更高版本。&lt;/li&gt;
&lt;li&gt;目前應用程式僅支援英文。&lt;/li&gt;
&lt;li&gt;Google Search 的 AI Mode 並非支援所有帳號、國家和語言。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;也就是說，如果你使用的是 Windows 10 或 Windows 11，可以先安裝測試。官方頁面目前明確寫的是 &lt;strong&gt;Now available on Windows&lt;/strong&gt;，所以這裡以 Windows 版為準介紹。&lt;/p&gt;
&lt;h2 id=&#34;主要功能&#34;&gt;主要功能
&lt;/h2&gt;&lt;h3 id=&#34;1-快捷鍵調出搜尋框&#34;&gt;1. 快捷鍵調出搜尋框
&lt;/h3&gt;&lt;p&gt;安裝完成後，可以透過：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Alt + Space
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;快速調出 Google 桌面搜尋框。再按一次可以隱藏。&lt;/p&gt;
&lt;p&gt;這個體驗有點像系統啟動器：無論你正在寫文件、看網頁、整理檔案，還是打開了其他應用程式，都可以直接喚出搜尋入口，不需要切回瀏覽器。&lt;/p&gt;
&lt;h3 id=&#34;2-ai-mode-搜尋與連續追問&#34;&gt;2. AI Mode 搜尋與連續追問
&lt;/h3&gt;&lt;p&gt;普通搜尋通常是給你一組網頁連結，而 AI Mode 更像是把搜尋結果先整理成答案。你可以直接問一個問題，它會給出較完整的說明，並附帶可繼續查看的連結。&lt;/p&gt;
&lt;p&gt;更實用的是，它支援繼續追問。比如你先問：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;這款工具適合用來做什麼？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;得到答案後，可以繼續問：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;如果我是內容創作者，應該怎麼用它提升效率？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;這樣就不用反覆更換關鍵字，也不用在多個網頁之間來回跳。&lt;/p&gt;
&lt;h3 id=&#34;3-上傳圖片進行識別和搜尋&#34;&gt;3. 上傳圖片進行識別和搜尋
&lt;/h3&gt;&lt;p&gt;桌面版 Google App 支援上傳圖片後提問。常見用法包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;識別圖片裡的人物、地點、商品或物體。&lt;/li&gt;
&lt;li&gt;查找相似圖片和相關資料。&lt;/li&gt;
&lt;li&gt;根據圖片內容提取描述。&lt;/li&gt;
&lt;li&gt;讓 AI 基於圖片繼續生成創意提示詞。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;比如上傳一張人物圖片後，可以問：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;圖片中的人物是誰？請提供相關介紹和參考資料。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果只是日常查圖、找出處、識別物品，這會比手動打開網頁再上傳圖片更順手。&lt;/p&gt;
&lt;h3 id=&#34;4-google-lens-圈選螢幕內容&#34;&gt;4. Google Lens 圈選螢幕內容
&lt;/h3&gt;&lt;p&gt;Google Lens 是這款桌面應用程式裡很實用的一部分。你可以直接圈選螢幕上的某一塊內容，讓它識別並搜尋。&lt;/p&gt;
&lt;p&gt;適合這些場景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;圈選網頁裡的商品，查找同款或相關資訊。&lt;/li&gt;
&lt;li&gt;圈選截圖中的文字，讓它解釋含義。&lt;/li&gt;
&lt;li&gt;圈選軟體介面，讓它判斷這是什麼工具。&lt;/li&gt;
&lt;li&gt;圈選錯誤訊息，讓它幫你定位問題。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;它的核心價值是「看到什麼，搜什麼」。以前你可能需要截圖、儲存、上傳，現在可以直接在螢幕上選中目標。&lt;/p&gt;
&lt;h3 id=&#34;5-螢幕分享搜尋&#34;&gt;5. 螢幕分享搜尋
&lt;/h3&gt;&lt;p&gt;除了圈選某一部分內容，它還支援螢幕分享。開啟後，可以讓 AI 看到目前視窗或整個螢幕，然後圍繞螢幕內容提問。&lt;/p&gt;
&lt;p&gt;例如你正在打開一篇部落格，可以問：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;請總結目前頁面的重點內容。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;也可以問：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;你覺得這個頁面有哪些可以優化的地方？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;在閱讀網頁、檢查設計稿、分析程式碼片段、總結長頁面時，這個功能會比較省時間。開啟螢幕分享時，系統通常會有明顯的邊框提示，方便確認目前是否正在分享。&lt;/p&gt;
&lt;h3 id=&#34;6-搜尋電腦檔案和-google-drive&#34;&gt;6. 搜尋電腦檔案和 Google Drive
&lt;/h3&gt;&lt;p&gt;官方介紹中還提到，它可以從同一個搜尋框裡查找電腦上的應用程式和檔案，也可以搜尋 Google Drive。&lt;/p&gt;
&lt;p&gt;這類功能更像是把桌面搜尋和雲端搜尋放在一起。比如你記得某個檔案的大概名字、內容關鍵字，或者想快速找到 Google Drive 裡的資料，就不必分別打開檔案總管和雲端硬碟頁面。&lt;/p&gt;
&lt;p&gt;首次使用時，如果頁面提示開啟 Google Drive 搜尋或本機檔案搜尋，可以按自己的需求授權。涉及本機檔案和雲端資料時，建議只開啟自己確實需要的範圍。&lt;/p&gt;
&lt;h2 id=&#34;安裝與使用步驟&#34;&gt;安裝與使用步驟
&lt;/h2&gt;&lt;h3 id=&#34;1-打開官方下載頁面&#34;&gt;1. 打開官方下載頁面
&lt;/h3&gt;&lt;p&gt;訪問官方頁面：&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://search.google/google-app/desktop/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://search.google/google-app/desktop/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;點擊頁面上的 &lt;strong&gt;Download app&lt;/strong&gt; 下載應用程式。&lt;/p&gt;
&lt;h3 id=&#34;2-安裝桌面應用程式&#34;&gt;2. 安裝桌面應用程式
&lt;/h3&gt;&lt;p&gt;下載完成後，執行安裝程式，按提示完成安裝即可。&lt;/p&gt;
&lt;p&gt;安裝後可以選擇登入 Google 帳號。登入後更方便使用 Google Drive 搜尋、個人化搜尋以及部分 AI 能力；如果只是做基礎搜尋，也可以先按頁面提示體驗。&lt;/p&gt;
&lt;h3 id=&#34;3-調出搜尋框&#34;&gt;3. 調出搜尋框
&lt;/h3&gt;&lt;p&gt;按下快捷鍵：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Alt + Space
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;桌面上會出現 Google 搜尋框。你可以直接輸入問題，也可以使用上傳、Lens、螢幕分享等功能。&lt;/p&gt;
&lt;h3 id=&#34;4-開啟需要的搜尋範圍&#34;&gt;4. 開啟需要的搜尋範圍
&lt;/h3&gt;&lt;p&gt;如果你希望搜尋 Google Drive 或本機檔案，可以根據提示開啟相關權限。&lt;/p&gt;
&lt;p&gt;建議做法是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;先開啟 Google Drive 搜尋，測試雲端資料查找效果。&lt;/li&gt;
&lt;li&gt;再按需開啟本機檔案搜尋。&lt;/li&gt;
&lt;li&gt;不需要搜尋的範圍就先不要授權。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這樣既能體驗完整功能，也能更清楚它存取了哪些資料。&lt;/p&gt;
&lt;h2 id=&#34;常見使用場景&#34;&gt;常見使用場景
&lt;/h2&gt;&lt;h3 id=&#34;分析-pdf-和文件&#34;&gt;分析 PDF 和文件
&lt;/h3&gt;&lt;p&gt;可以把 PDF、表格或文件拖進去，讓它幫你總結重點。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;請總結這份 PDF 的核心內容，並列出需要注意的事項。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果是表格、流水、申請表、說明書這類資訊密度高的檔案，可以繼續追問：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;請按類別整理其中的關鍵資訊。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;這類場景比自己逐頁翻文件更有效率。&lt;/p&gt;
&lt;h3 id=&#34;總結網頁內容&#34;&gt;總結網頁內容
&lt;/h3&gt;&lt;p&gt;開啟螢幕分享後，可以讓它直接總結目前頁面。&lt;/p&gt;
&lt;p&gt;比如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;請提煉這個頁面的主要觀點，並用 5 條要點總結。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;適合快速瀏覽長文章、產品頁面、說明文件或新聞內容。&lt;/p&gt;
&lt;h3 id=&#34;識別截圖和介面&#34;&gt;識別截圖和介面
&lt;/h3&gt;&lt;p&gt;用 Google Lens 圈選螢幕上的軟體介面、程式碼片段、錯誤提示或圖片內容，可以讓它解釋目前看到的資訊。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;請解釋這段錯誤是什麼意思，並給出排查思路。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;或者：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;請判斷這個截圖裡展示的是什麼工具，它可能用於什麼場景。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;輔助內容創作&#34;&gt;輔助內容創作
&lt;/h3&gt;&lt;p&gt;它也可以用來寫標題、生成大綱、整理賣點。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;幫我寫 10 個關於 AI 工具推薦的文章標題，分別偏向乾貨、效率工具和職場辦公方向。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;得到初稿後，還可以繼續要求它按平台風格優化：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;把這些標題改得更適合科技部落格。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;這種連續追問的體驗，比一次性讓搜尋引擎給結果更自然。&lt;/p&gt;
&lt;h2 id=&#34;使用建議&#34;&gt;使用建議
&lt;/h2&gt;&lt;p&gt;如果只是日常查資料，可以把它當成一個更快的 Google Search 入口；如果你經常處理圖片、PDF、網頁和截圖，就可以重點嘗試 Lens、檔案上傳和螢幕分享。&lt;/p&gt;
&lt;p&gt;使用時也建議注意三點：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;目前官方頁面寫明僅英文可用，中文提問的效果可能會因帳號和地區而不同。&lt;/li&gt;
&lt;li&gt;AI Mode 不一定對所有帳號開放，如果看不到相關能力，可以先確認帳號、地區和語言設定。&lt;/li&gt;
&lt;li&gt;本機檔案、Google Drive、螢幕分享都涉及隱私權限，開啟前先確認自己要讓它存取哪些內容。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;快速總結&#34;&gt;快速總結
&lt;/h2&gt;&lt;p&gt;Google App 桌面版最大的價值，是把搜尋入口從瀏覽器裡抽出來，變成一個隨時可以呼出的桌面 AI 搜尋框。&lt;/p&gt;
&lt;p&gt;它能做的事情可以概括為：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Alt + Space&lt;/code&gt; 快速呼出搜尋。&lt;/li&gt;
&lt;li&gt;用 AI Mode 直接獲得整理後的答案。&lt;/li&gt;
&lt;li&gt;上傳圖片或檔案進行分析。&lt;/li&gt;
&lt;li&gt;用 Google Lens 圈選螢幕內容搜尋。&lt;/li&gt;
&lt;li&gt;透過螢幕分享理解目前視窗或整個螢幕。&lt;/li&gt;
&lt;li&gt;搜尋電腦檔案、應用程式和 Google Drive 內容。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你本來就依賴 Google 搜尋，又希望搜尋過程更接近「問一個助手」，這款桌面版 Google App 值得試一下。&lt;/p&gt;
&lt;h2 id=&#34;參考連結&#34;&gt;參考連結
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Google App 桌面版官方頁面：&lt;a class=&#34;link&#34; href=&#34;https://search.google/google-app/desktop/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://search.google/google-app/desktop/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>分享一個電商商品圖去背與標準化的 Agent Skill</title>
        <link>https://knightli.com/zh-tw/2026/04/09/product-cutout-normalize-agent-skill-guide/</link>
        <pubDate>Thu, 09 Apr 2026 21:43:50 +0800</pubDate>
        
        <guid>https://knightli.com/zh-tw/2026/04/09/product-cutout-normalize-agent-skill-guide/</guid>
        <description>&lt;p&gt;&lt;code&gt;product-cutout-normalize&lt;/code&gt; 是一個給商品圖使用的 Agent Skill。&lt;/p&gt;
&lt;p&gt;它會把原圖處理成統一規格的透明底方圖。預設規則是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;1024x1024&lt;/code&gt; 畫布&lt;/li&gt;
&lt;li&gt;透明背景&lt;/li&gt;
&lt;li&gt;盡量完整保留主體&lt;/li&gt;
&lt;li&gt;直向主體自動轉成橫向&lt;/li&gt;
&lt;li&gt;主體置中&lt;/li&gt;
&lt;li&gt;主體可視寬度統一到 &lt;code&gt;820px&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;適合電商素材、商品庫和詳情頁圖片預處理。&lt;/p&gt;
&lt;h2 id=&#34;這個-skill-解決什麼問題&#34;&gt;這個 skill 解決什麼問題
&lt;/h2&gt;&lt;p&gt;很多商品圖做完基礎去背後，還是會有這些問題：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;白邊或淺灰背景殘留&lt;/li&gt;
&lt;li&gt;主體橫豎方向不一致&lt;/li&gt;
&lt;li&gt;畫布大小不一致&lt;/li&gt;
&lt;li&gt;主體大小忽大忽小&lt;/li&gt;
&lt;li&gt;透明區域裡有小噪點&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這個 skill 會按照固定流程處理：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用 Gemini 去背&lt;/li&gt;
&lt;li&gt;清理邊緣淺色背景&lt;/li&gt;
&lt;li&gt;去掉小碎片噪點&lt;/li&gt;
&lt;li&gt;直圖轉橫圖&lt;/li&gt;
&lt;li&gt;按目標寬度縮放&lt;/li&gt;
&lt;li&gt;放到統一尺寸的透明畫布中央&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;這樣輸出的圖片會更整齊，也更適合批次使用。&lt;/p&gt;
&lt;h2 id=&#34;適用場景&#34;&gt;適用場景
&lt;/h2&gt;&lt;p&gt;適合下面這些需求：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;批次處理商品照片&lt;/li&gt;
&lt;li&gt;統一輸出透明底 PNG&lt;/li&gt;
&lt;li&gt;統一主視覺尺寸&lt;/li&gt;
&lt;li&gt;需要穩定、可重複的處理流程&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你只處理少量圖片，或每張圖都要單獨調整版面，那它未必適合。&lt;/p&gt;
&lt;h2 id=&#34;快速開始&#34;&gt;快速開始
&lt;/h2&gt;&lt;p&gt;最直接的執行方式：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.\.venv\Scripts\python.exe&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.codex\skills\product-cutout-normalize\scripts\run_pipeline.py&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;input_dir&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;output_dir&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-overwrite&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;執行前需要：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GEMINI_API_KEY&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;google-genai&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pillow&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;安裝依賴：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;.\.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;venv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Scripts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;python&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;exe&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-m&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pip&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;install&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;google-genai&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pillow&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;設定環境變數：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$env:GEMINI_API_KEY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;your_api_key&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;輸出規則&#34;&gt;輸出規則
&lt;/h2&gt;&lt;p&gt;預設輸出：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;透明背景 &lt;code&gt;PNG&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1024x1024&lt;/code&gt; 畫布&lt;/li&gt;
&lt;li&gt;主體寬度 &lt;code&gt;820px&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;主體置中&lt;/li&gt;
&lt;li&gt;小噪點會被清理&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以它不只是去背腳本，更像是一個商品圖整理腳本。&lt;/p&gt;
&lt;h2 id=&#34;主要參數說明&#34;&gt;主要參數說明
&lt;/h2&gt;&lt;p&gt;常用參數：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--model&lt;/code&gt;
預設 &lt;code&gt;gemini-2.5-flash-image&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--canvas-size&lt;/code&gt;
輸出方形畫布尺寸，預設 &lt;code&gt;1024&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--target-width&lt;/code&gt;
主體可視寬度，預設 &lt;code&gt;820&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--min-component-pixels&lt;/code&gt;
小於這個像素數的透明碎片會被移除，預設 &lt;code&gt;500&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--overwrite&lt;/code&gt;
輸出檔案已存在時直接覆蓋&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.\.venv\Scripts\python.exe&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.codex\skills\product-cutout-normalize\scripts\run_pipeline.py&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.\input&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.\output&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-canvas-size&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1280&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-target-width&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;960&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-overwrite&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;處理流程&#34;&gt;處理流程
&lt;/h2&gt;&lt;p&gt;處理流程很簡單：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用 Gemini 去背&lt;/li&gt;
&lt;li&gt;清理邊緣淺色背景&lt;/li&gt;
&lt;li&gt;去掉小碎片噪點&lt;/li&gt;
&lt;li&gt;直圖轉橫圖&lt;/li&gt;
&lt;li&gt;按目標寬度縮放&lt;/li&gt;
&lt;li&gt;放到統一尺寸的透明畫布中央&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;和一般去背腳本的差別&#34;&gt;和一般去背腳本的差別
&lt;/h2&gt;&lt;p&gt;和一般去背腳本相比，它還會額外處理這些問題：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;主體方向統一&lt;/li&gt;
&lt;li&gt;主體尺寸統一&lt;/li&gt;
&lt;li&gt;畫布尺寸統一&lt;/li&gt;
&lt;li&gt;小碎片噪點清理&lt;/li&gt;
&lt;li&gt;結果更適合直接放進素材庫&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;skillmd-原始碼&#34;&gt;SKILL.md 原始碼
&lt;/h2&gt;&lt;p&gt;下面保留 &lt;code&gt;SKILL.md&lt;/code&gt; 的完整原始碼，內容不做改動：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;45
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;46
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;47
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;48
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;49
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;50
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;51
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;52
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;53
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;54
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-md&#34; data-lang=&#34;md&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;name: product-cutout-normalize
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;description: Run a reusable Gemini product-image pipeline that removes backgrounds, preserves the full subject, rotates tall products to a horizontal orientation, centers them on a 1024x1024 transparent canvas, and normalizes the visible subject width to 820px. Use when the user wants a repeatable cutout-and-normalize workflow for product photos or asks to batch-process product images into standardized square PNG assets.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gh&#34;&gt;# Product Cutout Normalize
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Use this skill when product photos need the same deterministic finishing pipeline:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; Gemini cutout from the original photo
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; border cleanup to transparent
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; preserve the full subject
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; rotate to horizontal when the subject is taller than it is wide
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; center on a &lt;span class=&#34;sb&#34;&gt;`1024x1024`&lt;/span&gt; transparent canvas
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; normalize the visible subject width to &lt;span class=&#34;sb&#34;&gt;`820px`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gu&#34;&gt;## Quick Start
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Run the bundled script:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;```powershell
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.\.venv\Scripts\python.exe&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.codex\skills\product-cutout-normalize\scripts\run_pipeline.py&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;input_dir&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;output_dir&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-overwrite&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;```&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Required environment:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;sb&#34;&gt;`GEMINI_API_KEY`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;sb&#34;&gt;`google-genai`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;sb&#34;&gt;`Pillow`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gu&#34;&gt;## Workflow
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;1.&lt;/span&gt; Confirm the request matches this standard pipeline. If the user asks for a different canvas size, subject width, or layout rule, pass explicit flags instead of changing the script.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;2.&lt;/span&gt; Run the bundled script on the input directory.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;3.&lt;/span&gt; If a result looks misaligned, inspect the alpha bounding box and small detached artifacts first; this pipeline already removes tiny alpha components by default.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;4.&lt;/span&gt; Report the exact input and output directories used, plus any non-default flags.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gu&#34;&gt;## Script
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Primary entry point:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;sb&#34;&gt;`scripts/run_pipeline.py`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Key flags:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;sb&#34;&gt;`--model`&lt;/span&gt;: Gemini image model, default &lt;span class=&#34;sb&#34;&gt;`gemini-2.5-flash-image`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;sb&#34;&gt;`--canvas-size`&lt;/span&gt;: output square size, default &lt;span class=&#34;sb&#34;&gt;`1024`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;sb&#34;&gt;`--target-width`&lt;/span&gt;: visible subject width after normalization, default &lt;span class=&#34;sb&#34;&gt;`820`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;sb&#34;&gt;`--min-component-pixels`&lt;/span&gt;: remove detached alpha specks smaller than this, default &lt;span class=&#34;sb&#34;&gt;`500`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;sb&#34;&gt;`--overwrite`&lt;/span&gt;: replace existing outputs in the destination directory
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gu&#34;&gt;## Repo Integration
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;If the current project already has [&lt;span class=&#34;nt&#34;&gt;`scripts/nano_banana_cutout.py`&lt;/span&gt;](&lt;span class=&#34;na&#34;&gt;/c:/Work/my_shop/scripts/nano_banana_cutout.py&lt;/span&gt;), prefer that repo script when the user wants the same pipeline inside this repository. Use the bundled skill script when the task is cross-project reuse or when you want the workflow to stay self-contained inside the skill.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;scriptsrun_pipelinepy-原始碼&#34;&gt;scripts/run_pipeline.py 原始碼
&lt;/h2&gt;&lt;p&gt;下面保留 &lt;code&gt;scripts/run_pipeline.py&lt;/code&gt; 的完整原始碼，內容不做改動：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;  1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 45
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 46
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 47
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 48
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 49
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 50
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 51
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 52
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 53
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 54
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 55
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 56
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 57
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 58
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 59
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 60
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 61
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 62
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 63
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 64
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 65
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 66
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 67
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 68
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 69
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 70
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 71
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 72
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 73
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 74
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 75
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 76
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 77
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 78
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 79
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 80
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 81
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 82
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 83
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 84
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 85
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 86
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 87
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 88
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 89
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 90
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 91
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 92
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 93
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 94
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 95
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 96
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 97
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 98
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 99
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;100
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;101
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;102
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;103
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;104
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;105
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;106
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;107
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;108
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;109
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;110
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;111
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;112
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;113
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;114
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;115
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;116
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;117
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;118
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;119
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;120
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;121
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;122
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;123
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;124
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;125
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;126
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;127
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;128
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;129
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;130
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;131
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;132
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;133
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;134
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;135
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;136
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;137
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;138
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;139
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;140
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;141
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;142
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;143
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;144
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;145
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;146
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;147
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;148
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;149
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;150
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;151
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;152
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;153
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;154
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;155
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;156
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;157
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;158
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;159
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;160
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;161
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;162
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;163
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;164
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;165
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;166
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;167
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;168
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;169
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;170
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;171
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;172
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;173
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;174
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;175
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;176
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;177
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;178
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;179
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;180
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;181
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;182
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;183
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;184
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;185
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;186
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;187
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;188
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;189
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;190
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;191
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;192
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;193
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;194
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;195
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;196
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;197
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;198
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;199
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;200
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;201
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;202
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;203
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;204
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;205
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;206
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;207
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;208
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;209
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;210
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;211
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;212
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;213
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;214
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;215
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;216
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;217
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;218
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;219
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;220
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;221
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;222
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;223
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;224
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;225
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;226
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;227
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;228
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;229
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;230
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;231
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;232
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;233
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;234
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;235
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;236
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;237
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;238
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;239
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;240
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;241
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;242
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;243
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;244
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;245
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;246
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;247
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;248
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;249
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;250
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;251
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;252
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;253
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;254
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;255
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;256
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;257
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;258
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;259
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;260
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;261
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;262
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;263
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;264
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;265
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;266
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;267
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;268
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;269
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;270
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;271
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;272
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;273
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;274
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;275
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;276
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;277
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;278
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;279
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;280
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;281
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;282
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;283
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;284
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;285
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;286
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;287
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;288
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;289
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;290
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;291
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;__future__&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;annotations&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;argparse&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;collections&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deque&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pathlib&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;PIL&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;google&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;genai&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;ImportError&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;exc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# pragma: no cover&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;SystemExit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;Missing dependency: google-genai. Install it with &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;sa&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#39;.\.venv\Scripts\python.exe -m pip install google-genai&amp;#39;.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;exc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;PROMPT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;Remove the entire background from this product photo and return only the product &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;on a fully transparent background as a PNG. Keep the full product intact, preserve &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;thin cable details, clean the inner loops and holes, and do not add any new objects &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;or shadows.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;DEFAULT_CANVAS_SIZE&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1024&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;DEFAULT_TARGET_WIDTH&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;820&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;DEFAULT_MIN_COMPONENT_PIXELS&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;500&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;SUPPORTED_EXTENSIONS&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;.jpg&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.jpeg&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.png&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.webp&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;is_light_background_pixel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;brightness&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;spread&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;max&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;min&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;brightness&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;170&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;spread&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;35&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;to_pil_image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;image_obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;isinstance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;image_obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;image_obj&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;pil_image&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;getattr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;image_obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;_pil_image&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;isinstance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pil_image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pil_image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;as_pil&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;getattr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;image_obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;pil_image&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;isinstance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;as_pil&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;as_pil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;TypeError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Unsupported image object type: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;image_obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;!r}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;make_transparent_from_borders&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;rgba&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;convert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;RGBA&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;height&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rgba&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;pixels&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rgba&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;load&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;visited&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;tuple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;queue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deque&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;tuple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deque&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;push_if_bg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;visited&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;_&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pixels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;is_light_background_pixel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;visited&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;queue&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;push_if_bg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;push_if_bg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;height&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;height&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;push_if_bg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;push_if_bg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;width&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;queue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;queue&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;popleft&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ny&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;width&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ny&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;height&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;push_if_bg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ny&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;visited&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;pixels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rgba&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;remove_small_components&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;min_component_pixels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;min_component_pixels&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;rgba&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;convert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;RGBA&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rgba&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getchannel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;A&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;height&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rgba&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;alpha_pixels&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;load&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;rgba_pixels&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rgba&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;load&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;visited&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;tuple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;height&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;alpha_pixels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;visited&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;k&#34;&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;queue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deque&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;tuple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deque&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;visited&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;component&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;tuple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;queue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;cx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cy&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;queue&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;popleft&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;component&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ny&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cy&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cy&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;width&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ny&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;height&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;alpha_pixels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ny&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ny&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;visited&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                            &lt;span class=&#34;k&#34;&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        &lt;span class=&#34;n&#34;&gt;visited&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ny&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        &lt;span class=&#34;n&#34;&gt;queue&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ny&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;component&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;min_component_pixels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;py&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;component&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;_&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rgba_pixels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;py&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;n&#34;&gt;rgba_pixels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;py&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rgba&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;normalize_product_image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;target_width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;rgba&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;convert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;RGBA&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;bbox&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rgba&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getchannel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;A&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getbbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bbox&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;RGBA&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;subject&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rgba&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;subject&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;height&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;subject&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;subject&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;subject&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;90&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;expand&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;resample&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Resampling&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;BICUBIC&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;rotated_bbox&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;subject&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getchannel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;A&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getbbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rotated_bbox&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;subject&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;subject&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rotated_bbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;scale&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;target_width&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;subject&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;width&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;subject&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;subject&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;resize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target_width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;max&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;round&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;subject&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;height&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;scale&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Resampling&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LANCZOS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;canvas&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;RGBA&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;offset_x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;subject&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;offset_y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;subject&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;height&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;canvas&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha_composite&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;subject&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;offset_x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;offset_y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;canvas&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;finalize_product_image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;target_width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;min_component_pixels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;transparent&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;make_transparent_from_borders&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;cleaned&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;remove_small_components&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;transparent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;min_component_pixels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;normalize_product_image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cleaned&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;target_width&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target_width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;save_first_image_part&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;target_width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;min_component_pixels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;getattr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;parts&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parts&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;getattr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;candidates&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;parts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;candidates&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;parts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;RuntimeError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Model returned no content parts.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;part&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;inline_data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;getattr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;part&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;inline_data&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;inline_data&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;isinstance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;part&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;inline_data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;part&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;inline_data&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;inline_data&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;hasattr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;part&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;as_image&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;image&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;to_pil_image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;part&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;as_image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;parent&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mkdir&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;parents&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;exist_ok&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;finalize_product_image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;target_width&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target_width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;min_component_pixels&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min_component_pixels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;save&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;getattr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;inline_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;parent&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mkdir&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;parents&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;exist_ok&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;wb&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;handle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;handle&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;write&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;processed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;finalize_product_image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;n&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;n&#34;&gt;target_width&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target_width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;n&#34;&gt;min_component_pixels&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min_component_pixels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;processed&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;save&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;with_suffix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;.png&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;suffix&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lower&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.png&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;unlink&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;missing_ok&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;RuntimeError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Model returned text only and no edited image.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;process_image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;src&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;target_width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;min_component_pixels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;src&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;convert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;RGBA&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;response&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;models&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;generate_content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;contents&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PROMPT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;save_first_image_part&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;target_width&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target_width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;min_component_pixels&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min_component_pixels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;parse_args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;argparse&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Namespace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parser&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;argparse&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;description&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Cut out product images with Gemini and normalize them to square transparent PNGs.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parser&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_argument&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;input_dir&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parser&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_argument&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;output_dir&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parser&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_argument&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;--model&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;gemini-2.5-flash-image&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parser&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_argument&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;--canvas-size&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;DEFAULT_CANVAS_SIZE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parser&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_argument&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;--target-width&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;DEFAULT_TARGET_WIDTH&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parser&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_argument&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;--min-component-pixels&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;DEFAULT_MIN_COMPONENT_PIXELS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parser&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_argument&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;--overwrite&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;action&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;store_true&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parser&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;parse_args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parse_args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;api_key&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;environ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;GEMINI_API_KEY&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;api_key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;SystemExit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Missing GEMINI_API_KEY environment variable.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;input_dir&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;is_dir&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;SystemExit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Input directory does not exist: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;input_dir&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;SystemExit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;--canvas-size must be positive.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target_width&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target_width&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;SystemExit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;--target-width must be positive and no larger than --canvas-size.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min_component_pixels&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;SystemExit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;--min-component-pixels must be &amp;gt;= 0.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;output_dir&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mkdir&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;parents&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;exist_ok&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;genai&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Client&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;api_key&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;api_key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;src&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;sorted&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;input_dir&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;iterdir&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;src&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;is_file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;src&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;suffix&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lower&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SUPPORTED_EXTENSIONS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;output_dir&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;src&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stem&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.png&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exists&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;overwrite&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;skip &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;process_image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;src&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;canvas_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;target_width&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target_width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;min_component_pixels&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min_component_pixels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;下載附件：&lt;a class=&#34;link&#34; href=&#34;product-cutout-normalize.7z&#34; &gt;product-cutout-normalize.7z&lt;/a&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>如何呼叫 Google Nano Banana 做圖片去背</title>
        <link>https://knightli.com/zh-tw/2026/04/09/google-nano-banana-cutout-guide/</link>
        <pubDate>Thu, 09 Apr 2026 20:10:48 +0800</pubDate>
        
        <guid>https://knightli.com/zh-tw/2026/04/09/google-nano-banana-cutout-guide/</guid>
        <description>&lt;p&gt;這篇文章用一段實際可執行的 Python 腳本，示範如何呼叫 Google 的 &lt;code&gt;Nano Banana&lt;/code&gt; 圖像編輯能力來做商品圖去背。&lt;/p&gt;
&lt;p&gt;目前這份實作的目標很明確：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;讀取一個目錄中的商品圖片&lt;/li&gt;
&lt;li&gt;呼叫 Google 圖像模型執行背景移除&lt;/li&gt;
&lt;li&gt;對回傳圖片再做一次本地透明背景清理&lt;/li&gt;
&lt;li&gt;最終輸出為透明底 &lt;code&gt;PNG&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你手上已經有一批白底商品圖、耳機圖、線材圖，想快速生成可用於電商的透明背景圖片，這種方式會很直接。&lt;/p&gt;
&lt;h2 id=&#34;這段程式碼做了什麼&#34;&gt;這段程式碼做了什麼
&lt;/h2&gt;&lt;p&gt;這份腳本主要分成 4 個部分：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;定義提示詞，讓模型知道要執行「去背景、保留主體、不要加陰影」&lt;/li&gt;
&lt;li&gt;呼叫 &lt;code&gt;google-genai&lt;/code&gt; 的圖像生成介面&lt;/li&gt;
&lt;li&gt;從模型回應中提取圖片結果&lt;/li&gt;
&lt;li&gt;再用本地邏輯把邊緣淺色背景轉成透明，減少殘邊&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;也就是說，它不是單純把圖片丟給模型就結束，而是把「模型編輯 + 本地後處理」串起來了。&lt;/p&gt;
&lt;h2 id=&#34;執行前準備&#34;&gt;執行前準備
&lt;/h2&gt;&lt;p&gt;先安裝依賴：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.&lt;span class=&#34;se&#34;&gt;\.&lt;/span&gt;venv&lt;span class=&#34;se&#34;&gt;\S&lt;/span&gt;cripts&lt;span class=&#34;se&#34;&gt;\p&lt;/span&gt;ython.exe -m pip install google-genai pillow
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;如何取得-gemini_api_key&#34;&gt;如何取得 GEMINI_API_KEY
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;GEMINI_API_KEY&lt;/code&gt; 就是呼叫 Gemini API 時使用的金鑰。根據 Google 官方 quickstart，如果你還沒有 key，可以直接在 Google AI Studio 建立。&lt;/p&gt;
&lt;p&gt;取得步驟如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;打開 Google AI Studio。&lt;/li&gt;
&lt;li&gt;登入你的 Google 帳號。&lt;/li&gt;
&lt;li&gt;找到 &lt;code&gt;Get API key&lt;/code&gt; 或 &lt;code&gt;API keys&lt;/code&gt; 頁面。&lt;/li&gt;
&lt;li&gt;建立一個新的 API key。&lt;/li&gt;
&lt;li&gt;複製產生出來的 key。&lt;/li&gt;
&lt;li&gt;把它設定到本地環境變數中，供腳本讀取。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果頁面中還沒有可用專案，通常需要先完成專案初始化，之後再回到 API Key 頁面建立金鑰。&lt;/p&gt;
&lt;p&gt;拿到 key 之後，再設定環境變數：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$env&lt;/span&gt;:GEMINI_API_KEY&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;your_api_key&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果你用的是 &lt;code&gt;cmd&lt;/code&gt;，可以寫成：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;GEMINI_API_KEY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;your_api_key
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果你同時設定了 &lt;code&gt;GEMINI_API_KEY&lt;/code&gt; 和 &lt;code&gt;GOOGLE_API_KEY&lt;/code&gt;，實際執行時通常會優先讀取 &lt;code&gt;GOOGLE_API_KEY&lt;/code&gt;，所以建議只保留一個，避免混淆。&lt;/p&gt;
&lt;h2 id=&#34;目錄結構範例&#34;&gt;目錄結構範例
&lt;/h2&gt;&lt;p&gt;腳本接收兩個參數：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;input_dir&lt;/code&gt;：輸入圖片目錄&lt;/li&gt;
&lt;li&gt;&lt;code&gt;output_dir&lt;/code&gt;：輸出圖片目錄&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;images/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  product1.jpg
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  product2.png
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;output/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;如何執行&#34;&gt;如何執行
&lt;/h2&gt;&lt;p&gt;假設腳本檔名是 &lt;code&gt;cutout.py&lt;/code&gt;，執行方式如下：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.&lt;span class=&#34;se&#34;&gt;\.&lt;/span&gt;venv&lt;span class=&#34;se&#34;&gt;\S&lt;/span&gt;cripts&lt;span class=&#34;se&#34;&gt;\p&lt;/span&gt;ython.exe .&lt;span class=&#34;se&#34;&gt;\c&lt;/span&gt;utout.py .&lt;span class=&#34;se&#34;&gt;\i&lt;/span&gt;mages .&lt;span class=&#34;se&#34;&gt;\o&lt;/span&gt;utput
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果你想換模型，也可以明確傳參：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.&lt;span class=&#34;se&#34;&gt;\.&lt;/span&gt;venv&lt;span class=&#34;se&#34;&gt;\S&lt;/span&gt;cripts&lt;span class=&#34;se&#34;&gt;\p&lt;/span&gt;ython.exe .&lt;span class=&#34;se&#34;&gt;\c&lt;/span&gt;utout.py .&lt;span class=&#34;se&#34;&gt;\i&lt;/span&gt;mages .&lt;span class=&#34;se&#34;&gt;\o&lt;/span&gt;utput --model gemini-2.5-flash-image
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;腳本會遍歷輸入目錄中的這些格式檔案：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.jpg&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.jpeg&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.png&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.webp&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;處理完成後，會在輸出目錄中生成同名的透明底 &lt;code&gt;PNG&lt;/code&gt; 檔案。&lt;/p&gt;
&lt;h2 id=&#34;核心呼叫流程&#34;&gt;核心呼叫流程
&lt;/h2&gt;&lt;p&gt;真正呼叫 Google Nano Banana 的關鍵程式碼在這裡：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;response&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;models&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;generate_content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;contents&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PROMPT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;這裡傳入了兩個內容：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一段文字提示詞 &lt;code&gt;PROMPT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;一張 &lt;code&gt;PIL.Image&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;提示詞內容是讓模型把整張商品圖背景移除，只保留主體，並強調幾件事：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;保留完整商品&lt;/li&gt;
&lt;li&gt;保留細線和線纜細節&lt;/li&gt;
&lt;li&gt;清理內部空洞和環形區域&lt;/li&gt;
&lt;li&gt;不要新增物體&lt;/li&gt;
&lt;li&gt;不要添加陰影&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這類提示詞對去背品質影響很大，尤其是耳機線、透明邊緣、空洞區域這類細節。&lt;/p&gt;
&lt;h2 id=&#34;為什麼還要做一次本地後處理&#34;&gt;為什麼還要做一次本地後處理
&lt;/h2&gt;&lt;p&gt;模型回傳結果後，腳本沒有直接儲存，而是又執行了 &lt;code&gt;make_transparent_from_borders(image)&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;這一步的思路是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;從圖片四周邊界開始找淺色背景像素&lt;/li&gt;
&lt;li&gt;用廣度優先搜尋把連通的淺色區域全部標記出來&lt;/li&gt;
&lt;li&gt;最後把這些區域統一改成透明&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這樣做的好處是可以進一步清掉一些殘留白邊、淺灰背景和不夠乾淨的邊緣區域。&lt;/p&gt;
&lt;p&gt;判斷「是不是背景」的條件在這裡：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;is_light_background_pixel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;brightness&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;spread&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;max&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;min&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;brightness&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;170&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;spread&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;35&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;簡單理解就是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;顏色整體夠亮&lt;/li&gt;
&lt;li&gt;RGB 三通道差異不能太大&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這比較適合處理白底、淺灰底、接近純色的商品圖背景。&lt;/p&gt;
&lt;h2 id=&#34;完整原始碼&#34;&gt;完整原始碼
&lt;/h2&gt;&lt;p&gt;下面保留目前這份完整原始碼，方便你直接重用或二次修改：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;  1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 45
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 46
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 47
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 48
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 49
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 50
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 51
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 52
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 53
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 54
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 55
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 56
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 57
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 58
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 59
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 60
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 61
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 62
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 63
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 64
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 65
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 66
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 67
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 68
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 69
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 70
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 71
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 72
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 73
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 74
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 75
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 76
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 77
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 78
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 79
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 80
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 81
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 82
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 83
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 84
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 85
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 86
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 87
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 88
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 89
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 90
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 91
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 92
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 93
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 94
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 95
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 96
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 97
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 98
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 99
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;100
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;101
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;102
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;103
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;104
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;105
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;106
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;107
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;108
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;109
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;110
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;111
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;112
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;113
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;114
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;115
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;116
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;117
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;118
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;119
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;120
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;121
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;122
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;123
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;124
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;125
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;126
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;127
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;128
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;129
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;130
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;131
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;132
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;133
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;134
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;135
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;136
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;137
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;138
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;139
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;140
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;141
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;142
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;143
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;144
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;145
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;146
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;147
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;148
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;149
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;150
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;__future__&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;annotations&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;argparse&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pathlib&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;collections&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deque&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;PIL&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;google&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;genai&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;ImportError&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;exc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# pragma: no cover&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;SystemExit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;Missing dependency: google-genai. Install it with &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;sa&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#39;.\.venv\Scripts\python.exe -m pip install google-genai&amp;#39;.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;exc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;PROMPT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;Remove the entire background from this product photo and return only the product &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;on a fully transparent background as a PNG. Keep the full product intact, preserve &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;thin cable details, clean the inner loops and holes, and do not add any new objects &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;or shadows.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;is_light_background_pixel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;brightness&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;spread&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;max&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;min&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;brightness&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;170&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;spread&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;35&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;to_pil_image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;image_obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;isinstance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;image_obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;image_obj&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;pil_image&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;getattr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;image_obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;_pil_image&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;isinstance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pil_image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pil_image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;as_pil&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;getattr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;image_obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;pil_image&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;isinstance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;as_pil&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;as_pil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;TypeError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Unsupported image object type: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;image_obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;!r}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;make_transparent_from_borders&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;rgba&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;convert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;RGBA&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;height&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rgba&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;pixels&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rgba&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;load&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;visited&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;tuple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;queue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deque&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;tuple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deque&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;push_if_bg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;visited&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;_&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pixels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;is_light_background_pixel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;visited&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;queue&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;push_if_bg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;push_if_bg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;height&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;height&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;push_if_bg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;push_if_bg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;width&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;queue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;queue&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;popleft&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ny&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;width&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ny&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;height&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;push_if_bg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ny&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;visited&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;pixels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rgba&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;save_first_image_part&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;getattr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;parts&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parts&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;getattr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;candidates&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;parts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;candidates&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;parts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;RuntimeError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Model returned no content parts.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;part&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;inline_data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;getattr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;part&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;inline_data&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;inline_data&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;isinstance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;part&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;inline_data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;part&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;inline_data&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;inline_data&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;hasattr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;part&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;as_image&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;image&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;to_pil_image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;part&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;as_image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;parent&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mkdir&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;parents&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;exist_ok&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;make_transparent_from_borders&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;save&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;getattr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;inline_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;getattr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;inline_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;mime_type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;parent&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mkdir&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;parents&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;exist_ok&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;wb&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;handle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;handle&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;write&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;img&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;processed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;make_transparent_from_borders&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;img&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;processed&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;save&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;with_suffix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;.png&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;suffix&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lower&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.png&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;unlink&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;missing_ok&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;RuntimeError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Model returned text only and no edited image.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;process_image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;src&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;src&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;convert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;RGBA&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;response&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;models&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;generate_content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;contents&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PROMPT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;save_first_image_part&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parser&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;argparse&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;description&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Use Nano Banana / Gemini image editing to cut out product images.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parser&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_argument&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;input_dir&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parser&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_argument&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;output_dir&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parser&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_argument&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;--model&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;gemini-2.5-flash-image&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parser&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;parse_args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;api_key&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;environ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;GEMINI_API_KEY&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;api_key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;SystemExit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Missing GEMINI_API_KEY environment variable.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;genai&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Client&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;api_key&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;api_key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;exts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;.jpg&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.jpeg&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.png&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.webp&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;src&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;sorted&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;input_dir&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;iterdir&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;src&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;is_file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;src&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;suffix&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lower&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;exts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;output_dir&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;src&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stem&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.png&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;process_image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;src&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;適合繼續優化的地方&#34;&gt;適合繼續優化的地方
&lt;/h2&gt;&lt;p&gt;如果你準備把這段腳本繼續用於批次生產，後面還可以補這些能力：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;增加失敗重試，避免單張圖片報錯後整批中斷&lt;/li&gt;
&lt;li&gt;記錄日誌，方便定位是哪張圖處理失敗&lt;/li&gt;
&lt;li&gt;把不同背景閾值做成可配置化&lt;/li&gt;
&lt;li&gt;支援遞迴掃描子目錄&lt;/li&gt;
&lt;li&gt;增加原圖與結果圖的對比預覽&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;小結&#34;&gt;小結
&lt;/h2&gt;&lt;p&gt;如果你只想快速理解「怎麼呼叫 Google Nano Banana 做去背」，其實核心就三步：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;安裝 &lt;code&gt;google-genai&lt;/code&gt; 和 &lt;code&gt;Pillow&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;設定 &lt;code&gt;GEMINI_API_KEY&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;用 &lt;code&gt;client.models.generate_content()&lt;/code&gt; 傳入提示詞和圖片&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;而這份程式碼的價值在於，它不只是呼叫模型，還補上了透明背景後處理，更適合直接拿去做商品圖去背任務。&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
