初始发布: 21 个 skills (Claude Code / Codex / DSH)
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
---
|
||||
name: glm-image
|
||||
description: 调用智谱 GLM-Image 文生图模型生成图片。触发关键词:「生图」「生成图片」「画一张」「GLM生图」「文生图」「画海报」「出图」「生成插画」「AI画图」「做一张图」。适用场景:商业海报、科普插画、多格图画、社交媒体图文、人像、文字密集型图像(GLM-Image 擅长图中文字渲染)。调用脚本 generate.py 生成并下载图片到本地。
|
||||
version: 1.0.0
|
||||
author: william
|
||||
---
|
||||
|
||||
# GLM-Image 文生图 Skill
|
||||
|
||||
调用智谱 **GLM-Image** 模型(`glm-image`)从文本提示词生成图片并下载到本地。
|
||||
|
||||
## 触发判断
|
||||
|
||||
用户说"画一张…"、"生成图片"、"帮我生图"、"做一张海报/插画/封面"、"GLM 生图"、"文生图"等 → 立即按下方流程执行。
|
||||
|
||||
## 调用方式
|
||||
|
||||
**入口脚本**:`~/.claude/skills/glm-image/generate.py`(Python 3 标准库,无需安装依赖)
|
||||
|
||||
### 基本调用
|
||||
|
||||
```bash
|
||||
python3 ~/.claude/skills/glm-image/generate.py "提示词" -s 1280x1280
|
||||
```
|
||||
|
||||
### 参数
|
||||
|
||||
| 参数 | 说明 | 默认 |
|
||||
|------|------|------|
|
||||
| `prompt`(位置参数) | 生成提示词,最多 1000 字符 | 必填 |
|
||||
| `-s, --size` | 图片尺寸 `WxH` | `1280x1280` |
|
||||
| `-o, --output` | 输出文件路径 | `glm-image-<时间戳>.png` |
|
||||
| `--open` | 生成后在 Finder 打开 | 否 |
|
||||
| `--json` | 同时打印完整 JSON 返回 | 否 |
|
||||
| `--no-download` | 只返回图片 URL,不下载 | 否 |
|
||||
|
||||
### API Key
|
||||
|
||||
- 优先读环境变量 `GLM_API_KEY`
|
||||
- 未设置时使用脚本内置默认 key
|
||||
- 如需切换:`export GLM_API_KEY=<新key>`
|
||||
|
||||
## 尺寸规则
|
||||
|
||||
- **推荐尺寸**(直接套用):
|
||||
`1280x1280` · `1568x1056` · `1056x1568` · `1472x1088` · `1088x1472` · `1728x960` · `960x1728`
|
||||
分别对应 1:1 / 3:2 / 2:3 / 4:3 / 3:4 / 16:9 / 9:16
|
||||
- **自定义尺寸**:长宽均需在 **512px–2048px** 范围内,且为 **32 的整数倍**,否则脚本会报错退出
|
||||
- 选尺寸看用途:海报/竖版用 `1056x1568`,横版封面用 `1568x1056`,头像/方图用 `1280x1280`,社交媒体横幅用 `1728x960`
|
||||
|
||||
## 工作流
|
||||
|
||||
1. **理解需求**:从用户描述提炼画面主体、风格、构图、色调、文字内容
|
||||
2. **选尺寸**:根据用途从「推荐尺寸」中选;用户未指定默认 `1280x1280`
|
||||
3. **写提示词**:参考下方「提示词写法」,越具体越好;如需图中出现文字,把文字内容用「」或""引起来明确告诉模型
|
||||
4. **调用脚本**:执行 `generate.py`,确认返回的本地文件路径
|
||||
5. **展示结果**:用 `open` 命令打开图片,或在对话中告知文件路径;如效果不理想,根据反馈调整提示词重生成
|
||||
|
||||
### 示例
|
||||
|
||||
```bash
|
||||
# 商业海报(竖版)
|
||||
python3 ~/.claude/skills/glm-image/generate.py \
|
||||
"暗黑艺术感品牌海报:低饱和深灰背景,主体两匹写实马(左白右黑),头部被红黑格纹丝巾蒙眼;右上角白色骑士 logo,底部大号白色无衬线字体「BURBERRY」;柔和人像光,高级时尚品牌风" \
|
||||
-s 1056x1568 --open
|
||||
|
||||
# 人像特写
|
||||
python3 ~/.claude/skills/glm-image/generate.py \
|
||||
"哈苏胶片质感,长发美女置身柔和室内光影,窗外枝叶摇曳投射斑驳树影到脸庞肩头,薄纱朦胧,轮廓光勾勒慵懒姿态,近景特写凝望镜头,清透肌肤高明暗对比,背景略微模糊,高噪点胶片色彩" \
|
||||
-s 1280x1280 -o portrait.png
|
||||
|
||||
# 社交媒体图文
|
||||
python3 ~/.claude/skills/glm-image/generate.py \
|
||||
"冬季 OOTD 穿搭封面,复古拼贴风:主体女生冬季搭配,周围拼贴 2-3 张同系列小图;浅灰方格墙面+街景背景;大尺寸浅蓝艺术字「OOTD」,手写标注「autumn/win」" \
|
||||
-s 1568x1056
|
||||
```
|
||||
|
||||
## 提示词写法(GLM-Image 特性)
|
||||
|
||||
GLM-Image 采用「自回归+扩散解码器」混合架构,**擅长文字密集型生成**(海报/PPT/科普图中的文字渲染准确率高)。写提示词要点:
|
||||
|
||||
1. **结构化描述**:按「整体风格 → 主体 → 背景 → 文字内容 → 光影色调 → 氛围」顺序写,每项展开细节
|
||||
2. **文字明确标注**:要出现在图中的文字,用「」或""引起来,并说明字体风格(粗黑体/手写/无衬线)和位置(顶部横幅/底部通栏/左上角)
|
||||
3. **指定材质质感**:胶片质感、水彩晕染、撕裂纸边、和纸胶带、金属边等具体材质词能显著提升表现
|
||||
4. **构图说明**:竖版/横版、近景特写/全景、元素拼贴位置(左/右/底部散落)
|
||||
5. **色彩与光影**:低饱和暗调、高明暗对比、轮廓光、柔和人像光等
|
||||
|
||||
## 价格与限制
|
||||
|
||||
- 价格:0.1 元 / 次
|
||||
- 输入:纯文本,最大 1000 字符
|
||||
- 输出:图片 URL(脚本会自动下载为本地 PNG)
|
||||
- URL 有时效性,**务必下载到本地**,不要只记 URL
|
||||
|
||||
## 注意
|
||||
|
||||
- 脚本用 Python 3 标准库(urllib),无需 pip install 任何包
|
||||
- 生成通常 10–30 秒,脚本默认超时 120s
|
||||
- 下载的图片为 PNG 格式(按 URL 实际内容)
|
||||
- 如果调用报 `HTTP 401` → API Key 失效,让用户更新 `GLM_API_KEY`
|
||||
- 如果报 size 校验错 → 改用「推荐尺寸」之一
|
||||
Executable
+149
@@ -0,0 +1,149 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""GLM-Image 文生图调用脚本(智谱 GLM-Image 模型)。
|
||||
|
||||
用法:
|
||||
python3 generate.py "提示词" [-s SIZE] [-o OUTPUT] [--open] [--json]
|
||||
|
||||
示例:
|
||||
python3 generate.py "一只可爱的小猫咪,坐在阳光明媚的窗台上" -s 1280x1280
|
||||
python3 generate.py "商业海报:新品上市" -s 1056x1568 -o poster.png --open
|
||||
|
||||
默认 size=1280x1280,输出到当前目录 glm-image-<时间戳>.png
|
||||
API Key 优先读环境变量 GLM_API_KEY,否则用内置默认 key。
|
||||
"""
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
|
||||
API_ENDPOINT = "https://open.bigmodel.cn/api/paas/v4/images/generations"
|
||||
DEFAULT_KEY = "" # 服务器版不含内置 key,请设置环境变量 GLM_API_KEY
|
||||
|
||||
RECOMMENDED_SIZES = [
|
||||
"1280x1280", "1568x1056", "1056x1568",
|
||||
"1472x1088", "1088x1472", "1728x960", "960x1728",
|
||||
]
|
||||
|
||||
|
||||
def parse_size(size):
|
||||
"""校验 size,返回 (w, h)。规则:512-2048,且为 32 的整数倍。"""
|
||||
try:
|
||||
w, h = size.lower().split("x")
|
||||
w, h = int(w), int(h)
|
||||
except ValueError:
|
||||
raise ValueError(f"size 格式错误:'{size}',应为 WxH,如 1280x1280")
|
||||
for v, name in ((w, "宽"), (h, "高")):
|
||||
if v < 512 or v > 2048:
|
||||
raise ValueError(f"{name}={v} 不在 512-2048 范围内")
|
||||
if v % 32 != 0:
|
||||
raise ValueError(f"{name}={v} 不是 32 的整数倍")
|
||||
return w, h
|
||||
|
||||
|
||||
def generate(prompt, size="1280x1280", api_key=None, timeout=120, watermark=True):
|
||||
"""调用 GLM-Image 接口,返回图片 URL。
|
||||
|
||||
watermark=False 关闭 AI 水印,需账号已在「个人中心-安全管理-去水印管理」签署免责声明。
|
||||
"""
|
||||
parse_size(size) # 校验
|
||||
key = api_key or os.environ.get("GLM_API_KEY") or DEFAULT_KEY
|
||||
payload = {
|
||||
"model": "glm-image",
|
||||
"prompt": prompt,
|
||||
"size": size,
|
||||
"watermark_enabled": watermark,
|
||||
}
|
||||
data = json.dumps(payload).encode("utf-8")
|
||||
req = urllib.request.Request(
|
||||
API_ENDPOINT,
|
||||
data=data,
|
||||
headers={
|
||||
"Authorization": f"Bearer {key}",
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json",
|
||||
},
|
||||
method="POST",
|
||||
)
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=timeout) as resp:
|
||||
body = resp.read().decode("utf-8")
|
||||
except urllib.error.HTTPError as e:
|
||||
err = e.read().decode("utf-8", errors="replace")
|
||||
raise RuntimeError(f"HTTP {e.code}: {err}") from None
|
||||
except urllib.error.URLError as e:
|
||||
raise RuntimeError(f"网络错误: {e.reason}") from None
|
||||
|
||||
obj = json.loads(body)
|
||||
if not obj.get("data"):
|
||||
raise RuntimeError(f"返回无 data 字段: {body}")
|
||||
url = obj["data"][0].get("url")
|
||||
if not url:
|
||||
raise RuntimeError(f"返回无 url: {body}")
|
||||
return url, obj
|
||||
|
||||
|
||||
def download(url, output):
|
||||
"""下载图片 URL 到 output,返回输出路径。"""
|
||||
with urllib.request.urlopen(url, timeout=120) as resp:
|
||||
content = resp.read()
|
||||
with open(output, "wb") as f:
|
||||
f.write(content)
|
||||
return output
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description="GLM-Image 文生图")
|
||||
ap.add_argument("prompt", help="生成提示词(最多 1000 字符)")
|
||||
ap.add_argument("-s", "--size", default="1280x1280",
|
||||
help=f"图片尺寸 WxH(默认 1280x1280)。推荐: {', '.join(RECOMMENDED_SIZES)}")
|
||||
ap.add_argument("-o", "--output", default=None,
|
||||
help="输出文件路径(默认 glm-image-<时间戳>.png)")
|
||||
ap.add_argument("--open", action="store_true", help="生成后在 Finder 中打开")
|
||||
ap.add_argument("--json", action="store_true", help="打印完整 JSON 返回")
|
||||
ap.add_argument("--no-download", action="store_true", help="只返回 URL,不下载")
|
||||
ap.add_argument("--no-watermark", action="store_true",
|
||||
help="关闭 AI 水印(需账号已在「个人中心-安全管理-去水印管理」签署免责声明)")
|
||||
args = ap.parse_args()
|
||||
|
||||
if len(args.prompt) > 1000:
|
||||
sys.exit(f"错误: 提示词 {len(args.prompt)} 字符,超过 1000 上限")
|
||||
|
||||
try:
|
||||
parse_size(args.size)
|
||||
except ValueError as e:
|
||||
sys.exit(f"错误: {e}")
|
||||
|
||||
print(f"→ 调用 GLM-Image(size={args.size}, watermark={'off' if args.no_watermark else 'on'})...", file=sys.stderr)
|
||||
t0 = time.time()
|
||||
try:
|
||||
url, obj = generate(args.prompt, args.size, watermark=not args.no_watermark)
|
||||
except RuntimeError as e:
|
||||
sys.exit(f"错误: {e}")
|
||||
elapsed = time.time() - t0
|
||||
print(f"✓ 生成成功({elapsed:.1f}s): {url}", file=sys.stderr)
|
||||
|
||||
if args.json:
|
||||
print(json.dumps(obj, ensure_ascii=False, indent=2))
|
||||
|
||||
if args.no_download:
|
||||
print(url)
|
||||
return
|
||||
|
||||
output = args.output or f"glm-image-{int(time.time())}.png"
|
||||
try:
|
||||
download(url, output)
|
||||
except Exception as e:
|
||||
sys.exit(f"下载失败: {e}\n图片 URL: {url}")
|
||||
print(f"✓ 已保存: {output}", file=sys.stderr)
|
||||
print(output)
|
||||
|
||||
if args.open:
|
||||
os.system(f'open "{output}"')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user