从 HuggingFace 搬家到魔搭:一个二次元项目的上线手记
零,缘起
我们项目的 GitHub 仓库公开之后,魔搭的小编在 Twitter 上找到我,说“创空间正在做测试,如果愿意把 demo 放过来,可以免费用一台 Ada 系列的机器,方便国内用户直接跑模型做测试”。我当时的第一反应是“那试试看”。试完发现还是挺划算的:等于在国内白得了一个 CDN 加一台随时能访问的推理服务器。用户点进去就能用,不用折腾网络优化之类的繁复操作。对一个没什么预算的学术项目来说,“用户点开就能用”这一步很重要,而且也算是给我们的项目做了一个小小的宣传,算是互相成就了。
我们只是个做二次元图形学的研究组,方向小众,没有商业化,也没有预算买一张推理卡挂个常驻 demo。模型跑一次要占十几个 G 显存,跑一次两三分钟,这种东西自己租台服务器只怕是第二天就欠费下线了。有这样一个服务平台,对我们来说是非常有帮助的。
魔搭给的是一个 Ada 系列显卡、48G 显存、8 vCPU、64G 内存的空间,我们一直用到了现在。数据相当不错:
- 45,789 次访问,15,798 位独立访客
- 26,978 次真实推理
- 279 个喜欢,7 条社区反馈帖
我们也听到了一些来自社区的反馈,特别是画师、独立游戏开发者、以及做 Live2D 的朋友。在此之前,他们访问这个工具确实有困难。我们在 HuggingFace 上也有一个 Space,但国内访问不一定顺畅,ZeroGPU 的免费额度一天也只够跑一两次。魔搭提供了一个国内访问友好的 demo,我们也能和社区互动。

运行中的 See-Through 创空间。顶栏能看到 xGPU 和 MCP 的标识。
一、我们的项目
简单说:给一张动漫角色立绘,自动拆成一堆带透明通道的语义图层,按深度排好序,输出一个分层 PSD。
头发、脸、眼睛、衣服、配饰,每一层都是完整修复过的,而且被遮挡的部分也给你补上。做 Sprite 拆立绘、做 Live2D 前期分层、做游戏角色部件拆解的朋友应该懂这个需求,手工做一遍是真的费时间,有一个初步的分层对于他们来说还是有些帮助的。
从流程上讲,我们的系统是两个大的模块串在一起:
- LayerDiff 3D——基于 SDXL 的扩散模型,负责生成带透明度的分层。这是大头。
- 微调过的 Marigold——负责估计深度,用来定图层的前后顺序。
训练数据是我们自己标注的一批 Live2D 模型。Live2D 天然就是分层的,每个 Drawable 就是一个独立图层,有深度、有遮挡关系,而且这些分层是艺术家自己设计的,质量非常好。
它到底重在哪
跟大语言模型比,我们的模型并不算重量级。但在图像和扩散模型这一档里,它确实属于偏重的那一类,而且不止体现在分辨率上,更是一个结构问题。23 个图层是在同一个 diffusion process 里面一起生成的。 我们的 UNet 内部是一个 Transformer3DModel,把图层当成“帧”送进去,并且在每个空间位置上跨图层做一次 attention,因为前发得知道后发在哪,衣领得知道脖子在哪,不然拼回去必然对不上。换句话说,结构上它更像一个视频模型,只不过把时间维度换成图层维度。一次 1280 分辨率的推理,本质上是一次 30 步、23 帧的视频生成。
在 1024 分辨率下我们的运行时间差不多是:
[21:11:32] LayerDiff done (103.4s)
[21:11:47] Marigold done (15.4s)
[21:11:47] PSD assembly done (0.4s)
[21:11:47] Total inference time: 119.7s
1280 分辨率约 200 秒:
[03:00:33] Total inference time: 198.7s
与此同时,两个 pipeline 的权重又要常驻显存(bf16 下十几个 G)。这样看来,测试我们的模型确实需要一张大显存、性能足够的卡。魔搭这就帮了大忙了:同一份模型,这边默认 1024、上限能拉到 1600;而 HuggingFace 那边默认 768、上限 1280。如果超过 1280 分辨率,大概率就要超时了。
二、怎么部署:实际流程
如果手上有一个能跑的 Gradio 应用,那整个流程会非常简单。
我的起点是 HuggingFace Space,app.py 是现成的。下面这套流程算是对魔搭开发的一个简单总结。
2.1 建空间、选硬件
新建创空间,选 gradio 作为部署框架,然后在部署设置里挑硬件。xGPU 的免费档目前有 Tesla 系列(16G 显存)和 Ada 系列(48G 显存),我们用的是后者。(需要加入一个叫 xGPU 乐园的组织,找运营申请一下。)

