Der GitHub Copilot

Mitte 2020 hat die Firma OpenAI ihr Produkt GPT-3 als Nachfolger von GPT-2 vorgestellt. Es handelt sich dabei um die Weiterentwicklung einer künstlichen Intelligenz, die Texte vervollständigen und auch nach Gabe von Stichworten komplett verfassen konnte. Dahinter steht ein künstliches neuronales Netz mit einem Modell das "beschreibt, wie wahrscheinlich ein bestimmter Satz in einem Kontext ist" [1]. GTP-3 hat anhand von Millionen Textseiten gelernt, wie wahrscheinlich Sätze in einem Zusammenhang stehen, und kann somit Sätze ergänzen - bis hin zu ganzen Artikeln. 

Es hat nicht lange gedauert, bis Varianten davon auch für Quellcode trainiert wurden. Denn Quellcode einer bestimmten Sprache folgt auch einer Grammatik, und ist in Form von Kommentaren auch mit natürlicher Sprache in einen Kontext gesetzt. Das Ganze hat sich GitHub zunutze gemacht und ihr Produkt "Copilot" gebaut [2]. Wir haben eine Testfahrt gemacht! 

GitHub Copilot

Der Copilot ist ein Plugin für bekannte Entwicklungsumgebungen wie VS.Code oder Goland von JetBrains. Nach einer Registrierung kann es in die eigenen Projekte eingebunden werden, und es macht in Echtzeit während des Entwickelns Vorschläge, wie der im Entstehen begriffene Code vermutlich ausschauen soll. 

Die Schnittstellenarbeit des Copilot kann man dabei mit einem Language Server Protocol vergleichen. Die Leistung aus dem neuronalen Netz des Copilot kommt dabei aus dem Internet – von OpenAI. Dabei muss die Entwicklungsumgebung Teile dessen was gerade getippt wird, als Basis an den Dienst übertragen [3], das Netz macht Vorschläge, wie der aktuelle Codeblock ergänzt werden kann. 

Die Bedingungen für das Hochladen und Teilen von eigenem Code sind in den "Telemetry Terms" verfasst. Natürlich ist das Vorgehen in Bezug auf Datenschutz, GDPR und Kundengeheimnis nicht unproblematisch. Ich habe den Copiloten deshalb anhand eines privaten Projekts mit Go unter einer Open Source Lizenz ausprobiert – im Rahmen von Kundenprojekten kommt der Copilot bei Aleri nicht zum Einsatz. 

Das obige Bild zeigt den ersten Eindruck von der Nutzung. Zeilen 5-7 stellen ein einfaches Go-Struct „GCPSecretManager“, mit einem einzelnen Field „log“ dar. In Zeile 9 habe ich angefangen „func N“ zu tippen. 

Aus vergleichbaren anderen Structs in meinem Projekt (es gibt z.B. das Struct AzureKeyVault) ist naheliegende, eine „New…“-Funktion zu haben, die eine neue Instanz dieses Structs erzeugt. Nach kurzem Nachdenken der IDE erscheint der graue Text in Zeile 9f. Der Copilot schlägt vor, eine Funktion „NewGCPSecretManager“ zu erstellen, mit dem Logger als Parameter. Zurückgeliefert wird ein Zeiger auf den GCPSecretManager. Es folgt die einfache Erzeugung, Initialisierung und Rückgabe.  

Man kann nun diesen Vorschlag sehr einfach akzeptieren und er ist da. In diesem Falle war es auch genau das, was ich wollte. Die Komplexität ist zugegebenermaßen eher gering, aber es hat auf jeden Fall Tipparbeit abgenommen. 

Aber halt, es fehlt die Dokumentation dieser exportierten Funktion. Bevor der Linter sich beschwert, schnell vor Zeile 9 eine Leerzeile mit // gestellt. Das Ergebnis sieht man unten in Abbildung 1.

Der Copilot ergänzt automatisch den Kommentar. Also wird hier nicht nur „in Code“ gearbeitet, sondern auch natürlichsprachlich. Das ist in diesem Fall für eine KI nicht schwer, da sie aus sehr vielen anderen Beispielen weiß, dass eine „New“-Funktion für das „create“ von etwas neuem verantwortlich ist. Zumal so ein Text bereits an mehreren anderen Stellen in meinem Beispielprojekt auftaucht.  

