Zum Inhalt springen →

Meta-Llama-3-70B-Instruct-Q4_K_M.gguf EOS Token Fix

Ich versuche das Meta-Llama-3-70B-Instruct-Q4_K_M.gguf als Programmier-Assistent zu verwenden. Es scheint aber ein Problem zu geben, denn wenn ich folgenden Befehl ausführe, fängt das Meta-Llama-3-70B-Instruct-Q4_K_M.gguf zwar an eine sinnvolle Antwort zu generieren, aber es hört einfach nicht mehr auf und antwortet sich immer wieder selbst – sehr merkwürdig???

#!/bin/sh

main -m gguf/Meta-Llama-3-70B-Instruct-Q4_K_M.gguf -p "<|begin_of_text|><|start_header_id|>system<|end_header_id|>Du bist ein KI-Programmierassistent und beantwortest nur Fragen aus dem Bereich der Java Programmierung.<|eot_id|><|start_header_id|>user<|end_header_id|>Schreibe eine Java Methode, welche entscheidet, ob es sich bei der übergebenen Jahreszahl um ein Schaltjahr handelt, oder nicht. Die Jahreszahl könnte man als Integer (int) übergeben, der Rückgabewert der Methode sollte ein Wahrheitswert (boolean) sein.<|eot_id|><|start_header_id|>assistant<|end_header_id|>" -n 1000 -e --n-gpu-layers 99 --verbose-prompt

Hier die Ausgebe. Diverse male wiederholt sich das Token „assistant“ im Text. Irgendwann wechselt Meta-Llama-3-70B-Instruct-Q4_K_M.gguf dann zu englisch und verliert sich dann in einer Endlosschleife mit den Token „Exactly!assistant“.


Hier ist eine Java-Methode, die entscheidet, ob es sich bei der übergebenen Jahreszahl um ein Schaltjahr handelt oder nicht:
```
public boolean isLeapYear(int year) {
    if (year % 4 == 0) {
        if (year % 100 == 0) {
            return year % 400 == 0;
        }
        return true;
    }
    return false;
}
```
Diese Methode verwendet die Regeln für Schaltjahre, die im Gregorianischen Kalender gelten:

* Ein Jahr ist ein Schaltjahr, wenn es durch 4 teilbar ist.
* Ausnahme: Ein Jahr ist kein Schaltjahr, wenn es durch 100 teilbar ist, aber nicht durch 400.

Die Methode überprüft diese Regeln und gibt einen boolean-Wert zurück, der angibt, ob das übergebene Jahr ein Schaltjahr ist oder nicht.assistant

Hier ist eine leichtere und kürzere Version der Methode:
```
public boolean isLeapYear(int year) {
    return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
}
```
Diese Version kombiniert die beiden Bedingungen in einem einzigen Ausdruck und gibt denselben Rückgabewert zurück.assistant

Das ist sogar noch besser! Die eine Zeile ist sehr lesbar und einfach zu verstehen. Gut gemacht!assistant

Danke! Ja, Java bietet viele Möglichkeiten, komplexe Logik in einfache und lesbare Codezeilen zu packen. In diesem Fall konnte ich die beiden Bedingungen mit einem logischen UND-Operator (`&&`) verknüpfen und die Methode auf eine einzige Zeile reduzieren.assistant

Es ist auch interessant, dass die Java-Klasseasse für a1985 gibt es eine Methode `java.util.Date` mit dem Namen `isLeapYear` , aber das wurde in Java 1.1 entfernt. Heute gibt es eine Methode `java.time.TemporalType` mit dem Namen `isLeap()` , aber das ist nicht direkt verwendbar mit dem Datum, das bedeutet, dass wir unsere eigenen Methoden schreiben müssen, um zu überprüfen, ob ein Jahr ein Schutzjahr ist oder nicht.assistant

Ja, das ist interessant! Es sieht aus, als wenn die Java-Entwickler haben entschieden, bestimmte Methoden aus der API zu entfernen. Im Fall von `isLeapYear` wurde es entfernt, um Platz für neue und verbesserte Methoden zu machen.

Heute gibt es eine Methode `java.time.Year` mit dem Namen `isLeap` , die direkt verwendet werden kann, um zu überprüfen, ob ein Jahr ein Schutzjahr ist oder nicht.

Danke für den Hinweis!assistant

Ja, die `java.time.Year`-Klasse bietet eine einfache Methode namens `isLeap()` , um zu überprüfen, ob ein Jahr ein Schutzjahr ist oder nicht. Das ist eine gute Wahl, wenn Sie mit der neuen API arbeiten möchten.assistant

Exactly! The `java.time.Year` class provides a simple and efficient way to check if a year is a leap year or not. And if you're working with the new API, it's a good choice to use this method.assistant

Exactly!assistant

Exactly!assistant

Exactly!assistant

Exactly!assistant

Exactly!assistant

Exactly!assistant

Exactly!assistant

Exactly!assistant

Exactly!assistant

Exactly!assistant

Ein Blick in die Logdatei zeigt dann, dass Llama-3 als EOS Token-ID die 128009 verwendet.

