paint-brush
Jouer Simon Says avec Gemma-2b et MediaPipeby@darrylbayliss
665
665

Jouer Simon Says avec Gemma-2b et MediaPipe

Darryl Bayliss11m2024/03/29
Read on Terminal Reader

Gemma est un nouveau LLM de Google suffisamment petit pour fonctionner sur des machines locales et des appareils mobiles. Vous pouvez utiliser MediaPipe pour vous connecter au LLM sur l'appareil et lui poser des requêtes. Le modèle 2b ne semble pas bien fonctionner et le modèle 7b est une amélioration. Pour les versions v1, il est impressionnant qu’elles fonctionnent sur un appareil mobile.
featured image - Jouer Simon Says avec Gemma-2b et MediaPipe
Darryl Bayliss HackerNoon profile picture
0-item
1-item


Il y a quelques semaines, j'ai assisté à la journée des développeurs Gemma de Google. Une journée dédiée à Google présentant les capacités, la portabilité et l'ouverture de leurs nouveaux modèles LLM appelés Gemma.


Ces modèles présentent une nouvelle phase passionnante pour l’IA générative. Des modèles suffisamment petits pour être déployés sur des appareils locaux et peuvent néanmoins offrir une expérience attrayante et utile.


Cela fait un moment que je n'ai pas regardé Mobile AI et je suis reparti de la journée inspiré. J'ai décidé de voir ce qui se passe lorsque j'essaie ces modèles dans une application Android.

L'application

Je voulais proposer à Gemma un défi simple mais inédit. Jouer à un jeu de Simon Says.


Les règles sont simples. Un joueur devient Simon. Leur rôle est de confier aux autres joueurs des tâches à accomplir. Le joueur jouant le rôle de Simon doit dire « Simon dit » avant de confier la tâche.


J'ai créé une application avec trois écrans. Un écran de saisie, un écran d'instructions et un écran de discussion où Gemma peut communiquer et confier des tâches.


Simon dit que les écrans d'application


Pour accélérer la création de l'écran de discussion, j'ai trouvé ce billet de blog de Meyta Taliti extrêmement utile.

Avec les écrans créés, ma prochaine tâche était d'intégrer Gemma. Pour cela, je me suis appuyé sur un ensemble d'outils que j'ai découvert appelé MediaPipe.

MédiaPipe

MediaPipe est une collection d'outils dont le but est de simplifier l'intégration de modèles d'IA dans les applications sur Android, iOS et le Web. Avec MediaPipe, vous avez beaucoup de choix en fonction de vos besoins.


Logo MediaPipe


Si vous souhaitez démarrer rapidement, MediaPipe fournit une API appelée Tasks pour vous permettre de faire appel aux modèles d'IA. Ces API sont divisées en différents domaines tels que Vision, Texte et Audio.


MediaPipe fournit également une collection de modèles pré-entraînés à intégrer dans vos applications. Encore une fois, utile pour démarrer rapidement.


Si vous avez besoin de quelque chose de plus personnalisé et que vous ne souhaitez pas créer un modèle à partir de zéro, MediaPipe fournit un outil appelé Model Maker . Model Maker utilise un processus appelé Transfer Learning pour recycler un modèle d'apprentissage automatique existant et lui fournir de nouvelles données. L'avantage de cette approche est qu'elle permet de gagner du temps et nécessite moins de données de formation pour créer un nouveau modèle.


Model Maker peut également réduire la taille du modèle créé grâce à ce processus. Notez que ce processus amène le modèle à « oublier » certaines de ses connaissances existantes.


Le dernier outil de MediaPipe est MediaPipe Studio , une application Web permettant d'évaluer et de peaufiner vos modèles personnalisés. Utile si vous souhaitez comparer vos modèles et comprendre leur fonctionnement avant le déploiement.


Pour nos besoins, nous allons exploiter l'API LLM Interfence, une nouvelle API pour MediaPipe. Cela nous permet de communiquer avec Gemma et de recevoir une réponse.

Mettre MediaPipe au travail

Pour utiliser MediaPipe, vous devez d'abord l'ajouter en tant que dépendance progressive à l'application :

 implementation ("com.google.mediapipe:tasks-genai:0.10.11")


Ensuite, vous créez une instance de LlmInference . Voici l'objet que vous utilisez pour communiquer avec Gemma :


 val llmInference = LlmInference.createFromOptions( context, LlmInference.LlmInferenceOptions.builder() .setModelPath("/data/local/tmp/llm/gemma-2b-it-cpu-int8.bin") .build() )


