From 295378c0d4971079f9e06faab37fd6bff122e752 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Thu, 24 Oct 2024 15:49:38 +0900 Subject: [PATCH 1/3] Initial specification work, focused on creation and downloading --- index.bs | 377 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 370 insertions(+), 7 deletions(-) diff --git a/index.bs b/index.bs index d4f1672..8c79db7 100644 --- a/index.bs +++ b/index.bs @@ -1,21 +1,384 @@ -
+
 
-Introduction {#intro}
-=====================
+
+
+
+
+

Introduction

For now, see the [explainer]([REPOSITORYURL]). + +

Shared AI APIs and infrastructure

+ + +partial interface WindowOrWorkerGlobalScope { + [Replaceable, SecureContext] readonly attribute AI ai; +}; + +[Exposed=(Window,Worker), SecureContext] +interface AI {}; + +[Exposed=(Window,Worker), SecureContext] +interface AICreateMonitor : EventTarget { + attribute EventHandler ondownloadprogress; +}; + +callback AICreateMonitorCallback = undefined (AICreateMonitor monitor); + +enum AICapabilityAvailability { "readily", "after-download", "no" }; + + +Each {{WindowOrWorkerGlobalScope}} has an AI namespace, an {{AI}} object. Upon creation of the {{WindowOrWorkerGlobalScope}} object, its [=WindowOrWorkerGlobalScope/AI namespace=] must be set to a [=new=] {{AI}} object created in the {{WindowOrWorkerGlobalScope}} object's [=relevant realm=]. + +The ai getter steps are to return [=this=]'s [=WindowOrWorkerGlobalScope/AI namespace=]. + +
+ +[=Tasks=] queued by this specification use the AI task source. + +
+ +The following are the [=event handlers=] (and their corresponding [=event handler event types=]) that must be supported, as [=event handler IDL attributes=], by all {{AICreateMonitor}} objects: + + + + + + +
[=Event handler=] + [=Event handler event type=] +
ondownloadprogress + downloadprogress +
+ +

The summarizer API

+ + +partial interface AI { + readonly attribute AISummarizerFactory summarizer; +}; + +[Exposed=(Window,Worker), SecureContext] +interface AISummarizerFactory { + Promise<AISummarizer> create(optional AISummarizerCreateOptions options = {}); + Promise<AISummarizerCapabilities> capabilities(); +}; + +[Exposed=(Window,Worker), SecureContext] +interface AISummarizer { + Promise<DOMString> summarize(DOMString input, optional AISummarizerSummarizeOptions options = {}); + ReadableStream summarizeStreaming(DOMString input, optional AISummarizerSummarizeOptions options = {}); + + readonly attribute DOMString sharedContext; + readonly attribute AISummarizerType type; + readonly attribute AISummarizerFormat format; + readonly attribute AISummarizerLength length; + + undefined destroy(); +}; + +[Exposed=(Window,Worker), SecureContext] +interface AISummarizerCapabilities { + readonly attribute AICapabilityAvailability available; + + AICapabilityAvailability createOptionsAvailable(optional AISummarizerCreateCoreOptions options = {}); + AICapabilityAvailability languageAvailable(DOMString languageTag); +}; + +dictionary AISummarizerCreateCoreOptions { + AISummarizerType type = "key-points"; + AISummarizerFormat format = "markdown"; + AISummarizerLength length = "short"; +}; + +dictionary AISummarizerCreateOptions : AISummarizerCreateCoreOptions { + AbortSignal signal; + AICreateMonitorCallback monitor; + + DOMString sharedContext; +}; + +dictionary AISummarizerSummarizeOptions { + AbortSignal signal; + DOMString context; +}; + +enum AISummarizerType { "tl;dr", "key-points", "teaser", "headline" }; +enum AISummarizerFormat { "plain-text", "markdown" }; +enum AISummarizerLength { "short", "medium", "long" }; + + +Each {{AI}} has an summarizer factory, an {{AISummarizerFactory}} object. Upon creation of the {{AI}} object, its [=AI/summarizer factory=] must be set to a [=new=] {{AISummarizerFactory}} object created in the {{AI}} object's [=relevant realm=]. + +The summarizer getter steps are to return [=this=]'s [=AI/summarizer factory=]. + +

Creation

+ +
+ The create(|options|) method steps are: + + 1. If [=this=]'s [=relevant global object=] is a {{Window}} whose [=associated Document=] is not [=Document/fully active=], then return [=a promise rejected with=] an "{{InvalidStateError}}" {{DOMException}}. + + 1. If |options|["{{AISummarizerCreateOptions/signal}}"] [=map/exists=] and is [=AbortSignal/aborted=], then return [=a promise rejected with=] |options|["{{AISummarizerCreateOptions/signal}}"]'s [=AbortSignal/abort reason=]. + + 1. Let |fireProgressEvent| be an algorithm taking two arguments that does nothing. + + 1. If |options|["{{AISummarizerCreateOptions/monitor}}"] [=map/exists=], then: + + 1. Let |monitor| be a [=new=] {{AICreateMonitor}} created in [=this=]'s [=relevant realm=]. + + 1. [=Invoke=] |options|["{{AISummarizerCreateOptions/monitor}}"] with « |monitor| » and "`rethrow`". + + If an exception |e| is thrown, return [=a promise rejected with=] |e|. + + 1. Set |fireProgressEvent| to an algorithm taking arguments |loaded| and |total|, which performs the following steps: + + 1. [=Assert=]: this algorithm is running [=in parallel=]. + + 1. [=Queue a global task=] on the [=AI task source=] given [=this=]'s [=relevant global object=] to perform the following steps: + + 1. [=Fire an event=] named {{AICreateMonitor/downloadprogress}} at |monitor|, using {{ProgressEvent}}, with the {{ProgressEvent/loaded}} attribute initialized to |loaded|, the {{ProgressEvent/total}} attribute initialized to |total|, and the {{ProgressEvent/lengthComputable}} attribute initialized to true. + + 1. Let |abortedDuringDownload| be false. + +

This variable will be written to from the [=event loop=], but read from [=in parallel=]. + + 1. If |options|["{{AISummarizerCreateOptions/signal}}"] [=map/exists=], then [=AbortSignal/add|add the following abort steps=] to |options|["{{AISummarizerCreateOptions/signal}}"]: + + 1. Set |abortedDuringDownload| to true. + + 1. Let |promise| be [=a new promise=] created in [=this=]'s [=relevant realm=]. + + 1. [=In parallel=]: + + 1. Let |availability| be the [=current summarizer capability value=] given |options|["{{AISummarizerCreateCoreOptions/type}}"], |options|["{{AISummarizerCreateCoreOptions/format}}"], and |options|["{{AISummarizerCreateCoreOptions/length}}"]. + + 1. Switch on |availability|: + +

+ : "{{AICapabilityAvailability/no}}" + :: + 1. [=Reject=] |promise| with a "{{NotSupportedError}}" {{DOMException}}. + + 1. Abort these steps. + + : "{{AICapabilityAvailability/readily}}" + :: + 1. If [=initializing the summarization model=] given |promise| and |options| returns false, then abort these steps. + + 1. Let |totalBytes| be the total size of the previously-downloaded summarization capabilities, in bytes. + + 1. [=Assert=]: |totalBytes| is greater than 0. + + 1. Perform |fireProgressEvent| given 0 and |totalBytes|. + + 1. Perform |fireProgressEvent| given |totalBytes| and |totalBytes|. + + 1. [=Finalize summarizer creation=] given |promise| and |options|. + + : "{{AICapabilityAvailability/after-download}}" + :: + 1. Initiate the download process for everything the user agent needs to summarize text according to |options|["{{AISummarizerCreateCoreOptions/type}}"], |options|["{{AISummarizerCreateCoreOptions/format}}"], or |options|["{{AISummarizerCreateCoreOptions/length}}"]. + + 1. Run the following steps, by [=abort when=] |abortedDuringDownload| becomes true: + + 1. Wait for the total number of bytes to be downloaded to become determined, and let that number be |totalBytes|. + + 1. Let |lastProgressTime| be the [=monotonic clock=]'s [=monotonic clock/unsafe current time=]. + + 1. Perform |fireProgressEvent| given 0 and |totalBytes|. + + 1. While true: + + 1. If one or more bytes have been downloaded, then: + + 1. If the [=monotonic clock=]'s [=monotonic clock/unsafe current time=] minus |lastProgressTime| is greater than 50 ms, then: + + 1. Let |bytesSoFar| be the number of bytes downloaded so far. + + 1. [=Assert=]: |bytesSoFar| is greater than 0 and less than or equal to |totalBytes|. + + 1. Perform |fireProgressEvent| given |bytesSoFar| and |totalBytes|. + + 1. If |bytesSoFar| equals |totalBytes|, then [=iteration/break=]. + + 1. Set |lastProgressTime| to the [=monotonic clock=]'s [=monotonic clock/unsafe current time=]. + + 1. Otherwise, if downloading has failed and cannot continue, then: + + 1. [=Queue a global task=] on the [=AI task source=] given [=this=]'s [=relevant global object=] to [=reject=] |promise| with a "{{NetworkError}}" {{DOMException}}. + + 1. Abort these steps. + + 1. [=If aborted=], then: + 1. [=Queue a global task=] on the [=AI task source=] given [=this=]'s [=relevant global object=] to perform the following steps: + + 1. [=Assert=]: |options|["{{AISummarizerCreateOptions/signal}}"]'s is [=AbortSignal/aborted=]. + + 1. [=Reject=] |promise| with |options|["{{AISummarizerCreateOptions/signal}}"]'s [=AbortSignal/abort reason=]. + + 1. Abort these steps. + + 1. If [=initializing the summarization model=] given |promise| and |options| returns false, then abort these steps. + + 1. [=Finalize summarizer creation=] given |promise| and |options|. +
+ + 1. Return |promise|. +
+ +
+ To initialize the summarization model, given a {{Promise}} |promise| and an {{AISummarizerCreateOptions}} |options|: + + 1. [=Assert=]: these steps are running [=in parallel=]. + + 1. Perform any necessarily initialization operations for the AI model backing the [=user agent=]'s summarization capabilities. + + This could include loading the model into memory, loading |options|["{{AISummarizerCreateOptions/sharedContext}}"] into the model's context window, or loading any fine-tunings necessary to support |options|["{{AISummarizerCreateCoreOptions/type}}"], |options|["{{AISummarizerCreateCoreOptions/format}}"], or |options|["{{AISummarizerCreateCoreOptions/length}}"]. + + 1. If initialization failed for any reason, then: + + 1. [=Queue a global task=] on the [=AI task source=] given |promise|'s [=relevant global object=] to [=reject=] |promise| with an "{{OperationError}}" {{DOMException}}. + + 1. Return false. + + 1. Return true. +
+ +
+ To finalize summarizer creation, given a {{Promise}} |promise| and an {{AISummarizerCreateOptions}} |options|: + + 1. [=Assert=]: these steps are running [=in parallel=]. + + 1. [=Assert=]: the [=current summarizer capability value=] for |options|["{{AISummarizerCreateCoreOptions/type}}"], |options|["{{AISummarizerCreateCoreOptions/format}}"], and |options|["{{AISummarizerCreateCoreOptions/length}}"] is "{{AICapabilityAvailability/readily}}". + + 1. [=Queue a global task=] on the [=AI task source=] given |promise|'s [=relevant global object=] to perform the following steps: + + 1. If |options|["{{AISummarizerCreateOptions/signal}}"] [=map/exists=] and is [=AbortSignal/aborted=], then: + + 1. [=Reject=] |promise| with |options|["{{AISummarizerCreateOptions/signal}}"]'s [=AbortSignal/abort reason=]. + + 1. Abort these steps. + +

This check is necessary in case any code running on the [=agent/event loop=] caused the {{AbortSignal}} to become [=AbortSignal/aborted=] before this [=task=] ran. + + 1. Let |summarizer| be a new {{AISummarizer}} object, created in |promise|'s [=relevant realm=], with + +

+ : [=AISummarizer/shared context=] + :: |options|["{{AISummarizerCreateOptions/sharedContext}}"] + + : [=AISummarizer/summary type=] + :: |options|["{{AISummarizerCreateCoreOptions/type}}"] + + : [=AISummarizer/summary format=] + :: |options|["{{AISummarizerCreateCoreOptions/format}}"] + + : [=AISummarizer/summary length=] + :: |options|["{{AISummarizerCreateCoreOptions/length}}"] +
+ + 1. If |options|["{{AISummarizerCreateOptions/signal}}"] [=map/exists=], then [=AbortSignal/add|add the following abort steps=] to |options|["{{AISummarizerCreateOptions/signal}}"]: + + 1. [=AISummarizer/Destroy=] |summarizer| with |options|["{{AISummarizerCreateOptions/signal}}"]'s [=AbortSignal/abort reason=]. + + 1. [=Resolve=] |promise| with |summarizer|. +
+ +

Capabilities

+ +TODO algorithm for the creation of {{AISummarizerCapabilities}} objects and how they get their snapshot. + +
+ +Every {{AISummarizerCapabilities}} has an available create options, a [=map=] from [=tuples=] of ({{AISummarizerType}}, {{AISummarizerFormat}}, {{AISummarizerLength}}) values to {{AICapabilityAvailability}} values, set during creation. The [=map/values=] will never be "{{AICapabilityAvailability/no}}". + +Every {{AISummarizerCapabilities}} has an available languages, a [=map=] of strings representing BCP 47 language tags to {{AICapabilityAvailability}} values, set during creation. The [=map/values=] will never be "{{AICapabilityAvailability/no}}". + +
+ The available getter steps are: + + 1. If either [=this=]'s [=AISummarizerCapabilities/available create options=] or [=this=]'s [=AISummarizerCapabilities/available languages=] [=map/is empty|are empty=], then return "{{AICapabilityAvailability/no}}". + + 1. If all of [=this=]'s [=AISummarizerCapabilities/available create options=]'s [=map/values=] or all of [=this=]'s [=AISummarizerCapabilities/available languages=]'s [=map/values=] are "{{AICapabilityAvailability/after-download}}", then return "{{AICapabilityAvailability/after-download}}". + + 1. Return "{{AICapabilityAvailability/readily}}". +
+ +
+ The createOptionsAvailable(|options|) method steps are: + + 1. Return [=this=]'s [=AISummarizerCapabilities/available create options=][(|options|["{{AISummarizerCreateCoreOptions/type}}"], |options|["{{AISummarizerCreateCoreOptions/format}}"], |options|["{{AISummarizerCreateCoreOptions/length}}"])]. +
+ +
+ The languageAvailable(|languageTag|) method steps are: + + 1. Return [=this=]'s [=AISummarizerCapabilities/available languages=][|languageTag|]. + +

Per WICG/translation-api#11 it seems we're supposed to do something more complex than just straight string comparison here, but it's not clear what.

+
+ +
+ +
+ The current summarizer capability value, given a {{AISummarizerType}} |type|, {{AISummarizerFormat}} |format|, and an {{AISummarizerLength}} |length|, is the return value of the following steps: + + 1. [=Assert=]: this algorithm is running [=in parallel=]. + + 1. If the user agent supports summarizing text into the type of summary described by |type|, in the format described by |format|, and with the length guidance given by |length| without performing any downloading operations, then return "{{AICapabilityAvailability/readily}}". + + 1. If the user agent believes it can summarize text according to |type|, |format|, and |length|, but only after performing a download (e.g., of an AI model or fine-tuning), then return "{{AICapabilityAvailability/after-download}}". + + 1. Otherwise, return "{{AICapabilityAvailability/no}}". +
+ +

Summarization

+ +Every {{AISummarizer}} has a shared context, a [=string=], set during creation. + +Every {{AISummarizer}} has a summary type, an {{AISummarizerType}}, set during creation. + +Every {{AISummarizer}} has a summary format, an {{AISummarizerFormat}}, set during creation. + +Every {{AISummarizer}} has a summary length, an {{AISummarizerLength}}, set during creation. + +The sharedContext getter steps are to return [=this=]'s [=AISummarizer/shared context=]. + +The type getter steps are to return [=this=]'s [=AISummarizer/summary type=]. + +The format getter steps are to return [=this=]'s [=AISummarizer/summary format=]. + +The length getter steps are to return [=this=]'s [=AISummarizer/summary length=]. + +The destroy() method steps are to [=AISummarizer/destroy=] [=this=] given a new "{{AbortError}}" {{DOMException}}. + +
+ To destroy an {{AISummarizer}} |summarizer|, given a JavaScript value |exception|: + + 1. TODO use |summarizer| and |exception|. +
From 2c71f68803901fb5ce19cde88606afc36d626443 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Tue, 29 Oct 2024 11:36:19 +0900 Subject: [PATCH 2/3] Respond to review feedback --- index.bs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/index.bs b/index.bs index 8c79db7..86de198 100644 --- a/index.bs +++ b/index.bs @@ -90,8 +90,14 @@ interface AISummarizerFactory { [Exposed=(Window,Worker), SecureContext] interface AISummarizer { - Promise summarize(DOMString input, optional AISummarizerSummarizeOptions options = {}); - ReadableStream summarizeStreaming(DOMString input, optional AISummarizerSummarizeOptions options = {}); + Promise summarize( + DOMString input, + optional AISummarizerSummarizeOptions options = {} + ); + ReadableStream summarizeStreaming( + DOMString input, + optional AISummarizerSummarizeOptions options = {} + ); readonly attribute DOMString sharedContext; readonly attribute AISummarizerType type; @@ -105,7 +111,9 @@ interface AISummarizer { interface AISummarizerCapabilities { readonly attribute AICapabilityAvailability available; - AICapabilityAvailability createOptionsAvailable(optional AISummarizerCreateCoreOptions options = {}); + AICapabilityAvailability createOptionsAvailable( + optional AISummarizerCreateCoreOptions options = {} + ); AICapabilityAvailability languageAvailable(DOMString languageTag); }; @@ -256,7 +264,7 @@ The summarizer getter steps are to return [=this=] 1. [=Assert=]: these steps are running [=in parallel=]. - 1. Perform any necessarily initialization operations for the AI model backing the [=user agent=]'s summarization capabilities. + 1. Perform any necessary initialization operations for the AI model backing the [=user agent=]'s summarization capabilities. This could include loading the model into memory, loading |options|["{{AISummarizerCreateOptions/sharedContext}}"] into the model's context window, or loading any fine-tunings necessary to support |options|["{{AISummarizerCreateCoreOptions/type}}"], |options|["{{AISummarizerCreateCoreOptions/format}}"], or |options|["{{AISummarizerCreateCoreOptions/length}}"]. From e60fe383bff7e8eb09b5e4c9fc41a58b57b7a278 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Tue, 29 Oct 2024 15:43:28 +0900 Subject: [PATCH 3/3] Do most of the capabilities spec, modulo language tag issues --- index.bs | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 81 insertions(+), 9 deletions(-) diff --git a/index.bs b/index.bs index 86de198..5b86992 100644 --- a/index.bs +++ b/index.bs @@ -14,9 +14,10 @@ Assume Explicit For: yes Default Biblio Status: current Boilerplate: omit conformance Indent: 2 -Die On: warning
+TODO add back Die On: warning + @@ -183,11 +184,17 @@ The summarizer getter steps are to return [=this=] 1. [=In parallel=]: - 1. Let |availability| be the [=current summarizer capability value=] given |options|["{{AISummarizerCreateCoreOptions/type}}"], |options|["{{AISummarizerCreateCoreOptions/format}}"], and |options|["{{AISummarizerCreateCoreOptions/length}}"]. + 1. Let |availability| be the [=current summarizer create options availability=] given |options|["{{AISummarizerCreateCoreOptions/type}}"], |options|["{{AISummarizerCreateCoreOptions/format}}"], and |options|["{{AISummarizerCreateCoreOptions/length}}"]. 1. Switch on |availability|:
+ : null + :: + 1. [=Reject=] |promise| with an "{{UnknownError}}" {{DOMException}}. + + 1. Abort these steps. + : "{{AICapabilityAvailability/no}}" :: 1. [=Reject=] |promise| with a "{{NotSupportedError}}" {{DOMException}}. @@ -282,7 +289,7 @@ The summarizer getter steps are to return [=this=] 1. [=Assert=]: these steps are running [=in parallel=]. - 1. [=Assert=]: the [=current summarizer capability value=] for |options|["{{AISummarizerCreateCoreOptions/type}}"], |options|["{{AISummarizerCreateCoreOptions/format}}"], and |options|["{{AISummarizerCreateCoreOptions/length}}"] is "{{AICapabilityAvailability/readily}}". + 1. [=Assert=]: the [=current summarizer create options availability=] for |options|["{{AISummarizerCreateCoreOptions/type}}"], |options|["{{AISummarizerCreateCoreOptions/format}}"], and |options|["{{AISummarizerCreateCoreOptions/length}}"] is "{{AICapabilityAvailability/readily}}". 1. [=Queue a global task=] on the [=AI task source=] given |promise|'s [=relevant global object=] to perform the following steps: @@ -319,18 +326,57 @@ The summarizer getter steps are to return [=this=]

Capabilities

-TODO algorithm for the creation of {{AISummarizerCapabilities}} objects and how they get their snapshot. +
+ The capabilities() method steps are: + + 1. If [=this=]'s [=relevant global object=] is a {{Window}} whose [=associated Document=] is not [=Document/fully active=], then return [=a promise rejected with=] an "{{InvalidStateError}}" {{DOMException}}. + + 1. Let |promise| be [=a new promise=] created in [=this=]'s [=relevant realm=]. + + 1. [=In parallel=]: + + 1. Let |availableCreateOptions| be a new [=map=] from [=tuples=] of ({{AISummarizerType}}, {{AISummarizerFormat}}, {{AISummarizerLength}}) values to {{AICapabilityAvailability}} values, initially empty. + + 1. [=list/For each=] |type| of {{AISummarizerType}}'s [=enumeration values=]: + + 1. [=list/For each=] |format| of {{AISummarizerFormat}}'s [=enumeration values=]: + + 1. [=list/For each=] |length| of {{AISummarizerLength}}'s [=enumeration values=]: + + 1. Set |availableCreateOptions|[(|type|, |format|, |length|)] to the [=current summarizer create options availability=] given |type|, |format|, and |length|. + + 1. Let |availableLanguages| be the [=current summarizer language availability map=]. + + 1. If |availableLanguages| is null, or |availableCreateOptions|'s [=map/values=] [=list/contains=] null, then [=queue a global task=] on the [=AI task source=] given [=this=] to perform the following steps: + + 1. [=Reject=] |promise| with an "{{UnknownError}}" {{DOMException}}. + + 1. Otherwise, [=queue a global task=] on the [=AI task source=] given [=this=] to perform the following steps: + + 1. Let |capabilitiesObject| be a new {{AISummarizerCapabilities}} object, created in [=this=]'s [=relevant realm=], with + +
+ : [=AISummarizerCapabilities/available create options=] + :: |availableCreateOptions| + : [=AISummarizerCapabilities/available languages=] + :: |availableLanguages| +
+ + 1. [=Resolve=] |promise| with |capabilitiesObject|. +

-Every {{AISummarizerCapabilities}} has an available create options, a [=map=] from [=tuples=] of ({{AISummarizerType}}, {{AISummarizerFormat}}, {{AISummarizerLength}}) values to {{AICapabilityAvailability}} values, set during creation. The [=map/values=] will never be "{{AICapabilityAvailability/no}}". +Every {{AISummarizerCapabilities}} has an available create options, a [=map=] from [=tuples=] of ({{AISummarizerType}}, {{AISummarizerFormat}}, {{AISummarizerLength}}) values to {{AICapabilityAvailability}} values, set during creation. Every {{AISummarizerCapabilities}} has an available languages, a [=map=] of strings representing BCP 47 language tags to {{AICapabilityAvailability}} values, set during creation. The [=map/values=] will never be "{{AICapabilityAvailability/no}}".
The available getter steps are: - 1. If either [=this=]'s [=AISummarizerCapabilities/available create options=] or [=this=]'s [=AISummarizerCapabilities/available languages=] [=map/is empty|are empty=], then return "{{AICapabilityAvailability/no}}". + 1. If [=this=]'s [=AISummarizerCapabilities/available languages=] [=map/is empty|are empty=], then return "{{AICapabilityAvailability/no}}". + + 1. If [=this=]'s all of [=this=]'s [=AISummarizerCapabilities/available create options=] [=map/values=] are "{{AICapabilityAvailability/no}}", then return "{{AICapabilityAvailability/no}}". 1. If all of [=this=]'s [=AISummarizerCapabilities/available create options=]'s [=map/values=] or all of [=this=]'s [=AISummarizerCapabilities/available languages=]'s [=map/values=] are "{{AICapabilityAvailability/after-download}}", then return "{{AICapabilityAvailability/after-download}}". @@ -346,15 +392,15 @@ Every {{AISummarizerCapabilities}} has an av
The languageAvailable(|languageTag|) method steps are: - 1. Return [=this=]'s [=AISummarizerCapabilities/available languages=][|languageTag|]. + 1. Return [=this=]'s [=AISummarizerCapabilities/available languages=][|languageTag|], or "{{AICapabilityAvailability/no}}" if no such [=map/entry=] [=map/exists=]. -

Per WICG/translation-api#11 it seems we're supposed to do something more complex than just straight string comparison here, but it's not clear what.

+

Per WICG/translation-api#11 it seems we're supposed to do something more complex than just straight string comparison for language tags, but it's not clear what.


- The current summarizer capability value, given a {{AISummarizerType}} |type|, {{AISummarizerFormat}} |format|, and an {{AISummarizerLength}} |length|, is the return value of the following steps: + The current summarizer create options availability, given a {{AISummarizerType}} |type|, {{AISummarizerFormat}} |format|, and an {{AISummarizerLength}} |length|, is given by the following steps. They return an {{AICapabilityAvailability}} value or null. 1. [=Assert=]: this algorithm is running [=in parallel=]. @@ -362,9 +408,35 @@ Every {{AISummarizerCapabilities}} has an av 1. If the user agent believes it can summarize text according to |type|, |format|, and |length|, but only after performing a download (e.g., of an AI model or fine-tuning), then return "{{AICapabilityAvailability/after-download}}". + 1. If there is some error attempting to determine whether the user agent supports summarizing text, which the user agent believes to be transient (such that re-querying the [=current summarizer create options availability=] could stop producing such an error), then return null. + 1. Otherwise, return "{{AICapabilityAvailability/no}}".
+
+ The current summarizer language availability map is given by the following steps. They return a [=map=] from strings representing BCP 47 language tags to {{AICapabilityAvailability}} values, or null. [[!RFC5646]] + + 1. [=Assert=]: this algorithm is running [=in parallel=]. + + 1. If there is some error attempting to determine whether the user agent supports summarizing text, which the user agent believes to be transient (such that re-querying the [=current summarizer create options availability=] could stop producing such an error), then return null. + + 1. Let |availableLanguages| be an empty [=map=]. + + 1. [=list/For each=] human language for which the user agent supports summarizing text written in that language, without performing any downloading operations: + + 1. Let |languageTag| be that language, represented as a BCP 47 language tag string. Describe how to handle subtags. + + 1. Set |availableLanguages|[|languageTag|] to "{{AICapabilityAvailability/readily}}". + + 1. [=list/For each=] human language for which the user agent believes it can summarize text written in that language, but only after performing a download (e.g., of an AI model or fine-tuning): + + 1. Let |languageTag| be that language, represented as a BCP 47 language tag string. Describe how to handle subtags. + + 1. Set |availableLanguages|[|languageTag|] to "{{AICapabilityAvailability/after-download}}". + + 1. Return |availableLanguages|. +
+

Summarization

Every {{AISummarizer}} has a shared context, a [=string=], set during creation.