Guanghu Domestic Migration a2fa7d57d8 chore: import sanitized domestic snapshot for REPO-005
Source snapshot: 23037fa3a2e9b0597162735755e92fc763bf4d94
2026-07-17 15:55:48 +08:00

137 lines
4.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# LIB · Seedream 3/4/5 适配器
# D181 · 2026-07-10 · 默认模型: Seedream 3.0 (轻量,便宜)
"""火山方舟 ARK API → Seedream 系列 文生图/图生图"""
import json
import os
import urllib.request
import base64
from lib.secrets import get_ark_key
ARK_KEY = get_ark_key()
ARK_BASE = "https://ark.cn-beijing.volces.com/api/v3"
# 模型配置
# 模型配置ARK端点上实际可用的模型
SEEDREAM_3 = "doubao-seedream-4-0-250828" # Seedream 4.0 (最便宜可用)
SEEDREAM_4 = "doubao-seedream-4-0-250828" # 同上
SEEDREAM_4_5 = "doubao-seedream-4-5-251128" # Seedream 4.5
SEEDREAM_5 = "doubao-seedream-5-0-260128" # Seedream 5.0
SEEDREAM_5_PRO = "doubao-seedream-5-0-pro-260628" # Seedream 5.0 Pro
SEEDREAM_MODEL = SEEDREAM_3 # 默认模型
SEEDREAM_MODEL = SEEDREAM_3 # 默认模型 (爸爸指定用便宜的)
# 尺寸约束
SIZES = {
SEEDREAM_3: ["1024x1024", "1024x768", "768x1024"],
SEEDREAM_4: ["1664x936", "936x1664", "1024x1024"],
}
DEFAULT_SIZE = "1024x1024" # 即梦3默认方图
def _api_call(endpoint, payload):
"""通用 ARK API 调用"""
req = urllib.request.Request(
f"{ARK_BASE}{endpoint}",
data=json.dumps(payload).encode(),
headers={
"Authorization": f"Bearer {ARK_KEY}",
"Content-Type": "application/json"
},
method="POST"
)
try:
with urllib.request.urlopen(req, timeout=30) as resp:
return json.loads(resp.read())
except urllib.error.HTTPError as e:
err_body = e.read().decode()
return {"error": str(e.code), "detail": err_body}
def seedream_t2i(prompt, size=DEFAULT_SIZE, n=1, model=SEEDREAM_MODEL):
"""文生图
prompt: 中英文提示词
size: "1024x1024" (即梦3) / "1664x936" (即梦4)
model: SEEDREAM_3 (默认) / SEEDREAM_4
"""
# 即梦3不支持 n>1
if model == SEEDREAM_3 and n > 1:
import warnings
warnings.warn("即梦3.0 不支持 n>1已固定为 n=1")
n = 1
payload = {
"model": model,
"prompt": prompt,
"size": size,
"n": n
}
return _api_call("/images/generations", payload)
def seedream_i2i(prompt, image_path, size=DEFAULT_SIZE, n=1, model=SEEDREAM_MODEL):
"""图生图 · 即梦3.0 图生图 (seededit-3.0)"""
if model == SEEDREAM_3:
# 即梦3图生图用 seededit-3.0
model = "seededit-3.0"
with open(image_path, "rb") as f:
img_b64 = base64.b64encode(f.read()).decode()
payload = {
"model": model,
"prompt": prompt,
"image": f"data:image/jpeg;base64,{img_b64}",
"size": size,
"n": 1 # 图生图只支持单张
}
return _api_call("/images/generations", payload)
def seedream_multi(prompt, image_paths, size=DEFAULT_SIZE, n=1, model=SEEDREAM_MODEL):
"""多图融合 · 仅即梦4支持"""
if model == SEEDREAM_3:
raise RuntimeError("多图融合仅即梦4.0支持,请使用 model=SEEDREAM_4")
imgs = []
for p in image_paths:
with open(p, "rb") as f:
fmt = "png" if p.endswith(".png") else "jpeg"
imgs.append(f"data:image/{fmt};base64,{base64.b64encode(f.read()).decode()}")
payload = {
"model": model,
"prompt": prompt,
"image": imgs,
"size": size,
"n": n
}
return _api_call("/images/generations", payload)
def seedream_download(result, output_path):
"""从 API 结果下载图片"""
if "error" in result:
return None
url = result.get("data", [{}])[0].get("url")
if not url:
return None
urllib.request.urlretrieve(url, output_path)
return output_path
# ====== CLI ======
if __name__ == "__main__":
import sys
if len(sys.argv) < 2:
print("Usage: python seedream.py t2i <prompt> [output] [--model 3|4] [--size WxH]")
print(" python seedream.py i2i <prompt> <image_path> [output] [--model 3|4]")
print(" python seedream.py multi <prompt> <img1> <img2> [output]")
print(f" Default model: {SEEDREAM_MODEL} (即梦3.0 · ¥0.2/张)")
sys.exit(1)
cmd = sys.argv[1]
if cmd == "t2i":
prompt = sys.argv[2]
out = sys.argv[3] if len(sys.argv) > 3 else "seedream_output.jpg"
r = seedream_t2i(prompt)
p = seedream_download(r, out)
print(f"{p}" if p else f"{r.get('error','unknown')}")
elif cmd == "i2i":
prompt, img, out = sys.argv[2], sys.argv[3], (sys.argv[4] if len(sys.argv) > 4 else "seedream_i2i_output.jpg")
r = seedream_i2i(prompt, img)
p = seedream_download(r, out)
print(f"{p}" if p else f"{r.get('error','unknown')}")
elif cmd == "multi":
prompt, imgs, out = sys.argv[2], sys.argv[3:-1], sys.argv[-1]
r = seedream_multi(prompt, imgs)
p = seedream_download(r, out)
print(f"{p}" if p else f"{r.get('error','unknown')}")