Lokales Coding mit LM Studio und Bionic: Erfahrungen, Modellwahl und Performance-Tuning

Lokale Large Language Models werden für Softwareentwicklung zunehmend interessant. Mit LM Studio lassen sich aktuelle Open-Source-Modelle lokal betreiben, während Bionic direkt als Coding-Agent auf Projekte zugreifen, Dateien analysieren und Änderungen durchführen kann.

In meinem Test ging es vor allem um eine Frage: Welches Modell eignet sich auf einem normalen Desktop-PC sinnvoll für agentisches Coding, und wie lassen sich Prompt-Verarbeitung und Generierung optimieren?

Als Testsystem kam folgende Hardware zum Einsatz:

CPU: Ryzen 7 5700X
RAM: 32 GB DDR4
GPU: AMD Radeon RX 9060 XT
VRAM: 16 GB

Dabei zeigte sich schnell: Nicht nur die Qualität des Modells ist entscheidend. Gerade bei Coding-Agenten spielen Modellgröße, Kontextfenster, KV-Cache und Prompt Processing eine mindestens ebenso große Rolle.

Modelle mit einer einheitlichen Testaufgabe vergleichen

Um verschiedene lokale LLMs in OpenCode sinnvoll miteinander zu vergleichen, sollte jedes Modell möglichst dieselbe klar definierte Aufgabe erhalten. Als praktische Testaufgabe eignet sich beispielsweise die Entwicklung eines kleinen Tetris-Clones als Webseite mit PHP, HTML, CSS und JavaScript. Die Anwendung soll ein klassisches 10×20-Spielfeld, alle sieben Tetrominos, Bewegung und Rotation, Hard Drop, das Entfernen vollständiger Reihen, Punkte und Level sowie eine Vorschau auf den nächsten Stein enthalten. Zusätzlich sollen Start, Pause und Neustart sowie eine Tastatursteuerung umgesetzt werden. Externe Frameworks sind nicht erlaubt, und der Code soll sauber in sinnvolle Dateien gegliedert werden.

Eine solche Aufgabe eignet sich gut als Benchmark, weil sie mehrere Fähigkeiten gleichzeitig testet: Das Modell muss eine kleine Softwarearchitektur planen, Spiellogik implementieren, Zustände verwalten, eine Benutzeroberfläche erstellen und mehrere Dateien konsistent miteinander verbinden. Zusätzlich lässt sich anschließend überprüfen, ob das Ergebnis tatsächlich funktioniert oder ob beispielsweise Rotation, Kollisionsprüfung, Reihenlöschung oder Levelsystem fehlerhaft umgesetzt wurden. Für einen aussagekräftigen Vergleich sollten die Modelle möglichst mit denselben OpenCode-Einstellungen, demselben System-Prompt und einem leeren Projektverzeichnis starten.

Ein geeigneter System-Prompt für lokale Coding-Modelle

Neben dem eigentlichen Modell beeinflusst auch der System-Prompt die Qualität eines Coding-Agenten. Gerade bei kleineren lokalen Modellen sollte dieser möglichst kurz und eindeutig gehalten werden. OpenCode stellt dem Modell bereits eigene Informationen über Werkzeuge, Dateien und Arbeitsumgebung zur Verfügung. Ein umfangreicher zusätzlicher System-Prompt verbraucht daher nicht nur Kontext, sondern kann im ungünstigsten Fall auch mit den Agentenanweisungen von OpenCode konkurrieren.

Für lokale Coding-Modelle hat sich deshalb ein kompakter Prompt mit wenigen klaren Regeln angeboten:

You are a senior software engineer working autonomously in an existing project.

Inspect the relevant code before editing it.
Use the available tools to search, read, edit, build, and test.

Make the smallest correct change that solves the user's request.
Follow the existing architecture and coding style.
Do not invent APIs, files, or dependencies.
Do not modify unrelated code.

After changes, build or test the project when possible.
Fix errors caused by your changes.
Never claim success unless it was verified.
If the task is clear, proceed without asking unnecessary questions.

Besonders wichtig sind dabei vier Grundregeln: erst analysieren, dann verändern; die verfügbaren Tools verwenden; Änderungen möglichst klein halten; und das Ergebnis anschließend bauen oder testen. Diese Vorgaben adressieren typische Schwächen kleinerer lokaler Modelle, etwa das Erfinden nicht vorhandener APIs, unnötig große Refactorings oder das vorschnelle Melden einer erfolgreichen Lösung ohne tatsächliche Überprüfung.


