Firebase JS SDK 中 LanguageModelCreateCoreOptions 详解:配置 Chrome 端侧语言模型会话的入口
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('描述这张图片');
需要注意几点(均由源码行为确认):
monitor与onDownloadProgress互斥:在 chrome-adapter.ts 的download()私有方法中,只有当createOptions.monitor未被设置、且initializeDeviceModel传入了onDownloadProgress时,SDK 才会把后者包装成一个自动订阅downloadprogress事件的 monitor 回调。若两者同时提供,onDownloadProgress会被静默忽略(generative-model.ts 的 JSDoc 也明确说明了这一点)。- 必须放在用户交互之后调用:initializeDeviceModel 的文档注释强调,若需要触发下载,此调用必须在用户与页面发生过交互(点击、按键等)之后进行,否则浏览器会报错——这是 Chrome Prompt API 的要求。
- 在 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,就能完整掌控"何时端侧推理、如何预下载、如何观测进度"这三个核心问题。
关键源码入口: