跳到主要內容

【2026 最新】GPT-Image 2 Prompt as Code 教學:用 JSON Schema 做出可重跑品牌視覺

最後更新: ·
GPT-Image 2 Prompt as Code 教學:用 JSON Schema、受控變體與回歸驗收打造可版本化品牌視覺

你用同一句描述做出第一張海報,效果很好;隔天只想換成橫幅,罐子比例、品牌色與中文字卻一起漂走。問題通常不是你少背了一句「神奇咒語」,而是那份需求沒有可檢查的欄位。GPT-Image 2 Prompt as Code 的目的,就是把散文提示詞改造成可以驗證、比較與留下紀錄的視覺契約。

這個方法正在受到注意。2026 年 8 月 26 日,同一個 awesome-gpt-image-2 固定版本約整理了 530 個案例;GitHub Trending 當時顯示的快取星數,還和稍後的 REST 快照不同。這只能證明開發者關注,不能證明 JSON 會讓圖片更好。

這篇專為第一次把生圖流程放進專案的人寫。我會用一個完全虛構、文字與規格均為自有範例的飲料品牌,帶你建立最小 JSON Schema、產生四個只改一項的變體、接上官方 Image API,再用五道 gate 驗收。你不必先懂後端;照著檔名與指令做,就能留下下一輪接得上的版本。

先說結論:可重跑不是同一張圖,而是同一場實驗

🧩 Prompt as Code = 結構化 Brief + 固定參數 + 版本紀錄 + 可重複驗收

  • 結構化 Brief:主體、鏡頭、光線、材質、版面與文案各有自己的欄位。
  • 固定參數:端點、模型 snapshot、尺寸、品質、格式與背景都明寫。
  • 版本紀錄:輸入、prompt hash、輸出 hash、素材權利與挑選理由一起保存。
  • 可重複驗收:每次都用同一份主體、文字、階層、色彩與跨尺寸 rubric 檢查。

換句話說,這套流程讓你知道「改了什麼、得到什麼、為何選它」,不保證重跑會得到相同像素。

GPT-Image 2 Prompt as Code 是什麼?先拆掉兩個誤會

第一,它不是 OpenAI 新增的一種 API 模式。官方 GPT Image 2 模型頁把 Structured Outputs 標為不支援;Image API 的 prompt 仍是字串。我們是在自己的專案先用 JSON Schema 驗證物件,再把通過的 JSON 序列化成 prompt 字串。

第二,JSON 不是畫質加速器。OpenAI 的 官方生圖提示指南說,極短文字、段落、JSON-like 或指令式格式都能工作;生產流程更應優先選容易維護與掃讀的模板。JSON 的優勢是表單化、可 diff,不是模型偏愛大括號。

GPT-Image 2 Prompt as Code 從品牌 Brief、JSON Schema 驗證、prompt 字串到輸出驗收與版本紀錄的流程圖
Schema 只負責擋住不完整的輸入;圖片是否合格,仍由輸出後的五道 gate 決定。

Step 0:先建一個不會把素材與成品混在一起的資料夾

visual-prompt/
├── schema/visual-prompt.schema.json
├── briefs/base.json
├── variants/
│   ├── v0-baseline.json
│   ├── v1-camera.json
│   ├── v2-lighting.json
│   └── v3-layout.json
├── materialized/
├── outputs/
├── runs/
├── evals/
└── rights/assets.json

briefs 是不變的品牌事實,variants 只放這一輪想測的差異,materialized 是兩者合併後真正送出的完整設定。rights 則記錄素材擁有人、來源網址、授權或許可、取用日與檔案 hash。這次範例沒有搬用案例庫的圖、文案或 logo,避免把「看得到」誤當成「可商用」。

Step 1:用六個創意欄位,建立最小 JSON Schema

