Codex 调用 gpt-image-2 生图实战:Windows 固定配置、脚本封装与代理兼容
本文记录如何在 Windows 的 Codex 工作区中固定保存图像 API 配置,并通过一个 PowerShell 命令调用
gpt-image-2生成图片。方案支持内联提示词和提示词文件,也兼容接口返回 Base64 或临时图片 URL 两种情况。
一、最终效果
配置完成后,在项目根目录执行:
powershell
.\scripts\generate-image.ps1 `
-Prompt "一朵粉色水彩花,白色背景,画面简洁,不要文字" `
-OutFile ".\outputs\pink-flower.png"
脚本会自动完成以下操作:
- 读取固定 API 地址、模型和默认参数;
- 从本地文件加载 API Key;
- 查找 Codex 自带的 Python 运行时;
- 首次运行时自动安装依赖;
- 调用
gpt-image-2; - 处理 Base64 或图片 URL 响应;
- 将最终 PNG 保存到
outputs目录。
发布文章时,可以在这里插入一张自己的测试生成图。
二、项目结构
text
项目目录/
├─ config/
│ ├─ imagegen.json # API 地址、模型及默认参数
│ └─ api-key.txt # API Key,本地明文文件,不提交 Git
├─ scripts/
│ ├─ generate-image.ps1 # 统一调用入口
│ └─ imagegen_client.py # Python 图像 API 客户端
├─ outputs/ # 图片输出目录
├─ work/ # 提示词文件等临时内容
├─ .imagegen-runtime/ # 自动安装的 Python 依赖
└─ .gitignore
三、准备配置文件
1. 图像 API 配置
新建 config/imagegen.json:
json
{
"base_url": "https://your-api-host.example/v1",
"model": "gpt-image-2",
"size": "1024x1024",
"quality": "low",
"output_format": "png"
}
参数说明:
| 参数 | 说明 |
|---|---|
base_url |
OpenAI 兼容接口地址,通常以 /v1 结尾 |
model |
生图模型,本文使用 gpt-image-2 |
size |
默认分辨率,例如 1024x1024 |
quality |
low、medium、high 或 auto |
output_format |
输出格式,本文使用 png |
low 适合快速预览,正式海报可以改为 high。常用横向尺寸有 1536x1024、2048x1152,方形图片可以使用 1024x1024 或 2048x2048。
2. 固定 API Key
新建 config/api-key.txt,文件中只保存一行 Key:
text
sk-your-api-key-here
本文为了调用方便使用明文文件。该文件属于敏感信息,必须加入 .gitignore,不要上传到 GitHub、网盘或文章附件。
3. 配置 .gitignore
gitignore
# 本地 API 凭据和运行依赖
config/api-key.txt
.imagegen-runtime/
四、编写 Python 图像客户端
新建 scripts/imagegen_client.py:
python
import argparse
import base64
from pathlib import Path
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(
description="Generate an image with a GPT Image compatible API"
)
prompt_group = parser.add_mutually_exclusive_group(required=True)
prompt_group.add_argument("--prompt")
prompt_group.add_argument("--prompt-file")
parser.add_argument("--out", required=True)
parser.add_argument("--model", required=True)
parser.add_argument("--size", required=True)
parser.add_argument("--quality", required=True)
parser.add_argument("--output-format", default="png")
return parser.parse_args()
def main() -> int:
args = parse_args()
from openai import OpenAI
import httpx2
prompt = args.prompt
if args.prompt_file:
prompt = Path(args.prompt_file).read_text(encoding="utf-8")
result = OpenAI().images.generate(
model=args.model,
prompt=prompt,
n=1,
size=args.size,
quality=args.quality,
output_format=args.output_format,
)
item = result.data[0]
# 官方接口可能返回 Base64,部分兼容网关则返回临时 URL。
if item.b64_json:
image_bytes = base64.b64decode(item.b64_json)
elif item.url:
response = httpx2.get(
item.url,
timeout=600,
follow_redirects=True,
)
response.raise_for_status()
image_bytes = response.content
else:
raise RuntimeError(
"The API response contains neither b64_json nor url"
)
output = Path(args.out).resolve()
output.parent.mkdir(parents=True, exist_ok=True)
output.write_bytes(image_bytes)
print(f"Saved image: {output} ({len(image_bytes)} bytes)")
return 0
if __name__ == "__main__":
raise SystemExit(main())
这段代码中最重要的是同时判断 b64_json 和 url。部分 OpenAI 兼容网关虽然完成了生图,但返回的是 URL。如果代码只读取 b64_json,保存阶段可能出现下面的错误:
text
TypeError: argument should be a bytes-like object or ASCII string,
not 'NoneType'
这并不一定表示生成失败,而可能只是响应格式与客户端预期不同。
五、编写 PowerShell 统一入口
新建 scripts/generate-image.ps1:
powershell
[CmdletBinding(DefaultParameterSetName = 'InlinePrompt')]
param(
[Parameter(Mandatory = $true, ParameterSetName = 'InlinePrompt')]
[string]$Prompt,
[Parameter(Mandatory = $true, ParameterSetName = 'PromptFile')]
[string]$PromptFile,
[Parameter(Mandatory = $true)]
[string]$OutFile,
[string]$Model,
[string]$Size,
[ValidateSet('low', 'medium', 'high', 'auto')]
[string]$Quality
)
$ErrorActionPreference = 'Stop'
$projectRoot = Split-Path -Parent $PSScriptRoot
$configPath = Join-Path $projectRoot 'config\imagegen.json'
$keyPath = Join-Path $projectRoot 'config\api-key.txt'
$clientPath = Join-Path $PSScriptRoot 'imagegen_client.py'
$packagePath = Join-Path $projectRoot '.imagegen-runtime\python-packages'
if (-not (Test-Path -LiteralPath $configPath)) {
throw "Missing configuration file: $configPath"
}
if (-not (Test-Path -LiteralPath $keyPath)) {
throw "Missing API key file: $keyPath"
}
$config = Get-Content -Raw -LiteralPath $configPath | ConvertFrom-Json
if (-not $Model) { $Model = $config.model }
if (-not $Size) { $Size = $config.size }
if (-not $Quality) { $Quality = $config.quality }
[array]$pythonCandidates = @(
(Get-Command python -ErrorAction SilentlyContinue).Source,
"$env:USERPROFILE\.cache\codex-runtimes\codex-primary-runtime\dependencies\python\python.exe"
) | Where-Object {
$_ -and (Test-Path -LiteralPath $_)
}
if (-not $pythonCandidates) {
throw 'Python was not found. Open this project in Codex once.'
}
$pythonExe = $pythonCandidates[0]
# 依赖只安装到当前项目,不污染系统 Python。
New-Item -ItemType Directory -Force -Path $packagePath | Out-Null
$env:PYTHONPATH = $packagePath
& $pythonExe -c 'import openai, httpx2' 2>$null
if ($LASTEXITCODE -ne 0) {
Write-Host 'Installing local image-generation dependencies...'
& $pythonExe -m pip install `
--disable-pip-version-check `
--target $packagePath `
openai pillow
if ($LASTEXITCODE -ne 0) {
throw 'Failed to install image-generation dependencies.'
}
}
$apiKey = (Get-Content -Raw -LiteralPath $keyPath).Trim()
if ([string]::IsNullOrWhiteSpace($apiKey)) {
throw "API key file is empty: $keyPath"
}
try {
# 只把凭据注入当前调用进程。
$env:OPENAI_API_KEY = $apiKey
$env:OPENAI_BASE_URL = $config.base_url
$arguments = @(
$clientPath,
'--out', $OutFile,
'--model', $Model,
'--size', $Size,
'--quality', $Quality,
'--output-format', $config.output_format
)
if ($PSCmdlet.ParameterSetName -eq 'PromptFile') {
$arguments += @(
'--prompt-file',
(Resolve-Path -LiteralPath $PromptFile).Path
)
}
else {
$arguments += @('--prompt', $Prompt)
}
& $pythonExe @arguments
if ($LASTEXITCODE -ne 0) {
throw "Image generation failed with exit code $LASTEXITCODE"
}
}
finally {
# 调用结束后清理当前进程中的环境变量。
$apiKey = $null
Remove-Item Env:OPENAI_API_KEY -ErrorAction SilentlyContinue
Remove-Item Env:OPENAI_BASE_URL -ErrorAction SilentlyContinue
Remove-Item Env:PYTHONPATH -ErrorAction SilentlyContinue
}
注意这里的 [array]$pythonCandidates。如果候选路径只有一个,而变量被当作普通字符串处理,$pythonCandidates[0] 可能只得到盘符首字母 C,随后出现:
text
The term 'C' is not recognized as a name of a cmdlet
显式声明为数组即可避免这个问题。
六、运行方式
1. 直接传入提示词
powershell
.\scripts\generate-image.ps1 `
-Prompt "一朵蓝色水彩花,白色背景,居中构图,无文字,无水印" `
-OutFile ".\outputs\blue-flower.png"
2. 使用提示词文件
复杂海报适合把提示词保存在 work/poster-prompt.txt:
text
Use case: stylized-concept
Asset type: landscape character poster
Primary request: 一张左右分屏的足球人物插画海报
Style/medium: 手绘数字水粉与墨线
Composition/framing: 2048x1152 横向画布,严格左右平衡
Lighting/mood: 体育场灯光,强烈但保留人物面部细节
Constraints: 无水印,无乱码文字,无多余人物
执行:
powershell
.\scripts\generate-image.ps1 `
-PromptFile ".\work\poster-prompt.txt" `
-OutFile ".\outputs\poster.png" `
-Size "2048x1152" `
-Quality "high"
命令行中的 -Size、-Quality 和 -Model 会覆盖 JSON 中的默认值。
七、推荐的提示词结构
复杂图片不要只写一句主题,建议使用结构化提示词:
text
Use case: stylized-concept
Asset type: 图片用途
Primary request: 核心画面要求
Scene/backdrop: 场景与背景
Subject: 主体、数量和位置
Style/medium: 插画、摄影、水彩、3D 等
Composition/framing: 横竖比例、景别和留白
Lighting/mood: 光线与情绪
Color palette: 主色与辅助色
Constraints: 必须满足的限制
Avoid: 不要出现的内容
对于人物群像,建议明确写出:
- 人物总数及左右各有多少人;
- 中心人物与辅助人物的位置;
- 胸像、半身还是全身;
- 是否需要文字、队徽、商标;
- 禁止重复人物、额外手臂、乱码和水印。
八、常见问题排查
1. OPENAI_API_KEY is not set
检查 config/api-key.txt 是否存在、是否为空。文件中不要增加引号或说明文字。
2. Authentication failed
可能原因包括:
- Key 无效或已经过期;
base_url缺少/v1;- API 服务的 TLS 或证书与 PowerShell 客户端不兼容;
- 接口服务限制了来源 IP。
如果 PowerShell 的 Invoke-RestMethod 失败,而 Python SDK 可以访问,可以继续使用本文的 Python 客户端通道。
3. 生图完成后出现 NoneType Base64 错误
兼容网关可能返回 url,而不是 b64_json。本文客户端已经同时兼容两种响应字段。
4. content_policy_violation
简化提示词中对真人身份、暴力、敏感内容或强身份复刻的表述。可以把"完全一致的真人肖像"调整为"编辑插画风格的致敬形象",同时保留构图与服装要求。
5. 高质量图片等待时间较长
这是正常现象。建议先用:
text
size: 1024x1024
quality: low
确认构图后,再改为 2K 与 high 生成最终版本。
九、安全建议
本文采用明文 Key 文件,优点是调用方便,缺点是任何能读取项目目录的程序都可能读取凭据。至少应做到:
- 始终将
config/api-key.txt加入.gitignore; - 不要在截图、录屏和文章代码中展示真实 Key;
- 不要把整个项目目录打包上传;
- 定期轮换 Key,并设置额度或调用限制;
- Key 一旦在公开页面出现,应立即作废并重新生成。
生产环境更推荐系统凭据库、环境变量或专用密钥管理服务。
十、总结
通过 JSON 配置、PowerShell 入口和 Python 客户端三层拆分,可以把 Codex 生图流程固定下来:日常只需要提供提示词和输出路径,不必每次重新输入 API 地址、模型与 Key。
本文方案还解决了两个 Windows 和兼容网关中常见的问题:Python 路径被误取成首字符,以及接口返回 URL 导致 Base64 保存失败。配置完成后,简单插画、人物海报和高分辨率横幅都可以使用同一个命令生成。
推荐标题: Codex 调用 gpt-image-2 生图实战:Windows 固定配置、脚本封装与代理兼容
文章摘要: 本文介绍如何在 Windows Codex 工作区中固定保存 gpt-image-2 的 API 配置,通过 PowerShell 与 Python 封装统一生图入口,并解决兼容网关返回 URL、Python 路径解析、依赖隔离等常见问题。
推荐标签: Codex、OpenAI、gpt-image-2、AIGC、Python、PowerShell