GenAI Summarization API

With ML Kit's GenAI Summarization API, you can automatically generate summaries of articles and conversations as a list of bullet points. This helps users understand large bodies of text.

Summarization benefits from on-device generative AI because it addresses concerns about data privacy and cost efficiency. Apps that summarize personal chats, emails, notes, and reminders often handle sensitive information, making on-device processing important for user privacy. In addition, summarization tasks, especially those with long contexts or many items, can require significant processing power. Processing this content on the device reduces server load and lowers serving costs, while keeping user data private.

Key capabilities

The GenAI Summarization API covers the following capabilities:

  • Summarize text, categorized as article or conversation.
  • Output summarization in one, two, or three bullets.

Get started

Add the ML Kit summarization API as a dependency in your build.gradle configuration.

  implementation 
 ( 
 "com.google.mlkit:genai-summarization:1.0.0-beta1" 
 ) 
 

Next, implement the code in your project:

  1. Create a Summarizer object.
  2. Download the feature if it is downloadable.
  3. Create a summarization request.
  4. Run inference and retrieve the result.

Kotlin

  val 
  
 articleToSummarize 
  
 = 
  
 "Announcing a set of on-device GenAI APIs..." 
 // Define task with required input type, output type, and language 
 val 
  
 summarizerOptions 
  
 = 
  
 SummarizerOptions 
 . 
 builder 
 ( 
 context 
 ) 
  
 . 
 setInputType 
 ( 
 InputType 
 . 
 ARTICLE 
 ) 
  
 . 
 setOutputType 
 ( 
 OutputType 
 . 
 ONE_BULLET 
 ) 
  
 . 
 setLanguage 
 ( 
 Language 
 . 
 ENGLISH 
 ) 
  
 . 
 build 
 () 
 val 
  
 summarizer 
  
 = 
  
 Summarization 
 . 
 getClient 
 ( 
 summarizerOptions 
 ) 
 suspend 
  
 fun 
  
 prepareAndStartSummarization 
 () 
  
 { 
  
 // Check feature availability. Status will be one of the following: 
  
 // UNAVAILABLE, DOWNLOADABLE, DOWNLOADING, AVAILABLE 
  
 val 
  
 featureStatus 
  
 = 
  
 summarizer 
 . 
 checkFeatureStatus 
 (). 
 await 
 () 
  
 if 
  
 ( 
 featureStatus 
  
 == 
  
 FeatureStatus 
 . 
 DOWNLOADABLE 
 ) 
  
 { 
  
 // Download feature if necessary. If downloadFeature is not called, 
  
 // the first inference request will also trigger the feature to be 
  
 // downloaded if it's not already downloaded. 
  
 summarizer 
 . 
 downloadFeature 
 ( 
 object 
  
 : 
  
 DownloadCallback 
  
 { 
  
 override 
  
 fun 
  
 onDownloadStarted 
 ( 
 bytesToDownload 
 : 
  
 Long 
 ) 
  
 { 
  
 } 
  
 override 
  
 fun 
  
 onDownloadFailed 
 ( 
 e 
 : 
  
 GenAiException 
 ) 
  
 { 
  
 } 
  
 override 
  
 fun 
  
 onDownloadProgress 
 ( 
 totalBytesDownloaded 
 : 
  
 Long 
 ) 
  
 {} 
  
 override 
  
 fun 
  
 onDownloadCompleted 
 () 
  
 { 
  
 startSummarizationRequest 
 ( 
 articleToSummarize 
 , 
  
 summarizer 
 ) 
  
 } 
  
 }) 
  
 } 
  
 else 
  
 if 
  
 ( 
 featureStatus 
  
 == 
  
 FeatureStatus 
 . 
 DOWNLOADING 
 ) 
  
 { 
  
 // Inference request will automatically run once feature is 
  
 // downloaded. If Gemini Nano is already downloaded on the device, 
  
 // the feature-specific LoRA adapter model will be downloaded 
  
 // quickly. However, if Gemini Nano is not already downloaded, the 
  
 // download process may take longer. 
  
 startSummarizationRequest 
 ( 
 articleToSummarize 
 , 
  
 summarizer 
 ) 
  
 } 
  
 else 
  
 if 
  
 ( 
 featureStatus 
  
 == 
  
 FeatureStatus 
 . 
 AVAILABLE 
 ) 
  
 { 
  
 startSummarizationRequest 
 ( 
 articleToSummarize 
 , 
  
 summarizer 
 ) 
  
 } 
 } 
 fun 
  
 startSummarizationRequest 
 ( 
 text 
 : 
  
 String 
 , 
  
 summarizer 
 : 
  
 Summarizer 
 ) 
  
 { 
  
 // Create task request 
  
 val 
  
 summarizationRequest 
  
 = 
  
 SummarizationRequest 
 . 
 builder 
 ( 
 text 
 ). 
 build 
 () 
  
 // Start summarization request with streaming response 
  
 summarizer 
 . 
 runInference 
 ( 
 summarizationRequest 
 ) 
  
 { 
  
 newText 
  
 - 
>  
 // Show new text in UI 
  
 } 
  
 // You can also get a non-streaming response from the request 
  
 // val summarizationResult = summarizer.runInference( 
  
 //     summarizationRequest).get().summary 
 } 
 // Be sure to release the resource when no longer needed 
 // For example, on viewModel.onCleared() or activity.onDestroy() 
 summarizer 
 . 
 close 
 () 
 

