<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom"><title>Simon Willison's Weblog: transformers-js</title><link href="http://simonwillison.net/" rel="alternate"/><link href="http://simonwillison.net/tags/transformers-js.atom" rel="self"/><id>http://simonwillison.net/</id><updated>2026-06-22T23:43:51+00:00</updated><author><name>Simon Willison</name></author><entry><title>Porting the Moebius 0.2B image inpainting model to run in the browser with Claude Code</title><link href="https://simonwillison.net/2026/Jun/22/porting-moebius/" rel="alternate"/><published>2026-06-22T23:43:51+00:00</published><updated>2026-06-22T23:43:51+00:00</updated><id>https://simonwillison.net/2026/Jun/22/porting-moebius/</id><summary type="html">
    &lt;p&gt;This morning &lt;a href="https://news.ycombinator.com/item?id=48630171"&gt;on Hacker News&lt;/a&gt; I saw &lt;a href="https://hustvl.github.io/Moebius/"&gt;Moebius: 0.2B Lightweight Image Inpainting Framework with 10B-Level Performance&lt;/a&gt;, describing a small but effective inpainting model - a model where you can mark regions of an image to remove and the model imagines what should fill the space. The released model &lt;a href="https://github.com/hustvl/Moebius/blob/9310b76e368f5f7a8ecdf06493231af279c9973b/requirements.txt#L1"&gt;required PyTorch and NVIDIA CUDA&lt;/a&gt;, but since it described itself as 0.2B I decided to try and get it running using WebGPU in a browser. TL;DR: I got it working, and you can try the demo at &lt;a href="https://simonw.github.io/moebius-web/"&gt;simonw.github.io/moebius-web/&lt;/a&gt;. Read on for the details.&lt;/p&gt;
&lt;h4 id="the-finished-tool"&gt;The finished tool&lt;/h4&gt;
&lt;p&gt;Here's a video demo of the finished tool:&lt;/p&gt;

&lt;video
width="1280"
height="1070"
poster="https://static.simonwillison.net/static/2026/inpainting_1280_poster.jpg"
preload="none"
controls="controls"
playsinline="playsinline"
style="max-width:100%;height:auto"&gt;
&lt;source src="https://static.simonwillison.net/static/2026/inpainting_1280.mp4" type="video/mp4" /&gt;
&lt;/video&gt;

