中级 12 分钟每日计划

WebLLM:在浏览器中运行 AI 模型 navigateur

WebLLM:在浏览器中运行 AI 模型 navigateur

WebLLM 是一个 JavaScript 库,借助 WebGPU 在浏览器标签页中、利用本机 GPU 运行 LLM。系统层面无需安装任何东西,但需要核实三个条件:浏览器兼容性、模型下载以及页面的实际行为。在您的 GPU 上执行计算,既不能证明页面可以离线运行,也不能证明您的消息留在本地。本指南说明如何对此进行检查;其中不包含任何基准测试。

作者: Mohamed Meguedmi·更新于 2026-11-09·已在 Windows、macOS 和 Linux 上测试
!
本指南的局限
在撰写本文当天(2026 年 11 月 9 日),我们未能复核 WebLLM 的代码仓库及其文档,QuelLLM 也未运行本指南中的任何代码。WebLLM 代码片段描述的是我们所了解的 API,不保证对应特定版本:如有出入,以仓库的 README 为准。有关 WebGPU、存储和安全策略的内容来自 MDN,已于 2026 年 11 月 9 日复核。

#WebLLM:这个库能做什么

使用 Ollama 时,安装在本机上的程序加载模型,并在 http://localhost:11434 上响应请求。使用 WebLLM 时,一切都通过网页完成:网页加载引擎的 JavaScript 和 WebAssembly 代码,获取模型权重,再通过 WebGPU 将计算任务交给 GPU。既无需启动服务,也无需开放端口。

在开发者层面,其 API 沿用了 OpenAI API 的形式:先创建一个引擎,然后传入消息列表调用 engine.chat.completions.create。因此,为该格式编写的应用可以较快完成适配。不过,引擎运行在页面内部:它并不是一个可供 Open WebUI、代码编辑器或 Python 脚本接入的 HTTP 服务器。

WebGPU
一种让浏览器能够调用 GPU 进行计算的 API。没有它,或没有可用的适配器,引擎就无法在 GPU 上运行。
WebAssembly
引擎部分组件的交付格式。与 JavaScript 一样,它也属于页面必须加载的内容。
模型权重
体积较大的文件,与页面代码相互独立。它们从配置中指定的地址下载,然后由浏览器缓存。
MLC 格式
WebLLM 使用为其引擎编译的模型,这类模型可通过标识符中的 MLC 后缀识别。为 Ollama 或 LM Studio 下载的 GGUF 文件无法直接加载。

#WebLLM 还是 Ollama:哪种需求用哪种工具?

打造专属 AI 助手的完整套件。

借助我们的经验和引导式路径,打造你的本地助手,在日常中使用你的 AI。

  • 在线空间,终身可用
  • PDF + 文件
  • 30 天内退款

WebLLM 并不能取代传统的本地安装。它的价值在别处:在网页中为不会安装任何软件的用户提供 AI 功能。

WebLLM 适用于
公开演示、内部 Web 工具、集成在应用中的助手,或在无法安装任何软件的电脑上快速试用。
Ollama 或 LM Studio 适用于
日常使用、从大量模型中挑选、运行更大的模型、提供可供其他工具复用的 API,以及不受浏览器标签页限制的运行方式。
需要接受的代价
可用模型目录取决于已编译为 MLC 格式的模型,可用内存还受浏览器限制的影响,而且缓存可能会在不通知您的情况下被清除。

我们不提供速度对比:本指南没有任何附带测试流程和硬件说明的实测数据作为支撑。如果速度对您的项目很重要,请在目标设备上使用相同的模型和相同的量化方式进行测量,并记录浏览器和驱动程序的版本。

#前提条件与 WebGPU 兼容性

在 2026 年 9 月 2 日修改的页面上,MDN 仍将 WebGPU 列为有限可用,即不属于 Baseline:该 API 在部分广泛使用的浏览器中无法运行。支持情况取决于浏览器、操作系统和显卡驱动的组合。因此,同一浏览器可能在一个系统上提供 WebGPU,而在另一个系统上不提供。与其参考很快就会过时的版本列表,不如查阅 MDN 的兼容性表格,然后在每台目标设备上进行测试。

