Comienza a usar la API de Gemini en apps para Android (SDK cliente)

En este instructivo, se muestra cómo acceder a la API de Gemini directamente desde tu app para Android con el SDK cliente de la IA de Google para Android. Puedes usar este SDK cliente si no quieres trabajar directamente con las APIs de REST o el código del servidor (como Python) para acceder a modelos de Gemini en tu app para Android.

En este instructivo, aprenderás a hacer lo siguiente:

Además, este instructivo contiene secciones sobre casos de uso avanzados (como contar tokens) y opciones para controlar la generación de contenido.

Accede a Gemini en el dispositivo

El SDK cliente para Android que se describe en este instructivo te permite acceder a los modelos de Gemini Pro que se ejecutan en los servidores de Google. Para los casos de uso que involucran el procesamiento de datos sensibles, la disponibilidad sin conexión o el ahorro de costos de los flujos de usuarios más frecuentes, te recomendamos acceder a Gemini Nano, que se ejecuta en el dispositivo. Para obtener más detalles, consulta el instructivo de Android (en el dispositivo).

Requisitos previos

En este instructivo, se asume que sabes usar Android Studio para desarrollar apps para Android.

Para completar este instructivo, asegúrate de que el entorno de desarrollo y la app para Android cumplan con los siguientes requisitos:

  • Android Studio (versión más reciente)
  • Tu app para Android debe orientarse al nivel de API 21 o uno posterior.

Configura tu proyecto

Antes de llamar a la API de Gemini, debes configurar tu proyecto de Android, lo que incluye configurar tu clave de API, agregar las dependencias del SDK a tu proyecto de Android y, luego, inicializar el modelo.

Cómo configurar tu clave de API

Para usar la API de Gemini, necesitarás una clave de API. Si aún no tienes una, crea una clave en Google AI Studio.

Obtén una clave de API.

Protege tu clave de API

Te recomendamos que no registres una clave de API en tu sistema de control de versión. En cambio, debes almacenarla en un archivo local.properties (que se encuentra en el directorio raíz de tu proyecto, pero se excluye del control de versión) y, luego, usar el complemento Secrets Gradle para Android para leer tu clave de API como una variable de configuración de compilación.

Kotlin

// Access your API key as a Build Configuration variable
val apiKey = BuildConfig.apiKey

Java

// Access your API key as a Build Configuration variable
String apiKey = BuildConfig.apiKey;

En todos los fragmentos de este instructivo, se usa esta práctica recomendada. Además, si deseas ver la implementación del complemento Secrets para Gradle, puedes revisar la app de ejemplo de este SDK o usar la versión preliminar más reciente de Android Studio Iguana, que tiene una plantilla de Gemini API Starter (que incluye el archivo local.properties para comenzar).

Agrega la dependencia del SDK a tu proyecto

  1. En el archivo de configuración de Gradle del módulo (nivel de app) (como <project>/<app-module>/build.gradle.kts), agrega la dependencia del SDK de Google AI para Android:

    Kotlin

    dependencies {
      // ... other androidx dependencies
    
      // add the dependency for the Google AI client SDK for Android
      implementation("com.google.ai.client.generativeai:generativeai:0.3.0")
    }
    

    Java

    En el caso de Java, debes agregar dos bibliotecas adicionales.

    dependencies {
        // ... other androidx dependencies
    
        // add the dependency for the Google AI client SDK for Android
        implementation("com.google.ai.client.generativeai:generativeai:0.3.0")
    
        // Required for one-shot operations (to use `ListenableFuture` from Guava Android)
        implementation("com.google.guava:guava:31.0.1-android")
    
        // Required for streaming operations (to use `Publisher` from Reactive Streams)
        implementation("org.reactivestreams:reactive-streams:1.0.4")
    }
    
  2. Sincroniza tu proyecto de Android con archivos Gradle.

Inicializa el modelo generativo

Antes de realizar llamadas a la API, debes inicializar el objeto GenerativeModel:

Kotlin