Il est important de noter le chemin défini à l'aide de .setModelPath . C'est là que réside le modèle Gemma sur l'appareil. Il est également important que le modèle Gemma utilisé soit la version gemma-2b . Les versions 7b ne sont pas encore prises en charge par MediaPipe, nous en saurons plus sur ce que tout cela signifie plus tard. Pour l'instant, téléchargeons le modèle.


Vous pouvez télécharger Gemma depuis Kaggle . Un site dédié aux Data Scientists et au Machine Learning. Vous devez créer un compte et accepter les conditions générales d'utilisation avant de pouvoir télécharger les modèles. Vous pouvez trouver la page Gemma ici .


Si vous suivez cet article, n'oubliez pas de télécharger uniquement les versions gemma-2b-it-cpu du modèle, sous l'onglet TensorFlow Lite . Vous êtes seul si vous essayez les versions gemma-2b-it-gpu .


Une fois le modèle téléchargé. Utilisez l' Explorateur de périphériques dans Android Studio pour importer le modèle dans le chemin défini dans .setModelPath . Si vous avez modifié le chemin ou le nom du modèle, assurez-vous de mettre à jour le nom du chemin.


Une fois le modèle importé, vous pouvez commencer à transmettre des invites à Gemma à l'aide de la méthode .generateResponse . Voici un exemple de l'invite que je transmets à Gemma pour jouer Simon Says :


 private const val SimonSaysPrompt = """ You are a Simon in a game of Simon Says. Your objective is to ask the player to perform tasks. For every task you give, you must prefix it with the words "Simon says". You must not ask the player to do anything that is dangerous, unethical or unlawful. Do not try to communicate with the player. Only ask the player to perform tasks. """ val gemmaResponse = llmInference.generateResponse(SimonSaysPrompt)


Si vous avez déjà utilisé des LLM et avez une compréhension de base de Prompt Engineering, cela devrait vous sembler familier. Par excès de prudence, j'ai inclus des instructions de précaution dans l'invite. Nous ne voulons pas que Simon demande à l'utilisateur de faire quelque chose de douteux !


Si vous essayez de l'exécuter sur un appareil, plusieurs choses peuvent se produire :


  1. L'application peut mettre un certain temps à répondre et éventuellement fournir une réponse.

  2. L'application peut planter. En regardant dans Logcat, vous verrez des messages indiquant que MediaPipe ne parvient pas à trouver le modèle. Avez-vous défini le bon chemin du modèle ?

  3. L'application peut planter. Si vous regardez dans Logcat, vous pouvez voir de nombreuses journaux de code natif et des informations sur la mémoire recyclée.


Mon expérience tombait dans la deuxième et la troisième catégorie. Vos propres expériences peuvent varier si vous avez tout configuré correctement et si vous utilisez un appareil physique de haute spécification.


Si vous n'avez pas d'éther de ces choses. Il existe une autre option, augmentant la quantité de RAM disponible via l'émulateur.

Création d'un émulateur Android avec une RAM accrue

L'augmentation de la quantité de RAM disponible est généralement utile dans un environnement gourmand en mémoire, alors pourquoi un LLM gourmand en mémoire serait-il différent ? Pour ce faire, j'ai personnalisé la quantité de RAM utilisée par mon émulateur Android.


Si vous disposez d'un émulateur existant, vous remarquerez peut-être que le champ RAM est désactivé. Vous pouvez toujours mettre à jour la quantité de RAM disponible en cliquant sur les trois points à droite dans le Gestionnaire de périphériques.


Cliquez sur Afficher sur le disque , puis ouvrez les fichiers config.ini et hardware-qemu.ini dans un éditeur de texte. Modifiez les valeurs de hw.ramSize dans chaque fichier. Merci à cette question Stack Overflow de m'avoir donné la réponse sur la façon de le faire.


L'émulateur Android s'affiche sur le disque


Vous pouvez également créer un émulateur personnalisé en accédant au Gestionnaire de périphériques dans Android Studio, en cliquant sur Créer un périphérique virtuel , puis sur Nouveau profil matériel . Dans le cadre des options de personnalisation, vous pouvez sélectionner la quantité de RAM.


L'émulateur Android Studio configure le profil matériel


J'ai trouvé que 8 Go de RAM fonctionnaient relativement bien. J'ai également tenté ma chance avec 22 Go de RAM. Il est légèrement plus performant en termes de vitesse, mais pas autant que ce à quoi je m'attendais.


