图片编辑:根据指令编辑参考图或融合两张图
curl --request POST \
--url https://api.apiyi.com/v1/images/edits \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form model=MAI-Image-2.6-Flash \
--form 'prompt=把茶壶改成深钴蓝釉,其余部分完全保持不变' \
--form image='@example-file' \
--form image2='@example-file'import requests
url = "https://api.apiyi.com/v1/images/edits"
files = {
"image": ("example-file", open("example-file", "rb")),
"image2": ("example-file", open("example-file", "rb"))
}
payload = {
"model": "MAI-Image-2.6-Flash",
"prompt": "把茶壶改成深钴蓝釉,其余部分完全保持不变"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('model', 'MAI-Image-2.6-Flash');
form.append('prompt', '把茶壶改成深钴蓝釉,其余部分完全保持不变');
form.append('image', '<string>');
form.append('image2', '{
"fileName": "example-file"
}');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://api.apiyi.com/v1/images/edits', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.apiyi.com/v1/images/edits",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nMAI-Image-2.6-Flash\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\n把茶壶改成深钴蓝釉,其余部分完全保持不变\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image2\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.apiyi.com/v1/images/edits"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nMAI-Image-2.6-Flash\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\n把茶壶改成深钴蓝釉,其余部分完全保持不变\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image2\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.apiyi.com/v1/images/edits")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nMAI-Image-2.6-Flash\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\n把茶壶改成深钴蓝釉,其余部分完全保持不变\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image2\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.apiyi.com/v1/images/edits")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nMAI-Image-2.6-Flash\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\n把茶壶改成深钴蓝釉,其余部分完全保持不变\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image2\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"created": 1791000788,
"data": [
{
"b64_json": "<string>"
}
],
"usage": {
"prompt_tokens": 1000,
"total_tokens": 1000
}
}MAI-Image 2.6 生圖/編輯
圖片編輯 API 參考
MAI-Image 2.6 圖片編輯 API 參考與線上除錯 — 上傳參考圖 + 指令改圖,支援 image + image2 雙圖融合,必須使用 multipart/form-data 檔案上傳
POST
/
v1
/
images
/
edits
图片编辑:根据指令编辑参考图或融合两张图
curl --request POST \
--url https://api.apiyi.com/v1/images/edits \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form model=MAI-Image-2.6-Flash \
--form 'prompt=把茶壶改成深钴蓝釉,其余部分完全保持不变' \
--form image='@example-file' \
--form image2='@example-file'import requests
url = "https://api.apiyi.com/v1/images/edits"
files = {
"image": ("example-file", open("example-file", "rb")),
"image2": ("example-file", open("example-file", "rb"))
}
payload = {
"model": "MAI-Image-2.6-Flash",
"prompt": "把茶壶改成深钴蓝釉,其余部分完全保持不变"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('model', 'MAI-Image-2.6-Flash');
form.append('prompt', '把茶壶改成深钴蓝釉,其余部分完全保持不变');
form.append('image', '<string>');
form.append('image2', '{
"fileName": "example-file"
}');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://api.apiyi.com/v1/images/edits', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.apiyi.com/v1/images/edits",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nMAI-Image-2.6-Flash\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\n把茶壶改成深钴蓝釉,其余部分完全保持不变\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image2\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.apiyi.com/v1/images/edits"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nMAI-Image-2.6-Flash\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\n把茶壶改成深钴蓝釉,其余部分完全保持不变\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image2\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.apiyi.com/v1/images/edits")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nMAI-Image-2.6-Flash\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\n把茶壶改成深钴蓝釉,其余部分完全保持不变\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image2\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.apiyi.com/v1/images/edits")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nMAI-Image-2.6-Flash\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\n把茶壶改成深钴蓝釉,其余部分完全保持不变\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image2\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"created": 1791000788,
"data": [
{
"b64_json": "<string>"
}
],
"usage": {
"prompt_tokens": 1000,
"total_tokens": 1000
}
}右側的互動式 Playground 支援直接上傳本地圖片。請在 Authorization 中填入你的 API Key(格式:
Bearer sk-xxx),選擇 image 檔案並填入 prompt、model 後一鍵傳送即可。🔴 本介面只接受 不支援圖片 URL 入參。手上只有 URL 時,請先在服務端下載成檔案再上傳。檔案上傳不需要圖床,直接傳本地檔案即可。
multipart/form-data 檔案上傳傳送 JSON 到 /v1/images/edits(image 填 URL、data URI 或裸 base64)會返回 400:request Content-Type isn't multipart/form-data
場景說明:本頁用於「基於參考圖改圖 / 雙圖融合」。如需純文本生成圖片,請使用 文生圖介面。
⚠️ 多圖欄位名是
image + image2,不是 image[]兩張參考圖時,第一張欄位名 image、第二張 image2。image[] 重複兩次、image 同名兩次、帶 mask 欄位都會返回 400 File must be attached in a form field with a name starting with 'image'。因此 OpenAI SDK 的 client.images.edit(image=[f1, f2]) 多圖寫法不可用(它會發 image[]);單圖編輯用 SDK 沒問題。引數紅線與文生圖相同:不要傳
response_format、seed、negative_prompt(返回 400)。返回值固定為 data[0].b64_json(PNG)。程式碼示例
Python(OpenAI SDK · 單圖編輯)
from openai import OpenAI
import base64
client = OpenAI(
api_key="sk-your-api-key",
base_url="https://api.apiyi.com/v1",
timeout=180.0
)
# SDK 的 images.edit 內部就是 multipart 檔案上傳;不要傳 response_format
resp = client.images.edit(
model="MAI-Image-2.6-Flash",
image=open("teaset.jpg", "rb"),
prompt="Change the teapot to a deep cobalt blue glaze, keep everything else identical"
)
with open("edited.png", "wb") as f:
f.write(base64.b64decode(resp.data[0].b64_json))
Python(原生 requests · 單圖編輯)
import base64
import os
import requests
# 用 files= 傳檔案,requests 會自動設定 multipart/form-data 及 boundary
# 不要用 json=,也不要手動設 Content-Type
with open("teaset.jpg", "rb") as fp:
response = requests.post(
"https://api.apiyi.com/v1/images/edits",
headers={"Authorization": f"Bearer {os.environ['APIYI_API_KEY']}"},
data={
"model": "MAI-Image-2.6",
"prompt": "把茶壺改成深鈷藍釉,其餘部分完全保持不變"
},
files={"image": ("teaset.jpg", fp, "image/jpeg")},
timeout=180
)
response.raise_for_status()
with open("edited.png", "wb") as f:
f.write(base64.b64decode(response.json()["data"][0]["b64_json"]))
Python(雙圖融合 · image + image2)
import base64
import os
import requests
files = {
"image": ("scene.jpg", open("scene.jpg", "rb"), "image/jpeg"), # 圖1
"image2": ("person.jpg", open("person.jpg", "rb"), "image/jpeg"), # 圖2,欄位名是 image2
}
response = requests.post(
"https://api.apiyi.com/v1/images/edits",
headers={"Authorization": f"Bearer {os.environ['APIYI_API_KEY']}"},
data={
"model": "MAI-Image-2.6",
"prompt": "讓圖2的人物坐在圖1的桌前,正在擺弄這套茶具,自然光,寫實攝影"
},
files=files,
timeout=180
)
response.raise_for_status()
with open("fused.png", "wb") as f:
f.write(base64.b64decode(response.json()["data"][0]["b64_json"]))
cURL
# 單圖編輯:-F 即 multipart/form-data,@ 字首表示上傳本地檔案
curl -X POST "https://api.apiyi.com/v1/images/edits" \
-H "Authorization: Bearer sk-your-api-key" \
-F "model=MAI-Image-2.6-Flash" \
-F "prompt=把茶壺改成深鈷藍釉,其餘部分完全保持不變" \
-F "[email protected]" \
| python3 -c "import sys,json,base64; open('edited.png','wb').write(base64.b64decode(json.load(sys.stdin)['data'][0]['b64_json']))"
# 雙圖融合 + 改畫幅為 1536×1024
curl -X POST "https://api.apiyi.com/v1/images/edits" \
-H "Authorization: Bearer sk-your-api-key" \
-F "model=MAI-Image-2.6" \
-F "prompt=讓圖2的人物坐在圖1的桌前,正在擺弄這套茶具" \
-F "width=1536" \
-F "height=1024" \
-F "[email protected]" \
-F "[email protected]"
Node.js(原生 fetch + FormData)
import fs from 'node:fs';
const form = new FormData();
form.append('model', 'MAI-Image-2.6-Flash');
form.append('prompt', '把背景換成雪夜的松林,保持人物不變');
form.append('image', new Blob([fs.readFileSync('./photo.jpg')]), 'photo.jpg');
// 第二張參考圖:form.append('image2', ...)
const resp = await fetch('https://api.apiyi.com/v1/images/edits', {
method: 'POST',
// 不要手動設 Content-Type,交給 FormData 自動帶 boundary
headers: { 'Authorization': `Bearer ${process.env.APIYI_API_KEY}` },
body: form,
signal: AbortSignal.timeout(120000)
});
const data = await resp.json();
fs.writeFileSync('edited.png', Buffer.from(data.data[0].b64_json, 'base64'));
引數說明速查
| 引數名 | 型別 | 必填 | 預設 | 說明 |
|---|---|---|---|---|
model | string | ✅ | — | MAI-Image-2.6($0.12/張)或 MAI-Image-2.6-Flash($0.06/張),大小寫敏感 |
prompt | string | ✅ | — | 編輯指令。建議寫明「改什麼」並宣告「其餘保持不變」 |
image | file | ✅ | — | 參考圖檔案(第一張) |
image2 | file | ❌ | — | 第二張參考圖(雙圖融合時用) |
width / height | integer | ❌ | 跟隨原圖比例 | 指定輸出尺寸,規則同文生圖;與原圖比例不同時會重新構圖 |
n | integer | ❌ | 1 | 出圖張數,本端點有效,按張計費 |
mask | — | — | — | 不支援,傳入返回 400 |
response_formatseednegative_prompt | — | — | — | 傳入返回 400 |
不傳尺寸時的輸出:按原圖比例貼合到 16 的倍數網格,例如 1344×756 的輸入輸出 1360×768。只想改局部、不想動構圖時,不要傳
width / height。編輯效果與提示詞寫法
編輯介面會保留原圖的構圖、配色與細節,只改提示詞指定的部分:
| 寫法 | 效果 |
|---|---|
✅ 把茶壺改成深鈷藍釉,其餘部分完全保持不變 | 只有茶壺變色,尺寸標註、其它物件逐畫素保留 |
✅ 把這張照片改成水彩畫風格,構圖不變 | 風格整體重繪,構圖保持 |
✅ 讓圖2的人物坐在圖1的桌前 | 雙圖融合,圖1提供場景、圖2提供人物 |
⚠️ 讓它更好看一點 | 指令過於籠統,改動範圍不可控 |
雙圖融合時在提示詞裡用「圖1 / 圖2」指代
image / image2。實測人物融合時身份保真度一般(臉部特徵可能變化),對人像一致性要求高的場景請先小批次驗證。響應格式
{
"created": 1791000788,
"data": [
{
"b64_json": "iVBORw0KGgoAAAANSUhEUgAABAAAAAQACAIAAADwf7zU..."
}
],
"usage": {
"prompt_tokens": 1000,
"total_tokens": 1000,
"input_tokens": 1000,
"output_tokens": 0
}
}
響應欄位說明
b64_json是純 base64,不帶data:字首,解碼後為 PNG。n > 1時data陣列有多項,別隻取data[0]。- 不返回
url與revised_prompt。
usage 不能用來核賬:是佔位值(prompt_tokens 恆為 1000 × 張數)。編輯與文生圖同價,按張固定計費,真實扣費請以 API易 控制台賬單為準。授權
在 API易控制台获取的 API Key
主體
multipart/form-data
模型 ID(大小写敏感)
可用選項:
MAI-Image-2.6-Flash, MAI-Image-2.6 编辑指令。建议明确「改什么」并声明「其余保持不变」
範例:
"把茶壶改成深钴蓝釉,其余部分完全保持不变"
参考图文件(第一张,提示词中的「图1」)。格式 png / jpg / webp
可选,第二张参考图(提示词中的「图2」),用于双图融合
可选,输出宽度。规则同文生图:每维 ≥ 768、宽×高 ≤ 2,359,296,须与 height 成对
必填範圍:
x >= 768可选,输出高度,规则同 width
必填範圍:
x >= 768出图张数,本端点有效,按张计费
必填範圍:
x >= 1範例:
1
這個頁面有幫助嗎?