&lt;p&gt;You can open any image in it (non-square images get letterboxed), highlight areas to remove, click the "Run inpaint" button and wait for the model to do its magic.&lt;/p&gt;
&lt;h4 id="a-parallel-agent-side-project"&gt;A parallel agent side-project&lt;/h4&gt;
&lt;p&gt;My main project for today was landing a major feature in Datasette: a UI for creating and altering tables, as a follow-up to the &lt;a href="https://simonwillison.net/2026/Jun/16/datasette/"&gt;insert and edit rows feature&lt;/a&gt; I released last week.&lt;/p&gt;
&lt;p&gt;I was working on that in Codex Desktop (here's &lt;a href="https://github.com/simonw/datasette/pull/2789"&gt;the PR&lt;/a&gt;) and often found myself spending 5-10 minutes spinning my fingers waiting for it to complete a mid-sized refactor or add the finishing touches to a change to the UI.&lt;/p&gt;
&lt;p&gt;(An amusing thing about coding agents is that the harder a problem is the &lt;em&gt;more&lt;/em&gt; time you have to get distracted while you wait for them to finish crunching!)&lt;/p&gt;
&lt;p&gt;So I decided to spin up Claude Code in a terminal window and see how far I could get at porting Moebius to the web.&lt;/p&gt;
&lt;h4 id="some-agentic-research-to-kick-off-the-project"&gt;Some agentic research to kick off the project&lt;/h4&gt;
&lt;p&gt;My first step was to ask regular Claude about the feasibility of this project. In &lt;a href="https://claude.ai/"&gt;Claude.ai&lt;/a&gt;, which has the ability to clone repos from GitHub:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Clone https://github.com/hustvl/Moebius/ and tell me if they published the code and weights to run this model anywhere&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;(I hadn't spotted the link to the weights yet, that's tucked away in the "News" section.)&lt;/p&gt;
&lt;p&gt;Then:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;For Moebius what are the options for running it right now - Python and NVIDIA CUDA only or other options too?&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Muse on the feasibility of porting it to Transformers.js or similar and running it in a browser&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I like telling models to "muse on X", it's the shortest way I've found of expressing that I want them to contemplate a problem for me without providing them with a concrete goal.&lt;/p&gt;
&lt;p&gt;Here's &lt;a href="https://claude.ai/share/551c3dc8-17ce-4a4b-a0c9-8cbded6c7bf1"&gt;that chat transcript&lt;/a&gt;. I copied out the last answer and saved it as &lt;a href="https://github.com/simonw/moebius-web/blob/main/research.md"&gt;research.md&lt;/a&gt; for Claude Code to read later.&lt;/p&gt;
&lt;p&gt;Claude suggested using &lt;strong&gt;ONNX Runtime Web on the WebGPU backend&lt;/strong&gt; - the layer &lt;em&gt;below&lt;/em&gt; the &lt;a href="https://huggingface.co/docs/transformers.js/en/index"&gt;Transformers.js&lt;/a&gt; library I had suggested.&lt;/p&gt;
&lt;p&gt;That was enough to convince me it was worth setting Claude Code loose and seeing how far it could get.&lt;/p&gt;
&lt;p&gt;I usually start projects like this by gathering as much information as the coding agent might need as possible. Since I didn't expect this project to actually work I did everything in my &lt;code&gt;/tmp&lt;/code&gt; folder:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell"&gt;&lt;pre&gt;&lt;span class="pl-c1"&gt;cd&lt;/span&gt; /tmp
mkdir Moebius
&lt;span class="pl-c1"&gt;cd&lt;/span&gt; Moebius
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Grab the Moebius python code&lt;/span&gt;
git clone https://github.com/hustvl/Moebius
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; And the model weights (Claude figured this out):&lt;/span&gt;
GIT_LFS_SKIP_SMUDGE=0 git clone \
  https://huggingface.co/hustvl/Moebius Moebius-weights
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Finally a couple of libraries we might use:&lt;/span&gt;
git clone https://github.com/huggingface/transformers.js
git clone https://github.com/microsoft/onnxruntime&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id="setting-off-claude-code"&gt;Setting off Claude Code&lt;/h4&gt;
&lt;p&gt;I created a directory for the rest of the project and ran &lt;code&gt;git init&lt;/code&gt; in that so Claude could start committing code notes:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell"&gt;&lt;pre&gt;mkdir /tmp/Moebius/moebius-web
&lt;span class="pl-c1"&gt;cd&lt;/span&gt; /tmp/Moebius/moebius-web
git init
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Copy in that research.md from earlier&lt;/span&gt;
git add research.md
git commit -m &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Initial research by Claude Opus 4.8&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I fired up a &lt;code&gt;claude&lt;/code&gt; instance in the &lt;code&gt;/tmp/Moebius&lt;/code&gt; folder, the level above all of the research materials I had prepared for it. I prompted:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Read ./moebius-web/research.md - your goal is to port this model to ONNX and WebGPU so we can run it directly in a browser, with a simple UI&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As it started to work I dropped in this follow-up (typos included):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Bulid this in /tmp/Moebius/moebius-web and commit early and often, also maintain a notes.md file in there with notes about what you figure out along the way - also start by writing out a plan.md in there and update that plan as oy work too&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I often ask agents to keep notes like this - the end result is often interesting, both for myself and for the next agent session that touches the same project. Here's what that &lt;a href="https://github.com/simonw/moebius-web/blob/main/notes.md"&gt;notes.md file&lt;/a&gt; looked like at the end of the project.&lt;/p&gt;
&lt;p&gt;I kicked it off and went back to my main project, checking in occasionally to see how Claude was doing. When it looked like it might have something that worked I prompted:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Tell me what URL I can visit in my own browser to try this&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then I tried it out in Chrome and pasted some errors (and screenshots of errors) back into Claude Code.&lt;/p&gt;
&lt;p&gt;After a few rounds of this we had something that appeared to work! Time to put it on the internet so other people could use it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;How would we publish this to Hugging Face such that the model weights were on there and the HTML demo would show up in Hugging Face spaces?&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Claude Code knows how to use the &lt;code&gt;hf&lt;/code&gt; CLI tool, so I created a model repo on &lt;a href="https://huggingface.co/"&gt;Hugging Face&lt;/a&gt;, then &lt;a href="https://huggingface.co/settings/tokens"&gt;created a token&lt;/a&gt; that could write to that repo and dropped it into a &lt;code&gt;/tmp/Moebius/token.txt&lt;/code&gt; file so Claude could use it.&lt;/p&gt;
&lt;p&gt;It published the 1.24GB of converted ONNX weights to &lt;a href="https://huggingface.co/simonw/Moebius-ONNX"&gt;huggingface.co/simonw/Moebius-ONNX&lt;/a&gt; for me.&lt;/p&gt;
&lt;p&gt;I'd seen other demos load weights into the browser from Hugging Face before, so I knew it was possible. I decided to host my own frontend code on GitHub Pages, so I said:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;I want to publish the moebius-web folder to GitHub, minus the large files (so maybe minus the models/ folder), such that when I turn on GitHub Pages for that repo navigating to https://simonw.github.io/moebius-web/ serves the UI&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Telling it the final URL was important in case it needed to fix the URLs in the demos that it was building so they would work when deployed to production.&lt;/p&gt;
&lt;p&gt;After a few more rounds of iteration, in between working on my main project, we got to a working, deployed version!&lt;/p&gt;
&lt;p&gt;Except... each time I reloaded the page it seemed to download ~1.3GB of model weights. Browser caching seemed pretty important for this!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;anything clever we can do with serviceworkers or similar to help cache this stuff? It seems to reload every time, I am concerned that there might be something weird about the way HF redirects work that mean we don't benefit from browser caching&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I knew that Transformers.js projects could handle this properly, so I grabbed a copy of the &lt;a href="https://huggingface.co/spaces/Xenova/whisper-web"&gt;Whisper Web&lt;/a&gt; demo, dropped it into &lt;code&gt;/tmp/Moebius/whisper-web&lt;/code&gt; and said:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;look in /tmp/Moebius/whisper-web (with a subagent) and see how they do this&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That project was entirely obfuscated, built JavaScript files so I figured using a subagent would avoid spending the rest of my top-level token context deciphering those files.&lt;/p&gt;
&lt;p&gt;Claude figured out that it was using &lt;code&gt;caches.open("transformers-cache")&lt;/code&gt; - the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage/open"&gt;CacheStorage API&lt;/a&gt; - and &lt;a href="https://github.com/simonw/moebius-web/commit/05c1cbc4894460a70a8bc1718ac6d152219e0f28#diff-fb89c342dfa36f544a2d16a885b0f3d1d49f436a7d0eaeb80505f80a1f922603"&gt;added that to our project&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I've shared the &lt;a href="https://gisthost.github.io/?58039ba5c1ca3ed177e8659168996ee4"&gt;full Claude Code transcript&lt;/a&gt; for this project (published using my &lt;a href="https://github.com/simonw/claude-code-transcripts"&gt;claude-code-transcripts&lt;/a&gt; tool).&lt;/p&gt;
&lt;h4 id="what-did-i-learn-from-all-of-this-"&gt;What did I learn from all of this?&lt;/h4&gt;
&lt;p&gt;This definitely counts as vibe coding: I didn't look at a single line of code from the project, restricting my input to testing, suggesting small feature improvements (like a progress bar for the large file downloads) and pointing the model in the direction of examples of how I wanted things to work.&lt;/p&gt;
&lt;p&gt;Since I didn't write any code the amount I learned about the underlying technologies - WebGPU, ONNX, and the Moebius model itself - was very limited.&lt;/p&gt;
&lt;p&gt;As is usually the case with this kind of project the most important things I learned concerned what was &lt;em&gt;possible&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Claude Opus 4.8 is capable of converting a PyTorch model to ONNX, publishing the result to Hugging Face and then building out a web application and interface that can load and execute that model.&lt;/li&gt;
&lt;li&gt;Chrome, Firefox and Safari are all now capable of running this kind of model - I tried it in all three.&lt;/li&gt;
&lt;li&gt;The CacheStorage API works with ~1.3GB model files.&lt;/li&gt;
&lt;li&gt;... which means we can have inpainting as a feature of a client-only web application! (If our users can tolerate the 1.3GB download.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I felt like I should probably try and learn a little more about my project. I fired up &lt;a href="https://claude.ai/"&gt;Claude.ai&lt;/a&gt; and prompted:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Clone https://github.com/simonw/moebius-web/ and use it to teach me all about the model and ONNX and the process of converting a model to ONNX and WebGPU and basically everything I'd need to know in order to fully understand this repo&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here's &lt;a href="https://claude.ai/share/d11b8f2b-a52d-4ca2-be75-a710eaf18572"&gt;the transcript&lt;/a&gt; and the &lt;a href="https://github.com/simonw/moebius-web/blob/main/understanding.md"&gt;understanding.md&lt;/a&gt; Markdown file it created, which I've now added to the GitHub repo. I found the explanation of ONNX particularly enlightening:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;ONNX&lt;/strong&gt; (Open Neural Network Exchange) is a portable, framework-neutral file format for neural networks. An &lt;code&gt;.onnx&lt;/code&gt; file is essentially two things bundled together:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A computation graph&lt;/strong&gt; — a directed graph of &lt;em&gt;nodes&lt;/em&gt;, where each node is an &lt;strong&gt;operator&lt;/strong&gt; (&lt;code&gt;Conv&lt;/code&gt;, &lt;code&gt;MatMul&lt;/code&gt;, &lt;code&gt;Add&lt;/code&gt;, &lt;code&gt;Einsum&lt;/code&gt;, &lt;code&gt;Softmax&lt;/code&gt;, &lt;code&gt;Gather&lt;/code&gt;, &lt;code&gt;Resize&lt;/code&gt;, …) wired together by named tensors flowing between them. This is the "recipe" for the forward pass.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The weights&lt;/strong&gt; — the learned parameter tensors (the convolution kernels, the embedding table, etc.), stored as initializers in that same graph.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Crucially, ONNX describes &lt;em&gt;what to compute&lt;/em&gt;, abstractly, without saying &lt;em&gt;how&lt;/em&gt; or &lt;em&gt;on what hardware&lt;/em&gt;. The operator set is versioned by an &lt;strong&gt;opset&lt;/strong&gt; number (this repo uses &lt;strong&gt;opset 18&lt;/strong&gt;), which pins down exactly which operators exist and what their semantics are.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It turns out PyTorch has built in mechanisms for exporting to ONNX, as seen &lt;a href="https://github.com/simonw/moebius-web/blob/080be6e737ec976130e260d34707d7d9b7f63d5b/python/export_onnx.py#L91"&gt;here in export_onnx.py&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;span class="pl-s1"&gt;torch&lt;/span&gt;.&lt;span class="pl-c1"&gt;onnx&lt;/span&gt;.&lt;span class="pl-c1"&gt;export&lt;/span&gt;(
    &lt;span class="pl-s1"&gt;dec&lt;/span&gt;, (&lt;span class="pl-s1"&gt;lat&lt;/span&gt;,), &lt;span class="pl-s1"&gt;dec_path&lt;/span&gt;, &lt;span class="pl-s1"&gt;opset_version&lt;/span&gt;&lt;span class="pl-c1"&gt;=&lt;/span&gt;&lt;span class="pl-s1"&gt;args&lt;/span&gt;.&lt;span class="pl-c1"&gt;opset&lt;/span&gt;,
    &lt;span class="pl-s1"&gt;input_names&lt;/span&gt;&lt;span class="pl-c1"&gt;=&lt;/span&gt;[&lt;span class="pl-s"&gt;"latent"&lt;/span&gt;], &lt;span class="pl-s1"&gt;output_names&lt;/span&gt;&lt;span class="pl-c1"&gt;=&lt;/span&gt;[&lt;span class="pl-s"&gt;"image"&lt;/span&gt;],
    &lt;span class="pl-s1"&gt;dynamic_axes&lt;/span&gt;&lt;span class="pl-c1"&gt;=&lt;/span&gt;{&lt;span class="pl-s"&gt;"latent"&lt;/span&gt;: {&lt;span class="pl-c1"&gt;0&lt;/span&gt;: &lt;span class="pl-s"&gt;"B"&lt;/span&gt;}, &lt;span class="pl-s"&gt;"image"&lt;/span&gt;: {&lt;span class="pl-c1"&gt;0&lt;/span&gt;: &lt;span class="pl-s"&gt;"B"&lt;/span&gt;}},
)&lt;/pre&gt;
&lt;p&gt;Claude also included a &lt;a href="https://github.com/simonw/moebius-web/blob/main/understanding.md#12-mini-glossary"&gt;handy glossary&lt;/a&gt; and an only-slightly-broken &lt;a href="https://github.com/simonw/moebius-web/blob/main/understanding.md#10-putting-the-whole-pipeline-in-one-picture"&gt;ASCII-art diagram&lt;/a&gt; showing how the model pipeline fits together.&lt;/p&gt;
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/browsers"&gt;browsers&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/transformers-js"&gt;transformers-js&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/webgl"&gt;webgl&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/vibe-coding"&gt;vibe-coding&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/coding-agents"&gt;coding-agents&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/claude-code"&gt;claude-code&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/onnx"&gt;onnx&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="browsers"/><category term="transformers-js"/><category term="webgl"/><category term="vibe-coding"/><category term="coding-agents"/><category term="claude-code"/><category term="onnx"/></entry><entry><title>Load Llama-3.2 WebGPU in your browser from a local folder</title><link href="https://simonwillison.net/2025/Sep/8/webgpu-local-folder/" rel="alternate"/><published>2025-09-08T20:53:52+00:00</published><updated>2025-09-08T20:53:52+00:00</updated><id>https://simonwillison.net/2025/Sep/8/webgpu-local-folder/</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://static.simonwillison.net/static/2025/llama-3.2-webgpu/"&gt;Load Llama-3.2 WebGPU in your browser from a local folder&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Inspired by &lt;a href="https://news.ycombinator.com/item?id=45168953#45169054"&gt;a comment&lt;/a&gt; on Hacker News I decided to see if it was possible to modify the &lt;a href="https://github.com/huggingface/transformers.js-examples/tree/main/llama-3.2-webgpu"&gt;transformers.js-examples/tree/main/llama-3.2-webgpu&lt;/a&gt; Llama 3.2 chat demo (&lt;a href="https://huggingface.co/spaces/webml-community/llama-3.2-webgpu"&gt;online here&lt;/a&gt;, I &lt;a href="https://simonwillison.net/2024/Sep/30/llama-32-webgpu/"&gt;wrote about it last November&lt;/a&gt;) to add an option to open a local model file directly from a folder on disk, rather than waiting for it to download over the network.&lt;/p&gt;
&lt;p&gt;I posed the problem to OpenAI's GPT-5-enabled Codex CLI like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git clone https://github.com/huggingface/transformers.js-examples
cd transformers.js-examples/llama-3.2-webgpu
codex
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then this prompt:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Modify this application such that it offers the user a file browse button for selecting their own local copy of the model file instead of loading it over the network. Provide a "download model" option too.&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Codex churned away for several minutes, even running commands like &lt;code&gt;curl -sL https://raw.githubusercontent.com/huggingface/transformers.js/main/src/models.js | sed -n '1,200p'&lt;/code&gt; to inspect the source code of the underlying Transformers.js library.&lt;/p&gt;
&lt;p&gt;After four prompts total (&lt;a href="https://gist.github.com/simonw/3c46c9e609f6ee77367a760b5ca01bd2?permalink_comment_id=5751814#gistcomment-5751814"&gt;shown here&lt;/a&gt;) it built something which worked!&lt;/p&gt;
&lt;p&gt;To try it out you'll need your own local copy of the Llama 3.2 ONNX model. You can get that (a ~1.2GB) download) like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git lfs install
git clone https://huggingface.co/onnx-community/Llama-3.2-1B-Instruct-q4f16
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then visit my &lt;a href="https://static.simonwillison.net/static/2025/llama-3.2-webgpu/"&gt;llama-3.2-webgpu&lt;/a&gt; page in Chrome or Firefox Nightly (since WebGPU is required), click "Browse folder", select that folder you just cloned, agree to the "Upload" confirmation (confusing since nothing is uploaded from your browser, the model file is opened locally on your machine) and click "Load local model".&lt;/p&gt;
&lt;p&gt;Here's an animated demo (recorded in real-time, I didn't speed this up):&lt;/p&gt;
&lt;p&gt;&lt;img alt="GIF. I follow the setup instructions, clicking to load a local model and browsing to the correct folder. Once loaded the model shows a chat interface, I run the example about time management which returns tokens at about 10/second." src="https://static.simonwillison.net/static/2025/webgpu-llama-demo-small.gif" /&gt;&lt;/p&gt;
&lt;p&gt;I pushed &lt;a href="https://github.com/simonw/transformers.js-examples/commit/cdebf4128c6e30414d437affd4b13b6c9c79421d"&gt;a branch with those changes here&lt;/a&gt;. The next step would be to modify this to support other models in addition to the Llama 3.2 demo, but I'm pleased to have got to this proof of concept with so little work beyond throwing some prompts at Codex to see if it could figure it out.&lt;/p&gt;
&lt;p&gt;According to the Codex &lt;code&gt;/status&lt;/code&gt; command &lt;a href="https://gist.github.com/simonw/3c46c9e609f6ee77367a760b5ca01bd2?permalink_comment_id=5751807#gistcomment-5751807"&gt;this used&lt;/a&gt; 169,818 input tokens, 17,112 output tokens and 1,176,320 cached input tokens. At current GPT-5 token pricing ($1.25/million input, $0.125/million cached input, $10/million output) that would cost 53.942 cents, but Codex CLI hooks into my existing $20/month ChatGPT Plus plan so this was bundled into that.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://news.ycombinator.com/item?id=45168953#45173297"&gt;My Hacker News comment&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llama"&gt;llama&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/local-llms"&gt;local-llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-assisted-programming"&gt;ai-assisted-programming&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/transformers-js"&gt;transformers-js&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/webgpu"&gt;webgpu&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llm-pricing"&gt;llm-pricing&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/vibe-coding"&gt;vibe-coding&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/gpt-5"&gt;gpt-5&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/codex"&gt;codex&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/gpt"&gt;gpt&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/onnx"&gt;onnx&lt;/a&gt;&lt;/p&gt;



</summary><category term="javascript"/><category term="ai"/><category term="generative-ai"/><category term="llama"/><category term="local-llms"/><category term="llms"/><category term="ai-assisted-programming"/><category term="transformers-js"/><category term="webgpu"/><category term="llm-pricing"/><category term="vibe-coding"/><category term="gpt-5"/><category term="codex"/><category term="gpt"/><category term="onnx"/></entry><entry><title>Introducing EmbeddingGemma</title><link href="https://simonwillison.net/2025/Sep/4/embedding-gemma/" rel="alternate"/><published>2025-09-04T22:27:41+00:00</published><updated>2025-09-04T22:27:41+00:00</updated><id>https://simonwillison.net/2025/Sep/4/embedding-gemma/</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://developers.googleblog.com/en/introducing-embeddinggemma/"&gt;Introducing EmbeddingGemma&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Brand new open weights (under the slightly janky &lt;a href="https://ai.google.dev/gemma/terms"&gt;Gemma license&lt;/a&gt;) 308M parameter embedding model from Google:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Based on the Gemma 3 architecture, EmbeddingGemma is trained on 100+ languages and is small enough to run on less than 200MB of RAM with quantization.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It's available via &lt;a href="https://ai.google.dev/gemma/docs/embeddinggemma/fine-tuning-embeddinggemma-with-sentence-transformers"&gt;sentence-transformers&lt;/a&gt;, &lt;a href="https://huggingface.co/collections/ggml-org/embeddinggemma-300m-68b2a87d78ca52408f7918f3"&gt;llama.cpp&lt;/a&gt;, &lt;a href="https://huggingface.co/collections/mlx-community/embeddinggemma-68b9a55aac55466fbd514f7c"&gt;MLX&lt;/a&gt;, &lt;a href="https://ollama.com/library/embeddinggemma"&gt;Ollama&lt;/a&gt;, &lt;a href="https://lmstudio.ai/models/google/embedding-gemma-300m"&gt;LMStudio&lt;/a&gt; and more. &lt;/p&gt;
&lt;p&gt;As usual for these smaller models there's a &lt;a href="https://huggingface.co/blog/embeddinggemma#transformersjs"&gt;Transformers.js&lt;/a&gt; demo (&lt;a href="https://twitter.com/xenovacom/status/1963638444233511016"&gt;via&lt;/a&gt;) that runs directly in the browser (in Chrome variants) - &lt;a href="https://huggingface.co/spaces/webml-community/semantic-galaxy"&gt;Semantic Galaxy&lt;/a&gt; loads a ~400MB model and then lets you run embeddings against hundreds of text sentences, map them in a 2D space and run similarity searches to zoom to points within that space.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of The Semantic Galaxy web application interface showing a semantic search tool with a left sidebar containing &amp;quot;Your Dataset&amp;quot; with sample text &amp;quot;The sun peeked through the clouds after a drizzly&amp;quot; and a blue &amp;quot;Generate Galaxy&amp;quot; button, below which is text &amp;quot;Galaxy generated with 106 points. Ready to explore!&amp;quot; followed by &amp;quot;Search Results&amp;quot; listing various text snippets with similarity scores to the search term &amp;quot;pelican riding a bicycle&amp;quot; such as &amp;quot;The cyclist pedaled up the steep hill... 0.491&amp;quot;, &amp;quot;It was so hot that even the birds sou... 0.446&amp;quot;, etc. The main area shows a dark starfield visualization with white dots representing semantic clusters and text snippets floating as labels near the clusters." src="https://static.simonwillison.net/static/2025/semantic-galaxy-transformers.jpg" /&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/google"&gt;google&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/embeddings"&gt;embeddings&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/transformers-js"&gt;transformers-js&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/gemma"&gt;gemma&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/janky-licenses"&gt;janky-licenses&lt;/a&gt;&lt;/p&gt;