部署设置页。部署框架、云资源规格、镜像版本,这三项后面都会用到。
镜像版本那一栏写着:
ubuntu22.04-py311-torch2.9.1-modelscope1.35.0
意思是 Python 3.11、PyTorch 2.9.1、modelscope 1.35.0 镜像里已经装好了。
2.2 推代码
创空间就是一个 git 仓库,和 HuggingFace Space 一样:
# 注意默认分支是 master,不是 main
git remote add modelscope https://oauth2:<你的令牌>@www.modelscope.cn/studios/<用户名>/<空间名>.git
git push modelscope master
令牌在 http://modelscope.cn/my/myaccesstoken 拿。
仓库里最少要有三个文件:app.py、requirements.txt、README.md。README 的 frontmatter 是魔搭自己的一套定义:
---
domain:
- cv
tags:
- layer-decomposition
- anime
- psd
models:
- ljsabc/seethroughv0.0.2_layerdiff3d
- ljsabc/seethroughv0.0.1_marigold
license: Apache License 2.0
---
models: 这个字段 HuggingFace 那边没有对应物,它把创空间和模型库关联起来。建议填一下,这样只想拿模型、或者想了解模型信息的人能顺着找过去。
2.3 模型放哪
把权重传到魔搭的模型库,然后用 modelscope 的接口下载:
from modelscope import snapshot_download
_local_layerdiff = snapshot_download("ljsabc/seethroughv0.0.2_layerdiff3d")
_local_depth = snapshot_download("ljsabc/seethroughv0.0.1_marigold")
国内的上传下载速度很快。而且空间启动直接从模型库拉数据,所以基本不会遇到拉一半断掉的情况。整个权重仓库重新校验一遍不到 30 秒:
| INFO | modelscope_hub.download | Downloading 23 files from ljsabc/seethroughv0.0.2_layerdiff3d@master
另外,缓存目录是平台替你配好的,落在 /mnt/workspace 下面,而这个目录是持久化的,所以重启不会重新下一遍权重。
2.4 GPU 怎么用
这是从 HuggingFace 搬过来最需要改的地方。
ZeroGPU 是“申报预算”模式,你需要显式地写 @spaces.GPU(duration=N),N 从调用者的每日额度里预扣,超了直接拒绝执行。
魔搭的 xGPU 简单一些。没有 duration,容器初始化的时候 GPU 就在。所以把 .to("cuda") 直接放模块级就行:
# 模块级直接加载到 GPU,不需要任何装饰器
_layerdiff_pipe.unet.to(dtype=torch.bfloat16, device="cuda")
_layerdiff_pipe.vae.to(dtype=torch.bfloat16, device="cuda")
# ...
_marigold_pipe.to(device="cuda", dtype=torch.bfloat16)
冷启动慢一点(在我们的空间上大约 100 秒,包括拉权重、校验和 pipeline 初始化),但是实际上根据我们的日志,空间大部分的时间都是热着的,无需重新初始化。说实话提交这个改动的时候我心里没底,commit message 里还写了“如果 xGPU 在 init 阶段拿不到 GPU 就回滚”。结果是一路畅通,一直跑到了今天。
三、适配
下面是踩过的一些坑,给大家做下参考。
1. 别在 requirements.txt 里 pin torch。 镜像自带 torch 2.9.1。写 torch==2.8.0 会让 pip 先把镜像里的卸载掉再重装;而只要留着 --extra-index-url https://download.pytorch.org/whl/cu128,解析器就一定会去境外那个源拉将近 4G 的 PyTorch 安装包(PEP 440 里 2.8.0+cu128 排序上大于 2.8.0)。把 torch、torchvision 和那行 extra-index-url 一起删掉就好。(顺带一提,网上“某某 PyPI 镜像会重定向回官方源”的说法并不成立,不用在几个镜像之间反复横跳。)
2. >= 对镜像里已有的包是空操作。 这条我们是真踩过。平台执行的是 pip install -r requirements.txt,不带 --upgrade。镜像里预装了 ms-swift,它顺带把 peft 也带进来了。我们撞上的现象是启动时报:
ImportError: cannot import name 'HybridCache' from 'transformers'
而 requirements 里根本没写 peft(transformers 5.x 删掉了 HybridCache,某几个版本的 peft 会在导入时无条件引用它,diffusers 建 pipeline 时又会去 import peft)。加 peft>=0.14.0 完全没用,因为镜像里那个版本已经满足条件,pip 打印一句 Requirement already satisfied 就走了。写成 peft>=0.18.0,下限超过镜像里的版本,才真正触发升级。
提示:>= 只用来表示“我不想覆盖镜像里的版本”(比如 torch)。任何你需要真正改变版本的包,得用 ==,或者一个明确高于镜像版本的下限。
3. gradio、pydantic 由平台控制,别写进 requirements.txt。 平台的安装顺序是:先装自己的 gradio==6.2.0,再按需装 gradio[mcp],然后升级 modelscope,最后才轮到我们自己的 requirements.txt。
gradio 那步会把 pydantic 降级(2.13.4 → 2.12.5),而 pydantic 和 pydantic-core 是精确绑定的一对,版本对不上会在 import pydantic 时直接抛 SystemError。
4. 是 from modelscope import snapshot_download。 有点绕的一个地方:写成 from modelscope.hub import snapshot_download 不会报错,因为 modelscope/hub/snapshot_download.py 确实是个存在的模块文件,Python 找不到属性时会回退去导入同名子模块。于是你拿到的是模块对象而不是函数,报错发生在十几行之后的调用处,只有一句 TypeError: 'module' object is not callable,看着莫名其妙。这个坑是 agent 帮我翻出来的。
顺便给从 HuggingFace 迁移的朋友一份速查:
| HuggingFace | ModelScope |
| huggingface_hub.snapshot_download | modelscope.snapshot_download |
| hf_hub_download(repo, filename) | modelscope.model_file_download(model_id, file_path) |
| 默认分支 main | 默认分支 master |
| HF_HOME | MODELSCOPE_CACHE |
| HF_TOKEN | MODELSCOPE_API_TOKEN |
5. 搜一遍代码里写死的 http://huggingface.co。 这条是我们自己挖的坑。我们有个写死的依赖库,里面的 pipeline 类会去 http://huggingface.co 拉一个叫 juggernautXL 的仓库,只为了读一份十几行的 scheduler_config.json。这个仓库名 app.py 和 requirements 里一个字都没提,但它会让启动多一次境外访问,连不通的时候启动就跟着失败。
这种小配置文件其实根本不用联网拖库,本地缓存一份、显式传进去就可以了:
_scheduler = DPMSolverMultistepScheduler.from_pretrained(
_local_layerdiff, subfolder="scheduler",
algorithm_type="sde-dpmsolver++", final_sigmas_type="zero",
)
_layerdiff_pipe = KDiffusionStableDiffusionXLPipeline.from_pretrained(
_local_layerdiff, ..., scheduler=_scheduler # 不要传 None
)
部署前花三十秒 grep 一下就能发现:
grep -rn "huggingface.co\|from_pretrained(\"[a-zA-Z0-9_-]*/" your_project/
实在懒得改,也可以先用 HF_ENDPOINT=https://hf-mirror.com 兜底。
看日志也很关键。日志入口在 空间管理 → 查看日志 → 运行日志。

