Vor ein paar Wochen nahm ich am Gemma Developer Day von Google teil. Ein Tag, an dem Google die Fähigkeiten, Portabilität und Offenheit seiner neuesten LLM-Modelle namens Gemma präsentierte.
Diese Modelle stellen eine spannende neue Phase für generative KI dar. Die Modelle sind klein genug, um auf lokalen Geräten eingesetzt zu werden und können dennoch eine ansprechende und hilfreiche Erfahrung bieten.
Es ist schon eine Weile her , seit ich mich mit Mobile AI beschäftigt habe und den Tag mit Inspiration verbracht habe. Ich beschloss, zu sehen, was passiert, wenn ich diese Modelle in einer Android-App ausprobiere.
Ich wollte Gemma eine einfache, aber neuartige Herausforderung stellen: eine Partie „Simon sagt“.
Die Regeln sind einfach. Ein Spieler schlüpft in die Rolle von Simon. Seine Rolle besteht darin, den anderen Spielern Aufgaben zu geben. Der Spieler, der Simon spielt, muss „Simon sagt“ sagen, bevor er die Aufgabe gibt.
Ich habe eine App mit drei Bildschirmen erstellt. Einem Eingabebildschirm, einem Anweisungsbildschirm und einem Chat-Bildschirm, auf dem Gemma kommunizieren und Aufgaben erteilen kann.
Um die Erstellung des Chat-Bildschirms zu beschleunigen, fand ich diesen Blog-Beitrag von Meyta Taliti äußerst hilfreich.
Nachdem die Bildschirme erstellt waren, bestand meine nächste Aufgabe darin, Gemma zu integrieren. Dazu habe ich mich auf eine Reihe von Tools namens MediaPipe verlassen, die ich kennengelernt habe.
MediaPipe ist eine Sammlung von Tools mit dem Ziel, die Integration von KI-Modellen in Apps auf Android, iOS und im Web zu vereinfachen. Mit MediaPipe haben Sie je nach Bedarf eine große Auswahl.
Wenn Sie schnell loslegen möchten, bietet MediaPipe eine API namens Tasks , mit der Sie KI-Modelle aufrufen können. Diese APIs sind in verschiedene Bereiche wie Vision, Text und Audio unterteilt.
MediaPipe bietet außerdem eine Sammlung vorab trainierter Modelle, die Sie in Ihre Apps einbetten können. Auch dies ist nützlich, um schnell loslegen zu können.
Wenn Sie etwas Individuelleres benötigen und kein Modell von Grund auf neu erstellen möchten, bietet MediaPipe ein Tool namens Model Maker . Model Maker verwendet einen Prozess namens Transfer Learning , um ein vorhandenes maschinelles Lernmodell neu zu trainieren und mit neuen Daten zu versorgen. Der Vorteil dieses Ansatzes besteht darin, dass er Zeit spart und weniger Trainingsdaten erfordert, um ein neues Modell zu erstellen.
Model Maker kann durch diesen Prozess auch die Größe des erstellten Modells reduzieren. Beachten Sie, dass dieser Prozess dazu führt, dass das Modell einen Teil seines vorhandenen Wissens „vergisst“.
Das letzte Tool von MediaPipe ist MediaPipe Studio , eine Webanwendung zum Bewerten und Optimieren Ihrer benutzerdefinierten Modelle. Nützlich, wenn Sie Ihre Modelle vergleichen und herausfinden möchten, wie gut sie vor der Bereitstellung funktionieren.
Für unsere Zwecke nutzen wir die LLM Interfence API, eine neue API für MediaPipe. Damit können wir mit Gemma kommunizieren und eine Antwort erhalten.
Um MediaPipe zu verwenden, müssen Sie es zunächst als Gradle-Abhängigkeit zur App hinzufügen:
implementation ("com.google.mediapipe:tasks-genai:0.10.11")
Als nächstes erstellen Sie eine Instanz von LlmInference
. Dies ist das Objekt, das Sie zur Kommunikation mit Gemma verwenden:
val llmInference = LlmInference.createFromOptions( context, LlmInference.LlmInferenceOptions.builder() .setModelPath("/data/local/tmp/llm/gemma-2b-it-cpu-int8.bin") .build() )
Es ist wichtig, den mit .setModelPath
festgelegten Pfad zu notieren. Dies ist der Speicherort des Gemma-Modells auf dem Gerät. Es ist auch wichtig, dass das verwendete Gemma-Modell die gemma-2b
Version ist. Die 7b
Versionen werden von MediaPipe noch nicht unterstützt. Mehr dazu später. Lassen Sie uns jetzt das Modell herunterladen.
Sie können Gemma von Kaggle herunterladen. Eine Website für Datenwissenschaftler und maschinelles Lernen. Sie müssen ein Konto erstellen und die Nutzungsbedingungen akzeptieren, bevor Sie die Modelle herunterladen können. Die Gemma-Seite finden Sie hier .
Wenn Sie diesem Beitrag folgen, denken Sie daran, nur die gemma-2b-it-cpu
Versionen des Modells unter der Registerkarte TensorFlow Lite
herunterzuladen. Wenn Sie die gemma-2b-it-gpu
Versionen ausprobieren, sind Sie auf sich allein gestellt.
Sobald das Modell heruntergeladen ist. Verwenden Sie den Geräte-Explorer in Android Studio, um das Modell in den in .setModelPath
festgelegten Pfad zu importieren. Wenn Sie den Pfad oder den Modellnamen geändert haben, aktualisieren Sie unbedingt den Pfadnamen.
Sobald das Modell importiert ist, können Sie mit der Methode .generateResponse
beginnen, Eingabeaufforderungen an Gemma zu übergeben. Hier ist ein Beispiel für die Eingabeaufforderung, die ich an Gemma übergebe, um „Simon Says“ abzuspielen:
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)
Wenn Sie bereits LLMs verwendet haben und über Grundkenntnisse in Prompt Engineering verfügen, sollte Ihnen dies bekannt vorkommen. Um auf Nummer sicher zu gehen, habe ich in die Eingabeaufforderung Warnhinweise aufgenommen. Wir möchten nicht, dass Simon den Benutzer auffordert, etwas Fragwürdiges zu tun!
Wenn Sie versuchen, dies auf einem Gerät auszuführen, können einige Dinge passieren:
Es kann einen Moment dauern, bis die App reagiert und schließlich eine Antwort liefert.
Die App kann abstürzen. Wenn Sie in Logcat nachsehen, sehen Sie Meldungen, dass MediaPipe das Modell nicht finden kann. Haben Sie den richtigen Modellpfad festgelegt?
Die App kann abstürzen. Wenn Sie in Logcat nachsehen, können Sie eine Menge natives Code-Logging und Informationen über die Wiederverwendung des Speichers sehen.
Meine Erfahrung fiel in die zweite und dritte Kategorie. Ihre eigenen Erfahrungen können abweichen, wenn Sie alles richtig eingerichtet haben und ein physisches Gerät mit hoher Spezifikation verwenden.
Wenn Sie über keines dieser Dinge verfügen, gibt es eine andere Möglichkeit: Sie können die über den Emulator verfügbare RAM-Menge erhöhen.
In einer speicherintensiven Umgebung ist es normalerweise hilfreich, den verfügbaren RAM zu erhöhen. Warum sollte es bei einem speicherhungrigen LLM anders sein? Zu diesem Zweck habe ich die RAM-Menge angepasst, die mein Android-Emulator verwendet.
Wenn Sie einen vorhandenen Emulator haben, stellen Sie möglicherweise fest, dass das RAM-Feld deaktiviert ist. Sie können die verfügbare RAM-Menge dennoch aktualisieren, indem Sie im Geräte-Manager auf die drei Punkte rechts daneben klicken.
Klicken Sie auf „Auf Datenträger anzeigen“ und öffnen Sie dann die Dateien config.ini und hardware-qemu.ini in einem Texteditor. Ändern Sie die Werte von hw.ramSize
in jeder Datei. Dank dieser Stack Overflow- Frage habe ich die Antwort darauf erhalten.
Alternativ können Sie einen benutzerdefinierten Emulator erstellen, indem Sie in Android Studio zum Geräte-Manager gehen, auf Virtuelles Gerät erstellen und dann auf Neues Hardwareprofil klicken. Als Teil der Anpassungsoptionen können Sie die RAM-Menge auswählen.
Ich habe festgestellt, dass 8 GB RAM relativ gut funktionieren. Ich habe auch mein Glück mit 22 GB RAM versucht. Die Leistung ist in Bezug auf die Geschwindigkeit geringfügig besser, wenn auch nicht so gut wie erwartet.
Ich vermute, dass es irgendwo einen Engpass gibt, wenn Gemma in den Speicher geladen wird, da der Rest des Emulators flüssig läuft. Vielleicht kann irgendwo eine Verbesserung vorgenommen werden.
Die mit MediaPipe kompatiblen Gemma-Modelle sind die gemma-2b
Versionen. Die 2b
steht für 2 Milliarden Parameter. Die Anzahl der Parameter, die zusammenarbeiten, damit das Modell funktioniert.
Dies sind die Werte, die während des Trainings im Modell festgelegt werden, um die Verbindungen und Schlussfolgerungen untereinander bereitzustellen, wenn Sie Gemma eine Frage stellen.
Es gibt auch eine gemma-7b
Sammlung, die 7 Milliarden Parameter verwendet. Diese werden jedoch von MediaPipe nicht unterstützt. Vielleicht eines Tages!
Wenn Sie mehr über die Parameter im Zusammenhang mit LLMs erfahren möchten, empfehle ich Ihnen diese Seite .
Ein Modell mit 2 Milliarden Parametern auf ein Mobilgerät zu laden und auszuführen ist eine beeindruckende Leistung. Aber wie gut funktioniert es? Lassen Sie es uns herausfinden.
Das gemma-2b-it-cpu-int4
ist ein 4-Bit-LLM. Das bedeutet, dass jeder vom Modell verwendete Parameter eine Speichergröße von 4 Bit hat. Der Vorteil hierbei ist, dass die Gesamtgröße des Modells kleiner ist. Allerdings bedeutet die reduzierte Speichergröße für jeden Parameter auch, dass die Genauigkeit und Qualität des Modells beeinträchtigt werden.
Wie sieht also die Leistung von gemma-2b-it-cpu-int4
aus? Ehrlich gesagt nicht so toll. Hier sind ein paar Screenshots meiner Versuche, Simon Says mit der obigen Eingabeaufforderung zu spielen und allgemeine Fragen zu stellen.
Die Antworten waren unerwartet und es war frustrierend, das Modell dazu zu bringen, irgendetwas zu machen, das einer „Simon sagt“-Runde ähnelte. Es schweifte zu einem anderen Thema ab und halluzinierte ungenaue Informationen.
Halluzinationen sind ein Phänomen, bei dem LLMs Unwahrheiten und unwahre Dinge sagen, als wären sie Tatsachen. Nehmen wir das obige Beispiel: Es stimmt nicht, dass man mit 60 Meilen pro Stunde in 60 Minuten zum Mars fahren kann. Noch jedenfalls nicht. 😃
Es fehlte auch die Kontextwahrnehmung. Das heißt, es konnte sich nicht an etwas erinnern, das ich zuvor in einem Gespräch erwähnt hatte. Dies liegt wahrscheinlich an der eingeschränkten Größe des Modells.
Nach einer Weile habe ich dieses Modell aufgegeben und beschlossen, das größere 8-Bit-Modell auszuprobieren.
gemma-2b-it-cpu-int8
ist ein 8-Bit-LLM. Es ist größer als sein 4-Bit-Geschwisterchen. Das bedeutet, dass es genauer sein und qualitativ bessere Antworten liefern kann. Was war also das Ergebnis hier?
Dieses Modell konnte die Idee von „Simon sagt“ erfassen und sofort die Rolle von Simon übernehmen. Leider fehlte auch hier das Kontextbewusstsein.
Um dem entgegenzuwirken, musste ich das Modell jedes Mal erneut mit den „Simon Says“-Regeln auffordern und dies mit einer weiteren Aufforderung kombinieren, eine Aufgabe bereitzustellen.
Die Aufgabenanweisungen werden nach dem Zufallsprinzip aus einer Liste ausgewählt und an Gemma weitergegeben, was für etwas Abwechslung bei den gestellten Aufgaben sorgt.
Hier ist ein Beispiel dessen, was unten passiert:
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)
Es gibt gelegentlich überraschende Reaktionen, die untypisch erscheinen. Ich führe das auf die Größe des Modells zurück. Außerdem sollte man bedenken, dass dies nur v1 ist.
Nachdem die Eingabeaufforderungen in Stein gemeißelt waren, fand ich es sinnvoll, sich nur auf die Eingabeaufforderungen zu verlassen und die Benutzereingaben nicht zu berücksichtigen. Da dem Modell die Kontextwahrnehmung fehlt, führt die Benutzereingabe dazu, dass es die Wiedergabe von „Simon Says“ beendet und stattdessen auf die Eingabe reagiert.
Das Ergebnis dieses kleinen Tricks war nicht zufriedenstellend, aber Gemma musste weiterhin „Simon Says“ spielen.
Kann Gemma „Simon Says“ auf einem Android-Gerät spielen? Ich würde sagen: „Mit etwas Hilfe schon.“
Ich würde mir wünschen, dass die 4-Bit-Version von Gemma 2b intuitiver reagiert. Es wäre auch hilfreich, Gemma 2b kontextsensitiv zu machen, damit es nicht bei jeder Anfrage erneut abgefragt werden muss, und bei der Benutzereingabe vorsichtig zu sein.
Für einfache Anfragen, die nur eine einzige Eingabeaufforderung erfordern. Ich kann mir vorstellen, dass Gemma 2b diese Aufgaben problemlos bewältigen kann.
Man sollte auch bedenken, dass es sich hier um die Version 1 der Modelle handelt. Die Tatsache, dass sie auf einem mobilen Betriebssystem laufen und funktionieren, ist eine beeindruckende Leistung!
Wie sieht die Zukunft von LLMs auf Mobilgeräten aus? Ich sehe zwei Hindernisse: Hardwareeinschränkungen und praktische Anwendungsfälle.
Ich denke, wir sind an einem Punkt angelangt, an dem nur High-End-Geräte diese Modelle effektiv ausführen können. Geräte, die mir in den Sinn kommen, sind die Telefonserien Pixel 7 oder Pixel 8 mit ihren Tensor-G-Chips und das iPhone von Apple mit seinem Neural-Engine-Chip.
Wir müssen sehen, dass derartige Spezifikationen auch bei den Mittelklassetelefonen Einzug halten.
Interessante Ideen könnten von geräteinternen LLMs kommen, die Retrieval Augmented Generation nutzen. Dabei handelt es sich um eine Technik, mit der LLMs mit externen Datenquellen kommunizieren können, um bei der Bereitstellung von Antworten zusätzlichen Kontext abzurufen. Dies könnte eine effektive Möglichkeit zur Leistungssteigerung sein.
Die zweite Hürde besteht darin, praktische Anwendungsfälle zu finden. Ich denke, diese sind begrenzt, solange Geräte über das Internet mit leistungsstärkeren LLMs kommunizieren können. GPT-4 von OpenAI beispielsweise soll Gerüchten zufolge über eine Billion Parameter unterstützen!
Es könnte jedoch eine Zeit kommen, in der die Bereitstellung dieser Modelle auf Mobilgeräten günstiger wird als das Hosten in der Cloud. Da Kostensenkung heutzutage der letzte Schrei ist, kann ich mir vorstellen, dass dies ein praktikabler Anwendungsfall ist.
Darüber hinaus profitieren Sie von den Datenschutzvorteilen eines eigenen persönlichen LLM, bei dem keine Informationen Ihr Gerät verlassen. Ein nützlicher Vorteil, der datenschutzbewusste App-Benutzer ansprechen wird.
Ich wette, dass es noch ein paar Jahre dauern wird, bis LLMs regelmäßig auf Geräten eingesetzt werden.
Wenn Sie Gemma selbst auf einem Mobilgerät ausprobieren möchten, finden Sie hier einige hilfreiche Ressourcen:
Gemma : Die offizielle Gemma-Website enthält eine Fülle von Informationen, darunter Benchmarks, Kurzanleitungen und Informationen zum Ansatz von Google zur verantwortungsvollen Entwicklung generativer KI.
MediaPipe : MediaPipe verfügt über einen eigenen Google Developer-Bereich , in dem Sie mehr über die Software und ihre Verwendung erfahren können. Sehr empfehlenswerte Lektüre.
Google Developer Group Discord : Die Google Developer Group Discord verfügt über eigene Kanäle für Generative AI. Schauen Sie sich die Kanäle #gemma, #gemini und #ml an, um mit Gleichgesinnten zu chatten.
Simons Says App: Klonen und führen Sie den Beispielcode für diesen Blogbeitrag aus, um ihn in Aktion zu sehen. Er beinhaltet auch die Verwendung der Bildklassifizierungsaufgabe von MediaPipe. Einrichtungsanweisungen finden Sie in der README-Datei.
Aktualisiert am 23.03.24, um den Aufruf der LLM-Inferenz aus einem IO-Thread zu erwähnen
Mir ist nach dem Schreiben dieses Beitrags aufgefallen, dass der Aufruf von Gemma ein Lese-/Schreibvorgang für eine Datei ist. Wenn Sie die Methode .generateResponse()
in einen IO-Thread verschieben, vermeiden Sie das enorme Ruckeln, wenn Gemma in den Speicher geladen wird:
suspend fun sendMessage(): String { return withContext(Dispatchers.IO) { val prompt = prompts.random() llmInference.generateResponse(prompt) } }
Erscheint auch hier .