Nano Banana 2图像生成实战:用JSON提示词实现精准可控出图

Nano Banana 2图像生成实战:用JSON提示词实现精准可控出图 Nano Banana 2 在中文社区通常指谷歌新一代图像生成模型对应 Gemini 系列中的图像生成模型迭代很多带中文字幕的讲解视频会直接用一段 JSON 提示词来控制画面细节。JSON 在这里不只是配置文件的格式它本质上是一份“可编程的视觉需求说明书”。把语言描述拆成字段再交给模型执行出图稳定性和可复用性都会明显提高。这篇内容会从模型概念讲起给出完整的环境准备、JSON 提示词模板、Python 调用示例、存储传输方案、常见排错和最佳实践适合想在图片生成工作流里引入结构化提示词的开发者参考。1. 先理解 Nano Banana 2 与 JSON 提示词之间的关系很多人第一次看到“Nano Banana 2”这个名称时会误以为它是一个独立的软件工具。实际上这是社区对谷歌图像生成模型的昵称官方 API 中的模型名通常是gemini-2.5-flash-image之类。这个模型的核心能力是根据一段文本描述生成或编辑图像并且能比较准确地理解物体关系、画面构图和风格化指令。为什么要专门用 JSON 提示词因为自然语言提示词虽然方便但存在几个实际问题字段边界模糊模型可能把“主体”和“背景”混在一起同样一句话在不同图片上执行结果差异很大一旦需要批量生成后续无法做参数对比和版本管理。JSON 提示词把需求结构化相当于给模型一张明确的“需求表单”。1.1 Nano Banana 类图像模型的底层能力范围图像生成模型并不是一个简单的“文生图”工具。以 Gemini 图像生成模型为例它支持图像编辑、局部重绘、多轮对话式改图也能理解用户上传的参考图。也就是说提示词不仅能描述“画什么”还能描述“在上一张图的基础上改哪里、改成什么样”。这种能力给提示词设计带来了新的要求。如果提示词只是一句“画一只戴眼镜的香蕉”模型虽然能出图但细节完全不可控。换成 JSON 提示词后可以把主体、动作、场景、镜头、风格、色彩、文本内容甚至负面要求拆开写模型按字段逐项落实。1.2 为什么结构化提示词比一句自然语言更可控自然语言提示词本质上是一段连续文本。模型要从整段文本里做意图解析而意图解析常常有歧义。比如“一个穿着校服的男孩在教室里看着电脑屏幕上有 JSON 代码画面偏蓝色调”这句话模型可能侧重人物忽略屏幕内容也可能把“偏蓝色调”理解成整体环境光而不是画面后期风格。JSON 提示词将信息分割成 key-value 结构后模型更容易把每个字段当作一个独立约束。下面用一个对比表说明差异对比维度自然语言提示词JSON 提示词信息边界语义混在一起模型自行拆分字段明确每个属性独立表达可复用性往往只能整个短语复制可修改单个字段复用参数调试难以控制变量改一个字段就能观察差异批量生成不方便程序化处理天然适合 JSON 序列化与 API 调用可校验性无法做语法校验可用 JSON Schema 校验当然JSON 提示词不是银弹。模型最终理解的是文本语义而不是真的在读取数据结构。但实践表明结构化表达能显著减少歧义尤其适合生成细节较多的图片场景。1.3 读这篇文章需要什么基础这篇文章默认读者具备以下基础会使用 Python能安装 pip 包并运行脚本。了解 JSON 的基本语法比如对象、数组、字符串和嵌套结构。有谷歌 AI Studio 或 Gemini API 的访问权限并准备了一个 API Key。如果完全没接触过 API建议先跑通官方文档里的最小示例再回来学习 JSON 提示词的写法。下面从环境准备开始。2. 准备运行环境API Key、SDK 与最小请求图像生成 API 的调试链路比普通文本接口长因为涉及模型名、提示词、图像输出格式和二进制内容解析。环境没准备好时后面所有 JSON 提示词都无从验证。2.1 需要准备的资源清单先明确需要的东西资源说明是否必需谷歌账号用于访问 AI Studio 或 Google Cloud Console必需API Key在 AI Studio 中创建按额度计费必需Python 3.9 及以上运行示例代码必需google-genai SDK官方 Python SDK封装图像生成接口必需网络连接调用海外 API 的正常网络环境必需本地图片查看工具查看生成的 PNG 文件推荐注意API Key 属于敏感凭据不要把它写死在代码里也不要提交到 Git 仓库。建议使用环境变量或本地密钥文件管理。2.2 安装 google-genai SDKgoogle-genai 是官方的 Python SDK。安装命令如下pip install google-genai如果是在已有虚拟环境中安装建议先创建虚拟环境避免污染全局 Pythonpython -m venv .venv source .venv/bin/activate # Windows 下执行 .venv\Scripts\activate pip install --upgrade pip pip install google-genai pillow这里还安装了 Pillow用于后续把返回的二进制图像数据保存成 PNG 文件。安装完成后可以用下面的命令确认版本号pip show google-genai如果网络环境有限制可以先配置 pip 镜像源再继续安装。2.3 用环境变量配置 API Key在项目目录下创建.env文件不是必须的但推荐使用环境变量。这里在终端中直接导出export GEMINI_API_KEY你的 API Key在 Windows PowerShell 中$env:GEMINI_API_KEY 你的 API KeyPython 代码里通过os.environ读取import os api_key os.environ.get(GEMINI_API_KEY) if not api_key: raise RuntimeError(请先设置 GEMINI_API_KEY 环境变量)这样做的核心目的是防止凭据泄露同时也方便在不同环境中切换 Key。2.4 发送第一个图像生成请求完成环境准备后先发送一个最简单的文本提示词请求验证链路是否通畅import os from google import genai from google.genai import types client genai.Client(api_keyos.environ.get(GEMINI_API_KEY)) response client.models.generate_images( modelgemini-2.5-flash-image, prompta yellow banana wearing glasses, cartoon style, configtypes.GenerateImagesConfig( number_of_images1, aspect_ratio1:1, output_mime_typeimage/png, ), ) image_bytes response.generated_images[0].image.image_bytes with open(first_test.png, wb) as f: f.write(image_bytes) print(image saved to first_test.png)检查点脚本没有报认证错误说明 API Key 有效。本地生成了first_test.png说明图像输出链路正常。如果能正常出图再开始替换成 JSON 提示词。这里要注意实际项目里model名称要以官方文档当时公布的模型为准。社区可能称它为 Nano Banana 2但代码中应使用可运行的模型标识符。3. 构造一份可复用的 JSON 提示词模板基础请求跑通后核心工作就变成了“设计提示词结构”。JSON 提示词的设计质量直接影响出图效果。3.1 JSON 提示词里的核心字段如何划分图像生成类提示词通常可以分为几组任务描述告诉模型要生成新图还是编辑已有图。主体信息谁出现在画面里长什么样子。场景与背景发生在什么地方前后景如何安排。风格与质感写实、卡通、3D、水彩、赛博朋克等。构图与镜头景别、角度、主体位置、镜头焦距。色彩与光影整体色调、光源方向、氛围。画面文字需要出现哪些文本必须逐字写清。负面描述不想要什么元素。把这些信息组织成 JSON 对象时字段名最好清晰一致。下面是一个可用的模板{ task: generate, metadata: { scene_id: scene_001, version: 1.0 }, subject: { name: a small banana character, attributes: [wearing round glasses, holding a tiny laptop], expression: focused and curious }, scene: { location: on a wooden desk beside a coffee cup, background: blurred bookshelf and warm window light, props: [laptop screen showing JSON code, a small notebook] }, style: { base: 3D render, lighting: soft studio lighting, color_palette: warm yellow and brown tones }, composition: { camera_angle: slightly high angle, framing: medium close-up, subject centered, depth_of_field: shallow }, text_on_image: { content: JSON, position: on laptop screen, language: English }, negative_prompt: blurry, distorted hands, watermark, low resolution }这份模板不是固定标准而是一个思考框架。实际项目中完全可以删减或增加字段但要注意模型未必认识所有自定义字段。因此建议至少保留subject、scene、style这三个核心项其余字段作为补充描述。3.2 为什么字段不能随意使用大写字母JSON 本身区分大小写字段名和枚举值的大小写不同语义就可能不同。比如style: {base: 3D render}里的3D写成3d模型通常能理解但换成Style就可能导致解析歧义。更严重的是有些语言或框架在对象属性名首字母大写时序列化行为会发生变化。这在实际集成中很常见。比如 Java 后端定义了一个ImagePrompt类字段名是Scene使用某些 JSON 库序列化后输出可能是scene也可能是Scene取决于库的命名策略。如果下游模型只识别小写字段而接口传过去的是大写开头就可能解析失败。统一约定JSON 提示词字段全部使用小写驼峰或者小写下划线比如camera_angle、color_palette。这样在 Python、Java、Go 之间传递时不容易出现大小写不一致问题。3.3 用 JSON 数组管理多个画面版本有时一次需要生成多个风格变体。这时可以把提示词组织成 JSON 数组每个元素代表一个版本[ { version: cartoon, style: {base: 2D cartoon, color_palette: bright primary colors} }, { version: realistic, style: {base: photorealistic, color_palette: natural colors} }, { version: cyberpunk, style: {base: neon cyberpunk, color_palette: pink and blue} } ]在调用时把整个数组序列化成字符串传给prompt字段并在提示词里加上“请根据每个版本生成一张图”。这种写法的好处是后续可以在代码里遍历数组把每次请求的 JSON 原样记录下来方便对比不同风格的效果。3.4 提示词模板与模型返回 JSON 的配合方式图像生成接口返回的数据中除了图片二进制内容还包含元信息字段。后续处理时需要把这些信息一并保存。返回结构类似{ generated_images: [ { image: { image_bytes: ..., mime_type: image/png }, metadata: { model_version: gemini-2.5-flash-image, token_count: 128 } } ] }具体字段名以 SDK 版本为准。实际开发中比较重要的做法是把请求时使用的提示词 JSON 和返回的响应 JSON 一起持久化这样将来排查“为什么这张图效果不对”时能完整还原生成现场。4. 用 Python 调用生成接口并保存 JSON 结果模板确定后就可以写一段完整脚本把提示词 JSON 作为输入生成图像并把运行结果保存到本地文件和 SQLite 数据库。4.1 从 JSON 文件读取提示词先把提示词模板保存为prompt.json这样提示词和代码分离后续修改提示词不需要改代码。读取方式import json with open(prompt.json, r, encodingutf-8) as f: prompt_obj json.load(f)注意这里使用encodingutf-8是为了防止中文注释或中文字段出现乱码。如果提示词中包含中文文本序列化时也需要设置为ensure_asciiFalse否则中文会被转成\uXXXX既不美观也不利于日志排查。4.2 发送请求并保存返回图片完整调用代码如下import json import logging import os from datetime import datetime from google import genai from google.genai import types logging.basicConfig(levellogging.INFO, format%(asctime)s %(levelname)s %(message)s) logger logging.getLogger(__name__) api_key os.environ.get(GEMINI_API_KEY) client genai.Client(api_keyapi_key) def load_prompt(path: str) - dict: with open(path, r, encodingutf-8) as f: return json.load(f) def generate_image(prompt_obj: dict, output_dir: str output) - dict: os.makedirs(output_dir, exist_okTrue) prompt_str json.dumps(prompt_obj, ensure_asciiFalse, indent2) logger.info(start generating with prompt: %s, prompt_str) response client.models.generate_images( modelgemini-2.5-flash-image, promptprompt_str, configtypes.GenerateImagesConfig( number_of_images1, aspect_ratio16:9, output_mime_typeimage/png, ), ) image_bytes response.generated_images[0].image.image_bytes timestamp datetime.now().strftime(%Y%m%d_%H%M%S) image_path os.path.join(output_dir, foutput_{timestamp}.png) with open(image_path, wb) as f: f.write(image_bytes) result { status: success, image_path: image_path, prompt_used: prompt_obj, created_at: timestamp, } with open(os.path.join(output_dir, fresult_{timestamp}.json), w, encodingutf-8) as f: json.dump(result, f, ensure_asciiFalse, indent2) logger.info(image saved to %s, image_path) return result if __name__ __main__: prompt load_prompt(prompt.json) result generate_image(prompt) print(json.dumps(result, ensure_asciiFalse, indent2))关键点json.dumps(..., ensure_asciiFalse)会保留中文方便在日志和结果文件中阅读。每次生成都记录prompt_used保证可回溯。图片和 JSON 结果使用同一个时间戳命名便于关联。number_of_images1控制单次返回图片数量数量越大消耗额度越多。4.3 把 JSON 结果写入 SQLite当生成任务变多后文件式管理会混乱需要把任务信息写入 SQLite。先建表CREATE TABLE IF NOT EXISTS image_task ( id INTEGER PRIMARY KEY AUTOINCREMENT, task_name TEXT NOT NULL, prompt_json TEXT NOT NULL, result_path TEXT, status TEXT DEFAULT pending, error_message TEXT, created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP );Python 写入逻辑import sqlite3 def insert_task(task_name: str, prompt_obj: dict): conn sqlite3.connect(image_task.db) cursor conn.cursor() cursor.execute( INSERT INTO image_task (task_name, prompt_json, status) VALUES (?, ?, ?) , (task_name, json.dumps(prompt_obj, ensure_asciiFalse), pending), ) conn.commit() task_id cursor.lastrowid conn.close() return task_id def update_task_result(task_id: int, image_path: str): conn sqlite3.connect(image_task.db) cursor conn.cursor() cursor.execute( UPDATE image_task SET result_path ?, status success, updated_at CURRENT_TIMESTAMP WHERE id ? , (image_path, task_id), ) conn.commit() conn.close()这里的prompt_json字段直接存储文本型 JSON查询时可用json_extract做简单筛选。比如查询所有包含task: generate的记录SELECT id, task_name FROM image_task WHERE json_extract(prompt_json, $.task) generate;SQLite 的 JSON 函数在较新版本中默认可用非常适合做提示词任务的中转存储。4.4 Java 等其他语言遇到的大小写序列化问题很多团队的后端不是 Python而是 Java。Java 中如果 Bean 属性名是大写字母开头序列化成 JSON 时可能出现字段名变化。比如SceneName属性可能被序列化成scenename或SceneName取决于 Jackson、Gson 的配置。推荐的规避方式与前后端、模型侧约定统一的字段命名规范。Java Bean 属性使用小写驼峰例如sceneName、colorPalette。如果必须保留特殊字段名可以使用JsonProperty(scene_name)指定序列化名称。不要依赖框架默认规则关键字段全部显式指定。如果原始项目中已经存在大写字段问题可以在序列化后统一做一次字段名映射转换但更深层的做法是重构 Bean 命名。5. 从 Demo 到工程化JSON 提示词的存储、传输与版本管理单机脚本能出图后下一步要考虑的是提示词从哪里来、如何传输、如何落库、如何做多版本管理。5.1 不要把提示词硬编码在业务代码里常见错误是直接把 JSON 字符串写在 Python 文件或 Java 类里。这种写法的坏处提示词更新需要重新发版。不同业务场景无法复用同一套代码。日志和参数无法分离。推荐做法是把提示词文件放在独立目录例如config/ prompts/ product_shot.json character_design.json scene_edit.json代码中通过配置中心或本地配置目录加载。若团队已经使用配置中心可以把提示词 JSON 作为配置项下发给服务运行时动态读取。5.2 用 SQLite 管理任务状态时的字段设计工程化任务表不应该只存提示词和结果路径还应包含任务状态机常见状态有pending、processing、success、failed。状态更新时错误信息要单独保存便于事后分析。一个更完整的表结构CREATE TABLE image_task ( id INTEGER PRIMARY KEY AUTOINCREMENT, scene_id TEXT NOT NULL, prompt_version TEXT, prompt_json TEXT NOT NULL, model_name TEXT, image_path TEXT, status TEXT NOT NULL DEFAULT pending, error_code TEXT, error_message TEXT, created_at TEXT DEFAULT CURRENT_TIMESTAMP, started_at TEXT, finished_at TEXT ); CREATE INDEX idx_image_task_status ON image_task(status); CREATE INDEX idx_image_task_scene_id ON image_task(scene_id);增加索引和常用时间字段后续统计每日生成量、失败率时会很方便。5.3 通过 RabbitMQ 传输 JSON 提示词的实践当图片生成不是同步接口而是异步任务时可以使用消息队列分发任务。生产端把 JSON 提示词作为消息体发送消费端接收后调用模型并更新结果。生产端示例import json import pika connection pika.BlockingConnection(pika.ConnectionParameters(localhost)) channel connection.channel() queue_name image_task_queue channel.queue_declare(queuequeue_name, durableTrue) task { task_id: TASK-0001, scene_id: scene_001, prompt: prompt_obj, model: gemini-2.5-flash-image } channel.basic_publish( exchange, routing_keyqueue_name, bodyjson.dumps(task, ensure_asciiFalse), propertiespika.BasicProperties( delivery_mode2, content_typeapplication/json ) ) print(task published) connection.close()消费端核心逻辑import json import pika def callback(ch, method, properties, body): task json.loads(body) print(freceive task: {task[task_id]}) # 调用图像生成接口保存图片更新数据库 ch.basic_ack(delivery_tagmethod.delivery_tag) connection pika.BlockingConnection(pika.ConnectionParameters(localhost)) channel connection.channel() channel.queue_declare(queueimage_task_queue, durableTrue) channel.basic_qos(prefetch_count1) channel.basic_consume(queueimage_task_queue, on_message_callbackcallback) print(waiting for tasks...) channel.start_consuming()这里使用basic_ack确认消息消费成功失败时不能确认以保证消息不丢失。生产环境还需要考虑死信队列和重试策略。5.4 与 DataX 等数据同步工具配合时的 JSON 字段映射DataX 是一个数据同步工具它本身使用 JSON 配置 job。如果需要把 SQLite 或 MySQL 中的提示词任务同步到其他存储可以在 DataX 的job配置里定义 reader 和 writer。例如从 MySQL 读取提示词任务写入 JSON 文件{ job: { content: [ { reader: { name: mysqlreader, parameter: { username: root, password: ****, column: [id, scene_id, prompt_json], splitPk: id, connection: [ { table: [image_task], jdbcUrl: [jdbc:mysql://localhost:3306/image_db] } ] } }, writer: { name: jsonfilewriter, parameter: { path: /data/output, fileName: image_task.json, writeMode: truncate } } } ], setting: { speed: { channel: 2 } } } }关键点DataX 本身只负责搬移数据不负责解析提示词内容。因此字段类型尽量保持为字符串不要在中途做 JSON 格式化避免数据变形。6. 常见报错与排查路径JSON 提示词接入图像生成接口后报错类型通常集中在 JSON 解析、字段格式、接口参数、内容安全、返回结果不匹配这几个方面。6.1 问题现象与处理方案速查表问题现象常见原因检查方式处理建议返回 400 invalid JSONJSON 语法错误逗号、引号缺失使用在线 JSON 校验或json.tool校验先python -m json.tool prompt.json格式化校验返回 401 API key invalidAPI Key 错误或环境变量未生效打印环境变量是否为正常值重新导出环境变量确认没有多余空格字段名解析失败字段使用了大写开头或特殊字符查看服务端返回的 error message统一小写驼峰命名避免大小写混用图片内容与提示词不一致字段描述互相冲突检查prompt_used中是否有多余内容删除冲突字段减少不相关细节中文提示词变成乱码序列化时ensure_asciiTrue检查调用日志中的 prompt 内容使用ensure_asciiFalse指定 UTF-8 编码返回图片被截断或空白生成失败或额度不足查看 HTTP 状态码和响应体控制图片数量检查账户额度请求超时参数过多或网络波动使用小图尺寸测试缩小提示词内容设置重试机制6.2 JSON 解析失败要从哪一层查起出现invalid JSON时先确认是哪一个 JSON 出问题本地prompt.json是否有语法错误。代码中json.dumps序列化后的字符串是否符合预期。传输到服务端前是否被日志系统截断或转义。服务端返回的错误信息里是否包含具体行号和字符位置。可以在 Python 中快速校验python -m json.tool prompt.json如果没有输出任何错误说明 JSON 语法没问题问题可能出在后续字段内容或接口兼容性上。6.3 生成结果与提示词不一致的排查思路如果 JSON 完全合法但图片和预期差距很大优先怀疑语义冲突。比如subject里写“一只戴眼镜的香蕉”scene里又写“房间里有一个人”模型可能把人与香蕉同时放进画面。排查顺序只保留subject字段去掉其他字段看主体是否正确。单独加入scene字段看场景是否按预期变化。最后加style和composition逐步逼近目标画面。这个方法类似二分排查能快速定位是哪个字段干扰了结果。6.4 在 JMeter 或 LabVIEW 中调试 JSON 提示词的思路部分开发者在接口测试或自动化工具中处理 JSON。JMeter 里常用 JSON Extractor 提取响应字段。比如接口返回的任务编号task_id可以通过 JSON Path 表达式$.taskId提取传递给下一个请求。注意 JSON Path 表达式直接依赖字段名大小写接口返回taskId时提取taskId如果返回task_id则写$.task_id。LabVIEW 场景中先读取 JSON 文件用 LabVIEW 的 JSON 库解析成对应的键值对再拼接到 API 请求头或请求体中。这里的常见问题是LabVIEW 的字符串转义规则和 Python 不同拼接 JSON 时容易把双引号丢掉。建议在 LabVIEW 中直接使用字节流方式读取文件避免多次转义。7. 最佳实践搭建一套稳定的 JSON 提示词工作流有了代码和排错能力后更关键的是建立一套可持续使用的工作流。只有提示词、任务、结果三者形成闭环后续优化才有数据支撑。7.1 提示词组织方式的三种推荐模式组织模式适用场景优点缺点单 JSON 文件测试、一次性生成简单直接任务多了难管理JSON 文件加版本号需要回溯历史版本可对比不同版本效果需要额外维护版本索引数据库存储批量生产任务可查询可统计需要建表和写入逻辑建议从“JSON 文件加版本号”开始比如prompt_v1.0.json、prompt_v1.1.json。等任务规模上来再迁到数据库。7.2 用 JSON Schema 做前置校验为了防止错误提示词进入模型调用可以在发送前用 JSON Schema 做一次结构校验。示例{ $schema: http://json-schema.org/draft-07/schema#, type: object, required: [subject, scene, style], properties: { subject: { type: object, required: [name], properties: { name: {type: string}, attributes: {type: array, items: {type: string}} } }, scene: {type: object}, style: {type: object} }, additionalProperties: true }Python 中可以使用jsonschema库校验pip install jsonschemaimport json import jsonschema from jsonschema import Draft7Validator schema json.load(open(prompt_schema.json, encodingutf-8)) prompt json.load(open(prompt.json, encodingutf-8)) validator Draft7Validator(schema) errors sorted(validator.iter_errors(prompt), keylambda e: e.path) if errors: for err in errors: print(f字段 {list(err.path)}: {err.message}) else: print(prompt schema check passed)前置校验能拦截大部分字段缺失问题避免浪费 API 额度。7.3 生产环境发布前的检查清单生产环境接入 JSON 提示词图像生成服务时至少检查以下项[ ] API Key 是否通过环境变量或密钥服务注入而不是写死在代码里。[ ] 模型名称是否与当前账号权限匹配。[ ] 是否存在超时重试、指数退避机制。[ ] 是否记录完整的请求 JSON、响应 JSON 和失败原因。[ ] 是否把生成的图片保存到对象存储而不是只放在本地磁盘。[ ] 是否对用户输入的提示词做长度限制和敏感词校验。[ ] 数据库中的任务状态是否具备人工重跑能力。[ ] 是否设定每日调用额度和告警阈值。[ ] 是否保留原始提示词的版本记录方便对比效果。[ ] 是否存在队列积压监控消费进程挂掉后能否自动恢复。7.4 下一步可以扩展的方向JSON 提示词只是结构化生成的第一步。后续可以继续探索用程序批量生成一批提示词自动跑出多张候选图再人工筛选。把生成的图片和提示词关联起来构造属于自己团队的数据集用于后续模型微调或效果评估。在提示词中加入随机种子或风格权重字段实现半自动化的风格探索。将提示词模板交给配置平台管理业务人员不需要改代码就能调整画面效果。真正的价值不在于“写出一条完美的 JSON 提示词”而在于建立一套“改参数、跑任务、看结果、记数据”的循环。只要每次生成都能留下结构化记录图生效果的优化就不会是拍脑袋。建议从小场景开始先跑通一份 JSON 提示词模板再把存储、传输、状态管理和排查路径逐个补齐最终沉淀成团队内部可复用的图像生成工具链。