星辰TokenHub 图片生成
概述
通过天翼云 AI 网关(https://ai.ctaigw.cn)调用豆包 Seedream 系列模型,执行文生图、图生图、图层拆分三种图片生成操作。API Key 通过环境变量 XING_CHEN_TOKENHUB 读取,不打包 .env 文件,适合分享分发。
> 模型策略:不指定模型时默认使用 5.0-lite(Doubao-Seedream-5.0-lite);用户指定了模型则使用指定模型。
快速开始
0. 前置条件
设置环境变量 XING_CHEN_TOKENHUB 为你的星辰TokenHub API Key(首次使用时提示用户提供):
# PowerShell(当前会话)
$env:XING_CHEN_TOKENHUB = "your_api_key"
# CMD(当前会话)
set XING_CHEN_TOKENHUB=your_api_key
# Linux / macOS
export XING_CHEN_TOKENHUB="your_api_key"
API Key 获取方式:登录星辰TokenHub控制台 → 模型服务 → 服务接入 → 创建服务组 → 选择服务 → 获取APIKey。
1. 文生图
python scripts/generate_image.py --prompt "星际穿越,黑洞" --size 2K --output result.jpg
2. 图生图
python scripts/generate_image.py --prompt "狗狗趴在草地上" --image-url "https://example.com/ref.png" --mode img2img --output edited.jpg
3. 图层拆分
python scripts/generate_image.py --image-url "https://example.com/image.png" --mode layer --output layers
模型选择
> 模型策略:不指定 --model 时默认 5.0-lite;指定了则用指定模型。
| 别名 | 完整模型名 | 适用场景 |
|---|---|---|
5.0-pro |
doubao-seedream-5.0-pro | 最高画质,复杂场景 |
4.5 |
doubao-seedream-4.5 | 上代旗舰,兼容性好 |
5.0-lite |
Doubao-Seedream-5.0-lite | 轻量快速,批量生成(默认) |
4.0 |
doubao-seedream-4.0 | 基础版,成本最低 |
脚本参数
scripts/generate_image.py 支持以下参数:
| 参数 | 说明 | 默认值 |
|---|---|---|
--prompt |
提示词(文生图/图生图必填) | - |
--model |
模型别名或完整名(不指定时默认 5.0-lite) | 5.0-lite |
--size |
尺寸:2K/3K/4K 或 WxH 像素 | 2K |
--mode |
模式:text2img / img2img / layer | text2img |
--image-url |
参考图 URL(图生图/图层拆分必填) | - |
--response-format |
返回格式:url / b64_json | url |
--no-watermark |
关闭水印 | false |
--output / -o |
输出文件路径 | generated_<timestamp>.jpg |
--timeout |
请求超时秒数 | 120 |
--dry-run |
只打印参数不调用 API | false |
工作流程
- 确认模式: 根据用户需求选择 text2img / img2img / layer
- 选择模型: 不指定模型时默认
5.0-lite(轻量快速);用户指定模型则使用指定模型(高画质用5.0-pro,控制成本用4.0) - 构造提示词: 编写详细描述性提示词,包含风格、构图、色彩、光影等要素
- 执行脚本: 运行
generate_image.py并传入参数 - 保存图片: 脚本自动下载 URL 返回的图片到本地,同时保存同名 .txt 文件记录提示词,形成可复用示例(xx.jpg + xx.txt)
- 直接交付: 脚本执行成功后直接告知用户图片路径,不需要对生成的图片做视觉校验
- 图片展示页(可选): 如果工作目录中图片数量≥10张,生成一个卡片式 HTML 展示页(见下方「图片展示页」章节)
交付策略
- 生成成功后直接告知用户图片路径,不做图片视觉校验,不调用 image_understanding 等工具验证图片内容
- 信任 API 返回结果,只要脚本输出「调用成功」即视为完成
- 如用户主动要求检查图片效果,再按需校验
图片展示页
当工作目录中图片数量≥10张时,生成一个自包含的卡片式 HTML 单页用于展示所有图片。
生成条件
- 工作目录根目录下的图片文件(.jpg/.jpeg/.png/.webp)数量≥10张
- 图片可能来自多次生图任务的积累,也包括本次刚生成的
HTML 要求
- 自包含单文件:所有 CSS/JS 内联,图片用相对路径引用本地文件,不依赖外部资源
- 卡片式布局:CSS Grid 响应式布局,每张图片一张卡片,包含缩略图 + 文件名 + 同名 .txt 中的提示词摘要(截取前80字)
- 点击放大:点击卡片可弹出全尺寸图片查看,再次点击关闭
- 配色:根据内容主题选用贴合的配色方案,不默认使用电信色系
- 文件名:
gallery.html,保存在工作目录根目录 - 排序:按文件修改时间倒序排列(最新的在最前)
HTML 模板结构
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>AI 图片画廊</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, 'Microsoft YaHei', sans-serif; background: #0f0f1a; color: #e0e0e0; }
.header { text-align: center; padding: 40px 20px 20px; }
.header h1 { font-size: 28px; color: #fff; }
.header p { margin-top: 8px; color: #888; font-size: 14px; }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 20px; padding: 20px; max-width: 1400px; margin: 0 auto; }
.card { background: #1a1a2e; border-radius: 12px; overflow: hidden; transition: transform 0.2s, box-shadow 0.2s; cursor: pointer; }
.card:hover { transform: translateY(-4px); box-shadow: 0 8px 24px rgba(0,0,0,0.4); }
.card img { width: 100%; aspect-ratio: 1; object-fit: cover; display: block; }
.card .info { padding: 12px 16px; }
.card .name { font-size: 14px; color: #ccc; margin-bottom: 6px; word-break: break-all; }
.card .prompt { font-size: 12px; color: #777; line-height: 1.5; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.lightbox { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.9); z-index: 999; justify-content: center; align-items: center; cursor: pointer; }
.lightbox.show { display: flex; }
.lightbox img { max-width: 90%; max-height: 90%; object-fit: contain; border-radius: 8px; }
</style>
</head>
<body>
<div class="header">
<h1>AI 图片画廊</h1>
<p>共 N 张图片 · 点击图片可放大查看</p>
</div>
<div class="grid">
<!-- 对每张图片生成一个 card -->
<div class="card" onclick="openLightbox('图片路径')">
<img src="图片路径" alt="文件名" loading="lazy">
<div class="info">
<div class="name">文件名</div>
<div class="prompt">提示词摘要(截取同名 .txt 前80字,无 .txt 则留空)</div>
</div>
</div>
<!-- ... 重复每张图 ... -->
</div>
<div class="lightbox" id="lightbox" onclick="this.classList.remove('show')">
<img id="lightbox-img" src="" alt="">
</div>
<script>
function openLightbox(src) {
document.getElementById('lightbox-img').src = src;
document.getElementById('lightbox').classList.add('show');
}
</script>
</body>
</html>
生成方式
无需脚本,直接由智能体根据工作目录中的图片文件列表和同名 .txt 内容,用 Write 工具生成 gallery.html。生成后告知用户文件路径。
提示词技巧
- 用逗号分隔的关键词效果优于长句
- 包含维度:主体、场景、风格、光影、色彩、构图视角、渲染方式
- 中文提示词效果良好,混合中英文也可
- 示例:
星际穿越,黑洞,复古列车,电影大片,末日既视感,动感,对比色,oc渲染,光线追踪,动态模糊,景深,超现实主义,深蓝,质感真实,暗黑风背景
API 参考文档
完整 API 参数说明、请求/响应示例详见 references/api_docs.md。
安全说明
- API Key 通过环境变量
XING_CHEN_TOKENHUB读取,不硬编码在代码中,不打包 .env 文件 - 分享技能时需提示接收方自行设置
XING_CHEN_TOKENHUB环境变量 - 脚本使用 Python 标准库(
urllib),零额外依赖
踩坑记录
模型名大小写敏感
星辰TokenHub API 对模型名大小写敏感。5.0-lite 模型的正确写法只有两种:Doubao-Seedream-5.0-lite(D 和 S 大写)和 doubao-seedream-5.0-lite(全小写)。其他变体如 doubao-Seedream-5.0-lite(中间 S 大写)或 Doubao-seedream-5.0-lite(中间 s 小写)均返回 HTTP 404 model_not_found。脚本中 SUPPORTED_MODELS 别名表已使用正确写法,直接传别名即可避免此问题。
输出路径自动补后缀
当 --output 指定的路径没有图片后缀(如 .jpg/.png)时,脚本自动补 .jpg。同时生成同名 .txt 文件保存提示词,形成可复用示例对(xx.jpg + xx.txt)。
图片像素面积上限
API 限制单张图片面积最多 4,624,220 像素。常见 2:3 竖幅尺寸 1800×2700 = 4,860,000 像素会超限,返回 HTTP 400 InvalidParameter(image area must be at most 4624220 pixels)。2:3 竖幅安全尺寸为 1700×2550(4,335,000 像素)。
> 2:3 竖幅快速查表:1700×2550 ✅ | 1800×2700 ❌
自定义尺寸时,确保 宽 × 高 ≤ 4,624,220。常见比例安全尺寸参考:
| 比例 | 安全尺寸 | 像素数 |
|---|---|---|
| 2:3 竖幅 | 1700×2550 | 4,335,000 |
| 3:2 横幅 | 2550×1700 | 4,335,000 |
| 1:1 方幅 | 2140×2140 | 4,579,600 |
| 9:16 竖幅 | 1620×2880 | 4,665,600 ❌ → 用 1600×2844 = 4,550,400 |
图生图本地参考图需转 data URL
--image-url 参数只接受 URL 或 data:image/...;base64,... 格式的 data URL,不支持本地文件路径。使用本地图片做参考图时,需先将图片读取为 base64 并拼接成 data URL 传入。裸 base64 字符串(不带 data:image/jpeg;base64, 前缀)会被 API 拒绝。
由于 base64 字符串可能很长,直接通过命令行 --image-url 传参不安全(可能超出命令行长度限制)。推荐写临时 Python 脚本处理:
import base64
with open("本地图片路径", "rb") as f:
b64 = base64.b64encode(f.read()).decode("ascii")
image_data_url = f"data:image/jpeg;base64,{b64}"
# 然后将 image_data_url 作为 API 请求体中的 image 参数传入
生成完成后删除临时脚本即可。
并行多 prompt 生成的文件映射确认
当用不同提示词并行生成多张图片时(如一次发 8 个不同 prompt 各生成 1 张),返回的文件路径中时间戳可能因并行执行而交错,无法仅凭返回顺序判断哪张图对应哪个 prompt。
正确做法:生成后用 image_understanding 逐张确认内容,再按确认结果重命名或归类。注意这与「交付策略」中的「不做视觉校验」不矛盾——交付策略针对单张生成时信任 API 画质;此处针对多 prompt 并行时的文件身份识别,属于必要的映射确认。
示例:生成 8 个不同动物的甲骨文象形文字,8 次调用并行返回,时间戳 141310/141309/141307/141302 交错排列,无法靠顺序判断。用 image_understanding 逐张问"这是什么动物"后确认映射,再重命名为 glyph-ma.jpg / glyph-hu.jpg 等。