</summary><category term="google"/><category term="ai"/><category term="embeddings"/><category term="transformers-js"/><category term="gemma"/><category term="janky-licenses"/></entry><entry><title>DeepSeek Janus-Pro</title><link href="https://simonwillison.net/2025/Jan/27/deepseek-janus-pro/" rel="alternate"/><published>2025-01-27T21:49:44+00:00</published><updated>2025-01-27T21:49:44+00:00</updated><id>https://simonwillison.net/2025/Jan/27/deepseek-janus-pro/</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/deepseek-ai/Janus?tab=readme-ov-file"&gt;DeepSeek Janus-Pro&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Another impressive model release from DeepSeek. Janus is their series of "unified multimodal understanding and generation models" - these are models that can both accept images as input &lt;em&gt;and&lt;/em&gt; generate images for output.&lt;/p&gt;
&lt;p&gt;Janus-Pro is the new 7B model, which DeepSeek describe as "an advanced version of Janus, improving both multimodal understanding and visual generation significantly". It's released under the not fully open source &lt;a href="https://github.com/deepseek-ai/DeepSeek-LLM/blob/HEAD/LICENSE-MODEL"&gt;DeepSeek license&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Janus-Pro is accompanied by &lt;a href="https://github.com/deepseek-ai/Janus/blob/main/janus_pro_tech_report.pdf"&gt;this paper&lt;/a&gt;, which includes this note about the training:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Our Janus is trained and evaluated using &lt;a href="https://www.high-flyer.cn/en/blog/hai-llm/"&gt;HAI-LLM&lt;/a&gt;, which is a lightweight and efficient distributed training framework built on top of PyTorch. The whole training process took about 7/14 days on a cluster of 16/32 nodes for 1.5B/7B model, each equipped with 8 Nvidia A100 (40GB) GPUs.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It includes a lot of high benchmark scores, but closes with some notes on the model's current limitations:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In terms of multimodal understanding, the input resolution is limited
to 384 × 384, which affects its performance in fine-grained tasks such as OCR. For text-to-image generation, the low resolution, combined with reconstruction losses introduced by the vision tokenizer, results in images that, while rich in semantic content, still lack fine details. For example, small facial regions occupying limited image space may appear under-detailed. Increasing the image resolution could mitigate these issues.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The easiest way to try this one out is using the &lt;a href="https://huggingface.co/spaces/deepseek-ai/Janus-Pro-7B"&gt;Hugging Face Spaces demo&lt;/a&gt;. I tried the following prompt for the image generation capability:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;A photo of a raccoon holding a handwritten sign that says "I love trash"&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And got back this image:&lt;/p&gt;
&lt;p&gt;&lt;img alt="I cute raccoon is holding a sign which says the word I, then a red heart, then a garbled word like tratieh, then a less garbled wrd trash" src="https://static.simonwillison.net/static/2025/janus-i-love-trash.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;It's now also been ported to &lt;a href="https://huggingface.co/docs/transformers.js/en/index"&gt;Transformers.js&lt;/a&gt;, which means you can run the 1B model directly in a WebGPU browser such as Chrome &lt;a href="https://huggingface.co/spaces/webml-community/janus-pro-webgpu"&gt;here at webml-community/janus-pro-webgpu&lt;/a&gt; (loads about 2.24 GB of model files).


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/transformers-js"&gt;transformers-js&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/vision-llms"&gt;vision-llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deepseek"&gt;deepseek&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/multi-modal-output"&gt;multi-modal-output&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llm-release"&gt;llm-release&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-in-china"&gt;ai-in-china&lt;/a&gt;&lt;/p&gt;



