{"id":3555,"date":"2025-02-07T18:15:43","date_gmt":"2025-02-07T17:15:43","guid":{"rendered":"https:\/\/blog.tomayac.com\/2025\/02\/07\/playing-with-ai-inference-in-firefox-web-extensions\/"},"modified":"2025-02-07T18:15:43","modified_gmt":"2025-02-07T17:15:43","slug":"playing-with-ai-inference-in-firefox-web-extensions","status":"publish","type":"post","link":"https:\/\/tomayac.com\/wordpress\/2025\/02\/07\/playing-with-ai-inference-in-firefox-web-extensions\/","title":{"rendered":"Playing with AI inference in Firefox Web extensions"},"content":{"rendered":"\n\t\t\t<p>Recently, in a blog post titled\n<a href=\"https:\/\/blog.mozilla.org\/en\/products\/firefox\/firefox-ai\/running-inference-in-web-extensions\/\">Running inference in web extensions<\/a>,\nMozilla announced a pretty interesting experiment on their blog:<\/p>\n<blockquote>\n<p>We've recently shipped a new\n<a href=\"https:\/\/firefox-source-docs.mozilla.org\/toolkit\/components\/ml\/\">component<\/a>\ninside of Firefox that leverages\n<a href=\"https:\/\/huggingface.co\/docs\/transformers.js\/index\">Transformers.js<\/a> [\u2026] and\nthe underlying <a href=\"https:\/\/onnxruntime.ai\/\">ONNX runtime engine<\/a>. This component\nlets you run any machine learning model that is compatible with\nTransformers.js in the browser, with no server-side calls beyond the initial\ndownload of the models. This means Firefox can run everything on your device\nand avoid sending your data to third parties.<\/p>\n<\/blockquote>\n<p>They expose this component to Web extensions under the <code>browser.trial.ml<\/code>\nnamespace. Where it gets really juicy is at the detail how models are stored\n(emphasis mine):<\/p>\n<blockquote>\n<p>Model files are stored using IndexedDB and <strong>shared across origins<\/strong><\/p>\n<\/blockquote>\n<p>Typically when you develop an app with Transformers.js, the model needs to be\ncached for each\n<a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Glossary\/Origin\">origin<\/a> separately,\nso if two apps on different origins end up using the same model, the model needs\nto be downloaded and stored redundantly. (Together with\n<a href=\"https:\/\/christianliebel.com\/\">Chris<\/a> and\n<a href=\"https:\/\/github.com\/beaufortfrancois\">Fran\u00e7ois<\/a>, I have\n<a href=\"https:\/\/github.com\/tomayac\/cross-origin-storage\/\">thought about this problem<\/a>,\ntoo, but that's not the topic of this blog post.)<\/p>\n<p>To get a feeling for the platform, I extracted their\n<a href=\"https:\/\/searchfox.org\/mozilla-central\/source\/toolkit\/components\/ml\/docs\/extensions-api-example\">example extension<\/a>\nfrom the Firefox source tree and put it separately\n<a href=\"https:\/\/github.com\/tomayac\/firefox-ml-extension\">in a GitHub repository<\/a>, so\nyou can more easily test it on your own.<\/p>\n<ol>\n<li>\n<p>Make sure that the following flags are toggled to <code>true<\/code> on the special\n<code>about:config<\/code> page:<\/p>\n<pre class=\"language-bash\"><code class=\"language-bash\">browser.ml.enable\nextensions.ml.enabled<\/code><\/pre>\n<\/li>\n<li>\n<p>Check out the source code.<\/p>\n<pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">git<\/span> clone git@github.com:tomayac\/firefox-ml-extension.git<\/code><\/pre>\n<\/li>\n<li>\n<p>Load the extension as a temporary extension on the <strong>This Nightly<\/strong> tab of\nthe special <code>about:debugging<\/code> page. It's important to actually use\n<a href=\"https:\/\/www.mozilla.org\/en-US\/firefox\/channel\/desktop\/#nightly\">Firefox Nightly<\/a>.<\/p>\n<p><img src=\"https:\/\/blog.tomayac.com\/images\/testingaiinfer--eu7b4fay57d.png\" alt=\"Special about:debugging page in Firefox Nightly.\" \/><\/p>\n<\/li>\n<li>\n<p>After loading the extension, you're brought to the welcome page, where you\nneed to grant the ML permission. The permission reads <em>&quot;Example extension\nrequests additional permissions. It wants to: Download and run AI models on\nyour device&quot;<\/em>. In the <code>manifest.json<\/code>, it looks like this:<\/p>\n<pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{<\/span>\n  <span class=\"token property\">\"optional_permissions\"<\/span><span class=\"token operator\">:<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token string\">\"trialML\"<\/span><span class=\"token punctuation\">]<\/span>\n<span class=\"token punctuation\">}<\/span><\/code><\/pre>\n<p><img src=\"https:\/\/blog.tomayac.com\/images\/testingaiinfer--6y4beuzmiwp.png\" alt=\"Permission dialog that reads &quot;Example extension requests additional permissions. It wants to: Download and run AI models on your device\" \/><\/p>\n<\/li>\n<li>\n<p>After granting permission, right-click any image on a page, for example,\n<a href=\"https:\/\/unsplash.com\/\">Unsplash<\/a>. In the context menu, select <strong>\u2728 Generate\nAlt Text<\/strong>.<\/p>\n<p><img src=\"https:\/\/blog.tomayac.com\/images\/testingaiinfer--p5tcfscpym.png\" alt=\"Context menu with the &quot;\u2728 Generate Alt Text&quot; option.\" \/><\/p>\n<\/li>\n<li>\n<p>If this was the first time, this triggers the download of the model. On the\nJavaScript code side, this is the relevant part:<\/p>\n<pre class=\"language-js\"><code class=\"language-js\"><span class=\"token comment\">\/\/ Initialize the event listener<\/span>\nbrowser<span class=\"token punctuation\">.<\/span>trial<span class=\"token punctuation\">.<\/span>ml<span class=\"token punctuation\">.<\/span>onProgress<span class=\"token punctuation\">.<\/span><span class=\"token function\">addListener<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">progressData<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=><\/span> <span class=\"token punctuation\">{<\/span>\n  console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span>progressData<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n\n<span class=\"token comment\">\/\/ Create the inference engine. This may trigger model downloads.<\/span>\n<span class=\"token keyword\">await<\/span> browser<span class=\"token punctuation\">.<\/span>trial<span class=\"token punctuation\">.<\/span>ml<span class=\"token punctuation\">.<\/span><span class=\"token function\">createEngine<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span>\n  <span class=\"token literal-property property\">modelHub<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">'mozilla'<\/span><span class=\"token punctuation\">,<\/span>\n  <span class=\"token literal-property property\">taskName<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">'image-to-text'<\/span><span class=\"token punctuation\">,<\/span>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/code><\/pre>\n<p>You can see the extension display download progress in the lower left corner.<\/p>\n<p><img src=\"https:\/\/blog.tomayac.com\/images\/testingaiinfer--70ltkwwvhze.png\" alt=\"Model download progress as an injected overlay on the Unsplash homepage.\" \/><\/p>\n<\/li>\n<li>\n<p>Once the model download is complete, the inference engine is ready to run.<\/p>\n<pre class=\"language-js\"><code class=\"language-js\"><span class=\"token comment\">\/\/ Call the engine.<\/span>\n<span class=\"token keyword\">const<\/span> res <span class=\"token operator\">=<\/span> <span class=\"token keyword\">await<\/span> browser<span class=\"token punctuation\">.<\/span>trial<span class=\"token punctuation\">.<\/span>ml<span class=\"token punctuation\">.<\/span><span class=\"token function\">runEngine<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span>\n  <span class=\"token literal-property property\">args<\/span><span class=\"token operator\">:<\/span> <span class=\"token punctuation\">[<\/span>imageUrl<span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">,<\/span>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\nconsole<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span>res<span class=\"token punctuation\">[<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">.<\/span>generated_text<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/code><\/pre>\n<p>It's not the most detailed description, but &quot;A computer desk with a monitor,\nkeyboard, and a plant&quot; definitely isn't wrong.<\/p>\n<p><img src=\"https:\/\/blog.tomayac.com\/images\/testingaiinfer--3z49xb3ae7f.png\" alt=\"Injected overlay with an accurate image description on the Unsplash homepage.\" \/><\/p>\n<p>If you click <strong>Inspect<\/strong> on the extension debugging page, you can play with\nthe\n<a href=\"https:\/\/firefox-source-docs.mozilla.org\/toolkit\/components\/ml\/extensions.html\">WebExtensions AI APIs<\/a>\ndirectly.<\/p>\n<p><img src=\"https:\/\/blog.tomayac.com\/images\/testingaiinfer--2z5827cdx7b.png\" alt=\"Special about:debugging page with the Inspect button highlighted.\" \/><\/p>\n<\/li>\n<li>\n<p>The <code>browser.trial.ml<\/code> namespace exposes the following functions:<\/p>\n<ul>\n<li><code>createEngine()<\/code>: creates an inference engine.<\/li>\n<li><code>runEngine()<\/code>: runs an inference engine.<\/li>\n<li><code>onProgress()<\/code>: listener for engine events<\/li>\n<li><code>deleteCachedModels()<\/code>: delete model(s) files<\/li>\n<\/ul>\n<p><img src=\"https:\/\/blog.tomayac.com\/images\/testingaiinfer--j43wjeiu9m.png\" alt=\"Firefox DevTools window shown inspecting the  namespace.\" \/><\/p>\n<p>I played with various tasks, and initially, I had some trouble getting\ntranslation to run, so I hopped on the <code>firefox-ai<\/code> channel on the\n<a href=\"https:\/\/discord.gg\/Jmmq9mGwy7\">Mozilla AI Discord<\/a>, where\n<a href=\"https:\/\/fr.linkedin.com\/in\/tarekziade\">Tarek Ziade<\/a> from the Firefox team\n<a href=\"https:\/\/discord.com\/channels\/1089876418936180786\/1329145280838500475\/1336387543490494534\">helped me out<\/a>\nand also pointed me at <code>about:inference<\/code>, another cool special page in\nFirefox Nightly where you can manage the installed AI models. If you want to\ndelete models from JavaScript, it seems like it's all or nothing, as the\n<code>deleteCachedModels()<\/code> function doesn't seem to take an argument. (It also\nthrew a <code>DOMException<\/code> when I tried to run it on Firefox Nightly <code>137.0a1<\/code>.)<\/p>\n<pre class=\"language-js\"><code class=\"language-js\"><span class=\"token comment\">\/\/ Delete all AI models.<\/span>\n<span class=\"token keyword\">await<\/span> browser<span class=\"token punctuation\">.<\/span>trial<span class=\"token punctuation\">.<\/span>ml<span class=\"token punctuation\">.<\/span><span class=\"token function\">deleteCachedModels<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/code><\/pre>\n<p><img src=\"https:\/\/blog.tomayac.com\/images\/testingaiinfer--dowi2w6wu1m.png\" alt=\"Inference manager on about:inference special page with overview of downloaded models.\" \/><\/p>\n<\/li>\n<li>\n<p>The <code>about:inference<\/code> page also lets you play directly with many AI tasks\nsupported by Transformers.js and hence Firefox WebExtensions AI APIs.<\/p>\n<p><img src=\"https:\/\/blog.tomayac.com\/images\/testingaiinfer--1bso1w4u01n.png\" alt=\"Inference manager on about:inference special page with options to test the available models.\" \/><\/p>\n<\/li>\n<\/ol>\n<p>Concluding, I think this is a very interesting way of working with AI inference\nin the browser. The obvious downside is that you need to convince your users to\ndownload an extension, but the obvious upside is that you possibly can save them\nfrom having to download a model they may already have downloaded and stored on\ntheir disk. When you experiment with AI models a bit, disk space can definitely\nbecome a problem, especially on smaller SSDs, which led me to a\n<a href=\"https:\/\/toot.cafe\/@tomayac\/113958051687160248\">fun random discovery<\/a> the other\nday, when I was trying to free up some disk space for Gemini Nano\u2026<\/p>\n<p>As teased before, Chris, Fran\u00e7ois, and I have some\n<a href=\"https:\/\/github.com\/tomayac\/cross-origin-storage\/\">ideas<\/a> around cross-origin\nstorage in general, but the Firefox WebExtensions AI APIs definitely solve the\nproblem for AI models. Be sure to read their\n<a href=\"https:\/\/firefox-source-docs.mozilla.org\/toolkit\/components\/ml\/extensions.html\">documentation<\/a>\nand play with their\n<a href=\"https:\/\/github.com\/tomayac\/firefox-ml-extension\/\">demo extension<\/a>! On the\nChrome team, we're experimenting with\n<a href=\"https:\/\/developer.chrome.com\/docs\/ai\/built-in\">built-in AI APIs in Chrome<\/a>.\nIt's a very exciting space for sure! Special thanks again to\n<a href=\"https:\/\/fr.linkedin.com\/in\/tarekziade\">Tarek Ziade<\/a> on the\n<a href=\"https:\/\/discord.gg\/Jmmq9mGwy7\">Mozilla AI Discord<\/a> for his help in getting me\nstarted.<\/p>\n\n\t\t\t<p>\n\t\t\t\t<img alt=\"Thomas Steiner\" width=\"32\" height=\"32\" src=\"https:\/\/blog.tomayac.com\/feed.php?dl=https%3A%2F%2Fblog.tomayac.com%2F2025%2F02%2F07%2Fplaying-with-ai-inference-in-firefox-web-extensions%2F&dp=%2F2025%2F02%2F07%2Fplaying-with-ai-inference-in-firefox-web-extensions%2F&dt=Playing%20with%20AI%20inference%20in%20Firefox%20Web%20extensions\" alt=\"\">\n\t\t\t\t<br\/>This post appeared first on <a href=\"https:\/\/blog.tomayac.com\/2025\/02\/07\/playing-with-ai-inference-in-firefox-web-extensions\/\">https:\/\/blog.tomayac.com\/2025\/02\/07\/playing-with-ai-inference-in-firefox-web-extensions\/<\/a>.\n\t\t\t<\/p>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Recently, in a blog post titled<br \/>\n<a href=\"https:\/\/blog.mozilla.org\/en\/products\/firefox\/firefox-ai\/running-inference-in-web-extensions\/\">Running inference in web extensions<\/a>,<br \/>\nMozilla announced a pretty interesting experiment on their blog:<\/p>\n<blockquote>\n<p>We&#8217;ve recently shipped a new<br \/>\n<a href=\"https:\/\/firefox-source-docs.mozilla.org\/toolkit\/components\/ml\/\">component<\/a><br \/>\ninside of Firefox that leverages<br \/>\n<a href=\"https:\/\/huggingface.co\/docs\/transformers.js\/index\">Transformers.js<\/a> [\u2026] and<br \/>\nthe underlying <a href=\"https:\/\/onnxruntime.ai\/\">ONNX runtime engine<\/a>. This component<br \/>\nlets you run any machine learning model that is compatible with<br \/>\nTransformers.js in the browser, with no server-side calls beyond the initial<br \/>\ndownload of the models. This means Firefox can run everything on your device<br \/>\nand avoid sending your data to third parties.<\/p>\n<\/blockquote>\n<p>They expose this component to Web extensions under the <code>browser.trial.ml<\/code><br \/>\nnamespace. Where it gets really juicy is at the detail how models are stored<br \/>\n(emphasis mine):<\/p>\n<blockquote>\n<p>Model files are stored using IndexedDB and <strong>shared across origins<\/strong><\/p>\n<\/blockquote>\n<p>Typically when you develop an app with Transformers.js, the model needs to be<br \/>\ncached for each<br \/>\n<a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Glossary\/Origin\">origin<\/a> separately,<br \/>\nso if two apps on different origins end up using the same model, the model needs<br \/>\nto be downloaded and stored redundantly. (Together with<br \/>\n<a href=\"https:\/\/christianliebel.com\/\">Chris<\/a> and<br \/>\n<a href=\"https:\/\/github.com\/beaufortfrancois\">Fran\u00e7ois<\/a>, I have<br \/>\n<a href=\"https:\/\/github.com\/tomayac\/cross-origin-storage\/\">thought about this problem<\/a>,<br \/>\ntoo, but that&#8217;s not the topic of this blog post.)<\/p>\n<p>To get a feeling for the platform, I extracted their<br \/>\n<a href=\"https:\/\/searchfox.org\/mozilla-central\/source\/toolkit\/components\/ml\/docs\/extensions-api-example\">example extension<\/a><br \/>\nfrom the Firefox source tree and put it separately<br \/>\n<a href=\"https:\/\/github.com\/tomayac\/firefox-ml-extension\">in a GitHub repository<\/a>, so<br \/>\nyou can more easily test it on your own.<\/p>\n<ol>\n<li>\n<p>Make sure that the following flags are toggled to <code>true<\/code> on the special<br \/>\n<code>about:config<\/code> page:<\/p>\n<pre class=\"language-bash\"><code class=\"language-bash\">browser.ml.enable\nextensions.ml.enabled<\/code><\/pre>\n<\/li>\n<li>\n<p>Check out the source code.<\/p>\n<pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">git<\/span> clone git@github.com:tomayac\/firefox-ml-extension.git<\/code><\/pre>\n<\/li>\n<li>\n<p>Load the extension as a temporary extension on the <strong>This Nightly<\/strong> tab of<br \/>\nthe special <code>about:debugging<\/code> page. It&#8217;s important to actually use<br \/>\n<a href=\"https:\/\/www.mozilla.org\/en-US\/firefox\/channel\/desktop\/#nightly\">Firefox Nightly<\/a>.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.tomayac.com\/images\/testingaiinfer--eu7b4fay57d.png\" alt=\"Special about:debugging page in Firefox Nightly.\"><\/p>\n<\/li>\n<li>\n<p>After loading the extension, you&#8217;re brought to the welcome page, where you<br \/>\nneed to grant the ML permission. The permission reads <em>&#8220;Example extension<br \/>\nrequests additional permissions. It wants to: Download and run AI models on<br \/>\nyour device&#8221;<\/em>. In the <code>manifest.json<\/code>, it looks like this:<\/p>\n<pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{<\/span>\n  <span class=\"token property\">\"optional_permissions\"<\/span><span class=\"token operator\">:<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token string\">\"trialML\"<\/span><span class=\"token punctuation\">]<\/span>\n<span class=\"token punctuation\">}<\/span><\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/blog.tomayac.com\/images\/testingaiinfer--6y4beuzmiwp.png\" alt='Permission dialog that reads \"Example extension requests additional permissions. It wants to: Download and run AI models on your device'><\/p>\n<\/li>\n<li>\n<p>After granting permission, right-click any image on a page, for example,<br \/>\n<a href=\"https:\/\/unsplash.com\/\">Unsplash<\/a>. In the context menu, select <strong>\u2728 Generate<br \/>\nAlt Text<\/strong>.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.tomayac.com\/images\/testingaiinfer--p5tcfscpym.png\" alt='Context menu with the \"\u2728 Generate Alt Text\" option.'><\/p>\n<\/li>\n<li>\n<p>If this was the first time, this triggers the download of the model. On the<br \/>\nJavaScript code side, this is the relevant part:<\/p>\n<pre class=\"language-js\"><code class=\"language-js\"><span class=\"token comment\">\/\/ Initialize the event listener<\/span>\nbrowser<span class=\"token punctuation\">.<\/span>trial<span class=\"token punctuation\">.<\/span>ml<span class=\"token punctuation\">.<\/span>onProgress<span class=\"token punctuation\">.<\/span><span class=\"token function\">addListener<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">progressData<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=&gt;<\/span> <span class=\"token punctuation\">{<\/span>\n  console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span>progressData<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n\n<span class=\"token comment\">\/\/ Create the inference engine. This may trigger model downloads.<\/span>\n<span class=\"token keyword\">await<\/span> browser<span class=\"token punctuation\">.<\/span>trial<span class=\"token punctuation\">.<\/span>ml<span class=\"token punctuation\">.<\/span><span class=\"token function\">createEngine<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span>\n  <span class=\"token literal-property property\">modelHub<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">'mozilla'<\/span><span class=\"token punctuation\">,<\/span>\n  <span class=\"token literal-property property\">taskName<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">'image-to-text'<\/span><span class=\"token punctuation\">,<\/span>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/code><\/pre>\n<p>You can see the extension display download progress in the lower left corner.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.tomayac.com\/images\/testingaiinfer--70ltkwwvhze.png\" alt=\"Model download progress as an injected overlay on the Unsplash homepage.\"><\/p>\n<\/li>\n<li>\n<p>Once the model download is complete, the inference engine is ready to run.<\/p>\n<pre class=\"language-js\"><code class=\"language-js\"><span class=\"token comment\">\/\/ Call the engine.<\/span>\n<span class=\"token keyword\">const<\/span> res <span class=\"token operator\">=<\/span> <span class=\"token keyword\">await<\/span> browser<span class=\"token punctuation\">.<\/span>trial<span class=\"token punctuation\">.<\/span>ml<span class=\"token punctuation\">.<\/span><span class=\"token function\">runEngine<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span>\n  <span class=\"token literal-property property\">args<\/span><span class=\"token operator\">:<\/span> <span class=\"token punctuation\">[<\/span>imageUrl<span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">,<\/span>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\nconsole<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span>res<span class=\"token punctuation\">[<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">.<\/span>generated_text<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/code><\/pre>\n<p>It&#8217;s not the most detailed description, but &#8220;A computer desk with a monitor,<br \/>\nkeyboard, and a plant&#8221; definitely isn&#8217;t wrong.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.tomayac.com\/images\/testingaiinfer--3z49xb3ae7f.png\" alt=\"Injected overlay with an accurate image description on the Unsplash homepage.\"><\/p>\n<p>If you click <strong>Inspect<\/strong> on the extension debugging page, you can play with<br \/>\nthe<br \/>\n<a href=\"https:\/\/firefox-source-docs.mozilla.org\/toolkit\/components\/ml\/extensions.html\">WebExtensions AI APIs<\/a><br \/>\ndirectly.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.tomayac.com\/images\/testingaiinfer--2z5827cdx7b.png\" alt=\"Special about:debugging page with the Inspect button highlighted.\"><\/p>\n<\/li>\n<li>\n<p>The <code>browser.trial.ml<\/code> namespace exposes the following functions:<\/p>\n<ul>\n<li><code>createEngine()<\/code>: creates an inference engine.<\/li>\n<li><code>runEngine()<\/code>: runs an inference engine.<\/li>\n<li><code>onProgress()<\/code>: listener for engine events<\/li>\n<li><code>deleteCachedModels()<\/code>: delete model(s) files<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/blog.tomayac.com\/images\/testingaiinfer--j43wjeiu9m.png\" alt=\"Firefox DevTools window shown inspecting the  namespace.\"><\/p>\n<p>I played with various tasks, and initially, I had some trouble getting<br \/>\ntranslation to run, so I hopped on the <code>firefox-ai<\/code> channel on the<br \/>\n<a href=\"https:\/\/discord.gg\/Jmmq9mGwy7\">Mozilla AI Discord<\/a>, where<br \/>\n<a href=\"https:\/\/fr.linkedin.com\/in\/tarekziade\">Tarek Ziade<\/a> from the Firefox team<br \/>\n<a href=\"https:\/\/discord.com\/channels\/1089876418936180786\/1329145280838500475\/1336387543490494534\">helped me out<\/a><br \/>\nand also pointed me at <code>about:inference<\/code>, another cool special page in<br \/>\nFirefox Nightly where you can manage the installed AI models. If you want to<br \/>\ndelete models from JavaScript, it seems like it&#8217;s all or nothing, as the<br \/>\n<code>deleteCachedModels()<\/code> function doesn&#8217;t seem to take an argument. (It also<br \/>\nthrew a <code>DOMException<\/code> when I tried to run it on Firefox Nightly <code>137.0a1<\/code>.)<\/p>\n<pre class=\"language-js\"><code class=\"language-js\"><span class=\"token comment\">\/\/ Delete all AI models.<\/span>\n<span class=\"token keyword\">await<\/span> browser<span class=\"token punctuation\">.<\/span>trial<span class=\"token punctuation\">.<\/span>ml<span class=\"token punctuation\">.<\/span><span class=\"token function\">deleteCachedModels<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/blog.tomayac.com\/images\/testingaiinfer--dowi2w6wu1m.png\" alt=\"Inference manager on about:inference special page with overview of downloaded models.\"><\/p>\n<\/li>\n<li>\n<p>The <code>about:inference<\/code> page also lets you play directly with many AI tasks<br \/>\nsupported by Transformers.js and hence Firefox WebExtensions AI APIs.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.tomayac.com\/images\/testingaiinfer--1bso1w4u01n.png\" alt=\"Inference manager on about:inference special page with options to test the available models.\"><\/p>\n<\/li>\n<\/ol>\n<p>Concluding, I think this is a very interesting way of working with AI inference<br \/>\nin the browser. The obvious downside is that you need to convince your users to<br \/>\ndownload an extension, but the obvious upside is that you possibly can save them<br \/>\nfrom having to download a model they may already have downloaded and stored on<br \/>\ntheir disk. When you experiment with AI models a bit, disk space can definitely<br \/>\nbecome a problem, especially on smaller SSDs, which led me to a<br \/>\n<a href=\"https:\/\/toot.cafe\/@tomayac\/113958051687160248\">fun random discovery<\/a> the other<br \/>\nday, when I was trying to free up some disk space for Gemini Nano\u2026<\/p>\n<p>As teased before, Chris, Fran\u00e7ois, and I have some<br \/>\n<a href=\"https:\/\/github.com\/tomayac\/cross-origin-storage\/\">ideas<\/a> around cross-origin<br \/>\nstorage in general, but the Firefox WebExtensions AI APIs definitely solve the<br \/>\nproblem for AI models. Be sure to read their<br \/>\n<a href=\"https:\/\/firefox-source-docs.mozilla.org\/toolkit\/components\/ml\/extensions.html\">documentation<\/a><br \/>\nand play with their<br \/>\n<a href=\"https:\/\/github.com\/tomayac\/firefox-ml-extension\/\">demo extension<\/a>! On the<br \/>\nChrome team, we&#8217;re experimenting with<br \/>\n<a href=\"https:\/\/developer.chrome.com\/docs\/ai\/built-in\">built-in AI APIs in Chrome<\/a>.<br \/>\nIt&#8217;s a very exciting space for sure! Special thanks again to<br \/>\n<a href=\"https:\/\/fr.linkedin.com\/in\/tarekziade\">Tarek Ziade<\/a> on the<br \/>\n<a href=\"https:\/\/discord.gg\/Jmmq9mGwy7\">Mozilla AI Discord<\/a> for his help in getting me<br \/>\nstarted.<\/p>\n<p>\n\t\t\t\t<img loading=\"lazy\" decoding=\"async\" alt=\"Thomas Steiner\" width=\"32\" height=\"32\" src=\"https:\/\/blog.tomayac.com\/feed.php?dl=https%3A%2F%2Fblog.tomayac.com%2F2025%2F02%2F07%2Fplaying-with-ai-inference-in-firefox-web-extensions%2F&amp;dp=%2F2025%2F02%2F07%2Fplaying-with-ai-inference-in-firefox-web-extensions%2F&amp;dt=Playing%20with%20AI%20inference%20in%20Firefox%20Web%20extensions\"><br \/>\n\t\t\t\t<br \/>This post appeared first on <a href=\"https:\/\/blog.tomayac.com\/2025\/02\/07\/playing-with-ai-inference-in-firefox-web-extensions\/\">https:\/\/blog.tomayac.com\/2025\/02\/07\/playing-with-ai-inference-in-firefox-web-extensions\/<\/a>.\n\t\t\t<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"intlwemo_wallet_address":"","footnotes":""},"categories":[],"tags":[],"class_list":["post-3555","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/tomayac.com\/wordpress\/wp-json\/wp\/v2\/posts\/3555","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tomayac.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tomayac.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tomayac.com\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tomayac.com\/wordpress\/wp-json\/wp\/v2\/comments?post=3555"}],"version-history":[{"count":1,"href":"https:\/\/tomayac.com\/wordpress\/wp-json\/wp\/v2\/posts\/3555\/revisions"}],"predecessor-version":[{"id":3556,"href":"https:\/\/tomayac.com\/wordpress\/wp-json\/wp\/v2\/posts\/3555\/revisions\/3556"}],"wp:attachment":[{"href":"https:\/\/tomayac.com\/wordpress\/wp-json\/wp\/v2\/media?parent=3555"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tomayac.com\/wordpress\/wp-json\/wp\/v2\/categories?post=3555"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tomayac.com\/wordpress\/wp-json\/wp\/v2\/tags?post=3555"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}