Firebase JS SDK 中 LanguageModelCreateCoreOptions 详解:配置 Chrome 端侧语言模型会话的入口

原创2026-10-14 16:45:501,746 阅读
文章标签:开发工具后端

Firebase JS SDK 中 LanguageModelCreateCoreOptions 详解:配置 Chrome 端侧语言模型会话的入口

在 Firebase JS SDK 的 @firebase/ai 包中,"混合推理"(hybrid inference)允许应用根据 InferenceMode(PREFER_ON_DEVICE、ONLY_ON_DEVICE、ONLY_IN_CLOUD、PREFER_IN_CLOUD)自动在云端 Gemini 模型与 Chrome 浏览器内置的端侧语言模型(Prompt API)之间切换。LanguageModelCreateCoreOptions 正是这一机制中配置端侧模型会话创建行为的公开接口:它声明了端侧模型期望的输入/输出模态与语言(expectedInputs / expectedOutputs),并提供了直连 Chrome 原生下载监控对象的钩子(monitor)。读完本文,你将理解该接口每个字段的含义与默认值、SDK 源码如何用它驱动模型可用性检查与下载,以及如何通过 getGenerativeModel + initializeDeviceModel 把这套配置真正用起来。

接口定义与三个属性

该接口定义于 language-model.ts,并经由 types/index.ts 对外导出:

/**
 * Configures the creation of an on-device language model session.
 * @public
 */
export interface LanguageModelCreateCoreOptions {
  /**
   * Defaults to image input and English text input
   * if not overriden.
   */
  expectedInputs?: LanguageModelExpected[];
  /**
   * Defaults to English text output if not overriden.
   */
  expectedOutputs?: LanguageModelExpected[];
  /**
   * The native download monitor provided by the Chrome API.
   * This provides direct access to the monitor object and is
   * only needed for advanced cases. For
   * a simpler download monitoring interface, provide an
   * `onDownloadProgress` callback
   * to {@link GenerativeModel.initializeDeviceModel} instead.
   */
  monitor?: (monitor: LanguageModelDownloadMonitor) => void;
}
属性 类型 说明
expectedInputs LanguageModelExpected[] 不覆盖时默认为图像输入 + 英文文本输入
expectedOutputs LanguageModelExpected[] 不覆盖时默认为覆盖时默认为英文文本输出
monitor (monitor: LanguageModelDownloadMonitor) => void 接收 Chrome API 提供的原生下载监控对象;仅在高级场景需要。更简单的进度监控方式是向 GenerativeModel.initializeDeviceModel() 传入 onDownloadProgress 回调

expectedInputs / expectedOutputs:期望的模态与语言

两者的元素类型都是 LanguageModelExpected,其定义同样位于 language-model.ts:

export interface LanguageModelExpected {
  type: LanguageModelMessageType; // 'text' | 'image' | 'audio'
  languages?: string[];          // 仅对文本模态有意义
}
  • type 取自 LanguageModelMessageType('text' | 'image' | 'audio');
  • languages 为可选的语言代码数组,例如 ['en']、['zh']。

这些声明会在会话创建前传给浏览器的 LanguageModel.availability() / create() 方法,用于告知浏览器"这个会话将消费哪些模态、哪些语言",浏览器据此判断所需模型是否可用、需要下载哪一个(这一点可从源码中 LanguageModel 接口签名 availability(options?: LanguageModelCreateCoreOptions): Promise<Availability> 得到印证)。

monitor:直连 Chrome 原生下载监控对象

回调参数类型是 LanguageModelDownloadMonitor,SDK 在 language-model.ts 中将其声明为:

export interface LanguageModelDownloadMonitor {
  addEventListener: (
    eventType: 'downloadprogress',
    eventListener: (e: { loaded: number }) => void
  ) => void;
  removeEventListener: (
    eventType: 'downloadprogress',
    eventListener: (e: { loaded: number }) => void
  ) => void;
}

即它是 Chrome Prompt API 原生 monitor 对象的最小化声明,只暴露了 downloadprogress 事件的 addEventListener / removeEventListener 两个方法。接口语义上明确写了:"只在需要直接访问 monitor 对象的高级场景使用;更简单的接口是 initializeDeviceModel(onDownloadProgress)"。

