<?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/tags/gemini/</link>
        <description>Recent content in Gemini on KnightLi的博客</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-cn</language>
        <lastBuildDate>Thu, 21 May 2026 08:33:14 +0800</lastBuildDate><atom:link href="https://knightli.com/tags/gemini/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Google I/O 之后，GPT 和 Gemini 订阅怎么选？普通用户与开发者对比</title>
        <link>https://knightli.com/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/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/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/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/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/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/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/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/2026/05/17/google-gemini-spark-ai-agent-leak/</link>
        <pubDate>Sun, 17 May 2026 11:58:08 +0800</pubDate>
        
        <guid>https://knightli.com/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，谷歌想在编程和 Agent 上追回节奏</title>
        <link>https://knightli.com/2026/05/17/gemini-35-pro-cappuccino-spark-leak/</link>
        <pubDate>Sun, 17 May 2026 11:47:27 +0800</pubDate>
        
        <guid>https://knightli.com/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/2026/05/17/google-gemini-intelligence-android/</link>
        <pubDate>Sun, 17 May 2026 09:13:32 +0800</pubDate>
        
        <guid>https://knightli.com/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 提前曝光：谷歌想用 Spark Agent 抢回 AI 编程入口</title>
        <link>https://knightli.com/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/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 工具接入。它们指向同一个方向：谷歌不只是想更新一个聊天模型，而是想把模型、工具、Agent 和 Google 生态入口重新绑在一起。&lt;/p&gt;
&lt;p&gt;不过，在正式发布前，这些信息都应该按“爆料”看待。真正值得关注的不是某一张截图或某一个跑分，而是谷歌接下来可能要补的几块短板。&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 的说法。如果命名属实，说明谷歌想在新一轮发布里讲一个更大的版本故事，而不是只做常规小更新。&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 系列一直强调多模态，谷歌也有足够强的分发渠道。真正的问题是，它能不能在开发者工具和 Agent 工作流上赶上 OpenAI、Anthropic 的节奏。&lt;/p&gt;
&lt;h2 id=&#34;编程能力是谷歌最需要补的课&#34;&gt;编程能力是谷歌最需要补的课
&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 的协同。相比之下，谷歌虽然有 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 真正的看点，不只是“能不能帮你干活”，而是谷歌能否把权限、审计、确认机制和用户控制做得足够清楚。&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;如果这部分最终落地，说明谷歌也在把模型从“问答系统”推向“工具操作系统”。模型不再只是生成文本，而是要能调用外部工具、访问业务系统、读写文件、执行命令，并在多个步骤之间保持任务状态。&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;多模态仍然是谷歌的优势牌&#34;&gt;多模态仍然是谷歌的优势牌
&lt;/h2&gt;&lt;p&gt;谷歌最有机会打出差异化的地方，仍然是多模态。&lt;/p&gt;
&lt;p&gt;从曝光的 SVG、交互式页面、动画和视觉生成案例看，Gemini 可能继续强化“从提示词生成可交互内容”的能力。相比单纯写一段代码，这更接近产品原型生成：用户描述一个想法，模型直接给出可操作、可调节、可预览的界面。&lt;/p&gt;
&lt;p&gt;这条路线很适合谷歌。它既能承接 Gemini 的多模态能力，也能和 Android、Chrome、Workspace、搜索、广告、云服务等入口结合。&lt;/p&gt;
&lt;p&gt;如果谷歌想避免只在“谁的代码模型更强”上硬拼，它很可能会把重点放到更完整的多模态 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;谷歌的优势则是生态入口。Gmail、Docs、Chrome、Android、搜索、YouTube、地图和云服务构成了一个巨大的个人与企业数据网络。只要 Agent 能安全接入这些入口，谷歌就有机会从“模型追赶者”变成“工作流入口控制者”。&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;谷歌是否给出清晰价格、额度和企业权限管理，而不是只展示演示效果。&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 的爆料说明，谷歌正在加速补齐 AI 编程和 Agent 入口。模型能力提升是一部分，Gemini Spark 这类全天候 Agent 可能才是更大的战略动作。&lt;/p&gt;
&lt;p&gt;但越是能帮用户“自动干活”的系统，越需要严格的权限边界和可验证流程。对谷歌来说，真正的挑战不只是追上 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/2026/05/13/ccx-ai-api-proxy-gateway/</link>
        <pubDate>Wed, 13 May 2026 23:20:40 +0800</pubDate>
        
        <guid>https://knightli.com/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/2026/05/07/chatgpt-claude-code-gemini-memory-comparison/</link>
        <pubDate>Thu, 07 May 2026 14:47:17 +0800</pubDate>
        
        <guid>https://knightli.com/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/2026/05/04/gemini-embedding-2-multimodal-rag/</link>
        <pubDate>Mon, 04 May 2026 06:01:10 +0800</pubDate>
        
        <guid>https://knightli.com/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;这种前缀适合非对称检索：用户查询往往很短，文档内容往往很长。把 query 和 document 分别按任务格式整理，可以改善短查询到长文档之间的匹配。&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 也适合聚类、分类和异常检测。和前面的问答检索不同，这些属于对称任务，query 和 document 可以使用同一种任务前缀：&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/2026/05/01/gemini-cars-with-google-built-in/</link>
        <pubDate>Fri, 01 May 2026 06:09:57 +0800</pubDate>
        
        <guid>https://knightli.com/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/2026/04/25/chatgpt-claude-gemini-task-selection/</link>
        <pubDate>Sat, 25 Apr 2026 10:51:19 +0800</pubDate>
        
        <guid>https://knightli.com/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/2026/04/18/google-app-desktop-ai-search-windows/</link>
        <pubDate>Sat, 18 Apr 2026 11:08:00 +0800</pubDate>
        
        <guid>https://knightli.com/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/2026/04/09/product-cutout-normalize-agent-skill-guide/</link>
        <pubDate>Thu, 09 Apr 2026 21:43:50 +0800</pubDate>
        
        <guid>https://knightli.com/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/2026/04/09/google-nano-banana-cutout-guide/</link>
        <pubDate>Thu, 09 Apr 2026 20:10:48 +0800</pubDate>
        
        <guid>https://knightli.com/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>