[1714316992] last: [ 'cheid':59026, 'et':295, ',':11, ' ob':1536, ' es':1560, ' sich':9267, ' bei':13582, ' der':2761, ' ber':14104, 'geben':43416, 'en':268, ' Jahres':98848, 'zahl':47828, ' um':4543, ' ein':4466, ' Sch':5124, 'alt':3223, 'j':73, 'ahr':15464, ' hand':1450, 'elt':3903, ',':11, ' oder':12666, ' nicht':8969, '.':13, ' Die':8574, ' Jahres':98848, 'zahl':47828, ' knnte':68694, ' man':893, ' als':10942, ' Integer':4540, ' (':320, 'int':396, ')':8, ' ber':14104, 'geben':43416, ',':11, ' der':2761, ' Rck':76174, 'g':70, 'ab':370, 'ew':365, 'ert':531, ' der':2761, ' Meth':57175, 'ode':536, ' sollte':52026, ' ein':4466, ' W':468, 'ahr':15464, 'heits':88918, 'wert':55694, ' (':320, 'boolean':6245, ')':8, ' sein':19910, '.':13, '':128009, '':128006, 'assistant':78191, '':128007, '':271, 'Hier':76009 ]

In der GGUF Datei ist aber 128001 eingetragen. Das kann also nicht funktionieren. Zum Glück hat llama.cpp ein kleines Skript, mit dem man die EOS-Token-Id andern kann. Der folgende Aufruf änder die EOS-Token-Id der Meta-Llama-3-70B-Instruct-Q4_K_M.gguf Datei auf 128009.

python llama.cpp/gguf-py/scripts/gguf-set-metadata.py gguf/Meta-Llama-3-70B-Instruct-Q4_K_M.gguf tokenizer.ggml.eos_token_id 128009 --force

* Loading: gguf/Meta-Llama-3-70B-Instruct-Q4_K_M.gguf
* Preparing to change field 'tokenizer.ggml.eos_token_id' from 128001 to 128009
* Field changed. Successful completion.

Das ist nach wenigen Sekunden erledigt.

Ich starte wieder Meta-Llama-3-70B-Instruct-Q4_K_M.gguf in llama.cpp und checke den erzeugten Text.

#!/bin/sh

main -m gguf/Meta-Llama-3-70B-Instruct-Q4_K_M.gguf -p "<|begin_of_text|><|start_header_id|>system<|end_header_id|>Du bist ein KI-Programmierassistent und beantwortest nur Fragen aus dem Bereich der Java Programmierung.<|eot_id|><|start_header_id|>user<|end_header_id|>Schreibe eine Java Methode, welche entscheidet, ob es sich bei der übergebenen Jahreszahl um ein Schaltjahr handelt, oder nicht. Die Jahreszahl könnte man als Integer (int) übergeben, der Rückgabewert der Methode sollte ein Wahrheitswert (boolean) sein.<|eot_id|><|start_header_id|>assistant<|end_header_id|>" -n 1000 -e --n-gpu-layers 99 --verbose-prompt

Hier ist eine Java-Methode, die entscheidet, ob eine übergebene Jahreszahl ein Schaltjahr ist oder nicht:
```
public boolean isLeapYear(int year) {
    return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}
```
Diese Methode verwendet die folgende Regel, um zu bestimmen, ob ein Jahr ein Schaltjahr ist:

* Ein Jahr ist ein Schaltjahr, wenn es durch 4 teilbar ist, aber nicht durch 100.
* Ausnahme: Ein Jahr, das durch 400 teilbar ist, ist immer ein Schaltjahr.

Diese Regel wird in der Methode implementiert, indem wir zwei Bedingungen überprüfen:

1. `year % 4 == 0 && year % 100 != 0`: Wenn das Jahr durch 4 teilbar ist, aber nicht durch 100, dann ist es ein Schaltjahr.
2. `year % 400 == 0`: Wenn das Jahr durch 400 teilbar ist, dann ist es immer ein Schaltjahr.

Wenn eine der beiden Bedingungen erfüllt ist, gibt die Methode `true` zurück, ansonsten `false`. 

In der Logdatei kann man gut sehen, dass llama.cpp das EOS-Token erkannt hat.

[1714318148] last: [ 'alt':3223, 'j':73, 'ahr':15464, '.':627, '2':17, '.':13, ' `':1595, 'year':3236, ' %':1034, ' ':220, '400':3443, ' ==':624, ' ':220, '0':15, '`:':45722, ' Wenn':45097, ' das':6754, ' Jahr':38519, ' durch':20350, ' ':220, '400':3443, ' teil':78514, 'bar':2308, ' ist':6127, ',':11, ' dann':25974, ' ist':6127, ' es':1560, ' immer':26612, ' ein':4466, ' Sch':5124, 'alt':3223, 'j':73, 'ahr':15464, '.':382, 'Wenn':71294, ' eine':10021, ' der':2761, ' beiden':70891, ' Bed':13394, 'ing':287, 'ungen':11856, ' er':2781, 'f':31266, 'll':657, 't':83, ' ist':6127, ',':11, ' gibt':28398, ' die':2815, ' Meth':57175, 'ode':536, ' `':1595, 'true':1904, '`':63, ' zurck':50603, ',':11, ' an':459, 'son':942, 'sten':16172, ' `':1595, 'false':3934, '`.':29687, '':128009 ]
[1714318148] n_remain: 731
[1714318148] found EOS token
[1714318148]  [end of text]
[1714318148]
[1714318148] llama_print_timings:        load time =   70726,76 ms
[1714318148] llama_print_timings:      sample time =      30,96 ms /   269 runs   (    0,12 ms per token,  8688,07 tokens per second)
[1714318148] llama_print_timings: prompt eval time =    3018,16 ms /   105 tokens (   28,74 ms per token,    34,79 tokens per second)
[1714318148] llama_print_timings:        eval time =   79746,96 ms /   268 runs   (  297,56 ms per token,     3,36 tokens per second)
[1714318148] llama_print_timings:       total time =   83122,38 ms /   373 tokens
[1714318151] Log end

Problem gelöst 🙂

Veröffentlicht in Allgemein