Java

  String 
  
 articleToSummarize 
  
 = 
  
 "Announcing: a set of on-device GenAI AI APIs." 
 ; 
 // Define task with required input type, output type, and language 
 SummarizerOptions 
  
 summarizerOptions 
  
 = 
  
  
 SummarizerOptions 
 . 
 builder 
 ( 
 context 
 ) 
  
 . 
 setInputType 
 ( 
 SummarizerOptions 
 . 
 InputType 
 . 
 ARTICLE 
 ) 
  
 . 
 setOutputType 
 ( 
 SummarizerOptions 
 . 
 OutputType 
 . 
 ONE_BULLET 
 ) 
  
 . 
 setLanguage 
 ( 
 SummarizerOptions 
 . 
 Language 
 . 
 ENGLISH 
 ) 
  
 . 
 build 
 (); 
 Summarizer 
  
 summarizer 
  
 = 
  
 Summarization 
 . 
 getClient 
 ( 
 summarizerOptions 
 ); 
 void 
  
 prepareAndStartSummarization 
 () 
  
 throws 
  
 ExecutionException 
 , 
  
 InterruptedException 
  
 { 
  
 // Check feature availability. Status will be one of the following: 
  
 // UNAVAILABLE, DOWNLOADABLE, DOWNLOADING, AVAILABLE 
  
 try 
  
 { 
  
 int 
  
 featureStatus 
  
 = 
  
 summarizer 
 . 
 checkFeatureStatus 
 (). 
 get 
 (); 
  
 if 
  
 ( 
 featureStatus 
  
 == 
  
 FeatureStatus 
 . 
 DOWNLOADABLE 
 ) 
  
 { 
  
 // Download feature if necessary. 
  
 // If downloadFeature is not called, the first inference request 
  
 // will also trigger the feature to be downloaded if it's not 
  
 // already downloaded. 
  
 summarizer 
 . 
 downloadFeature 
 ( 
 new 
  
 DownloadCallback 
 () 
  
 { 
  
 @Override 
  
 public 
  
 void 
  
 onDownloadCompleted 
 () 
  
 { 
  
 startSummarizationRequest 
 ( 
 articleToSummarize 
 , 
  
 summarizer 
 ); 
  
 } 
  
 @Override 
  
 public 
  
 void 
  
 onDownloadFailed 
 ( 
 GenAiException 
  
 e 
 ) 
  
 { 
  
 /* handle error */ 
  
 } 
  
 @Override 
  
 public 
  
 void 
  
 onDownloadProgress 
 ( 
 long 
  
 totalBytesDownloaded 
 ) 
  
 {} 
  
 @Override 
  
 public 
  
 void 
  
 onDownloadStarted 
 ( 
 long 
  
 bytesDownloaded 
 ) 
  
 {} 
  
 }); 
  
 } 
  
 else 
  
 if 
  
 ( 
 featureStatus 
  
 == 
  
 FeatureStatus 
 . 
 DOWNLOADING 
 ) 
  
 { 
  
 // Inference request will automatically run once feature is 
  
 // downloaded. If Gemini Nano is already downloaded on the 
  
 // device, the feature-specific LoRA adapter model will be 
  
 // downloaded quickly. However, if Gemini Nano is not already 
  
 // downloaded, the download process may take longer. 
  
 startSummarizationRequest 
 ( 
 articleToSummarize 
 , 
  
 summarizer 
 ); 
  
 } 
  
 else 
  
 if 
  
 ( 
 featureStatus 
  
 == 
  
 FeatureStatus 
 . 
 AVAILABLE 
 ) 
  
 { 
  
 startSummarizationRequest 
 ( 
 articleToSummarize 
 , 
  
 summarizer 
 ); 
  
 } 
  
 } 
  
 catch 
  
 ( 
 ExecutionException 
  
 | 
  
 InterruptedException 
  
 e 
 ) 
  
 { 
  
 e 
 . 
 printStackTrace 
 (); 
  
 } 
 } 
 void 
  
 startSummarizationRequest 
 ( 
 String 
  
 text 
 , 
  
 Summarizer 
  
 summarizer 
 ) 
  
 { 
  
 // Create task request 
  
 SummarizationRequest 
  
 summarizationRequest 
  
 = 
  
 SummarizationRequest 
 . 
 builder 
 ( 
 text 
 ). 
 build 
 (); 
  
 // Start summarization request with streaming response 
  
 summarizer 
 . 
 runInference 
 ( 
 summarizationRequest 
 , 
  
 newText 
  
 - 
>  
 { 
  
 // Show new text in UI 
  
 }); 
  
 // You can also get a non-streaming response from the request 
  
 // ListenableFuture<SummarizationResult> summarizationResult 
  
 //         = summarizer.runInference(summarizationRequest); 
  
 // String summary = summarizationResult.get().getSummary(); 
 } 
 // Be sure to release the resource when no longer needed 
 // For example, on viewModel.onCleared() or activity.onDestroy() 
 summarizer 
 . 
 close 
 (); 
 