安全上下文
根据 MDN,整个 API 仅在安全上下文中可用:请通过 HTTPS 提供页面,开发期间可使用 localhost。通过 HTTP 在局域网地址上打开的页面不符合要求。
浏览器与驱动程序
两者均需保持最新。如果驱动程序或浏览器阻止访问,仅有新款 GPU 是不够的。
GPU 内存
QuelLLM 在常用软件栈上的 Q4 参考值:3B 约 2 GB,7B 约 5 GB。这些只是数量级估计,并非 WebLLM 的实测数据。
磁盘空间与网络连接
需要足够的空间来存储模型,并至少下载一次。请在加载进度中核实实际大小。

此测试可粘贴到开发者工具的控制台中运行,页面需使用 HTTPS 或位于 localhost。它基于标准 API,不加载任何模型。根据 MDN,当没有合适的适配器可用时,requestAdapter 会返回 null:因此仅凭 navigator.gpu 存在并不足以下结论。

浏览器控制台:测试 WebGPU
if (!navigator.gpu) {
  console.log('WebGPU absent : navigateur non compatible, API désactivée ou contexte non sécurisé');
} else {
  const adapter = await navigator.gpu.requestAdapter();
  if (!adapter) {
    console.log('API présente, mais aucun adaptateur disponible');
  } else {
    console.log('shader-f16 :', adapter.features.has('shader-f16'));
    console.log('maxBufferSize :', adapter.limits.maxBufferSize);
    console.log('maxStorageBufferBindingSize :', adapter.limits.maxStorageBufferBindingSize);
  }
}

shader-f16 这一行有助于选择模型变体。WebLLM 的标识符通常区分 q4f16 模型(需要该功能)和 q4f32 模型(不需要该功能)。两项缓冲区限制说明了浏览器愿意分配多少内存;即使显卡拥有足够的显存,它们也可能导致大模型无法加载。

#下载意味着什么

首次加载时,页面会从其配置中的地址获取模型文件及相关的编译代码。据我们所知,在 WebLLM 的预置列表中,这些地址指向 Hugging Face 和 GitHub 等外部仓库:请在“网络”标签页中核实。这样一来,即使尚未发送任何消息,这些托管方也能看到您的 IP 地址和所请求的模型。

之后,文件会保存在浏览器存储中,并与页面的源(origin)绑定。MDN 说明了需要了解的规则:该存储默认处于 best-effort 模式,浏览器在磁盘空间紧张时可以在不打扰用户的情况下将其清除,并从最久未使用的源开始。被清除的源会一次性丢失全部数据。此外,在启用跨站跟踪防护时,如果某个源在浏览器使用的七天内没有任何交互,Safari 也可能删除该源通过脚本创建的数据。

页面控制台:配额与持久化存储
const { usage, quota } = await navigator.storage.estimate();
console.log('Utilisé :', usage, 'octets sur un quota estimé de', quota);

const persistant = await navigator.storage.persist();
console.log('Stockage persistant accordé :', persistant);
→
申请持久化并不能保证任何事情
Firefox 会向用户弹出请求;Chrome、Edge 和 Safari 则根据用户与该网站的交互历史自行决定(MDN,页面修改于 2026 年 1 月 5 日)。如果 persist 返回 false,请做好模型可能需要重新下载的准备。

#在页面中安装 WebLLM:操作步骤

本流程假定您有一个使用构建工具(例如 Vite)的 JavaScript 项目。将软件包安装到项目中,而不是从 CDN 导入,可以避免在页面加载时增加第三方域名,也更便于离线运行。

终端,在您的项目中
npm install @mlc-ai/web-llm
  1. 01
    锁定版本
    记下 package-lock.json 中安装的版本,并阅读对应版本的 README。同时核实软件包的许可证和模型的许可证,这是两件不同的事。
  2. 02
    列出可用模型
    不要从文章里照抄模型标识符:列表会不断变化。请用下面的第一个代码片段,在已安装的版本中读取该列表。列表中标注的内存字段只是一个起点,而非保证。
  3. 03
    从小范围开始
    先选择能满足需求的最小模型;如果上一步测试显示缺少 shader-f16,则选用 q4f32。首次尝试成功后,就能把代码问题与内存问题区分开来。
  4. 04
    显示进度
    下载可能耗时较长。如果没有可视反馈,页面看起来就像卡住了:initProgressCallback 会提供可供显示的进度文本。
  5. 05
    改用 Web Worker
    如果加载和生成在主线程中执行,可能会拖慢界面。为此,WebLLM 提供了 CreateWebWorkerMLCEngine,并在 worker 端配合使用 WebWorkerMLCEngineHandler 处理程序。请在上线前做好规划。
  6. 06
    在目标设备上测试
    在开发工作站上的结果,并不能说明配备集成显卡的笔记本电脑上的表现。如果缺少 WebGPU,请提供明确的提示信息,而不是显示空白页面。
