Categories
AI Development

LoRA von meinem Gesicht

Ich arbeite mich grade durch einen Kurs "ChatGPT, Machine learning, DeepLearning, Neuronale Netze, OpenAI API, GPTs, Assistant API, Gemini, LLMs u. deine Modelle" auf Udemy Business durch und einen Abschnitt wollte ich mir nicht nur anhören, sondern auch nach arbeiten.
Es geht um den Abschnitt "67. Der einfachste & schnellste Weg zu deinem Lora & Bilder mit deinem Gesicht" und das Video ist nur 10 Minuten lang.
Es hörte sich so einfach an: Ein paar Selfies aufnehmen, zurechtschneiden und ein Jupyter Notebook auf Google Colab ausführen. Fertig ist das LoRA des eigenen Gesichts.

Was ist ein LoRA?

LoRAs (Low-Rank Adaptations) sind kleinere Modelle, die man mit bestehenden Stable Diffusion Modellen kombinieren kannst. Sie erlauben es ein Bestehendes Modell «fine zu tunen». So kann man neue "Konzepte", wie mein Gesicht, den generierten Bildern hinzufügen.

Selfies machen

Zuerst also ein paar Selfies aufnehmen, dabei darauf achten, dass im Hintergrund nicht zu viele Gegenstände ablenken, ich wählte eine weiße Wand und ein paar nahm ich noch vor einem schwarzen Hintergrund auf.
Zum Trainieren an den Daten müssen die Bilder auf das Format 512x512 Pixel zurechtgeschnitten werden.
Da war auch schon das erste Problem: Die Bilder meines iPhones legen im HEIC-Format vor:

Was eine HEIC-Datei ist

Die Abkürzung ist auch als HEIF bekannt und steht für High Efficiency Image Format.

  • Es handelt sich dabei um ein Bild-Format zum platzsparenden Speichern von Bildern auf Mobil-Geräten.
  • iOS-Geräte speichern Bilder in HEIC-Dateien, auf Android-Geräten finden Sie in der Regel HEIF-Bilder.
  • Der Vorteil dieses Bild-Formats ist eine kleine Dateigröße bei JPEG-Qualität oder sogar noch besserer Qualität.

Das Problem mit HEIC-Dateien

Es ist ein propritäres Format und kann nicht ohne weiteres verwendet werden.
Ich verwende Windows 11 und konnte die Bilder betrachten, allerdings nicht bearbeiten. Vermutlich hätte ich eine Erweiterung im MS Store kaufen müssen, dann hätte ich es mit Programmen wie IrfanView bearbeiten können.
Gelöst habe ich es statt dessen mit einem Python-Programm, dass die Bilder von HEIC nach JPEG umwandelt und auf 512x512 zurecht schneidet.

LoRA trainieren

Das Training des LoRAs soll in einem Jupyther Notebook auf Google Colab erfolgen. Link
Leider konnte ich es nicht ausführen, der Python Code funktioniert nicht. Kleinere Anpassungen halfen nicht weiter, daher kopierte ich das Jupyther Notebook und die erforderlichen Scripte in ein eigenes GitHub Repository und passte so lange Notebook und Scripte an, bis sie liefen.
Das Stable Diffusion DreamBooth Notebook kann unter diesem Link in Google Colab geöffnet werden.

Categories
AI Development Java

GPTs with Quarkus

We will use LangChain within Quarkus to connect to some GPTs. Quarkus uses the LangChain4j library.

Quarkus LangChain Extensions

What extensions Quarkus provides?

./mvnw quarkus:list-extensions | grep langchain
[INFO]   quarkus-langchain4j-azure-openai                   LangChain4j Azure OpenAI
[INFO]   quarkus-langchain4j-chroma                         LangChain4j Chroma
[INFO]   quarkus-langchain4j-core                           LangChain4j
[INFO]   quarkus-langchain4j-easy-rag                       LangChain4j Easy RAG
[INFO]   quarkus-langchain4j-hugging-face                   LangChain4j Hugging Face
[INFO]   quarkus-langchain4j-milvus                         LangChain4j Milvus embedding store
[INFO]   quarkus-langchain4j-mistral-ai                     LangChain4j Mistral AI
[INFO]   quarkus-langchain4j-ollama                         LangChain4j Ollama
[INFO]   quarkus-langchain4j-openai                         LangChain4j OpenAI
[INFO]   quarkus-langchain4j-pgvector                       Quarkus LangChain4j pgvector embedding store
[INFO]   quarkus-langchain4j-pinecone                       LangChain4j Pinecone embedding store
[INFO]   quarkus-langchain4j-redis                          LangChain4j Redis embedding store

Chat window

We will reuse our chat window from the last post,

src/main/resources/META-INF/resources/chat.html:




    
    
    WebSocket Chat Example
    


    

WebSocket Chat Example

Connecting...



package org.acme;

import io.quarkus.websockets.next.OnTextMessage;
import io.quarkus.websockets.next.WebSocket;
import jakarta.inject.Inject;

@WebSocket(path = "/chatsocket")
public class ChatSocket {
    @Inject
    ChatService chatService;

    @OnTextMessage
    public String onMessage(String userMessage){
        return chatService.chat(userMessage);
    }
}
package org.acme;

import io.quarkus.runtime.StartupEvent;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;

