GitHub Copilot und ChatGPT in der Praxis

Viele haben sich ja bereits zu dem Thema Copilot, ChatGPT, StableDiffusion, Dalle-2 geäußert, ich mache das jetzt auch mal. Ich habe selbst mit allen Modellen Erfahrungen gesammelt über die letzten 12 Monate.

Ich beziehe mich hier jetzt nur auf meine Erfahrung in puncto Code. Nicht Text oder Bilder. Zu meiner Nutzung von Stable Diffusion oder auch zur Generierung von Artikeln(fragmenten) werde ich mich nochmal separat äußern.

Ich verwende GitHub Copilot für ein Projekt, über das ich die Code-Rechte habe, bereits 1 Jahr und, seitdem es die Testversion von ChatGPT gibt, verwende ich auch das.

Beide Tools sind (etwas) hilfreich. Mit einigen Einschränkungen.

Copilot ergänzt Boilerplate mehr oder weniger zuverlässig, kann gelegentlich anhand eines Names, einer Kommentarzeile oder auch auf Basis des gerade fertig geschriebenen Codeschnipsels raten wie es weitergehen wird. Manchmal fällt da auch eine ganze i.d.R eher einfache Funktion fertig ab. Auch für das Generieren von Tests ist Copilot nützlich.

ChatGPT generiert zu Fragen Beispielcode oder erklärt Konzepte. Das erspart hie und da ein paar Googlesuchen, hält einem nen Spiegel vor oder gibt Anregungen. Teilweise kann man Vorschläge verwenden oder auch Test generieren lassen. Auch zu Fehlerausgaben und Stracktraces hat ChatGPT manches mal sinnvolle Ideen.

Fehler. Beide Tools produzieren aber auch immer wieder Fehler, wissen nicht wie komplexere Komponenten zusammengebaut werden und wissen halt schlicht nicht, was ich wirklich als nächstes will oder, was das Feature erfordern wird (was ich in Abhängigkeit von der Qualität der vorangegangenen Spezifikation z.T. selbst nicht genau weiß).

Rechtliche Probleme. Aufgrund der rechtliche Unnsicherheit verwende ich die Tools aktuell nicht in Projekten für Kunden, wo ich den Code absehbar verkaufe bzw. Dienstleistungen an deren Codebases erbringe. Vielleicht ist hier für manche Kunden tabnine bald eine Alternative, wo das Modell, auf Basis dessen AI-Vervollständigungen oder Code-Generierungen dem jeweiligen Kunden oder Unternehmen gehören, dass den Service einkauft.

Nutzen in Zeit. GitHub behauptet in einer eigenen Studie, das man mit Copilot 55% schneller fertig wäre mit dem Coden. Das scheint mir für den average case mit dem ich im Alltag zu tun habe deutlich übertrieben zu sein. Ich denke, für den reinen Coding-Part meiner Arbeit sind es eher 10-20%. Zudem muss man bedenken, dass einfach nicht alles am Job eines Developers Coden (laut einer Studie von Microsoft sind das 50% der Zeit eines Entwicklers) ist.

In meinem Fall kommen da Kommunikation, Konzeptentwicklung und das Verstehen der Ziele, die meine Kunden erreichen wollen hinzu sowie dem Verständnis deren existierender technischer Umgebung. Auch wenn ich in manchen Jobs die Tickets nicht selbst schreiben muss, die ich abarbeite, ist in ihnen selten alles so spezifiziert, dass ich das Ticket einfach bei ChatGPT eingeben könnte und dann direkt ne Antwort bekäme.

In meinem Beispielprojekt vs. meiner Kundenaufträge ohne Copilot und ChatGPT ist mir aber aufgefallen, dass der Pain (langweiliges) Boilerplate zu tippen mit den Tools abgenommen hat. Manchmal erleichtert ChatGPT das Verständnis. Man kann einfach jede “blöde Frage” eingeben und bekommt Antworten. Diese stimmen nicht immer, geben aber bisweilen interessante Ansätze, wonach ich als nächstes fragen oder googeln könnte.

