Guía de inferencia de LLM para Android

La API de inferencia de LLM te permite ejecutar modelos grandes de lenguaje (LLM) completamente integrados en el dispositivo para aplicaciones para Android, que puedes usar a fin de realizar una amplia variedad de tareas, como generar texto, recuperar información en formato de lenguaje natural y resumir documentos. La tarea proporciona compatibilidad integrada con varios modelos grandes de lenguaje de texto a texto, de modo que puedas aplicar los modelos de IA generativa más recientes integrados en el dispositivo a tus apps para Android.

La tarea admite Gemma 2B, una parte de una familia de modelos abiertos de vanguardia y ligeros compilados a partir de la misma investigación y tecnología que se usaron para crear los modelos de Gemini. También admite los siguientes modelos externos: Phi-2, Falcon-RW-1B y StableLM-3B, junto con todos los modelos exportados a través de AI Edge.

Para obtener más información sobre las capacidades, los modelos y las opciones de configuración de esta tarea, consulta la Descripción general.

Ejemplo de código

Esta guía hace referencia a un ejemplo de una app básica de generación de texto para Android. Puedes usarla como punto de partida de tu propia app para Android o consultarla cuando modifiques una app existente. El código de ejemplo se aloja en GitHub.

Descarga el código

En las siguientes instrucciones, se muestra cómo crear una copia local del código de ejemplo con la herramienta de línea de comandos git.

Para descargar el código de ejemplo, haz lo siguiente:

  1. Usa el siguiente comando para clonar el repositorio de Git:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. De manera opcional, configura tu instancia de Git para que use un proceso de confirmación de compra disperso, de modo que solo tengas los archivos para la app de ejemplo de la API de inferencia de LLM:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/llm_inference/android
    

Después de crear una versión local del código de ejemplo, puedes importar el proyecto a Android Studio y ejecutar la app. Para obtener instrucciones, consulta la Guía de configuración de Android.

Configuración

En esta sección, se describen los pasos clave para configurar tu entorno de desarrollo y los proyectos de código específicamente a fin de usar la API de inferencia de LLM. Si quieres obtener información general sobre cómo configurar tu entorno de desarrollo para usar tareas de MediaPipe, incluidos los requisitos de la versión de la plataforma, consulta la Guía de configuración para Android.

Dependencias

La API de inferencia de LLM usa la biblioteca com.google.mediapipe:tasks-genai. Agrega esta dependencia al archivo build.gradle de tu app para Android:

dependencies {
    implementation 'com.google.mediapipe:tasks-genai:0.10.14'
}

Modelo

La API de inferencia del LLM de MediaPipe requiere un modelo de lenguaje de texto a texto entrenado que sea compatible con esta tarea. Después de descargar un modelo, instala las dependencias necesarias y envíalo al dispositivo Android. Si usas un modelo que no sea Gemma, tendrás que convertirlo a un formato compatible con MediaPipe.

Si deseas obtener más información sobre los modelos entrenados disponibles para la API de inferencia de LLM, consulta la descripción general de tareas en la sección Modelos.

Descarga un modelo

Antes de inicializar la API de inferencia de LLM, descarga uno de los modelos compatibles y almacena el archivo dentro del directorio de tu proyecto:

  • Gemma 2B: Es parte de una familia de modelos abiertos, ligeros y de vanguardia, compilados a partir de la misma investigación y tecnología que se usó para crear los modelos de Gemini. Ideal para una variedad de tareas de generación de texto, como responder preguntas, resumir y razonar.
  • Phi-2: Es un modelo Transformer de 2, 700 millones de parámetros, el más adecuado para el formato de pregunta-respuesta, chat y código.
  • Falcon-RW-1B: Un modelo causal solo de decodificador de 1,000 millones de parámetros entrenado con 350,000 millones de tokens de RefinedWeb.
  • StableLM-3B: Modelo de lenguaje solo de decodificador de 3,000 millones de parámetros previamente entrenado con 1 billón de tokens de diversos conjuntos de datos de código y inglés.

Como alternativa, puedes usar modelos asignados y exportados a través de AI Edge Troch.

Recomendamos usar Gemma 2B, que está disponible en los modelos de Kaggle y tiene un formato que ya es compatible con la API de inferencia de LLM. Si usas otro LLM, deberás convertir el modelo a un formato compatible con MediaPipe. Para obtener más información sobre Gemma 2B, consulta el sitio de Gemma. Para obtener más información sobre los otros modelos disponibles, consulta la descripción general de la tarea Sección Modelos.

