Transformers.js 实战
Pipeline API、模型加载与缓存、本地推理与 Web Worker 多线程
Transformers.js 简介
Transformers.js 是 Hugging Face Transformers 库的 JavaScript 版本,专门为浏览器和 Node.js 环境设计。它允许开发者直接在浏览器中运行 Transformer 模型,无需任何服务器端推理基础设施。该库基于 ONNX Runtime Web 构建,通过 WebAssembly 和 WebGL 后端将预训练的 PyTorch 模型转换为 ONNX 格式并在客户端高效执行。
Transformers.js 的核心优势在于:用户数据无需离开本地设备,既降低了服务器成本,又提升了隐私保护水平。目前该库支持超过 80 种 Transformer 架构,涵盖自然语言处理、计算机视觉和音频处理等多个领域。
Pipeline API 使用
pipeline() 工厂函数
Transformers.js 提供了 pipeline() 工厂函数作为最高层级的 API 入口。它会根据传入的任务类型自动选择合适的模型和预处理流程,极大简化了推理代码的编写。
import { pipeline } from '@xenova/transformers';支持的任务类型
| 任务名称 | 任务标识 | 典型模型 | 输出类型 |
|---|---|---|---|
| 文本分类 | text-classification | BERT / RoBERTa | 标签与置信度 |
| 情感分析 | sentiment-analysis | distilbert-base-uncased | 情感标签与分数 |
| 图像分类 | image-classification | ResNet / ViT | 类别与概率 |
| 特征提取 | feature-extraction | BERT / Sentence-BERT | 固定长度向量 |
| 文本生成 | text-generation | GPT-2 / CodeGen | 生成的文本序列 |
| 问答任务 | question-answering | BERT / DistilBERT | 答案片段与置信度 |
| 填充掩码 | fill-mask | BERT / RoBERTa | 候选词与概率 |
| 零样本分类 | zero-shot-classification | BART / NLI 模型 | 候选标签与分数 |
代码示例
文本分类(情感分析)
import { pipeline } from '@xenova/transformers';
// 创建情感分析 pipeline
const classifier = await pipeline('sentiment-analysis');
// 执行推理
const result = await classifier('I love Transformers.js!');
console.log(result);
// [{ label: 'POSITIVE', score: 0.9998 }]图像分类
import { pipeline } from '@xenova/transformers';
const classifier = await pipeline('image-classification');
const result = await classifier('https://example.com/cat.jpg');
console.log(result);
// [{ label: 'tabby cat', score: 0.89 }, { label: 'tiger cat', score: 0.05 }]文本生成
import { pipeline } from '@xenova/transformers';
const generator = await pipeline('text-generation');
const result = await generator('Once upon a time', {
max_new_tokens: 50,
temperature: 0.7,
do_sample: true,
});
console.log(result[0].generated_text);模型加载与缓存
从 Hugging Face Hub 加载模型
Transformers.js 默认从 Hugging Face Hub 加载模型。首次使用时,库会自动下载模型文件(包括 model.onnx 和配套的 tokenizer 或 processor 配置)。
缓存机制
库内部使用 IndexedDB 进行模型缓存,加载策略如下:
| 加载方式 | 网络请求 | 加载耗时 | 适用场景 |
|---|---|---|---|
| 首次加载 | 需要下载完整模型 | 数秒至数分钟(依模型大小) | 首次使用或缓存被清除 |
| 后续加载 | 无需网络请求 | 毫秒级 | 重复使用同一模型 |
加载进度可以通过 progress_callback 参数实时监听:
import { pipeline } from '@xenova/transformers';
const classifier = await pipeline('sentiment-analysis', 'Xenova/distilbert-base-uncased-finetuned-sst-2-english', {
progress_callback: (progress) => {
console.log(`加载进度: ${Math.round(progress * 100)}%`);
},
});指定模型与量化选项
Transformers.js 支持 FP32、FP16 和 INT8 三种量化精度。量化可以显著减小模型体积并提升推理速度,代价是轻微的精度损失。
import { pipeline } from '@xenova/transformers';
// 使用远端模型并指定量化类型
const extractor = await pipeline('feature-extraction', 'Xenova/all-MiniLM-L6-v2', {
quantized: true, // 使用 INT8 量化版本(默认)
// quantized: false, // 使用 FP32 原始版本
// dtype: 'fp16', // 也可通过 dtype 指定浮点精度
revision: 'main', // 模型分支
});
// 检查模型是否为量化版本
console.log(extractor.model.config.quantized ? 'INT8 量化模型' : 'FP32 模型');对于需要低延迟的场景,建议使用 Xenova/ 命名空间下已预转换的量化模型,它们针对 Web 环境做了优化,体积更小、加载更快。
本地推理与 Web Worker 多线程
主线程推理的问题
Transformers.js 的模型推理是计算密集型操作。在主线程中执行推理会阻塞 JavaScript 事件循环,导致页面卡顿、动画掉帧、用户交互响应延迟。对于小型模型(如 DistilBERT)影响尚可接受,但对于 GPT-2、Whisper 等稍大模型,阻塞时间可达数秒。
Web Worker 方案
Web Worker 浏览器 API 允许在独立的后台线程中执行 JavaScript 代码。将 Transformers.js 的推理逻辑放在 Worker 线程中,可以完全避免主线程阻塞,保持 UI 流畅。主线程与 Worker 之间通过 postMessage 和 onmessage 进行异步通信。
代码示例
worker.js — 工作线程,承载模型加载与推理逻辑
// worker.js
import { pipeline } from '@xenova/transformers';
let classifier = null;
// 监听主线程消息
self.addEventListener('message', async (event) => {
const { type, payload } = event.data;
if (type === 'load') {
// 在 Worker 中加载模型
classifier = await pipeline('sentiment-analysis', payload.modelId, {
progress_callback: (progress) => {
self.postMessage({ type: 'progress', payload: progress });
},
});
self.postMessage({ type: 'loaded' });
}
if (type === 'predict' && classifier) {
const result = await classifier(payload.text);
self.postMessage({ type: 'result', payload: result });
}
});main.js — 主线程,负责 UI 交互与 Worker 管理
// main.js
const worker = new Worker(new URL('./worker.js', import.meta.url), {
type: 'module',
});
// 接收 Worker 消息
worker.addEventListener('message', (event) => {
const { type, payload } = event.data;
switch (type) {
case 'progress':
updateProgressBar(payload);
break;
case 'loaded':
setStatus('模型加载完成');
enableInput();
break;
case 'result':
displayResult(payload);
setStatus('推理完成');
break;
}
});
// 加载模型
worker.postMessage({
type: 'load',
payload: { modelId: 'Xenova/distilbert-base-uncased-finetuned-sst-2-english' },
});
// 执行推理
function analyzeSentiment(text) {
setStatus('推理中...');
worker.postMessage({ type: 'predict', payload: { text } });
}
// 清理
function cleanup() {
worker.terminate();
}使用 Web Worker 后,即使在推理过程中用户也可以正常滚动页面、输入文本或点击按钮,交互体验和原生桌面应用无异。
实际应用场景
Transformers.js 在以下场景中展现出显著价值:
- 浏览器端实时翻译:加载 NLLB 或 MarianMT 模型,在用户输入时即时翻译,无需将文本发送到服务器,保护用户隐私。
- 敏感内容审核:对用户生成的文本或图片在本地进行内容审核,在数据离开设备前过滤敏感内容,结合零样本分类实现灵活的策略规则。
- 离线辅助功能:在无网络环境下提供文本摘要、语法纠正、图像描述等辅助能力,特别适用于笔记应用、文档编辑器、无障碍工具等场景。
Transformers.js 降低了 Transformer 模型的前端使用门槛,将 AI 能力从服务端延伸到浏览器端,为构建隐私友好、响应迅速的智能 Web 应用提供了坚实的技术基础。