Ich kann auch einfach Code aus Libraries in ChatGPT geben und dann bekomme ich zurück, was es dazu “denkt”. Das ist manchmal schon ganz interessant. Einfach, weil sich hier jemand (hier: ChatGPT) die Arbeit macht, dass, was da steht tatsächlich mal in menschliche Sprache zu übersetzen (wenn auch eher auf niedriger Flughöhe). Da komme ich (häufig genug aus Faulheit oder Zeitmangel) nicht drauf.

Einem echten Pairing mit einem kompetenten Co-Developer würde ich die beiden Tools jedoch nicht vorziehen. Interessant könnte es sein, die Tools vielleicht in einem solchen Setting mitzuverwenden. Das hat sich für mich jedoch bislang noch nicht ergeben. Ich sehe da jedoch immer eher punktuelle Unterstützung zu klar abgegrenzen Fragestellungen.

Mit einem echten Menschen, kann man zügiger mehr “Land” abgrasen: den Code aus der Vogelperspektive betrachten, Lösungen aus anderen Komponenten oder Erfahrungen aus anderen Projekten, der Uni oder einem bestimmten Paper einbringen, von dem man intuitiv oder aus konkreten Gründen weiß, dass es einen insight bringt.

Auch zwischen Abstraktionsebenen im Kontext eines bestimmten Projektes “zu diskutieren”, kann ich mir mit ChatGPT nicht wirklich vorstellen. Noch nicht. Ich kann mir vorstellen, dass bei Projekten, die auf sehr kleine abgeschlossene Einheiten beruhen – also z.B. einzelne Commandzeilen Befehle einzugeben, die man neu macht, ChatGPT schon einiges bringen kann.

Auf der anderen Seite: wenn ich das dann einmal gemacht habe, schreibe ich mir ein Skript oder eine README.. das geht immer noch viel schneller als eines der Tools immer wieder zu verwenden.. Selbst wenn das mal so nicht geht, dann kann ich auch immer via Strg + Umschalt + r im Command Stack der Shell suchen und werde da für die meisten Dinge, die ich alltäglich brauche fündig. Das geht immer noch schneller, als was in ChatGPT zu suchen, das zu kopieren (ggf. noch anzupassen) und dann wieder abzufeuern..

Ich kann mir durchaus vorstellen, dass diese Tools besser werden und vielleicht in Zukunft als Service die Repos von Produkten scannen, vorschläge machen, Bugs identifizieren und vielleicht mit der Zeit da auch Dinge automatisch fixen.

Wenn die Systeme irgendwann auch noch mehr Gedächtnis und Kontextinformationen aufnehmen könnten, aus Jira, die Gespräche in Meetings oder mit Kunden mithören und finally via Neuralink-Implantat meine Gedanken lesen könnten, ja, dann werden die Tools wahrscheinlich alle Arbeit machen.

Bis dahin sind sie eine nette Hilfe – für den Fall, dass sie in Deutschland jemals wegen der rechtliche Hürden breiter in die Anwendung finden sollten. Ich komme jedoch bei Coding-Anteil meiner Arbeit * %-Beschleunigung im best case auf: 0.5 * 0.2 = 0,1 => 10% Beschleunigung meiner Arbeit. Ich sehe hier keinen Zusammenbruch der Software-Industrie und leider auch keine signifiante Abnahme der open issues vieler Projekte, die uns das Leben schwer machen.

