GenAI Summarization API

借助 ML Kit 的 GenAI Summarization API,您可以自动生成文章和对话的摘要,并以项目符号列表的形式呈现。这有助于用户理解大量文本。

摘要功能得益于设备端生成式 AI,因为它解决了数据隐私和成本效益方面的问题。总结个人聊天内容、电子邮件、笔记和提醒的应用通常会处理敏感信息,因此设备端处理对于用户隐私保护至关重要。此外,摘要任务(尤其是那些具有长上下文或许多项目的任务)可能需要大量的处理能力。在设备上处理这些内容可减少服务器负载并降低传送费用,同时还能确保用户数据的私密性。

主要功能

GenAI 总结 API 涵盖以下功能:

  • 总结归类为文章或对话的文本。
  • 以一、二或三个项目符号的形式输出总结。

开始使用

build.gradle 配置中添加 ML Kit 总结 API 作为依赖项。

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

接下来,在项目中实现代码:

  1. 创建一个 Summarizer 对象。
  2. 下载可下载的功能。
  3. 创建总结请求。
  4. 运行推理并检索结果。

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();

模型如何处理不同的输入类型

如果将文本输入指定为 InputType.CONVERSATION,则模型需要采用以下格式的输入:

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

这样一来,模型就能更好地理解对话和互动,从而生成更准确的摘要。

支持的功能和限制

输入内容必须少于 4,000 个 token(或大约 3,000 个英文单词)。如果输入超过 4, 000 个词法单元,请考虑以下选项:

  • 优先总结前 4,000 个令牌。测试表明,对于较长的输入,此模型通常会产生良好的结果。考虑通过调用 setLongInputAutoTruncationEnabled 开启自动截断功能,以便自动截断多余的输入内容。
  • 将输入内容分段为 4, 000 个令牌一组,然后分别进行总结。
  • 不妨考虑更适合处理较大输入的云解决方案。

对于 InputType.ARTICLE,输入内容还必须超过 400 个字符,并且当文章至少有 300 字时,模型效果最佳。

GenAI 总结 API 支持英语、日语和韩语,并在 SummarizerOptions.Language 中定义。

特定功能配置(由 SummarizerOptions 指定)的可用性可能因特定设备的配置和已下载到设备的模型而异。

对于开发者而言,确保设备支持具有所请求 SummarizerOptions 的预期 API 功能的最可靠方法是调用 checkFeatureStatus() 方法。此方法可在运行时提供设备上功能可用性的确定状态。

常见设置问题

机器学习套件生成式 AI API 依赖于 Android AICore 应用来访问 Gemini Nano。当设备刚刚设置(包括重置)或 AICore 应用刚刚重置(例如,清除数据、卸载然后重新安装)时,AICore 应用可能没有足够的时间来完成初始化(包括从服务器下载最新配置)。因此,ML Kit GenAI API 可能无法按预期运行。以下是您可能会看到的常见设置错误消息以及处理方法:

错误消息示例 如何处理
AICore 失败,出现错误类型 4-CONNECTION_ERROR 和错误代码 601-BINDING_FAILURE:AICore 服务绑定失败。 如果您在设备设置完毕后立即使用 ML Kit GenAI API 安装应用,或者在应用安装完毕后卸载 AICore,则可能会出现这种情况。更新 AICore 应用,然后重新安装您的应用,应该就能解决此问题。
AICore 失败,错误类型为 3-PREPARATION_ERROR,错误代码为 606-FEATURE_NOT_FOUND:功能 ... 不可用。 如果 AICore 尚未完成下载最新配置,可能会发生这种情况。当设备连接到互联网时,更新通常需要几分钟到几小时。重新启动设备可以加快更新速度。

请注意,如果设备的引导加载程序处于解锁状态,您也会看到此错误消息,因为此 API 不支持引导加载程序处于解锁状态的设备。
AICore 失败,错误类型为 1-DOWNLOAD_ERROR,错误代码为 0-UNKNOWN:功能 ... 失败,失败状态为 0,错误 esz 为:UNAVAILABLE:无法解析主机 ... 保持网络连接,等待几分钟,然后重试。