如果所有要求都擠在一段話裡,少寫品牌色或 CTA 時,程式不會提醒你。解法是把創意拆成六格:subject、camera、lighting、materials、layout、copy;再加上 palette、constraints 與 output 三個操作層。JSON Schema 就像出貨前的勾選表,先擋掉缺欄位與拼錯 key 的請求。

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "subject", "camera", "lighting", "materials",
    "layout", "copy", "palette", "constraints", "output"
  ],
  "properties": {
    "subject": { "type": "object" },
    "camera": { "type": "object" },
    "lighting": { "type": "object" },
    "materials": {
      "type": "array",
      "minItems": 1,
      "items": { "type": "string" }
    },
    "layout": { "type": "object" },
    "copy": {
      "type": "object",
      "required": ["locale", "headline", "subheadline", "cta"],
      "properties": {
        "locale": { "const": "zh-Hant" },
        "headline": { "type": "string", "minLength": 1 },
        "subheadline": { "type": "string", "minLength": 1 },
        "cta": { "type": "string", "minLength": 1 }
      }
    },
    "palette": { "type": "array", "minItems": 2 },
    "constraints": { "type": "array", "minItems": 1 },
    "output": {
      "type": "object",
      "required": ["size", "quality", "format", "background"]
    }
  }
}

把它存成 schema/visual-prompt.schema.json。這是能上手的最小版;正式專案可再對 HEX 格式、允許尺寸、每個巢狀欄位與 additionalProperties 加限制。JSON Schema Draft 2020-12的角色是描述 JSON 結構,並不會描述「一張好看的圖」。

Step 2:把自有品牌 Brief 寫成可以被驗證的基準版

範例品牌叫「潮汐茶房」,產品是虛構的「白桃烏龍氣泡茶」。痛點不是缺形容詞,而是「產品長怎樣、文字是什麼、哪些不能動」沒有分開。以下基準版把三段繁中列成 literal copy,也把四個主體特徵鎖住:

{
  "subject": {
    "primary": "一罐虛構品牌「潮汐茶房」的 330 mL 白桃烏龍氣泡茶",
    "locked_traits": [
      "霧面米白鋁罐",
      "正面有深墨綠圓形浪紋",
      "罐身比例纖長",
      "罐頂與底圈為原色鋁"
    ]
  },
  "camera": {
    "shot": "單一產品的三分之二身景",
    "angle": "與罐身等高的三分之四角度",
    "lens": "70mm 商品攝影視角,輕微景深"
  },
  "lighting": {
    "key": "左上大型柔光",
    "fill": "正面低強度中性補光",
    "accent": "右後方淡桃色輪廓光"
  },
  "materials": ["霧面鋁罐", "少量凝結水珠", "淺色白橡木桌面", "切半白桃"],
  "layout": {
    "reading_order": ["產品", "標題", "副標", "行動文字"],
    "subject_zone": "產品位於左側 42% 區域",
    "copy_zone": "文字位於右側 50% 區域並左對齊",
    "safe_area": "四邊保留 8%,文字與產品不重疊"
  },
  "copy": {
    "locale": "zh-Hant",
    "headline": "白桃烏龍氣泡茶",
    "subheadline": "一口,回到夏天",
    "cta": "立即預購"
  },
  "palette": [
    { "name": "墨綠", "hex": "#173F35" },
    { "name": "米白", "hex": "#F3EBDD" },
    { "name": "白桃", "hex": "#F29A8A" }
  ],
  "constraints": [
    "只顯示 copy 欄位內的三段繁體中文",
    "不得新增其他商標、徽章或價格",
    "保留鋁罐比例與四項 locked_traits"
  ],
  "output": {
    "size": "1536x1024",
    "quality": "high",
    "format": "png",
    "background": "opaque"
  }
}

HEX 在這裡是目標色,不是像素保證;鏡頭規格也是構圖線索,不是物理相機模擬。這兩句先寫清楚,後面才不會把「接近」包裝成「精準還原」。

Step 3:做四個受控變體,每次只動一個創意欄位