Es gibt neben rechtlichen Fragen aber noch anderes zu bedenken: wenn man  weniger Erfahrung hat – und das gilt ja für jeden nach Gebiet – ist es nicht so leicht einzuschätzen, was von dem, was aus den Tools rausfällt wie gut stimmt. Gerade ChatGPT hat mir mal 3x hinterinander irgendwelche C++ Libraries für die Generierung fraktaler Bilder herbeihalluziniert, die einfach nicht existieren – und das ist nur ein Beispiel. Also, wenn man mit den Ergebnissen kritisch umgeht, ist der Nutzen, der abfällt meiner Meinung nach alle Mal 10 US Dollar im Monat Wert (aktueller Preis von GitHub Copilot). Aber ich glaube nicht, dass hier kurzfristig eine Verschiebung der Industrie vom good ole software development (Knowledge, Austausch, Stackoverflow + Google) hin zu reinem Prompt-Engineering absehbar ist, auch wenn da draußen viele Leute (auch ich zu Anfang) schreien. Ein interessanter Seitenaspekt ist, dass ja GPT-3 schon wirklich sehr groß ist und GPT-4 absehbar noch größer sein wird. Ich bin nicht sicher wie sehr das stimmt, aber selbst wenn GPT-4 noch viel besser sein sollte, ist die Frage: wird es kurzfristig genug CPU-, GPU- und RAM-Ressourcen geben, dass damit ein signifikatner Teil der Menschheit zu einem akzeptablen Preis wird arbeiten können?

Das, dass mit diesen Werkzeugen verdiente Geld wiederum im Schlund von Microsoft und OpenAI (und bald sicher auch anderen großen Schiffen) landet,  und nicht mal anteilig bei den Millionen Entwicklern, die das Kunststück ein solchen Modell trainieren zu können erst möglich gemacht haben, ist mir da selbstverständlich auch ein Dorn im Auge. Übrigens ein Grund, warum ich meinen privaten Code zum größten Teil schon langen nicht mehr auf GitHub parke. Keine Ahnung, warum nicht mehr Leute wenigstens diesen einfachen Schritt gehen. Gibt offenbar doch weniger Nerds als ich dachte..

Und hey, Kapitalismus heißt ja auch schon lange nicht mehr, dass man Geld äquivalent zur erbrachten Leistung bekommt.. falls das überhaupt jemals so gewesen ist. Wenn man als Gedankenexperiment den aktuell expontentiell erscheinenden Fortschritt fortschreibt werfen sich für die (mehr oder weniger Nahe) Zukunft eine interessante Frage auf: wem gehört denn eigentlich die Milliarde, die ein hypothetisches Unternehmen abwirft, für das in Zukunft eine x-beliebige Person einfach der AI der Zukunft die Frage gestellt hat: “Generiere mir mal ein Unternehmen, dass eine Milliarde wert ist!” ?

Bei den vielfältigen ökologischen, sozialen und auch ökonomischen und jetzt noch AI-Alignment Problemen, denen sich die Menscheit gegenüber sieht, haben wir glaube ich noch viel Gesprächsstoff vor uns, um dem großen kosmischen Filter zu entgehen.

Letztlich wird aus meiner Sicht schon seit Jahren zu wenig über AI gesprochen – von Seiten der Politik höre ich da so gut wie gar nix. Also, liebe Mitentwickler, arbeitet euch auch etwas ein und klärt andere auf. Denn auch ohne Skynet kann eine Welt, in der einige wenige AI verwenden und viele anderen nicht recht blöd aussehen – bzw. noch blöder als die Welt heute – wenn eine superintelligente AI uns nicht “aus Versehen” in Büroklammern umwandeln sollte.

Ich bin gespannt.

Wenn git deine .gitignore ignoriert.

Wenn git Einträge in deiner .gitignore ignoriert kann das verschiedene Gründe haben:

1. Format und Ort: Stelle sicher, dass die Datei “.gitignore” korrekt formatiert und im Stammverzeichnis deines Git-Repositories gespeichert ist. Git wird nur Dateien ignorieren, die in der “.gitignore”-Datei im Stammverzeichnis deines Repositories aufgelistet sind.

