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 esta SDK cliente si no quieres trabajar directamente con las APIs de REST o con el código del servidor (como Python) para acceder a los modelos de Gemini en tu app para Android.
En este instructivo, aprenderás a hacer lo siguiente:
- Configura tu proyecto, incluida tu clave de API
- Cómo generar texto a partir de entradas de solo texto
- Genera texto a partir de entradas de texto e imágenes (multimodal)
- Crea conversaciones de varios turnos (chat)
- Usa la transmisión para interactuar más rápido
Además, este instructivo contiene secciones sobre casos de uso avanzados (como tokens de recuento), así como las opciones para controlar la generación de contenido.
Considera acceder a Gemini integrado en el dispositivo
El SDK cliente para Android descrito en este instructivo te permite acceder a la Modelos de Gemini Pro que se ejecutan en los servidores de Google. Para casos de uso que involucran 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 información, consulta la Instructivo para Android (en el dispositivo)
Requisitos previos
En este instructivo, se asume que estás familiarizado con el uso de Android Studio para desarrollar apps para Android.
Para completar este instructivo, asegúrate de que tu entorno de desarrollo y La app para Android cumple con los siguientes requisitos:
- Android Studio (versión más reciente)
- Tu app para Android debe orientarse al nivel de API 21 o versiones posteriores.
Configura tu proyecto
Antes de llamar a la API de Gemini, debes configurar tu proyecto de Android, que incluye configurar tu clave de API y agregar las dependencias del SDK a tu el proyecto e 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 uno, crea una clave en Google AI Studio.
Protege tu clave de API
Te recomendamos que no incluyas una clave de API en tu versión
un sistema de control de calidad. En su lugar, debes almacenarla en un archivo local.properties
(que se encuentra en el directorio raíz del proyecto, pero se excluye de la versión
control) y, luego, utilizar 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;
Todos los fragmentos de este instructivo utilizan esta práctica recomendada. Además, si
si quieres ver la implementación del complemento Secrets Gradle, puedes revisar el
app de ejemplo
para este SDK o usa la versión preliminar más reciente de Android Studio Iguana, que cuenta con un
Plantilla de Gemini API Starter
(que incluye el archivo local.properties
para que puedas comenzar).
Agrega la dependencia del SDK a tu proyecto
En el archivo de configuración de Gradle de tu módulo (nivel de app) (como
<project>/<app-module>/build.gradle.kts
), agrega la dependencia del SDK de IA de Google 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.9.0") }
Java
Para 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.9.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") }
Sincroniza tu proyecto de Android con archivos Gradle.
Inicializa el modelo generativo
Antes de realizar llamadas a las APIs, debes inicializar el modelo generativo:
Kotlin
val generativeModel = GenerativeModel(
// The Gemini 1.5 models are versatile and work with most use cases
modelName = "gemini-1.5-flash",
// Access your API key as a Build Configuration variable (see "Set up your API key" above)
apiKey = BuildConfig.apiKey
)
Java
En el caso de Java, también debes inicializar el objeto GenerativeModelFutures
.
// Use a model that's applicable for your use case
// The Gemini 1.5 models are versatile and work with most use cases
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-1.5-flash",
// 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-1.5-flash
es para entradas multimodales). En esta guía, las instrucciones para cada de implementación, y luego enumerar el modelo recomendado para cada caso de uso.
Implementa casos de uso comunes
Ahora que tu proyecto está configurado, puedes explorar con la API de Gemini para implementar diferentes casos de uso:
- Cómo generar texto a partir de entradas de solo texto
- Genera texto a partir de entradas de texto e imágenes (multimodal)
- Crea conversaciones de varios turnos (chat)
- Usa la transmisión para interactuar más rápido
Genera texto a partir de entradas de solo texto
Cuando la entrada de la instrucción solo incluya texto, usa un modelo de Gemini 1.5 o
Modelo de Gemini 1.0 Pro con generateContent
para generar salida de texto:
Kotlin
Ten en cuenta que generateContent()
es una función de suspensión y se debe
llamado desde un alcance de corrutinas. Si no conoces las corrutinas, lee lo siguiente:
Corrutinas de Kotlin en Android
val generativeModel = GenerativeModel(
// The Gemini 1.5 models are versatile and work with both text-only and multimodal prompts
modelName = "gemini-1.5-flash",
// 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
Usa un ListenableFuture
.
// The Gemini 1.5 models are versatile and work with both text-only and multimodal prompts
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-1.5-flash",
// 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 imágenes (multimodal)
Gemini proporciona varios modelos que pueden controlar entradas multimodales (modelos de Gemini 1.5) para que puedas ingresar texto e imágenes. Asegúrate de revisa los requisitos de imágenes para las instrucciones.
Cuando la entrada de la instrucción incluya imágenes y texto, usa un modelo de Gemini 1.5 con
generateContent
para generar salida de texto:
Kotlin
Ten en cuenta que generateContent()
es una función de suspensión y se debe
llamado desde un alcance de corrutinas. Si no conoces las corrutinas, lee lo siguiente:
Corrutinas de Kotlin en Android
val generativeModel = GenerativeModel(
// The Gemini 1.5 models are versatile and work with both text-only and multimodal prompts
modelName = "gemini-1.5-flash",
// 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
Usa un ListenableFuture
.
// The Gemini 1.5 models are versatile and work with both text-only and multimodal prompts
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-1.5-flash",
// 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 entablar conversaciones de formato libre en múltiples turnos. El
SDK simplifica el proceso, ya que administra el estado de la conversación, así que,
con generateContent
, no tienes que almacenar el historial de conversaciones
de ti mismo.
Para crear una conversación de varios turnos (como el chat), usa un modelo de Gemini 1.5 o
modelo de Gemini 1.0 Pro e inicializar el chat llamando a startChat()
.
Luego, usa sendMessage()
para enviar un nuevo mensaje de usuario, que también agregará el
y la respuesta al historial de chat.
Hay dos opciones posibles para role
asociado con el contenido de una
conversación:
user
: Es la función que proporciona los mensajes. Este es el valor predeterminado parasendMessage
llamada.model
: Es la función que proporciona las respuestas. Este rol puede usarse cuando Llamando astartChat()
conhistory
existentes
Kotlin
Ten en cuenta que generateContent()
es una función de suspensión y se debe
llamado desde un alcance de corrutinas. Si no conoces las corrutinas, lee lo siguiente:
Corrutinas de Kotlin en Android
val generativeModel = GenerativeModel(
// The Gemini 1.5 models are versatile and work with multi-turn conversations (like chat)
modelName = "gemini-1.5-flash",
// 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
Usa un ListenableFuture
.
// The Gemini 1.5 models are versatile and work with multi-turn conversations (like chat)
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-1.5-flash",
// 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.Builder userMessageBuilder = new Content.Builder();
userMessageBuilder.setRole("user");
userMessageBuilder.addText("How many paws are in my house?");
Content userMessage = userMessageBuilder.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 tener interacciones más rápidas
De forma predeterminada, el modelo devuelve una respuesta después de completar toda la generación. el proceso de administración de recursos. Puede lograr interacciones más rápidas si no espera a que todo resultado y, en su lugar, usa la transmisión para manejar resultados parciales.
En el siguiente ejemplo, se muestra cómo implementar la transmisión con
generateContentStream
para generar texto a partir de un mensaje de entrada de texto e imagen.
Kotlin
Ten en cuenta que generateContentStream()
es una función de suspensión y se debe
llamado desde un alcance de corrutinas. Si no conoces las corrutinas, lee lo siguiente:
Corrutinas de Kotlin en Android
val generativeModel = GenerativeModel(
// The Gemini 1.5 models are versatile and work with both text-only and multimodal prompts
modelName = "gemini-1.5-flash",
// 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 las Transmisiones reactivas
biblioteca.
// The Gemini 1.5 models are versatile and work with both text-only and multimodal prompts
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-1.5-flash",
// 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);
StringBuilder outputContent = new StringBuilder();
streamingResponse.subscribe(new Subscriber<GenerateContentResponse>() {
@Override
public void onNext(GenerateContentResponse generateContentResponse) {
String chunk = generateContentResponse.getText();
outputContent.append(chunk);
}
@Override
public void onComplete() {
System.out.println(outputContent);
}
@Override
public void onError(Throwable t) {
t.printStackTrace();
}
@Override
public void onSubscribe(Subscription s) {
s.request(Long.MAX_VALUE);
}
});
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
llamado desde un alcance de corrutinas. Si no conoces las corrutinas, lee lo siguiente:
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 las Transmisiones reactivas
biblioteca.
// Use streaming with text-only input
Publisher<GenerateContentResponse> streamingResponse =
model.generateContentStream(inputContent);
StringBuilder outputContent = new StringBuilder();
streamingResponse.subscribe(new Subscriber<GenerateContentResponse>() {
@Override
public void onNext(GenerateContentResponse generateContentResponse) {
String chunk = generateContentResponse.getText();
outputContent.append(chunk);
}
@Override
public void onComplete() {
System.out.println(outputContent);
}
@Override
public void onSubscribe(Subscription s) {
s.request(Long.MAX_VALUE);
}
// ... other methods omitted for brevity
});
// Use streaming with multi-turn conversations (like chat)
ChatFutures chat = model.startChat(history);
Publisher<GenerateContentResponse> streamingResponse =
chat.sendMessageStream(inputContent);
StringBuilder outputContent = new StringBuilder();
streamingResponse.subscribe(new Subscriber<GenerateContentResponse>() {
@Override
public void onNext(GenerateContentResponse generateContentResponse) {
String chunk = generateContentResponse.getText();
outputContent.append(chunk);
}
@Override
public void onComplete() {
System.out.println(outputContent);
}
@Override
public void onSubscribe(Subscription s) {
s.request(Long.MAX_VALUE);
}
// ... other methods omitted for brevity
});
Implementa casos de uso avanzados
Los casos de uso comunes descritos en la sección anterior de este instructivo ayudan a a que te familiarices con la API de Gemini. En esta sección, se describen algunas que podrían considerarse más avanzados.
Llamada a función
Las llamadas a función facilitan la obtención de resultados de datos estructurados desde generativos. Luego, puedes usar estos resultados para llamar a otras APIs y mostrar los datos de respuesta relevantes para el modelo. En otras palabras, las llamadas a funciones ayudan conecta modelos generativos a sistemas externos para que el contenido generado incluya la información más actualizada y precisa. Obtén más información en el instructivo de llamada a funciones.
Contar tokens
Cuando se usan instrucciones largas, podría ser útil contar los tokens antes de enviar cualquiera
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
llamado desde un alcance de corrutinas. Si no conoces las corrutinas, lee lo siguiente:
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
Usa 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 a través de la configuración de los parámetros del modelo y el uso 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 Parámetros del modelo.
Kotlin
val config = generationConfig {
temperature = 0.9f
topK = 16
topP = 0.1f
maxOutputTokens = 200
stopSequences = listOf("red")
}
val generativeModel = GenerativeModel(
// The Gemini 1.5 models are versatile and work with most use cases
modelName = "gemini-1.5-flash",
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();
// The Gemini 1.5 models are versatile and work with most use cases
GenerativeModel gm = new GenerativeModel(
"gemini-1.5-flash",
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 recibir respuestas que puede considerarse perjudicial. Según la configuración predeterminada, la configuración de seguridad bloquea el contenido con o una alta probabilidad de ser contenido no seguro en todas las dimensiones. Aprendizaje Obtén más información sobre la configuración de seguridad.
Sigue estos pasos para establecer una configuración de seguridad:
Kotlin
val generativeModel = GenerativeModel(
// The Gemini 1.5 models are versatile and work with most use cases
modelName = "gemini-1.5-flash",
apiKey = BuildConfig.apiKey,
safetySettings = listOf(
SafetySetting(HarmCategory.HARASSMENT, BlockThreshold.ONLY_HIGH)
)
)
Java
SafetySetting harassmentSafety = new SafetySetting(HarmCategory.HARASSMENT,
BlockThreshold.ONLY_HIGH);
// The Gemini 1.5 models are versatile and work with most use cases
GenerativeModel gm = new GenerativeModel(
"gemini-1.5-flash",
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(
// The Gemini 1.5 models are versatile and work with most use cases
modelName = "gemini-1.5-flash",
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);
// The Gemini 1.5 models are versatile and work with most use cases
GenerativeModel gm = new GenerativeModel(
"gemini-1.5-flash",
BuildConfig.apiKey,
null, // generation config is optional
Arrays.asList(harassmentSafety, hateSpeechSafety)
);
GenerativeModelFutures model = GenerativeModelFutures.from(gm);
¿Qué sigue?
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 redacción de instrucciones.
Gemini ofrece diversas variaciones de modelos para satisfacer las necesidades de los distintos usos como tipos de entrada y complejidad, implementaciones para chat u otros las tareas de lenguaje de diálogo y las restricciones de tamaño. Obtén más información sobre los modelos de Gemini disponibles.
El SDK cliente para Android descrito en este instructivo te permite acceder a la Modelos de Gemini Pro que se ejecutan en los servidores de Google. Para casos de uso que involucran 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 información, consulta la Instructivo para Android (en el dispositivo)