Je soupçonne qu'il y a un goulot d'étranglement quelque part lorsque Gemma est chargé en mémoire, car le reste de l'émulateur fonctionne de manière fluide. Peut-être une amélioration quelque part qui peut être apportée.

Gemma 2b et Gemma 7b

Les modèles Gemma compatibles avec MediaPipe sont les versions gemma-2b . Le 2b représente 2 milliards de paramètres. La quantité de paramètres travaillant ensemble pour faire fonctionner le modèle.


Ce sont les valeurs définies dans le modèle pendant la formation pour fournir les connexions et les inférences entre elles lorsque vous posez une question à Gemma.


Il existe également une collection gemma-7b , qui utilise 7 milliards de paramètres. Ceux-ci ne sont cependant pas pris en charge par MediaPipe. Peut-être un jour!


Si vous souhaitez en savoir plus sur les paramètres des LLM, je vous recommande cette page .


Avoir un modèle de 2 milliards de paramètres chargé et exécuté sur un appareil mobile est une réussite impressionnante. Mais est-ce que ça marche bien ? Découvrons-le.

gemma-2b-it-cpu-int4

Le gemma-2b-it-cpu-int4 est un LLM 4 bits. Cela signifie que chaque paramètre utilisé par le modèle a une taille de mémoire de 4 bits. L'avantage ici est que la taille totale du modèle est plus petite, mais la taille de mémoire réduite pour chaque paramètre signifie que la précision et la qualité du modèle sont également affectées.


Alors, comment fonctionne gemma-2b-it-cpu-int4 ? Pas si génial pour être honnête. Voici quelques captures d'écran de mes tentatives pour jouer à Simon Says en utilisant l'invite ci-dessus et en lui posant des questions générales.


conversation gemma-2b-it-cpu-int4

Les réponses étaient inattendues et il était frustrant de demander au modèle de faire quelque chose qui ressemblait à un jeu de Simon Says. Cela virerait à un sujet différent et à des informations hallucinées et inexactes.


Les hallucinations sont un phénomène où les LLM disent des mensonges et des mensonges comme s'il s'agissait de faits. Prenons l'exemple ci-dessus, ce n'est pas vrai que vous pouvez conduire jusqu'à Mars en 60 minutes à 60 mph. Pas encore en tout cas. 😃


Il y avait également un manque de conscience du contexte. Cela signifie qu'il ne pouvait pas se souvenir de quelque chose que j'avais mentionné plus tôt dans une conversation. Cela est probablement dû à la taille limitée du modèle.


Au bout d'un moment, j'ai abandonné ce modèle et j'ai décidé d'essayer le modèle plus grand, de 8 bits.

gemma-2b-it-cpu-int8

Le gemma-2b-it-cpu-int8 est un LLM 8 bits. Sa taille est plus grande que celle de son frère 4 bits. Cela signifie qu’il peut être plus précis et fournir des réponses de meilleure qualité. Alors, quel a été le résultat ici ?


conversation gemma-2b-it-cpu-int8


Ce modèle a su saisir l'idée de Simon Says, assumant immédiatement le rôle de Simon. Malheureusement, il souffrait lui aussi d'un manque de connaissance du contexte.


Pour contrer cela, je devais réinviter le modèle à chaque fois avec les règles de Simon Says et le combiner avec une autre invite pour lui demander de fournir une tâche.


Les invites de tâches sont sélectionnées au hasard dans une liste pour être transmises à Gemma, ce qui donne une certaine variété dans les tâches demandées.


Voici un exemple de ce qui se passe ci-dessous :


 private const val SimonSaysPrompt = """ You are a Simon in a game of Simon Says. Your objective is to ask the player to perform tasks. For every task you give, you must prefix it with the words "Simon says". You must not ask the player to do anything that is dangerous, unethical or unlawful. Do not try to communicate with the player. Only ask the player to perform tasks. """ private const val MovePrompt = SimonSaysPrompt + """ Give the player a task related to moving to a different position. """ private const val SingASongPrompt = SimonSaysPrompt + """ Ask the player to sing a song of their choice. """ private const val TakePhotoPrompt = SimonSaysPrompt + """ Give the player a task to take a photo of an object. """ private val prompts = listOf( MovePrompt, SingASongPrompt, TakePhotoPrompt ) val prompt = prompts.random() val response = llmInference.generateResponse(prompt)


Il lance occasionnellement une réponse de balle courbe qui semble hors de son caractère. J'attribue cela à la taille du modèle. Cela vaut également la peine de considérer qu'il ne s'agit que de la v1.