列出已安装版本中的模型
import { prebuiltAppConfig } from '@mlc-ai/web-llm';

console.table(prebuiltAppConfig.model_list.map((m) => ({
  id: m.model_id,
  vramMo: m.vram_required_MB,
})));
加载模型并以流式方式读取响应
import { CreateMLCEngine } from '@mlc-ai/web-llm';

// Remplacez par un identifiant relevé dans la liste ci-dessus
const modelId = 'IDENTIFIANT_DU_MODELE';

const engine = await CreateMLCEngine(modelId, {
  initProgressCallback: (p) => console.log(p.text),
});

const stream = await engine.chat.completions.create({
  messages: [{ role: 'user', content: 'Explique WebGPU en deux phrases.' }],
  stream: true,
});

let reponse = '';
for await (const chunk of stream) {
  reponse += chunk.choices[0]?.delta?.content || '';
}
console.log(reponse);

#检查 WebLLM 页面:网络、脚本、离线

WebLLM 至多只能保证计算在何处执行。其余部分取决于嵌入它的页面:流量统计脚本、小部件或发送功能都可能读取输入框的内容并将其传出,因为页面中加载的任何脚本都能访问该页面。这项检查适用于所有宣称在浏览器中运行 AI 的网站,也包括您自己的网站。

  1. 01
    准备一个干净的配置文件
    打开一个不含扩展程序的浏览器配置文件:在页面上获得授权的扩展程序可以读取页面显示的内容,从而干扰结果。打开“网络”标签页并启用“保留日志”。
  2. 02
    记录加载情况
    加载页面,然后记下每个被联系的域名及其作用:页面、引擎、模型、字体、受众统计、广告。任何作用不明确的域名都有待解释。
  3. 03
    记录消息的发送情况
    模型加载完成后,清空日志。发送一条包含自造标记的消息,例如 TEST-MARQUEUR-7Q2X,然后使用“网络”选项卡的搜索功能在日志中查找它。同时检查生成过程中发出的每一个请求,包括 WebSocket 消息。
  4. 04
    检查脚本和安全响应头
    在 Sources 标签页中,列出脚本的来源域名。在文档的响应头中查找 Content-Security-Policy:严格的 connect-src 指令可以减少可能的目标地址,但没有该指令并不能证明任何事情。
  5. 05
    查看磁盘上残留的内容
    在“应用”或“存储”标签页中,打开 IndexedDB、Cache 和本地存储。模型通常存放在这里,但您的对话也可能保存在其中,任何使用该会话的人都能以明文看到。
  6. 06
    真正断开网络
    关闭页面,关闭 Wi-Fi 或拔掉网线,然后重新打开该地址并发送一条新消息。页面应能正常加载并作出响应。关闭浏览器后再重复一次。
!
模型已缓存并不意味着页面可以离线使用
如果页面的 HTML、JavaScript 或 WebAssembly 没有同样被保存下来(通常借助 service worker),那么即使整个模型都已存放在磁盘上,断网后该地址也将无法打开。因此,一个已经打开的引擎在断网后仍能继续响应,并不能证明它可以离线运行:只有重新打开测试才算数。

这些检查有其局限性。找不到标记并不能排除脚本以加密或编码形式发送数据的可能。WebRTC 连接不会以普通请求的形式出现在“网络”标签页中:在 Chrome 上,可以通过 chrome://webrtc-internals 发现它们。最后,检查结果仅对所测试的版本有效,因为网站运营方随时可能更改其脚本。