Convierte el modelo a formato de MediaPipe

Conversión de modelos nativos

Si usas un LLM externo (Phi-2, Falcon o StableLM) o una versión de Gemma que no sea Kaggle, usa nuestras secuencias de comandos de conversión para formatear el modelo y que sea compatible con MediaPipe.

El proceso de conversión del modelo requiere el paquete MediaPipe PyPI. La secuencia de comandos de conversión está disponible en todos los paquetes de MediaPipe después de 0.10.11.

Instala e importa las dependencias con lo siguiente:

$ python3 -m pip install mediapipe

Usa la biblioteca genai.converter para convertir el modelo:

import mediapipe as mp
from mediapipe.tasks.python.genai import converter

config = converter.ConversionConfig(
  input_ckpt=INPUT_CKPT,
  ckpt_format=CKPT_FORMAT,
  model_type=MODEL_TYPE,
  backend=BACKEND,
  output_dir=OUTPUT_DIR,
  combine_file_only=False,
  vocab_model_file=VOCAB_MODEL_FILE,
  output_tflite_file=OUTPUT_TFLITE_FILE,
)

converter.convert_checkpoint(config)

Para convertir el modelo de LoRA, ConversionConfig debe especificar las opciones del modelo base, así como las opciones de LoRA adicionales. Ten en cuenta que, como la API solo admite inferencias de LoRA con GPU, el backend debe configurarse en 'gpu'.

import mediapipe as mp
from mediapipe.tasks.python.genai import converter

config = converter.ConversionConfig(
  # Other params related to base model
  ...
  # Must use gpu backend for LoRA conversion
  backend='gpu',
  # LoRA related params
  lora_ckpt=LORA_CKPT,
  lora_rank=LORA_RANK,
  lora_output_tflite_file=LORA_OUTPUT_TFLITE_FILE,
)

converter.convert_checkpoint(config)

El conversor generará dos archivos de búfer plano de TFLite, uno para el modelo base y otro para el modelo de LoRA.

Parámetro Descripción Valores aceptados
input_ckpt Es la ruta de acceso al archivo model.safetensors o pytorch.bin. Ten en cuenta que, a veces, el formato de los Safetensors del modelo se fragmenta en varios archivos, p.ej., model-00001-of-00003.safetensors, model-00001-of-00003.safetensors. Puedes especificar un patrón de archivo, como model*.safetensors. PATH
ckpt_format El formato de archivo del modelo. {"safetensors", "pytorch"}
model_type El LLM que se convertirá. {“PHI_2”, “FALCON_RW_1B”, “STABLELM_4E1T_3B”, “GEMMA_2B"}
backend El procesador (delegado) que se usa para ejecutar el modelo. {"cpu", "gpu"}
output_dir La ruta de acceso al directorio de salida que aloja los archivos de peso por capa. PATH
output_tflite_file Es la ruta de acceso al archivo de salida. Por ejemplo, "model_cpu.bin" o "model_gpu.bin". Este archivo solo es compatible con la API de inferencia de LLM y no se puede usar como un archivo general “tflite”. PATH
vocab_model_file Es la ruta de acceso al directorio que almacena los archivos tokenizer.json y tokenizer_config.json. En Gemma, selecciona el único archivo tokenizer.model. PATH
lora_ckpt La ruta de acceso al archivo ckpt de LoRA de Safetensors que almacena el peso del adaptador de LoRA. PATH
lora_rank Es un número entero que representa la clasificación de ckpt de LoRA. Obligatorio para convertir las ponderaciones de lora. Si no se proporcionan, el conversor considera que no hay ponderaciones de la LoRA. Nota: Solo el backend de GPU es compatible con LoRA. Número entero
lora_output_tflite_file Nombre de archivo de tflite de salida para las ponderaciones de LoRA. PATH

Conversión de modelos de AI Edge

Si usas un LLM asignado a un modelo de TFLite a través de AI Edge, usa nuestra secuencia de comandos de paquetes para crear un paquete de tareas. El proceso de creación de paquetes empaqueta el modelo asignado con metadatos adicionales parámetros del tokenizador) necesarios para ejecutar inferencias de extremo a extremo.

El proceso de agrupamiento del modelo requiere el paquete MediaPipe PyPI. La secuencia de comandos de conversión está disponible en todos los paquetes de MediaPipe después de 0.10.14.

Instala e importa las dependencias con lo siguiente:

$ python3 -m pip install mediapipe

Usa la biblioteca genai.bundler para empaquetar el modelo:

import mediapipe as mp
from mediapipe.tasks.python.genai import bundler

config = bundler.BundleConfig(
    tflite_model=TFLITE_MODEL,
    tokenizer_model=TOKENIZER_MODEL,
    start_token=START_TOKEN,
    stop_tokens=STOP_TOKENS,
    output_filename=OUTPUT_FILENAME,
    enable_bytes_to_unicode_mapping=ENABLE_BYTES_TO_UNICODE_MAPPING,
)
bundler.create_bundle(config)
Parámetro Descripción Valores aceptados
tflite_model La ruta de acceso al modelo de TFLite exportado de AI Edge. PATH
tokenizer_model La ruta de acceso al modelo del tokenizador de SentencePiece. PATH
start_token Token de inicio específico del modelo. El token de inicio debe estar presente en el modelo de asignación de tokens proporcionado. STRING
stop_tokens Modela tokens de parada específicos. Los tokens de detención deben estar presentes en el modelo de asignación de tokens proporcionado. LISTA[STRING]
output_filename Es el nombre del archivo de paquete de tareas de salida. PATH

Enviar el modelo al dispositivo

Envía el contenido de la carpeta output_path al dispositivo Android.

$ adb shell rm -r /data/local/tmp/llm/ # Remove any previously loaded models
$ adb shell mkdir -p /data/local/tmp/llm/
$ adb push output_path /data/local/tmp/llm/model_version.bin

Crea la tarea

La API de inferencia del LLM de MediaPipe usa la función createFromOptions() para configurar la tarea. La función createFromOptions() acepta valores para las opciones de configuración. Si deseas obtener más información sobre las opciones de configuración, consulta Opciones de configuración.

El siguiente código inicializa la tarea con opciones de configuración básicas:

// Set the configuration options for the LLM Inference task
val options = LlmInferenceOptions.builder()
        .setModelPATH('/data/local/.../')
        .setMaxTokens(1000)
        .setTopK(40)
        .setTemperature(0.8)
        .setRandomSeed(101)
        .build()

// Create an instance of the LLM Inference task
llmInference = LlmInference.createFromOptions(context, options)

Opciones de configuración

Usa las siguientes opciones de configuración para configurar una app para Android:

Nombre de la opción Descripción Rango de valores Valor predeterminado
modelPath La ruta de acceso en la que se almacena el modelo dentro del directorio del proyecto. PATH N/A
maxTokens La cantidad máxima de tokens (tokens de entrada + tokens de salida) que controla el modelo. Número entero 512
topK La cantidad de tokens que el modelo considera en cada paso de generación. Limita las predicciones a los k tokens más probables principales. Cuando configuras topK, también debes establecer un valor para randomSeed. Número entero 40
temperature La cantidad de aleatoriedad introducida durante la generación. Una temperatura más alta da como resultado más creatividad en el texto generado, mientras que una temperatura más baja produce una generación más predecible. Cuando configuras temperature, también debes establecer un valor para randomSeed. Float 0.8
randomSeed El valor inicial aleatorio usado durante la generación de texto. Número entero 0
loraPath Es la ruta de acceso absoluta al modelo de LoRA local en el dispositivo. Nota: Esto solo es compatible con los modelos de GPU. PATH N/A
resultListener Configura el objeto de escucha de resultados para recibir los resultados de forma asíncrona. Solo es aplicable cuando se usa el método de generación asíncrona. N/A N/A
errorListener Establece un objeto de escucha de errores opcional. N/A N/A

prepara los datos

La API de inferencia de LLM acepta las siguientes entradas:

  • prompt (string): Una pregunta o instrucción.
val inputPrompt = "Compose an email to remind Brett of lunch plans at noon on Saturday."

Ejecuta la tarea

Usa el método generateResponse() para generar una respuesta de texto al texto de entrada proporcionado en la sección anterior (inputPrompt). Esto produce una sola respuesta generada.

val result = llmInference.generateResponse(inputPrompt)
logger.atInfo().log("result: $result")

Para transmitir la respuesta, usa el método generateResponseAsync().

val options = LlmInference.LlmInferenceOptions.builder()
  ...
  .setResultListener { partialResult, done ->
    logger.atInfo().log("partial result: $partialResult")
  }
  .build()

llmInference.generateResponseAsync(inputPrompt)

Cómo controlar y mostrar los resultados