How the model handles different input types

When the text input is specified as InputType.CONVERSATION , the model expects input in the following format:

 <name>: <message>
<name2>: <message2>
<name>: <message3>
<name3>: <message4> 

This enables the model to produce a more accurate summary by providing a better understanding of the conversation and interactions.

Supported features and limitations

Input must be under 4000 tokens (or approximately 3000 English words). If the input exceeds 4000 tokens, consider these options:

  • Prioritize summarization of the first 4000 tokens. Testing indicates this usually yields good results for longer inputs. Consider turning on auto truncation by calling setLongInputAutoTruncationEnabled so the extra input is automatically truncated.
  • Segment the input into groups of 4000 tokens, and summarize them individually.
  • Consider a cloud solution that is more suitable for the larger input.

For InputType.ARTICLE , input must also be over 400 characters, with the model performing best when the article is at least 300 words.

The GenAI Summarization API supports English, Japanese, and Korean, and is defined in SummarizerOptions.Language .

Availability of the specific feature configuration (specified by SummarizerOptions ) may vary depending on the particular device's configuration and the models that have been downloaded to the device.

The most reliable way for developers to ensure that the intended API feature is supported on a device with the requested SummarizerOptions is to call the checkFeatureStatus() method. This method provides the definitive status of feature availability on the device at runtime.

Common setup issues

ML Kit GenAI APIs rely on the Android AICore app to access Gemini Nano. When a device is just setup (including reset), or the AICore app is just reset (e.g. clear data, uninstalled then reinstalled), the AICore app may not have enough time to finish initialization (including downloading latest configurations from server). As a result, the ML Kit GenAI APIs may not function as expected. Here are the common setup error messages you may see and how to handle them:

Example error message How to handle
AICore failed with error type 4-CONNECTION_ERROR and error code 601-BINDING_FAILURE: AICore service failed to bind. This could happen when you install the app using ML Kit GenAI APIs immediately after device setup or when AICore is uninstalled after your app is installed. Updating AICore app then reinstalling your app should fix it.
AICore failed with error type 3-PREPARATION_ERROR and error code 606-FEATURE_NOT_FOUND: Feature ... is not available. This could happen when AICore hasn't finished downloading the latest configurations. When the device is connected to the internet, it usually takes a few minutes to a few hours to update. Restarting the device can speed up the update.

Note that if the device's bootloader is unlocked, you'll also see this error—this API does not support devices with unlocked bootloaders.
AICore failed with error type 1-DOWNLOAD_ERROR and error code 0-UNKNOWN: Feature ... failed with failure status 0 and error esz: UNAVAILABLE: Unable to resolve host ... Keep network connection, wait for a few minutes and retry.
Create a Mobile Website
View Site in Mobile | Classic
Share by: