# OpenAI 图片编辑 API：GPT Image 2 变体迁移与 dall-e-2 报错

> 将 GPT Image 2 的 variations 请求迁移到 edits，并排查 Value must be 'dall-e-2'：涵盖非空提示词、文件与 JSON 输入、蒙版、图片保存及连续修改。

- Source: https://www.aifreeapi.com/zh/posts/openai-image-editing-api
- Language: zh
- Published: 2026-03-23
- Updated: 2026-09-08
- Publisher: AI Free API (https://www.aifreeapi.com)

使用 `gpt-image-2` 调用图片编辑接口，却收到 `Value must be 'dall-e-2'`，先不要把模型改成 `dall-e-2`。**截至 2026 年 9 月 8 日，OpenAI 官方指南明确支持 `gpt-image-2` 的 `images.edit()` 调用，DALL·E 2 则已从 API 移除。** 这条错误说明请求遇到了只接受旧模型的校验；仅凭错误文本，还不能确定校验来自哪一层，也不能认定 GPT Image 2 不支持编辑。[GPT Image 2 模型说明](https://developers.openai.com/api/docs/models/gpt-image-2)、[DALL·E 2 状态](https://developers.openai.com/api/docs/models/dall-e-2)。

如果你是把旧变体代码里的模型名换成了 `gpt-image-2`，还需要确认调用是否仍然停留在 `images/variations`。这个旧端点不支持 GPT Image 2，应迁移到 edits。下面先区分这两种情况，再给出编辑与保存请求、报错诊断及后续修改方法。代码依据当前文档整理，未对你的账号或所用服务执行在线调用。

## 从 variations 迁移：方法、端点和提示词一起改

[官方 variations 参考页](https://developers.openai.com/api/reference/resources/images/methods/create_variation)将该端点限定为 DALL·E 2。即使共享的 `ImageModel` 类型列表出现了 `gpt-image-2`，也不能据此推断每个方法都支持它；具体端点的明确限制才决定调用是否成立。

“基于原图生成变体”仍然可以作为 GPT Image 2 的编辑任务。需要改变的是调用方式：

| 旧请求中的内容 | 迁移后的内容 |
| --- | --- |
| `POST /v1/images/variations` | `POST /v1/images/edits` |
| Python 的 `client.images.create_variation(...)` | `client.images.edit(...)` |
| 上传原图，不传提示词 | 上传原图，并提供有意义的非空 `prompt` |
| 只替换模型名 | 同时确认 SDK 方法、实际请求路径和编辑指令 |

当前 edits 的 `prompt` 要求至少一个字符，但只填空格或无关文字，并不能表达变体需求。更有用的指令是：“保留房间家具和构图，生成一个傍晚暖光版本，只改变窗外光线与室内照明。”它说明了允许改变的内容，也明确了需要保留的对象。[当前编辑请求定义](https://developers.openai.com/api/reference/resources/images/methods/edit)。

`n` 控制返回图片数量，不会把 edits 变回旧版无需提示词的 variations 接口。要比较三种明确方案，可以分别使用“傍晚暖光”“阴天柔光”“午后侧光”的指令，每次从同一张原图开始；若在一份请求中增加 `n`，仍是在同一编辑要求下取得多个结果。下文的保存示例只取第一张；选择多张输出时，要遍历 `result.data` 并分别解码保存。

迁移后仍收到 `Value must be 'dall-e-2'`，才继续按下文对照实际 edits 请求。换回已经移除的 DALL·E 2 不能完成这次迁移。

## 先用最小请求完成编辑与保存

直接编辑的端点是 `POST /v1/images/edits`。下面上传本地文件时使用 multipart 表单，明确传入模型、图片和提示词。先不带蒙版，也不带从 DALL·E 或 GPT Image 1.5 示例中复制的可选参数。

```bash
curl --fail-with-body https://api.openai.com/v1/images/edits \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -F 'model=gpt-image-2' \
  -F 'image=@room.png;type=image/png' \
  -F 'prompt=将房间墙上的挂画换成一幅蓝色抽象画。保留家具、房间布局、光线和拍摄角度，生成完整的室内照片。' \
  -o edit-response.json
```

这里调用的是 OpenAI 官方地址，环境变量也必须对应 OpenAI 凭据。如果你的应用通过其他服务商接入，先核实应用实际使用的域名和路径，再在**同一服务商**上做对照；不要拿一家的密钥去请求另一家的接口，也不要把官方示例当成所有兼容接口的能力承诺。

请求成功后，GPT Image 的图片数据位于 `data[0].b64_json`。默认 PNG 输出可以这样解码：

```python
import base64
import json
from pathlib import Path

response = json.loads(Path("edit-response.json").read_text())
if response.get("error"):
    raise RuntimeError(response["error"])

images = response.get("data") or []
if not images or not images[0].get("b64_json"):
    raise RuntimeError("响应中没有可保存的图片数据")

image_bytes = base64.b64decode(images[0]["b64_json"], validate=True)
Path("room-edited.png").write_bytes(image_bytes)
```

`edit-response.json` 是响应文件，`room-edited.png` 才是解码后的图片。仅收到 HTTP 200、请求编号或 usage 信息，都不足以证明已经拿到可打开的图片；还要确认图片字段存在、解码成功，并打开保存的文件。[官方编辑与输出指南](https://developers.openai.com/api/docs/guides/image-generation#edit-images)。

### 已有图像引用时，也可以使用 JSON 输入

multipart 不是当前编辑接口唯一的输入形式。[现行 edits 参考页](https://developers.openai.com/api/reference/resources/images/methods/edit)也定义了 JSON 请求体，其中 `images` 数组可以通过 `image_url` 或 `file_id` 引用图片。`image_url` 可以是完整 URL 或包含图片数据的 base64 data URL；`file_id` 应指向你可用的已上传图片。

下面展示文件 ID 的请求体结构，使用前将占位值替换为实际 ID，并向同一编辑端点发送 `Content-Type: application/json` 的请求：

```json
{
  "model": "gpt-image-2",
  "images": [{"file_id": "file-REPLACE_WITH_YOUR_IMAGE_ID"}],
  "prompt": "保留房间家具与构图，生成傍晚暖光版本，只改变窗外光线与室内照明。",
  "output_format": "png"
}
```

电脑上的 `room.png` 或绝对路径写进 JSON，不会上传该文件的字节。SDK 对 JSON `images` 形态的支持还应按所装版本核对，不能直接把它塞进旧 SDK 的 `image` 参数。本文的最小 cURL 对照使用本地文件，因此继续让 `-F` 自动设置 multipart 的 Content-Type 和 boundary；成功响应仍按前面的图片解码方式保存。

## 为什么错误里还会出现 dall-e-2

相同的报错文字曾经对应不同问题，不能只套用一个修复口诀。

2026 年 4 月 27 日，OpenAI Node SDK 的 [Issue #1844](https://github.com/openai/openai-node/issues/1844) 报告了 `gpt-image-2` 编辑被要求使用 `dall-e-2`。报告者同时提供了 SDK 和原始 cURL 复现，原始请求没有 `response_format`。8 月的[后续回复](https://github.com/openai/openai-node/issues/1844#issuecomment-5285642026)说明，上游图片编辑校验已修复，旧 DALL·E 模型被有意拒绝；该问题已关闭。

这段历史说明两件事：此错误曾与上游校验有关；它不能被统一归因于 `response_format` 或某个 SDK 的类型定义。它也不证明今天每个兼容网关都已修好，更不能据此编造一个“升级到某版本必好”的版本号。

另一个[社区讨论](https://community.openai.com/t/edit-endpoint-images-edits-refusing-gpt-image-models/1375581)记录了早期 GPT Image 编辑的不同经历：有人移除 `response_format` 后恢复，也有人发现没有文件名的内存文件触发失败，给文件补上名称后解决。它们适合用来设计排查步骤，但不是对所有 GPT Image 2 请求的诊断结论。

因此，遇到这个错误时，最有用的问题是：**同一个服务商、同一个模型，最小文件上传请求是否也失败？** 这个结果决定你接下来应该检查业务封装，还是把注意力转向接口校验与服务支持。

## 按返回结果决定下一步

![在同一服务商比较最小文件请求与应用请求的排查示意](https://www.aifreeapi.com/posts/zh/openai-image-editing-api/img/request-comparison.webp)

先记录实际的请求时间、域名、路径、HTTP 状态、`error.message`、`error.param`、`error.code` 和请求编号。不要只截取最后一句异常；也不要在日志或工单中附上 Authorization、完整 API Key、私有图片数据或带签名的下载地址。

| 你实际观察到的结果 | 接下来检查什么 |
| --- | --- |
| 实际路径仍是 `/images/variations` | 将操作迁移到 edits，并传入有意义的非空提示词；仅修改模型名不够 |
| 最小 cURL 成功，应用失败 | 对比最终发出的模型、表单字段、上传文件名与 MIME 类型；确认 SDK 的 base URL 和应用代理是否改写请求 |
| 同一服务商的最小 cURL 也返回模型校验错误 | 核实该服务商当前的编辑模型支持，保留脱敏请求与请求编号反馈；不要反复修改提示词 |
| 错误转为图片格式、大小或蒙版问题 | 请求已经遇到另一项校验，按对应文件要求处理；不要继续把所有错误归入模型不支持 |
| 返回成功，但没有 `b64_json` | 检查完整响应结构和服务商文档，确认是不是任务状态、包装后的响应或其他数据格式 |
| 图片已保存，但修改位置或人物外观不对 | 进入提示词、蒙版与保留效果调整；这已不是模型枚举错误 |

做对照时一次改变一个条件。先用磁盘上的一张 PNG，把最小请求跑通；然后接回原来的 SDK、内存上传和可选参数。这样得到的是可比较的结果，而不是同时换模型、接口、文件和提示词后无法解释的偶然成功。

如果官方端点和兼容服务表现不同，分别按照各自的文档和请求编号定位。`/v1/images/edits` 这个路径相同，不代表两个域名背后的参数支持、模型映射或响应结构相同。

## 旧示例里有两个参数需要重新处理

从旧版图片教程迁移到 GPT Image 2 时，最容易留下的是 `response_format` 和 `input_fidelity`。

| 项目 | GPT Image 2 的处理方式 | 它实际控制什么 |
| --- | --- | --- |
| `model` | 显式写 `gpt-image-2` | 选择编辑模型，避免依赖旧默认值 |
| `response_format` | 省略，包括 `response_format="b64_json"` | 这是旧 DALL·E 响应选项，不能因为想要 base64 就继续带上 |
| `output_format` | 需要时设为 `png`、`jpeg` 或 `webp` | 解码后图片的文件格式，不改变 base64 承载方式 |
| `input_fidelity` | 省略 | GPT Image 2 自动采用高保真处理，不能再切换高低档 |
| `mask` | 只在需要指定修改区域时添加 | 提供编辑位置引导，不能保证边界外所有像素不变 |

例如，需要 JPEG 时加 `output_format="jpeg"`，解码后的文件使用 `.jpg` 或 `.jpeg` 扩展名。不要把 JPEG 字节保存成 `.png`，也不要用 `response_format` 代替文件格式设置。[编辑参数参考](https://developers.openai.com/api/reference/ruby/resources/images/methods/edit)、[GPT Image 2 输入保真说明](https://developers.openai.com/api/docs/guides/image-generation#image-input-fidelity)。

删除旧字段是合理的迁移步骤，但如果删除后仍收到同一条模型错误，应继续进行前面的接口与上传对照。历史报告中存在完全不带 `response_format` 的复现，不能把删字段说成必然有效的修复。

## Python 与 Node：给上传文件明确的名称

SDK 可以处理内存数据，并非只有磁盘文件才合法。OpenAI Python SDK 支持字节、路径对象以及文件三元组；Node SDK 支持文件流、`File`、`Response` 和 `toFile` 等上传方式。排查时显式提供文件名与 MIME 类型，可以减少封装层如何解释文件的歧义。[Python 文件上传说明](https://github.com/openai/openai-python#file-uploads)、[Node 文件上传说明](https://github.com/openai/openai-node#file-uploads)。

Python 的内存上传示例：

```python
import base64
from pathlib import Path
from openai import OpenAI

client = OpenAI()
image_bytes = Path("room.png").read_bytes()

result = client.images.edit(
    model="gpt-image-2",
    image=("room.png", image_bytes, "image/png"),
    prompt="把墙上的挂画换成蓝色抽象画，保留房间布局、家具、光线和拍摄角度。",
    output_format="png",
)

if not result.data or not result.data[0].b64_json:
    raise RuntimeError("响应中没有图片数据")

Path("room-edited.png").write_bytes(
    base64.b64decode(result.data[0].b64_json, validate=True)
)
```

Node 的对应写法如下。先在项目中安装 `openai` 包，并将示例保存为 `.mjs` 文件，或使用已启用 ES 模块的项目。

```js
import fs from "node:fs/promises";
import OpenAI, { toFile } from "openai";

const client = new OpenAI();
const bytes = await fs.readFile("room.png");

const result = await client.images.edit({
  model: "gpt-image-2",
  image: await toFile(bytes, "room.png", { type: "image/png" }),
  prompt: "把墙上的挂画换成蓝色抽象画，保留房间布局、家具、光线和拍摄角度。",
  output_format: "png",
});

const encoded = result.data?.[0]?.b64_json;
if (!encoded) throw new Error("响应中没有图片数据");

await fs.writeFile("room-edited.png", Buffer.from(encoded, "base64"));
```

这里的 `room.png` 应与实际字节格式一致。如果传入 JPEG，就使用正确的名称和 `image/jpeg`。把文件重命名不会转换编码，补上文件名也不会修复已经损坏的图片。

如果这份写法成功，而原来的内存上传失败，可以重点检查原封装是否丢失文件名、MIME 类型或文件内容；如果两者都失败，则不能因为历史帖子提过文件名，就认定当前问题也出在这里。

## 请求通过之后，再加蒙版和多张参考图

![客厅原图、挂画位置的透明蒙版与蓝色挂画编辑结果示意](https://www.aifreeapi.com/posts/zh/openai-image-editing-api/img/mask-edit-example.webp)

蒙版（mask）解决的是“重点修改哪里”，不是接口是否接受 `gpt-image-2`。把它留到基础编辑成功后再加，能避免模型校验与文件校验混在一起。

一个保守的文件准备方式是：原图和蒙版均使用 PNG，宽高完全相同；蒙版包含 alpha 通道，**透明区域，也就是 alpha 为 0 的区域，表示要编辑的位置**。一张没有透明通道的黑白图，不应直接当作透明蒙版使用。多图输入时，蒙版应用于第一张图。[官方蒙版说明](https://developers.openai.com/api/docs/guides/image-generation#edit-an-image-using-a-mask)。

需要注意官方资料的大小口径：编辑参数参考将蒙版限定为 PNG、低于 4 MB；生成指南有更宽泛的 50 MB 表述。为避免边界不一致，下面的工作流按更严格的**蒙版小于 4 MB**准备。普通 GPT Image 输入支持 PNG、WebP、JPG，每张小于 50 MB，最多 16 张；不要将普通输入上限直接套给蒙版。[编辑输入参数](https://developers.openai.com/api/reference/ruby/resources/images/methods/edit)。

```python
with open("room.png", "rb") as image, open("mask.png", "rb") as mask:
    result = client.images.edit(
        model="gpt-image-2",
        image=image,
        mask=mask,
        prompt=(
            "生成一张完整的室内照片：把墙上的挂画换成蓝色抽象画。"
            "保留沙发、桌子、窗户、自然光和拍摄角度。"
        ),
        output_format="png",
    )
```

返回结果沿用前面的 `b64_json` 解码保存方式。提示词应描述最终整张图，并写清重要的保留条件；仅写“改成蓝色”容易留下对象、范围和风格上的歧义。

如果要把第二张图的商品放进第一张图的场景，先明确图片顺序，再说明每张图的作用。例如：“以图一为场景，将图二的台灯放在图一书桌右侧，保留台灯外形和颜色，并匹配室内光线。”多参考图用于提供不同信息，不需要为了使用多图功能而加入不相关素材。

### 高保真不等于像素完全锁定

GPT Image 2 自动采用高保真处理，但它仍然是生成式编辑。官方说明明确指出，蒙版提供引导，模型可能不能严格遵循蒙版形状。因此，接口接受蒙版、成功生成图片，与“未选中区域逐像素不变”是两个不同结果。

对于商品图、人物照片或带品牌标识的素材，把真正重要的保留条件写具体：商品几何、人物身份、商标文字、镜头角度或光照。先只修改一个对象，查看结果，再基于已经接近目标的图片进行下一次编辑。不要在同一个请求里同时换场景、改服装、调整姿势并要求所有细节不变，否则很难判断哪一项要求导致偏差。

如果业务必须保证某些区域的像素不变，需要另外采用确定性的裁切或合成处理；单靠蒙版与提示词不能获得这种保证。

## 连续修改：先选对上一版，再决定是否用 Responses

一次上传、一次编辑、保存文件，继续用 `images.edit()` 就足够。多步微调也可以连续调用它，但每一次请求都要明确传入所选图片：将已经满意的结果保存为 `room-v1.png`，下一次把它作为输入，只要求“将挂画稍微缩小，保留当前灯光与其他物体”，再将新结果保存为 `room-v2.png`。记录所用图片和提示词，避免误把原图或未采用的结果传回去。

这与前面从同一原图比较不同光照方案的做法不同。独立方案从原图开始，连续微调则接续已经接受的版本；如果主体已经明显偏离，应回到原图或最近一张合适的结果，而不是在偏差上不断追加要求。因为历史上出现过模型校验错误而迁移整个 API，也不能替代这一步输入管理。

当产品需要连续对话，例如“把刚才的挂画再缩小一点”，并且需要把图片修改与文本推理或其他工具调用串联起来时，可以考虑 Responses API，通过 `previous_response_id` 接续对话上下文。它使用支持图片生成工具的主模型，再通过 `image_generation` 工具完成图像操作；**不要把 `gpt-image-2` 直接填进 Responses 顶层 `model` 当作对话主模型**。[官方 API 选择说明](https://developers.openai.com/api/docs/guides/image-generation)。

如果还需要了解 GPT Image 2 的其他接入方式和接口选择，可以继续阅读 [GPT Image 2 API 指南](/zh/posts/gpt-image-2-api)。处理这两类报错时，先确认 variations 已迁移为 edits 且带有明确指令；若正确的编辑请求仍被拒绝，再用同一服务商的最小文件请求建立对照，依据实际错误检查参数、上传信息或接口支持。
