Ein lokales LLM ohne GPU: was mich ein Jahr Ollama auf einem alten i5 gelehrt hat
Sechs Kerne, 32 GB RAM, keine GPU — und Sprachmodelle, die zu Hause wirklich arbeiten: Alerts zusammenfassen, einen Heim-Agenten betreiben, nach Bedeutung suchen. Über Modellauswahl, Temperaturen und Fallen, die in keinem Tutorial stehen.

Wozu ein langsames Modell, wenn die Cloud schnell ist
Die kurze Antwort: weil die Prompts das Haus nicht verlassen. Mein Heim-Agent liest Server-Alerts, die Notizen der Familie und den Zustand der Geräte — genau die Art von Daten, die ich an keine externe API schicken will, egal wie günstig sie ist. Dazu kommt Berechenbarkeit: Ein lokales Modell ändert keine Preisliste, verschwindet nicht aus dem Angebot und fängt nicht plötzlich an, anders zu antworten, weil jemand auf der anderen Seite die Version ausgetauscht hat.
Die lange Antwort füllt den Rest dieses Beitrags, denn ein lokales LLM ohne ist eine Kette von Kompromissen — und über die schreiben Tutorials, die bei ollama run enden, selten.
Hardware: die Ernüchterung ist eingeplant
Mein Server ist ein Intel i5-8500 — sechs Kerne von 2018 — mit 32 GB RAM. Keine GPU. Auf dieser Hardware betreibt heute mehrere Modelle, jedes mit eigener Aufgabe:
| Modell | Größe | Tempo auf CPU | Rolle |
|---|---|---|---|
| phi4-mini | 2,5 GB | ~8 Tok/s | Klassifikation von Alerts |
| gemma4:e4b | 9,6 GB | ~5 Tok/s | Heim-Agent mit Tools |
| qwen3-embedding 0.6b | 639 MB | unter einer Sekunde | Embeddings für die Suche |
| Bielik 4.5B | 5,1 GB | ~4 Tok/s | polnische Alert-Benachrichtigungen |
Diese Zahlen setzen Erwartungen besser als jeder Benchmark aus dem Internet. Acht Tokens pro Sekunde bedeuten: Eine Alert-Zusammenfassung entsteht in zehn bis einigen Dutzend Sekunden. Eine Kuriosität in der Tabelle: gemma4:e4b belegt fast 10 GB auf der Platte und generiert trotzdem schneller als das deutlich kleinere, dichte 4B-Modell, das ich vorher benutzt habe — weil es eine MoE-Architektur ist und immer nur ein Teil der Parameter aktiv arbeitet. „Größere Datei“ heißt nicht mehr „langsamer“.
Der Agent mit Tools brauchte früher ~250 Sekunden für eine Anfrage mit einem einzigen Tool. Heute dauert dasselbe Gespräch ~30 Sekunden — nicht wegen eines neuen Modells, sondern wegen des umgebauten Wegs und des Prompt-Caches, dazu gleich mehr. Ein Kaltstart, wenn das Modell erst in den Speicher lädt, kommt obendrauf.
Die schmerzhafteste Lektion betraf allerdings nicht das Generieren, sondern das Lesen. Mein persönlicher Agent bekam einmal einen ausufernden System-Prompt — rund zweitausend Tokens an Instruktionen. Auf der CPU dauerte allein die Verarbeitung des Prompts über vier Minuten, bevor das Modell das erste Wort schrieb. Auf einer GPU merkt das niemand; auf der CPU ist Prompt-Länge ein realer Preis, fällig bei jedem einzelnen Gespräch.
Fällig — außer du lernst, den Prompt-Cache zu nutzen. Ollama kann sich das erneute Durchrechnen des Gesprächsanfangs sparen, solange er Byte für Byte identisch mit der vorherigen Anfrage ist. Bei mir funktionierte das lange nicht, weil ich an jede Nutzernachricht einen frischen Kontextblock geklebt habe — der Prompt lief direkt hinter der Systeminstruktion auseinander und der Cache hatte nichts zu treffen. Nachdem der Kontext in den stabilen Teil des Prompts umgezogen war, verarbeitet sich die zweite und jede weitere Gesprächsrunde in neun Sekunden statt hundertvier. Dieselbe Maschine, dasselbe Modell, ein zwölffacher Unterschied.
Drei kleine Modelle statt eines großen
Der erste Reflex ist immer derselbe: das größte Modell nehmen, das in den RAM passt. Mein größter Anfängerfehler — denn „es passt“ und „es ist brauchbar“ sind zwei verschiedene Dinge. Ein 11B-Modell läuft auf der CPU technisch. Praktisch: Du hast Zeit, Tee zu kochen (vorher noch das Lagerfeuer zu entfachen), bevor es einen Satz beendet.
Stattdessen funktioniert bei mir Arbeitsteilung. Das schnelle phi4-mini klassifiziert Monitoring-Alerts, und Bielik macht daraus kurze polnische Benachrichtigungen — beides enge, repetitive Aufgaben, für die kleine Modelle völlig reichen. Gemma 4 E4B führt den Heim-Agenten, weil es in meinen Tests Tools am zuverlässigsten aufruft: Es verliert keine Pflichtargumente und erfindet keine Funktionen, die es nicht gibt. Und qwen3-embedding verwandelt Notizen und das Gedächtnis des Agenten in Vektoren — dadurch sucht die Suche nach Bedeutung statt nach Stichwörtern, und das im Bruchteil einer Sekunde.
Bei den Embeddings wartete eine Falle, die kein Model Card offen ausspricht: qwen3-embedding ist ein asymmetrisches Modell. Dokumente kodierst du ohne alles, Anfragen brauchen dagegen ein spezielles Instruktions-Präfix — ohne das kann das Ranking absurd werden: Auf die Frage „was trinkt er gern“ landete eine Notiz über ein Nutella-Glas über dem eigentlichen Fakt zum Kaffee. Ein Präfix im Code, und die Reihenfolge kehrt zur Vernunft zurück. Wenn deine Suche nach einem Wechsel des Embedding-Modells plötzlich „verblödet“ — fang dort an.
Bielik — das polnische Modell von SpeakLeash — habe ich in der 4.5B-Version getestet, mit dem Gedanken, phi4-mini bei den Alerts abzulösen. Das Ergebnis war lehrreich: Auf Polnisch fasst es spürbar eleganter zusammen, aber an der Klassifikation von Alerts mit striktem JSON-Format ist es gescheitert — es hat alle Prioritäten auf Mittel plattgedrückt, während phi4-mini sie fehlerfrei und dreimal schneller getrennt hat. Die schönste Sprache gewinnt keine Aufgabe, die harte Klassifikation verlangt statt gepflegten Stil. Bielik blieb auf der Platte — und hat diese Aufgabe inzwischen bekommen: Im Alert-Pfad klassifiziert heute phi4-mini, und Bielik schreibt die endgültige Nachricht auf Polnisch — jedes Modell macht das, was es gut kann. Eine Falle aus dem Rollout: Über das rohe /api/generate hat Bielik den Prompt als Echo zurückgeworfen statt zu antworten; geholfen haben erst Chat-Aufrufe über /api/chat plus eine Beispielantwort im System-Prompt.
Temperaturen, oder: die Physik meldet sich
Dazu schweigen die Tutorials komplett: Ein LLM auf der CPU ist die härteste Arbeit, die dieser Prozessor je verrichtet hat. Während der Inferenz laufen alle Kerne ununterbrochen am Anschlag, über Dutzende Sekunden. Mein i5 erreichte dabei 88-95°C — bei einer Warnschwelle von 82°C. Eine Zeit lang hielt ich das für „akzeptabel“, was ein Euphemismus ist für „ich habe das Problem ignoriert“.

Die Lösung war banal und hatte mit AI nichts zu tun:
# docker-compose.yml — Ausschnitt der Ollama-Konfiguration
environment:
- OLLAMA_NUM_THREAD=4 # 4 von 6 Kernen → ~65% CPU, Temperatur unter 80°C
- OLLAMA_KEEP_ALIVE=2m # Standard: schnelles Entladen des Modells nach dem Gespräch
- OLLAMA_MAX_LOADED_MODELS=3 # Agent + Alerts + Embeddings gleichzeitig
- OLLAMA_NUM_PARALLEL=2 # max. 2 parallele Anfragen
deploy:
resources:
limits:
memory: 24g # hartes RAM-Limit des Containers — dazu gleich mehr
Zwei Kerne abzugeben kostet etwas Tempo, aber der Prozessor flirtet nicht mehr mit der kritischen Schwelle — und ein Server, der nebenbei alles andere erledigt, hat Luft zum Atmen. Der zweite Parameter ist ein Kompromiss in die Gegenrichtung: Ein kurzes globales KEEP_ALIVE gibt RAM frei und senkt die Temperaturen im Leerlauf, aber ein Gespräch nach einer Pause kann mit einem Kaltstart beginnen.
Man kann übrigens beides haben, denn keepAlive lässt sich pro Anfrage überschreiben. Das globale 2m ist bei mir die Standardhygiene für Ad-hoc-Aufgaben, aber die Anfragen des Agenten setzen ihr eigenes keepAlive: 24h und numCtx: 8192 — das Agentenmodell sitzt dauerhaft im RAM, damit ein Gespräch nicht mit Kaltstart und erneuter Verarbeitung des langen Prompts beginnt. Die übrigen Modelle kommen und gehen.
Und hier kam etwas heraus, das ich einen halben Tag lang unterschätzt habe: keepAlive ist eine Bitte, keine Garantie. Ob ein Modell wirklich im Speicher bleibt, entscheidet MAX_LOADED_MODELS — beim Limit 2 hat jeder Alert (der das Zusammenfassungsmodell lädt) und jede Suche (die das Embedding-Modell lädt) meinen „ewigen“ Agenten leise aus dem RAM gedrängt. Der Effekt: vierzig Sekunden Ladezeit, aufgeschlagen auf scheinbar zufällige Gespräche. Das Limit 3 hat das Thema beendet — alle drei Stamm-Modelle passen mit Reserve in 24 GB.
Die Falle, die wie RAM-Mangel aussieht
Der seltsamste Fehler des Jahres: Ollama weigert sich, ein Modell zu laden, mit der Begründung, es passe nicht in den Speicher — auf einer Maschine mit 32 GB, von denen real acht belegt sind. Der Grund: Beim Prüfen des freien Speichers schaut Ollama auf MemFree, nicht auf MemAvailable. Und MemFree kann auf einem Server, der viel von der Platte liest, unter ein Gigabyte fallen, weil Linux den Rest zu Recht im Cache hält — den es sofort hergibt, sobald ihn jemand braucht.
In Zahlen sieht das absurd aus: 32 GB RAM, davon real ~8 belegt, gut 20 GB im Cache — und MemFree zeigt weniger als ein Gigabyte, also verweigert Ollama ein Modell, das acht braucht. Das Modell „passt nicht“ in Speicher, der reichlich vorhanden ist; das System hat ihn nur noch nicht aufgeräumt. Bei mir halfen ein explizites Speicherlimit für Ollama und das Verschieben schwererer AI-Jobs in die Nacht, außerhalb der I/O-Stoßzeiten. Aber die Diagnose dauerte deutlich länger als die Reparatur — weil die Fehlermeldung über die Ursache lügt.
Timeouts: alle Uhren müssen im Takt ticken
Ein langsames Modell legt ein Problem offen, an das man bei einer schnellen API nie denkt: Timeouts. Lange Zeit lief meine Anfrage durch die Anwendung, dann durch , am Ende zu Ollama — und jede Schicht hatte ihre eigene Uhr. Wartet die Anwendung kürzer als n8n, bekommt der Nutzer einen Fehler, obwohl die Antwort noch entsteht. Schneidet n8n früher ab als Ollama, schreibt das Modell ins Leere.
Die Regel, zu der ich nach ein paar „Error in workflow“ ohne klaren Schuldigen kam: Die Uhren stellt man vom Ende her. Zuerst die realistische Zeit der langsamsten Modellantwort — mit Kaltstart und langem Prompt, nicht mit dem Durchschnitt — und dann bekommt jede Schicht darüber mindestens genauso viel. Plus eine Dokumentation, warum so viel, denn ein halbes Jahr später wirken diese Werte willkürlich.
Diese Uhren können Dutzende Minuten erreichen, und das klingt nach einer Ewigkeit — meistens ist es eine. Aber die Reserve rechnet sich am schlimmsten Fall: Kaltstart plus langer Prompt plus zwei Tools auf dem Weg. Eine Uhr, die zehn Sekunden zu früh abschneidet, verschwendet fünf Minuten Prozessorarbeit. Heute habe ich weniger Schichten und damit weniger Uhren — warum, gleich.
Der Bug, den du nicht fixen kannst: warum der Agent aus n8n ausgezogen ist
Diese Geschichte begann mit einer Meldung, die jeder Nutzer des AI-Agent-Nodes in n8n kennt: Received tool input did not match expected schema. Ein Agent, der monatelang Fragen zum Serverzustand beantwortet hatte, scheiterte plötzlich an jedem Tool-Aufruf. Erster Verdächtiger: ein zu schwaches Modell. Ich tauschte es gegen ein besseres — keine Änderung. Zweiter Verdächtiger: Das Modell verheddert sich bei über einem Dutzend Tools. Der entscheidende Test: ein Tool ganz ohne Parameter, an das das Modell korrekte, leere Argumente schickte — scheiterte auch.
Der wahre Übeltäter saß in n8n selbst — in Version 2.25, die ich damals betrieb: Nach einem der Updates gingen die Argumente der Tool-Aufrufe zwischen der LLM-Bibliothek und der Ausführung verloren, und der Validator bekam Leere, egal was das Modell geantwortet hatte. Auf n8ns GitHub gibt es mehrere Meldungen mit dieser Fehlermeldung (#14399, #17241, #23588) — während ich das schreibe, werden sie als veraltet oder als „Support-Fall“ geschlossen, ohne Fix. Zurück auf eine ältere Version? Unmöglich — n8n migriert seine Datenbank nur in eine Richtung. Das ist der Moment, in dem Self-Hosting die Zähne zeigt: ein Bug in einer fremden Zwischenschicht, auf den du keinen Einfluss hast und den du nicht umgehen kannst.
Der Ausweg war einfacher, als er klang: die Zwischenschicht rauswerfen. Eine Agenten-Schleife ist im Kern ein kleines Programm — schicke das Gespräch mitsamt Tool-Liste an Ollama; will das Modell ein Tool benutzen, führe es aus und hänge das Ergebnis an; wiederhole, bis eine Antwort entsteht. Ich habe sie direkt ins Backend der Anwendung geschrieben: ohne LLM-Framework, ohne visuellen Editor, dafür mit voller Kontrolle über jeden Timeout, jeden Prompt und jedes Log. n8n leistet bei mir weiterhin hervorragende Arbeit in den Automatisierungen — Alert-Pipeline, Benachrichtigungen, Zeitpläne — aber das Gespräch des Agenten mit dem Modell läuft nicht mehr hindurch.
Der Nebeneffekt erwies sich als wichtiger als die Reparatur selbst: Die volle Kontrolle über den Weg erlaubte es, den Prompt für den Cache zu strukturieren (die neun Sekunden statt hundertvier vom Anfang dieses Beitrags), das richtige Modell im Speicher zu halten und die Antwort live zu streamen. Ein Gespräch mit Tool, das auf dem alten Weg ~250 Sekunden dauerte, ist heute in ~30 erledigt. Derselbe Prozessor, dasselbe Modell der 4B-Klasse.
Wo ein lokales LLM Sinn ergibt — und wo nicht
Nach einem Jahr ist die Verteilung klar. Lokale AI funktioniert bei Aufgaben, die im Hintergrund laufen und niemanden warten lassen: Zusammenfassungen von Monitoring-Alerts, Embeddings und semantische Suche, Tagging von Inhalten, ein Heim-Agent, der in einigen Dutzend Sekunden antwortet und den Staubsauger steuert. Der gemeinsame Nenner: Niemand sitzt davor und starrt auf den Cursor — und seit die Antwort des Agenten live streamt, sieht selbst das Warten nach Arbeit aus, nicht nach Stillstand.
Sie funktioniert nicht, wo das Warten ein Gespräch sein soll: interaktiver Chat mit Zwei-Sekunden-Antwort, lange Kontexte in Echtzeit, alles, was mit der Flüssigkeit eines Cloud-Chats konkurriert. Man kann sich darüber ärgern oder es akzeptieren und um die Stärken herum bauen — meine Alert-Liste braucht keine Antwort in zwei Sekunden, sie braucht eine Antwort, die den Inhalt des Alerts nicht aus dem Haus geschickt hat.
Womit anfangen
Nicht mit dem Kauf einer GPU. Mit einem kleinen Modell — 3-4B Parameter — und einer echten Aufgabe: fasse mir das zusammen, tagge jenes, finde ähnliche Notizen. Wenn die Aufgabe nach einer Woche tatsächlich von selbst passiert, lohnt es sich weiterzugehen. Wenn nicht — hast du dir die Grafikkarte gespart, und docker compose down kostet weniger als die Reue über ausgegebenes Geld.
Bei mir ist es geblieben. Alerts kommen zusammengefasst an, der Agent schaltet das Licht aus und hütet das Gedächtnis der Familienabsprachen, und die Notizsuche versteht, dass „Papas Geburtstag“ und „Geschenk für Vater“ dasselbe Thema sind. Alles auf sechs Kernen von 2018 — langsam, lokal und genau so, wie ich es wollte. Und eine GPU? Kann man immer nachrüsten — aber das ist eine ganz andere Geschichte.
Häufige Fragen
Brauche ich eine GPU, um ein lokales LLM zu betreiben?
Nein — aber du musst die Erwartungen anpassen. Auf reiner CPU eignen sich Modelle mit wenigen Milliarden Parametern gut für Hintergrundaufgaben, und ein durchdachter Aufbau (Prompt-Cache, Modell dauerhaft im RAM) drückt die Antwort eines Agenten mit Tools auf einige Dutzend Sekunden. Einen interaktiven Chat wie mit ChatGPT bekommst du so trotzdem nicht.
Ersetzt mir ein lokales Modell ChatGPT?
Es dient einem anderen Zweck. Ein lokales LLM gewinnt dort, wo Privatsphäre und Hintergrundarbeit zählen: Zusammenfassungen, Tagging, semantische Suche, Automatisierungen. Für schnelle Gespräche und schwere Aufgaben bleiben Cloud-Modelle bequemer.
Mit welchem Modell fange ich ohne GPU an?
Mit einem kleinen: 3-4B Parameter (etwa phi4-mini oder ein qwen in der 4B-Variante). Es passt in den RAM, antwortet in vernünftiger Zeit und zeigt dir, ob ein lokales LLM dein Problem überhaupt löst. Größere Modelle weißt du erst zu schätzen, wenn du weißt, wofür du sie brauchst.
Was ändert eine GPU?
Die Größenordnung. Prompt-Verarbeitung und Generierung fallen von Minuten auf Sekunden, und Modelle ab 11B hören auf, eine Geduldsübung zu sein. Die Architektur bleibt dieselbe — Ollama, dieselben Tools, derselbe Weg — es begrenzen nur Budget und Stromverbrauch.