Начало работы с Prompt API

В этой статье рассказывается, как:

  • Как настроить проект для использования Prompt API
  • Как отправить текстовый запрос и получить ответ
  • Предоставлять изображения с сопутствующим текстом и получать ответ.

Дополнительную информацию о Prompt API можно найти в справочной документации для Kotlin (com.google.mlkit.genai.prompt) и Java (com.google.mlkit.genai.prompt.java, com.google.mlkit.genai.prompt).

Настроить проект

Добавьте ML Kit Prompt API в качестве зависимости в конфигурацию build.gradle:

implementation("com.google.mlkit:genai-prompt:1.0.0-beta4")

Если вам нужно, чтобы ответы были в определенном формате, используйте Structured Output API. Для этого настройте KSP и добавьте дополнительные зависимости. Подробнее о том, как генерировать структурированные выходные данные…

Реализация генеративной модели

Чтобы добавить код в проект, выполните следующие действия:

  • Создайте объект generativeModel:

    Kotlin

    // Get a GenerativeModel instance
    val generativeModel = Generation.getClient()
    

    Java

    // Get a GenerativeModel instance
    GenerativeModelFutures generativeModelFutures = GenerativeModelFutures
        .from(Generation.INSTANCE.getClient());
    
  • Проверьте, какой статус у Gemini Nano: AVAILABLE,, DOWNLOADABLE или UNAVAILABLE. Затем скачайте функцию, если это возможно:

    Kotlin

    val status = generativeModel.checkStatus()
    when (status) {
        FeatureStatus.UNAVAILABLE -> {
            // Gemini Nano not supported on this device or device hasn't fetched the latest configuration to support it
        }
    
        FeatureStatus.DOWNLOADABLE -> {
            // Gemini Nano can be downloaded on this device, but is not currently downloaded
            generativeModel.download().collect { status ->
                when (status) {
                    is DownloadStatus.DownloadStarted ->
                        Log.d(TAG, "starting download for Gemini Nano")
    
                    is DownloadStatus.DownloadProgress ->
                        Log.d(TAG, "Nano ${status.totalBytesDownloaded} bytes downloaded")
    
                    DownloadStatus.DownloadCompleted -> {
                        Log.d(TAG, "Gemini Nano download complete")
                        modelDownloaded = true
                    }
    
                    is DownloadStatus.DownloadFailed -> {
                        Log.e(TAG, "Nano download failed ${status.e.message}")
                    }
                }
            }
        }
    
        FeatureStatus.DOWNLOADING -> {
            // Gemini Nano currently being downloaded
        }
    
        FeatureStatus.AVAILABLE -> {
            // Gemini Nano currently downloaded and available to use on this device
        }
    }
    

    Java

    ListenableFuture<Integer> status = generativeModelFutures.checkStatus();
    Futures.addCallback(generativeModelFutures.checkStatus(), new FutureCallback<>() {
        @Override
        public void onSuccess(Integer featureStatus) {
            switch (featureStatus) {
                case FeatureStatus.AVAILABLE - > {
                    // Gemini Nano currently downloaded and available to use on this device
                }
                case FeatureStatus.UNAVAILABLE - > {
                    // Gemini Nano not supported on this device or device hasn't fetched the latest configuration to support it
                }
                case FeatureStatus.DOWNLOADING - > {
                    // Gemini Nano currently being downloaded
                }
                case FeatureStatus.DOWNLOADABLE - > {
                    generativeModelFutures.download(new DownloadCallback() {
                        @Override
                        public void onDownloadStarted(long l) {
                            Log.d(TAG, "starting download for Gemini Nano");
                        }
                        @Override
                        public void onDownloadProgress(long l) {
                            Log.d(TAG, "Nano " + l + " bytes downloaded");
                        }
                        @Override
                        public void onDownloadCompleted() {
                            Log.d(TAG, "Gemini Nano download complete");
                        }
                        @Override
                        public void onDownloadFailed(@NonNull GenAiException e) {
                            Log.e(TAG, "Nano download failed: " + e.getMessage());
                        }
                    });
                }
            }
        }
        @Override
        public void onFailure(@NonNull Throwable t) {
            // Failed to check status
        }
    }, ContextCompat.getMainExecutor(context));
    
    

Введите текстовый запрос

Kotlin

val response = generativeModel.generateContent("Write a 3 sentence story about a magical dog.")

Java

GenerateContentResponse response = generativeModelFutures.generateContent(
  new GenerateContentRequest.Builder(
    new TextPart("Write a 3 sentence story about a magical dog."))
  .build())
  .get();

Вы также можете добавить необязательные параметры:

Kotlin

val response = generativeModel.generateContent(
    generateContentRequest(
        TextPart("Write a 3 sentence story about a magical dog."),
    ) {
        // Optional parameters
        temperature = 0.2f
        topK = 10
        candidateCount = 3
    },
)

