如何在 Chrome 扩展中使用 Transformers.js
摘要
本文提供了一份技术指南,介绍如何将 Transformers.js 集成到基于 Manifest V3 的 Chrome 扩展中,详细阐述了后台 Service Worker 架构、模型缓存和 Agent 循环的设计。
查看缓存全文
缓存时间: 2026/05/08 09:02
如何在 Chrome 扩展中使用 Transformers.js
来源:https://huggingface.co/blog/transformersjs-chrome-extension
返回文章 (https://huggingface.co/blog)
Nico Martin 的头像 (https://huggingface.co/nico-martin)
- 适用人群
- 我们将构建什么
- 1) Chrome 扩展架构 (MV3)
- 2) Transformers.js 集成细节
- 3) Agent 与工具执行循环
- 4) 数据边界与持久化
- 5) 构建与打包注意事项
- 最终要点
我们最近发布了一个基于 Transformers.js 的演示浏览器扩展,由 Gemma 4 E2B 驱动,帮助用户浏览网页。在构建过程中,我们积累了关于 Manifest V3 运行时、模型加载和消息通信的实践经验,值得分享。
适用人群
本指南面向希望在 Chrome 扩展中使用 Transformers.js 实现本地 AI 功能、并受 Manifest V3 约束的开发者。阅读完成后,你将掌握该项目使用的架构:后台 service worker 托管模型、侧边面板聊天 UI、以及用于页面级操作的内容脚本。
我们将构建什么
在本指南中,我们将重现 Transformers.js Gemma 4 浏览器助手 的核心架构,以已发布的扩展为参考,开源代码库为实现蓝图。
- 在线扩展:Chrome Web Store
- 源代码:github.com/nico-martin/gemma4-browser-extension
- 最终成果:后台托管的 Transformers.js 引擎、侧边面板聊天 UI、以及用于页面提取和高亮的内容脚本。
1) Chrome 扩展架构 (MV3)
深入之前,先说明范围:本文不会深入 React UI 层或 Vite 构建配置。重点是高层架构决策:每个 Chrome 运行时中运行什么,以及这些部分如何协调。如果 Manifest V3 对你来说是新的,请先阅读这篇简短概述:What is Manifest V3?。
1.1 运行时上下文与入口点
在 MV3 中,架构始于 public/manifest.json(源码)。本项目定义了三个入口点:
background.service_worker = background.js,由src/background/background.ts(源码)构建。side_panel.default_path = sidebar.html,由src/sidebar/index.html(源码)构建。content_scripts[].js = content.js,配置为matches: http(s)://*/\*和run_at: document_idle,由src/content/content.ts(源码)构建。
后台 service worker 还处理 chrome.action.onClicked 以打开当前标签页的侧边面板。相关入口点须知:action.default_popup 可定义弹出窗口,适用于快速操作。本项目使用侧边面板实现持久聊天,但协调模式相同。
1.2 各模块职责
关键设计决策是将重度协调工作保留在后台,UI/页面逻辑保持轻量。
- 后台(
src/background/background.ts)是控制平面:agent 生命周期、模型初始化、工具执行、以及特征提取等共享服务。 - 侧边面板(
src/sidebar/*)是交互层:聊天输入/输出、流式更新、设置控件。 - 内容脚本(
src/content/content.ts)是页面桥梁:DOM 提取和高亮操作。
这一划分的一个实际后果是,对话历史也保存在后台(Agent.chatMessages):UI 发送 AGENT_GENERATE_TEXT 等事件,后台追加消息、运行推理,然后向侧边面板发送 MESSAGES_UPDATE。这种拆分避免了重复加载模型、保持 UI 响应,并尊重 Chrome 围绕 DOM 访问的安全边界。
1.3 消息通信协议
运行时分离后,消息通信成为 backbone。在本项目中,所有消息通过 src/shared/types.ts(源码)中的枚举进行类型化。
-
侧边面板 → 后台(
BackgroundTasks):CHECK_MODELS、INITIALIZE_MODELSAGENT_INITIALIZE、AGENT_GENERATE_TEXT、AGENT_GET_MESSAGES、AGENT_CLEAREXTRACT_FEATURES
-
后台 → 侧边面板(
BackgroundMessages):DOWNLOAD_PROGRESS、MESSAGES_UPDATE
-
后台 → 内容(
ContentTasks):EXTRACT_PAGE_DATA、HIGHLIGHT_ELEMENTS、CLEAR_HIGHLIGHTS
协调规则很简单:后台是单一协调器;侧边面板和内容脚本是请求操作并渲染结果的专用工作者。
典型请求流程:
- 侧边面板发送
AGENT_GENERATE_TEXT - 后台追加到
Agent.chatMessages并运行模型/工具步骤 - 后台发出
MESSAGES_UPDATE - 侧边面板从更新的消息列表重新渲染
2) Transformers.js 集成细节
2.1 模型与职责
在 src/shared/constants.ts(源码)中,此扩展使用两种模型角色:
- 文本生成 / LLM:
onnx-community/gemma-4-E2B-it-ONNX(text-generation,q4f16) - 向量嵌入:
onnx-community/all-MiniLM-L6-v2-ONNX(feature-extraction,fp32)
这种拆分是有意为之:Gemma 4 负责推理/工具决策,而 MiniLM 生成向量嵌入,用于 ask_website 和 find_history 中的语义相似度搜索。
2.2 推理运行位置
所有推理都在后台运行(src/background/background.ts):
- 文本生成通过
pipeline("text-generation", ...)实现,启用我们新的DynamicCache类提供一致的 KV 缓存 - 嵌入通过
pipeline("feature-extraction", ...)加向量归一化实现
这为所有标签页/会话提供了单一模型宿主,避免重复内存占用,并保持侧边面板 UI 响应。由于模型从后台 service worker 加载,工件缓存在扩展源(chrome-extension://)下,而非按网站源分别缓存,这为整个扩展安装提供了共享缓存。
MV3 生命周期提示:service worker 可能被挂起和重启,因此模型运行时状态应视为可恢复的,并在需要时重新初始化。
2.3 下载与缓存生命周期
模型生命周期是显式的:
CHECK_MODELS检查已缓存内容并估算剩余下载大小INITIALIZE_MODELS下载/初始化模型,并向 UI 发送DOWNLOAD_PROGRESS- 初始化后复用长生命周期实例:
- 生成 pipeline 在
src/background/agent/Agent.ts - 嵌入 pipeline 在
src/background/utils/FeatureExtractor.ts
- 生成 pipeline 在
权限和隐私是架构的一部分,而非最后的勾选框。在本项目中,public/manifest.json 申请 sidePanel、storage、scripting 和 tabs,以及 http(s)://*/\* 的 host_permissions:
sidePanel:打开和控制侧边面板 UX 所需storage:跨会话持久化工具/设置状态所需tabs+scripting:标签页感知工具和页面级操作所需host_permissions为http(s)://*/\*:内容提取/高亮设计为在任意网站工作
为何保持精简:权限定义用户信任和 Chrome Web Store 审核风险。仅申请功能实际需要的内容,并明确说明推理在扩展本地运行,让用户了解其数据处理位置。
3) Agent 与工具执行循环
3.1 工具调用基础(为何存在这一层)
在执行循环之前,理解模型工具调用如何工作很有帮助(任何 agent 工作流的基础)。你传入消息和工具模式(name、description 和 parameters),Transformers.js 使用模型的聊天模板从这些输入格式化实际提示。由于聊天模板是模型特定的,精确的工具调用格式取决于你使用的模型。
使用 Gemma-4 风格模板时,模型在决定调用工具时会发出特殊的工具调用令牌块。
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<|"|>}
这正是本项目存在归一化层(webMcp)和解析器(extractToolCalls)的原因:模型输出必须转换为确定的工具执行。
3.2 本项目中的工具接口
src/background/agent/webMcp.tsx 将扩展工具归一化为模型友好的形态:
name、description、inputSchema、execute
示例工具包括 get_open_tabs、go_to_tab、open_url、close_tab、find_history、ask_website 和 highlight_website_element。
3.3 循环设计 (Agent.runAgent)
这里的核心设计决策是将内部模型消息与面向 UI 的聊天消息分离:
- 内部模型记录(
messages):用于generator(...)中消息的 system/user/tool/assistant 轮次 - UI 记录(
chatMessages):用户可见内容,包括流式助手文本、工具执行元数据(tools)和性能指标
执行流程:
- 将用户输入添加到
chatMessages,创建占位助手消息,并流式传输令牌 - 用
extractToolCalls.ts解析流式/最终模型输出为{ message, toolCalls } - 保持用户可见的助手消息为纯文本,同时工具调用在后台执行
- 将工具结果追加到助手工具元数据,并将结果作为下一提示轮次反馈
- 重复直到无工具调用,然后最终确定助手内容 + 指标
这保持了用户通信的简洁性,同时在后台保留了确定的工具循环。
4) 数据边界与持久化
状态放置是 MV3 中另一个重要的架构决策。在此实现中,状态按生命周期和访问模式拆分:
- 对话状态:后台内存(
Agent.chatMessages),用于快速的逐轮协调 - 工具偏好:
chrome.storage.local,设置跨会话持久化 - 语义历史向量:IndexedDB(
VectorHistoryDB),用于较大的本地检索数据 - 提取的页面内容:后台缓存(
WebsiteContentManager),按活动 URL 键控
如 1.2 节所述,将对话历史保留在后台为 UI 更新提供了单一权威状态。短生命周期状态保留在内存中,持久设置存入扩展存储,重度检索数据存入本地数据库。
5) 构建与打包注意事项
5.1 构建配置
本项目使用 Vite 构建扩展。关键配置点:
vite.config.ts中配置多入口点:background、sidebar、content- 内容脚本需要
build.lib配置以输出 IIFE 格式 - 静态资源(模型文件、wasm 等)通过
public/目录或 CDN 提供
5.2 打包体积优化
- 模型文件不打包进扩展,运行时从 Hugging Face Hub 或 CDN 下载
- 使用
onnx-community的量化模型减少内存和下载量 - 利用 Chrome 扩展的
chrome.storage和 IndexedDB 缓存模型
5.3 发布准备
manifest.json版本号与 package.json 同步- 提供清晰的权限说明和用户隐私声明
- 准备扩展截图和描述,突出“本地 AI“、“隐私优先“等卖点
最终要点
在 Chrome 扩展中运行 Transformers.js 需要理解 MV3 的运行时限制,并将模型托管、UI 渲染和页面交互明确分离。关键经验:
- 后台 service worker 是模型宿主:避免重复加载,共享跨标签页状态
- 消息通信是架构核心:类型化的消息协议确保各运行时可靠协调
- 工具调用需要归一化层:模型输出格式各异,需解析为确定执行
- 状态分层持久化:内存、storage、IndexedDB 各司其职
- 权限最小化:仅申请必要权限,明确告知用户数据本地处理
这套模式不仅适用于 Gemma 4,也可迁移到其他模型和扩展场景。完整代码参考 GitHub 仓库。
相似文章
在 Transformers.js 中尝试提议的跨源存储 API
这篇客座文章探讨了提议的跨源存储API,用于改进Transformers.js中AI模型资源的缓存,从而实现跨源的高效复用,同时保持浏览器内推理的隐私和完整性。
@nicodotdev:关于 Transformers.js 你一直想了解的一切,都在一个视频中。我深入探讨了 AI 模型如何从…运行
一个深入探讨的视频,解释如何使用 Transformers.js 从 JavaScript 运行 AI 模型,涵盖张量、ONNX、量化、WebGPU/WASM 等。
构建 uMatrix 替代品
本文探讨了在 Chrome Manifest V3 下替换已弃用的 uMatrix 浏览器扩展的选项,提出了一种使用 declarativeNetRequest 和内容安全策略来控制网站权限和子资源请求的解决方案。
@OpenAI:Chrome 扩展扩大了 Codex 在编码和工作方面的能力。从调试浏览器流程到检查仪表盘……
OpenAI 发布了 Codex 的新 Chrome 扩展,使人工智能能够直接在浏览器环境中处理基于浏览器的任务,例如调试流程、检查仪表盘、进行研究以及更新 CRM。
@AlphaSignalAI: 这个免费的交互式解释器刚刚揭示了GPT实际上是如何工作的。大多数人把Transformer当作魔法。你输入…
一个名为Transformer Explainer的免费交互式工具,在浏览器中运行实时GPT-2模型,通过桑基图和实时推理可视化Transformer的内部工作原理。