2. Datei wird bereits getrackt Prüfe, ob die Datei, die du ignorieren möchtest, bereits von Git getrackt wird. Wenn eine Datei bereits von Git getrackt wird, wird sie nicht ignoriert, selbst wenn sie in der “.gitignore”-Datei aufgelistet ist. Um eine Datei vom Tracking auszuschließen, gibt folgenden Befehl ein:

git rm --cached <file>

3. Bestehende Ignore-Regeln mit Vorrang Prüfe, ob es andere Ignore-Regeln gibt, die Vorrang vor der Regel in deiner “.gitignore”-Datei haben könnten. Wenn zum Beispiel eine globale Ignore-Datei (die sich unter “~/.gitignore_global” befindet) die Datei aufführt, die du ignorieren möchtest, wird Git sie ignorieren, selbst wenn sie in der “.gitignore”-Datei deines Repositories nicht aufgelistet ist. Es ist auch möglich, dass die Datei zunächst ignoriert und anschließend durch eine Ausnahmeregeln (mit !) wieder erlaubt wurde. Anders herum funktioniert das nicht: also, wenn für etwas zunächt eine Ausnahmeregel hinzugefügt wurde und anschließend ignoriert wird, bleibt die Datei auch ignoriert. Es gilt immer die letzte Regel.

4. Cache aktualisieren Wenn du Änderungen an deiner “.gitignore”-Datei vorgenommen hast und sie nicht erkannt werden, musst du möglicherweise den Cache aktualisieren, indem du den folgenden Befehl ausführst:

git rm -r --cached .
git add .
git commit -m "Refreshed cache"

Pattern Matching mit regulären Ausdrücken in Python.

Was sind reguläre Audrücke?

Reguläre Ausdrücke, auch als Regex oder RegEx bezeichnet, sind ein spezielles Format für Suchmuster, die von Python (oder auch anderen Programmiersprachen) interpretiert werden können. Sie werden häufig verwendet, um bestimmte Teile eines Strings zu suchen oder zu ersetzen.

Reguläre Ausdrücke enthalten spezielle Zeichen und Zeichenkombinationen, die bestimmte Suchmuster definieren. Zum Beispiel kann das Zeichen “.” jedes Zeichen in einem String entsprechen, während “*” eine beliebige Anzahl von Zeichen bedeutet.

Reguläre Ausdrücke können in Python mit dem re-Modul verwendet werden. Es enthält verschiedene Funktionen, die es ermöglichen, nach bestimmten Mustern in einem String zu suchen oder diese zu ersetzen.

Einfaches Pattern Matching

In Python kann man Pattern Matching mit regulären Ausdrücken machen. Reguläre Ausdrücke sind ein spezielles Format für Suchmuster, die von Python interpretiert werden können.

Hier ist ein Beispiel, wie man reguläre Ausdrücke in Python verwendet:

# Import the regular expression module
import re

# Define the string to search
my_string = "The quick brown fox jumps over the lazy dog."

# Define the pattern to search for
my_pattern = "quick"

# Use the re.search() function to search for the pattern in the string
match = re.search(my_pattern, my_string)

# Print the result of the search
if match:
  print("Match found!")
else:
  print("No match found.")

In diesem Beispiel suchen wir nach dem Wort “quick” in dem String “The quick brown fox jumps over the lazy dog.” Wir verwenden die re.search()-Funktion, um nach dem Pattern zu suchen, und dann prüfen wir, ob ein Match gefunden wurde.

Die Ausgabe dieses Beispiels wäre:

Match found!

Man kann auch komplexere Muster in regulären Ausdrücken definieren, um spezifischere Suchergebnisse zu erzielen.

Teile von Strings ersetzen

In Python kann man mit Regex (Regular Expressions) auch ersetzen. Regex sind ein spezielles Format für Suchmuster, die von Python interpretiert werden können.

Hier ist ein Beispiel, wie man Regex in Python verwendet, um einen Teil eines Strings zu ersetzen:

# Import the regular expression module
import re

# Define the string to be replaced
my_string = "The quick brown fox jumps over the lazy dog."