</summary><category term="ai"/><category term="generative-ai"/><category term="llms"/><category term="transformers-js"/><category term="vision-llms"/><category term="deepseek"/><category term="multi-modal-output"/><category term="llm-release"/><category term="ai-in-china"/></entry><entry><title>llama-3.2-webgpu</title><link href="https://simonwillison.net/2024/Sep/30/llama-32-webgpu/" rel="alternate"/><published>2024-09-30T16:27:22+00:00</published><updated>2024-09-30T16:27:22+00:00</updated><id>https://simonwillison.net/2024/Sep/30/llama-32-webgpu/</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://huggingface.co/spaces/webml-community/llama-3.2-webgpu"&gt;llama-3.2-webgpu&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Llama 3.2 1B is a really interesting models, given its 128,000 token input and its tiny size (barely more than a GB).&lt;/p&gt;
&lt;p&gt;This page loads a &lt;a href="https://huggingface.co/onnx-community/Llama-3.2-1B-Instruct-q4f16/tree/main/onnx"&gt;1.24GB q4f16 ONNX build&lt;/a&gt; of the Llama-3.2-1B-Instruct model and runs it with a React-powered chat interface directly in the browser, using &lt;a href="https://huggingface.co/docs/transformers.js/en/index"&gt;Transformers.js&lt;/a&gt; and WebGPU. &lt;a href="https://github.com/huggingface/transformers.js-examples/tree/main/llama-3.2-webgpu"&gt;Source code for the demo is here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It worked for me just now in Chrome; in Firefox and Safari I got a “WebGPU is not supported by this browser” error message.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://twitter.com/xenovacom/status/1840767709317046460"&gt;@xenovacom&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/webassembly"&gt;webassembly&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llama"&gt;llama&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/transformers-js"&gt;transformers-js&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/webgpu"&gt;webgpu&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/onnx"&gt;onnx&lt;/a&gt;&lt;/p&gt;



</summary><category term="ai"/><category term="webassembly"/><category term="generative-ai"/><category term="llama"/><category term="llms"/><category term="transformers-js"/><category term="webgpu"/><category term="onnx"/></entry><entry><title>Experimenting with local alt text generation in Firefox Nightly</title><link href="https://simonwillison.net/2024/Jun/2/experimenting-with-local-alt-text-generation-in-firefox-nightly/" rel="alternate"/><published>2024-06-02T13:12:44+00:00</published><updated>2024-06-02T13:12:44+00:00</updated><id>https://simonwillison.net/2024/Jun/2/experimenting-with-local-alt-text-generation-in-firefox-nightly/</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://hacks.mozilla.org/2024/05/experimenting-with-local-alt-text-generation-in-firefox-nightly/"&gt;Experimenting with local alt text generation in Firefox Nightly&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
The PDF editor in Firefox (confession: I did not know Firefox ships with a PDF editor) is getting an experimental feature that can help suggest alt text for images for the human editor to then adapt and improve on.&lt;/p&gt;
&lt;p&gt;This is a great application of AI, made all the more interesting here because Firefox will run a local model on-device for this, using a custom trained model they describe as "our 182M parameters model using a Distilled version of GPT-2 alongside a Vision Transformer (ViT) image encoder".&lt;/p&gt;
&lt;p&gt;The model uses WebAssembly with ONNX running in &lt;a href="https://huggingface.co/docs/transformers.js/en/index"&gt;Transfomers.js&lt;/a&gt;, and will be downloaded the first time the feature is put to use.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://twitter.com/mozhacks/status/1796774672639336804"&gt;@mozhacks&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/accessibility"&gt;accessibility&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/alt-text"&gt;alt-text&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/firefox"&gt;firefox&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/mozilla"&gt;mozilla&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/pdf"&gt;pdf&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/webassembly"&gt;webassembly&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/transformers-js"&gt;transformers-js&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/onnx"&gt;onnx&lt;/a&gt;&lt;/p&gt;



</summary><category term="accessibility"/><category term="alt-text"/><category term="firefox"/><category term="javascript"/><category term="mozilla"/><category term="pdf"/><category term="ai"/><category term="webassembly"/><category term="llms"/><category term="transformers-js"/><category term="onnx"/></entry><entry><title>The Tokenizer Playground</title><link href="https://simonwillison.net/2024/Mar/19/the-tokenizer-playground/" rel="alternate"/><published>2024-03-19T02:18:59+00:00</published><updated>2024-03-19T02:18:59+00:00</updated><id>https://simonwillison.net/2024/Mar/19/the-tokenizer-playground/</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://huggingface.co/spaces/Xenova/the-tokenizer-playground"&gt;The Tokenizer Playground&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
I built a tool like this a while ago, but this one is much better: it provides an interface for experimenting with tokenizers from a wide range of model architectures, including Llama, Claude, Mistral and Grok-1—all running in the browser using Transformers.js.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://twitter.com/xenovacom/status/1769546095871287423"&gt;@xenovacom&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/transformers-js"&gt;transformers-js&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/tokenization"&gt;tokenization&lt;/a&gt;&lt;/p&gt;



