Artificial Intelligence
Code-insluiting: een uitgebreide gids

Code-inbedding is een transformerende manier om codefragmenten weer te geven als dichte vectoren in een doorlopende ruimte. Deze inbedding legt de semantische en functionele relaties tussen codefragmenten vast, waardoor krachtige toepassingen in AI-ondersteund programmeren mogelijk worden. Net als bij woordinbedding bij natuurlijke taalverwerking (NLP), positioneren code-inbedding vergelijkbare codefragmenten dicht bij elkaar in de vectorruimte, waardoor machines code effectiever kunnen begrijpen en manipuleren.
Wat zijn code-insluitingen?
Code-inbedding zet complexe codestructuren om in numerieke vectoren die de betekenis en functionaliteit van de code vastleggen. In tegenstelling tot traditionele methoden die code als reeksen karakters behandelen, leggen inbeddingen de semantische relaties tussen delen van de code vast. Dit is cruciaal voor verschillende AI-gestuurde software-engineeringtaken, zoals het zoeken naar code, voltooiing, bugdetectie en meer.
Beschouw bijvoorbeeld deze twee Python-functies:
def add_numbers(a, b): return a + b
def sum_two_values(x, y): result = x + y return result
Hoewel deze functies er syntactisch anders uitzien, voeren ze dezelfde bewerking uit. Een goede code-inbedding zou deze twee functies met vergelijkbare vectoren weergeven, waarbij hun functionele gelijkenis ondanks hun tekstuele verschillen wordt vastgelegd.
Hoe worden code-insluitingen gemaakt?
Er zijn verschillende technieken voor het maken van code-insluitingen. Eén veel voorkomende aanpak omvat het gebruik van neurale netwerken om deze representaties te leren uit een grote dataset met code. Het netwerk analyseert de codestructuur, inclusief tokens (trefwoorden, identificatiegegevens), syntaxis (hoe de code is gestructureerd) en mogelijk commentaar om de relaties tussen verschillende codefragmenten te leren kennen.
Laten we het proces opsplitsen:
- Codeer als een reeks: Ten eerste worden codefragmenten behandeld als reeksen tokens (variabelen, trefwoorden, operators).
- Neurale netwerktraining: Een neuraal netwerk verwerkt deze reeksen en leert ze in vectorrepresentaties met een vaste grootte in kaart te brengen. Het netwerk houdt rekening met factoren als syntaxis, semantiek en relaties tussen code-elementen.
- Overeenkomsten vastleggen: De training heeft tot doel vergelijkbare codefragmenten (met vergelijkbare functionaliteit) dicht bij elkaar in de vectorruimte te plaatsen. Dit maakt taken mogelijk zoals het vinden van vergelijkbare code of het vergelijken van functionaliteit.
Hier is een vereenvoudigd Python-voorbeeld van hoe u code kunt voorbewerken voor insluiting:
import ast def tokenize_code(code_string): tree = ast.parse(code_string) tokens = [] for node in ast.walk(tree): if isinstance(node, ast.Name): tokens.append(node.id) elif isinstance(node, ast.Str): tokens.append('STRING') elif isinstance(node, ast.Num): tokens.append('NUMBER') # Add more node types as needed return tokens # Example usage code = """ def greet(name): print("Hello, " + name + "!") """ tokens = tokenize_code(code) print(tokens) # Output: ['def', 'greet', 'name', 'print', 'STRING', 'name', 'STRING']
Deze tokenized representatie kan vervolgens in een neuraal netwerk worden ingevoerd voor inbedding.
Bestaande benaderingen van code-inbedding
Bestaande methoden voor het insluiten van code kunnen in drie hoofdcategorieën worden ingedeeld:
Op tokens gebaseerde methoden
Op tokens gebaseerde methoden behandelen code als een reeks lexicale tokens. Technieken zoals Term Frequency-Inverse Document Frequency (TF-IDF) en deep learning-modellen zoals CodeBERT vallen in deze categorie.
Boomgebaseerde methoden
Op bomen gebaseerde methoden parseren code in abstracte syntaxisbomen (AST's) of andere boomstructuren, waarbij de syntactische en semantische regels van de code worden vastgelegd. Voorbeelden hiervan zijn op bomen gebaseerde neurale netwerken en modellen zoals code2vec en ASTNN.
Op grafieken gebaseerde methoden
Op grafieken gebaseerde methoden construeren grafieken uit code, zoals controlestroomgrafieken (CFG's) en gegevensstroomgrafieken (DFG's), om het dynamische gedrag en de afhankelijkheden van de code weer te geven. GrafiekCodeBERT is een opmerkelijk voorbeeld.
TransformCode: een raamwerk voor het insluiten van code
TransformCode is een raamwerk dat de beperkingen van bestaande methoden aanpakt door code-inbedding op een contrastieve manier te leren. Het is encoder- en taalonafhankelijk, wat betekent dat het elk encodermodel kan gebruiken en elke programmeertaal kan verwerken.
Het bovenstaande diagram illustreert het raamwerk van TransformCode voor het zonder toezicht leren van code-inbedding met behulp van contrastief leren. Het bestaat uit twee hoofdfasen: Vóór de training en Contrastief leren voor training. Hier volgt een gedetailleerde uitleg van elk onderdeel:
Vóór de training
1. Gegevensvoorverwerking:
- Gegevensset: De initiële invoer is een dataset met codefragmenten.
- Genormaliseerde code: De codefragmenten worden genormaliseerd om opmerkingen te verwijderen en variabelen te hernoemen naar een standaardindeling. Dit helpt bij het verminderen van de invloed van de naamgeving van variabelen op het leerproces en verbetert de generaliseerbaarheid van het model.
- Codetransformatie: De genormaliseerde code wordt vervolgens getransformeerd met behulp van verschillende syntactische en semantische transformaties om positieve monsters te genereren. Deze transformaties zorgen ervoor dat de semantische betekenis van de code onveranderd blijft, waardoor diverse en robuuste voorbeelden voor contrastief leren worden geboden.
2. Tokenisatie:
- Treintokenizer: Er wordt een tokenizer getraind op de codegegevensset om codetekst om te zetten in insluitingen. Dit houdt in dat de code wordt opgedeeld in kleinere eenheden, zoals tokens, die door het model kunnen worden verwerkt.
- Gegevensset insluiten: De getrainde tokenizer wordt gebruikt om de volledige codedataset om te zetten in inbedding, die als input dient voor de contrastieve leerfase.
Contrastief leren voor training
3. Trainingsproces:
- Treinvoorbeeld: Een voorbeeld uit de trainingsgegevensset wordt geselecteerd als representatie van de querycode.
- Positief monster: Het overeenkomstige positieve monster is de getransformeerde versie van de querycode, verkregen tijdens de fase van gegevensvoorverwerking.
- Negatieve monsters in batch: Negatieve monsters zijn alle andere codevoorbeelden in de huidige minibatch die verschillen van het positieve monster.
4. Encoder en momentum-encoder:
- Transformer-encoder met relatieve positie en MLP-projectiekop: Zowel de query als de positieve voorbeelden worden in een Transformer-encoder ingevoerd. De encoder bevat relatieve positiecodering om de syntactische structuur en relaties tussen tokens in de code vast te leggen. Een MLP-projectiekop (Multi-Layer Perceptron) wordt gebruikt om de gecodeerde representaties in kaart te brengen naar een lager-dimensionale ruimte waar het contrastieve leerdoel wordt toegepast.
- Momentum-encoder: Er wordt ook gebruik gemaakt van een momentum-encoder, die wordt bijgewerkt door een voortschrijdend gemiddelde van de parameters van de query-encoder. Dit helpt de consistentie en diversiteit van de representaties te behouden, waardoor de ineenstorting van het contrastieve verlies wordt voorkomen. De negatieve monsters worden gecodeerd met behulp van deze momentum-encoder en in de wachtrij geplaatst voor het contrastieve leerproces.
5. Contrastief leerdoel:
- Bereken InfoNCE-verlies (overeenkomst): De InfoNCE-verlies (Noise Contrastive Estimation). wordt berekend om de gelijkenis tussen de zoekopdracht en de positieve monsters te maximaliseren, terwijl de gelijkenis tussen de zoekopdracht en de negatieve monsters wordt geminimaliseerd. Dit doel zorgt ervoor dat de geleerde inbedding discriminerend en robuust is, waarbij de semantische gelijkenis van de codefragmenten wordt vastgelegd.
Het hele raamwerk maakt gebruik van de sterke punten van contrastief leren om betekenisvolle en robuuste code-inbedding te leren uit ongelabelde gegevens. Het gebruik van AST-transformaties en een momentum-encoder verbetert de kwaliteit en efficiëntie van de geleerde representaties verder, waardoor TransformCode een krachtig hulpmiddel wordt voor verschillende software-engineeringtaken.
Belangrijkste kenmerken van TransformCode
- Flexibiliteit en aanpassingsvermogen: Kan worden uitgebreid naar verschillende downstream-taken die coderepresentatie vereisen.
- Efficiëntie en schaalbaarheid: Vereist geen groot model of uitgebreide trainingsgegevens en ondersteunt elke programmeertaal.
- Ongecontroleerd en begeleid leren: Kan op beide leerscenario's worden toegepast door taakspecifieke labels of doelstellingen op te nemen.
- Instelbare parameters: Het aantal encoderparameters kan worden aangepast op basis van de beschikbare computerbronnen.
TransformCode introduceert een data-augmentatietechniek genaamd AST-transformatie, waarbij syntactische en semantische transformaties worden toegepast op de originele codefragmenten. Dit genereert diverse en robuuste voorbeelden voor contrastief leren.
Toepassingen van code-insluitingen
Code-inbedding heeft een revolutie teweeggebracht in verschillende aspecten van software-engineering door code te transformeren van een tekstueel formaat naar een numerieke representatie die bruikbaar is door machine learning-modellen. Hier zijn enkele belangrijke toepassingen:
Verbeterd zoeken naar codes
Traditioneel was het zoeken naar code afhankelijk van het matchen van trefwoorden, wat vaak tot irrelevante resultaten leidde. Code-insluitingen maken semantisch zoeken mogelijk, waarbij codefragmenten worden gerangschikt op basis van hun gelijkenis in functionaliteit, zelfs als ze verschillende trefwoorden gebruiken. Dit verbetert aanzienlijk de nauwkeurigheid en efficiëntie van het vinden van relevante code binnen grote codebases.
Slimmere voltooiing van codes
Tools voor het voltooien van code suggereren relevante codefragmenten op basis van de huidige context. Door gebruik te maken van code-insluitingen kunnen deze tools nauwkeurigere en behulpzamere suggesties bieden door de semantische betekenis van de code die wordt geschreven te begrijpen. Dit vertaalt zich in snellere en productievere codeerervaringen.
Geautomatiseerde codecorrectie en bugdetectie
Code-insluitingen kunnen worden gebruikt om patronen te identificeren die vaak duiden op bugs of inefficiënties in code. Door de gelijkenis tussen codefragmenten en bekende bugpatronen te analyseren, kunnen deze systemen automatisch oplossingen voorstellen of gebieden markeren die mogelijk verdere inspectie vereisen.
Verbeterde samenvatting van de code en het genereren van documentatie
Grote codebases ontberen vaak de juiste documentatie, waardoor het voor nieuwe ontwikkelaars moeilijk wordt om de werking ervan te begrijpen. Code-insluitingen kunnen beknopte samenvattingen creëren die de essentie van de functionaliteit van de code weergeven. Dit verbetert niet alleen de onderhoudbaarheid van de code, maar vergemakkelijkt ook de kennisoverdracht binnen ontwikkelteams.
Verbeterde codebeoordelingen
Codereviews zijn cruciaal voor het behoud van de codekwaliteit. Code-insluitingen kunnen reviewers helpen door potentiële problemen onder de aandacht te brengen en verbeteringen voor te stellen. Bovendien kunnen ze vergelijkingen tussen verschillende codeversies vergemakkelijken, waardoor het beoordelingsproces efficiënter wordt.
Meertalige codeverwerking
De wereld van softwareontwikkeling beperkt zich niet tot één enkele programmeertaal. Code-inbedding is veelbelovend voor het faciliteren van meertalige codeverwerkingstaken. Door de semantische relaties vast te leggen tussen code die in verschillende talen is geschreven, kunnen deze technieken taken mogelijk maken zoals het zoeken en analyseren van code in verschillende programmeertalen.