Aufbau eines einzigen Knowledge Graphs über 46 Repositories hinweg
Ich bin Ryan, CTO bei airCloset.
Ich habe drei Monate damit verbracht, code-graph aufzubauen. Es handelt sich um einen einzigen Knowledge Graph, der 46 Repositories über mehrere Services hinweg vereinigt.
Viele denken, man könne der KI einfach den gesamten Code übergeben und Fragen dazu stellen. Das scheitert aus zwei Gründen:
- Kontextfenster: Man kann nicht jahrelangen Code aus 46 Repos in einen einzigen Prompt packen.
- Halluzination: Die KI macht Fehler, wenn sie versucht, Beziehungen abzuleiten. Sie übersieht Verbindungen.
Um dies zu lösen, habe ich statische Analyse verwendet, um eine Source of Truth aufzubauen.
Die Herausforderung: Grenzen überschreiten
Eine große Codebasis ist unübersichtlich. Eine API wird vielleicht von fünf verschiedenen Repositories aufgerufen. Eine Datenbanktabelle wird vielleicht von drei verschiedenen Services genutzt.
Wenn man nur ein einzelnes Repository betrachtet, verpasst man das Gesamtbild. Das ist gefährlich. Wenn man Code ändert und den tatsächlichen Blast Radius nicht sieht, bringt man das System zum Absturz.
Mein Ansatz nutzt tree-sitter, um Code in Syntaxbäume zu parsen. Aber tree-sitter allein kann keine Repository-Grenzen überschreiten.
Ich habe Boundary Nodes entwickelt, um dies zu lösen.
So funktioniert es:
- Wir extrahieren Beziehungen innerhalb eines Repos mithilfe von tree-sitter.
- Wir nutzen die TypeScript Compiler API, um Typen und Variablen aufzulösen.
- Wir nutzen Gemini, um dynamische Fälle zu handhaben, die Tools übersehen.
Anstatt die KI raten zu lassen, liefern wir ihr Fakten. Wir sagen ihr: „Diese API wird auch aus Repo X aufgerufen.“ Das verhindert Halluzinationen.
Der schwierige Teil: Der Framework-Zoo
Der eigentliche Kampf bestand darin, diese Grenzen zu extrahieren. Jedes Framework definiert Grenzen anders.
Ein Team nutzt NestJS-Decorators. Ein anderes nutzt Express-Routes. Ein weiteres nutzt rohes jQuery. Jedes davon erzeugt eine andere Struktur im Code.
Um dies umzusetzen, mussten wir maßgeschneiderte Parser für Folgendes bauen:
- NestJS und TypeORM
- Express und Fastify
- AngularJS und Redux
- Verschiedene Path-Alias-Schemata
Wir mussten eine Genauigkeit von 99 % anstreben. Wenn unsere Verbindungsrate nur bei 90 % liegt, übersieht die KI 10 % der Verbindungen. In einem Produktionssystem sind genau diese 10 % der Ort, an dem sich die Bugs verstecken.
Wir führen nun einen täglichen Check durch. Wenn unsere Verbindungsrate um mehr als 5 % sinkt, erhalten wir einen Alarm. So bemerken wir, wenn neue Codemuster unsere Parser unterbrechen.
Aktuelle Einschränkungen
Der Graph ist nicht perfekt.
- Die Suche ist schwierig. Man muss oft einen Funktionsnamen kennen, um die Suche überhaupt zu starten.
- Node-Explosion. Das Verfolgen eines Pfades kann tausende winzige, nutzlose Helper-Funktionen mit hineinziehen.
- Wartung. Jedes Mal, wenn ein neues Framework in unseren Stack aufgenommen wird, müssen wir einen neuen Parser schreiben.
Dies ist Teil 1. In Teil 2 werde ich die Service-Product-Graph (SPG)-Schicht besprechen, die ich entwickelt habe, um diese Lücken zu schließen.
Optionale Lern-Community: https://t.me/GyaanSetuAi
