Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions .github/workflows/diffsynth_studio-quick-start.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# diffsynth_studio quick start guard - project thin trigger.
#
# Calls the common engine .github/workflows/quick-start-template.yml;

name: diffsynth_studio-quick-start

concurrency:
# format() is load-bearing: a '||' between 'manual-' and
# github.run_id would short-circuit on the truthy literal and
# every dispatch would share one 'manual-' group.
group: ${{ github.event_name == 'schedule' && 'diffsynth_studio-quick-start-schedule' || format('manual-{0}', github.run_id) }}
# cancel-in-progress: false because (1) a schedule run cancelled
# mid-way loses its outcome writeback - the outcome is what makes
# the retry mechanism work, and the 'if: always()' guard isn't
# enough when the container is being torn down; (2) dispatch / PR
# runs already live in unique groups so there's nothing to cancel.
cancel-in-progress: false

on:
schedule:
# Offset from peft's '30 */3 * * *' and llama_cpp's '45 */3 * * *'.
- cron: '20 */3 * * *'
workflow_dispatch:
# PR trigger: docs/tests changes get a guard run. paths filter avoids burning
# the self-hosted NPU runner on unrelated PRs. `pull_request` (not
# `pull_request_target`): contents: read is enough, no write-token risk.
pull_request:
branches: [main]
paths:
- 'sources/diffsynth_studio/**'
- 'tests/diffsynth_studio/**'

permissions:
contents: read

jobs:
diffsynth_studio-quick-start:
uses: ./.github/workflows/quick-start-template.yml
with:
# Namespaces cache keys (monitor-state-diffsynth_studio-*), artifacts
# (diffsynth_studio-quick-start-<run_id>) and the test working dir
# (workflows/tests/diffsynth_studio).
project: diffsynth_studio
# Self-hosted NPU runner for the test job only; the engine pins
# the cache I/O jobs (restore-cache / publish-and-persist) to
# GitHub-hosted ubuntu-latest.
test_runner: '["linux-aarch64-a2-1"]'
image: swr.cn-south-1.myhuaweicloud.com/ascendhub/cann:9.1.0-910b-ubuntu22.04-py3.12
# 2 h budget. Cold path is torch-npu wheels plus a ~4 GB Hugging Face
# snapshot of stable-diffusion-v1-5, then five SD inference steps.
# Do not add a container bind-mount for /root/.cache: the runner
# NFS already persists that tree. Hub files reuse the default
# /root/.cache/huggingface/hub layout.
timeout_minutes: 120
upstream_repo: modelscope/DiffSynth-Studio
# Doc URL points to the upstream Ascend/docs repo. {0} is filled by the
# engine: PR head SHA on PR runs, 'main' otherwise. Same-repo PRs (head
# SHA exists on Ascend/docs) test the PR-version of the doc; fork PRs
# (head SHA on a fork) 404 on doc fetch - accepted, since the content
# lands on Ascend/docs post-merge.
doc_url: 'https://raw.githubusercontent.com/Ascend/docs/{0}/sources/diffsynth_studio/quick_start.md'
doc_path: https://github.com/Ascend/docs/blob/main/sources/diffsynth_studio/quick_start.md
# cwd is the repo root inside the `workflows` checkout (matches
# engine template's `working-directory: workflows`); env contract
# (MONITORED_DOC_URL / UPSTREAM_REF / NPU_READY) is injected by the
# engine. All project env prep lives in the test subclass's
# prepare_environment hook.
test_command: python -m unittest tests.diffsynth_studio.test_quick_start_ascend -v 2>&1
Binary file added _static/images/diffsynth_studio.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,13 @@
</div>


<!-- DiffSynth-Studio -->
<div class="project-card">
<div class="card-top"><div class="card-icon" style="background-image: url('_static/images/diffsynth_studio.png')"></div><h3 class="card-title">DiffSynth-Studio</h3></div>
<p class="card-desc">ModelScope 的扩散模型引擎,支持在昇腾 NPU 上文生图。</p>
<div class="card-footer"><a href="https://github.com/modelscope/DiffSynth-Studio">官方链接</a><span class="split">|</span><a href="https://diffsynth-studio-doc.readthedocs.io/zh-cn/latest/">文档中心</a><span class="split">|</span><a href="sources/diffsynth_studio/index.html">快速上手</a></div>
</div>

<!-- LM-Eval -->
<div class="project-card">
<div class="card-top"><div class="card-icon" style="background-image: url('_static/images/lm-evalution.png')"></div><h3 class="card-title">lm-evaluation-harness</h3></div>
Expand Down Expand Up @@ -635,6 +642,7 @@