LM Studio mit OpenCode verbinden

LM Studio stellt einen OpenAI-kompatiblen API-Server bereit. Dadurch können externe Programme wie OpenCode lokale Modelle verwenden.

Der API-Endpunkt lautet standardmäßig:

http://127.0.0.1:1234/v1

Eine mögliche OpenCode-Konfiguration sieht beispielsweise so aus:

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "lmstudio": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "LM Studio",
      "options": {
        "baseURL": "http://127.0.0.1:1234/v1"
      },
      "models": {
        "MODEL-ID": {
          "name": "Lokales Modell"
        }
      }
    }
  }
}

Damit kann OpenCode LM Studio praktisch wie einen lokalen OpenAI-Server verwenden.


Bionic oder OpenCode?

LM Studio besitzt mit Bionic inzwischen selbst einen Coding-Agenten. Beide Lösungen verfolgen grundsätzlich denselben Ansatz:

LLM
 ↓
Coding-Agent
 ↓
Dateien suchen und lesen
 ↓
Code verändern
 ↓
Terminalbefehle ausführen
 ↓
Tests und Builds durchführen

OpenCode bietet dabei sehr viele Konfigurationsmöglichkeiten und eignet sich besonders gut für komplexe Entwicklungsworkflows.

Bionic hat dagegen einen wichtigen Vorteil: Es ist direkt auf die Nutzung lokaler und offener Modelle innerhalb von LM Studio zugeschnitten.

Gerade beim Tool Calling kann dies relevant sein. Ein Modell kann zwar guten Code erzeugen, muss für einen Coding-Agenten aber zusätzlich zuverlässig entscheiden können:

  • welche Dateien gelesen werden müssen,
  • wann ein Terminalbefehl notwendig ist,
  • welche Änderungen durchgeführt werden sollen,
  • wie Testergebnisse zu interpretieren sind.

Für lokale Modelle ist Bionic deshalb eine sehr interessante Alternative zu OpenCode.


Erster Versuch: Qwen3.6 35B A3B

Zunächst wurde folgendes Modell verwendet:

Qwen3.6 35B A3B Q4_K_M

Dabei handelt es sich um ein Mixture-of-Experts-Modell. Obwohl insgesamt etwa 35 Milliarden Parameter vorhanden sind, werden pro Token nur ungefähr 3 Milliarden Parameter aktiviert.

Das klingt zunächst ideal für lokale Nutzung.

In der Praxis war das Modell auf einem System mit 16 GB VRAM und 32 GB RAM allerdings zu groß.

Die quantisierte Modelldatei benötigt bereits ungefähr 20 GB Speicher. Damit passt das Modell nicht komplett in den VRAM.

Die Folge:

GPU
16 GB VRAM
     │
     ├── Teil des Modells
     ├── KV Cache
     │
System-RAM
     │
     └── restliches Modell

Dadurch müssen Teile der Berechnung zwischen GPU und Arbeitsspeicher aufgeteilt werden.

Das Modell funktionierte zwar, war für einen interaktiven Coding-Agenten aber deutlich zu schwergewichtig.


Context Size Exceeded

Ein weiteres Problem trat relativ schnell auf:

Engine protocol predict stream returned an error:

Context size has been exceeded.

Bei einem normalen Chat besteht der Kontext hauptsächlich aus:

System Prompt
+ Benutzerfrage
+ bisherige Antworten

Bei einem Coding-Agenten kommt wesentlich mehr hinzu:

System Prompt
+ Chatverlauf
+ Projektinformationen
+ eingelesene Quelldateien
+ Tool Calls
+ Terminalausgaben
+ Compilerfehler
+ Git-Diffs
+ Reasoning

Dadurch können selbst kleine Coding-Aufgaben schnell mehrere zehntausend Tokens erzeugen.

Ein Kontextfenster von beispielsweise:

8192 Tokens

ist deshalb für einen Coding-Agenten kaum ausreichend.

Als sinnvoll erwiesen sich mindestens:

32768 Tokens

Für größere Aufgaben sind:

65536 Tokens

deutlich komfortabler.


Die bessere Lösung: Gemma 4 12B QAT

Als Alternative wurde anschließend:

Gemma 4 12B QAT

