使用Claude Code将Moebius 0.2B图像修复模型移植到浏览器中运行
摘要
Simon Willison借助Claude Code,将Moebius 0.2B图像修复模型移植到浏览器中运行,使用了WebGPU和ONNX Runtime。最终的演示允许用户上传图片并通过修复移除物体。
暂无内容
查看缓存全文
缓存时间: 2026/06/23 01:40
# 使用 Claude Code 将 Moebius 0.2B 图像修补模型移植到浏览器中运行
来源:https://simonwillison.net/2026/Jun/22/porting-moebius/
2026年6月22日
今天早上在 Hacker News (https://news.ycombinator.com/item?id=48630171) 上看到 Moebius: 0.2B 轻量级图像修补框架,拥有 10B 级性能 (https://hustvl.github.io/Moebius/),描述了一个小巧但有效的修补模型——这种模型可以标记图像中要移除的区域,然后模型会想象出应该填充的内容。发布的模型需要 PyTorch 和 NVIDIA CUDA (https://github.com/hustvl/Moebius/blob/9310b76e368f5f7a8ecdf06493231af279c9973b/requirements.txt#L1),但由于它自称只有 0.2B 参数,我决定尝试用 WebGPU 在浏览器中运行它。简而言之:我成功了,你可以在 simonw.github.io/moebius-web/ (https://simonw.github.io/moebius-web/) 试用演示。详情如下。
#### 最终工具
这是最终工具的视频演示:
你可以打开任意图像(非方形图像会加黑边),高亮需要移除的区域,点击“Run inpaint”按钮,等待模型施展魔法。
#### 一个并行代理的副项目
我今天的首要任务是在 Datasette 中落地一个主要功能:创建和修改表的 UI,作为上周发布的 insert and edit rows 功能 (https://simonwillison.net/2026/Jun/16/datasette/) 的后续。
我当时在 Codex Desktop 中开发这个功能(这里是 PR (https://github.com/simonw/datasette/pull/2788)),经常发现自己要花 5-10 分钟干等它完成中等规模的代码重构或对 UI 修改的收尾工作。
(编程代理的一个有趣之处在于,问题越难,你在等它们完成计算时能分心的时间就越多!)
于是我决定在终端窗口启动 Claude Code,看看把 Moebius 移植到网页上能走多远。
#### 用代理研究来启动项目
我的第一步是让普通 Claude 评估这个项目的可行性。在 Claude.ai (https://claude.ai/) 中,它可以克隆 GitHub 仓库:
> `Clone https://github.com/hustvl/Moebius/ 并告诉我他们是否发布了运行此模型的代码和权重`
(我之前没注意到权重的链接,它藏在“新闻”部分。)
然后:
> `对于 Moebius,目前有哪些运行选项?——只有 Python 和 NVIDIA CUDA,还是也有其他选项?`
接着:
> `思考一下将其移植到 Transformers.js 或类似技术并在浏览器中运行的可行性`
我喜欢让模型“思考一下 X”,这是我发现的最简洁的方式,用来表达我希望它为我考虑一个问题,而不给出具体目标。
这是对话记录 (https://claude.ai/share/551c3dc8-17ce-4a4b-a0c9-8cbded6c7bf1)。我把最后一个答案复制出来,保存为 research.md (https://github.com/simonw/moebius-web/blob/main/research.md),供 Claude Code 稍后读取。
Claude 建议使用 ONNX Runtime Web 的 WebGPU 后端——这是我提议的 Transformers.js (https://huggingface.co/docs/transformers.js/en/index) 库的底层。
这足以让我相信值得让 Claude Code 试试看,看它能走多远。
我通常这样启动项目:尽可能多地收集编码代理可能需要的资料。由于我预期这个项目不会真的成功,所以所有操作都在 `/tmp` 文件夹中完成:
```
cd /tmp
mkdir Moebius
cd Moebius
# 获取 Moebius 的 Python 代码
git clone https://github.com/hustvl/Moebius
# 以及模型权重(Claude 搞清楚了这一点):
GIT_LFS_SKIP_SMUDGE=0 git clone \
https://huggingface.co/hustvl/Moebius Moebius-weights
# 最后是几个可能用到的库:
git clone https://github.com/huggingface/transformers.js
git clone https://github.com/microsoft/onnxruntime
```
#### 启动 Claude Code
我为项目的其余部分创建了一个目录,并在其中运行 `git init`,以便 Claude 可以开始提交代码笔记:
```
mkdir /tmp/Moebius/moebius-web
cd /tmp/Moebius/moebius-web
git init
# 复制之前的 research.md
git add research.md
git commit -m "Claude Opus 4.8 的初步研究"
```
我在 `/tmp/Moebius` 文件夹中启动了一个 `claude` 实例,该文件夹位于我为它准备的所有研究材料的上层。我输入了提示:
> `阅读 ./moebius-web/research.md —— 你的目标是将此模型移植到 ONNX 和 WebGPU,以便我们能在浏览器中直接运行它,同时带有一个简单的 UI`
当它开始工作时,我补充了以下提示(包含拼写错误):
> `在 /tmp/Moebius/moebius-web 中构建,并频繁提交,同时在里面维护一个 notes.md 文件,记录你一路学到的东西——还要先在里面写一个 plan.md,并在你工作时更新这个计划`
我经常让代理保留这样的笔记——最终结果通常很有趣,无论对我自己还是对下次处理同一项目的代理会话来说都是如此。这是项目结束时 notes.md 文件 (https://github.com/simonw/moebius-web/blob/main/notes.md) 的样子。
我启动它后,就回到自己的主要项目,偶尔检查一下 Claude 的进展。当它看起来可能弄出点能用的东西时,我提示:
> `告诉我可以在自己浏览器中访问哪个 URL 来试试`
然后我在 Chrome 中试了试,把一些错误(以及错误截图)粘贴回 Claude Code。
经过几轮这样的迭代,我们终于有了看起来能用的东西!是时候把它放到网上让别人也能用了。
> `我们如何将模型权重发布到 Hugging Face 上,并把 HTML 演示放到 Hugging Face Spaces 中?`
Claude Code 知道如何使用 `hf` CLI 工具,所以我在 Hugging Face (https://huggingface.co/) 上创建了一个模型仓库,然后创建了一个 token (https://huggingface.co/settings/tokens),可以写入该仓库,并将其放入 `/tmp/Moebius/token.txt` 文件,供 Claude 使用。
它为我将转换好的 1.24GB ONNX 权重发布到了 huggingface.co/simonw/Moebius-ONNX (https://huggingface.co/simonw/Moebius-ONNX)。
我之前见过其他演示从 Hugging Face 加载权重到浏览器,所以知道这是可行的。我决定将前端代码托管在自己的 GitHub Pages 上,于是说:
> `我想把 moebius-web 文件夹发布到 GitHub,不包括大文件(可能不包括 models/ 文件夹),这样当我为那个仓库启用 GitHub Pages 时,访问 https://simonw.github.io/moebius-web/ 就能提供 UI`
告诉它最终的 URL 很重要,以防它需要修改正在构建的演示中的 URL,使其在部署到生产环境后能正常工作。
又经过几轮迭代,在主项目的间歇中,我们终于得到了一个能工作且已部署的版本!
只是……每次重新加载页面时,它似乎都要下载约 1.3GB 的模型权重。浏览器缓存对这个来说似乎非常重要!
> `有什么巧妙的方法可以用 serviceworker 之类的东西来帮助缓存这些内容吗?它似乎每次都要重新加载,我担心 Hugging Face 的重定向方式可能有问题,导致我们无法利用浏览器缓存`
我知道 Transformers.js 项目可以正确处理这个问题,所以我下载了一份 Whisper Web (https://huggingface.co/spaces/Xenova/whisper-web) 演示,放入 `/tmp/Moebius/whisper-web`,然后说:
> `用子代理查看 /tmp/Moebius/whisper-web,看看他们是怎么做的`
那个项目是完全混淆的、构建好的 JavaScript 文件,所以我认为使用子代理可以避免花费剩余的高级 token 上下文来解读那些文件。
Claude 发现它使用了 `caches.open("transformers-cache")`——即 CacheStorage API (https://developer.mozilla.org/zh-CN/docs/Web/API/CacheStorage/open)——并将其添加到了我们的项目 (https://github.com/simonw/moebius-web/commit/05c1cbc4894460a70a8bc1718ac6d152219e0f28#diff-fb89c342dfa36f544a2d16a885b0f3d1d49f436a7d0eaeb80505f80a1f922603) 中。
我已经分享了该项目的完整 Claude Code 记录 (https://gisthost.github.io/?58039ba5c1ca3ed177e8659168996ee4)(使用我的 claude-code-transcripts (https://github.com/simonw/claude-code-transcripts) 工具发布)。
#### 我从中学到了什么?
这绝对算得上是“氛围编码”:我没有看项目中的一行代码,只限于测试、建议小的功能改进(比如大文件下载的进度条),以及引导模型了解我希望事情如何运作的示例。
由于我没有写任何代码,我对底层技术——WebGPU、ONNX 以及 Moebius 模型本身——的了解非常有限。
和这类项目通常的情况一样,我学到的最重要的事情是关于什么 是可能的:
- Claude Opus 4.8 能够将 PyTorch 模型转换为 ONNX,将结果发布到 Hugging Face,然后构建一个可以加载并执行该模型的 Web 应用程序和界面。
- Chrome、Firefox 和 Safari 现在都能够运行这类模型——我在三者中都试过了。
- CacheStorage API 可以处理约 1.3GB 的模型文件。
- ……这意味着我们可以让修补功能成为纯客户端 Web 应用程序的一个特性!(只要用户能忍受 1.3GB 的下载量。)
我觉得自己或许应该稍微多了解一下自己的项目。我启动了 Claude.ai (https://claude.ai/),输入提示:
> `Clone https://github.com/simonw/moebius-web/ 并用它来教我所有关于这个模型、ONNX 以及将模型转换为 ONNX 和 WebGPU 的过程,基本上就是我能完全理解这个仓库所需的一切知识`
这是对话记录 (https://claude.ai/share/d11b8f2b-a52d-4ca2-be75-a710eaf18572) 以及它创建的 understanding.md (https://github.com/simonw/moebius-web/blob/main/understanding.md) Markdown 文件,我现在已经将其添加到 GitHub 仓库。我觉得对 ONNX 的解释特别有启发:
> **ONNX**(开放神经网络交换格式)是一种可移植、框架无关的神经网络文件格式。一个 `.onnx` 文件本质上包含两样东西:1. **计算图**——一个有向图,包含**节点**,每个节点是一个**算子**(`Conv`、`MatMul`、`Add`、`Einsum`、`Softmax`、`Gather`、`Resize`……),通过命名的张量连接在一起。这就是前向传播的“配方”。2. **权重**——学习到的参数张量(卷积核、嵌入表等),作为同一个图中的初始化器存储。关键的是,ONNX 抽象地描述*要计算什么*,而不说明*如何*或*在什么硬件上*计算。算子集通过**opset** 编号进行版本管理(本仓库使用 **opset 18**),它精确定义了哪些算子存在及其语义。
原来 PyTorch 内置了导出到 ONNX 的机制,如 export_onnx.py (https://github.com/simonw/moebius-web/blob/080be6e737ec976130e260d34707d7d9b7f63d5b/python/export_onnx.py#L91) 所示:
```
torch.onnx.export(
dec, (lat,), dec_path, opset_version=args.opset,
input_names=["latent"], output_names=["image"],
dynamic_axes={"latent": {0: "B"}, "image": {0: "B"}},
)
```
它还包括一个方便的术语表 (https://github.com/simonw/moebius-web/blob/main/understanding.md#12-mini-glossary) 和一个仅略有瑕疵的 ASCII 艺术图 (https://github.com/simonw/moebius-web/blob/main/understanding.md#10-putting-the-whole-pipeline-in-one-picture),展示了模型流水线如何组合在一起。
相似文章
Moebius:0.2B轻量级图像修复框架,具备10B级性能
Moebius是一个0.22B参数的图像修复框架,媲美FLUX.1-Fill-Dev等10B级别模型,通过新颖的局部-全局交互模块和自适应蒸馏策略,实现超过15倍的推理加速。
Bonsai 27B:使用自定义WebGPU内核在浏览器中本地运行的1比特密集型大语言模型
Bonsai 27B是一个1比特密集型大语言模型,通过使用自定义WebGPU内核可以在浏览器中本地运行,实现高效的设备端推理。
Show HN: 通过 WebGPU 在浏览器中运行 Manim(3Blue1Brown 的动画引擎)
Academa Studio 使用 WebGPU 将 3Blue1Brown 的 Manim 动画引擎带到浏览器,实现原生 AI 的 Manim 编辑,无需本地环境配置。
浏览器中的1位LLM
一款1位LLM(Bonsai)现在可以通过WebGPU在浏览器中运行,实现高效的设备端推理。
PrismML 刚刚发布了二值和三值的 Bonsai Image 4B:一种 1比特/三值文本到图像扩散变换器,甚至可以在浏览器中通过 WebGPU 100% 本地运行。
PrismML 发布了 Bonsai Image 4B 模型的二值和三值量化版本,使得文本到图像生成可以仅用 3GB 大小通过 WebGPU 在浏览器中本地运行,采用 Apache-2.0 许可证。