La API de inferencia de LLM muestra un LlmInferenceResult, que incluye el texto de respuesta generado.

Here's a draft you can use:

Subject: Lunch on Saturday Reminder

Hi Brett,

Just a quick reminder about our lunch plans this Saturday at noon.
Let me know if that still works for you.

Looking forward to it!

Best,
[Your Name]

Personalización del modelo de LoRA

La API de inferencia de LLM de Mediapipe se puede configurar para que admita la adaptación de bajo rango (LoRA) en modelos grandes de lenguaje. Mediante modelos de LoRA ajustados, los desarrolladores pueden personalizar el comportamiento de los LLM a través de un proceso de entrenamiento rentable.

La compatibilidad de LoRA con la API de inferencia de LLM funciona con los modelos Gemma-2B y Phi-2 para el backend de la GPU, y las ponderaciones de LoRA se aplican solo a las capas de atención. Esta implementación inicial sirve como una API experimental para desarrollos futuros con planes de admitir más modelos y varios tipos de capas en las próximas actualizaciones.

Prepara modelos de LoRA

Sigue las instrucciones en HuggingFace para entrenar un modelo de LoRA ajustado en tu propio conjunto de datos con los tipos de modelos compatibles: Gemma-2B o Phi-2. Los modelos Gemma-2B y Phi-2 están disponibles en HuggingFace en el formato de cajas fuertes. Dado que la API de inferencia de LLM solo admite LoRA en las capas de atención, especifica únicamente estas capas mientras creas el LoraConfig de la siguiente manera:

# For Gemma-2B
from peft import LoraConfig
config = LoraConfig(
    r=LORA_RANK,
    target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
)

# For Phi-2
config = LoraConfig(
    r=LORA_RANK,
    target_modules=["q_proj", "v_proj", "k_proj", "dense"],
)

Para las pruebas, hay modelos de LoRA perfeccionados y de acceso público que se ajustan a la API de inferencia de LLM disponibles en HuggingFace. Por ejemplo, monsterapi/gemma-2b-lora-maths-orca-200k para Gemma-2B y lole25/phi-2-sft-ultrachat-lora para Phi-2.

Después de entrenar con el conjunto de datos preparado y guardar el modelo, obtendrás un archivo adapter_model.safetensors que contiene los pesos del modelo de LoRA ajustados. El archivo Safetensors es el punto de control de la LoRA que se usa en la conversión del modelo.

En el siguiente paso, debes convertir los pesos del modelo en un búfer plano de TensorFlow Lite con el paquete de MediaPipe para Python. El ConversionConfig debe especificar las opciones del modelo base, así como las opciones de LoRA adicionales. Ten en cuenta que, como la API solo admite la inferencia de LoRA con GPU, el backend debe configurarse en 'gpu'.

import mediapipe as mp
from mediapipe.tasks.python.genai import converter

config = converter.ConversionConfig(
  # Other params related to base model
  ...
  # Must use gpu backend for LoRA conversion
  backend='gpu',
  # LoRA related params
  lora_ckpt=LORA_CKPT,
  lora_rank=LORA_RANK,
  lora_output_tflite_file=LORA_OUTPUT_TFLITE_FILE,
)

converter.convert_checkpoint(config)

El conversor generará dos archivos de búfer plano de TFLite, uno para el modelo base y otro para el modelo de LoRA.

Inferencia del modelo de LoRA

Se actualizaron las APIs de inferencia de LLM para iOS, Android y la Web para admitir la inferencia de modelos de LoRA. Web admite LoRA dinámica, que puede cambiar diferentes modelos de LoRA durante el tiempo de ejecución. iOS y Android admiten la LoRA estática, que utiliza las mismas ponderaciones de la LoRA durante el ciclo de vida de la tarea.

Android admite la LoRA estática durante la inicialización. Para cargar un modelo de LoRA, los usuarios deben especificar la ruta de acceso del modelo de LoRA y el LLM base.

// Set the configuration options for the LLM Inference task
val options = LlmInferenceOptions.builder()
        .setModelPath('<path to base model>')
        .setMaxTokens(1000)
        .setTopK(40)
        .setTemperature(0.8)
        .setRandomSeed(101)
        .setLoraPath('<path to LoRA model>')
        .build()

// Create an instance of the LLM Inference task
llmInference = LlmInference.createFromOptions(context, options)

Para ejecutar la inferencia de LLM con LoRA, usa los mismos métodos generateResponse() o generateResponseAsync() que el modelo base.