val generativeModel = GenerativeModel(
    // Use a model that's applicable for your use case (see "Implement basic use cases" below)
    modelName = "MODEL_NAME",
    // Access your API key as a Build Configuration variable (see "Set up your API key" above)
    apiKey = BuildConfig.apiKey
)

Java

En Java, también debes inicializar el objeto GenerativeModelFutures.

// Use a model that's applicable for your use case (see "Implement basic use cases" below)
GenerativeModel gm = new GenerativeModel(/* modelName */ "MODEL_NAME",
// Access your API key as a Build Configuration variable (see "Set up your API key" above)
    /* apiKey */ BuildConfig.apiKey);

// Use the GenerativeModelFutures Java compatibility layer which offers
// support for ListenableFuture and Publisher APIs
GenerativeModelFutures model = GenerativeModelFutures.from(gm);

Cuando especifiques un modelo, ten en cuenta lo siguiente:

  • Usa un modelo que sea específico para tu caso de uso (por ejemplo, gemini-pro-vision es para la entrada multimodal). En esta guía, las instrucciones para cada implementación incluyen el modelo recomendado para cada caso de uso.

Implementa casos de uso comunes

Ahora que tu proyecto está configurado, puedes explorar el uso de la API de Gemini para implementar diferentes casos de uso:

Cómo generar texto a partir de entradas de solo texto

Cuando la entrada de instrucción incluya solo texto, usa el modelo gemini-pro con generateContent para generar una salida de texto:

Kotlin

Ten en cuenta que generateContent() es una función de suspensión y se debe llamar desde un alcance de corrutinas. Si no conoces las corrutinas, consulta Corrutinas de Kotlin en Android.

val generativeModel = GenerativeModel(
    // For text-only input, use the gemini-pro model
    modelName = "gemini-pro",
    // Access your API key as a Build Configuration variable (see "Set up your API key" above)
    apiKey = BuildConfig.apiKey
)

val prompt = "Write a story about a magic backpack."
val response = generativeModel.generateContent(prompt)
print(response.text)

Java

Ten en cuenta que generateContent() muestra un ListenableFuture. Si no conoces esta API, consulta la documentación de Android sobre Cómo usar un ListenableFuture.

// For text-only input, use the gemini-pro model
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-pro",
// Access your API key as a Build Configuration variable (see "Set up your API key" above)
    /* apiKey */ BuildConfig.apiKey);
GenerativeModelFutures model = GenerativeModelFutures.from(gm);

Content content = new Content.Builder()
    .addText("Write a story about a magic backpack.")
    .build();

Executor executor = // ...

ListenableFuture<GenerateContentResponse> response = model.generateContent(content);
Futures.addCallback(response, new FutureCallback<GenerateContentResponse>() {
    @Override
    public void onSuccess(GenerateContentResponse result) {
        String resultText = result.getText();
        System.out.println(resultText);
    }

    @Override
    public void onFailure(Throwable t) {
        t.printStackTrace();
    }
}, executor);

Generar texto a partir de entradas de texto e imagen (multimodal)

Gemini proporciona un modelo multimodal (gemini-pro-vision), por lo que puedes ingresar imágenes y texto. Asegúrate de revisar los requisitos de las imágenes para los mensajes.

Cuando la entrada de instrucción incluya imágenes y texto, usa el modelo gemini-pro-vision con generateContent para generar una salida de texto:

Kotlin

Ten en cuenta que generateContent() es una función de suspensión y se debe llamar desde un alcance de corrutinas. Si no conoces las corrutinas, consulta Corrutinas de Kotlin en Android.

val generativeModel = GenerativeModel(
    // For text-and-images input (multimodal), use the gemini-pro-vision model
    modelName = "gemini-pro-vision",
    // Access your API key as a Build Configuration variable (see "Set up your API key" above)
    apiKey = BuildConfig.apiKey
)

val image1: Bitmap = // ...
val image2: Bitmap = // ...

val inputContent = content {
    image(image1)
    image(image2)
    text("What's different between these pictures?")
}

val response = generativeModel.generateContent(inputContent)
print(response.text)

Java