一次改鏡頭、光線、文案與版面,看到差異也不知道由誰造成。解法是以 baseline 為 V0,另外三個 patch 分別只替換 camera、lighting、layout。識別碼與說明可以變,但創意欄位只改一組:

// v0-baseline.json
{}

// v1-camera.json
{
  "camera": {
    "shot": "單一產品近景",
    "angle": "略低於罐身中線的正面角度",
    "lens": "50mm 商品攝影視角,背景清楚可辨"
  }
}

// v2-lighting.json
{
  "lighting": {
    "key": "正上方狹長柔光,形成俐落高光",
    "fill": "左前方低強度冷色補光",
    "accent": "右後方淡桃色輪廓光"
  }
}

// v3-layout.json
{
  "layout": {
    "reading_order": ["標題", "產品", "副標", "行動文字"],
    "subject_zone": "產品位於中央下方 44% 區域",
    "copy_zone": "文字位於上方 38% 區域並置中",
    "safe_area": "四邊保留 8%,文字與產品不重疊"
  }
}

合併時用 { ...base, ...patch },讓 patch 替換整個頂層物件,再把四份完整 JSON 寫進 materialized

import { readFile, mkdir, writeFile } from "node:fs/promises";

const base = JSON.parse(await readFile("briefs/base.json", "utf8"));
const files = [
  "v0-baseline.json",
  "v1-camera.json",
  "v2-lighting.json",
  "v3-layout.json"
];

await mkdir("materialized", { recursive: true });
for (const file of files) {
  const patch = JSON.parse(
    await readFile("variants/" + file, "utf8")
  );
  const merged = { ...base, ...patch };
  await writeFile(
    "materialized/" + file,
    JSON.stringify(merged, null, 2) + "\n"
  );
}

接著依 Ajv CLI 官方用法驗證四份完整設定:

node scripts/build-variants.mjs

