Costruire un unico Knowledge Graph attraverso 46 repository
Sono Ryan, CTO di airCloset.
Ho trascorso tre mesi a costruire code-graph. Si tratta di un unico knowledge graph che unifica 46 repository distribuiti su più servizi.
Molte persone pensano di poter semplicemente consegnare tutto il proprio codice a un'IA e porre domande. Questo approccio fallisce per due motivi:
- Finestre di contesto: non è possibile inserire anni di codice provenienti da 46 repository in un singolo prompt.
- Allucinazione: l'IA commette errori quando cerca di inferire le relazioni. Perde le connessioni.
Per risolvere il problema, ho utilizzato l'analisi statica per costruire una "source of truth".
La sfida: superare i confini
Un codebase di grandi dimensioni è disordinato. Una singola API potrebbe essere chiamata da cinque repository diversi. Una tabella del database potrebbe essere utilizzata da tre servizi differenti.
Se guardi solo un repository, perdi il quadro completo. Questo è pericoloso. Se modifichi il codice senza vedere il reale "blast radius" (raggio d'azione dell'impatto), rischi di rompere il sistema.
Il mio approccio utilizza tree-sitter per analizzare il codice in alberi sintattici. Ma tree-sitter da solo non può vedere oltre i confini dei repository.
Ho creato dei "boundary nodes" (nodi di confine) per risolvere il problema.
Come funziona:
- Estraiamo le relazioni all'interno di un repository utilizzando tree-sitter.
- Utilizziamo la TypeScript Compiler API per risolvere tipi e variabili.
- Utilizziamo Gemini per gestire i casi dinamici che gli strumenti tradizionali trascurano.
Invece di chiedere all'IA di tirare a indovinare, le forniamo dei fatti. Le diciamo: "Questa API viene chiamata anche dal Repo X". Questo previene le allucinazioni.
La parte difficile: lo zoo dei framework
La vera battaglia è stata l'estrazione di questi confini. Ogni framework definisce i confini in modo diverso.
Un team usa i decorator di NestJS. Un altro usa le rotte di Express. Un altro ancora usa jQuery puro. Ognuno crea una struttura diversa nel codice.
Per far sì che tutto funzionasse, abbiamo dovuto costruire parser personalizzati per:
- NestJS e TypeORM
- Express e Fastify
- AngularJS e Redux
- Varie configurazioni di path-alias
Dovevamo puntare al 99% di precisione. Se il nostro tasso di connessione è solo del 90%, l'IA perde il 10% delle connessioni. In un sistema di produzione, quel 10% è proprio dove si nascondono i bug.
Ora eseguiamo un controllo giornaliero. Se il nostro tasso di connessione scende di oltre il 5%, riceviamo un avviso. Questo ci permette di accorgerci quando nuovi pattern di codice rompono i nostri parser.
Limitazioni attuali
Il grafo non è perfetto.
- La ricerca è difficile. Spesso è necessario conoscere il nome di una funzione per iniziare la ricerca.
- Esplosione di nodi. Seguire un percorso può trascinare con sé migliaia di piccole e inutili funzioni helper.
- Manutenzione. Ogni volta che un nuovo framework entra nel nostro stack, dobbiamo scrivere un nuovo parser.
Questa è la Parte 1. Nella Parte 2, discuterò dello strato service-product-graph (SPG) che ho costruito per colmare queste lacune.
Optional learning community: https://t.me/GyaanSetuAi