Une fois les invites gravées dans le marbre, j'ai trouvé qu'il était utile de s'appuyer uniquement sur les invites et de ne pas prendre en compte les entrées de l'utilisateur. Parce que le modèle manque de connaissance du contexte, l'entrée de l'utilisateur l'amène à arrêter de jouer Simon Says et à répondre à l'entrée.


Ajouter ce peu de supercherie n'était pas un résultat satisfaisant, mais il fallait que Gemma continue à jouer Simon Says.

Impressions et pensées

Alors, Gemma peut-elle jouer à Simon Says sur un appareil Android ? Je vais dire « en quelque sorte, avec de l'aide ».


J'aimerais voir la version 4 bits de Gemma 2b répondre de manière plus intuitive. Rendre Gemma 2b conscient du contexte pour éviter d'avoir à le réinviter pour chaque demande et être prudent avec les entrées de l'utilisateur serait également utile.


Pour les demandes simples ne nécessitant qu’une seule invite. Je vois que Gemma 2b est capable de gérer confortablement ces tâches.


Il convient également de garder à l’esprit qu’il s’agit de la version 1 des modèles. Le fait qu’ils fonctionnent sur un système d’exploitation mobile est une réussite impressionnante !

L'avenir des LLM sur appareil

Qu’en est-il de l’avenir des LLM sur appareils mobiles ? Il y a deux barrières que je vois. Limites matérielles et cas d’utilisation pratiques.


Je pense que nous sommes à un point où seuls les appareils haut de gamme peuvent faire fonctionner efficacement ces modèles. Les appareils qui me viennent à l’esprit sont les séries de téléphones Pixel 7 ou Pixel 8 avec leurs puces Tensor G, et l’iPhone d’Apple avec leur puce Neural Engine.


Nous devons voir ce type de spécifications s’appliquer aux téléphones de milieu de gamme.


Des idées intéressantes pourraient provenir de LLM sur appareil exploitant la génération augmentée de récupération . Une technique permettant aux LLM de communiquer avec des sources de données externes afin de récupérer un contexte supplémentaire lors de la fourniture de réponses. Cela pourrait être un moyen efficace d’améliorer les performances.


Le deuxième obstacle consiste à trouver des cas d’utilisation pratiques. Je pense que ceux-ci sont limités alors que les appareils peuvent communiquer avec des LLM plus puissants sur Internet. GPT-4 d'OpenAI, par exemple, prendrait en charge plus d'un billion de paramètres !


Il pourrait cependant arriver un moment où le coût de déploiement de ces modèles sur des appareils mobiles deviendra moins cher que celui de leur hébergement dans le cloud. Étant donné que la réduction des coûts est à la mode ces jours-ci, je peux considérer qu'il s'agit d'un cas d'utilisation viable.


Avoir votre propre LLM personnel présente également des avantages en matière de confidentialité, sans qu'aucune information ne quitte les limites de votre appareil. Un avantage utile qui séduira les utilisateurs d’applications soucieux de leur confidentialité.


Je parie que nous sommes encore à quelques années du déploiement régulier des LLM sur les appareils.

Ressources utiles

Si vous souhaitez essayer Gemma par vous-même sur un appareil mobile, voici quelques ressources pour vous aider :


Gemma : Le site Web officiel de Gemma contient une multitude d'informations, notamment des tests de référence, des guides de démarrage rapide et des informations sur l'approche de Google en matière de développement responsable de l'IA générative.


MediaPipe : MediaPipe possède sa propre section Google Developer où vous pouvez en savoir plus sur lui et comment l'utiliser. Lecture fortement recommandée.


Google Developer Group Discord : Le Google Developer Group Discord dispose de canaux dédiés à l'IA générative. Consultez les chaînes #gemma, #gemini et #ml pour discuter avec des personnes partageant les mêmes idées.


Simons Says App : clonez et exécutez l' exemple de code de cet article de blog pour le voir en action. Il inclut également l'utilisation de la tâche de classification d'images de MediaPipe. Les instructions de configuration se trouvent dans le README.


Notes de bas de page

Mis à jour le 23/03/24 pour mentionner l'appel de l'inférence LLM à partir d'un thread IO


  1. Il m'est venu à l'esprit après avoir écrit ce post que faire appel à Gemma est une opération de lecture/écriture sur un fichier. Déplacer la méthode .generateResponse() vers un thread IO évitera l'immense bruit lorsque gemma est chargé en mémoire :

     suspend fun sendMessage(): String { return withContext(Dispatchers.IO) { val prompt = prompts.random() llmInference.generateResponse(prompt) } }


Apparaît également ici .