</summary><category term="ai"/><category term="generative-ai"/><category term="llms"/><category term="transformers-js"/><category term="tokenization"/></entry><entry><title>Adaptive Retrieval with Matryoshka Embeddings</title><link href="https://simonwillison.net/2024/Feb/15/adaptive-retrieval-with-matryoshka-embeddings/" rel="alternate"/><published>2024-02-15T04:19:55+00:00</published><updated>2024-02-15T04:19:55+00:00</updated><id>https://simonwillison.net/2024/Feb/15/adaptive-retrieval-with-matryoshka-embeddings/</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://huggingface.co/spaces/Xenova/adaptive-retrieval-web"&gt;Adaptive Retrieval with Matryoshka Embeddings&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Nomic Embed v1 only came out two weeks ago, but the same team &lt;a href="https://www.nomic.ai/blog/posts/nomic-embed-matryoshka"&gt;just released Nomic Embed v1.5&lt;/a&gt; trained using a new technique called Matryoshka Representation.&lt;/p&gt;
&lt;p&gt;This means that unlike v1 the v1.5 embeddings are resizable - instead of a fixed 768 dimension embedding vector you can trade size for quality and drop that size all the way down to 64, while still maintaining strong semantically relevant results.&lt;/p&gt;
&lt;p&gt;Joshua Lochner build this interactive demo on top of Transformers.js which illustrates quite how well this works: it lets you embed a query, embed a series of potentially matching text sentences and then adjust the number of dimensions and see what impact it has on the results.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://twitter.com/xenovacom/status/1757798436009599413"&gt;@xenovacom&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/embeddings"&gt;embeddings&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/nomic"&gt;nomic&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/transformers-js"&gt;transformers-js&lt;/a&gt;&lt;/p&gt;



</summary><category term="ai"/><category term="llms"/><category term="embeddings"/><category term="nomic"/><category term="transformers-js"/></entry><entry><title>Observable notebook: Detect objects in images</title><link href="https://simonwillison.net/2023/Oct/1/detect-objects-in-images/" rel="alternate"/><published>2023-10-01T15:46:14+00:00</published><updated>2023-10-01T15:46:14+00:00</updated><id>https://simonwillison.net/2023/Oct/1/detect-objects-in-images/</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://observablehq.com/@simonw/detect-objects-in-images"&gt;Observable notebook: Detect objects in images&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
I built an Observable notebook that uses &lt;a href="https://github.com/huggingface/transformers.js"&gt;Transformers.js&lt;/a&gt; and the &lt;a href="https://huggingface.co/Xenova/detr-resnet-50"&gt;Xenova/detra-resnet-50&lt;/a&gt; model to detect objects in images, entirely running within your browser. You can select an image using a file picker and it will show you that image with bounding boxes and labels drawn around items within it. I have a demo image showing some pelicans flying ahead, but it works with any image you give it - all without uploading that image to a server.&lt;/p&gt;
&lt;p&gt;&lt;img alt="A blue image with four birds flying, each is enclosed in a bounding box labelled bird with a %99.something accuracy label." src="https://static.simonwillison.net/static/2023/bird-detection.jpg" /&gt;

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://twitter.com/simonw/status/1708508183189410288"&gt;@simonw&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/machine-learning"&gt;machine-learning&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/transformers"&gt;transformers&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/observable"&gt;observable&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/transformers-js"&gt;transformers-js&lt;/a&gt;&lt;/p&gt;



</summary><category term="javascript"/><category term="machine-learning"/><category term="transformers"/><category term="ai"/><category term="observable"/><category term="transformers-js"/></entry><entry><title>Perplexity: interactive LLM visualization</title><link href="https://simonwillison.net/2023/Sep/6/perplexity/" rel="alternate"/><published>2023-09-06T03:33:05+00:00</published><updated>2023-09-06T03:33:05+00:00</updated><id>https://simonwillison.net/2023/Sep/6/perplexity/</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://perplexity.vercel.app/"&gt;Perplexity: interactive LLM visualization&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
I linked to a video of Linus Lee's GPT visualization tool &lt;a href="https://simonwillison.net/2023/Sep/5/a-token-wise-likelihood-visualizer-for-gpt-2/"&gt;the other day&lt;/a&gt;. Today he's released a new version of it that people can actually play with: it runs entirely in a browser, powered by a 120MB version of the GPT-2 ONNX model loaded using the brilliant Transformers.js JavaScript library.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://twitter.com/thesephist/status/1699190649096933474"&gt;@thesephist&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/webassembly"&gt;webassembly&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/transformers-js"&gt;transformers-js&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/onnx"&gt;onnx&lt;/a&gt;&lt;/p&gt;



</summary><category term="javascript"/><category term="ai"/><category term="webassembly"/><category term="generative-ai"/><category term="llms"/><category term="transformers-js"/><category term="onnx"/></entry><entry><title>Could you train a ChatGPT-beating model for $85,000 and run it in a browser?</title><link href="https://simonwillison.net/2023/Mar/17/beat-chatgpt-in-a-browser/" rel="alternate"/><published>2023-03-17T15:43:38+00:00</published><updated>2023-03-17T15:43:38+00:00</updated><id>https://simonwillison.net/2023/Mar/17/beat-chatgpt-in-a-browser/</id><summary type="html">
    &lt;p&gt;I think it's now possible to train a large language model with similar functionality to GPT-3 for $85,000. And I think we might soon be able to run the resulting model entirely in the browser, and give it capabilities that leapfrog it ahead of ChatGPT.&lt;/p&gt;
