使用 Transformers.js 在 Chrome 扩展程序中
使用 Transformers.js 在 Chrome 扩展程序中
Hugging Face 发布了一个由 Gemma 4 E2B 驱动的演示浏览器扩展,以展示如何在 Chrome 扩展程序中运行本地 AI 功能。该实现利用 Transformers.js 在清单 V3 限制下,采用了一种解耦架构:后台服务工作器管理模型编排,而 UI 和内容脚本保持为薄客户端。
Chrome 扩展程序架构(清单 V3)
核心架构策略是将关注点分离到三个主要的 Chrome 运行时上下文,以确保 UI 响应能力并避免重复加载模型。
运行时上下文和入口点
如 manifest.json 所定义,扩展程序使用三个入口点:
- 后台服务工作器 (
background.js):充当代理生命周期、模型初始化和工具执行的控制平面。 - 侧边面板 (
sidebar.html):作为聊天输入/输出和流式更新的交互层。 - 内容脚本 (
content.js):作为页面桥梁,用于 DOM 提取和突出显示操作。
消息传递和编排
由于这些运行时是隔离的,一个通过枚举定义的类型化消息协议协调操作。后台服务工作器充当单一协调者:
- 侧边面板发送请求(例如,
AGENT_GENERATE_TEXT)。 - 后台工作器将消息追加到对话历史中,运行推理,并执行工具。
- 后台工作器发送更新(例如,
MESSAGES_UPDATE)回到侧边面板以进行渲染。
Transformers.js 集成详情
模型角色和职责
扩展程序采用两种不同的模型来平衡推理和检索:
- 文本生成 (LLM):
onnx-community/gemma-4-E2B-it-ONNX(q4f16) 负责推理和工具调用决策。 - 向量嵌入:
onnx-community/all-MiniLM-L6-v2-ONNX(fp32) 为历史和网站内容中的语义相似性搜索生成嵌入。
推理和缓存
所有推理在后台服务工作器中使用 pipeline("text-generation", ...) 和 DynamicCache 类进行一致的 KV 缓存,以及使用 pipeline("feature-extraction", ...) 进行嵌入。
将推理托管在后台工作器中可确保模型工件缓存在扩展源 (chrome-extension://<extension-id>) 下,而不是按网站源,从而在整个安装过程中提供共享缓存。开发者必须考虑清单 V3 的生命周期,因为服务工作器可能会被挂起和重启,需要模型运行时状态可恢复。
代理和工具执行循环
工具调用机制
Transformers.js 使用特定于模型的聊天模板来格式化提示。对于 Gemma 4,模型在决定调用工具时会发出特殊的工具调用令牌块(例如,<|tool_call>call:getWeather{location:<|">Bern<|">}<tool_call|>)。扩展程序使用归一化层(webMcp)和解析器(extractToolCalls)将这些模型输出转换为确定性执行。
循环设计 (Agent.runAgent)
扩展程序将内部模型转录与面向用户的聊天消息分开:
- 内部转录:包含用于
generator(...)函数的系统、用户、工具和助手轮次。 - UI 转录:包含流式助手文本、工具执行元数据和性能指标。
执行流程遵循一个循环:用户输入被添加 $\rightarrow$ 令牌被流式传输 $\rightarrow$ 在后台解析并执行工具调用 $\rightarrow$ 结果被反馈到提示中 $\rightarrow$ 循环重复,直到没有工具调用为止。
数据边界和持久性
状态根据生命周期和访问模式进行分布,以优化性能和持久性:
- 对话状态:存储在后台内存(
Agent.chatMessages)中以实现快速编排。 - 工具偏好:在会话之间持久化存储在
chrome.storage.local中。 - 语义历史向量:存储在 IndexedDB(
VectorHistoryDB)中以进行本地检索。 - 提取的页面内容:在后台缓存(
WebsiteContentManager)中进行管理,以活动 URL 为键。
构建和打包
为了满足清单 V3 的要求,项目通过 Vite 使用多入口构建,确保每个 Chrome 入口点有一个工件。内容脚本被保持为自包含输出,以防止运行时块加载问题,输出名称完全对齐于 manifest.json 的定义。