Ten en cuenta que generateContent() muestra un ListenableFuture. Si no conoces esta API, consulta la documentación de Android sobre Cómo usar un ListenableFuture.

// For text-and-images input (multimodal), use the gemini-pro-vision model
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-pro-vision",
// Access your API key as a Build Configuration variable (see "Set up your API key" above)
    /* apiKey */ BuildConfig.apiKey);
GenerativeModelFutures model = GenerativeModelFutures.from(gm);

Bitmap image1 = // ...
Bitmap image2 = // ...

Content content = new Content.Builder()
    .addText("What's different between these pictures?")
    .addImage(image1)
    .addImage(image2)
    .build();

Executor executor = // ...

ListenableFuture<GenerateContentResponse> response = model.generateContent(content);
Futures.addCallback(response, new FutureCallback<GenerateContentResponse>() {
    @Override
    public void onSuccess(GenerateContentResponse result) {
        String resultText = result.getText();
        System.out.println(resultText);
    }

    @Override
    public void onFailure(Throwable t) {
        t.printStackTrace();
    }
}, executor);

Crea conversaciones de varios turnos (chat)

Con Gemini, puedes desarrollar conversaciones de formato libre en varios turnos. El SDK simplifica el proceso mediante la administración del estado de la conversación, por lo que, a diferencia de generateContent, no tienes que almacenar el historial de la conversación.

Para crear una conversación de varios turnos (como el chat), usa el modelo gemini-pro e inicializa el chat llamando a startChat(). Luego, usa sendMessage() para enviar un mensaje al usuario nuevo, que también agregará el mensaje y la respuesta al historial de chat.

Hay dos opciones posibles para role asociado con el contenido en una conversación:

  • user: Es el rol que proporciona las indicaciones. Este es el valor predeterminado para las llamadas a sendMessage.

  • model: Es la función que proporciona las respuestas. Esta función se puede usar cuando se llama a startChat() con history existente.

Kotlin

Ten en cuenta que generateContent() es una función de suspensión y se debe llamar desde un alcance de corrutinas. Si no conoces las corrutinas, consulta Corrutinas de Kotlin en Android.

val generativeModel = GenerativeModel(
    // For text-only input, use the gemini-pro model
    modelName = "gemini-pro",
    // Access your API key as a Build Configuration variable (see "Set up your API key" above)
    apiKey = BuildConfig.apiKey
)

val chat = generativeModel.startChat(
    history = listOf(
        content(role = "user") { text("Hello, I have 2 dogs in my house.") },
        content(role = "model") { text("Great to meet you. What would you like to know?") }
    )
)

chat.sendMessage("How many paws are in my house?")

Java

Ten en cuenta que generateContent() muestra un ListenableFuture. Si no conoces esta API, consulta la documentación de Android sobre Cómo usar un ListenableFuture.

// For text-only input, use the gemini-pro model
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-pro",
// Access your API key as a Build Configuration variable (see "Set up your API key" above)
    /* apiKey */ BuildConfig.apiKey);
GenerativeModelFutures model = GenerativeModelFutures.from(gm);

// (optional) Create previous chat history for context
Content.Builder userContentBuilder = new Content.Builder();
userContentBuilder.setRole("user");
userContentBuilder.addText("Hello, I have 2 dogs in my house.");
Content userContent = userContentBuilder.build();

Content.Builder modelContentBuilder = new Content.Builder();
modelContentBuilder.setRole("model");
modelContentBuilder.addText("Great to meet you. What would you like to know?");
Content modelContent = userContentBuilder.build();

List<Content> history = Arrays.asList(userContent, modelContent);

// Initialize the chat
ChatFutures chat = model.startChat(history);

// Create a new user message
Content userMessage = new Content.Builder()
    .setRole("user")
    .addText("How many paws are in my house?")
    .build();

Executor executor = // ...

// Send the message
ListenableFuture<GenerateContentResponse> response = chat.sendMessage(userMessage);