sources/Diffusers/index.rst
sources/xdit/index.rst
sources/diffsynth_studio/index.rst
sources/lm_evaluation/index.rst
sources/open_clip/index.rst
sources/opencompass/index.rst
Expand Down
2 changes: 2 additions & 0 deletions sources/diffsynth_studio/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.. include:: quick_start.md
:parser: myst_parser.sphinx_
192 changes: 192 additions & 0 deletions sources/diffsynth_studio/quick_start.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
# DiffSynth-Studio

[DiffSynth-Studio](https://github.com/modelscope/DiffSynth-Studio) 是 ModelScope 的扩散模型引擎,用于文生图等生成任务。本文在单卡昇腾上安装它,并用 Stable Diffusion 1.5 生成一张图。


## 前置条件

### 硬件

Atlas 800T / 900 A2 训练系列,Ascend 910B。本文示例为单卡。

### 软件

| 类别 | 要求 |
| --- | --- |
| CANN | toolkit 与驱动已安装,并能 `source set_env.sh`。版本按 [昇腾软件配套清单](https://www.hiascend.com/developer/download/compatibility) 选择 |
| Python | 落在官方配套表范围内,并满足 DiffSynth-Studio 下限。当前正式版要求 3.10.1 及以上 |
| PyTorch | 安装官方当前推荐的 `torch` 与 `torch_npu`,CPU 轮子的版本号带 `+cpu`。见 [CANN 与 PyTorch 配套表](https://github.com/Ascend/pytorch/blob/master/COMPATIBILITY.md) 和 [PyTorch 安装包](https://www.hiascend.com/developer/software/ai-frameworks/pytorch/download) |
| DiffSynth-Studio | 当前正式版。将 `<ref>` 换成 PyPI 版本号,安装步骤见第 4 节 |
| 模型 | [stable-diffusion-v1-5/stable-diffusion-v1-5](https://huggingface.co/stable-diffusion-v1-5/stable-diffusion-v1-5) |

阅读本文前,请先按 [快速安装昇腾环境](https://ascend.github.io/docs/sources/ascend/quick_install.html) 准备好 CANN 与驱动。

### 本文验证环境

看护镜像为 `swr.cn-south-1.myhuaweicloud.com/ascendhub/cann:9.1.0-910b-ubuntu22.04-py3.12`。该镜像自带 Python 3.12。torch 使用 CPU 轮子,版本号以 `+cpu` 结尾。这组版本不是唯一支持组合。

## 1. 加载 CANN 环境

加载 CANN,并把 `/usr/local/sbin` 加入 PATH。

```shell
source /usr/local/Ascend/ascend-toolkit/set_env.sh
export PATH=/usr/local/sbin:$PATH
```

## 2. 检查环境是否就绪

### 2.1 确认 NPU 在线

```shell
npu-smi info
```

输出类似:

```text
+------------------------------------------------------------------------------------------------+
| npu-smi 25.5.2 Version: 25.5.2 |
+---------------------------+---------------+----------------------------------------------------+
| NPU Name | Health | Power(W) Temp(C) Hugepages-Usage(page)|
| Chip | Bus-Id | AICore(%) Memory-Usage(MB) HBM-Usage(MB) |
+===========================+===============+====================================================+
| 5 910B4 | OK | 89.9 39 0 / 0 |
| 0 | 0000:41:00.0 | 0 0 / 0 2922 / 32768 |
+===========================+===============+====================================================+
+---------------------------+---------------+----------------------------------------------------+
| NPU Chip | Process id | Process name | Process memory(MB) |
+===========================+===============+====================================================+
| No running processes found in NPU 5 |
+===========================+===============+====================================================+
```

如果 `npu-smi` 找不到,回到 [快速安装昇腾环境](https://ascend.github.io/docs/sources/ascend/quick_install.html) 检查驱动与设备挂载。

### 2.2 确认 CANN 已加载

```shell
test -n "$ASCEND_HOME_PATH"
```

命令成功时没有输出。

## 3. 安装 PyTorch NPU 栈

安装 `torch_npu`、`torchvision`、`numpy` 与 `pyyaml`,并打印 `torch`、`torch_npu` 和 `npu_available`。

```shell #test id="install-torch"
python -m pip install --retries 3 \
--index-url https://download.pytorch.org/whl/cpu \
--extra-index-url https://pypi.org/simple \
torch_npu torchvision numpy pyyaml
python -c "import numpy, yaml, torch, torch_npu; print('torch', torch.__version__); print('torch_npu', torch_npu.__version__); print('npu_available', torch.npu.is_available())"
```

完整输出较长,其中应包含:

```shell #test-result id="install-torch"
...
torch ...+cpu
torch_npu ...
npu_available True
```

`npu_available` 为 True。

## 4. 安装 DiffSynth-Studio

安装 `<ref>` 对应的 PyPI 正式版,然后打印设备类型和设备名。

<!--
```shell #test-setup store="upstream_ref"
python -m pip index versions diffsynth 2>/dev/null | awk 'NR==1 { gsub(/[()]/, "", $2); print $2 }'
```
-->

```shell #test id="install-diffsynth" load="upstream_ref>>ref"
python -m pip install --retries 3 --no-build-isolation "diffsynth==<ref>"
python -c "import torch, torch_npu; from importlib.metadata import version; from diffsynth.core.device.npu_compatible_device import get_device_name, get_device_type; print('diffsynth', version('diffsynth')); print('device_type', get_device_type()); print('device_name', get_device_name())"
```

输出结果如下:

```shell #test-result id="install-diffsynth"
...
diffsynth ...
device_type npu
device_name npu:0
```

```{note}
将 `<ref>` 换成 最新的 release 版本号
```

## 5. 在 NPU 上生成一张图

用 Python 执行以下代码。种子为 42,推理 5 步,高和宽都是 512。权重从 Hugging Face 下载。用 python 执行以下代码:

```python #test id="generate"
import torch
import torch_npu
from diffsynth.core import ModelConfig
from diffsynth.core.device.npu_compatible_device import get_device_name
from diffsynth.pipelines.stable_diffusion import StableDiffusionPipeline

print("device_name", get_device_name())
pipe = StableDiffusionPipeline.from_pretrained(
torch_dtype=torch.float32,
device="npu",
model_configs=[
ModelConfig(
model_id="stable-diffusion-v1-5/stable-diffusion-v1-5",
origin_file_pattern="text_encoder/model.safetensors",
download_source="huggingface",
),
ModelConfig(
model_id="stable-diffusion-v1-5/stable-diffusion-v1-5",
origin_file_pattern="unet/diffusion_pytorch_model.safetensors",
download_source="huggingface",
),
ModelConfig(
model_id="stable-diffusion-v1-5/stable-diffusion-v1-5",
origin_file_pattern="vae/diffusion_pytorch_model.safetensors",
download_source="huggingface",
),
],
tokenizer_config=ModelConfig(
model_id="stable-diffusion-v1-5/stable-diffusion-v1-5",
origin_file_pattern="tokenizer/",
download_source="huggingface",
),
)
print("pipe.device", pipe.device)
print("unet.device", next(pipe.unet.parameters()).device)
image = pipe(
prompt="a photo of an astronaut riding a horse on mars, high quality, detailed",
negative_prompt="blurry, low quality, deformed",
cfg_scale=7.5,
height=512,
width=512,
seed=42,
rand_device="npu",
num_inference_steps=5,
)
image.save("image.jpg")
print("image_size", image.size)
```

完整输出较长,其中应包含:

```text #test-result id="generate"
device_name npu:0
...
pipe.device npu
unet.device npu:0
image_size (512, 512)
...
```

## 6. 更多用法

本文演示的是单卡上用 Stable Diffusion 1.5 生成一张图。LoRA、视频生成和其他管线与社区文档相同,见 [DiffSynth-Studio 文档中心](https://diffsynth-studio-doc.readthedocs.io/zh-cn/latest/)。
29 changes: 29 additions & 0 deletions tests/diffsynth_studio/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""Tests package marker.

Single responsibility: inject the repo's ``tests/`` into ``sys.path``
so that ``from doc_test.base import ...`` can resolve.

Framework deps (mistune) are installed by the common quick-start workflow
template, not at import time here.

Why it lives here:
* unittest treats ``tests/`` as a package; the parent ``__init__.py``
executes before any submodule import.
* It runs before ``tests/test_*.py`` import, which is the earliest
opportunity to inject ``sys.path``.
"""

from __future__ import annotations

import sys
from pathlib import Path

# sys.path bootstrap: make ``doc_test.*`` resolvable.
# Layout: tests/diffsynth_studio/__init__.py -> parents[0]=tests/diffsynth_studio,
# parents[1]=tests, parents[2]=repo root.
_REPO_ROOT = Path(__file__).resolve().parents[2]
_TESTS_ROOT = _REPO_ROOT / 'tests'
for _p in (_TESTS_ROOT, _REPO_ROOT):
_ps = str(_p)
if _ps not in sys.path:
sys.path.insert(0, _ps)
Loading
Loading