&lt;p&gt;This is currently wild speculation on my part, but bear with me because I think this is worth exploring further.&lt;/p&gt;
&lt;p&gt;Large language models with GPT-3-like capabilities cost millions of dollars to build, thanks to the cost of running the expensive GPU servers needed to train them. Whether you are renting or buying those machines, there are still enormous energy costs to cover.&lt;/p&gt;
&lt;p&gt;Just one example of this: the &lt;a href="https://huggingface.co/bigscience/bloom-7b1"&gt;BLOOM large language model&lt;/a&gt; was trained in France with the support of the French government. The cost was estimated as $2-5M, it took almost four months to train and boasts about its low carbon footprint because most of the power came from a nuclear reactor!&lt;/p&gt;
&lt;p&gt;[ Fun fact: as of a few days ago you can now &lt;a href="https://github.com/NouamaneTazi/bloomz.cpp"&gt;run the openly licensed BLOOM on your own laptop&lt;/a&gt;, using Nouamane Tazi's adaptive copy of the &lt;code&gt;llama.cpp&lt;/code&gt; code that made that possible for LLaMA ]&lt;/p&gt;
&lt;p&gt;Recent developments have made me suspect that these costs could be made dramatically lower. I think a capable language model can now be trained from scratch for around $85,000.&lt;/p&gt;
&lt;h4&gt;It's all about that LLaMA&lt;/h4&gt;
&lt;p&gt;The LLaMA plus Alpaca combination is the key here.&lt;/p&gt;
&lt;p&gt;I wrote about these two projects previously:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://simonwillison.net/2023/Mar/11/llama/"&gt;Large language models are having their Stable Diffusion moment&lt;/a&gt; discusses the significance of LLaMA&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://simonwillison.net/2023/Mar/13/alpaca/"&gt;Stanford Alpaca, and the acceleration of on-device large language model development&lt;/a&gt; describes Alpaca&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To recap: &lt;a href="https://research.facebook.com/publications/llama-open-and-efficient-foundation-language-models/"&gt;LLaMA&lt;/a&gt; by Meta research provided a GPT-3 class model trained entirely on documented, available public training information, as opposed to OpenAI's continuing practice of not revealing the sources of their training data.&lt;/p&gt;
&lt;p&gt;This makes the model training a whole lot more likely to be replicable by other teams.&lt;/p&gt;
&lt;p&gt;The paper also describes some enormous efficiency improvements they made to the training process.&lt;/p&gt;
&lt;p&gt;The LLaMA research was still extremely expensive though. From the paper:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;... we estimate that we used 2048 A100-80GB for a period of approximately 5 months to develop our models&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;My friends at &lt;a href="https://replicate.com/"&gt;Replicate&lt;/a&gt; told me that a simple rule of thumb for A100 cloud costs is $1/hour.&lt;/p&gt;
&lt;p&gt;2048 * 5 * 30 * 24 = $7,372,800&lt;/p&gt;
&lt;p&gt;But... that $7M was the cost to both iterate on the model and to train all four sizes of LLaMA that they tried: 7B, 13B, 33B, and 65B.&lt;/p&gt;
&lt;p&gt;Here's Table 15 from the paper, showing the cost of training each model.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://static.simonwillison.net/static/2023/llama-table-15.jpg" alt="Table 15: Carbon footprint of training different models in the same data center. We follow Wu et al. (2022) to compute carbon emission of training OPT, BLOOM and our models in the same data center. For the power consumption of a A100-80GB, we take the thermal design power for NVLink systems, that is 400W. We take a PUE of 1.1 and a carbon intensity factor set at the national US average of 0.385 kg COze per KWh. Lists 6 models. OPT-175B: 809,472 GPU hours, 356 MWh, 137 tons CO2. BLOOM-175B: 1,082,880 GPU hours, 475 MWh, 183 tons. LLaMA-7B: 82,432 GPU hours, 36 MWh, 14 tons. LLaMA-13B: 135,168 GPU hours, 59 MWh, 23 tons. LLaMA-33B: 530,432 GPU hours, 233 MWh, 90 tons. LLaMA-65B: 1,022,362 GPU hours, 449 MWh, 173 tons." style="max-width: 100%;" /&gt;&lt;/p&gt;
&lt;p&gt;This shows that the smallest model, LLaMA-7B, was trained on 82,432 hours of A100-80GB GPUs, costing 36MWh and generating 14 tons of CO2.&lt;/p&gt;
&lt;p&gt;(That's about 28 people flying from London to New York.)&lt;/p&gt;
&lt;p&gt;Going by the $1/hour rule of thumb, this means that provided you get everything right on your first run you can train a LLaMA-7B scale model for around $82,432.&lt;/p&gt;
&lt;h4&gt;Upgrading to Alpaca&lt;/h4&gt;
&lt;p&gt;You can run LLaMA 7B &lt;a href="https://til.simonwillison.net/llms/llama-7b-m2"&gt;on your own laptop&lt;/a&gt; (or even &lt;a href="https://twitter.com/ggerganov/status/1635605532726681600"&gt;on a phone&lt;/a&gt;), but you may find it hard to get good results out of. That's because it hasn't been instruction tuned, so it's not great at answering the kind of prompts that you might send to ChatGPT or GPT-3 or 4.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://crfm.stanford.edu/2023/03/13/alpaca.html"&gt;Alpaca&lt;/a&gt; is the project from Stanford that fixes that. They fine-tuned LLaMA on 52,000 instructions (of &lt;a href="https://simonwillison.net/2023/Mar/13/alpaca/#bonus-training-data"&gt;somewhat dubious origin&lt;/a&gt;) and claim to have gotten ChatGPT-like performance as a result... from that smallest 7B LLaMA model!&lt;/p&gt;
&lt;p&gt;You can &lt;a href="https://crfm.stanford.edu/alpaca/"&gt;try out their demo&lt;/a&gt; (&lt;strong&gt;update:&lt;/strong&gt; no you can't, "Our live demo is suspended until further notice") and see for yourself that it really does capture at least some of that ChatGPT magic.&lt;/p&gt;
&lt;p&gt;The best bit? The Alpaca fine-tuning can be done for less than $100. The Replicate team have repeated the training process and &lt;a href="https://replicate.com/blog/replicate-alpaca"&gt;published a tutorial&lt;/a&gt; about how they did it.&lt;/p&gt;
&lt;p&gt;Other teams have also been able to replicate the Alpaca fine-tuning process, for example &lt;a href="https://github.com/antimatter15/alpaca.cpp"&gt;antimatter15/alpaca.cpp&lt;/a&gt; on GitHub.&lt;/p&gt;
&lt;p&gt;We are still within our $85,000 budget! And Alpaca - or an Alpaca-like model using different fine tuning data - is the ChatGPT on your own device model that we've all been hoping for.&lt;/p&gt;
&lt;h4&gt;Could we run it in a browser?&lt;/h4&gt;
&lt;p&gt;Alpaca is effectively the same size as LLaMA 7B - around 3.9GB (after 4-bit quantization ala &lt;a href="github.com/ggerganov/llama.cpp"&gt;llama.cpp&lt;/a&gt;). And LLaMA 7B has already been shown running on a whole bunch of different personal devices: laptops, Raspberry Pis (very slowly) and even a Pixel 5 phone at a decent speed!&lt;/p&gt;
&lt;p&gt;The next frontier: running it in the browser.&lt;/p&gt;
&lt;p&gt;I saw two tech demos yesterday that made me think this may be possible in the near future.&lt;/p&gt;
&lt;p&gt;The first is &lt;a href="https://github.com/xenova/transformers.js"&gt;Transformers.js&lt;/a&gt;. This is a WebAssembly port of the Hugging Face &lt;a href="https://huggingface.co/docs/transformers/index"&gt;Transformers&lt;/a&gt; library of models - previously only available for server-side Python.&lt;/p&gt;
&lt;p&gt;It's worth spending some time with &lt;a href="https://xenova.github.io/transformers.js/"&gt;their demos&lt;/a&gt;, which include some smaller language models and some very impressive image analysis languages too.&lt;/p&gt;
&lt;p&gt;The second is &lt;a href="https://github.com/mlc-ai/web-stable-diffusion"&gt;Web Stable Diffusion&lt;/a&gt;. This team managed to get the Stable Diffusion generative image model running entirely in the browser as well!&lt;/p&gt;
&lt;p&gt;Web Stable Diffusion uses WebGPU, a still emerging standard that's currently only working in Chrome Canary. But it does work! It rendered me this image of two raccoons eating a pie in the forest in 38 seconds.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://static.simonwillison.net/static/2023/web-stable-diffusion-raccoons.jpg" alt="mig.ai/web-stable-diffusion/ in a browser. The input prompt is two racoons eating a pie in the woods, with the default 20 step scheduler. After 38 seconds elapsed on the prograss bar a realistic photograph of two raccoons eating a fruit pie appears - although on closer inspection the raccoon holding the pie has three paws!" style="max-width: 100%;" /&gt;&lt;/p&gt;
&lt;p&gt;The Stable Diffusion model this loads into the browser is around 1.9GB.&lt;/p&gt;
&lt;p&gt;LLaMA/Alpaca at 4bit quantization is 3.9GB.&lt;/p&gt;
&lt;p&gt;The sizes of these two models are similar enough that I would not be at all surprised to see an Alpaca-like model running in the browser in the not-too-distant future. I wouldn't be surprised if someone is working on that right now.&lt;/p&gt;
&lt;h4 id="react-pattern"&gt;Now give it extra abilities with ReAct&lt;/h4&gt;
&lt;p&gt;A model running in your browser that behaved like a less capable version of ChatGPT would be pretty impressive. But what if it could be MORE capable than ChatGPT?&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://react-lm.github.io/"&gt;ReAct prompt pattern&lt;/a&gt; is a simple, proven way of expanding a language model's abilities by giving it access to extra tools.&lt;/p&gt;
&lt;p&gt;Matt Webb explains the significance of the pattern in &lt;a href="https://interconnected.org/home/2023/03/16/singularity"&gt;The surprising ease and effectiveness of AI in a loop&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I got it working with a few dozen lines of Python myself, which I described in &lt;a href="https://til.simonwillison.net/llms/python-react-pattern"&gt;A simple Python implementation of the ReAct pattern for LLMs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here's the short version: you tell the model that it must think out loud and now has access to tools. It can then work through a question like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Question:&lt;/strong&gt; Population of Paris, squared?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thought:&lt;/strong&gt; I should look up the population of paris and then multiply it&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Action:&lt;/strong&gt; search_wikipedia: Paris&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then it stops. Your code harness for the model reads that last line, sees the action and goes and executes an API call against Wikipedia. It continues the dialog with the model like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Observation:&lt;/strong&gt; &amp;lt;truncated content from the Wikipedia page, including the 2,248,780 population figure&amp;gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The model continues:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Thought:&lt;/strong&gt; Paris population is 2,248,780 I should square that&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Action:&lt;/strong&gt; calculator: 2248780 ** 2&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Control is handed back to the harness, which passes that to a calculator and returns:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Observation:&lt;/strong&gt; 5057011488400&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The model then provides the answer:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Answer:&lt;/strong&gt; The population of Paris squared is 5,057,011,488,400&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Adding new actions to this system is trivial: each one can be a few lines of code.&lt;/p&gt;
&lt;p&gt;But as &lt;a href="https://react-lm.github.io/"&gt;the ReAct paper&lt;/a&gt; demonstrates, adding these capabilities to even an under-powered model (such as LLaMA 7B) can dramatically improve its abilities, at least according to several common language model benchmarks.&lt;/p&gt;
&lt;p&gt;This is essentially what Bing is! It's GPT-4 with the added ability to run searches against the Bing search index.&lt;/p&gt;
&lt;p&gt;Obviously if you're going to give a language model the ability to execute API calls and evaluate code you need to do it in a safe environment! Like for example... a web browser, which runs code from untrusted sources as a matter of habit and has the most thoroughly tested sandbox mechanism of any piece of software we've ever created.&lt;/p&gt;
&lt;h4 id="llm-conclusion"&gt;Adding it all together&lt;/h4&gt;
&lt;p&gt;There are a lot more groups out there that can afford to spend $85,000 training a model than there are that can spend $2M or more.&lt;/p&gt;
&lt;p&gt;I think LLaMA and Alpaca are going to have a lot of competition soon, from an increasing pool of openly licensed models.&lt;/p&gt;
&lt;p&gt;A fine-tuned LLaMA scale model is leaning in the direction of a ChatGPT competitor already. But... if you hook in some extra capabilities as seen in ReAct and Bing even that little model should be able to way outperform ChatGPT in terms of actual ability to solve problems and do interesting things.&lt;/p&gt;
&lt;p&gt;And we might be able to run such a thing on our phones... or even in our web browsers... sooner than you think.&lt;/p&gt;
&lt;h4 id="llm-cheaper"&gt;And it's only going to get cheaper&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://twitter.com/tobi/status/1636810016140271616"&gt;Tobias Lütke on Twitter:&lt;/a&gt;&lt;/p&gt;

&lt;blockquote class="twitter-tweet" data-conversation="none"&gt;&lt;p lang="en" dir="ltr"&gt;H100s are shipping and you can half this again. Twice (or more) if fp8 works.&lt;/p&gt;- tobi lutke (@tobi) &lt;a href="https://twitter.com/tobi/status/1636810016140271616?ref_src=twsrc%5Etfw"&gt;March 17, 2023&lt;/a&gt;&lt;/blockquote&gt;

&lt;p&gt;The &lt;a href="https://www.nvidia.com/en-us/data-center/h100/"&gt;H100&lt;/a&gt; is the new Tensor Core GPU from NVIDIA, which they claim can offer up to a 30x performance improvement over their current A100s.&lt;/p&gt;
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/webassembly"&gt;webassembly&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/chatgpt"&gt;chatgpt&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llama"&gt;llama&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/local-llms"&gt;local-llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/bloom"&gt;bloom&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/mlc"&gt;mlc&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/transformers-js"&gt;transformers-js&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llm-tool-use"&gt;llm-tool-use&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llama-cpp"&gt;llama-cpp&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/tobias-lutke"&gt;tobias-lutke&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="ai"/><category term="webassembly"/><category term="generative-ai"/><category term="chatgpt"/><category term="llama"/><category term="local-llms"/><category term="llms"/><category term="bloom"/><category term="mlc"/><category term="transformers-js"/><category term="llm-tool-use"/><category term="llama-cpp"/><category term="tobias-lutke"/></entry><entry><title>Transformers.js</title><link href="https://simonwillison.net/2023/Mar/16/transformers-js/" rel="alternate"/><published>2023-03-16T23:41:55+00:00</published><updated>2023-03-16T23:41:55+00:00</updated><id>https://simonwillison.net/2023/Mar/16/transformers-js/</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://xenova.github.io/transformers.js/"&gt;Transformers.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Hugging Face Transformers is a library of Transformer machine learning models plus a Python package for loading and running them. Transformers.js provides a JavaScript alternative interface which runs in your browser, thanks to a set of precompiled WebAssembly binaries for a selection of models. This interactive demo is incredible: in particular, try running the Image classification with google/vit-base-patch16-224 (91MB) model against any photo to get back labels representing that photo. Dropping one of these models onto a page is as easy as linking to a hosted CDN script and running a few lines of JavaScript.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/machine-learning"&gt;machine-learning&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/transformers"&gt;transformers&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/webassembly"&gt;webassembly&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/hugging-face"&gt;hugging-face&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/transformers-js"&gt;transformers-js&lt;/a&gt;&lt;/p&gt;



</summary><category term="javascript"/><category term="machine-learning"/><category term="transformers"/><category term="ai"/><category term="webassembly"/><category term="generative-ai"/><category term="llms"/><category term="hugging-face"/><category term="transformers-js"/></entry></feed>