Futures.addCallback(response, new FutureCallback<GenerateContentResponse>() {
    @Override
    public void onSuccess(GenerateContentResponse result) {
        String resultText = result.getText();
        System.out.println(resultText);
    }

    @Override
    public void onFailure(Throwable t) {
        t.printStackTrace();
    }
}, executor);

Usa la transmisión para interacciones más rápidas

Según la configuración predeterminada, el modelo muestra una respuesta después de completar todo el proceso de generación. Puedes lograr interacciones más rápidas si no esperas a que se complete el resultado y, en su lugar, usa la transmisión para controlar los resultados parciales.

En el siguiente ejemplo, se muestra cómo implementar la transmisión con generateContentStream para generar texto a partir de una solicitud de entrada de imagen y texto.

Kotlin

Ten en cuenta que generateContentStream() es una función de suspensión y se debe llamar desde un alcance de corrutinas. Si no conoces las corrutinas, consulta Corrutinas de Kotlin en Android.

val generativeModel = GenerativeModel(
    // For text-and-image input (multimodal), use the gemini-pro-vision model
    modelName = "gemini-pro-vision",
    // Access your API key as a Build Configuration variable (see "Set up your API key" above)
    apiKey = BuildConfig.apiKey
)

val image1: Bitmap = // ...
val image2: Bitmap = // ...

val inputContent = content {
    image(image1)
    image(image2)
    text("What's the difference between these pictures?")
}

var fullResponse = ""
generativeModel.generateContentStream(inputContent).collect { chunk ->
    print(chunk.text)
    fullResponse += chunk.text
}

Java

Los métodos de transmisión de Java en este SDK muestran un tipo Publisher de la biblioteca Reactive Streams.

// For text-and-images input (multimodal), use the gemini-pro-vision model
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-pro-vision",
// Access your API key as a Build Configuration variable (see "Set up your API key" above)
    /* apiKey */ BuildConfig.apiKey);
GenerativeModelFutures model = GenerativeModelFutures.from(gm);

Bitmap image1 = // ...
Bitmap image2 = // ...

Content content = new Content.Builder()
    .addText("What's different between these pictures?")
    .addImage(image1)
    .addImage(image2)
    .build();

Publisher<GenerateContentResponse> streamingResponse =
    model.generateContentStream(content);

final String[] fullResponse = {""};

streamingResponse.subscribe(new Subscriber<GenerateContentResponse>() {
    @Override
    public void onNext(GenerateContentResponse generateContentResponse) {
        String chunk = generateContentResponse.getText();
        fullResponse[0] += chunk;
    }

    @Override
    public void onComplete() {
        System.out.println(fullResponse[0]);
    }

    @Override
    public void onError(Throwable t) {
        t.printStackTrace();
    }

    @Override
    public void onSubscribe(Subscription s) { }
});

Puedes usar un enfoque similar para los casos de uso de entrada de solo texto y chat:

Kotlin

Ten en cuenta que generateContentStream() es una función de suspensión y se debe llamar desde un alcance de corrutinas. Si no conoces las corrutinas, consulta Corrutinas de Kotlin en Android.

// Use streaming with text-only input
generativeModel.generateContentStream(inputContent).collect { chunk ->
    print(chunk.text)
}
// Use streaming with multi-turn conversations (like chat)
val chat = generativeModel.startChat()
chat.sendMessageStream(inputContent).collect { chunk ->
    print(chunk.text)
}

Java

Los métodos de transmisión de Java en este SDK muestran un tipo Publisher de la biblioteca Reactive Streams.

// Use streaming with text-only input
Publisher<GenerateContentResponse> streamingResponse =
    model.generateContentStream(inputContent);

final String[] fullResponse = {""};

streamingResponse.subscribe(new Subscriber<GenerateContentResponse>() {
    @Override
    public void onNext(GenerateContentResponse generateContentResponse) {
        String chunk = generateContentResponse.getText();
        fullResponse[0] += chunk;
    }

    @Override
    public void onComplete() {
        System.out.println(fullResponse[0]);
    }

    // ... other methods omitted for brevity
});
// Use streaming with multi-turn conversations (like chat)
ChatFutures chat = model.startChat(history);