默认值在源码中如何补齐

不指定 expectedInputs / expectedOutputs 时的默认值,在 chrome-adapter.ts 中有明确定义:

// Defaults to English text. This can be overriden by user config.
const defaultExpectedText: LanguageModelExpected = {
  type: 'text',
  languages: ['en']
};

export const defaultExpectedInputs: LanguageModelExpected[] = [
  defaultExpectedText,
  { type: 'image' }   // 图像输入 + 英文文本输入
];

export const defaultExpectedOutputs: LanguageModelExpected[] = [
  defaultExpectedText  // 英文文本输出
];

ChromeAdapterImpl 的构造函数对这份默认值做了逐字段补齐(chrome-adapter.ts):即使你传入了部分配置的 createOptions,SDK 也会保证缺失的 expectedInputs、expectedOutputs 各自回落为对应默认值,而不是整份覆盖。这意味着"部分覆盖"是安全的——只写 expectedOutputs: [{ type: 'text', languages: ['zh'] }] 时,expectedInputs 依然保持"图像 + 英文文本"的默认行为。

这份配置最终存放在适配器的 onDeviceParams(类型为 OnDeviceParams)中,createOptions 字段的静态类型是 LanguageModelCreateOptions——即 LanguageModelCreateCoreOptions 的扩展:

export interface LanguageModelCreateOptions
  extends LanguageModelCreateCoreOptions {
  signal?: AbortSignal;
  initialPrompts?: LanguageModelMessage[];
}

因此 LanguageModelCreateCoreOptions 是"核心三件套",而 LanguageModelCreateOptions 额外支持 AbortSignal 与初始会话消息;availability() 只需要核心三件套即可工作,create() 才会用到完整的 LanguageModelCreateOptions。

实际用法:从 getGenerativeModel 到 initializeDeviceModel

该接口不直接暴露给顶层 API,而是嵌在 HybridParams 的 onDeviceParams.createOptions 里。结合 api.ts 中 getGenerativeModel 的实现(当传入的 modelParams 带有 mode 字段时被识别为 HybridParams),完整用法如下:

import { initializeApp } from 'firebase/app';
import { getAI, getGenerativeModel, InferenceMode } from 'firebase/ai';
import type { LanguageModelDownloadMonitor } from 'firebase/ai';

const app = initializeApp({ /* ... */ });
const ai = getAI(app);

const model = getGenerativeModel(ai, {
  mode: InferenceMode.PREFER_ON_DEVICE,
  onDeviceParams: {
    createOptions: {
      expectedInputs: [
        { type: 'text', languages: ['en'] },
        { type: 'image' }
      ],
      expectedOutputs: [{ type: 'text', languages: ['en'] }],
      // 高级用法:拿到 Chrome 原生 monitor 对象
      monitor: (monitor: LanguageModelDownloadMonitor) => {
        monitor.addEventListener('downloadprogress', e => {
          console.log('loaded bytes:', e.loaded);
        });
      }
    }
  }
});

// 建议在用户交互(如点击按钮)后调用;
// 更简单的进度接口(progressValue 介于 0 和 1 之间):
await model.initializeDeviceModel((progress) => {
  console.log(`${(progress * 100).toFixed(0)}%`);
});

const result = await model.generateContent('描述这张图片');

需要注意几点(均由源码行为确认):

  1. monitor 与 onDownloadProgress 互斥:在 chrome-adapter.ts 的 download() 私有方法中,只有当 createOptions.monitor 未被设置、且 initializeDeviceModel 传入了 onDownloadProgress 时,SDK 才会把后者包装成一个自动订阅 downloadprogress 事件的 monitor 回调。若两者同时提供,onDownloadProgress 会被静默忽略(generative-model.ts 的 JSDoc 也明确说明了这一点)。
  2. 必须放在用户交互之后调用:initializeDeviceModel 的文档注释强调,若需要触发下载,此调用必须在用户与页面发生过交互(点击、按键等)之后进行,否则浏览器会报错——这是 Chrome Prompt API 的要求。
  3. 在 Node 环境中不会启用端侧路径:factory-browser.ts 才注册了 chromeAdapterFactory;chromeAdapterFactory 只有在浏览器全局存在 LanguageModel(Prompt API)且处于混合模式时才返回适配器,否则 onDeviceParams 完全不起作用。

