Jupyter Notebooks sind seit langem ein beliebtes Werkzeug für Datenwissenschaftler, Entwickler und Forscher gleichermaßen. Ihre Flexibilität und Interaktivität ermöglichen schnelle Iterationen, Ideenvisualisierungen und exploratives Programmieren. Viele Entwickler schwören darauf als ihre bevorzugte Umgebung für die erste Entwicklungsphase. Doch die Arbeit mit Jupyter bringt Herausforderungen mit sich, gerade wenn es um intelligente Codevervollständigung geht. Für viele stellt Cursor, eine moderne KI-gestützte Autocomplete-Software, eine vielversprechende Lösung dar.
Dennoch stößt gerade das sogenannte Tab-Modell von Cursor in der Praxis immer wieder an seine Grenzen – insbesondere wenn es darum geht, den eigenen Workflow individuell abzubilden und wirklich sinnvolle Codevorschläge zu generieren. Ein Entwickler beschloss daher, das Cursor Tab Modell hinter sich zu lassen und seine eigene, personalisierte Lösung zu entwickeln, die speziell auf seine Nutzung von Jupyter Notebooks zugeschnitten ist. Dieses Vorhaben zeigt, wie individuelle KI-Modelle die Produktivität und Freude am Programmieren deutlich steigern können. Im Zentrum der Problematik stand vor allem die Diskrepanz zwischen den automatischen Vorschlägen von Cursor Tab und den tatsächlichen Bedürfnissen im Notebook-Alltag. Beispielsweise wird beim einfachen Ausgeben eines Pandas DataFrames häufig eine Speicherung der Daten in eine CSV vorgeschlagen – eine Funktion, die der Entwickler zwar durchaus nutzte, aber selten als erste Option bei der schnellen Visualisierung oder Prüfung von Daten.
Solche Abweichungen zwischen Modellvorschlag und Erwartung brachten oft Frust und verlängerten den Entwicklungsprozess, da die automatischen Vorschläge gelöscht und durch manuelle Eingaben ersetzt werden mussten. Die bestehenden Konfigurationsmöglichkeiten, wie die Anpassung über sogenannte .cursorrules Dateien, beeinflussten das Tab-Verhalten dabei kaum. Auch ein Lernen des Modells basierend auf der Beobachtung des persönlichen Verhaltens erschien wenig praktikabel, da dies auf Benutzerseite schwierig zu implementieren ist und bei Cursor als zentralisiertem Angebot ohnehin nicht möglich ist. Motiviert durch einen Schub Kaffee und die eigene Arbeitsweise entschied sich der Entwickler, die Herausforderung selbst anzugehen und ein eigenes Modell zur Codevervollständigung für Jupyter Notebooks zu bauen.
Dabei wurden ausschließlich lokale Notebooks berücksichtigt, was den Ansatz sehr persönlich und individuell gestaltbar machte. Der erste Schritt bestand in der systematischen Sammlung sämtlicher .ipynb-Dateien auf dem eigenen Rechner. Dabei spielte die Qualität der Daten eine wichtige Rolle, aber die Strategie lautete, möglichst viele Dateien einzubeziehen, um eine umfassende Repräsentation der eigenen Programmiermuster zu erhalten. Die Untersuchung der Daten anhand von Methoden wie t-SNE Visualisierungen zeigte deutliche Cluster von ähnlichen Codestellen, was die Spezifität des eigenen Stils unterstrich.
Damit war die Grundlage gelegt, um ein datenspezifisches Modell zu trainieren, das genau zu den Anforderungen und Eigenheiten in der Notebook-Arbeit passt. Ein wesentlicher Knackpunkt bei der Entwicklung war das verwendete Prompting-Verfahren. In der Praxis orientieren sich viele moderne Autocomplete-Modelle an der sogenannten „fill-in-the-middle“ Technik, bei der fehlender Code zwischen bekanntem Anfang und Ende ergänzt wird. In Jupyter Notebooks kommt hinzu, dass Code oft nicht linear in einer einzigen Zelle geschrieben wird, sondern sich über mehrere Zellen oder innerhalb gewisser Blöcke verteilt und semantisch verbunden sein kann. Diese Dynamik stellte eine große Herausforderung bei der Datensatz-Erstellung dar.
Der Entwickler definierte zwei wichtige Szenarien: Zum einen Completion-Beispiele innerhalb einer einzelnen Zelle (intra-cell) und zum anderen über mehrere Zellen hinweg (inter-cell), wobei letztere oft komplexer und umfangreicher waren. Das Modell wurde auf Basis dieser sorgfältig zusammengestellten Daten mittels Transferlearning auf einem bereits vorhandenen, leistungsfähigen Basismodell (Qwen 2.5 Coder-3B) feinabgestimmt. Besonderer Wert wurde darauf gelegt, dass das Training ressourceneffizient und stabil bleibt – durch den Einsatz von LoRA-Adaptern und GPU-gestützter Infrastruktur von Lightning AI gelang dies sehr gut. Trotz der technischen Ausgangslage war der Trainingsvorgang selbst der vergleichsweise leichteste Abschnitt im Prozess.
Die Vielschichtigkeit lag vor allem in den subtilen Fehlern und im ständigen Feintuning der Trainingsparameter, um möglichst realistische und hilfreiche Vervollständigungen zu erzielen. Ein weiterer entscheidender Aufwand bestand in der Formatumwandlung des feinjustierten Modells in ein für die eigentliche Anwendung optimiertes Format (gguf für Ollama). Hierbei halfen diverse Hacks, die Installation zusätzlicher schwergewichtiger Libraries vermieden und die Kompatibilität gewährleistet haben. Schließlich konnte das eigene Modell in die Entwicklungsumgebung integriert werden. Über die VSCode-Erweiterung „Continue“ war es möglich, die neue Autocomplete-Engine einzubinden und mittels einer einfachen Anpassung in der Konfigurationsdatei den Wechsel zum selbst trainierten Modell zu vollziehen.
Nach weiteren Updates und Verfeinerungen waren nun echte Vergleiche im Einsatz möglich. Der spannendste Moment bestand darin, das Modell in alltäglichen Szenarien zu testen. Dabei wurden typische Datenwissenschafts-Workflows mit CSV-Import, Datenexploration, Modelltraining, Ergebnisvisualisierung und Save-Testzyklen durchlaufen. Das eigene Modell zeigte deutliche Vorteile gegenüber der ursprünglichen Cursor Tab Variante, die manchmal unpassende Platzhalter vorschlug oder gewünschte Importe nicht berücksichtigte. So wurde bei einem Beispiel CNN in PyTorch der modulare Ansatz mit nn.
Module von Cursor empfohlen, obwohl dieser Import nicht vorhanden war – ein Nachteil, der beim eigenen Modell nicht auftrat. Das neue Modell reagierte unmittelbar nach Kommentarzeilen, setzte sauber im Code an, erzeugte kompakten und verständlichen Code. Auch die Kürze der Vorschläge ließ darauf schließen, dass der Output effizient praxistauglich war, ohne unnötigen Ballast. Zwischen verschiedenen Plattformmodellen zeigte sich, dass keine perfekt war, aber die eigene Lösung in Summe den geringsten Aufwand bei der Workflow-Durchführung erforderte. Cursor benötigte mehr manuelles Eingreifen und aufwändige Korrekturen, während andere Modelle mit der Trennung von Trainings- und Validierungssets haperte.
Die persönliche Anpassung ermöglichte es zudem, Fehler zu erkennen und im Anschluss automatisiert zu korrigieren, was Themensprünge und Zwischenschritte in der Notebook-Arbeit deutlich vereinfachte. Die Vorteile einer eigenen Codevervollständigungslösung gehen über die reine Funktionalität hinaus. Der wichtigste ist wohl die vollständige Kontrolle. Ein lokal gehostetes Modell unterliegt keiner externen Abhängigkeit von APIs, Internetverbindung oder Abo-Variabilitäten. Auch Sicherheitsaspekte spielen eine Rolle, da sensibler Code das System nie verlässt.
Zudem ist das Modell ressourcenschonend: Die eingesetzte Base ist vergleichsweise klein und benötigt wenig RAM und Batteriestrom – eine Kombination, die besonders für Entwickler mit mobilen Setups interessant ist. Nicht zuletzt bietet eine eigene Lösung die Chance einer kontinuierlichen Verbesserung. Anders als bei statischen Cloud-Lösungen kann das Modell regelmäßig mit neuen eigenen Daten gefüttert und feinjustiert werden, sodass es sich laufend an veränderte Programmierstile oder neue Anforderungen anpasst. Der gesamte Prozess zeigt, wie Menschen mit technischen Mitteln und einem tiefen Verständnis ihrer eigenen Arbeitsweise Möglichkeiten schaffen können, KI passgenau und persönlich einzusetzen. Inspiration und Leitfaden hierfür lieferten diverse Open-Source-Projekte und Blogs, die das Nachbauen von Code-Assistenten vereinfachen.