Publisher<GenerateContentResponse> streamingResponse =
    chat.sendMessageStream(inputContent);

final String[] fullResponse = {""};

streamingResponse.subscribe(new Subscriber<GenerateContentResponse>() {
    @Override
    public void onNext(GenerateContentResponse generateContentResponse) {
        String chunk = generateContentResponse.getText();
        fullResponse[0] += chunk;
    }

    @Override
    public void onComplete() {
        System.out.println(fullResponse[0]);
    }

    // ... other methods omitted for brevity
});

Implementa casos de uso avanzados

Los casos de uso comunes descritos en la sección anterior de este instructivo te ayudarán a familiarizarte con el uso de la API de Gemini. En esta sección, se describen algunos casos de uso que podrían considerarse más avanzados.

Contar tokens

Cuando se usan instrucciones largas, puede ser útil contar los tokens antes de enviar contenido al modelo. En los siguientes ejemplos, se muestra cómo usar countTokens() para varios casos de uso:

Kotlin

Ten en cuenta que countTokens() es una función de suspensión y se debe llamar desde un alcance de corrutinas. Si no conoces las corrutinas, consulta Corrutinas de Kotlin en Android.

// For text-only input
val (totalTokens) = generativeModel.countTokens("Write a story about a magic backpack.")

// For text-and-image input (multi-modal)
val multiModalContent = content {
    image(image1)
    image(image2)
    text("What's the difference between these pictures?")
}

val (totalTokens) = generativeModel.countTokens(multiModalContent)

// For multi-turn conversations (like chat)
val history = chat.history
val messageContent = content { text("This is the message I intend to send")}
val (totalTokens) = generativeModel.countTokens(*history.toTypedArray(), messageContent)

Java

Ten en cuenta que countTokens() muestra un ListenableFuture. Si no conoces esta API, consulta la documentación de Android sobre Cómo usar un ListenableFuture.

Content text = new Content.Builder()
    .addText("Write a story about a magic backpack.")
    .build();

Executor executor = // ...

// For text-only input
ListenableFuture<CountTokensResponse> countTokensResponse = model.countTokens(text);

Futures.addCallback(countTokensResponse, new FutureCallback<CountTokensResponse>() {
    @Override
    public void onSuccess(CountTokensResponse result) {
        int totalTokens = result.getTotalTokens();
        System.out.println("TotalTokens = " + totalTokens);
    }

    @Override
    public void onFailure(Throwable t) {
        t.printStackTrace();
    }
}, executor);

// For text-and-image input
Bitmap image1 = // ...
Bitmap image2 = // ...

Content multiModalContent = new Content.Builder()
    .addImage(image1)
    .addImage(image2)
    .addText("What's different between these pictures?")
    .build();

ListenableFuture<CountTokensResponse> countTokensResponse = model.countTokens(multiModalContent);

// For multi-turn conversations (like chat)
List<Content> history = chat.getChat().getHistory();

Content messageContent = new Content.Builder()
    .addText("This is the message I intend to send")
    .build();

Collections.addAll(history, messageContent);

ListenableFuture<CountTokensResponse> countTokensResponse = model.countTokens(history.toArray(new Content[0]));

Opciones para controlar la generación de contenido

Puedes controlar la generación de contenido mediante la configuración de los parámetros del modelo y la configuración de seguridad.

Configura los parámetros del modelo

Cada instrucción que envías al modelo incluye valores de parámetros que controlan cómo el modelo genera una respuesta. El modelo puede generar resultados diferentes para los valores de parámetros diferentes. Obtén más información sobre los parámetros del modelo.

Kotlin

val config = generationConfig {
    temperature = 0.9f
    topK = 16
    topP = 0.1f
    maxOutputTokens = 200
    stopSequences = listOf("red")
}

val generativeModel = GenerativeModel(
    modelName = "MODEL_NAME",
    apiKey = BuildConfig.apiKey,
    generationConfig = config
)

Java

