@@ -41,8 +41,10 @@ export class ChromeAdapter {
4141 constructor (
4242 private languageModelProvider ?: LanguageModel ,
4343 private mode ?: InferenceMode ,
44- private onDeviceParams ?: LanguageModelCreateOptions
45- ) { }
44+ private onDeviceParams : LanguageModelCreateOptions = { }
45+ ) {
46+ this . addImageTypeAsExpectedInput ( ) ;
47+ }
4648
4749 /**
4850 * Checks if a given request can be made on-device.
@@ -64,12 +66,8 @@ export class ChromeAdapter {
6466 return false ;
6567 }
6668
67- const availability = await this . languageModelProvider ?. availability ( ) ;
68-
69- // Triggers async model download so it'll be available next time.
70- if ( availability === Availability . downloadable ) {
71- this . download ( ) ;
72- }
69+ // Triggers out-of-band download so model will eventually become available.
70+ const availability = await this . downloadIfAvailable ( ) ;
7371
7472 if ( this . mode === 'only_on_device' ) {
7573 return true ;
@@ -91,10 +89,7 @@ export class ChromeAdapter {
9189 * @returns {@link Response }, so we can reuse common response formatting.
9290 */
9391 async generateContent ( request : GenerateContentRequest ) : Promise < Response > {
94- const session = await this . createSession (
95- // TODO: normalize on-device params during construction.
96- this . onDeviceParams || { }
97- ) ;
92+ const session = await this . createSession ( ) ;
9893 // TODO: support multiple content objects when Chrome supports
9994 // sequence<LanguageModelMessage>
10095 const contents = await Promise . all (
@@ -115,10 +110,7 @@ export class ChromeAdapter {
115110 async generateContentStream (
116111 request : GenerateContentRequest
117112 ) : Promise < Response > {
118- const session = await this . createSession (
119- // TODO: normalize on-device params during construction.
120- this . onDeviceParams || { }
121- ) ;
113+ const session = await this . createSession ( ) ;
122114 // TODO: support multiple content objects when Chrome supports
123115 // sequence<LanguageModelMessage>
124116 const contents = await Promise . all (
@@ -155,7 +147,22 @@ export class ChromeAdapter {
155147 }
156148
157149 /**
158- * Triggers the download of an on-device model.
150+ * Encapsulates logic to get availability and download a model if one is downloadable.
151+ */
152+ private async downloadIfAvailable ( ) : Promise < Availability | undefined > {
153+ const availability = await this . languageModelProvider ?. availability (
154+ this . onDeviceParams
155+ ) ;
156+
157+ if ( availability === Availability . downloadable ) {
158+ this . download ( ) ;
159+ }
160+
161+ return availability ;
162+ }
163+
164+ /**
165+ * Triggers out-of-band download of an on-device model.
159166 *
160167 * <p>Chrome only downloads models as needed. Chrome knows a model is needed when code calls
161168 * LanguageModel.create.</p>
@@ -168,10 +175,8 @@ export class ChromeAdapter {
168175 return ;
169176 }
170177 this . isDownloading = true ;
171- const options = this . onDeviceParams || { } ;
172- ChromeAdapter . addImageTypeAsExpectedInput ( options ) ;
173178 this . downloadPromise = this . languageModelProvider
174- ?. create ( options )
179+ ?. create ( this . onDeviceParams )
175180 . then ( ( ) => {
176181 this . isDownloading = false ;
177182 } ) ;
@@ -214,19 +219,16 @@ export class ChromeAdapter {
214219 * <p>Chrome will remove a model from memory if it's no longer in use, so this method ensures a
215220 * new session is created before an old session is destroyed.</p>
216221 */
217- private async createSession (
218- // TODO: define a default value, since these are optional.
219- options : LanguageModelCreateOptions
220- ) : Promise < LanguageModel > {
222+ private async createSession ( ) : Promise < LanguageModel > {
221223 if ( ! this . languageModelProvider ) {
222224 throw new AIError (
223225 AIErrorCode . REQUEST_ERROR ,
224226 'Chrome AI requested for unsupported browser version.'
225227 ) ;
226228 }
227- // TODO: could we use this.onDeviceParams instead of passing in options?
228- ChromeAdapter . addImageTypeAsExpectedInput ( options ) ;
229- const newSession = await this . languageModelProvider ! . create ( options ) ;
229+ const newSession = await this . languageModelProvider . create (
230+ this . onDeviceParams
231+ ) ;
230232 if ( this . oldSession ) {
231233 this . oldSession . destroy ( ) ;
232234 }
@@ -235,11 +237,9 @@ export class ChromeAdapter {
235237 return newSession ;
236238 }
237239
238- private static addImageTypeAsExpectedInput (
239- options : LanguageModelCreateOptions
240- ) : void {
241- options . expectedInputs = options . expectedInputs || [ ] ;
242- options . expectedInputs . push ( { type : 'image' } ) ;
240+ private addImageTypeAsExpectedInput ( ) : void {
241+ // Defaults to support image inputs for convenience.
242+ this . onDeviceParams . expectedInputs ??= [ { type : 'image' } ] ;
243243 }
244244
245245 /**
0 commit comments