Skill: stanleychanh/aliyun-image (version 1.1.0)

--- name: aliyun-image description: "阿里云百炼图像生成、编辑与翻译。文生图：根据文本生成图像，支持复杂文字渲染。图像编辑：单图编辑、多图融合、风格迁移、物体增删。图像翻译：翻译图像中的文字，保留原始排版，支持11种源语言和14种目标语言。触发词：生成图片、AI作画、文生图、图像编辑、修图、换背景、风格迁移、多图融合、图像翻译、图片翻译。模型：qwen-image-plus(默认)、qwen-image-max、qwen-image-edit-plus(默认)、qwen-image-edit-max、qwen-mt-image。" metadata: { "openclaw": { "repository": "https://github.com/StanleyChanH/aliyun-image-skill", "clawhub": "https://clawhub.com/skill/aliyun-image", "sync": "GitHub 和 ClawHub 同步更新" } } --- # 阿里云百炼图像生成与编辑 > 🔄 **同步更新**：本项目在 [GitHub](https://github.com/StanleyChanH/aliyun-image-skill) 和 [ClawHub](https://clawhub.com/skill/aliyun-image) 同步发布。 ## 快速开始 ### 前提条件 ```bash # 配置 API Key export DASHSCOPE_API_KEY="sk-xxxx" ``` ### 文生图 ```python import os, requests resp = requests.post( "https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation", headers={"Authorization": f"Bearer {os.getenv('DASHSCOPE_API_KEY')}"}, json={ "model": "qwen-image-plus", "input": {"messages": [{"role": "user", "content": [{"text": "一只橘猫在阳光下打盹"}]}]}, "parameters": {"prompt_extend": True, "watermark": False} } ) print(resp.json()["output"]["choices"][0]["message"]["content"][0]["image"]) ``` ### 图像编辑 ```python resp = requests.post( "https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation", headers={"Authorization": f"Bearer {os.getenv('DASHSCOPE_API_KEY')}"}, json={ "model": "qwen-image-edit-plus", "input": {"messages": [{"role": "user", "content": [ {"image": "https://example.com/photo.jpg"}, {"text": "把背景换成星空"} ]}]}, "parameters": {"prompt_extend": True, "watermark": False} } ) print(resp.json()["output"]["choices"][0]["message"]["content"][0]["image"]) ``` ### 图像翻译 ```python import os, requests, time # 1. 创建翻译任务 resp = requests.post( "https://dashscope.aliyuncs.com/api/v1/services/aigc/image2image/image-synthesis", headers={ "Authorization": f"Bearer {os.getenv('DASHSCOPE_API_KEY')}", "X-DashScope-Async": "enable" }, json={ "model": "qwen-mt-image", "input": { "image_url": "https://example.com/english-poster.jpg", "source_lang": "en", "target_lang": "zh" } } ) task_id = resp.json()["output"]["task_id"] # 2. 轮询获取结果 while True: time.sleep(3) result = requests.get( f"https://dashscope.aliyuncs.com/api/v1/tasks/{task_id}", headers={"Authorization": f"Bearer {os.getenv('DASHSCOPE_API_KEY')}"} ).json() if result["output"]["task_status"] == "SUCCEEDED": print(result["output"]["image_url"]) break ``` --- ## 默认配置 | 场景 | 默认模型 | 高质量模型 | |------|----------|------------| | 文生图 | `qwen-image-plus` | `qwen-image-max` | | 图像编辑 | `qwen-image-edit-plus` | `qwen-image-edit-max` | | 图像翻译 | `qwen-mt-image` | - | **规则**：默认使用 Plus 系列，仅当用户明确要求"最好的"、"最高质量"时使用 Max 系列。 ### 默认参数 ```json { "negative_prompt": "低分辨率，低画质，肢体畸形，手指畸形，画面过饱和，蜡像感", "prompt_extend": true, "watermark": false } ``` --- ## 详细参考 按需加载以下文档： | 文档 | 用途 | |------|------| | [references/text-to-image.md](references/text-to-image.md) | 文生图完整API参考：模型列表、分辨率、所有参数 | | [references/image-edit.md](references/image-edit.md) | 图像编辑完整API参考：单图编辑、多图融合、输入要求 | | [references/image-translate.md](references/image-translate.md) | 图像翻译完整API参考：支持语言、异步调用、术语定义 | --- ## 工具脚本 | 脚本 | 用途 | |------|------| | [scripts/client.py](scripts/client.py) | 封装好的API客户端，支持文生图、图像编辑和图像翻译 | **使用脚本**： ```bash # 文生图 python scripts/client.py generate "一只橘猫在阳光下打盹" --size 1920*1080 # 图像编辑 python scripts/client.py edit "https://example.com/photo.jpg" "把背景换成星空" -n 2 # 图像翻译 python scripts/client.py translate "https://example.com/english.jpg" --source en --target zh ``` --- ## 关键注意事项 1. **图像URL有效期**：生成的图像URL仅保留 **24小时**，请及时下载 2. **地域**：API Key 和请求地址必须属于同一地域（北京/新加坡） 3. **费用**：按成功生成的图像张数计费 --- ## 常见错误 | 错误码 | 原因 | 解决方案 | |--------|------|----------| | `InvalidApiKey` | API Key无效 | 检查环境变量配置 | | `InvalidParameter` | 参数错误 | 检查请求格式 | | `DataInspectionFailed` | 内容审核失败 | 修改输入内容 |

path: README.md
content: # 阿里云百炼图像生成、编辑与翻译 Skill

[![Version](https://img.shields.io/badge/version-1.1.0-blue.svg)](https://clawhub.com)
[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![ClawHub](https://img.shields.io/badge/ClawHub-Synced-green.svg)](https://clawhub.com/skill/aliyun-image)

阿里云百炼平台提供的图像生成、编辑与翻译能力，包含千问-文生图(Qwen-Image)、千问-图像编辑(Qwen-Image-Edit)和千问-图像翻译(Qwen-MT-Image)三个模型。

## 🔄 同步更新

本项目在 **GitHub** 和 **ClawHub** 同步发布更新：

- **GitHub 仓库**: https://github.com/StanleyChanH/aliyun-image-skill
- **ClawHub 页面**: https://clawhub.com/skill/aliyun-image
- **GitHub Actions**: 自动同步 ✅

### 自动同步机制
- ✅ 使用 GitHub Actions 自动同步到 ClawHub
- ✅ 每次推送到 `main` 分支自动触发
- ✅ 版本号和更新日志保持一致
- ✅ GitHub Release 自动创建

### 配置自动同步
查看 [.github/SETUP.md](.github/SETUP.md) 了解如何配置 GitHub Actions 自动同步。

## 更新日志

### v1.1.0 (2026-02-13)
- 新增图像翻译功能（Qwen-MT-Image）
- 支持11种源语言和14种目标语言
- 提供术语定义、敏感词过滤、领域提示等高级功能
- 更新客户端脚本支持翻译命令

### v1.0.4 (2026-02-13)
- 修复 GitHub Actions 权限问题
- 添加 `permissions: contents: write` 以支持自动创建 Release
- 完整测试自动同步流程

### v1.0.3 (2026-02-13)
- 测试 GitHub Actions 自动同步到 ClawHub
- 验证自动发布流程

### v1.0.2 (2026-02-13)
- 作者改为 StanleyChanH
- 添加 GitHub Actions 自动同步到 ClawHub
- 更新文档说明 GitHub 和 ClawHub 同步更新机制
- 添加配置文档 .github/SETUP.md

### v1.0.1 (2026-02-13)
- 更新 API 文档和示例代码
- 优化技能说明和触发词
- 完善参考文档结构

## 功能特性

### 🎨 文生图 (Qwen-Image)
- 根据文本描述生成图像
- 支持复杂文字渲染
- 多种分辨率选择
- 智能提示词改写

### ✏️ 图像编辑 (Qwen-Image-Edit)
- 单图编辑：修改文字、增删物体、改变动作
- 多图融合：人物换装、姿势迁移
- 风格迁移：艺术风格转换
- 细节增强：图像质量提升

### 🌐 图像翻译 (Qwen-MT-Image)
- 精准翻译图像中的文字
- 保留原始排版与内容信息
- 支持11种源语言（中/英/日/韩/俄/西/法/葡/意/德/越）
- 支持14种目标语言（含马来/泰/印尼/阿拉伯）
- 领域提示：电商、客服等场景优化
- 敏感词过滤：屏蔽指定内容
- 术语定义：自定义专业术语翻译

## 支持的模型

### 文生图模型
- `qwen-image-max` - 高质量，真实感强
- `qwen-image-plus` - 性价比高，多样化风格
- `qwen-image` - 基础版

### 图像编辑模型
- `qwen-image-edit-max` - 高质量编辑
- `qwen-image-edit-plus` - 性价比高
- `qwen-image-edit` - 基础版

### 图像翻译模型
- `qwen-mt-image` - 图像文字翻译，保留排版

## 安装要求

### 环境变量
```bash
export DASHSCOPE_API_KEY="your_api_key_here"
```

### 获取 API Key
1. 访问 [阿里云百炼控制台](https://bailian.console.aliyun.com/)
2. 创建并获取 API Key
3. 配置到环境变量

### 依赖安装（可选）
```bash
pip install requests
```

## 使用示例

### 文生图
```python
import requests

response = requests.post(
    "https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation",
    headers={
        "Authorization": f"Bearer {DASHSCOPE_API_KEY}"
    },
    json={
        "model": "qwen-image-plus",
        "input": {
            "messages": [{
                "role": "user",
                "content": [{"text": "一只可爱的橘猫"}]
            }]
        },
        "parameters": {
            "size": "1024*1024"
        }
    }
)
```

### 图像编辑
```python
response = requests.post(
    "https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation",
    headers={"Authorization": f"Bearer {DASHSCOPE_API_KEY}"},
    json={
        "model": "qwen-image-edit-plus",
        "input": {
            "messages": [{
                "role": "user",
                "content": [
                    {"image": "https://example.com/input.jpg"},
                    {"text": "把背景改成星空"}
                ]
            }]
        }
    }
)
```

### 图像翻译
```python
import time

# 1. 创建翻译任务
response = requests.post(
    "https://dashscope.aliyuncs.com/api/v1/services/aigc/image2image/image-synthesis",
    headers={
        "Authorization": f"Bearer {DASHSCOPE_API_KEY}",
        "X-DashScope-Async": "enable"
    },
    json={
        "model": "qwen-mt-image",
        "input": {
            "image_url": "https://example.com/english-poster.jpg",
            "source_lang": "en",
            "target_lang": "zh"
        }
    }
)
task_id = response.json()["output"]["task_id"]

# 2. 轮询获取结果
while True:
    time.sleep(3)
    result = requests.get(
        f"https://dashscope.aliyuncs.com/api/v1/tasks/{task_id}",
        headers={"Authorization": f"Bearer {DASHSCOPE_API_KEY}"}
    ).json()
    if result["output"]["task_status"] == "SUCCEEDED":
        print(result["output"]["image_url"])
        break
```

### 使用客户端脚本
```bash
# 文生图
python scripts/client.py generate "一只橘猫在阳光下打盹" --size 1920*1080

# 图像编辑
python scripts/client.py edit "https://example.com/photo.jpg" "把背景换成星空" -n 2

# 图像翻译
python scripts/client.py translate "https://example.com/english.jpg" --source en --target zh

# 带高级选项的翻译
python scripts/client.py translate "https://example.com/ad.jpg" \
    --source auto --target zh \
    --domain "E-commerce product description" \
    --sensitives "促销,折扣" \
    --terms "API:应用程序接口,ML:机器学习"
```

## 特点

✅ 国内网络友好（阿里云服务）
✅ 支持中文提示词
✅ 多种分辨率选择
✅ 智能提示词优化
✅ 图像文字翻译，保留排版
✅ 24小时图像存储

## 适用场景

- 小红书封面生成
- 产品宣传图制作
- 社交媒体内容创作
- 艺术风格迁移
- 图像修复与增强
- 海报/说明书多语言翻译
- 跨境电商图片本地化

## 许可证

MIT

## 作者

StanleyChanH

## 同步更新

本项目在 **GitHub** 和 **ClawHub** 同步发布更新：

- **GitHub**: https://github.com/StanleyChanH/aliyun-image-skill
- **ClawHub**: https://clawhub.com/skill/aliyun-image

每次发布新版本时，会同时推送到两个平台，确保用户可以从任一渠道获取最新版本。

### 版本同步策略
- 所有版本更新优先发布到 GitHub
- 通过自动化流程同步到 ClawHub
- 两个平台保持版本号一致

---

**注意**：使用本 skill 需要 [阿里云百炼](https://bailian.console.aliyun.com/) 账号和 API Key。


path: metadata.json
content: {
  "name": "aliyun-image",
  "version": "1.1.0",
  "description": "阿里云百炼图像生成、编辑与翻译能力。支持文生图(Qwen-Image)、图像编辑(Qwen-Image-Edit)和图像翻译(Qwen-MT-Image)。文生图: 根据文本描述生成图像，支持多种分辨率、智能提示词改写。图像编辑: 单图编辑、多图融合，支持修改文字、增删物体、风格迁移、细节增强。图像翻译: 翻译图像中的文字，保留原始排版，支持11种源语言和14种目标语言，提供术语定义、敏感词过滤等自定义功能。",
  "author": "StanleyChanH",
  "tags": ["阿里云", "图像生成", "文生图", "图像编辑", "AI作画", "多图融合", "风格迁移", "图像翻译", "图片翻译", "qwen-mt-image"],
  "repository": "https://github.com/StanleyChanH/aliyun-image-skill",
  "license": "MIT"
}


path: references/image-edit.md
content: # 图像编辑 API 参考

支持单图编辑和多图融合，可修改文字、增删物体、改变动作、迁移风格。

## 目录

- [模型列表](#模型列表)
- [输入图像要求](#输入图像要求)
- [请求参数](#请求参数)
- [分辨率选项](#分辨率选项)
- [使用场景](#使用场景)
- [完整示例](#完整示例)

---

## 模型列表

| 模型 | 简介 | 输出规格 |
|------|------|----------|
| `qwen-image-edit-plus` | Plus系列，默认推荐 | PNG, 1-6张, 可自定义分辨率 |
| `qwen-image-edit-plus-2025-12-15` | Plus指定版本 | 同上 |
| `qwen-image-edit-max` | Max系列，更高质量 | PNG, 1-6张, 可自定义分辨率 |
| `qwen-image-edit-max-2026-01-16` | Max指定版本 | 同上 |
| `qwen-image-edit` | 基础版 | PNG, 1张, 默认分辨率 |

---

## 输入图像要求

| 项目 | 要求 |
|------|------|
| 格式 | JPG, JPEG, PNG, BMP, TIFF, WEBP, GIF |
| 分辨率 | 建议 384-3072 像素 |
| 大小 | ≤10MB |
| GIF | 仅处理第一帧 |
| 数量 | 1-3张 |

### 输入格式

| 格式 | 示例 |
|------|------|
| 公网URL | `https://example.com/image.jpg` |
| OSS临时URL | `oss://dashscope-instant/xxx/cat.png` |
| Base64 | `data:image/jpeg;base64,GDU7MtCZz...` |

---

## 请求参数

### Headers

| Header | 值 |
|--------|-----|
| `Content-Type` | `application/json` |
| `Authorization` | `Bearer $DASHSCOPE_API_KEY` |

### Body

| 参数 | 类型 | 必选 | 说明 |
|------|------|------|------|
| `model` | string | 是 | 模型名称 |
| `input.messages[].role` | string | 是 | 固定 `user` |
| `input.messages[].content[].image` | string | 是 | 图像URL/Base64，1-3张 |
| `input.messages[].content[].text` | string | 是 | 编辑指令，≤800字符 |

### parameters

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `n` | integer | 1 | 输出数量，Max/Plus支持1-6 |
| `negative_prompt` | string | - | 反向提示词，≤500字符 |
| `size` | string | 自动 | 分辨率 `宽*高`，范围[512, 2048] |
| `prompt_extend` | bool | `true` | 提示词智能改写 |
| `watermark` | bool | `false` | 是否添加水印 |
| `seed` | integer | 随机 | 随机种子 [0, 2147483647] |

---

## 分辨率选项

| 宽高比 | 分辨率 |
|--------|--------|
| 1:1 | `1024*1024`, `1536*1536` |
| 2:3 | `768*1152`, `1024*1536` |
| 3:2 | `1152*768`, `1536*1024` |
| 3:4 | `960*1280`, `1080*1440` |
| 4:3 | `1280*960`, `1440*1080` |
| 9:16 | `720*1280`, `1080*1920` |
| 16:9 | `1280*720`, `1920*1080` |
| 21:9 | `1344*576`, `2048*872` |

**默认规则**：若不设置size，输出图像保持与输入图像（多图时为最后一张）相似的宽高比，总像素≈1024*1024。

---

## 使用场景

### 单图编辑

```json
{
    "model": "qwen-image-edit-plus",
    "input": {
        "messages": [{
            "role": "user",
            "content": [
                {"image": "https://example.com/photo.jpg"},
                {"text": "把背景改成星空，添加流星"}
            ]
        }]
    },
    "parameters": {"n": 2, "prompt_extend": true, "watermark": false}
}
```

### 多图融合（最多3张输入图）

```json
{
    "model": "qwen-image-edit-plus",
    "input": {
        "messages": [{
            "role": "user",
            "content": [
                {"image": "https://example.com/person.jpg"},
                {"image": "https://example.com/dress.jpg"},
                {"image": "https://example.com/pose.jpg"},
                {"text": "图1中的人物穿着图2的裙子，按图3的姿势站立"}
            ]
        }]
    },
    "parameters": {"n": 1, "prompt_extend": true}
}
```

---

## 完整示例

### cURL

```bash
curl --location 'https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation' \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--data '{
    "model": "qwen-image-edit-plus",
    "input": {
        "messages": [{
            "role": "user",
            "content": [
                {"image": "https://example.com/photo.jpg"},
                {"text": "把女孩的头发改成红色"}
            ]
        }]
    },
    "parameters": {"n": 2, "prompt_extend": true, "watermark": false}
}'
```

### Python

```python
import os
import requests
import base64

def edit_image(images, instruction, n=1, size=None, use_max=False):
    """
    编辑图像

    Args:
        images: 图像URL或本地路径列表（1-3张）
        instruction: 编辑指令
        n: 输出数量（1-6）
        size: 输出分辨率
        use_max: 是否使用Max模型
    """
    [REDACTED_SECRET]"DASHSCOPE_API_KEY")
    model = "qwen-image-edit-max" if use_max else "qwen-image-edit-plus"

    # 处理图像输入
    content = []
    for img in images if isinstance(images, list) else [images]:
        if img.startswith("http") or img.startswith("oss://") or img.startswith("data:"):
            content.append({"image": img})
        else:
            # 本地文件转Base64
            with open(img, "rb") as f:
                b64 = base64.b64encode(f.read()).decode()
            content.append({"image": f"data:image/jpeg;base64,{b64}"})

    content.append({"text": instruction})

    payload = {
        "model": model,
        "input": {"messages": [{"role": "user", "content": content}]},
        "parameters": {"n": n, "prompt_extend": True, "watermark": False}
    }
    if size:
        payload["parameters"]["size"] = size

    resp = requests.post(
        "https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation",
        headers={"Content-Type": "application/json", "Authorization": f"Bearer {api_key}"},
        json=payload
    )
    result = resp.json()
    if "output" in result:
        return [c["image"] for c in result["output"]["choices"][0]["message"]["content"]]
    raise Exception(f"Error: {result.get('message', 'Unknown')}")

# 单图编辑
urls = edit_image("https://example.com/photo.jpg", "把背景替换成东京夜景", n=2)
for i, url in enumerate(urls):
    print(f"结果 {i+1}: {url}")

# 多图融合
urls = edit_image(
    ["person.jpg", "dress.jpg", "pose.jpg"],
    "图1的人物穿图2的裙子，按图3的姿势",
    n=1
)
```

---

## 编辑技巧

1. **明确指令**：清晰描述要修改的内容
2. **多图引用**：如"图1中的人物穿着图2的衣服"
3. **保持原图特征**：指定"保持原有背景"、"保持表情不变"
4. **适当使用反向提示词**：避免不需要的效果

---

## 响应格式

```json
{
    "output": {
        "choices": [{
            "finish_reason": "stop",
            "message": {
                "content": [
                    {"image": "https://dashscope-result-sz.oss-cn-shenzhen.aliyuncs.com/xxx.png"},
                    {"image": "https://dashscope-result-sz.oss-cn-shenzhen.aliyuncs.com/yyy.png"}
                ]
            }
        }]
    },
    "usage": {"image_count": 2, "width": 1536, "height": 1024},
    "request_id": "xxx"
}
```


path: references/image-translate.md
content: # 图像翻译 API 参考

千问-图像翻译模型（Qwen-MT-Image）可精准翻译图像中的文字，并保留原始排版。

## 目录

- [模型概览](#模型概览)
- [支持的语言](#支持的语言)
- [API 调用流程](#api-调用流程)
- [创建任务](#创建任务)
- [查询结果](#查询结果)
- [高级功能](#高级功能)
- [完整示例](#完整示例)

---

## 模型概览

| 模型 | 简介 | 计费 |
|------|------|------|
| `qwen-mt-image` | 图像翻译，保留排版 | 0.003元/张 |

**特点**：
- 精准翻译图像中的文字
- 保留原始排版与内容信息
- 支持术语定义、敏感词过滤、图像主体检测

---

## 支持的语言

### 源语种（11种）

| 中文名 | 英文全称 | 编码 |
|--------|----------|------|
| 简体中文 | Chinese | zh |
| 英文 | English | en |
| 韩语 | Korean | ko |
| 日语 | Japanese | ja |
| 俄语 | Russian | ru |
| 西语 | Spanish | es |
| 法语 | French | fr |
| 葡萄牙语 | Portuguese | pt |
| 意大利语 | Italian | it |
| 德语 | Germany | de |
| 越南语 | Vietnamese | vi |

### 目标语种（14种）

| 中文名 | 英文全称 | 编码 |
|--------|----------|------|
| 简体中文 | Chinese | zh |
| 英文 | English | en |
| 韩语 | Korean | ko |
| 日语 | Japanese | ja |
| 俄语 | Russian | ru |
| 西语 | Spanish | es |
| 法语 | French | fr |
| 葡萄牙语 | Portuguese | pt |
| 意大利语 | Italian | it |
| 越南语 | Vietnamese | vi |
| 马来语 | Malay | ms |
| 泰语 | Thai | th |
| 印尼语 | Indonesian | id |
| 阿拉伯语 | Arabian | ar |

**注意**：翻译方向必须以中文或英文作为源语种或目标语种。不支持在其他语种之间互译（如：日文译为韩文）。若不确定源语种，可设置为 `auto` 自动检测。

---

## API 调用流程

图像翻译采用异步模式，调用流程分两步：

1. **创建任务获取任务ID**：发送请求创建任务，返回 `task_id`
2. **根据任务ID查询结果**：使用 `task_id` 轮询任务状态，直到任务完成

---

## 创建任务

### 端点

```
POST https://dashscope.aliyuncs.com/api/v1/services/aigc/image2image/image-synthesis
```

### Headers

| Header | 值 |
|--------|-----|
| `Content-Type` | `application/json` |
| `Authorization` | `Bearer $DASHSCOPE_API_KEY` |
| `X-DashScope-Async` | `enable`（必须） |

### Body

| 参数 | 类型 | 必选 | 说明 |
|------|------|------|------|
| `model` | string | 是 | 固定 `qwen-mt-image` |
| `input.image_url` | string | 是 | 输入图像URL |
| `input.source_lang` | string | 是 | 源语种，支持语种全称或编码，不确定时设为 `auto` |
| `input.target_lang` | string | 是 | 目标语种 |
| `input.ext.domainHint` | string | 否 | 领域提示，英文描述使用场景、译文风格（≤200词） |
| `input.ext.sensitives` | array | 否 | 敏感词列表，屏蔽部分内容（≤50个） |
| `input.ext.terminologies` | array | 否 | 术语定义，`[{src, tgt}]` 格式 |
| `input.ext.config.skipImgSegment` | bool | 否 | 是否翻译主体文字，默认 `false` 不翻译 |

### 输入图像要求

| 项目 | 要求 |
|------|------|
| 格式 | JPG, JPEG, PNG, BMP, PNM, PPM, TIFF, WEBP |
| 分辨率 | 15-8192 像素，宽高比 1:10 至 10:1 |
| 大小 | ≤10MB |

### 响应

```json
{
    "output": {
        "task_status": "PENDING",
        "task_id": "0385dc79-5ff8-4d82-bcb6-xxxxxx"
    },
    "request_id": "4909100c-7b5a-9f92-bfe5-xxxxxx"
}
```

---

## 查询结果

### 端点

```
GET https://dashscope.aliyuncs.com/api/v1/tasks/{task_id}
```

### Headers

| Header | 值 |
|--------|-----|
| `Authorization` | `Bearer $DASHSCOPE_API_KEY` |

### 任务状态

| 状态 | 说明 |
|------|------|
| `PENDING` | 任务排队中 |
| `RUNNING` | 任务处理中 |
| `SUCCEEDED` | 任务执行成功 |
| `FAILED` | 任务执行失败 |
| `CANCELED` | 任务取消成功 |
| `UNKNOWN` | 任务不存在或状态未知 |

### 成功响应

```json
{
    "request_id": "5fec62eb-bf94-91f8-b9f4-f7f758e4e27e",
    "output": {
        "task_id": "72c52225-8444-4cab-ad0c-xxxxxx",
        "task_status": "SUCCEEDED",
        "submit_time": "2025-08-13 18:11:16.954",
        "scheduled_time": "2025-08-13 18:11:17.003",
        "end_time": "2025-08-13 18:11:23.860",
        "image_url": "http://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/xxx?Expires=xxx"
    },
    "usage": {"image_count": 1}
}
```

---

## 高级功能

### 领域提示（domainHint）

用英文描述使用场景和译文风格，获得更符合特定领域的翻译：

```json
{
    "input": {
        "ext": {
            "domainHint": "These sentences are from seller-buyer conversations on a B2C ecommerce platform. Translate them into clear, engaging customer service language."
        }
    }
}
```

### 敏感词过滤（sensitives）

屏蔽指定内容，翻译后图片中不显示：

```json
{
    "input": {
        "ext": {
            "sensitives": ["满200-20", "七天无理由退换"]
        }
    }
}
```

### 术语定义（terminologies）

为特定术语设定固定译文：

```json
{
    "input": {
        "ext": {
            "terminologies": [
                {"src": "应用程序接口", "tgt": "API"},
                {"src": "机器学习", "tgt": "ML"}
            ]
        }
    }
}
```

### 翻译主体文字（skipImgSegment）

控制是否翻译图像中关键主体（如人物、商品、Logo）上的文字：

- `false`（默认）：智能识别主体，不翻译主体上的文字
- `true`：将图像主体上的文字一并翻译

```json
{
    "input": {
        "ext": {
            "config": {"skipImgSegment": true}
        }
    }
}
```

---

## 完整示例

### cURL

```bash
# 1. 创建任务
curl --location 'https://dashscope.aliyuncs.com/api/v1/services/aigc/image2image/image-synthesis' \
--header 'X-DashScope-Async: enable' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
    "model": "qwen-mt-image",
    "input": {
        "image_url": "https://example.com/image.jpg",
        "source_lang": "en",
        "target_lang": "zh"
    }
}'

# 2. 查询结果（将task_id替换为实际值）
curl -X GET "https://dashscope.aliyuncs.com/api/v1/tasks/YOUR_TASK_ID" \
--header "Authorization: Bearer $DASHSCOPE_API_KEY"
```

### Python

```python
import os
import time
import requests

def translate_image(
    image_url: str,
    source_lang: str = "auto",
    target_lang: str = "zh",
    domain_hint: str = None,
    sensitives: list = None,
    terminologies: list = None,
    skip_img_segment: bool = False,
    poll_interval: int = 3
) -> str:
    """
    图像翻译

    Args:
        image_url: 输入图像URL
        source_lang: 源语种，默认自动检测
        target_lang: 目标语种，默认中文
        domain_hint: 领域提示
        sensitives: 敏感词列表
        terminologies: 术语定义列表
        skip_img_segment: 是否翻译主体文字
        poll_interval: 轮询间隔（秒）

    Returns:
        翻译后图像的URL
    """
    [REDACTED_SECRET]"DASHSCOPE_API_KEY")

    # 构建请求体
    payload = {
        "model": "qwen-mt-image",
        "input": {
            "image_url": image_url,
            "source_lang": source_lang,
            "target_lang": target_lang
        }
    }

    # 添加可选参数
    ext = {}
    if domain_hint:
        ext["domainHint"] = domain_hint
    if sensitives:
        ext["sensitives"] = sensitives
    if terminologies:
        ext["terminologies"] = terminologies
    if skip_img_segment:
        ext["config"] = {"skipImgSegment": True}

    if ext:
        payload["input"]["ext"] = ext

    # 创建任务
    resp = requests.post(
        "https://dashscope.aliyuncs.com/api/v1/services/aigc/image2image/image-synthesis",
        headers={
            "Content-Type": "application/json",
            "Authorization": f"Bearer {api_key}",
            "X-DashScope-Async": "enable"
        },
        json=payload
    )
    result = resp.json()

    if "code" in result:
        raise Exception(f"[{result['code']}] {result.get('message', 'Unknown error')}")

    task_id = result["output"]["task_id"]
    print(f"任务已创建: {task_id}")

    # 轮询查询结果
    while True:
        time.sleep(poll_interval)
        resp = requests.get(
            f"https://dashscope.aliyuncs.com/api/v1/tasks/{task_id}",
            headers={"Authorization": f"Bearer {api_key}"}
        )
        result = resp.json()
        status = result["output"]["task_status"]

        if status == "SUCCEEDED":
            return result["output"]["image_url"]
        elif status == "FAILED":
            raise Exception(f"任务失败: {result['output'].get('message', 'Unknown error')}")
        elif status in ("PENDING", "RUNNING"):
            print(f"任务状态: {status}, 等待中...")
        else:
            raise Exception(f"未知状态: {status}")

# 使用示例
url = translate_image(
    image_url="https://example.com/english-poster.jpg",
    source_lang="en",
    target_lang="zh"
)
print(f"翻译结果: {url}")
```

---

## 注意事项

1. **有效期**：
   - `task_id` 查询有效期为 **24小时**
   - 翻译后图像URL有效期为 **24小时**
2. **耗时**：模型处理约15秒，建议轮询间隔3秒
3. **限流**：RPS限制为1，同时处理任务数为2
4. **域名白名单**：如需访问图像链接，请配置OSS域名白名单


path: references/text-to-image.md
content: # 文生图 API 参考

根据文本描述生成图像，尤其擅长复杂文字渲染。

## 目录

- [模型列表](#模型列表)
- [API 端点](#api-端点)
- [请求参数](#请求参数)
- [分辨率选项](#分辨率选项)
- [响应格式](#响应格式)
- [完整示例](#完整示例)

---

## 模型列表

| 模型 | 简介 | 输出规格 |
|------|------|----------|
| `qwen-image-plus` | Plus系列，默认推荐 | PNG, 1张, 可选分辨率 |
| `qwen-image-plus-2026-01-09` | Plus指定版本 | 同上 |
| `qwen-image-max` | Max系列，更高质量 | PNG, 1张, 可选分辨率 |
| `qwen-image-max-2025-12-30` | Max指定版本 | 同上 |
| `qwen-image` | 基础版 | PNG, 1张, 默认分辨率 |

---

## API 端点

| 地域 | 端点 |
|------|------|
| 北京（默认） | `https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation` |
| 新加坡 | `https://dashscope-intl.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation` |

---

## 请求参数

### Headers

| Header | 值 |
|--------|-----|
| `Content-Type` | `application/json` |
| `Authorization` | `Bearer $DASHSCOPE_API_KEY` |

### Body

| 参数 | 类型 | 必选 | 说明 |
|------|------|------|------|
| `model` | string | 是 | 模型名称 |
| `input.messages` | array | 是 | 消息数组，仅支持单轮 |
| `input.messages[].role` | string | 是 | 固定 `user` |
| `input.messages[].content[].text` | string | 是 | 提示词，≤800字符 |

### parameters

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `negative_prompt` | string | - | 反向提示词，≤500字符 |
| `size` | string | `1664*928` | 分辨率 `宽*高` |
| `n` | integer | 1 | 生成数量，**固定为1** |
| `prompt_extend` | bool | `true` | 提示词智能改写 |
| `watermark` | bool | `false` | 是否添加水印 |
| `seed` | integer | 随机 | 随机种子 [0, 2147483647] |

---

## 分辨率选项

| 宽高比 | 分辨率 |
|--------|--------|
| 16:9（默认） | `1664*928` |
| 4:3 | `1472*1104` |
| 1:1 | `1328*1328` |
| 3:4 | `1104*1472` |
| 9:16 | `928*1664` |

---

## 响应格式

```json
{
    "output": {
        "choices": [{
            "finish_reason": "stop",
            "message": {
                "content": [{"image": "https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/xxx.png?Expires=xxx"}]
            }
        }]
    },
    "usage": {"image_count": 1, "width": 1664, "height": 928},
    "request_id": "xxx"
}
```

---

## 完整示例

### cURL

```bash
curl --location 'https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation' \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--data '{
    "model": "qwen-image-plus",
    "input": {
        "messages": [{"role": "user", "content": [{"text": "一只坐着的橘黄色的猫"}]}]
    },
    "parameters": {
        "negative_prompt": "低分辨率，低画质，肢体畸形",
        "prompt_extend": true,
        "watermark": false,
        "size": "1664*928"
    }
}'
```

### Python

```python
import os
import requests

def generate_image(prompt, size="1664*928", negative_prompt=None, use_max=False):
    [REDACTED_SECRET]"DASHSCOPE_API_KEY")
    model = "qwen-image-max" if use_max else "qwen-image-plus"

    payload = {
        "model": model,
        "input": {"messages": [{"role": "user", "content": [{"text": prompt}]}]},
        "parameters": {"prompt_extend": True, "watermark": False, "size": size}
    }
    if negative_prompt:
        payload["parameters"]["negative_prompt"] = negative_prompt

    resp = requests.post(
        "https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation",
        headers={"Content-Type": "application/json", "Authorization": f"Bearer {api_key}"},
        json=payload
    )
    result = resp.json()
    if "output" in result:
        return result["output"]["choices"][0]["message"]["content"][0]["image"]
    raise Exception(f"Error: {result.get('message', 'Unknown')}")

# 使用
url = generate_image("一片宁静的湖泊，远处是雪山倒影", size="1920*1080")
print(url)
```

## 提示词技巧

1. **具体描述**：详细描述场景、风格、构图
2. **使用修饰词**：如"高清"、"写实"、"卡通风格"
3. **指定细节**：颜色、光影、视角
4. **利用智能改写**：开启 `prompt_extend` 优化简短提示词


path: scripts/client.py
content: #!/usr/bin/env python3
"""
阿里云百炼图像生成与编辑 API 客户端

使用方法:
    # 文生图
    python client.py generate "提示词" [--size 1920*1080] [--max]

    # 图像编辑
    python client.py edit "图像URL" "编辑指令" [-n 2] [--size 1536*1024] [--max]

    # 多图融合
    python client.py edit "图1URL,图2URL,图3URL" "编辑指令" [-n 1]

    # 图像翻译
    python client.py translate "图像URL" --source en --target zh [--domain "电商客服"] [--sensitives "敏感词1,敏感词2"]

    # 下载图像
    python client.py download "图像URL" [保存路径]
"""

import argparse
import base64
import os
import sys
import time
from typing import List, Optional

import requests

# API 配置
API_BASE = "https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation"
TRANSLATE_API = "https://dashscope.aliyuncs.com/api/v1/services/aigc/image2image/image-synthesis"
TASK_API = "https://dashscope.aliyuncs.com/api/v1/tasks"

# 默认配置
DEFAULT_NEGATIVE_PROMPT = "低分辨率，低画质，肢体畸形，手指畸形，画面过饱和，蜡像感，人脸无细节"


class AliyunImageClient:
    """阿里云百炼图像API客户端"""

    def __init__(self, [REDACTED_SECRET] = None):
        self.[REDACTED_SECRET] or os.getenv("DASHSCOPE_API_KEY")
        if not self.api_key:
            raise ValueError("请设置 DASHSCOPE_API_KEY 环境变量或传入 api_key 参数")

    def _request(self, payload: dict) -> dict:
        """发送API请求"""
        resp = requests.post(
            API_BASE,
            headers={
                "Content-Type": "application/json",
                "Authorization": f"Bearer {self.api_key}"
            },
            json=payload,
            timeout=120
        )
        result = resp.json()

        if "code" in result:
            raise Exception(f"[{result['code']}] {result.get('message', 'Unknown error')}")

        return result

    def generate(
        self,
        prompt: str,
        size: str = "1664*928",
        negative_prompt: str = DEFAULT_NEGATIVE_PROMPT,
        prompt_extend: bool = True,
        watermark: bool = False,
        use_max: bool = False
    ) -> str:
        """
        文生图

        Args:
            prompt: 正向提示词
            size: 输出分辨率
            negative_prompt: 反向提示词
            prompt_extend: 是否开启提示词智能改写
            watermark: 是否添加水印
            use_max: 是否使用Max模型

        Returns:
            生成图像的URL
        """
        model = "qwen-image-max" if use_max else "qwen-image-plus"

        payload = {
            "model": model,
            "input": {
                "messages": [{
                    "role": "user",
                    "content": [{"text": prompt}]
                }]
            },
            "parameters": {
                "negative_prompt": negative_prompt,
                "prompt_extend": prompt_extend,
                "watermark": watermark,
                "size": size
            }
        }

        result = self._request(payload)
        return result["output"]["choices"][0]["message"]["content"][0]["image"]

    def edit(
        self,
        images: List[str],
        instruction: str,
        n: int = 1,
        size: Optional[str] = None,
        negative_prompt: str = DEFAULT_NEGATIVE_PROMPT,
        prompt_extend: bool = True,
        watermark: bool = False,
        use_max: bool = False
    ) -> List[str]:
        """
        图像编辑

        Args:
            images: 图像URL列表（1-3张）
            instruction: 编辑指令
            n: 输出图像数量（1-6）
            size: 输出分辨率
            negative_prompt: 反向提示词
            prompt_extend: 是否开启提示词智能改写
            watermark: 是否添加水印
            use_max: 是否使用Max模型

        Returns:
            生成图像的URL列表
        """
        model = "qwen-image-edit-max" if use_max else "qwen-image-edit-plus"

        # 构建content
        content = []
        for img in images:
            # 支持本地文件
            if os.path.exists(img):
                with open(img, "rb") as f:
                    b64 = base64.b64encode(f.read()).decode()
                content.append({"image": f"data:image/jpeg;base64,{b64}"})
            else:
                content.append({"image": img})

        content.append({"text": instruction})

        payload = {
            "model": model,
            "input": {
                "messages": [{
                    "role": "user",
                    "content": content
                }]
            },
            "parameters": {
                "n": n,
                "negative_prompt": negative_prompt,
                "prompt_extend": prompt_extend,
                "watermark": watermark
            }
        }

        if size:
            payload["parameters"]["size"] = size

        result = self._request(payload)
        return [c["image"] for c in result["output"]["choices"][0]["message"]["content"]]

    @staticmethod
    def download(url: str, save_path: str) -> str:
        """
        下载图像

        Args:
            url: 图像URL
            save_path: 保存路径

        Returns:
            保存的文件路径
        """
        resp = requests.get(url, timeout=60)
        resp.raise_for_status()

        with open(save_path, "wb") as f:
            f.write(resp.content)

        return os.path.abspath(save_path)

    def translate(
        self,
        image_url: str,
        source_lang: str = "auto",
        target_lang: str = "zh",
        domain_hint: Optional[str] = None,
        sensitives: Optional[List[str]] = None,
        terminologies: Optional[List[dict]] = None,
        skip_img_segment: bool = False,
        poll_interval: int = 3
    ) -> str:
        """
        图像翻译

        Args:
            image_url: 输入图像URL
            source_lang: 源语种，默认自动检测
            target_lang: 目标语种，默认中文
            domain_hint: 领域提示（英文）
            sensitives: 敏感词列表
            terminologies: 术语定义列表 [{"src": "源词", "tgt": "目标词"}]
            skip_img_segment: 是否翻译主体文字
            poll_interval: 轮询间隔（秒）

        Returns:
            翻译后图像的URL
        """
        # 构建请求体
        payload = {
            "model": "qwen-mt-image",
            "input": {
                "image_url": image_url,
                "source_lang": source_lang,
                "target_lang": target_lang
            }
        }

        # 添加可选参数
        ext = {}
        if domain_hint:
            ext["domainHint"] = domain_hint
        if sensitives:
            ext["sensitives"] = sensitives
        if terminologies:
            ext["terminologies"] = terminologies
        if skip_img_segment:
            ext["config"] = {"skipImgSegment": True}

        if ext:
            payload["input"]["ext"] = ext

        # 创建任务
        resp = requests.post(
            TRANSLATE_API,
            headers={
                "Content-Type": "application/json",
                "Authorization": f"Bearer {self.api_key}",
                "X-DashScope-Async": "enable"
            },
            json=payload,
            timeout=30
        )
        result = resp.json()

        if "code" in result:
            raise Exception(f"[{result['code']}] {result.get('message', 'Unknown error')}")

        task_id = result["output"]["task_id"]

        # 轮询查询结果
        while True:
            time.sleep(poll_interval)
            resp = requests.get(
                f"{TASK_API}/{task_id}",
                headers={"Authorization": f"Bearer {self.api_key}"},
                timeout=30
            )
            result = resp.json()
            status = result["output"]["task_status"]

            if status == "SUCCEEDED":
                return result["output"]["image_url"]
            elif status == "FAILED":
                raise Exception(f"任务失败: {result['output'].get('message', 'Unknown error')}")
            elif status in ("PENDING", "RUNNING"):
                continue
            else:
                raise Exception(f"未知状态: {status}")


def main():
    parser = argparse.ArgumentParser(description="阿里云百炼图像API客户端")
    subparsers = parser.add_subparsers(dest="command", required=True)

    # 文生图命令
    gen_parser = subparsers.add_parser("generate", help="文生图")
    gen_parser.add_argument("prompt", help="提示词")
    gen_parser.add_argument("--size", default="1664*928", help="输出分辨率")
    gen_parser.add_argument("--max", action="store_true", help="使用Max模型")
    gen_parser.add_argument("--no-extend", action="store_true", help="关闭提示词智能改写")

    # 图像编辑命令
    edit_parser = subparsers.add_parser("edit", help="图像编辑")
    edit_parser.add_argument("images", help="图像URL，多个用逗号分隔")
    edit_parser.add_argument("instruction", help="编辑指令")
    edit_parser.add_argument("-n", type=int, default=1, help="输出数量")
    edit_parser.add_argument("--size", help="输出分辨率")
    edit_parser.add_argument("--max", action="store_true", help="使用Max模型")

    # 图像翻译命令
    trans_parser = subparsers.add_parser("translate", help="图像翻译")
    trans_parser.add_argument("image", help="图像URL")
    trans_parser.add_argument("--source", "-s", default="auto", help="源语种（默认auto自动检测）")
    trans_parser.add_argument("--target", "-t", default="zh", help="目标语种（默认zh中文）")
    trans_parser.add_argument("--domain", "-d", help="领域提示（英文描述）")
    trans_parser.add_argument("--sensitives", help="敏感词，多个用逗号分隔")
    trans_parser.add_argument("--terms", help="术语定义，格式：源词1:目标词1,源词2:目标词2")
    trans_parser.add_argument("--skip-segment", action="store_true", help="翻译主体上的文字")

    # 下载命令
    dl_parser = subparsers.add_parser("download", help="下载图像")
    dl_parser.add_argument("url", help="图像URL")
    dl_parser.add_argument("path", nargs="?", default="output.png", help="保存路径")

    args = parser.parse_args()
    client = AliyunImageClient()

    if args.command == "generate":
        print(f"正在生成图像...")
        url = client.generate(
            prompt=args.prompt,
            size=args.size,
            use_max=args.max,
            prompt_extend=not args.no_extend
        )
        print(f"图像URL: {url}")
        print("注意：URL有效期24小时")

    elif args.command == "edit":
        images = [img.strip() for img in args.images.split(",")]
        print(f"正在编辑图像（输入{len(images)}张，输出{args.n}张）...")
        urls = client.edit(
            images=images,
            instruction=args.instruction,
            n=args.n,
            size=args.size,
            use_max=args.max
        )
        for i, url in enumerate(urls):
            print(f"图像 {i+1}: {url}")
        print("注意：URL有效期24小时")

    elif args.command == "translate":
        # 解析敏感词
        sensitives = None
        if args.sensitives:
            sensitives = [s.strip() for s in args.sensitives.split(",")]

        # 解析术语定义
        terminologies = None
        if args.terms:
            terminologies = []
            for term in args.terms.split(","):
                if ":" in term:
                    src, tgt = term.split(":", 1)
                    terminologies.append({"src": src.strip(), "tgt": tgt.strip()})

        print(f"正在翻译图像 ({args.source} -> {args.target})...")
        url = client.translate(
            image_url=args.image,
            source_lang=args.source,
            target_lang=args.target,
            domain_hint=args.domain,
            sensitives=sensitives,
            terminologies=terminologies,
            skip_img_segment=args.skip_segment
        )
        print(f"翻译结果: {url}")
        print("注意：URL有效期24小时")

    elif args.command == "download":
        path = client.download(args.url, args.path)
        print(f"已保存到: {path}")


if __name__ == "__main__":
    main()


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: suspicious | SkillSpector: suspicious (CRITICAL)