GenerationConfig.Builder configBuilder = new GenerationConfig.Builder();
configBuilder.temperature = 0.9f;
configBuilder.topK = 16;
configBuilder.topP = 0.1f;
configBuilder.maxOutputTokens = 200;
configBuilder.stopSequences = Arrays.asList("red");

GenerationConfig generationConfig = configBuilder.build();

GenerativeModel gm = new GenerativeModel(
    "MODEL_NAME",
    BuildConfig.apiKey,
    generationConfig
);

GenerativeModelFutures model = GenerativeModelFutures.from(gm);

Usar la configuración de seguridad

Puedes usar la configuración de seguridad para ajustar la probabilidad de obtener respuestas que puedan considerarse perjudiciales. De forma predeterminada, la configuración de seguridad bloquea el contenido con probabilidad media o alta de ser contenido inseguro en todas las dimensiones. Obtén más información sobre la configuración de seguridad.

Para establecer una configuración de seguridad, sigue estos pasos:

Kotlin

val generativeModel = GenerativeModel(
    modelName = "MODEL_NAME",
    apiKey = BuildConfig.apiKey,
    safetySettings = listOf(
        SafetySetting(HarmCategory.HARASSMENT, BlockThreshold.ONLY_HIGH)
    )
)

Java

SafetySetting harassmentSafety = new SafetySetting(HarmCategory.HARASSMENT,
    BlockThreshold.ONLY_HIGH);

GenerativeModel gm = new GenerativeModel(
    "MODEL_NAME",
    BuildConfig.apiKey,
    null, // generation config is optional
    Collections.singletonList(harassmentSafety)
);

GenerativeModelFutures model = GenerativeModelFutures.from(gm);

También puedes establecer más de una configuración de seguridad:

Kotlin

val harassmentSafety = SafetySetting(HarmCategory.HARASSMENT, BlockThreshold.ONLY_HIGH)

val hateSpeechSafety = SafetySetting(HarmCategory.HATE_SPEECH, BlockThreshold.MEDIUM_AND_ABOVE)

val generativeModel = GenerativeModel(
    modelName = "MODEL_NAME",
    apiKey = BuildConfig.apiKey,
    safetySettings = listOf(harassmentSafety, hateSpeechSafety)
)

Java

SafetySetting harassmentSafety = new SafetySetting(HarmCategory.HARASSMENT,
    BlockThreshold.ONLY_HIGH);

SafetySetting hateSpeechSafety = new SafetySetting(HarmCategory.HATE_SPEECH,
    BlockThreshold.MEDIUM_AND_ABOVE);

GenerativeModel gm = new GenerativeModel(
    "MODEL_NAME",
    BuildConfig.apiKey,
    null, // generation config is optional
    Arrays.asList(harassmentSafety, hateSpeechSafety)
);

GenerativeModelFutures model = GenerativeModelFutures.from(gm);

Próximos pasos

  • El diseño de instrucciones es el proceso de crear instrucciones que producen la respuesta deseada de los modelos de lenguaje. Escribir instrucciones bien estructuradas es una parte esencial de garantizar respuestas precisas y de alta calidad desde un modelo de lenguaje. Obtén más información sobre las prácticas recomendadas para la escritura de instrucciones.

  • Gemini ofrece muchas variaciones del modelo para satisfacer las necesidades de distintos casos de uso, como los tipos de entrada y la complejidad, las implementaciones para chat y otras tareas de lenguaje de diálogo, y las restricciones de tamaño. Obtén más información sobre los modelos de Gemini disponibles.

  • Gemini ofrece opciones para solicitar aumentos del límite de frecuencia. El límite de frecuencia de los modelos Gemini Pro es de 60 solicitudes por minuto (RPM).

  • El SDK cliente para Android que se describe en este instructivo te permite acceder a los modelos de Gemini Pro que se ejecutan en los servidores de Google. Para los casos de uso que involucran el procesamiento de datos sensibles, la disponibilidad sin conexión o el ahorro de costos de los flujos de usuarios más frecuentes, te recomendamos acceder a Gemini Nano, que se ejecuta en el dispositivo. Para obtener más detalles, consulta el instructivo de Android (en el dispositivo).