如何在Chrome扩展中使用Transformers.js
速览
本文详细讲解了如何在Chrome扩展中集成Transformers.js,利用Web技术实现模型推理。这一方法使得开发者能够在浏览器端直接运行机器学习模型,无需依赖后端服务器。其核心意义在于保护用户隐私并降低延迟,为Web应用带来强大的本地AI能力。
AI 深度解读
如何在 Chrome 扩展中使用 Transformers.js:架构与实践深度解读
背景
随着 Manifest V3 (MV3) 在 Chrome 扩展生态中的全面普及,开发者面临着新的运行时约束。传统的 Chrome 扩展架构往往依赖长期运行的后台页面,而 MV3 强制要求使用 Service Worker,这带来了状态易失、生命周期短暂等挑战。与此同时,本地 AI 推理成为提升用户体验的新趋势,但如何在资源受限且安全边界严格的扩展环境中高效运行大型语言模型(LLM)和向量嵌入模型,是一个尚未被充分探索的技术领域。
Hugging Face 博客发布的这篇指南,旨在解决上述痛点。它基于开源项目 gemma4-browser-extension,详细阐述了如何在 Manifest V3 的约束下,利用 Transformers.js 构建一个功能完备的本地 AI 助手。该指南不仅提供了代码层面的实现细节,更重点剖析了 MV3 运行时环境下的架构决策、模型加载策略、消息传递机制以及权限管理最佳实践。对于希望将 AI 能力集成到浏览器扩展中的开发者而言,这是一份极具参考价值的实战手册。
核心内容
本文档详细拆解了一个基于 Transformers.js 的 Chrome 扩展的核心架构,该架构旨在实现一个具备本地推理能力的浏览器助手。整个系统由三个主要部分组成:托管模型的后台 Service Worker、用于聊天的侧边栏 UI,以及用于页面交互的内容脚本。
1. Chrome 扩展架构 (MV3)
在 MV3 中,架构设计始于 public/manifest.json。该项目定义了三个关键的入口点,分别对应不同的运行时上下文:
- Background Service Worker (
background.js):由src/background/background.ts构建。它是整个系统的控制平面,负责代理生命周期管理、模型初始化、工具执行以及共享服务(如特征提取)。它还处理chrome.action.onClicked事件以打开活动标签页的侧边栏。 - Side Panel (
sidebar.html):由src/sidebar/index.html构建。作为交互层,它负责聊天输入/输出、流式更新显示以及设置控制。 - Content Script (
content.js):由src/content/content.ts构建,匹配所有 HTTP/HTTPS 网站并在文档空闲时运行。它充当页面桥梁,负责 DOM 提取和高亮显示操作。
关键设计决策:
- 职责分离:重型编排逻辑保留在后台,而 UI 和页面逻辑保持轻量。这种分离避免了模型重复加载,保持 UI 响应速度,并尊重 Chrome 关于 DOM 访问的安全边界。
- 状态管理:对话历史存储在后台 (
Agent.chatMessages)。侧边栏发送事件(如AGENT_GENERATE_TEXT),后台追加消息、运行推理,然后向侧边栏发射MESSAGES_UPDATE事件以重新渲染界面。
消息传递契约:
所有消息通过 src/shared/types.ts 中的枚举进行类型定义,确保运行时通信的可靠性:
- 侧边栏 -> 后台:包括
CHECK_MODELS、INITIALIZE_MODELS、AGENT_INITIALIZE、AGENT_GENERATE_TEXT、AGENT_GET_MESSAGES、AGENT_CLEAR和EXTRACT_FEATURES。 - 后台 -> 侧边栏:包括
DOWNLOAD_PROGRESS和MESSAGES_UPDATE。 - 后台 -> 内容脚本:包括
EXTRACT_PAGE_DATA、HIGHLIGHT_ELEMENTS和CLEAR_HIGHLIGHTS。
2. Transformers.js 集成细节
模型角色与职责:
项目在 src/shared/constants.ts 中定义了两个具有不同角色的模型:
- 文本生成/LLM:使用
onnx-community/gemma-4-E2B-it-ONNX(q4f16 量化)。负责推理和工具决策。 - 向量嵌入:使用
onnx-community/all-MiniLM-L6-v2-ONNX(fp32)。负责生成向量嵌入,用于ask_website和find_history功能中的语义相似度搜索。
推理运行位置:
所有推理均在后台 Service Worker (src/background/background.ts) 中执行:
- 文本生成:通过
pipeline("text-generation", ...)实现,启用了由新的DynamicCache类支持的 KV 缓存。 - 嵌入生成:通过
pipeline("feature-extraction", ...)实现,并辅以向量归一化。
这种单一模型宿主的设计避免了内存重复使用,并保持了侧边栏 UI 的响应能力。由于模型从后台 Service Worker 加载,缓存存储在扩展的起源下 (chrome-extension://<extension-id>),而非每个网站起源下,从而为整个扩展安装提供一个共享缓存。
生命周期注意: MV3 的 Service Worker 可能会被挂起和重启,因此模型运行时状态应被视为可恢复的,并在需要时重新初始化。
下载与缓存生命周期:
CHECK_MODELS:检查现有缓存并估算剩余下载大小。INITIALIZE_MODELS:下载/初始化模型,并向 UI 发射DOWNLOAD_PROGRESS。- 长期运行的实例在设置后被复用:生成管道位于
src/background/agent/Agent.ts,嵌入管道位于src/background/utils/FeatureExtractor.ts。
权限与隐私:
权限是架构的一部分,而非事后添加的选项。manifest.json 请求了以下权限:
sidePanel:打开和控制侧边栏 UX 所需。storage:跨会话持久化工具/设置状态所需。tabs+scripting:用于标签页感知工具和页面级操作。host_permissions(http(s)://*/*):因为内容提取/高亮设计用于任意网站。
保持权限狭窄不仅定义了用户信任,还降低了 Chrome Web Store 的审核风险。明确声明推理在扩展运行时本地运行,有助于用户理解数据处理位置。
3. Agent 和工具执行循环
工具调用的基础:
在执行循环之前,理解模型的工具调用机制至关重要。开发者传递消息加上工具模式(名称、描述、参数),Transformers.js 使用模型的聊天模板将这些输入格式化为实际提示。由于聊天模板因模型而异,工具调用格式取决于所使用的模型。对于 Gemma-4 风格的模板,当模型决定调用工具时,会发出特殊的工具调用令牌块。
代码示例展示了如何使用 @huggingface/transformers 加载模型并执行带有工具定义的生成:
import { pipeline } from "@huggingface/transformers";
const generator = await pipeline(
"text-generation",
"onnx-community/gemma-4-E2B-it-ONNX",
{
dtype: "q4f16",
device: "webgpu",
},
);
const messages = [{ role: "user", content: "What's the weather in Bern?" }];
const output = await generator(messages, {
max_new_tokens: 128,
do_sample: false,
tools: [
{
type: "function",
function: {
name: "getWeather",
description: "Get the weather in a location",
parameters: {
type: "object",
properties: {
location: {
type: "string",
description: "The location to get the weather for",
},
},
required: ["location"],
},
},
},
],
});
生成时,模型可能输出如下内容:
<|tool_call>call:getWeather{location:<|"|>Bern<|"|>}<tool_call|>
这就是该项目拥有规范化层 (webMcp) 和解析器 (extractToolCalls) 的原因:模型输出必须转换为确定性的工具执行。
项目中的工具接口:
src/background/agent/webMcp.tsx 将扩展工具规范化为 MCP (Model Context Protocol) 兼容格式,确保模型输出能够被可靠地解析和执行。
关键要点
- MV3 架构核心:采用“后台控制平面 + 轻量级 UI/内容脚本”的分
