qwen2.5-7b-spreizzaehler-v4
English summary: Experimental Qwen2.5-7B-Instruct with a reduced vocabulary (106,915 of 151,665 tokens), healed with continued pretraining and LoRA-tuned to count characters, letters and words by first spelling the text out ("Spreiz-Technik") inside a <think> block. Unlike v3 it needs no system prompt and has no persona: it answers normal questions normally and counts when asked to. Hand-written held-out counting tests: 32/40 on 40 unseen strings, 39/40 on letter frequency, 12/12 on word counts; chat sanity 27/30. The model passed all pre-registered acceptance criteria. It is not better at counting than modern reasoning models.
Nachfolger von v3. v3 zählte mit seinem Trainings-Prompt jede Eingabe („Hallo“ löste eine Zählshow aus); v4 hat keine Persona, keinen System-Prompt und normales Chat-Verhalten durch Replay-Daten. Varianten: GGUF Q8_0, LoRA-Adapter, geheiltes Basismodell. Daten, Tests, Skripte: Davidmg0815/spreizzaehler-daten.
Verwendung
Kein System-Prompt nötig (das Modell hat keine Persona mehr). Standard-Chat-Template von Qwen.
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
repo = "Davidmg0815/qwen2.5-7b-spreizzaehler-v4"
tok = AutoTokenizer.from_pretrained(repo)
model = AutoModelForCausalLM.from_pretrained(repo, dtype=torch.bfloat16, device_map="auto")
messages = [{"role": "user", "content": "Wie viele r sind in Erdbeere?"}]
text = tok.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = tok(text, return_tensors="pt", add_special_tokens=False).to(model.device)
out = model.generate(**inputs, max_new_tokens=3000, do_sample=False)
print(tok.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True))
Bei Zählfragen antwortet das Modell mit einem <think>-Block (Wort:, optional Gesucht:, Spreizung: in Einzelzeichen, Zählung: mit [Position i: Zeichen] -> …, Zur Sicherheit nachgezählt: N.) und danach mit einem normalen Satz. Leerzeichen stehen als ␣. Alle anderen Fragen beantwortet es normal. Empfohlen: Greedy (temperature 0), kein hoher Repetition-Penalty.
Echte Beispielantwort (unverändert aus dem Test)
Frage: Wie viele r sind in Erdbeere?
<think>
Wort: Erdbeere
Gesucht: r (Groß-/Kleinschreibung egal)
Spreizung: E - r - d - b - e - e - r - e
Zählung:
[Position 1: E] -> nein. Bisher: 0.
[Position 2: r] -> ja! Bisher: 1.
[Position 3: d] -> nein. Bisher: 1.
[Position 4: b] -> nein. Bisher: 1.
[Position 5: e] -> nein. Bisher: 1.
[Position 6: e] -> nein. Bisher: 1.
[Position 7: r] -> ja! Bisher: 2.
[Position 8: e] -> nein. Bisher: 2.
Zur Sicherheit nachgezählt: 2.
</think>
Der Buchstabe „r“ kommt 2-mal in „Erdbeere“ vor.
Ergebnisse
Greedy-Decoding, bf16, ohne System-Prompt, eine Probe pro Aufgabe. Richtig heißt: Die Zahl in der Antwort nach dem </think>-Block stimmt (und die Antwort ist regulär beendet).
Abnahmekriterien (vor dem Training festgelegt)
Alle vorab festgelegten Kriterien wurden erfüllt.
| Kriterium | Ergebnis | |
|---|---|---|
| ✅ | C1 Zaehlen unabhaengig >= 32/40 und Wiederholungen >= 4/6 | 32/40, Wiederholungen 5/6 |
| ✅ | C2 Zaehlen frisch >= 85 % | 106/120 = 88.3 % |
| ✅ | C3 Buchstabenhaeufigkeit >= 80 % | 39/40 = 97.5 % |
| ✅ | C4 Woerter zaehlen >= 9/12 | 12/12 |
| ✅ | C5 Chat-Sanity >= 27/30 | 27/30 |
| ✅ | C6 Format >= 95 % | 222/225 = 98.7 % |
| Test | v3 (mit Trainings-Prompt) | v3 (ohne Prompt)¹ | v4 (ohne Prompt) |
|---|---|---|---|
| unabhängig, 40 handgeschriebene Strings (ohne Grenzfälle) | 26/40 | nicht gemessen | 32/40 |
davon 6 Wiederholungs-Strings (abab…) | 0/6 | nicht gemessen | 5/6 |
| 28 Generalisierungsaufgaben² | 26/28 | 24/28 | 20/28 |
| 42 frische Aufgaben (Generatoren wie Training)² | 37/42 | nicht gemessen | 37/42 |
| 50 deutsche Wörter | 49/50 | 48/50 | 49/50 |
| 8 periodische Strings (neu) | – | – | 6/8 |
| Buchstabenhäufigkeit (40, handgeschrieben, neu) | nicht trainiert | nicht trainiert | 39/40 |
| Wörter zählen (12, neu) | nicht trainiert | nicht trainiert | 12/12 |
Chat-Sanity (30 normale Fragen: passende Antwort, keine <think>-/Persona-Reste) | – | – | 27/30 |
Antwort mit <think>…</think> und regulärem Ende | – | 2/50 (Wörter) | 222/225 |
¹ v3 ohne den Trainings-System-Prompt, neu ausgewertet mit „letzte Zahl nach dem Think-Block“. Die Zählung war meist richtig, aber das Format instabil: bei den 50 Wörtern hatten nur 2 Antworten einen </think>-Block, bei den 28 Aufgaben zeigten 24 die Zählshow der Persona.
² Diese Sätze haben die v3-Trainingsdaten beeinflusst (Fehler früherer Versionen). Für v4 wurden alle Teststrings aus dem Training ausgeschlossen (per Code geprüft), die Aufgabenarten sind aber teils dieselben; belastbarer ist die Zeile „unabhängig“ und die neu geschriebenen Sätze für Buchstaben/Wörter/Chat.
Ehrlicher Vergleich mit v3: Auf den 28 Generalisierungsaufgaben ist v4 schlechter als v3 (20/28 gegen 26/28); v3 wurde gezielt auf die Fehler an genau diesen Aufgaben trainiert, v4 nicht. Dafür ist v4 auf den 40 unabhängigen Strings besser (32/40 gegen 26/40), löst die Wiederholungs-Strings weitgehend, kann Buchstaben und Wörter zählen und redet normal. Bei den 42 frischen Aufgaben und den 50 Wörtern gleichauf. Bei Stichproben dieser Größe sind einzelne Punkte Rauschen.
Unabhängiger Test nach Kategorie
| Kategorie | richtig |
|---|---|
| Englisch | 5/6 |
| Deutsch | 5/6 |
| Code/Syntax | 7/10 |
| Zahlen/Formate | 6/6 |
| Wiederholungen | 5/6 |
| Lang 55-80 | 4/6 |
| Grenzfall | 3/5 |
Antwortlänge
Im Mittel etwa 23 Token pro Zeichen des zu zählenden Textes (längste Antwort im Test: 3200 Token). Für 80 Zeichen max_new_tokens ≥ 3000 setzen.
Einige der falschen Antworten (27 von 225 Zähl-Aufgaben insgesamt falsch)
| Text | Soll | Antwort |
|---|---|---|
I think, therefore I am. | 24 | None (abgebrochen) |
Heute gibt es Käsespätzle mit Röstzwiebe | 43 | 42 |
^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$ | 39 | 33 |
\frac{a}{b} + \sqrt{x^2 + 1} | 28 | 27 |
{"a": {"b": [1, 2, {"c": null}]}} | 33 | 29 |
ZZZZZZZZZZZZZZZZZZZZ | 20 | 21 |
Ich weiß nicht, was soll es bedeuten, da | 62 | 65 |
Lorem ipsum dolor sit amet, consectetur | 71 | 73 |
Καλημέρα κόσμε | 14 | 15 |
Wort mit zwei Leerzeichen | 28 | 25 |
Es scheint, dass sie insgesamt positiv w | 71 | 72 |
KKKKFFF##zzzz111--YYYYY>>>>@@SSS$ | 33 | 32 |
Allgemeine Fähigkeiten (je 100 Aufgaben, Arithmetik 40, gleiche Aufgaben für alle Modelle)
| Test | Original Qwen2.5-7B-Instruct | Geheilt (ohne LoRA) | Hardcore (v2-Daten) | v3 plain | v4 |
|---|---|---|---|---|---|
| GSM8K (100 Textaufgaben) | 98 | 89 | 90 | 89 | 96 |
| MMLU (100) | 82 | 80 | 78 | 78 | 81 |
| ARC-Challenge (100) | 91 | 90 | 90 | 90 | 90 |
| Arithmetik (40) | 32 | 32 | 31 | 31 | 30 |
„Hardcore (v2-Daten)“ und „v3 plain“ sind frühere Trainingsversionen (v3 ist auf Hugging Face). Kleine Stichproben: Unterschiede von wenigen Punkten sind Rauschen.
Wie das Modell entstanden ist
- Vokabular-Amputation: Aus
Qwen/Qwen2.5-7B-Instructwurden alle Token entfernt, in denen ein alphanumerisches Zeichen (ohne Beachtung der Groß-/Kleinschreibung) mehr als einmal vorkommt: 106.915 von 151.665 Token bleiben. Doppelte Buchstaben und Ziffern liegen dadurch an Token-Grenzen. - Heilung: 500 Schritte Continued Pretraining (LoRA, Embeddings und LM-Head mittrainiert) auf deutschen Texten, siehe Davidmg0815/qwen2.5-7b-reduced-vocab-healed.
- v4-Feintuning: LoRA (r=16, alpha=32, alle linearen Schichten), Loss nur auf den Antworten, ohne System-Prompt. Daten (10481 Beispiele):
- Zeichen zählen: 4900
- Buchstabenhäufigkeit: 1500
- Buchstaben insgesamt: 350
- Wörter zählen: 400
- Replay: wortbezogene Fragen ohne Zählauftrag: 272
- Replay: deutsche Chat-Fragen (oasst1): 258
- Replay: ins Deutsche übersetzte Fragen (ultrachat): 854
- Replay: englische Chat-Fragen (ultrachat): 1044
- Replay: GSM8K-Textaufgaben (nur richtig gelöste): 857
- Replay: Smalltalk/Begrüßungen: 46
Zählbeispiele sind rein regelbasiert erzeugt und gegen die bekannte Wahrheit geprüft (Texte: deutsche/englische Wörter und Sätze, Code, Zufalls- und Sonderzeichen-Strings, viele periodische Strings, 46 bis 90 Zeichen). Die Replay-Antworten stammen vom unveränderten
Qwen2.5-7B-Instruct(Selbst-Destillation, damit normales Verhalten erhalten bleibt); GSM8K-Antworten wurden nur behalten, wenn die Endzahl stimmt.
- Änderungen gegenüber v3: keine Persona, kein Trainings-System-Prompt, keine gesprochene Zählshow; zusätzlich Buchstabenhäufigkeit (mit laufendem Zwischenstand
Bisher: k), Buchstaben insgesamt, Wörter zählen und viele periodische Strings gegen die Endlosschleife von v3.
Einschränkungen (bitte lesen)
- Kein Zähl-Rekordmodell. Moderne Denk-Modelle (z. B. Gemma 4, Nemotron) zählen im selben Aufgabentyp besser und viel billiger in Token. Dieses Modell ist ein Experiment: ein lokales 7B, das den Zählvorgang sichtbar aufschreibt.
- Kleine, selbst geschriebene Tests. 30 bis 100 Aufgaben pro Gruppe, eine Probe pro Aufgabe, Greedy. Die Testaufgaben stammen vom selben Autor wie die Trainingsgeneratoren; auch wenn kein Teststring im Training vorkommt, ähneln sich die Aufgabenarten.
- Antworten sind lang (≈23 Token pro Zeichen) und das Modell braucht einen großzügigen Token-Limit (≥ 3000 für 80 Zeichen).
- Nicht-lateinische Schriften (Kyrillisch, Griechisch, CJK) und Mehrfach-Leerzeichen waren nicht Teil des Trainings; Emoji ebenso. Das Vokabular ist reduziert (106.915 statt 151.665 Token) und nicht mit dem Original-Qwen-Tokenizer austauschbar.
- Allgemeine Fähigkeiten etwas schwächer als beim Original (Mathe-Textaufgaben besonders), siehe Tabelle. Das Replay hält das Chat-Verhalten, kann den Verlust durch die Vokabular-Amputation aber nicht ausgleichen.
- Zählen ist Formatbindung: Das Modell löst das Zählformat bei Fragen der Form „Wie viele Zeichen/Buchstaben/Wörter …“ aus. Andere Formulierungen (z. B. „Ist der String länger als 20?“) wurden nicht getestet und können ins normale Antworten kippen.
- Restfehler: siehe Tabelle der falschen Antworten. Typisch sind ausgelassene oder doppelte Positionen in langen Strings und Verwechslungen bei Bindestrich-/Punktfolgen (der Spreiz-Trenner
-enthält selbst einen Bindestrich). - Chat-Sanity: 27/30 der 30 Chatfragen bestanden (passende Antwort ohne
<think>-/Persona-Reste; 0 Antworten enthielten trotzdem einen Think-Block). Von den drei „Fehlschlägen“ ist einer ein Fehlalarm meines Tests (die Antwort zur Einwohnerzahl von Berlin enthielt das Wort „Bevölkerungszählung“, das die Suche nach dem Marker „Zählung“ auslöste); ich habe das Kriterium nachträglich nicht geändert, die Antwort war inhaltlich in Ordnung. Die anderen zwei sind echte Fehler: „Good moring“ (Tippfehler) bei der Übersetzung von „Guten Morgen“ und „Schiffahrt“ statt „Schifffahrt“ bei der Frage nach der richtigen Schreibweise (das Modell schreibt Dreifach-Konsonanten gerade dort falsch, wo man es testet). - Kriterien knapp erreicht: C1 (32/40) und C5 (27/30) liegen genau auf der vorab festgelegten Schwelle. „Bestanden“ heißt hier nur „nicht schlechter als die vorab gesetzte Untergrenze“.
- Endlosschleife in einem Fall: Bei
I think, therefore I am.erzeugte das Modell endlos<think>(kein Abbruch, 1 von 45 unabhängigen Strings, insgesamt 3 von 225 Antworten ohne sauberes Format). Lange Token-Limits ohne Abbruchlogik im Client können dann sehr viele Token verbrauchen. - Empfindlich gegenüber der Frageform: „Zähl mal bitte 'Kühlschrank' durch“ wurde als Buchstabenhäufigkeit von „bitte“ missverstanden (Antwort 0), eine mehrdeutige Frage („Länge von Bettlaken?“, gemeint als Zentimeter) wurde als Zählaufgabe behandelt. Feste Formulierungen wie „Wie viele Zeichen hat …“ / „Wie viele r sind in …“ funktionieren am zuverlässigsten.
Daten, Lizenz und Danksagung
- Lizenz: Apache-2.0 (wie das Basismodell
Qwen/Qwen2.5-7B-Instruct; dieses Modell ist eine Ableitung). - Daten und Skripte: Davidmg0815/spreizzaehler-daten. Prompt-Quellen des Replay:
OpenAssistant/oasst1(Apache-2.0),HuggingFaceH4/ultrachat_200k(MIT; dessen Texte wurden ihrerseits mit einem Chat-Modell erzeugt),openai/gsm8k(MIT). Die Antworten erzeugteQwen2.5-7B-Instruct. Beispielsätze für Zählaufgaben stammen teils auspdelobelle/fineweb-german-edu-mt(abgeleitet von FineWeb-Edu, ODC-By 1.0). - Heilungstexte:
pdelobelle/fineweb-german-edu-mt. Danke an das Qwen-Team, Unsloth, Hugging Face (transformers,peft,trl) und das llama.cpp-Projekt.