ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

结构化提示词实战:用JSON稳定输出风格统一的AI图像

结构化提示词实战:用JSON稳定输出风格统一的AI图像 最近在图像生成模型的使用者中很多人都在讨论同一件事为什么同样一段提示词别人能稳定产出风格统一的一组图自己却每次都要重新抽卡如果你也有这种感觉问题可能不是模型能力而是提示词的组织方式。在一条关于 Nano Banana 2 的中文字幕教程里作者反复强调一个观点与其把提示词写成长难句不如像写程序一样用 JSON 这种结构化的方式去组织它。这个思路很有代表性所以这篇文章想把这个方法论拆开讲透。先说清楚边界本文不会去纠结 Nano Banana 2 的跑分和模型参数也不会预测它的版本节奏。我更关心的是“结构化提示词”这件事因为它不绑定某个具体模型只要你以后还在用 AI 做图像生成这个技能就能复用。文章会从五个角度来看Nano Banana 2 适合什么场景、为什么 JSON 提示词更稳定、如何设计 JSON 提示词结构、如何把 JSON 渲染成自然语言以及如何在代码里把它落地成模板和批量工具。1. Nano Banana 2 是什么从“画图工具”到“对话式图像工作流”1.1 它解决的真正问题如果只把 Nano Banana 2 理解成一个“能画图的 AI”你会错过它最值得关注的交互方式变化。从相关教程内容和公开讨论来看它属于 Google Gemini 图像生成能力的一个迭代代号核心特点是多轮对话式图像生成与编辑。也就是说你不需要每次都输入完整提示词重新生成而是可以在同一个会话里说“把背景改成夜晚”“把门头的红色换成青色”“给主角加一副墨镜”模型就能在上一张图的基础上继续修改。这种变化对提示词工程的影响是深远的。以前的 Stable Diffusion 或 Midjourney 使用习惯是“一次性把画面要素写全”因为每次生成都是独立的细节遗漏就得重新出图。但到了对话式图像模型这里提示词不再是最终答案而是一个初始需求。后续修改靠自然语言交互完成所以提示词要承担的职责变了它更像一份项目需求文档而不是一次性的设计稿。1.2 适合谁用从使用场景来看Nano Banana 2 这类模型比较适合四类人需要快速做视觉方案的设计师用来生成风格参考图。做内容创作的个人开发者需要给文章、视频配置封面图。需要角色设定的游戏策划想快速验证角色氛围和服饰方向。对提示词工程感兴趣的技术人想在业务里接入图像生成能力。如果你只是偶尔画一张头像那么提示词用自然语言随手写写就够了不需要 JSON。但如果你要持续产出风格一致的图片或者想把提示词交给团队复用JSON 化的收益就非常明显。下一节就专门来讲为什么自然语言提示词在这种场景下会失灵。2. 为什么提示词要 JSON 化自然语言的模糊性困局2.1 自然语言提示词的问题“给我画一个赛博朋克风格的咖啡师机器人站在夜晚的咖啡馆门口灯光很好看画面要精致。”这段提示词有问题吗读起来很通顺但交给模型时会产生大量歧义“灯光很好看”到底是什么灯光霓虹灯、暖黄射灯、月光还是显示屏光“站在门口”是站在左边还是右边是全身还是半身“赛博朋克风格”具体参考什么电影感、插画感、还是废土赛博风“画面要精致”在提示词里几乎等于没有提供有效信息。并不是模型笨而是自然语言本身允许这种模糊存在。两个人读同一句“灯光很好看”脑子里浮现的画面可能完全不同。模型也一样它只是做了概率最高的联想。而在需要批量生成和团队协作时这种模糊会导致一个更实际的问题提示词无法被复用。你上周写的“精致画面”下周一换个人看理解就变了。2.2 JSON 带来什么改变JSON 的核心价值不是格式本身而是它强迫你把信息分层。键值对告诉你“什么是什么”数组告诉你“有哪些并列项”嵌套结构告诉你“哪些信息属于同一个对象”。这正好对应图像生成提示词里的三类问题一个画面包含多个维度需要一个结构来承载这些维度。每个维度的取值需要明确避免同义词和模糊表达。不同角色、风格、场景需要复用结构化的数据最适合做模板和变量替换。下面用一张表对比自然语言提示词和 JSON 提示词的差异对比维度自然语言提示词JSON 提示词信息层级线性靠语序表达树形通过嵌套表达字段语义依赖上下文推断键值对直接指定可解析性只有人能读懂程序可解析可校验可复用性整体复制粘贴改字段即可复用批量生成需要手工改整段文字变量替换脚本遍历学习门槛低略高需要先掌握 JSON 基础注意这里的“JSON 提示词”有两种理解方式。第一种是把 JSON 作为工具自身的结构化参数比如某些图像生成 API 的 payload 本身就是 JSON你直接把字段传进去第二种是模型只接受自然语言输入但你在本地维护一份 JSON 作为源文件再通过脚本把它渲染成一段自然语言提示词。本文后面主要讲第二种因为它在任何工具上都能用。3. JSON 提示词的核心结构设计先想字段再写值3.1 字段设计原则写 JSON 提示词的第一步不是打开编辑器而是先想清楚“这个画面可以被拆成哪些维度”。拆得越细越不容易遗漏关键信息。我建议至少包含下面这些字段字段作用示例值task任务类型generate / edit / expandsubject画面主体及其属性咖啡师机器人、材质、表情scene场景与环境咖啡馆、夜晚、下雨composition构图与镜头中近景、平视、35mmstyle美术风格赛博朋克插画、厚涂color_palette色彩倾向品红、青色、深蓝lighting光线类型与方向霓虹灯、侧后方轮廓光mood整体氛围热闹中带着疏离感aspect_ratio画幅比例3:4 / 16:9quality画质关键词8k、高细节、金属材质清晰negative_prompt不想要的内容手部畸变、水印、多余手指这个字段列表不是固定的你可以根据自己的项目增加字段比如 camera_focal_length、style_reference、character_sheet 等。关键是保持稳定一组提示词用同一套字段不要今天用 scene 明天又改成 background否则后面做模板和批量生成会很痛苦。3.2 从最简单的模板开始新手不建议一上来就写满全部字段先从一个最小可用模板开始{ task: generate, subject: { name: 咖啡师机器人, description: 站在咖啡馆门口调制咖啡, attributes: { material: 金属外壳, expression: 专注 } }, style: 赛博朋克插画, color_palette: [品红, 青色], aspect_ratio: 3:4 }这个 JSON 输出后你先看效果再逐步加入 scene、lighting、composition 等字段。每加一个字段就生成一次观察它到底有没有影响画面。这样做的好处是你能积累“字段到画面效果”的映射经验而不是把所有变量一次性堆上去最后出了问题根本不知道是哪个字段导致的。4. 一个完整的 JSON Prompt 实战示例赛博朋克咖啡师4.1 完整 JSON 示例下面是一个相对完整的 JSON 提示词它对应了“赛博朋克风咖啡师机器人”这个形象的完整画面设定。你可以把这份 JSON 保存为prompt.json然后配合下一节提供的渲染脚本使用。{ task: generate, subject: { name: 赛博朋克风咖啡师机器人, description: 站在街边咖啡馆门口正在调制一杯拉花咖啡, attributes: { material: 金属和半透明亚克力外壳, expression: 专注且友好, accessories: [黑色围裙, 发光胸牌, 机械手套] } }, scene: { location: 未来感街边咖啡馆, time: 夜晚, environment: 霓虹灯招牌、细雨、湿润路面 }, composition: { framing: 中近景, camera_angle: 平视微仰, lens: 35mm, depth_of_field: 浅景深背景虚化 }, style: { art_style: 赛博朋克插画, influences: [银翼杀手, 攻壳机动队], rendering: 厚涂边缘略带玻璃反射质感 }, color_palette: [品红, 青色, 深蓝], lighting: { type: 霓虹灯光, direction: 侧后方轮廓光, intensity: 强对比有轻微雾气 }, mood: 热闹中带着一丝疏离感, aspect_ratio: 3:4, quality: 8k高细节金属材质清晰, negative_prompt: 低清晰度手部畸变多余手指文字水印logo }4.2 字段解读这份 JSON 的关键信息集中在几个容易出问题的地方attributes是数组还是字典这里我把 accessories 写成数组因为它有多项并列material 和 expression 写成字典的键值因为它们是单值属性。这样区分有助于保持语义一致。scene.environment写的是“霓虹灯招牌、细雨、湿润路面”三个名词之间用顿号连接仍然是一个字符串。如果想更结构化也可以改成数组[霓虹灯招牌, 细雨, 湿润路面]。两种都可以但渲染脚本要能区分处理。style.influences写成了数组表示可以并列多个参考风格。如果你用单个字符串写“银翼杀手、攻壳机动队”模型也能读但将来做变量替换时会麻烦一些。这里要提醒一点JSON 提示词的目的是让信息清晰不是为了让 JSON 看起来很复杂。如果一个字段值用字符串表达比嵌套三层对象更清楚那就用字符串。字段结构是手段不是目的。5. 如何把 JSON 渲染成模型可读的自然语言提示5.1 为什么要做渲染这一步很多图像生成模型的对话框并不接受直接粘贴 JSON或者说即使接受模型对 JSON 的理解也会因为你写法的差异而变得不稳定。最稳妥的方案是你维护 JSON 源文件用脚本把它渲染成一段通顺的自然语言提示词再把这段文字发给模型。这样做还有一个额外好处团队协作时大家维护的是同一套 JSON 字段而不是各写各的提示词。只要渲染逻辑固定同一份 JSON 在不同时间、不同人手里渲染出的自然语言完全一致。5.2 简单渲染脚本下面是一个 Python 渲染脚本放在与prompt.json同级的目录下文件名为prompt_render.py# 文件路径prompt_render.py import json def safe_get(d, key, default): 安全获取字典字段 if isinstance(d, dict): return d.get(key, default) return default def render_subject(subject): if isinstance(subject, str): return subject text safe_get(subject, name) desc safe_get(subject, description) if desc: text f{desc} attrs safe_get(subject, attributes) if isinstance(attrs, dict) and attrs: attr_text .join(f{k}{v} for k, v in attrs.items()) text f特征{attr_text} return text def render_scene(scene): if isinstance(scene, str): return scene parts [] for key in [location, time, environment]: value safe_get(scene, key) if value: parts.append(value) return .join(parts) def render_style(style): if isinstance(style, str): return style parts [] if safe_get(style, art_style): parts.append(style[art_style]) if safe_get(style, influences): parts.append(参考风格 、.join(style[influences])) if safe_get(style, rendering): parts.append(表现手法 style[rendering]) return .join(parts) def render_composition(composition): if not isinstance(composition, dict): return str(composition) parts [] for key in [framing, camera_angle, lens, depth_of_field]: value safe_get(composition, key) if value: parts.append(value) return .join(parts) def json_prompt_to_text(data): lines [] lines.append(画面要求 safe_get(data, task, generate)) subject data.get(subject, {}) lines.append(主体 render_subject(subject)) scene data.get(scene, {}) scene_text render_scene(scene) if scene_text: lines.append(场景 scene_text) composition data.get(composition, {}) comp_text render_composition(composition) if comp_text: lines.append(构图 comp_text) style data.get(style, {}) style_text render_style(style) if style_text: lines.append(风格 style_text) palette data.get(color_palette, []) if palette: lines.append(色彩 、.join(palette)) lighting data.get(lighting, {}) if isinstance(lighting, dict) and lighting: parts [] for key in [type, direction, intensity]: if safe_get(lighting, key): parts.append(lighting[key]) lines.append(光线 .join(parts)) if safe_get(data, mood): lines.append(氛围 data[mood]) if safe_get(data, aspect_ratio): lines.append(画幅 data[aspect_ratio]) if safe_get(data, quality): lines.append(画质 data[quality]) negative safe_get(data, negative_prompt) if negative: lines.append(避免 negative) return \n.join(lines) if __name__ __main__: with open(prompt.json, r, encodingutf-8) as f: prompt_data json.load(f) print(json_prompt_to_text(prompt_data))5.3 运行与验证在命令行执行python prompt_render.py预期输出大致如下画面要求generate 主体赛博朋克风咖啡师机器人站在街边咖啡馆门口正在调制一杯拉花咖啡特征material金属和半透明亚克力外壳expression专注且友好accessories[黑色围裙, 发光胸牌, 机械手套] 场景未来感街边咖啡馆夜晚霓虹灯招牌、细雨、湿润路面 构图中近景平视微仰35mm浅景深背景虚化 风格赛博朋克插画参考风格银翼杀手、攻壳机动队表现手法厚涂边缘略带玻璃反射质感 色彩品红、青色、深蓝 光线霓虹灯光侧后方轮廓光强对比有轻微雾气 氛围热闹中带着一丝疏离感 画幅3:4 画质8k高细节金属材质清晰 避免低清晰度手部畸变多余手指文字水印logo这段输出比原始 JSON 更适合复制到图像生成对话框但它完全是由 JSON 数据生成的所有修改都可以回到源文件里完成。运行失败时先看是否已经安装了 Python再看prompt.json是否与脚本在同一目录最后看 JSON 文件编码是否为 UTF-8。这三点是最常见的失败原因。6. 进阶用 JSON 模板批量生成一组图片6.1 批量需求的典型场景假设你要给一个赛博朋克主题的游戏项目画一组角色设定图角色有咖啡师机器人、巡逻机器人、黑客小姐姐、酒吧老板。如果手写提示词每个人物的自然语言描述会非常长而且风格要保持一致很困难。此时就可以把公共部分抽到基础模板里只修改角色相关的subject、style和color_palette字段。6.2 用一个 Python 脚本生成多份 JSON下面这个脚本可以从角色配置列表出发批量生成多份 JSON 文件# 文件路径build_prompts.py import json BASE_PROMPT { task: generate, scene: { location: 未来感街边咖啡馆, time: 夜晚, environment: 霓虹灯招牌、细雨、湿润路面 }, composition: { framing: 中近景, camera_angle: 平视微仰, lens: 35mm, depth_of_field: 浅景深 }, lighting: { type: 霓虹灯光, direction: 侧后方轮廓光, intensity: 强对比 }, mood: 热闹中带着一丝疏离感, aspect_ratio: 3:4, quality: 8k高细节金属材质清晰, negative_prompt: 低清晰度手部畸变多余手指文字水印logo } ROLES [ { name: 赛博朋克风咖啡师机器人, description: 正在调制一杯拉花咖啡, attributes: { material: 金属和半透明亚克力外壳, expression: 专注且友好, accessories: [黑色围裙, 发光胸牌, 机械手套] } }, { name: 雨夜巡逻安保机器人, description: 手持透明防暴盾牌身体略带磨损, attributes: { material: 哑光黑金属, expression: 冷静, accessories: [战术肩灯, 腰间工具包] } } ] def build_prompt(role, style, palette): prompt dict(BASE_PROMPT) prompt[subject] role prompt[style] style prompt[color_palette] palette return prompt if __name__ __main__: common_style { art_style: 赛博朋克插画, influences: [银翼杀手], rendering: 厚涂 } common_palette [品红, 青色, 深蓝] for idx, role in enumerate(ROLES, start1): prompt build_prompt(role, common_style, common_palette) with open(frole_{idx}.json, w, encodingutf-8) as f: json.dump(prompt, f, ensure_asciiFalse, indent2) print(f已生成 role_{idx}.json)运行后目录中会出现role_1.json和role_2.json。再结合上一节的prompt_render.py你可以继续把这两份 JSON 渲染成自然语言提示词。这里的关键洞察是当图像风格、场景、光线、画幅这些公共字段被固定在BASE_PROMPT里批量生成的核心就变成了“只改角色数据”。风格一致性来自公共字段的稳定而不是每次运气好。7. 常见问题与排查思路JSON 提示词的坑并不少下面这张表总结了我在实际使用中最常遇到的问题。问题现象可能原因排查方式解决方案脚本执行报错JSON 解析失败JSON 多了一个逗号、引号未闭合或用了中文引号用 Pythonjson.loads看报错行号用 VS Code 或在线 JSON 校验工具格式化确保键值对边界正确直接把 JSON 粘贴给模型模型根本不按字段执行模型希望接收自然语言而不是原生 JSON检查输入方式区分 API 参数和对话框文本先用渲染脚本把 JSON 转成自然语言提示词修改了mood字段画面氛围没有变化该字段与lighting、color_palette冲突逐个字段单独验证观察每个字段的影响力把mood写成可感知的描述例如“雾气弥漫、光线散射”同一批角色风格不一致每次生成都修改了 style 字段检查批量脚本是否固定了公共模板把生成参数抽到BASE_PROMPT只允许变量覆盖主体信息出现手部畸变、多余手指负面提示词没生效或提示词被模型截断查看最终发送的渲染文本是否包含 negative_prompt把负面词放在提示词尾部并避免用长难句包裹中文内容在脚本中乱码文件编码不是 UTF-8检查文件底部编码格式在编辑器右下角切换为 UTF-8保存后重新运行生成图片比例与设置不符模型不支持该比例或比例字段被忽略确认模型支持的比例列表改用目标模型支持的比例比如 1:1、4:3、3:4、16:9排查 JSON 提示词问题时记住一个原则每次只改一个字段。如果你同时改了场景、风格、光线三个字段出图效果变了你很难判断是哪一项起了作用。先用最小 JSON 跑通再逐步加字段这是成本最低的调试方式。8. 最佳实践与工程建议8.1 字段命名规范JSON 提示词一旦进入团队协作字段命名就会成为维护成本的关键。我建议字段名统一用英文例如subject、scene不要用主体、场景因为脚本和模型对英文键名的兼容性更好。字段值可以用中文中文的自然语言表达能力更强。固定枚举字段的取值。比如aspect_ratio只允许写1:1、3:4、4:3、16:9而不是竖图、横图、差不多方形否则无法做程序化校验。如果要表达多个并列属性优先用数组而不是用顿号分隔的字符串。数组在 JSON 里语义更明确也方便脚本遍历。8.2 提示词版本管理把 JSON 提示词当成代码来管理是我最推荐的做法。哪怕你只是个人使用也可以给每个 JSON 文件加一个meta字段记录创建时间、目标模型、使用的渲染脚本版本。例如{ meta: { version: 1.0, created_at: 2026-01-10, target_model: nano_banana_2 }, task: generate, subject: {} }如果使用 Git可以按照目录结构组织prompts/ base/ cyberpunk_style.json cafe_base.json characters/ role_1.json role_2.json scripts/ prompt_render.py build_prompts.py这样团队里任何人拿到的都是同一套模板不会出现某个人改了风格模板但其他成员不知道的情况。8.3 与模型能力边界结合不要试图用提示词解决所有问题。以 Nano Banana 2 这类对话式图像模型为例它的优势是多轮编辑因此提示词里描述不完美的部分完全可以在生成第一版后继续对话调整。正确使用方式是JSON 负责把“初始画面”稳定下来后续修改用自然语言交互完成。如果第一张图的风格和构图已经基本正确就不要重新改 JSON 再来一遍直接说“保持当前构图把灯光换成冷色调”即可。这一点和传统文生图工具很不一样。传统工具里你往往要反复改 JSON因为每张图都是独立生成的而在对话式工具里你多了一层“基于已有图片继续编辑”的能力JSON 的价值更多体现在约束初始状态和批量复现上。8.4 建立你自己的评估机制提示词写得好不好最直接的评估维度是“能否稳定复现”。每生成一张图可以打一个分例如构图是否符合要求。风格是否接近参考方向。光线是否与字段描述一致。角色是否保持了指定特征。文字、手指、边缘是否明显错误。打分次数多了你会发现哪些字段对模型影响最大哪些字段其实是冗余的。这个经验比任何教程都更有用。注意评估时要固定模型版本因为模型升级后同一份 JSON 提示词的效果可能会变化这不是你的问题而是模型行为发生了变化。9. 总结与下一步动作这次关于 JSON 提示词的讨论与其说是教你一个具体模型的新用法不如说是在展示一种提示词工程思维先拆分变量再写提示词。Nano Banana 2 也好其他图像生成工具也好它们的接口和模型能力会不断变化但结构化提示词这个思路大概率不会过时。现在你可以做三件事立刻开始实践第一把文中的prompt.json模板保存下来替换成你自己真正想生成的画面内容跑通一次“JSON - 渲染 - 出图”的流程。第二把批量生成脚本里的ROLES换成你的角色列表生成一组风格统一的图验证公共字段的约束效果。第三给 JSON 文件加上meta字段和目录结构哪怕现在只有你一个人使用也要让结构和命名符合工程规范。最后提醒一句刚开始使用 JSON 提示词时不要追求字段多先保证字段稳定。一个包含 5 个字段但含义明确的 JSON远比一个包含 30 个字段却互相矛盾的 JSON 有效得多。把提示词当成代码维护注意每一轮只改一个变量你会很快感受到结构化提示词带来的稳定性和团队协作便利。建议收藏备用下次写提示词时打开这篇对照着调参。
返回列表