Transformers.js 正在实验跨源存储(COS)API,通过哈希索引实现跨源文件共享,避免 AI 模型和 Wasm 运行时的重复下载与缓存,大幅提升 Web 应用性能。
Transformers.js 为 Web 开发者提供了在浏览器中使用 Transformer 模型的便捷方式。只需创建一个 pipeline() 实例并指定任务,即可运行推理。例如,以下代码设置了自动语音识别(ASR)管道:
import { pipeline } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@4.2.0';
const asr = await pipeline(
'automatic-speech-recognition',
'Xenova/whisper-tiny.en',
{ device: 'webgpu' },
);
const result = await asr('jfk.wav');
console.log(result);

代码中指定了模型 Xenova/whisper-tiny.en,这是 Transformers.js 的默认 ASR 模型。当在浏览器中运行时,Transformers.js 会自动下载并缓存模型资源和 Wasm 文件。从 Chrome DevTools 的缓存存储中可以看到这些文件。页面重新加载时,资源从缓存 API 中获取,模型近乎即时返回结果。

但问题是,如果多个不同来源的 Web 应用都使用同一个流行模型,每个应用都需要重新下载和缓存所有资源,即使字节完全相同。例如,从另一个来源访问相同示例,浏览器不得不再下载 177 MB 的重复数据。

更糟的是,不同模型可能共享同一个 Wasm 运行时文件(如 ort-wasm-simd-threaded.asyncify.wasm,约 4,733 kB)。即使使用不同的 AI 模型,浏览器仍会重复下载并缓存该文件,浪费带宽和磁盘空间。
AI 模型资源通常来自 Hugging Face Hub,最终由 Hugging Face CDN 提供。Wasm 运行时资源默认来自 jsDelivr CDN。你可能会认为,既然不同应用最终从同一 CDN 地址获取资源,缓存应该没问题。但并非如此:浏览器将缓存按来源隔离,以防止时序攻击,确保隐私安全。
在 Chrome 中,缓存键由“网络隔离键”(包含顶级站点和当前框架站点)加上资源 URL 组成。即使资源 URL 相同,但网络隔离键不同,就不会有缓存命中,导致重复下载和存储。这正是跨源存储提案要解决的问题。
💡 注: 跨源存储 API 是一个早期提案,尚未最终定稿。虽然浏览器尚未原生实现,但你可以立即体验:安装跨源存储扩展,该扩展会在所有页面上注入
navigator.crossOriginStoragepolyfill,让你测试完整流程。
提议的跨源存储(COS)API 引入了专门的 navigator.crossOriginStorage 接口,允许 Web 应用跨来源边界存储和检索大文件,文件不再由 URL 标识,而是由加密哈希标识。

