关于 bytedance-seedream
供通过 ByteDance 一方 Ark 图像生成 API 使用 Seedream 的应用参考的技能,指导模型与区域选择、请求构造、参考图编辑、成组输出、流式传输及响应校验。
主要功能
- 01按区域和能力选择模型
- 02根据文本提示生成图像
- 03编辑并融合参考图
- 04支持成组输出和流式传输
- 05校验请求与 API 响应
适用场景
- 01制作一组相关营销图像
- 02依据多张参考图编辑图像
- 03流式获取并校验生成结果
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ calesthio/ generative-media-skills --skill bytedance-seedream安装后在 Claude Code 中输入/bytedance-seedream确认已加载。
附带文件EVAL.md
详细介绍
ByteDance Seedream
当应用通过一方 Ark 图像生成 API 直接调用 Seedream 时,请使用此技能。它涵盖文生图、参考图引导生成、自然语言编辑、多图融合、分组输出和流式分组输出。不涵盖 Seedance 视频生成、第三方网关、消费级应用、模型训练或 UI 自动化。
以下所有时效性信息均已于 2026-07-09 对照一方文档核实。正式上线前,请重新检查链接中的模型目录、可用性、定价和退役页面。
证据标签
- 已记录 表示 ByteDance Seed、Volcengine 或 BytePlus 的当前页面说明了该行为。
- 提供方声明 表示一方产品或研究页面提出了定性性能声明;在应用的语料上测试之前,应将其视为营销内容。
- 运营建议 表示根据已记录的契约推断出的生产实践,并非提供方保证。
- 未知 表示经审阅的一方页面未明确说明该行为。请进行功能检测或咨询支持,而不要凭空编造契约。
先选择商业服务平台
模型 ID 和主机不可互换。
| 部署方式 | API 基础 URL | 截至 2026-07-09 记录的当前图像模型 ID | 重要限制 |
|---|---|---|---|
| Volcengine Ark,中国 | https://ark.cn-beijing.volces.com/api/v3 | doubao-seedream-5-0-pro-260628、doubao-seedream-5-0-260128(也记录为别名 doubao-seedream-5-0-lite-260128)、doubao-seedream-4-5-251128、doubao-seedream-4-0-250828 | 仅限中国主机和 doubao-... ID |
| BytePlus ModelArk,亚太地区 | https://ark.ap-southeast.bytepluses.com/api/v3 | seedream-5-0-260128(也记录为别名 seedream-5-0-lite-260128)、seedream-4-5-251128、seedream-4-0-250828 | 仅限全球主机和非 doubao ID |
| BytePlus ModelArk,欧洲 | https://ark.eu-west.bytepluses.com/api/v3 | 文档说明 Seedream 5.0 Lite 在欧盟可用;部署任何其他版本前,请确认实时目录 | 可用性页面禁止在欧盟/欧盟市场使用受限模型,包括 Seedream 4.0 |
三者均使用:
POST {API_BASE}/images/generations
Authorization: Bearer {ARK_API_KEY}
Content-Type: application/json
不要将中国令牌发送到 BytePlus 主机,也不要将 BytePlus 令牌发送到中国主机。请使用精确的主机允许列表,绝不要记录密钥,并在运行时从密钥管理器注入密钥。
已记录的区域注意事项: BytePlus 表示,亚太地区请求通常优先由亚太地区处理,但也可能由欧盟处理;有需要时,欧盟请求也可能由亚太地区处理。因此,选择端点并不能保证数据驻留。如果数据驻留是要求,请获取合同层面的明确答复。
根据契约选择模型,而非只看名称
| 能力 | China 5.0 Pro | 5.0 Lite | 4.5 | 4.0 |
|---|---|---|---|---|
| 文本生成和参考图/编辑输入 | 支持 | 支持 | 支持 | 支持 |
| 参考图数量上限 | 10 | 14 | 14 | 10(保守值);通用 API 标注为 14 |
分组输出(sequential_image_generation) | 不支持 | 支持 | 支持 | 支持 |
SSE 流式传输(stream) | 不支持 | 支持 | 支持 | 支持 |
web_search 工具 | 不支持 | 支持 | 不支持 | 不支持 |
| 输出格式控制 | PNG/JPEG | PNG/JPEG | 仅 JPEG | 仅 JPEG |
| 分辨率标注 | 1K/2K | 2K/3K/4K | 2K/4K | 1K/2K/4K |
| 提示词优化 | standard;不支持 fast | standard;不支持 fast | standard;不支持 fast | standard 或 fast |
5.0 Pro 这一行适用于上文所述的中国版模型;BytePlus 当前的全球图像 API 未记录全球版 5.0 Pro ID。请勿自行编造。
**一方资料中的 4.0 冲突:**当前通用图像 API 描述了 2–14 张参考输入,而 Seedream 4.0 专属卡片对多图生成单图和多图生成图组工作流标注了 2–10 张。4.0 生产环境的默认验证上限设为 10。只有在经授权的实时试运行确认了确切的端点契约后,才使用 11–14 张;并记录响应和检索日期。
需要分组输出、SSE 或可选实时网页搜索时,使用 5.0 Lite。需要其文档中描述的高端单图契约,且不需要分组或流式输出时,使用 China 5.0 Pro。只有出于经验证的兼容性、质量或成本原因才保留 4.5 或 4.0,并维护迁移测试。
Seedream 5.0 Lite 的一方发布页面介绍了多模态推理、世界知识和可选实时搜索。这些属于供应商声明;请使用有代表性的提示词评估事实准确性和视觉质量。
请求契约
核心字段
model为必填项,可以是文档中列出的模型 ID,也可以是已配置的端点 ID。prompt为必填项。指南建议不超过约 300 个汉字或 600 个英文单词;这是建议,并非文档中规定的服务器硬性限制。image为可选项,接受单个 URL/数据 URL 或数组。数据 URL 必须为data:image/<lowercase-format>;base64,<payload>。- 输入格式:JPEG、PNG、WebP、BMP、TIFF、GIF、HEIC 或 HEIF。每个维度必须大于 14 px,宽高比必须在
[1/16, 16]范围内,文件大小不得超过 30 MB,图像总面积不得超过 36 MP。 size接受模型支持的分辨率标注或明确的WIDTHxHEIGHT字符串。发送前请根据所选模型进行验证。response_format为url或b64_json;默认值为url。返回的 URL 会在 24 小时后过期。watermark默认为true,会添加可见的中文“AI 生成”标记。设为false可移除该可见标记;但这并不免除披露、溯源或法律义务。- 仅当前的 5.0 模型支持
output_format设置为png或jpeg;默认值为 JPEG。请勿向 4.5/4.0 发送此参数并期待格式转换。
当前规范的 4.0–5.0 API 页面未记录这些模型支持 seed 或 guidance_scale。BytePlus 仅为旧版 3.0 模型记录了这些控制项,并明确标注当前系列不支持 guidance。除非你所控制的确切端点契约明确记录了这些参数,否则请勿发送。输出相似不等于输出确定。
尺寸限制
| 模型 | 默认值 | 显式像素面积 | 宽高比 |
|---|---|---|---|
| China 5.0 Pro | 1024x1024 | 921,600 至 4,624,220 像素 | [1/16, 16] |
| 5.0 Lite | 2048x2048 | 3,686,400 至 16,777,216 像素 | [1/16, 16] |
| 4.5 | 2048x2048 | 3,686,400 至 16,777,216 像素 | [1/16, 16] |
| 4.0 | 2048x2048 | 921,600 至 16,777,216 像素 | [1/16, 16] |
建议在提示词中使用有文档说明的标签,并搭配宽高比或用途描述,或者选择有文档说明的推荐尺寸。常见的文档示例包括:5.0 Lite 2K 方形 2048x2048、横向 2848x1600、纵向 1600x2848;5.0 Lite 4K 方形 4096x4096;以及 Pro 1K 方形 1024x1024 或 2K 方形 2048x2048。不要假设不同模型中相同标签对应的像素尺寸也相同。
自然语言编辑与参考图
当前统一 API 没有单独的蒙版/局部重绘接口。提供一个或多个 image 参考图,并在 prompt 中描述要进行的编辑:
- 按顺序标识参考图:“在图像 1 中……使用图像 2 的光照效果。”
- 指明目标操作:添加、移除、替换、重新着色、重新布光、改变风格或合成。
- 明确说明不变项:“保持姿势、面部比例、相机、背景和所有文字不变。”
- 对于难以识别的局部区域,请在源图上用箭头、方框或涂鸦标注,并在提示词中指明该标记。提示词指南对此技巧有说明。
- 进行融合时,为每张参考图指定单一用途,不要让模型自行推断用途。
参考图 URL 必须可供服务获取。建议使用有效期较短且权限范围最小的预签名 URL。数据 URL 无需公开托管,但仍会将图像传给提供方,而且可能导致请求体过大。
分组输出
适用于 5.0 Lite、4.5 或 4.0:
{
"sequential_image_generation": "auto",
"sequential_image_generation_options": {"max_images": 4}
}
max_images 的取值范围为 1–15,默认值为 15。输入参考图数量与生成图像数量之和不得超过 15。auto 允许模型自行决定是否创建图像以及创建多少张;它不保证达到请求的最大数量。请在提示词中写明确切的集合,例如:“准确创建四张故事板帧;帧 1……帧 2……”,然后验证实际数量。不要向 China 5.0 Pro 发送这些字段。
可选的网络搜索
目前仅 5.0 Lite 有文档说明支持:
{"tools": [{"type": "web_search"}]}
是否使用网络搜索由模型决定;usage.tool_usage.web_search 会报告搜索使用情况。搜索会增加延迟,并带来外部内容风险。应将搜索到的事实和视觉细节视为不可信内容,检查出处和权利信息,不要承诺一定会进行搜索。
谨慎解读响应
对于非流式请求,响应顶层通常包含 model、created、data、usage,也可能包含 error。每个 data 成员可能是成功生成的图像(包含 url 或 b64_json、size,以及受支持时的 output_format),也可能是单项错误。因此,即使响应状态码为 200,也可能存在部分失败。
请验证:
- 顶层状态和错误。
- 每个
data项目。 - 实际成功数量是否符合所请求的交付内容。
- 声明的尺寸/格式是否与解码后的字节一致。
usage.generated_images、输出 token 数量和工具使用情况,以便监控成本并进行观测。
文档指出,只对成功生成的图像计费。不要因客户端超时就推断费用为零:由于没有文档说明幂等键,超时的请求可能已在服务端完成。
当 stream: true 时,请解析服务器发送的事件,直到最终完成事件:
image_generation.partial_succeeded:包含image_index(从零开始的索引)以及url或b64_json和size。image_generation.partial_failed:包含image_index和错误信息。image_generation.completed:最终用量/工具摘要。- 顶层
error:请求失败。
流式指南指出,内容过滤器导致的失败之后仍可能继续生成后续图像,而内部 500 错误会停止后续生成。不要将第一个部分事件视为任务已完成。
生产工作流
1. 建立策略边界
调用 API 前,记录以下信息:
- 部署环境、账户、端点区域、准确的模型/端点 ID 和上线日期;
- 允许的输入分类,以及是否允许个人数据、人脸、商标或机密材料;
- 每项任务的参考图数量、输出数量、尺寸、字节数、延迟、重试次数和费用上限;
- 可见水印/披露政策,以及持久的溯源政策;
- 公开、商业或高影响用途的审核人员和审批标准。
2. 规范化并验证输入
- 解码本地输入并检查其实际类型;不要只相信文件名或客户端 MIME 类型。
- 上传前拒绝格式错误、超大、解压炸弹、压缩比极高和不受支持的输入。
- 除非有意保留,否则移除不必要的 EXIF/位置信息。
- 为每个来源计算哈希、保存其许可证/同意记录,并分配稳定的参考编号。
- 从提示词到审计记录,保持参考图顺序稳定。
3. 构建可测试的提示词
使用自然语句,而不是堆砌关键词:
[deliverable/use]. [subject and action]. [environment].
[camera/composition]. [lighting/color/style].
[exact text in double quotes]. [reference roles]. [edit invariants].
[numbered outputs if a set].
对于排版,将必需文案放在双引号中,指定位置和层级,然后运行 OCR 并进行人工校对。生成结果不保证排版准确。
4. 提交任务并记录任务流水
创建客户端任务 ID,并持久化请求哈希、已删减敏感信息的参数、模型、主机、开始时间、尝试次数和状态。图像 API 是同步调用或请求范围内的 SSE;当前文档未说明异步图像任务、轮询 API、Webhook 或幂等键。不要套用 Seedance 视频任务语义。
5. 有针对性地重试
对于网络故障、429 限流和暂时性 500 错误,使用带上限的指数退避、随机抖动,并在存在 Retry-After 时遵循该值。限制总尝试次数和并发数。以下情况不要重试:
- 身份验证、账户、余额、服务未开放或模型访问失败;
- 参数无效/缺失或图像有问题;
- 内容安全、版权或隐私拒绝;
- 如果无法接受重复计费/输出,不要在超时情况不明时自动重试。
Ark 文档说明了账户/模型/端点特定的 IPM、RPM、TPM、突发流量、配额和过载错误。BytePlus 当前的 Seedream 教程列出当前全球模型每分钟 500 张图像,但账户和端点限制可能更低。测量实际响应头/错误,并将准入控制配置在已验证的限值之下。
6. 安全获取产物
对于 url 响应,请立即下载,因为链接有效期为 24 小时。产物 URL 是需要单独处理的不可信获取目标:
- 要求使用 HTTPS,拒绝凭据/片段,并拒绝意外重定向;
- 绝不要在获取产物时附带 Ark
Authorization请求头; - 在缓冲数据前限制流式传输的字节数;
- 将图像内容类型加入允许列表,验证文件签名字节,解码尺寸并重新扫描;
- 写入临时文件,按需执行 fsync,然后原子性地移至正式位置;
- 为最终字节计算哈希,并保存尺寸、MIME、模型、提示词哈希、来源哈希、审核状态和提供方用量。
对于 b64_json,使用严格的 base64 解码,并执行相同的解码后字节数、文件签名、尺寸和扫描检查。
7. 发布前进行评估
使用固定回归集,涵盖文生图、单图编辑、多参考图身份一致性、排版、违禁内容、极端宽高比、群组人数、部分失败、限流、超时和下载文件损坏等情况。评估提示词遵循度、编辑局部性、参考图一致性、视觉缺陷、OCR 准确度、安全性、延迟和成本。尽可能以盲测方式比较候选模型和现有模型。
示例:严格的非流式生成
这个完整的 Python 标准库示例不会由此技能执行。它使用 BytePlus AP 和 5.0 Lite,请求返回 base64 以避免资源 URL 过期,验证 API 基地址,限制解码后的大小,检查 PNG/JPEG 文件特征,并写入持久化元数据。设置 ARK_API_KEY;也可以设置 ARK_API_BASE 和 SEEDREAM_MODEL,并确保二者是兼容且有文档记录的组合。
import base64
import binascii
import hashlib
import json
import os
import pathlib
import tempfile
import time
import urllib.error
import urllib.request
ALLOWED = {
"https://ark.cn-beijing.volces.com/api/v3": {
"doubao-seedream-5-0-pro-260628", "doubao-seedream-5-0-260128",
"doubao-seedream-5-0-lite-260128", "doubao-seedream-4-5-251128",
"doubao-seedream-4-0-250828",
},
"https://ark.ap-southeast.bytepluses.com/api/v3": {
"seedream-5-0-260128", "seedream-5-0-lite-260128",
"seedream-4-5-251128", "seedream-4-0-250828",
},
"https://ark.eu-west.bytepluses.com/api/v3": {
"seedream-5-0-260128", "seedream-5-0-lite-260128",
},
}
MAX_IMAGE_BYTES = 25 * 1024 * 1024
MAX_JSON_BYTES = ((MAX_IMAGE_BYTES + 2) // 3) * 4 + 1024 * 1024
def atomic_write(path, data):
path.parent.mkdir(parents=True, exist_ok=True)
handle, temporary = tempfile.mkstemp(dir=path.parent, prefix=".seedream-")
try:
with os.fdopen(handle, "wb") as output:
output.write(data)
output.flush()
os.fsync(output.fileno())
os.replace(temporary, path)
except Exception:
try:
os.unlink(temporary)
except FileNotFoundError:
pass
raise
api_base = os.getenv(
"ARK_API_BASE", "https://ark.ap-southeast.bytepluses.com/api/v3"
).rstrip("/")
api_key = os.environ.get("ARK_API_KEY", "")
model = os.getenv("SEEDREAM_MODEL", "seedream-5-0-260128")
configured_endpoint = os.getenv("SEEDREAM_ALLOWED_ENDPOINT_ID")
configured_endpoint_base = os.getenv("SEEDREAM_ALLOWED_ENDPOINT_API_BASE")
configured_endpoint_model = os.getenv("SEEDREAM_ALLOWED_ENDPOINT_MODEL")
allowed_models = ALLOWED.get(api_base, set())
bound_endpoint = (
model == configured_endpoint
and api_base == configured_endpoint_base
and configured_endpoint_model in allowed_models
)
if api_base not in ALLOWED or (model not in allowed_models and not bound_endpoint):
raise SystemExit("Refusing an undocumented host/model namespace pairing")
payload = {
"model": model,
"prompt": (
"Square editorial product photograph for a coffee brand. A matte black "
"ceramic cup on pale limestone, soft window light from camera left, subtle "
"steam, generous negative space, realistic materials. No logos or text."
),
"size": "2K",
"response_format": "b64_json",
"output_format": "png",
"watermark": True,
}
body = json.dumps(payload, separators=(",", ":")).encode("utf-8")
request = urllib.request.Request(
api_base + "/images/generations",
data=body,
method="POST",
headers={
"Authorization": "Bearer " + api_key,
"Content-Type": "application/json",
"Accept": "application/json",
},
)
print({
"model": payload["model"], "size": payload["size"],
"request_sha256": hashlib.sha256(body).hexdigest(),
"watermark": payload["watermark"],
})
if os.environ.get("SEND_SEEDREAM_REQUEST") != "1":
raise SystemExit("Dry run only; set SEND_SEEDREAM_REQUEST=1 after approving the paid call")
if not api_key:
raise SystemExit("Set ARK_API_KEY before the paid call")
try:
with urllib.request.urlopen(request, timeout=180) as response:
raw = response.read(MAX_JSON_BYTES + 1)
except urllib.error.HTTPError as exc:
# Do not print request headers or secrets.
detail = exc.read(64 * 1024).decode("utf-8", "replace")
raise SystemExit(f"Ark HTTP {exc.code}: {detail}") from exc
if len(raw) > MAX_JSON_BYTES:
raise SystemExit("JSON response exceeded configured base64 envelope cap")
try:
document = json.loads(raw)
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
raise SystemExit("Response was not valid bounded JSON") from exc
if document.get("error"):
raise SystemExit(f"Ark error: {document['error']}")
successful = [item for item in document.get("data", []) if item.get("b64_json")]
failed = [item.get("error") for item in document.get("data", []) if item.get("error")]
if len(successful) != 1 or failed:
raise SystemExit(f"Expected one image; successes={len(successful)} failures={failed}")
encoded = successful[0]["b64_json"]
if len(encoded) > ((MAX_IMAGE_BYTES + 2) // 3) * 4 + 8:
raise SystemExit("Encoded image exceeds the configured cap")
try:
image = base64.b64decode(encoded, validate=True)
except (binascii.Error, ValueError) as exc:
raise SystemExit("Image was not strict base64") from exc
if len(image) > MAX_IMAGE_BYTES:
raise SystemExit("Decoded image exceeds the configured cap")
if image.startswith(b"\x89PNG\r\n\x1a\n"):
suffix = ".png"
elif image.startswith(b"\xff\xd8\xff"):
suffix = ".jpg"
else:
raise SystemExit("Unexpected image signature")
out = pathlib.Path("seedream-output" + suffix)
atomic_write(out, image)
metadata = {
"created_unix": int(time.time()),
"model": document.get("model", model),
"request_sha256": hashlib.sha256(body).hexdigest(),
"artifact_sha256": hashlib.sha256(image).hexdigest(),
"declared_size": successful[0].get("size"),
"usage": document.get("usage"),
"watermark_requested": payload["watermark"],
}
atomic_write(
out.with_suffix(out.suffix + ".json"),
json.dumps(metadata, indent=2, ensure_ascii=False).encode("utf-8"),
)
print(out.resolve())
生产代码还应使用维护良好的图像库解码像素,限制宽度、高度和面积,扫描内容,使用原子写入,脱敏日志,并集成上述重试策略。
示例:多个参考图、分组输出和安全获取 URL
这个完整示例不会由此技能执行。它需要两个 BytePlus 可获取的 HTTPS 参考图 URL,以及一个由管理员维护、以逗号分隔的 SEEDREAM_ASSET_HOSTS 允许列表,该列表应根据服务提供商当前的资源域名生成。由于分组模式为 auto,模型返回的图像可能少于三张;程序会记录每项失败,并安全下载成功结果的 URL,且不会转发 API 令牌。
import hashlib
import ipaddress
import json
import os
import pathlib
import socket
import tempfile
import urllib.error
import urllib.parse
import urllib.request
API_BASE = "https://ark.ap-southeast.bytepluses.com/api/v3"
API_KEY = os.environ.get("ARK_API_KEY", "")
REF_1 = os.environ.get("SEEDREAM_REFERENCE_1", "https://example.invalid/reference-1")
REF_2 = os.environ.get("SEEDREAM_REFERENCE_2", "https://example.invalid/reference-2")
MAX_DOWNLOAD = 25 * 1024 * 1024
MAX_API_JSON = 8 * 1024 * 1024
ASSET_HOSTS = {
host.strip().lower()
for host in os.environ.get("SEEDREAM_ASSET_HOSTS", "").split(",")
if host.strip()
}
if not ASSET_HOSTS:
raise SystemExit("Set SEEDREAM_ASSET_HOSTS to approved provider artifact hostnames")
class NoRedirect(urllib.request.HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
def validate_artifact_url(url):
parsed = urllib.parse.urlsplit(url)
if (
parsed.scheme != "https" or parsed.hostname not in ASSET_HOSTS
or parsed.username or parsed.password or parsed.fragment
):
raise ValueError("Artifact URL is outside the approved HTTPS allowlist")
addresses = {
info[4][0] for info in socket.getaddrinfo(parsed.hostname, parsed.port or 443)
}
if not addresses or any(not ipaddress.ip_address(value).is_global for value in addresses):
raise ValueError("Artifact host did not resolve exclusively to public addresses")
def atomic_write(path, data):
path.parent.mkdir(parents=True, exist_ok=True)
handle, temporary = tempfile.mkstemp(dir=path.parent, prefix=".seedream-meta-")
try:
with os.fdopen(handle, "wb") as output:
output.write(data)
output.flush()
os.fsync(output.fileno())
os.replace(temporary, path)
except Exception:
try:
os.unlink(temporary)
except FileNotFoundError:
pass
raise
for ref in (REF_1, REF_2):
parsed = urllib.parse.urlsplit(ref)
if parsed.scheme != "https" or parsed.username or parsed.password:
raise SystemExit("References must be credential-free HTTPS URLs")
payload = {
"model": "seedream-5-0-260128",
"prompt": (
"Create exactly three coordinated campaign images. Preserve the product "
"shape and label from image 1. Use only the blue-and-amber palette and soft "
"paper texture from image 2. Frame 1: square hero. Frame 2: vertical detail. "
"Frame 3: wide environmental scene. Keep all label spelling unchanged."
),
"image": [REF_1, REF_2],
"size": "2K",
"sequential_image_generation": "auto",
"sequential_image_generation_options": {"max_images": 3},
"response_format": "url",
"output_format": "jpeg",
"watermark": True,
}
request = urllib.request.Request(
API_BASE + "/images/generations",
data=json.dumps(payload).encode("utf-8"),
method="POST",
headers={
"Authorization": "Bearer " + API_KEY,
"Content-Type": "application/json",
"Accept": "application/json",
},
)
print({
"model": payload["model"], "references": len(payload["image"]),
"max_images": payload["sequential_image_generation_options"]["max_images"],
"request_sha256": hashlib.sha256(json.dumps(payload, separators=(",", ":")).encode()).hexdigest(),
})
if os.environ.get("SEND_SEEDREAM_REQUEST") != "1":
raise SystemExit("Dry run only; set SEND_SEEDREAM_REQUEST=1 after approving the paid call")
if not API_KEY or "example.invalid" in {urllib.parse.urlsplit(REF_1).hostname, urllib.parse.urlsplit(REF_2).hostname}:
raise SystemExit("Set ARK_API_KEY and both SEEDREAM_REFERENCE environment variables")
try:
with urllib.request.urlopen(request, timeout=240) as response:
response_bytes = response.read(MAX_API_JSON + 1)
except urllib.error.HTTPError as exc:
raise SystemExit(f"Ark HTTP {exc.code}") from exc
if len(response_bytes) > MAX_API_JSON:
raise SystemExit("Grouped API response exceeded configured JSON cap")
try:
document = json.loads(response_bytes)
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
raise SystemExit("Grouped API response was not valid bounded JSON") from exc
def safe_download(url: str, destination: pathlib.Path) -> dict:
opener = urllib.request.build_opener(NoRedirect())
current = url
response = None
for _ in range(6):
validate_artifact_url(current)
# Deliberately no Authorization header here or on any redirect hop.
req = urllib.request.Request(current, headers={"Accept": "image/png,image/jpeg"})
try:
response = opener.open(req, timeout=90)
break
except urllib.error.HTTPError as exc:
if exc.code not in {301, 302, 303, 307, 308}:
raise
location = exc.headers.get("Location")
exc.close()
if not location:
raise ValueError("Artifact redirect omitted Location")
current = urllib.parse.urljoin(current, location)
else:
raise ValueError("Too many artifact redirects")
hasher = hashlib.sha256()
total = 0
prefix = b""
destination.parent.mkdir(parents=True, exist_ok=True)
with response:
content_type = response.headers.get_content_type()
if content_type not in {"image/png", "image/jpeg"}:
raise ValueError(f"Unexpected Content-Type: {content_type}")
declared = response.headers.get("Content-Length")
if declared and int(declared) > MAX_DOWNLOAD:
raise ValueError("Artifact exceeds byte cap")
fd, temporary = tempfile.mkstemp(dir=destination.parent, prefix=".seedream-")
try:
with os.fdopen(fd, "wb") as output:
while True:
chunk = response.read(64 * 1024)
if not chunk:
break
total += len(chunk)
if total > MAX_DOWNLOAD:
raise ValueError("Artifact exceeded byte cap while streaming")
if len(prefix) < 12:
prefix += chunk[: 12 - len(prefix)]
hasher.update(chunk)
output.write(chunk)
output.flush()
os.fsync(output.fileno())
is_png = prefix.startswith(b"\x89PNG\r\n\x1a\n")
is_jpeg = prefix.startswith(b"\xff\xd8\xff")
if not (is_png or is_jpeg):
raise ValueError("Unexpected artifact signature")
os.replace(temporary, destination)
except Exception:
try:
os.unlink(temporary)
except FileNotFoundError:
pass
raise
return {"bytes": total, "sha256": hasher.hexdigest(), "content_type": content_type}
if document.get("error"):
raise SystemExit(f"Ark error: {document['error']}")
manifest = {"model": document.get("model"), "usage": document.get("usage"), "items": []}
success_index = 0
for index, item in enumerate(document.get("data", [])):
if item.get("error"):
manifest["items"].append({"index": index, "error": item["error"]})
continue
if not item.get("url"):
manifest["items"].append({"index": index, "error": "missing url"})
continue
success_index += 1
path = pathlib.Path("seedream-set") / f"image-{success_index:02d}.jpg"
audit = safe_download(item["url"], path)
manifest["items"].append({"index": index, "path": str(path), **audit})
atomic_write(
pathlib.Path("seedream-set/manifest.json"),
json.dumps(manifest, indent=2, ensure_ascii=False).encode("utf-8"),
)
if success_index == 0:
raise SystemExit("No successful images")
print(f"Saved {success_index} image(s); review count, labels, and visual consistency")
示例:请求范围的 SSE
这个 curl 示例不会由此技能执行。它演示的是线路格式,而非生产环境中的解析方式。生产环境中应使用真正的 SSE 解析器,保留事件顺序,处理部分失败,并等待 image_generation.completed。
: "${ARK_API_KEY:?set ARK_API_KEY}"
: "${SEND_SEEDREAM_REQUEST:?set SEND_SEEDREAM_REQUEST=1 after approving the paid call}"
[ "${SEND_SEEDREAM_REQUEST}" = "1" ] || { echo 'Refusing paid call without SEND_SEEDREAM_REQUEST=1' >&2; exit 2; }
curl --fail-with-body --no-buffer \
--connect-timeout 10 --max-time 300 \
'https://ark.ap-southeast.bytepluses.com/api/v3/images/generations' \
-H "Authorization: Bearer ${ARK_API_KEY}" \
-H 'Content-Type: application/json' \
-H 'Accept: text/event-stream' \
--data-binary @- <<'JSON'
{
"model": "seedream-5-0-260128",
"prompt": "Create a three-frame horizontal storyboard of a paper airplane crossing a quiet library: establishing shot, close tracking shot, final landing. Consistent airplane and lighting in every frame.",
"size": "2K",
"sequential_image_generation": "auto",
"sequential_image_generation_options": {"max_images": 3},
"response_format": "url",
"stream": true,
"watermark": true
}
JSON
错误映射和可观测性
| 类别 | 常见的有文档记录的错误 | 操作 |
|---|---|---|
| 400 请求错误 | 参数无效或缺失、图像/base64/URL 无效、输入/输出安全、版权或隐私问题 | 不要盲目重试;修正输入或停止 |
| 401/403 | 身份验证、访问被拒绝、账户欠费、服务未开通、条款/访问问题 | 轮换/修复凭证或账户状态;不要将其作为暂时性错误重试 |
| 404 | 未找到模型/端点、模型访问已禁用 | 检查服务入口、区域、模型 ID、端点、生命周期和访问权限 |
| 429 | 模型/账户 IPM、RPM、TPM、端点限制、突发流量、配额、过载 | 排队、降低并发、遵循重试时机、使用带随机抖动的退避策略 |
| 500 | 内部服务错误 | 如果可以接受重复风险,则进行有限次数的重试;否则手动核对 |
记录尝试次数、状态/错误代码、限流类别、队列等待时间、服务提供商延迟、下载延迟、成功/失败图像数量、字节数、分辨率、模型、区域端点、联网搜索使用情况、预估和开票费用、审核结果以及审核人员的决定等指标。绝不要记录原始机密;尽量减少遥测中的原始提示词和源 URL。
成本和生命周期控制
价格波动较大。中国区定价页面在 2026-07-09 显示:4.0 每张成功生成的图像 ¥0.20,4.5 为 ¥0.25,5.0 Lite 为 ¥0.22,5.0 Pro 在不超过 2.36 MP 时为 ¥0.30,高于 2.36 MP 时为 ¥0.60。查阅的 BytePlus 官方页面显示,4.0 每张图像 US$0.03,4.5 每张图像 US$0.04;尚未确认当前 5.0 Lite 的全球公开价格。请重新核对账户控制台和官方价格页面,因为区域、合同、税费、套餐和促销活动都可能导致价格不同。
提交前,根据最大成功分组数和适用的分辨率档位估算费用上限。核对服务提供商返回的 usage 和账单,不要只依赖估算。文档说明,审核失败的输出不计费,而部分失败分组中的成功结果仍会计费。
固定使用带日期的模型 ID,订阅模型退役通知,并维护一套黄金迁移测试集。当前目录和 API 页面是判断可用性的权威来源;不要根据产品名称推断生命周期。别名行为可能会变化。请将任何旧版 3.0 seed 工作流视为迁移项目,不要将旧版参数沿用到 4.0/5.0。
隐私、权利与安全门槛
BytePlus 当前的 Model Service 条款规定,未经单独同意,不会使用输入和输出训练基础模型,且 BytePlus 不主张拥有输出的所有权。条款还指出,输出可能并非独一无二,BytePlus、关联方及第三方持有的权利仍归其所有;客户仍需对输入、输出、适用法律及权利清理负责。这并不保证输出具备版权资格、独占性、不侵权、准确或安全。
BytePlus 的数据处理页面说明,处理活动可能发生在马来西亚、印度尼西亚和/或欧盟/欧洲经济区,并指出触发安全过滤器的内容可能会在马来西亚保留 180 天。该保留期限与 24 小时的生成图像 URL 有所不同。请根据实际合同确认当前的 DPA、子处理方所在地、加密选项、删除机制和支持承诺。
生成和发布前:
- 获取源图像、商标、受版权保护的角色、私人数据、面孔、肖像及涉及生物特征敏感用途的许可/同意;
- 禁止性剥削、虐待未成年人、未经同意的私密影像、欺骗性冒充、欺诈、非法监视/身份识别、仇恨/极端主义、鼓励自残及其他不允许的内容;
- 不得绕过安全系统,也不得移除/遮挡必要的凭证、水印、元数据或披露信息;
- 在法律、平台政策或具体情境要求时,为 AI 生成的材料添加标注,即使技术上使用了
watermark: false也不例外; - 对事实声明、排版文字、肖像、医疗/法律/财务影响、选举/公共事务及重大影响用途,必须进行人工审核;
- 保存来源记录;在审核过的图像 API 合同中,未发现普遍适用的 C2PA 保证。
在适用的 Model Service 条款禁止的情况下,不得使用该模型或其输出训练或改进其他模型。请咨询法律顾问,获取针对具体司法管辖区和合同的建议。
第一方来源
核查日期:2026-07-09:
- Volcengine Ark 图像生成 API:https://www.volcengine.com/docs/82379/1541523
- Volcengine Ark 当前模型目录:https://www.volcengine.com/docs/82379/1330310
- Volcengine Ark Seedream 4.0–5.0 提示词指南:https://www.volcengine.com/docs/82379/1829186
- Volcengine Ark 流式响应规范:https://www.volcengine.com/docs/82379/1824137
- Volcengine Ark 错误代码:https://docs.volcengine.com/docs/82379/1299023?lang=zh
- Volcengine Ark 定价:https://docs.volcengine.com/docs/82379/1544106?lang=zh
- Volcengine Ark 模型退役通知:https://docs.volcengine.com/docs/82379/1350667?lang=zh
- BytePlus ModelArk 图像生成 API:https://docs.byteplus.com/en/docs/ModelArk/1541523
- BytePlus Seedream 图像教程/能力矩阵:https://docs.byteplus.com/en/docs/ModelArk/1824121
- BytePlus ModelArk 区域可用性:https://docs.byteplus.com/api/docs/modelark/2191806
- BytePlus 国际可用性限制:https://docs.byteplus.com/en/docs/ModelArk/availability?TimeBefore=1757476852
- BytePlus ModelArk 数据处理:https://docs.byteplus.com/api/docs/ModelArk/BytePlus_ModelArk_Data_Processing
- BytePlus 特定服务条款(包括 Model Services):https://docs.byteplus.com/en/docs/legal/docs-service-specific-terms
- BytePlus GenAI 可接受使用政策:https://docs.byteplus.com/en/docs/legal/acceptable_use_policy_byteplus_genai
- ByteDance Seed Seedream 5.0 Lite 产品页面:https://seed.bytedance.com/en/seedream5_0_lite
- ByteDance Seed Seedream 5.0 Lite 发布文章:https://seed.bytedance.com/en/blog/deeper-thinking-more-accurate-generation-introducing-seedream-5-0-lite
- ByteDance Seed Seedream 4.0 产品页面:https://seed.bytedance.com/en/seedream4_0
已知缺口
经审阅的第一方图像 API 页面未明确说明幂等键、异步图像任务/轮询/Webhook 契约、当前系列模型的确定性种子、通用的数据驻留保证、通用的 C2PA 输出,或公开的 BytePlus 5.0 Lite 当前价格。请勿声称具备这些能力。若有需要,请重新查阅文档或获取提供商的书面答复。