Als nächstes muss eine weitere Funktion für das Struct entwickelt werden. Ich fange an mit „func (v *G“, und der Copilot ergänzt das, was in Abbildung 2 unten zu sehen ist.

Hier möchte er also eine Funktion „get“ erstellen, die anhand eines keys ein Ergebnis plus Fehlercode zurückgibt. Das Struct GCPSecretManager wird vorgeschlagen, was auch naheliegend ist. Hier hatte ich aber etwas anderes im Sinn, deshalb kann man auch einfach das eingeben, was man wirklich haben möchte. 

An anderen Stellen kommen sinnvollere Vorschläge, z. B. eine vorformatierte Fehlermeldung in Abb. 3. 

Hier wird in einer generischen Map geschaut, ob ein Schlüssel „projectID“ vorhanden ist. Beim Tippen von „if !ex“ wurde Zeile 33 vorgeschlagen, interessanterweise mit einer passenden Fehlermeldung, in fmt.Errorf verpackt. 

An anderen Stellen wird durch die Vorschläge ersichtlich, dass der Copilot die Struktur von aufgerufenen Funktionen und deren Rückgabewerten mit einbeziehen kann. Die obigen Beispiele waren hauptsächlich hilfreich, um Tipparbeit zu sparen. Es kommen aber durchaus Vorschläge zu tage, die mehrere Zeilen Code produzieren, die man sich auch erst einmal anschauen muss – einerseits um zu sehen ob es das ist, was man wollte, und andererseits um zu bewerten, ob das inhaltlich überhaupt korrekt ist.  

Die Vorschläge beschränken sich nicht nur auf Quellcodedateien, sondern auch auf Dokumentation, z. B. Markdown. Zwei Beispiele zeigen Abbildung 4 und 5.

Hier hat der Copilot nach Eingabe eines Markdown-Linkansatzes automatisch die korrekte (!) URL ergänzt. Der zweite Fall ist lustig, da es genau das war was ich ausdrücken wollte, aber nach Eingabe des Worts „default“ eigentlich nicht klar sein konnte, dass ich auf die Authentifizierungsmechanismus hinaus wollte. Allerdings lagen im selben Verzeichnis auch andere Markdown-Dateien, die einen vergleichbaren Aufbau hatten, und eben an dieser Stellen von Authentifizierung und Credentials die Rede war.  

Natürlich gibt es auch Fails, d.h. hier greift der Copilot daneben, wie die Abbildung 6 zeigt.

Das Struct, welches ich kommentieren möchte, heisst „GCPSecretManager“, nicht „GCPSecretManagerAdapter“. Es handelt sich tatsächlich um einen (Schnittstellen-)Adapter im Sinne der Clean Architecture, aber das Struct heisst nun einfach nicht so. (Abbildung 6)

Die Funktion in Abbildung 7 hatte ich schon als RetrieveSecret gecoded, nicht als ReadSecret – Kleinigkeit. 

Abbildung 8 - Hier hatte ich vor, ein leeres „Defaults“-Struct zurückzugeben. Der Copilot hatte wohl eher im Sinn, die Environment-Variable für ein Security-Token einer Drone.io-Umgebung zu verbauen. Lustig, da ich drone.io nicht verwende – wohl aber Vault. Aber es passte hier einfach nicht. 

Andere Stellen sind hilfreich, wie z. B. bei der Prüfung, ob ein Zeiger auf ein Array gegeben ist, und nach Eingabe von „&&“ als Erweiterung der if-Clause vorgeschlagen wird, die Länge des Arrays zu prüfen. (Abbildung 9)

Die hier gezeigten Beispiele sind recht einfach – tatsächlich kann der Copilot an verschiedensten Stellen mit eingreifen, und in den meisten Fällen Codebeispiele vorschlagen, die weiterführen. 

Fazit

Die Arbeit mit dem Copilot kann man erst einmal als hilfreich empfinden. Tipparbeit wird abgenommen, teilweise werden sogar Ideen eingebracht, z. B. zusätzliche Bedingungen zu prüfen. Für Neulinge in einer Sprache kann es sogar beim Lernen hilfreich sein, korrekte Konstrukte zu sehen, statt sich mit den Fehlermeldungen des Compilers auseinanderzusetzen.

Dabei ist klar, dass der Copilot aus Vorlagen und Code anderer lernt, und damit kommt die Gefahr des „Mehr-von-demselben“ auf. Eine Studie hat außerdem die Qualität des vorgeschlagenen Codes untersucht und festgestellt, dass er eine Basis von Fehlern und Sicherheitslücken sein kann [4].

Nicht zuletzt sind die Nutzungsbedingungen problematisch. Damit die KI erkennen kann, was im eigenen Entwicklungskontext sinnvoll ist, muss der Kontext an die KI übertragen werden. In Bezug auf Datenschutz und Betriebsgeheimnis ein No-Go. 
Diesen und weitere Aspekte wie z.B. Auswirkung im Zusammenhang mit Softwarelizenzen wurden in Papers untersucht, [5] gibt eine Übersicht der FSF.

Insgesamt bleibt aber der Ansatz ein spannender. Als Entwickler:in möchte man eher nicht, dass die Anwendung von einer künstlichen Intelligenz komplett generiert wird. Aber eine Automatisierung – in welcher Form auch immer – ist nicht abwegig. Schließlich wurden auch in vielen anderen Industrien die Werkzeuge verbessert und die Anzahl manueller Arbeitsschritte verkleinert, um die Produktivität zu verbessern.
Wir bleiben gespannt, was sich hier entwickelt. 


Quellen:

[1] https://de.wikipedia.org/wiki/OpenAI#GPT-3
[2] https://copilot.github.com/ 
[3] https://docs.github.com/en/github/copilot/github-copilot-telemetry-terms 
[4] https://www.theregister.com/2021/08/25/github_copilot_study/  
[5] https://www.fsf.org/news/publication-of-the-fsf-funded-white-papers-on-questions-around-copilot  

Ihre Ansprechpersonen zum Thema

Sie haben Fragen an unsere Expertinnen und Experten? Oder möchten mehr über unsere digitalen Lösungen erfahren?
Kontaktieren Sie uns gerne!

Andreas Schmidt, Aleri Solutions GmbH

Andreas Schmidt

CTOandreas.schmidt@aleri.de
Seite teilen