关键点在于:COS 通过哈希而非 URL 或来源识别文件。因此,当你在 https://googlechrome.github.io 上下载了某 Wasm 运行时,https://rawcdn.rawgit.net 再次请求相同文件时,会被识别为同一文件,无需重新下载。以下代码展示了基本流程:
const hash = {
algorithm: 'SHA-256',
value: '8f434346648f6b96df89dda901c5176b10a6d83961dd3c1ac88b59b2dc327aa4',
};
try {
const handle = await navigator.crossOriginStorage.requestFileHandle(hash);
// 缓存命中!直接获取文件 Blob 并使用
const fileBlob = await handle.getFile();
} catch (err) {
// 缓存未命中。从网络下载后存储供下次使用
const fileBlob = await fetch('https://cdn.jsdelivr.net/.../ort-wasm-simd-threaded.asyncify.wasm')
.then(r => r.blob());
const handle = await navigator.crossOriginStorage.requestFileHandle(
hash,
{ create: true, origins: '*' },
);
const writableStream = await handle.createWritable();
await writableStream.write(fileBlob);
await writableStream.close();
}
如果资源已在 COS 中,你会得到一个 FileSystemFileHandle,可直接通过 getFile() 读取 blob。否则,回退到网络下载,并将资源写入 COS 供后续应用使用。
API 的设计借鉴了文件系统标准中的 FileSystemDirectoryHandle.getFileHandle(),与 Origin Private File System (OPFS) 类似。hash 参数相当于 OPFS 中的 name,options.create 标志行为一致:缺失或 false 表示只读访问,true 表示要写入。
并非所有资源都应全局共享。COS 通过存储文件时的 origins 选项给予开发者精确控制。
origins: '*' 使文件全局可用,任何来源均可通过哈希找到。适合 AI 模型资源或 Wasm 运行时。['https://write.example.com', 'https://calculate.example.com'])限制访问范围,适合公司内部专有资源。origins 则文件仅对同站点来源可用,是跨子域共享的合理默认值。一个重要规则:可见性只能升级,不能降级。如果文件已全局可见,后续用受限列表存储的尝试会被静默忽略,防止恶意攻击。反之,初始受限的文件可以被更宽松的设置覆盖,但升级者必须完整写入文件,以防止通过升级路径作为侧信道探测文件是否存在。
COS 的一个微妙但重要的特性是:写入文件时浏览器会验证哈希。如果写入的数据与声明的哈希不匹配,写入失败。这使完整性检查自动化:读取 COS 中文件的应用可以确信它获得了期望的字节。
这在 Transformers.js 场景中非常有用:当前大多数应用在下载模型权重后没有实际方法验证 CDN 是否提供了正确的字节。而 COS 中每个文件在写入时都经过隐式验证,无论它来自官方 Hugging Face CDN 还是随机站点的自托管镜像。
跨源共享缓存自然会引发隐私问题:任何站点都可以通过哈希探测文件是否存在,攻击者可能据此推断用户的浏览历史。
COS 通过两种互补机制解决:
origins: '*' 存储,通过开发者教育鼓励合理设置。因此,应用应始终以相同方式处理错误:回退到网络。
回到之前的例子:ort-wasm-simd-threaded.asyncify.wasm 运行时约 4,733 kB,被每个 Transformers.js 应用共享。使用 COS,第一个加载它的应用下载一次,并以 SHA-256 哈希和 origins: '*' 存储。后续任何应用(无论来源)都能立即从 COS 中找到它。177 MB 的重复 Whisper 模型权重也是如此:Xenova/whisper-tiny.en 下载一次,第二次通过哈希识别,毫秒级从 COS 提供。
Transformers.js 本身已在库级别实验 COS API。PR #1549 引入了一个实验性的 COS 缓存后端,通过一个 opt-in 标志启用。只需在设置管道前添加一行代码:
import { env, pipeline } from "https://cdn.jsdelivr.net/npm/@huggingface/transformers@4.2.0";
// 👇 选择启用实验性跨源存储缓存后端
env.experimental_useCrossOriginStorage = true;
const asr = await pipeline('automatic-speech-recognition', 'Xenova/whisper-tiny.en', { device: 'webgpu' });
const result = await asr('jfk.wav');
console.log(result);
启用该标志后,Transformers.js 通过获取每个 Xet 跟踪模型文件的原始指针(如 decoder_model.onnx 的原始指针文件),提取 oid sha256: 字段作为哈希键,然后调用 navigator.crossOriginStorage。如果模型已在 COS 中,无需网络往返即可即时提供;否则回退到常规下载并存储到 COS。
注意 experimental_ 前缀,表明底层浏览器 API 尚未标准化,可能会在未升级主版本号的情况下更改。
COS API 尚未在浏览器中原生实现,但你可以立即体验:安装跨源存储扩展,该扩展会在所有页面上注入 polyfill。你可以查阅扩展源代码和使用说明开始使用。

安装扩展后,你可以立即体验完整的端到端流程:打开第一个启用 COS 的示例,加载 Xenova/whisper-tiny.en,然后打开来自第二个来源的 COS 示例。之前 177 MB 的重新下载不见了,模型在毫秒级从 COS 提供。打开扩展弹出窗口,你可以看到 COS 的实际运行情况。在“按资源查看”中,可以看到哈希为 950978b1dbcbf250335358c1236053ba19a7f7849b33dc777f4421b72b7626fa 的资源在 https://googlechrome.github.io 和 https://rawcdn.rawgit.net 之间共享。通过对比 Hugging Face 上的 SHA-256 哈希,你会发现它正是 decoder_model_merged.onnx。

如果你正在构建自己的 Transformers.js 应用,行动很简单:在第一个 pipeline() 调用之前添加 env.experimental_useCrossOriginStorage = true,安装扩展,即可看到网络选项卡中重复下载消失。每个选择启用的站点都会让其他站点的用户体验更快、更省带宽。选择启用完全无风险:如果用户未安装 COS 扩展,代码会自动回退到默认的 Web 缓存 API。
除 Transformers.js 外,WebLLM(opt-in)和 wllama(自动启用)也在实验 COS API。
Chrome 团队正在考虑在浏览器中原生实现 COS API。作为早期提案,我们欢迎对 API 和提案本身的反馈。跨源存储仓库是提交 issue、表达支持或发起 PR 的地方。
原文链接:Hugging Face
本文由前途科技编辑整理
免费获取企业 AI 成熟度诊断报告,发现转型机会
关注公众号

扫码关注,获取最新 AI 资讯
3 步完成企业诊断,获取专属转型建议
已有 200+ 企业完成诊断