如何在 Chrome 扩展中使用 Transformers.js

Hugging Face Blog 工具

摘要

本文提供了一份技术指南,介绍如何将 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)

我们最近发布了一个基于 Transformers.js 的演示浏览器扩展,由 Gemma 4 E2B 驱动,帮助用户浏览网页。在构建过程中,我们积累了关于 Manifest V3 运行时、模型加载和消息通信的实践经验,值得分享。

适用人群

本指南面向希望在 Chrome 扩展中使用 Transformers.js 实现本地 AI 功能、并受 Manifest V3 约束的开发者。阅读完成后,你将掌握该项目使用的架构:后台 service worker 托管模型、侧边面板聊天 UI、以及用于页面级操作的内容脚本。

我们将构建什么

在本指南中,我们将重现 Transformers.js Gemma 4 浏览器助手 的核心架构,以已发布的扩展为参考,开源代码库为实现蓝图。

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_MODELSINITIALIZE_MODELS
    • AGENT_INITIALIZEAGENT_GENERATE_TEXTAGENT_GET_MESSAGESAGENT_CLEAR
    • EXTRACT_FEATURES
  • 后台 → 侧边面板(BackgroundMessages):

    • DOWNLOAD_PROGRESSMESSAGES_UPDATE
  • 后台 → 内容(ContentTasks):

    • EXTRACT_PAGE_DATAHIGHLIGHT_ELEMENTSCLEAR_HIGHLIGHTS

协调规则很简单:后台是单一协调器;侧边面板和内容脚本是请求操作并渲染结果的专用工作者。

典型请求流程:

  1. 侧边面板发送 AGENT_GENERATE_TEXT
  2. 后台追加到 Agent.chatMessages 并运行模型/工具步骤
  3. 后台发出 MESSAGES_UPDATE
  4. 侧边面板从更新的消息列表重新渲染

2) Transformers.js 集成细节

2.1 模型与职责

src/shared/constants.ts源码)中,此扩展使用两种模型角色:

这种拆分是有意为之:Gemma 4 负责推理/工具决策,而 MiniLM 生成向量嵌入,用于 ask_websitefind_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 下载与缓存生命周期

模型生命周期是显式的:

权限和隐私是架构的一部分,而非最后的勾选框。在本项目中,public/manifest.json 申请 sidePanelstoragescriptingtabs,以及 http(s)://*/\*host_permissions

  • sidePanel:打开和控制侧边面板 UX 所需
  • storage:跨会话持久化工具/设置状态所需
  • tabs + scripting:标签页感知工具和页面级操作所需
  • host_permissionshttp(s)://*/\*:内容提取/高亮设计为在任意网站工作

为何保持精简:权限定义用户信任和 Chrome Web Store 审核风险。仅申请功能实际需要的内容,并明确说明推理在扩展本地运行,让用户了解其数据处理位置。

3) Agent 与工具执行循环

3.1 工具调用基础(为何存在这一层)

在执行循环之前,理解模型工具调用如何工作很有帮助(任何 agent 工作流的基础)。你传入消息和工具模式(namedescriptionparameters),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 将扩展工具归一化为模型友好的形态:

  • namedescriptioninputSchemaexecute

示例工具包括 get_open_tabsgo_to_tabopen_urlclose_tabfind_historyask_websitehighlight_website_element

3.3 循环设计 (Agent.runAgent)

这里的核心设计决策是将内部模型消息与面向 UI 的聊天消息分离:

  • 内部模型记录messages):用于 generator(...) 中消息的 system/user/tool/assistant 轮次
  • UI 记录chatMessages):用户可见内容,包括流式助手文本、工具执行元数据(tools)和性能指标

执行流程:

  1. 将用户输入添加到 chatMessages,创建占位助手消息,并流式传输令牌
  2. extractToolCalls.ts 解析流式/最终模型输出为 { message, toolCalls }
  3. 保持用户可见的助手消息为纯文本,同时工具调用在后台执行
  4. 将工具结果追加到助手工具元数据,并将结果作为下一提示轮次反馈
  5. 重复直到无工具调用,然后最终确定助手内容 + 指标

这保持了用户通信的简洁性,同时在后台保留了确定的工具循环。

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 渲染和页面交互明确分离。关键经验:

  1. 后台 service worker 是模型宿主:避免重复加载,共享跨标签页状态
  2. 消息通信是架构核心:类型化的消息协议确保各运行时可靠协调
  3. 工具调用需要归一化层:模型输出格式各异,需解析为确定执行
  4. 状态分层持久化:内存、storage、IndexedDB 各司其职
  5. 权限最小化:仅申请必要权限,明确告知用户数据本地处理

这套模式不仅适用于 Gemma 4,也可迁移到其他模型和扩展场景。完整代码参考 GitHub 仓库

相似文章

在 Transformers.js 中尝试提议的跨源存储 API

Hugging Face Blog

这篇客座文章探讨了提议的跨源存储API,用于改进Transformers.js中AI模型资源的缓存,从而实现跨源的高效复用,同时保持浏览器内推理的隐私和完整性。

构建 uMatrix 替代品

Hacker News Top

本文探讨了在 Chrome Manifest V3 下替换已弃用的 uMatrix 浏览器扩展的选项,提出了一种使用 declarativeNetRequest 和内容安全策略来控制网站权限和子资源请求的解决方案。