# Define the pattern to search for
my_pattern = "quick"

# Define the replacement string
my_replacement = "fast"

# Use the re.sub() function to search for the pattern in the string and replace it
replaced_string = re.sub(my_pattern, my_replacement, my_string)

# Print the result of the replacement
print(replaced_string)

In diesem Beispiel suchen wir nach dem Wort “quick” in dem String “The quick brown fox jumps over the lazy dog.” und ersetzen es durch das Wort “fast”. Wir verwenden die re.sub()-Funktion, um nach dem Pattern zu suchen und es zu ersetzen.

Die Ausgabe dieses Beispiels wäre:

The fast brown fox jumps over the lazy dog.

Komplexere Muster ersetzen

Man kann auch komplexere Muster in Regex definieren, um spezifischere Ersetzungen zu erzielen.

Natürlich kann man jetzt auch nach komplexeren Audrücken suchen und entsprechend ersetzen. Wenn man könnte z.B wenn man in einem Stück HTML-Code alle http:// durch https:// ersetzen möchte, da und nun nur nach dem Pattern “http” sucht, dann würden sowohl die existierenden http => https, aber auch die existierenden https => httpss ersetzt. Um das zu verhindern kann man mit folgendem Pattern arbeiten:

# Import the regular expression module
import re

# Define the string to be replaced
my_string = "This website uses http, but some websites use https instead."

# Define the pattern to search for
my_pattern = r"http(s)?:"

# Define the replacement string
my_replacement = "https:"

# Use the re.sub() function to search for the pattern in the string and replace it
replaced_string = re.sub(my_pattern, my_replacement, my_string)

# Print the result of the replacement
print(replaced_string)

In diesem Beispiel suchen wir nach dem Wort “http” oder “https” gefolgt von einem Doppelpunkt in dem String “This website uses http, but some websites use https instead.” und ersetzen es durch das Wort “https:”.

Die Ausgabe dieses Beispiels wäre:

This website uses https:, but some websites use https: instead.

Man muss “r”-Präfix vor dem regulären Ausdruck zu verwenden, um ihn als raw string zu kennzeichnen. Dies ist wichtig, da reguläre Ausdrücke normalerweise bestimmte Zeichen (wie “?”) haben, die von Python interpretiert werden können. Das “r”-Präfix deaktiviert diese Interpretation und ermöglicht es uns, genau das zu suchen, was wir angeben.

HTML-Tags inklusive Klassen entfernen

Ein weiteres Beispiel ist das entfernen von Tags inklusive Klassen, ohne den darin enthaltenen Text zu entfernen. Nehmen wir an, wir wollen alle spans aus einem Stück HTML Code entfernen. Das geht dann so:

# Import the regular expression module
import re

# Define the string to be modified
my_html = "<p>This is <span>some</span> text</p>"

# Define the pattern to search for
my_pattern = r"<span.*?>(.*?)</span>"

# Define the replacement string
my_replacement = "\\1"

# Use the re.sub() function to search for the pattern in the string and replace it
modified_html = re.sub(my_pattern, my_replacement, my_html)

# Print the result of the replacement
print(modified_html)

In diesem Beispiel suchen wir nach allen Spans im HTML-String und ersetzen sie durch den Inhalt des Spans. Wir verwenden auch eine Rückverweisung (\\1) im Ersatzstring, um den Inhalt des Spans im Ersatzstring zu referenzieren.

(Tipp: in vielen Editoren (z.B. Sublime) muss man statt \\1 => $1 schreiben und erhält denselben Effekt.)

Die Ausgabe dieses Beispiels wäre:

This is some text

Es ist zu beachten, dass dieses Beispiel nur für einfache Fälle von HTML gilt und möglicherweise nicht für komplexere HTML-Dokumente funktioniert. Für eine professionellere Lösung empfiehlt es sich, ein HTML-Parsing-Bibliothek wie BeautifulSoup zu verwenden.