Java

GenerateContentRequest.Builder requestBuilder =
        new GenerateContentRequest.Builder(
                new TextPart("Write a 3 sentence story about a magical dog."));
requestBuilder.setTemperature(.2f);
requestBuilder.setTopK(10);
requestBuilder.setCandidateCount(3);

GenerateContentResponse response =
        generativeModelFutures.generateContent(requestBuilder.build()).get();

Дополнительную информацию о необязательных параметрах можно найти в разделе Необязательные настройки.

Предоставьте мультимодальные входные данные (изображение и текст)

Объедините несколько изображений и текстовый запрос в функции generateContentRequest(). Текстовый запрос должен быть вопросом или командой, связанной с изображением. В одном запросе можно объединить до 10 изображений.

Kotlin

val response = generativeModel.generateContent(
    generateContentRequest(ImagePart(bitmap1), ImagePart(bitmap2), TextPart(textPrompt)) {
        // optional parameters
        ...
    },
)

Java

GenerateContentResponse response = generativeModelFutures.generateContent(
    new GenerateContentRequest.Builder(
        new Content.Builder()
            .addPart(new ImagePart(bitmap1))
            .addPart(new ImagePart(bitmap2))
            .addPart(new TextPart("textPrompt"))
            .build())
    // optional parameters
    .build())
.get();

Обработка результатов вывода

  • Выполните вывод и получите результат. Вы можете дождаться полного результата или передавать ответ по мере его генерации как для текстовых, так и для мультимодальных запросов.

    • В этом случае используется непотоковый вывод, при котором весь результат извлекается из модели ИИ перед возвратом результата:

    Kotlin

    // Call the AI model to generate content and store the complete
    // in a new variable named 'response' once it's finished
    val response = generativeModel.generateContent("Write a 3 sentence story about a magical dog")
    

    Java

    GenerateContentResponse response = generativeModelFutures.generateContent(
            new GenerateContentRequest.Builder(
                    new TextPart("Write a 3 sentence story about a magical dog."))
                    .build())
            .get();
    
    • В следующих фрагментах кода показано, как использовать потоковый инференс, который получает результат по частям по мере его генерации:

    Kotlin

    // Streaming inference
    var fullResponse = ""
    generativeModel.generateContentStream("Write a 3 sentence story about a magical dog").collect { chunk ->
        val newChunkReceived = chunk.candidates[0].text
        print(newChunkReceived)
        fullResponse += newChunkReceived
    }
    

    Java

    // Streaming inference
    StringBuilder fullResponse = new StringBuilder();
    generativeModelFutures.generateContent(new GenerateContentRequest.Builder(
        (new TextPart("Write a 3 sentence story about a magical dog"))).build(),
            chunk -> {
                Log.d(TAG, chunk);
                fullResponse.append(chunk);
            });
    

Подробнее о потоковом и непотоковом выводе…

Оптимизация задержки

Чтобы оптимизировать первый вызов вывода, ваше приложение может вызвать warmup(). Это загрузит Gemini Nano в память и инициализирует компоненты среды выполнения.

Дополнительные настройки

Для каждого объекта GenerateContentRequest можно задать следующие необязательные параметры:

  • temperature – управляет степенью случайности при выборе токенов.
  • seed – позволяет генерировать стабильные и детерминированные результаты.
  • topK – управляет случайностью и разнообразием результатов.
  • candidateCount – запрашивает количество возвращенных уникальных ответов. Обратите внимание, что точное количество ответов может не совпадать с candidateCount, поскольку повторяющиеся ответы автоматически удаляются.
  • maxOutputTokens – определяет максимальное количество токенов, которые могут быть сгенерированы в ответе.

Дополнительные сведения о необязательных настройках можно найти в GenerateContentRequest.

Поддерживаемые функции и ограничения

  • Входные данные должны содержать не более 4000 токенов (примерно 3000 слов на английском языке). Дополнительную информацию можно найти в справочнике по countTokens.
  • Избегайте сценариев, требующих длинных ответов (более 4000 токенов).
  • AICore применяет квоту на инференс для каждого приложения. Подробнее о квоте на приложение…

Распространенные проблемы с настройкой

API GenAI в ML Kit используют приложение Android AICore для доступа к Gemini Nano. Если устройство только что настроено (в том числе после сброса) или приложение AICore только что сброшено (например, очищены данные, приложение удалено и установлено заново), у AICore может не хватить времени, чтобы завершить инициализацию (в том числе скачать последние конфигурации с сервера). В результате API GenAI в ML Kit могут работать неправильно. Ниже приведены распространенные сообщения об ошибках настройки и способы их устранения.

Пример сообщения об ошибке Как устранить проблему
Ошибка 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 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 ... Сохраните сетевое подключение, подождите несколько минут и повторите попытку.