verwendet.

Das Modell erwies sich als wesentlich besser passend für die vorhandene Hardware.

QAT steht für:

Quantization-Aware Training

Während bei normaler Quantisierung ein fertig trainiertes Modell nachträglich beispielsweise auf 4 Bit reduziert wird, berücksichtigt Quantization-Aware Training die geringere Präzision bereits während des Trainings.

Dadurch können relativ kleine Modellvarianten erzeugt werden, ohne so viel Qualität wie bei einer einfachen nachträglichen Quantisierung zu verlieren.

Gemma 4 12B QAT benötigt auf dem Testsystem ungefähr:

9–10 GB VRAM

Damit bleibt auf einer 16-GB-Grafikkarte noch ausreichend Speicher für:

KV Cache
Context
Runtime
Batch Processing

übrig.


Gute LM-Studio-Einstellungen für Gemma 4 12B QAT

Als guter Ausgangspunkt haben sich folgende Werte ergeben:

Context Length:          32768–65536

GPU Offload:             Maximum
CPU Thread Pool:         8

Evaluation Batch Size:   4096
Physical Batch Size:     1024

Max Concurrent:          1

Flash Attention:         ON

Reasoning Budget:        4096–8192
Preserve Thinking:       OFF

KV Cache GPU:            ON
Unified KV Cache:        ON

K Cache:                 Q8_0
V Cache:                 Q8_0

Context Checkpoints:     16–32

Keep Model in Memory:    ON
mmap:                    ON

Bei den Sampling-Einstellungen kann man für Gemma ungefähr mit folgenden Werten beginnen:

Temperature: 1.0
Top K:       64
Top P:       0.95

CPU Thread Pool

Der Ryzen 7 5700X besitzt:

8 Kerne
16 Threads

Für LLM-Inferenz bedeutet mehr Threads nicht automatisch mehr Geschwindigkeit.

Ein sinnvoller Ausgangspunkt ist deshalb:

CPU Thread Pool Size = 8

also ungefähr die Anzahl der physischen Kerne.

In meinem Test spielte die CPU allerdings kaum eine Rolle, da das Modell vollständig beziehungsweise nahezu vollständig auf der GPU ausgeführt wurde.


Flash Attention

Eine Einstellung sollte für moderne Modelle praktisch immer aktiviert werden:

Flash Attention = ON

Flash Attention optimiert die Attention-Berechnung und kann sowohl:

  • Speicherverbrauch reduzieren
  • als auch die Geschwindigkeit erhöhen.

Gerade bei großen Kontextfenstern macht sich dieser Effekt bemerkbar.


Max Concurrent Predictions

LM Studio erlaubt mehrere parallele Inferenzanfragen.

Standardmäßig kann beispielsweise eingestellt sein:

Max Concurrent Predictions = 4

Für einen einzelnen Coding-Agenten ist das allerdings unnötig.

Sinnvoller ist:

Max Concurrent Predictions = 1

Damit steht die komplette Rechenleistung einer einzigen Bionic-Anfrage zur Verfügung.


Evaluation Batch und Physical Batch

Eine der wichtigsten Einstellungen für das Prompt Processing ist der Evaluation Batch.

Ursprünglich wurden folgende Werte verwendet:

Evaluation Batch = 2048
Physical Batch   = 512

Nach einer Erhöhung auf:

Evaluation Batch = 4096
Physical Batch   = 1024

stieg die Prompt-Verarbeitung deutlich.

Ein größerer Evaluation Batch bedeutet vereinfacht, dass mehr Prompt-Tokens gemeinsam durch das Modell verarbeitet werden.

Der Nachteil ist ein höherer Speicherbedarf.

Da Gemma 4 12B auf einer 16-GB-GPU noch genügend VRAM-Reserve besitzt, ist ein größerer Batch hier sinnvoll.


KV Cache

Der KV Cache speichert bereits berechnete Attention-Zustände des bisherigen Kontexts.

Ohne ihn müsste ein Modell bei jeder neuen Anfrage große Teile des bisherigen Gesprächs erneut vollständig berechnen.

Für einen Coding-Agenten sollte deshalb möglichst gelten:

KV Cache → GPU

Auf dem Testsystem funktionierten folgende Einstellungen gut:

Offload KV Cache to GPU = ON

K Cache Quantization = Q8_0
V Cache Quantization = Q8_0

Q8 reduziert den Speicherbedarf des Caches, ohne direkt auf eine sehr aggressive Q4-Quantisierung zurückgreifen zu müssen.


Preserve Thinking

Ein interessantes Feature moderner Reasoning-Modelle ist:

Preserve Thinking

Dadurch kann das Reasoning früherer Agenten-Schritte erneut in den Kontext aufgenommen werden.

Für komplexe Agentenketten kann das hilfreich sein.

Bei begrenztem Kontext hat es allerdings einen großen Nachteil:

mehr Thinking
→ mehr Tokens
→ größerer Kontext
→ längeres Prompt Processing

Deshalb wurde für Bionic:

Preserve Thinking = OFF

verwendet.


Reasoning Budget

Auch das Reasoning Budget sollte nicht unnötig groß gewählt werden.

Eine sinnvolle Abstufung ist:

kleine Coding-Aufgabe:
2048–4096 Tokens

normales Coding:
4096–8192 Tokens

komplexes Debugging:
8192–16384 Tokens

Für den normalen Entwicklungsalltag haben sich etwa:

4096 Tokens

als guter Ausgangspunkt erwiesen.


Der große Unterschied: Prompt Processing und Token Generation

Bei der Geschwindigkeit eines lokalen LLM muss man zwei völlig unterschiedliche Werte betrachten.

Token Generation

Das ist die Geschwindigkeit, mit der das Modell seine Antwort erzeugt.

Beispielsweise:

29,84 Tokens/s

Prompt Processing

Das ist die Geschwindigkeit, mit der der Eingabekontext verarbeitet wird.

Beispielsweise:

372,95 Tokens/s

Für Coding-Agenten ist der zweite Wert besonders wichtig.

Warum?

Weil ein Agent einen enorm großen Prompt erzeugen kann.


Erste Messung

Eine erste Messung mit Gemma 4 ergab:

Prompt:
1775 Tokens

Prompt Processing:
65,56 Tokens/s

Generierung:
23,32 Tokens/s

Die eigentliche Token-Generierung war bereits akzeptabel.

Das Prompt Processing erschien dagegen ausgesprochen langsam.


Optimierte Messung

Nach Anpassung der Einstellungen ergab sich:

Prompt:
33220 Tokens

Prompt Processing:
372,95 Tokens/s

Generierung:
29,84 Tokens/s

Damit war das Prompt Processing etwa:

5,7 × schneller

und auch die eigentliche Generierung verbesserte sich um ungefähr:

28 %

Die Hardware wurde währenddessen sehr gut ausgelastet:

GPU Compute:       ca. 95 %
VRAM:               ca. 9,6 / 16 GB
CPU:                ca. 8 %
RAM:                ca. 17 / 32 GB
GPU-Temperatur:     ca. 55 °C

Damit war klar:

Die CPU war nicht der Flaschenhals. Das Modell lief effizient auf der GPU.


Trotzdem dauerte das Prompt Processing 89 Sekunden

Der Log zeigte:

prompt eval time =
89072 ms / 33220 tokens

372,95 tokens/s

Das entspricht ungefähr:

33220 / 372,95
≈ 89 Sekunden

Die hohe Wartezeit entstand also nicht mehr durch schlechte Hardwareauslastung.

Das eigentliche Problem war:

Bionic schickte mehr als 33.000 Tokens an das Modell.

Selbst eine schnelle GPU benötigt bei solchen Promptgrößen Zeit.


Warum Coding-Agenten so viel Kontext benötigen

Ein Coding-Agent arbeitet nicht nur mit dem eigentlichen Benutzerprompt.

Eine typische Aufgabe kann beispielsweise so aussehen:

Benutzeranfrage
      ↓
Projekt durchsuchen
      ↓
5 Dateien lesen
      ↓
Abhängigkeiten analysieren
      ↓
Quellcode ändern
      ↓
Build starten
      ↓
Compilerfehler lesen
      ↓
weitere Datei öffnen
      ↓
Code erneut ändern
      ↓
Tests starten

All diese Informationen können Teil des Agentenkontexts werden.

Dadurch wächst eine Session sehr schnell auf:

20.000
30.000
40.000
oder mehr Tokens

an.


Größerer Kontext ist deshalb nicht immer besser

Ein Modell kann beispielsweise:

256k Context

unterstützen.

Das bedeutet aber nicht, dass man diesen Wert unbedingt verwenden sollte.

Bei lokalem Coding gilt:

größerer Kontext
        ↓
mehr Speicher
        ↓
mehr Prompt Processing
        ↓
längere Wartezeit

Für das Testsystem hat sich deshalb folgende Einordnung ergeben:

32k → sehr guter Daily Driver

64k → für größere Coding-Aufgaben

128k+ → technisch möglich,
        aber lokal oft nicht sinnvoll

Neue Sessions können schneller sein

Wenn eine Coding-Aufgabe abgeschlossen ist, kann es sinnvoll sein, für die nächste größere Aufgabe eine neue Bionic-Session zu öffnen.

Statt:

alte Session
35.000 Tokens

+ neue Aufgabe

beginnt man beispielsweise wieder mit:

neue Session
5.000–10.000 Tokens

Das kann die Wartezeit beim Prompt Processing massiv reduzieren.

Wichtig ist allerdings:

Wenn Bionic bereits für die erste Aufgabe wieder große Teile des Projektes einliest, entsteht natürlich erneut ein großer Prompt.


Prompts möglichst konkret formulieren

Auch die Aufgabenstellung beeinflusst die Menge des eingelesenen Codes.

Ungünstig:

Analysiere das gesamte Projekt und finde mögliche Probleme.

Besser:

Untersuche OrderService.cs und die direkt davon verwendeten Klassen.

Finde heraus, warum beim Speichern eines Auftrags eine
NullReferenceException auftritt.

Ändere nur die dafür notwendigen Dateien und führe anschließend
die relevanten Tests aus.

Je genauer der Auftrag formuliert ist, desto weniger unnötigen Projektkontext muss der Agent sammeln.


Modellgröße ist nicht alles

Eine der wichtigsten Erkenntnisse des Tests war:

Das größte Modell ist nicht automatisch das beste Modell für lokales Coding.

Qwen3.6 35B A3B besitzt deutlich mehr Parameter und ist grundsätzlich leistungsfähiger als Gemma 4 12B.

Für einen Coding-Agenten muss ein Modell aber möglicherweise dutzende Male hintereinander aufgerufen werden.

Dann macht die Geschwindigkeit einen enormen Unterschied.

Vereinfacht:

Großes Modell

1 Agenten-Schritt = langsam
30 Agenten-Schritte = sehr langsam

gegen:

kleineres Modell

1 Agenten-Schritt = schnell
30 Agenten-Schritte = akzeptabel

Für agentisches Coding ist deshalb häufig ein etwas kleineres Modell mit hoher Inferenzgeschwindigkeit produktiver.


Fazit

Mit LM Studio und Bionic lässt sich inzwischen eine erstaunlich leistungsfähige lokale Coding-Umgebung aufbauen.

Für einen Rechner mit:

Ryzen 7 5700X
32 GB RAM
16 GB VRAM

erwies sich ein 35B-Modell allerdings als unnötig schwergewichtig.

Gemma 4 12B QAT bietet dagegen einen deutlich besseren Kompromiss aus:

  • Modellqualität,
  • Coding-Fähigkeiten,
  • Geschwindigkeit,
  • VRAM-Verbrauch,
  • großem Kontextfenster.

Mit optimierten Einstellungen wurden auf dem Testsystem etwa:

Prompt Processing:
~373 Tokens/s

Generation:
~30 Tokens/s

erreicht.

Der wichtigste Flaschenhals war am Ende nicht mehr das Modell oder die GPU, sondern die Menge an Kontext, die Bionic bei komplexen Aufgaben erzeugt.

Die wichtigste Erkenntnis lautet deshalb:

Bei lokalen Coding-Agenten sollte man nicht nur auf Tokens pro Sekunde achten. Mindestens genauso wichtig ist, wie viele Tokens der Agent bei jedem Schritt überhaupt an das Modell übergibt.

Ein gut gewähltes 9B- bis 14B-Modell, vollständig auf der GPU, mit sinnvoll begrenztem Kontext kann im Entwicklungsalltag daher deutlich angenehmer sein als ein wesentlich größeres Modell, das permanent zwischen VRAM und Arbeitsspeicher ausgelagert werden muss.

Lokales Coding mit LM Studio und Bionic: Erfahrungen, Modellwahl und Performance-Tuning
Markiert in:             

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert


CAPTCHA-Bild
Bild neu laden