Strukturierte Verhaltensaufnahme für Qwen-Modelle auf ARC-AGI-2.
Nicht: „auf welchen Puzzles ist das Modell gut und auf welchen schlecht". Sondern: wo tut es etwas, das man nicht vorhersagen könnte — und woran hängt das.
Eine Genauigkeitszahl über 120 Puzzles sagt fast nichts darüber, was ein Modell eigentlich tut. Sie kann nicht unterscheiden zwischen
- „hat die Regel verstanden und einen Rechenfehler gemacht",
- „hat die Test-Eingabe abgeschrieben",
- „ist mitten in der Antwort ins Chinesische gekippt",
- „hat mit maximaler Sicherheit Unsinn produziert",
- „hat dasselbe Puzzle in Blau gelöst und in Rot nicht".
Der letzte Punkt ist der Hebel. Nimm ein Puzzle und lege es dem Modell mehrfach vor — umgefärbt, transponiert, mit vertauschten Beispielen, in anderer Notation. Transformationen, die das Puzzle nicht verändern. Wer die Regel verstanden hat, antwortet überall gleich. Wer an Oberflächenmerkmalen hängt, antwortet unterschiedlich — und welche Ansicht kippt, sagt genau, woran er hing.
Das ist die Invarianz-Batterie, der Kern dieses Pakets. Zwei Eigenschaften machen sie zum Arbeitspferd:
- Sie braucht keine Lösungen. Ein Widerspruch zwischen zwei Ansichten desselben Puzzles ist ein Widerspruch, egal ob eine davon richtig war. Das funktioniert auf dem unbeschrifteten Wettbewerbs-Test-Split.
- Sie findet das Unerwartete. Ein Puzzle unter einer Farbpermutation zu lösen und unter einer anderen nicht, ist genau die Sorte Befund, auf die man nicht käme, wenn man nicht danach gesucht hätte.
Darüber liegen zwei weitere Schichten: benannte Regeldetektoren für das, was man schon kennt, und eine unüberwachte Schicht (Isolation Forest über alle Verhaltenssignale) für das, wofür niemand eine Regel geschrieben hat.
pip install -e .
rqwen run --config configs/smoke.yaml
cat runs/smoke-*/report.mdDas läuft gegen ein deterministisches Mock-Modell auf zwölf synthetischen Mini-Puzzles und erzeugt einen vollständigen Bericht. Der Bericht sagt nichts über irgendein echtes Modell — er zeigt, was die Pipeline misst und wie das Ergebnis aussieht. Das Mock spritzt bekannte Pathologien in bekannten Raten ein; genau daran sind die Detektoren getestet.
notebooks/rqwen_colab_a100.ipynb — Laufzeit
auf A100 + Hoher Arbeitsspeicher stellen, Zellen der Reihe nach ausführen.
Installiert vLLM, lädt ARC-AGI-2, zeigt den Versuchsplan, läuft, sichert nach
Drive.
Auf Colab ist Session-Zeit die knappe Ressource, nicht GPU-Speicher. Daraus
folgen drei Dinge, die die Configs colab_a100_*.yaml bereits setzen:
run.batch_size: 32— vLLM überlappt Prefill und Decode über Anfragen hinweg. Sequenziell würde eine A100 zu über 90 % leerlaufen, und die Invarianz-Batterie liefert mit vielen fast identischen Prompts je Puzzle genau die passende Last.run.max_runtime_s: 37800(10,5 h) — läuft das Budget ab, hält der Lauf sauber zwischen zwei Batches an und analysiert und berichtet, was da ist. Ohne das kostet ein Abschuss bei Stunde 11 die gesamte Auswertung.Ausführung unterbrechenwirkt genauso.out_dir: /content/runs— lokale SSD, nicht Drive. Der Blob-Store legt viele kleine Dateien an; gemountetes Drive ist dafür sehr langsam. Das Notebook archiviert am Ende einmal dorthin.
Fortsetzen nach Abbruch: rqwen run --config <cfg> --resume --run-id <id>.
Modellwahl für 40 GB, kurz: Qwen3-8B in bf16 ist der Startpunkt (~16 GB
Gewichte, ~20 GB KV-Cache, volle Batterie bequem im Budget). Qwen3-32B passt nur
4-bit-quantisiert und ist deutlich langsamer. Vollständige Tabelle samt
KV-Cache-Rechnung in docs/colab.md.
git clone --depth 1 https://github.com/arcprize/ARC-AGI-2 /tmp/arc2
mkdir -p data/arc-agi-2
cp -r /tmp/arc2/data/{training,evaluation} data/arc-agi-2/
rqwen validate-data --data data/arc-agi-2Das Kaggle-Layout (arc-agi_*_challenges.json + *_solutions.json) wird
genauso erkannt. Details in data/README.md.
rqwen plan --config configs/qwen_vllm.yamlDie Batterie multipliziert die Aufrufzahl. plan macht das sichtbar, solange es
noch änderbar ist.
rqwen run --config configs/qwen_vllm.yaml --resumeMitgelieferte Configs:
| Datei | Backend | Wofür |
|---|---|---|
configs/smoke.yaml |
Mock | Sekunden, kein Setup |
configs/colab_a100_qwen3_8b.yaml |
vLLM | Colab A100 40 GB, gebatcht, mit Zeitbudget |
configs/colab_a100_qwen3_32b_awq.yaml |
vLLM | Colab A100, 32B in 4 Bit |
configs/colab_a100_qwen3_8b_hf.yaml |
HF lokal | Colab-Plan-B ohne vLLM: läuft immer, ~10x langsamer |
configs/qwen_vllm.yaml |
vLLM offline | schnellster Weg für eine ganze Batterie auf einer Maschine |
configs/qwen_api.yaml |
OpenAI-kompatibel | vLLM-Server, DashScope, OpenRouter, Ollama, LM Studio |
configs/qwen_hf_full_battery.yaml |
HF lokal | volle Batterie, reichste Telemetrie |
rqwen report --run <run_id> --stdout
rqwen inspect --run <run_id> --episode <episode_id> --promptinspect zeigt Prompt, Rohausgabe und alle Funde einer Episode im Volltext.
Der Bericht verlinkt die auffälligsten Episoden direkt mit dem passenden
Befehl.
Neun Familien, rund 40 Codes. Vollständig in
docs/anomalie-taxonomie.md, maschinenlesbar über
rqwen taxonomy --json. Ein Auszug dessen, was ohne Lösungen funktioniert:
| Code | Was er zeigt |
|---|---|
INS_COLOR_FRAGILE |
Antwort kippt bei Farbpermutation — das Modell hing an Farbwerten, nicht an Struktur. |
INS_GEOM_FRAGILE |
Antwort kippt bei Transposition — die Kompetenz hängt an der Orientierung. |
INS_ORDER_FRAGILE |
Antwort kippt bei umsortierten Beispielen — Recency statt Regel. |
INS_FORMAT_FRAGILE |
Antwort kippt bei anderer Notation — die Kompetenz hängt an der Tokenisierung. |
INS_ANTI_INVARIANCE |
Falsch beim Original, richtig unter der Störung. |
CPY_CROSS_TASK |
Antwort auf Puzzle A ist ein Gitter aus Puzzle B: Kontextverschleppung. |
THK_UNCLOSED |
Das Token-Budget ging komplett in den Denkblock, eine Antwort kam nie. |
LNG_SCRIPT_DRIFT |
Mitten in der englischen Antwort ins Chinesische gekippt. |
UNS_MULTIVARIATE_OUTLIER |
Signatur unähnlich zu allem im Lauf, ohne auffälliges Einzelsignal. |
UNS_RARE_COMBINATION |
Code-Kombination, die sonst kein einziges Mal vorkommt. |
Mit Lösungen kommen unter anderem CAL_CONFIDENT_WRONG (maximale Sicherheit
bei falscher Antwort) und INS_ANTI_INVARIANCE dazu.
Der Bericht sagt zu Beginn, welche Codes im jeweiligen Lauf gar nicht auslösen konnten. Eine 0 dort heißt nicht gemessen, nicht nicht aufgetreten. Ohne diese Zeile wäre jede Zählung irreführend.
runs/<run_id>/
manifest.json Config, Git-Commit, Modellbeschreibung, Provenienz
episodes.jsonl eine Zeile je Modellaufruf — der eigentliche Datensatz
anomalies.jsonl eine Zeile je Fund, denormalisiert für Auswertungen
cells.jsonl Zellen, aggregiert über die Stichproben
blobs/ inhaltsadressierte Prompts und Rohausgaben
report.md der Bericht
Der Bericht hat sieben Abschnitte: was messbar war → Grundzahlen → Anomalien nach Code → Invarianz-Batterie → auffälligste Puzzles → Anomalierate nach Puzzle-Eigenschaft → die überraschendsten Episoden.
Der letzte Abschnitt sortiert nach Schwere und Seltenheit. Was oft passiert, rutscht nach unten. Eine Liste nach reiner Häufigkeit würde von den langweiligen Fällen angeführt — und die sind nicht die Frage.
Das ist die wichtigste Struktureigenschaft.
rqwen run --config ... # teuer, einmal
rqwen analyze --run <id> # Sekunden, beliebig oftDie Taxonomie wird wachsen — jedes Mal, wenn jemand einen Bericht liest und
sagt „das da ist auch merkwürdig". Ein neuer Detektor kostet dann einen
analyze-Lauf über bereits vorhandene Episoden, keine GPU-Stunden.
Wer auch den Parser ändern will: der replay-Runner spielt gespeicherte
Rohausgaben erneut ab, byte-identisch, abgeglichen über den Prompt-Hash.
src/rqwen/
arc/ ARC laden, Gitteroperationen, Strukturmerkmale
prompts/ sieben Notationen, vier Templates
perturb.py die Invarianz-Batterie
runners/ mock · openai_compat · hf_local · vllm · replay
parse.py Gitter aus Freitext bergen, Fehlermodus protokollieren
telemetry.py Text-, Token- und Prozesssignale
detect/ registry (Taxonomie) · rules · consistency · unsupervised
store.py append-only, fortsetzbar, inhaltsadressiert
report.py Bericht
Der Kern kommt ohne Fremdbibliotheken aus — reine Standardbibliothek, inklusive
Isolation Forest. Das ist kein Purismus: es hält die Pipeline in einem
Offline-Kaggle-Notebook lauffähig, wo kein pip install möglich ist. Torch,
transformers und vLLM hängen hinter optionalen Extras und optionalen Importen.
pip install -e '.[hf]' # transformers lokal
pip install -e '.[vllm]' # vLLM offline
pip install -e '.[dev]' # Tests
pytest146 Tests, Laufzeit ~6 Sekunden, keine GPU nötig.
- Die Kaggle-Notebooks konnten nicht gelesen werden. Die Wettbewerbsseite liefert für automatisierte Zugriffe HTTP 403. Das Paket ist deshalb bewusst runner-agnostisch: welches Qwen-Setup dort auch immer läuft, es lässt sich über eines der vier Backends anschließen, ohne dass die Pipeline etwas über seine Interna wissen muss.
- Die Entropie ist eine Untergrenze. Sie wird aus den Top-k-Alternativen
berechnet. Für Vergleiche innerhalb eines Laufs reicht das; als absoluter Wert
ist sie nicht zu lesen. Deshalb heißen die Felder
entropy_topk_*. - Ein Invarianzbruch sagt nicht, welche Ansicht recht hat. Er sagt, dass sich zwei widersprechen. Ohne Lösung ist das eine Inkonsistenz, kein Fehler.
- Bei
temperature > 0ist ein Teil jeder Abweichung Sampling-Rauschen. Die Analyse aggregiert über die Versuche einer Zelle zur Mehrheitsantwort und berichtet das Rauschen separat alsINS_SEED_UNSTABLE. Ab drei Versuchen pro Zelle sind die beiden Effekte sauber getrennt; mitattempts: 1sind sie es nicht, und die Config-Prüfung sagt das. data/sample/ist synthetisch. Zwölf Mini-Puzzles für Tests und den Smoke-Lauf, kein Ersatz für ARC.- Die Schwellwerte sind Startwerte, keine kalibrierten Konstanten. Sie
stehen in
DEFAULT_THRESHOLDS, sind per Config überschreibbar, und der Bericht nennt die Messung, die einen Fund ausgelöst hat — damit jeder Befund bis zum Schwellwert zurückverfolgbar ist.
docs/anomalie-taxonomie.md— alle Codes, warum sie zählen, woran sie scheiterndocs/pipeline.md— Architektur, Datenschema, Frames, eigenes Backend anschließendata/README.md— Datenlayouts