Halogen auf Strix Halo
Halogen ist eine proprietäre Inferenz-Engine von peonist-ai, gebaut für gfx1151. Auf dem Ryzen AI Max+ 395 liegt sie beim Prefill klar vor llama.cpp — beim Decode nur knapp. Und sie unterstützt genau ein Modell. Diese Seite sortiert, was davon für den eigenen Betrieb zählt: gemessene Zahlen, die Cache-Fixes der 0.11.x-Reihe, die Fallstricke und der Update-Ablauf.
Einordnung
Lohnt sich, wenn …
- ✓Langer Kontext, viele Turns, Agenten-Fan-out
- ✓Prefill-dominierte Workloads (große System-Prompts, Repo-Kontext)
- ✓Lizenz muss kostenlos und kommerziell nutzbar sein
Lohnt sich nicht, wenn …
- ✕Mehr als ein Modell nötig
- ✕Offene Engine, selbst patchbar, nachvollziehbar
- ✕Kurze Einzel-Chats mit kleinem Kontext
Steckbrief
- ✓Perpetual-Lizenz, kostenlos
- ✓kommerzielle Nutzung erlaubt
- ✓keine Telemetrie
- ·Qwen3.8-Flash-Next
Mehr ist es nicht. Wer ein zweites Modell braucht, bleibt bei llama.cpp oder Ollama.
Leistung: Halogen gegen llama.cpp
| Kennzahl | Kontext | Halogen | llama.cpp | Faktor |
|---|---|---|---|---|
| Prefill | 12k Tokens Prompt | 1.340 t/s | 413 t/s | 3,2× |
| Decode | Token-Ausgabe | 33,5 t/s | 26,1 t/s | 1,28× |
Der eigentliche Gewinn. Agenten hängen am ersten Token — hier entscheidet sich, ob ein Turn mit langem System-Prompt Minuten oder Sekunden kostet.
Spürbar, aber nicht dramatisch. Wer nur chattet, merkt davon wenig; der Unterschied summiert sich erst bei langen Antworten.
Prompt-Cache: der eigentliche Grund für die Updates
Determinismus-Bug im Cache
Ein kalter Request lieferte nicht dasselbe Ergebnis wie derselbe Request mit deaktiviertem Cache.
Bei temperature > 0 führte das zu plausibel klingenden Falschantworten. Nichts crasht, nichts loggt — die Antwort ist einfach still falsch.
Cache-Pfad und Nicht-Cache-Pfad verhalten sich identisch.
Cache-Verdrängung bei parallelen Konversationen
Zwei lange parallele Konversationen und Fan-out-Muster (ein Eltern-Agent mit mehreren Kind-Agenten) passten nicht nebeneinander in den Cache.
Bei jedem Turn wurde komplett neu geprefillt: 100 bis 160 Sekunden pro Turn. Eltern und Kinder warfen sich gegenseitig aus dem Cache.
99 Prozent Cache-Treffer in denselben Szenarien.
| Version | Bereich | Was passierte |
|---|---|---|
| 0.11.0 | Token-Budget | Engine reserviert selbst Antwortraum (thinking_answer_room) — entschärft das Problem mit den Denk-Tokens gegen max_tokens. |
| 0.11.3 | Cache | Determinismus-Bug behoben (kalter Request ≠ Ergebnis mit deaktiviertem Cache). |
| 0.11.5 + 0.11.7 | Cache | Cache-Verdrängung bei parallelen Konversationen und Fan-out behoben: von 100–160 s pro Turn auf 99 % Treffer. |
| 0.11.6 | Modellformate | Liest zusätzlich K-Quant GGUF, nicht nur das eigene .hgn-Format. |
| 0.11.9 | Speicher | GTT-Leak behoben: 35 GiB blieben nach unsauberem Abbruch im Kernel hängen. |
Fallstricke im Alltag
KV-Pool kleiner als Kontext
Der Container beendet sich beim Start mit Exit 1. Ohne Meldung, was genau fehlt.
HALOGEN_KV_POOL_POSITIONS muss größer oder gleich HALOGEN_CTX sein. Beide Werte gehören zusammen geprüft, bevor der Start überhaupt Sinn ergibt.
Denk-Tokens fressen das Antwortbudget
Standard-reasoning_effort ist xhigh. Die Denk-Tokens zählen gegen max_tokens — ohne chat_template_kwargs kommt leerer Content zurück.
Entweder reasoning_effort explizit setzen und max_tokens großzügig bemessen, oder ab 0.11.0 auf thinking_answer_room verlassen: die Engine reserviert den Antwortraum selbst.
localhost löst auf IPv6 auf
Clients bekommen Connection error. Auf vielen Distributionen löst localhost nur auf ::1 auf, die Engine lauscht aber auf IPv4.
In Client-Konfigurationen 127.0.0.1 statt localhost schreiben. Kostet eine Zeile Konfiguration und spart die halbe Stunde Fehlersuche.
Das model-Feld wird ignoriert
Beliebige Werte im model-Feld des Requests funktionieren kommentarlos. Der Client glaubt, mit einem anderen Modell zu reden.
Nicht als Modell-Weiche missbrauchen wollen. Was geliefert wird, steht in der Server-Konfiguration, nicht im Request.
Kein Parallelbetrieb mit llama.cpp
Halogen und llama.cpp schließen sich gegenseitig aus, wenn beide denselben Port und den Grafikspeicher beanspruchen.
Umsteigen heißt abschalten. Ein Side-by-Side-A/B über beide Engines hinweg erfordert getrennte Ports und genug Speicher für beide — oder zwei Startvorgänge nacheinander.
Betrieb: Update im laufenden Betrieb
- 1Neues Image ziehen
Läuft 4,5 Minuten, ohne den laufenden Container zu stören.
- 2Alten Container parken statt löschen
Hält den Rollback verfügbar, bis der neue bewiesen ist.
- 3Neuen Container starten
/health antwortet — Version, Slots, Pool-Größe und Kontext abgleichen.
- 4Echten Completion-Request absetzen
Health allein reicht nicht. Es muss ein echter Prompt durch, der Content muss stimmen.
- 5Bei Fehlern zurückrollen
Den geparkten Container wieder starten, Problem am neuen Image suchen.
| Kennzahl | Wert | Kontext |
|---|---|---|
| Downtime beim Rolling-Update | 26 s | Gemessen von altem Container weg bis neuer Container bedienbar. |
| Image-Pull | 4,5 min | Läuft parallel zum laufenden Betrieb, unterbricht nichts. |
| Health-Endpunkt | /health | Liefert Version, Slots, Pool-Größe und Kontext. |