您可以声称“可离线运行”
前提是:在断网状态下,于所测试的浏览器上、在测试当日,重新打开页面并发送新消息均获成功。请注明缓存可能会被清除。
您可以说“未观察到任何外发”
前提是:在所测试的版本上、按照所述流程,日志中没有显示任何与消息相关的请求。这是一项注明日期的观察结果。
您不能声称“完全私密”
除非您能掌控所提供的全部代码及其更新,且不含任何第三方脚本,并通过阅读代码来补充这项检查。即便如此,模型托管方仍能看到下载行为,扩展程序也依然存在风险。

#全部从自己的域名提供

对于内部工具,最易于掌控的配置是从同一来源提供页面、引擎和模型,且不使用任何第三方脚本。WebLLM 支持自定义配置,其中每个模型都会指定其权重的地址及其编译库的地址。以下路径仅为示例,请根据实际情况调整。

自定义配置(示例地址)
import { CreateMLCEngine } from '@mlc-ai/web-llm';

const appConfig = {
  model_list: [{
    model: 'https://outil.example.fr/modeles/mon-modele/',
    model_id: 'mon-modele',
    model_lib: 'https://outil.example.fr/libs/mon-modele.wasm',
  }],
};

const engine = await CreateMLCEngine('mon-modele', { appConfig });

引擎会根据此前缀自行构建文件地址。它可能需要与 Hugging Face 类似的目录结构:如果请求出现 404 失败,请在“网络”选项卡中查看所请求的确切路径,并在您的服务器上照样复现。编译好的库必须与模型相匹配:不要随意将其与其他模型搭配使用。

将所有内容迁移到本地后,安全策略可以把一项承诺变成技术约束:根据 MDN,connect-src 尤其会限制 fetch、XMLHttpRequest、WebSocket、EventSource 和 sendBeacon,若未设置则回退到 default-src。以下示例未经 WebLLM 测试。请先以 Content-Security-Policy-Report-Only 模式部署,并查看控制台。

HTTP 标头,请根据您的页面调整
Content-Security-Policy: default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; worker-src 'self'; connect-src 'self'

该响应头也会阻止从 Hugging Face 下载:这是有意为之,此时模型必须由您的域名提供。它并不能覆盖所有可能的外发途径,例如跳转到其他地址。若要实现离线使用,请添加一个缓存页面文件的 service worker。WebLLM 也为这种场景提供了一个引擎 CreateServiceWorkerMLCEngine:请参阅其 README。

#故障排除

navigator.gpu 的值为 undefined
首先检查地址:必须是 HTTPS 或 localhost。然后查阅 MDN 上针对您的浏览器和系统的兼容性表,再将两者都更新到最新版本。
requestAdapter 返回 null
API 存在,但没有可用的合适适配器。请更新驱动程序,并确认浏览器的硬件加速已启用。可换用其他浏览器以排查原因。
与 shader-f16 相关的错误
所选模型需要您的适配器所不具备的功能。如果有 q4f32 变体,请改用该变体。
QuotaExceededError
已超出该来源的配额:MDN 指出 IndexedDB、Cache 和 OPFS 都会出现此错误。请释放空间或改用更小的模型,并在代码中捕获该错误。
加载结束时崩溃或 GPU 丢失
可能是内存不足或达到了缓冲区上限。请关闭占用资源较多的标签页,将模型降低一个尺寸档次,并在控制台中查看确切的错误信息。
模型被重新下载
无痕浏览、存储被逐出、网站数据被清除,或来源发生变化(因为每个域名都有各自独立的存储)。据我们所知,该软件包提供了 hasModelInCache,可在开始加载前进行检查。
生成期间界面卡住
引擎运行在主线程中。请改用 CreateWebWorkerMLCEngine。
控制台中出现安全策略错误
该消息会指明被拦截的指令和地址。在放宽规则之前,请先确认该地址是否合法,尤其是当您宣称页面不向外部发送数据时。

#深入了解

如果您想要的是供自己使用的助手,而不是集成在页面中的功能,那么传统的本地安装会更易于掌控:免费方案对比是很好的起点。对于敏感用途,请在本指南的检查之外,再配合隐私检查清单进行核查。

这份指南对您有帮助吗?

有反馈、发现了错误,或想补充说明?请告诉我们,让这份指南对每个人都更有帮助。