Praxistipp: Open-Source LLMs auf Zephyr OS Finetunen
Teil 1 der Serie: LLMs auf Zephyr OS finetunen Ganze Serie
Wir wollen ein Open-Source-LLM auf Zephyr OS fine-tunen
"Der längste Weg beginnt mit dem ersten Schritt." — Laotse
Wir sind uns sicher, dass wir künftig viel mehr Prototypen in Zephyr OS entwickeln. Denn das ist viel einfacher, als ständig kleine, neue Elektroniken aufzubauen. Wie aber können wir unsere Arbeit mit Zephyr OS verbessern, wenn wir agil Hardware entwickeln?
Ein Projekt, das wir aktuell verfolgen, ist die Schaffung eines internen, auf Zephyr OS spezialisierten Large Language Models (LLM). Dieses Open-Source-Modell soll unseren Entwicklerinnen und Entwicklern künftig als intelligenter Assistent zur Seite stehen und beim Programmieren sowie beim Hardware-Design im komplexen Zephyr OS-Umfeld unterstützen.
Weitere Vorteile eines eigenen LLMs:
- keine laufenden Abogebühren
- keine Datenschutz- und NDA-Probleme (weil ja alles lokal läuft und nichts hochgeladen wird)
- LLM kann auch unbeschränkt laufen (wie das LLM reagiert, können wir hier einstellen)
- unabhängig von aussen (weitestgehend zumindest)
Warum ein eigenes Zephyr-LLM?
Generische LLMs wie ChatGPT, Llama oder Mistral sind beeindruckend (das unten aufgeführte Skript zum Webcrawlen entstand mit viel Hilfe von Gemini), neigen jedoch in spezialisierten Domänen wie der Embedded-Entwicklung oder einem spezifischen RTOS wie Zephyr OS zu sogenannten "Halluzinationen" – sie erfinden plausible, aber faktisch falsche Informationen. Das hilft uns natürlich nicht beim agilen Aufsetzen von Prototypen.
Durch das Fine-Tuning eines Open-Source-LLM auf einer maßgeschneiderten, selbst zusammengesuchten Datenbasis wollen wir ein Modell schaffen, das Zephyr OS wirklich "versteht" und präzise, domänenspezifische Antworten liefert.
Weitere Ideen zum Fine-Tunen sind andere RTOS, die Dokumentation von Arduino eventuell, oder die Dokumentationen von Alitum Designer oder KiCAD, um einen Agenten zu haben, der einem beim PCB-Design hilft.
Wir sammeln Daten mit unserem "ki-data-crawler"
Der erste Schritt auf diesem Weg ist Daten sammeln fürs Anlernen. Dafür haben wir einen spezialisierten Web-Crawler zusammengefummelt, den wir unter alpha-board-Github: ki-data-crawler als Open-Source-Projekt veröffentlicht haben.
Aktuell hat der Crawler gerade die gesamte offizielle Zephyr OS Dokumentation durchforstet. Die gesammelten Daten werden in einer großen JSON Lines-(JSONL)-Datei gespeichert. Dieses Format passt gut für Daten zum Anlernen von LLM-Modellen.
Das exakte Finden der benötigten Informationen in der ganzen HTML-Buchstabensuppe ist nicht einfach (und setzt u.a. auf die Python-Bibliothek Beautiful Soup). Manchmal entgeht uns was, manchmal kommt nach dem Bereinigen um doppelte Leerzeichen und ähnliches nichts Verständliches mehr heraus. Wir überlegen gerade, ob wir nun auch noch die Pythonbibliothek Scrapy verwenden und testen das gerade.
Wie kommen die Daten ins LLM?
Sobald die JSONL-Datei vollständig ist, dient sie als primäre Input-Quelle für unser Fine-Tuning. Der Prozess läuft im Wesentlichen so ab:
- Vortrainiertes Basis-LLM: Wir wählen ein bestehendes, leistungsfähiges Open-Source-LLM (z.B. aus der Llama-Familie oder Mistral) als Ausgangsbasis. Dieses Modell besitzt bereits ein breites allgemeines Sprachverständnis.
- Fine-Tuning: Die JSONL-Datei, die Zephyr-spezifisches Wissen enthält (Code-Beispiele, API-Beschreibungen, Erklärungen), wird diesem Basis-LLM präsentiert. Das Modell "lernt" dann aus diesen Daten und passt seine internen Parameter so an, dass es besser auf Fragen zu Zephyr OS reagiert und Code-Beispiele im Zephyr-Stil generiert. Hierfür kommen effiziente Methoden wie LoRA (Low-Rank Adaptation) oder QLoRA zum Einsatz.
Unsere Hardware-Basis fürs Fine-Tunen von LLMs
Für das ressourcenintensive Fine-Tuning und den späteren lokalen Betrieb des LLMs haben wir uns für den neuen Apple M4 Max Prozessor mit 128 GB Unified RAM entschieden. Andere Rechner für KI/LLM sind schneller, insbesondere wenn sie sehr neue, teure Grafikkarten von Nvidia nutzen. Aber die Geräte von Apple haben einen anderen Vorteil: sie schafffen durch ihre Architektur einen Unified RAM, der aus RAM und VRAM besteht. Denn ein LLM muss komplett im Speicher sein, um zu arbeiten.
Und die Größe eines LLM-Modells wird hauptsächlich durch die Anzahl der Parameter (übersetzt: Neuronen) und der Länge der Bytes für den Trigger des Neurons, sozusagen. Es gibt welche mit sehr langen Gleitpunktzahlen und andere mit viel kürzeren, ungenaueren, sogenannten quantifizierten Triggern.
Die Größe eines Modells in Byte oder Gigabyte lässt sich grob berechnen als:
$$\text{Modellgröße (in Byte)} = \text{Anzahl der Parameter} \times \text{Bytelänge pro Parameter} + \text{20% für Overhead} $$
Beispiel: 7B-Modell (7 Milliarden Parameter) im FP32-Format:
$$7 \times 10^9 \text{ Parameter} \times 4 \text{ Byte/Parameter} \times 1.2 = 28 \times 10^9 \text{ Byte} \times 1.2 \approx 33,6 \text{ GB}$$
Wir wollen viele Parameter und idealerweise auch keine quantifizierten Modelle. Zudem planen wir, intern zwei Modelle zur Verfügung zu stellen: einen Code-Agent und einen Agent für Reasoning. Daher also großzügige 128GB RAM.
Geplanter Software-Stack fürs Fine-Tuning und Hosting
Auf unserer neuen Hardware werden folgende Programme zum Einsatz kommen:
- Fine-Tuning: Hier setzen wir auf bewährte Python-Bibliotheken aus dem Hugging Face Ecosystem, insbesondere die transformers-Bibliothek in Kombination mit PEFT (Parameter-Efficient Fine-Tuning) und speziellen Optimierungen für Apple Silicon wie das MLX Framework. Dies ermöglicht es uns, selbst große Modelle auf dem verfügbaren Unified RAM effizient anzupassen.
- Hosting des LLM: Für den lokalen Betrieb und die Interaktion mit dem feinabgestimmten Modell kommt LM Studio zum Einsatz. LM Studio bietet eine benutzerfreundliche Oberfläche, um LLMs schnell zu laden, mit ihnen zu chatten und ihre Parameter anzupassen und im internen Netz zur Verfügung zu stellen.

Was wir so gelernt haben beim Datensammeln
Natürlich gab und gibt es auf diesem Weg einige spannende Herausforderungen, an denen wir viel lernen:
- HTML-Selektoren und Text-Extraktion: Das Finden des "richtigen" Textes in komplexen Webseitenstrukturen (insbesondere bei Doxygen-generierter API-Dokumentation) war eine knifflige Aufgabe. Wir mussten eine Reihe von Fallback-Selektoren implementieren, um sicherzustellen, dass der gesamte relevante Inhalt sauber erfasst wird.
- robots.txt beachten: Als "gute Bürger" des Internets respektiert unser Crawler die robots.txt-Dateien der Zephyr-Dokumentation. Dies stellt sicher, dass wir nur Bereiche crawlen, die dafür vorgesehen sind, und unnötige Last auf den Servern vermeiden. Dies bedeutet aber auch, dass wir manche ältere Dokumentationsversionen nicht erfassen.
- Geschwindigkeit und Robustheit: Um den Crawling-Prozess effizient und zuverlässig zu gestalten, mussten wir Techniken wie requests.Session() für wiederverwendbare HTTP-Verbindungen, das Setzen von User-Agent-Headern und einen robusten Mechanismus für MAX_RETRIES (maximale Wiederholungsversuche bei Fehlern) implementieren. So stellen wir sicher, dass temporäre Netzwerkprobleme oder nicht erreichbare Links den Crawl nicht stoppen. URLs, die dauerhaft nicht erreichbar sind, werden in einer separaten Log-Datei dokumentiert.
- Was wir vorerst ausklammern: Um den Fokus zu wahren, konzentrieren wir uns zunächst auf die Kern-Dokumentation. Später wollen wir das Projekt erweitern, um auch den Zephyr OS Quellcode, Modul-Repositories, Open-Source-Projekte auf GitHub, Mailinglisten und Foren in die Datenbasis einzubeziehen. Auch das Thema der Bildanalyse (OCR) klammern wir vorerst aus.
Wir sind gespannt, wie gut das Fine-Tunen eines LLMs auf Zephyr OS klappen wird. Mehr dazu in den nächsten Folgen dieser Serie.