@ApplicationScoped
public class ChatService {
    protected void startup(@Observes StartupEvent event) { 
        System.out.println("Startuuuuuuuuuup event");
    }

    public String chat(String message) {
        return message + " you said.";
    }
}

ChatGPT

Extension

./mvnw quarkus:add-extension -Dextensions='quarkus-langchain4j-openai'

Configuration

quarkus.langchain4j.openai.api-key= 
quarkus.langchain4j.openai.chat-model.model-name=gpt-3.5-turbo

API-Key: You can get an API key from OpenAI. But you need at least to pay 5$, what I did. Alternativley you can use demo as API key for limited testing.

Model-Name: Here are the OpenAI Models. gpt-3.5-turbo is default.
Hint: It is not working, if there is a " "(space/blank) after the model-name.

I had stored my OpenAI-API-key as GitHub secret, so the key is available as environment variable in my Codespace. Therefore I changed the configuration:

quarkus.langchain4j.openai.api-key=${OPEN_API_KEY:demo} 
quarkus.langchain4j.openai.chat-model.model-name=gpt-4o

Code

package org.acme;

import io.quarkiverse.langchain4j.RegisterAiService; 

@RegisterAiService 
public interface Assistant { 
    String chat(String message); 
}

Use this Assistant instead of the ChatService:

package org.acme;

import io.quarkus.websockets.next.OnTextMessage;
import io.quarkus.websockets.next.WebSocket;
import jakarta.inject.Inject;

@WebSocket(path = "/chatsocket")
public class ChatSocket {
    @Inject
    Assistant assistant;

    @OnTextMessage
    public String onMessage(String userMessage){
        return assistant.chat(userMessage);
    }
}

Hugging Face

Extension

./mvnw quarkus:add-extension -Dextensions='quarkus-langchain4j-hugging-face'

Configuration

quarkus.langchain4j.chat-model.provider=huggingface

quarkus.langchain4j.huggingface.api-key=${HUGGINGFACE_API_KEY:nokey}
quarkus.langchain4j.huggingface.chat-model.model-id=KingNish/OpenGPT-4o

Provider: Now we have two models configured, we need to specify which provider to use (huggingface)

API-Key: Get free API-Key from Hugging Face:
Login -> Settings -> Access Tokens -> Generate (Type: 'Read')

Model: Search on the Hugging Face website, I randomly took KingNish/OpenGPT-4o

Code

No code change needed, it works with the same code as for ChatGPT.

Everything is changed by configuration.

Antrophic Claude

Extension

./mvnw quarkus:add-extension -Dextensions='quarkus-langchain4j-anthropic'

[ERROR] ❗  Nothing installed because keyword(s) 'quarkus-langchain4j-anthropic' were not matched in the catalog.

It did not work with the maven executable. Need to add dependency manually to pom.xml, see documentation:


    io.quarkiverse.langchain4j
    quarkus-langchain4j-anthropic
    0.15.1

Configuration

quarkus.langchain4j.chat-model.provider=anthropic

quarkus.langchain4j.anthropic.api-key=${ANTHROPIC_API_KEY:no key}
quarkus.langchain4j.anthropic.chat-model.model-name=claude-3-haiku-20240307

API-Key: Login to Antropic Console and get an API key for free.

Model: Select one from documentation.

Code

No code change needed, it works with the same code as for ChatGPT.

But did not work:

org.jboss.resteasy.reactive.ClientWebApplicationException: Received: 'Bad Request, status code 400' when invoking: Rest Client method: 'io.quarkiverse.langchain4j.anthropic.AnthropicRestApi#createMessage'

Quarkus terminal logging

Without API-key I got a status code 401.

Ollama

Prerequisites

Ollama has to be installed. See this post or Ollama Homepage.

curl -fsSL https://ollama.com/install.sh | sh
export OLLAMA_HOST=0.0.0.0:11434
ollama serve
ollama pull moondream

ollama --version
ollama version is 0.1.41

Extension

./mvnw quarkus:add-extension -Dextensions='quarkus-langchain4j-ollama'

Configuration

quarkus.langchain4j.chat-model.provider=ollama

quarkus.langchain4j.ollama.chat-model.model-id=moondream
quarkus.langchain4j.ollama.timeout=120s

Model: I choose moondream, because it is the smallest one (829MB).

Models can be found on the GitHub page or on Ollama library.

However, Quarkus is ignoring my resourcefriendly choice, as I can see in the Logs: "Preloading model llama3" 🤷‍♂️
UPDATE: For Ollama it is model-id, not model-name!

Code

Also no change.

Mistral

Extension

./mvnw quarkus:add-extension -Dextensions='quarkus-langchain4j-mistral'

Configuration

quarkus.langchain4j.chat-model.provider=mistralai

quarkus.langchain4j.mistralai.api-key=${MISTRALAI_API_KEY:no key}
quarkus.langchain4j.mistralai.chat-model.model-name=mistral-tiny

API-key: You can generate an API-key in Mistral AI Console. But you are required to have a Abonnement, which I do not have. Therefore nor API-key for me.

Model: mistral-tiny is default one

Code

Also no change.

But could not test, because I do not have an API-key.

Groq

I like Groq but unfortunately there is no LangChain4j support yet.

The Python LangChain project has already implemented Groq.