for file in materialized/*.json; do
  npx --yes ajv-cli@5.0.0 validate --spec=draft2020 -s schema/visual-prompt.schema.json -d "$file"
done

AlphaLab 在 2026 年 8 月 26 日實際跑過這個驗證流程,四份 materialized JSON 都回傳 valid,建置腳本與生圖腳本也通過 Node 語法檢查。這證明契約與合併流程可執行;因本次沒有呼叫付費生圖 API,本文不捏造四張輸出或優勝分數。

Step 4:把通過驗證的 JSON 送進 GPT Image 2

最短路徑是直接用 Image API。不要把 gpt-image-2 當成 Responses API 的主模型;若走 Responses,架構會是另一個主線模型加 image_generation 工具,而且工具可能改寫 prompt。這個受控比較只用同一個 /v1/images/generations 端點。

npm install openai@7.5.0
export OPENAI_API_KEY="你的 API key"
node scripts/generate.mjs materialized/v0-baseline.json
import OpenAI from "openai";
import { readFile, writeFile } from "node:fs/promises";

const spec = JSON.parse(await readFile(process.argv[2], "utf8"));
const prompt = [
  "用途:品牌社群主視覺。請依下列已驗證的視覺契約產圖。",
  "所有 copy 必須逐字使用,不要自行改寫。",
  JSON.stringify(spec, null, 2)
].join("\n\n").normalize("NFC");

const client = new OpenAI();
const result = await client.images.generate({
  model: "gpt-image-2-2026-04-21",
  prompt,
  n: 1,
  size: spec.output.size,
  quality: spec.output.quality,
  output_format: spec.output.format,
  background: spec.output.background,
  moderation: "auto"
});

await writeFile(
  "output.png",
  Buffer.from(result.data[0].b64_json, "base64")
);

這裡有一個容易踩的坑:寫在 JSON 裡的 quality 本身不會設定 API;是程式把它取出,再放進真正的 quality 參數。官方 Image Generation Guide目前列出的主要輸出控制包括 size、quality、format、compression 與 background;PNG 不需要 compression。

Step 5:每次生圖都存一份 run manifest

只把勝出的 PNG 拖到桌面,三天後就無法回答「它用哪版 prompt?」每次呼叫後,至少保存 endpoint、模型 snapshot、SDK 版本、prompt hash、明示參數、request ID、輸入素材 hash、原始輸出 hash、權利紀錄與挑選理由:

{
  "endpoint": "/v1/images/generations",
  "model": "gpt-image-2-2026-04-21",
  "sdk": { "package": "openai", "version": "7.5.0" },
  "input_file": "materialized/v0-baseline.json",
  "prompt_unicode_normalization": "NFC",
  "prompt_sha256": "實際計算值",
  "parameters": {
    "n": 1,
    "size": "1536x1024",
    "quality": "high",
    "output_format": "png",
    "background": "opaque",
    "moderation": "auto"
  },
  "request_id": "實際回傳值",
  "output_sha256": "實際計算值",
  "rights_record": "rights/assets.json",
  "selection_reason": null
}

最後才把 selection_reason 填成具體理由,例如「三段文字逐字正確、四項主體特徵都保留、CTA 沒有碰撞」。不要寫「比較有感覺」;那無法讓下一位編輯複查。

Step 6:用五道 gate 驗收,不用「我覺得好看」投票

每個變體若只產一張,只能叫四個示範案例,不能證明哪種設定更穩。若要宣稱「改善」,每個條件要重複生成、保留全部樣本、先寫選圖規則,再報告樣本數。初學者可先用以下 0/1/2 rubric,但不要杜撰還沒跑出的分數:

  1. 主體一致性:四項 locked traits 是否逐項保留?0 是身分改變,1 是有可修漂移,2 是全部可辨。
  2. 繁中可讀性:人工逐字轉錄 headline、subheadline、CTA;記錄漏字、錯字、繁簡誤換與順序,不只看 OCR。
  3. 版面階層:第一眼是否先看到指定主角?文字是否落在預定區域、有無遮擋與碰撞?
  4. 品牌色:HEX 只作目標;在事先指定的純色區域取樣,保存實測值,不從整張圖挑最接近的一顆像素。
  5. 跨尺寸穩定性:勝出方案再跑 1024×1024、1536×1024、1024×1536,檢查不變量是否保留。不同長寬比容許重排,不要求相同構圖。
GPT-Image 2 Prompt as Code 四個受控變體與主體、繁中、階層、品牌色、跨尺寸五道驗收 gate
四個 variant 只改一項創意欄位;五道 gate 使用同一張評分卡,才看得出差異來自哪裡。

Prompt as Code 的 7 個坑:版本化不等於自動正確

  1. 把 JSON 當魔法語法:它改善維護性,不保證提升畫質。
  2. 一輪改四件事:diff 很熱鬧,因果卻不可判讀;一次只改一個創意欄位。
  3. 只存最後一張:沒有 prompt、參數與 hash,就無法追溯淘汰原因。
  4. 把 HEX 當硬色票:光影、材質與壓縮都會改變像素;用預定取樣區驗收。
  5. 用四張圖下穩定結論:單次輸出只足以示範;比較級需要重複樣本與固定選圖規則。
  6. 把 snapshot 當像素鎖:固定 gpt-image-2-2026-04-21有助於控制模型版本,仍不是相同像素保證。截至 2026 年 8 月 26 日,官方 generation request schema 未列 seed;本文也不自行添加。
  7. 整包複製案例庫:該 repo 的 MIT 授權不會自動替個別匯入案例清權;要回到每項素材的原作者與授權。

官方也明列現行限制:文字位置或清晰度、跨次生成的品牌元素一致性,以及精密版面仍可能失敗。因此 rubric 不是額外文書,而是生圖流程的一部分。

什麼時候用一般 prompt,什麼時候升級 Prompt as Code?

  • 一次性靈感草圖:一般 prompt 已足夠,先追求方向,不必建立整套目錄。
  • 兩張以上同系列素材:開始拆 subject、copy 與 palette,避免每張重寫品牌事實。
  • 多人交接、定期活動、跨尺寸投放:使用完整 Schema、manifest、rights ledger 與 eval rubric。
  • 需要精準文字或 logo:生圖只做背景或產品素材,文字與官方 logo 交給可控的排版工具;不要要求模型仿造品牌標誌。

若你想先理解「規則如何約束 Agent」,可從 AI Agent Harness補概念;要把視覺流程做成可交接的圖表,則可接著讀 Diagram Design SVG/PNG 交付教學

GPT-Image 2 Prompt as Code 常見問題(FAQ)

Q1:Prompt as Code 是 OpenAI 官方功能嗎?

不是。這是應用層的工作方法;OpenAI API 收到的仍是 prompt 字串。

Q2:改成 JSON,圖片一定比較好嗎?

不一定。JSON 的直接收益是欄位完整、容易 diff 與自動驗證;輸出品質仍要看內容與評測。

Q3:同一份 JSON 會得到同一張圖嗎?

不會承諾。版本化讓實驗條件可追溯,不代表像素級 deterministic。

Q4:完全不會寫程式也能用嗎?

可以先用。先以 JSON 當表單填六個欄位;要自動驗證、合併與存 hash,再照本文三段指令執行。

Q5:GPT Image 2 能保證繁體中文零錯字嗎?

不能保證。把 literal copy 列清楚有助於溝通,但每張仍要人工逐字驗收;正式稿可在排版工具重上文字。

Q6:一定要用 Responses API 嗎?

不用。本文要控制同一端點與 prompt,所以直接用 Image API;多輪對話式修改才考慮 Responses 的 image generation tool。

Q7:GitHub 案例庫的圖片與 prompt 可以直接商用嗎?

不能一概而論。專案根目錄授權與個別匯入素材的權利是兩件事;逐項確認來源與許可,最簡單的教學路線是用自有或已授權內容。

Q8:最高分圖片就能直接當品牌最終稿嗎?

不建議。rubric 是篩選工具,不是法律、品牌與印刷終審;商標、權利、文字、色彩與實際尺寸仍要由人確認。

給新手的 6 個重點

  1. 先把品牌不變量寫成欄位,再開始堆形容詞。
  2. Schema 驗證輸入結構,rubric 驗證圖片輸出,兩者不能互相代替。
  3. 四個變體要各自從同一 baseline 出發,不要累積修改。
  4. 模型 snapshot、端點與所有參數要跟 prompt 一起版本化。
  5. 保存全部樣本與挑選理由,別只留下最好看的一張。
  6. 使用自有或已授權素材,正式稿再做文字、品牌與權利終審。

接著閱讀

左右滑動查看更多推薦

結語:先版本化一次差異,不要先追求完美模板

第一次實作只做一件事:把你現有的一段視覺 prompt 拆成六個創意欄位,建立 V0,再只改 camera 做 V1。驗證、生成、填完五道 gate,最後把選擇理由寫進 manifest。你已經完成一個最小但可交接的回圈。

回到本文的錨點:Prompt as Code = 結構化 Brief + 固定參數 + 版本紀錄 + 可重複驗收。真正被版本化的不是「漂亮」,而是你對漂亮做了哪些可檢查的決定。想繼續追蹤 AI 創作方法,可到 AlphaLab AI 專區;要把這種規格化思考延伸到完整工程工作流,也可查看 AlphaLab 線上課程

ALPHALAB 社群

有問題?來 Telegram 聊

和 Terry、編輯、其他網友一起討論這篇文章。提問、分享觀點,回覆更即時。

加入 Telegram 討論

📩 訂閱 AlphaLab 電子報

每週最多三封:一封 Weekly 週報與最多兩封關鍵 Alpha Signal。

我們不會 spam,隨時可退訂。