日志入口

支持构建日志/运行日志切换、5 秒轮询刷新、搜索和整包下载,保留近 7 天内 1 万条。
有一个地方要留意:gradio 类型的创空间,“构建日志”是空的,pip install 的输出实际上打在运行日志里(“构建日志”是给 docker 类型用的)。
上面这几个问题,运行日志里全都写得很明白。把日志下载下来自己读一遍,或者干脆丢给 agent 读,基本就能定位、解决问题了。
四、数据、社区,以及再次感谢
在我们所有的演示渠道里,这里是使用量最高的一处了(两万七千次推理)。对一个自己真的在意的项目来说,有人用才是最好的,作为项目主催我很欣慰。
感谢社区
创空间的交流反馈区有一些社区的意见。

社区反馈
有人很仔细地指出“发饰类小部件切割会缺失,但耳坠不会消失,很神奇”。这确实是模型的已知弱点。小尺寸高频部件在分层时的确容易被吸进相邻图层。有人问“psd 分成为什么没有颜色了”,有人报告“突然提示 502 了”。也有人写“今天效果棒棒的,是不是进化了”:其实我们没改模型,但看到这条的时候还是挺开心的。
社区的反馈和论文里的指标都很重要。论文的统计数据是在我们自己划的测试集上跑的,而真实用户会拿各种我们完全没想到的图来试:超长的立绘、多人构图、非常规的画风和角色设计。我们下一版的改进方向,也会参考这些反馈和意见。
最后
正如开头说的,做二次元方向的工具其实不那么划算。和大模型、具身智能比起来,我们的方向影响力和关注度都要小很多——然而有些事情总还是要去做的。很多时候做下来才发现,卡住我们的有时候不是想法,是用户的意见和社区的反馈。
感谢魔搭提供了这次机会,给了我们一个长期免费试用的空间。未来我也准备把组里以前的一些老 demo 也慢慢移植过来。也欢迎各位来创空间试试这个项目,上传一张立绘,三分钟后你会拿到一个分层 PSD。
也感谢小编的耐心(和催稿)。
See-Through 是我们组发表在 ACM SIGGRAPH 2026 Conference Proceedings 的工作。代码、模型权重、GUI 和训练代码均已开源。欢迎试用,也欢迎在创空间的交流反馈区拍砖。
声明:本项目为开源研究项目,我们未开设任何付费服务。如遇到以此功能收费的网站,均与我们无关,请注意甄别。
创空间链接:https://modelscope.cn/studios/ljsabc/See-Through
代码:https://github.com/shitagaki-lab/see-through
论文:https://arxiv.org/abs/2602.03749
更多推荐




所有评论(0)