SDK 内部:这份配置如何驱动可用性检查与下载

LanguageModelCreateCoreOptions 在 ChromeAdapterImpl 中被反复使用,核心链路是:

  • 可用性检查:isAvailable(request)(chrome-adapter.ts)先按 mode 分流(ONLY_IN_CLOUD 直接返回 false),随后调用 languageModelProvider.availability(this.onDeviceParams.createOptions)。Availability 枚举有四个状态:UNAVAILABLE、DOWNLOADABLE、DOWNLOADING、AVAILABLE。
  • 下载编排:downloadIfAvailable(onDownloadProgress)(chrome-adapter.ts)再次调用 availability(),若状态为 DOWNLOADABLE 或 DOWNLOADING,则触发 download(),后者调用浏览器的 create(options) 并缓存 downloadPromise 防止重复请求下载(因为 Chrome 可能在启动或首次 create() 时自动开始下载)。
  • 会话创建:generateContent / generateContentStream 通过 createSession()(chrome-adapter.ts)以同一份 createOptions 调 create() 获得新的 LanguageModel 会话。从源码注释可以推断,SDK 对每次推理都新建会话(因为 Firebase AI 是单轮调用,而 Chrome 使用多轮会话),并在建立新会话后再销毁旧会话,避免模型被浏览器移出内存。
  • ONLY_ON_DEVICE 下的失败语义:当 availability 为 UNAVAILABLE(环境根本不支持该 API)且模式为 ONLY_ON_DEVICE 时,initializeDeviceModel 会抛出 AIError(错误信息为 'Local LanguageModel API not available in this environment.');而在 PREFER_ON_DEVICE 下仅记录 debug 日志并回落到云端。

除模态/语言声明外,SDK 还有自己的请求级兼容性门槛(isOnDeviceRequest,chrome-adapter.ts):端侧请求不能为空、不能包含 functionResponse 部件,内联图片的 MIME 类型必须在 <a href="https://link.gitcode.com/i/aa576c1ed32be4bfd8ed935ad1bed5a8" target="_blank">'image/jpeg', 'image/png'] 白名单内,否则即使模型可用也会回落到云端(或抛错,取决于模式)。另外 countTokens 在端侧尚不可用,[chrome-adapter.ts 会直接抛出 REQUEST_ERROR。

测试用例对该行为的验证

generative-model.test.ts 的 initializeDeviceModel 测试套件验证了与这份配置直接相关的四条行为:

用例 验证内容
throws if unavailable and ONLY_ON_DEVICE availability 为 UNAVAILABLE 且模式为 ONLY_ON_DEVICE 时,initializeDeviceModel() 抛错且 download 未被调用
noops if ONLY_IN_CLOUD 纯云端模式下直接空操作,不触发下载
noops if no adapter 浏览器无 Prompt API(无 chromeAdapter)时空操作
passes downloadProgress callback to download() 进度回调被透传给 downloadIfAvailable

配套的适配器测试位于 chrome-adapter.test.ts 与 chrome-adapter-browser.test.ts,后者还包含 chromeAdapterFactory 在无 LanguageModel 全局对象时返回 undefined 的场景。

小结与适用前提

LanguageModelCreateCoreOptions 是 @firebase/ai 混合推理中面向端侧模型的最小配置面:expectedInputs / expectedOutputs 声明模态与语言(默认"图像 + 英文文本输入、英文文本输出",且构造时会逐字段补齐),monitor 则把 Chrome 原生的 LanguageModelDownloadMonitor 暴露给需要精细控制下载事件的开发者。使用前提:浏览器暴露了 LanguageModel(Chrome Prompt API)、模型通过带 mode 的 HybridParams 创建、需要下载时 initializeDeviceModel() 须发生在用户交互之后。理解这一接口后,再配合 InferenceMode 与 OnDeviceParams,就能完整掌控"何时端侧推理、如何预下载、如何观测进度"这三个核心问题。

关键源码入口:

登录后查看全文
firebase-js-sdk