I denne blog vil vi vise dig, hvordan du indekserer kodebase til RAG med CocoIndex. CocoIndex er et værktøj til at hjælpe dig med at indeksere og forespørge på dine data. Det er designet til at blive brugt som en ramme til at bygge din egen datapipeline. CocoIndex giver indbygget support til kodebase-chunking med indbygget Tree-sitter-understøttelse. Træsitter er et parser-generatorværktøj og et inkrementelt parsingbibliotek, det er tilgængeligt i Rust 🦀 - . CocoIndex har indbygget Rust-integration med Tree-sitter for effektivt at parse kode og udtrække syntakstræer til forskellige programmeringssprog. Tree-sitter GitHub Codebase chunking er processen med at nedbryde en kodebase i mindre, semantisk meningsfulde bidder. CocoIndex udnytter Tree-sitters evner til intelligent at dele kode baseret på den faktiske syntaksstruktur frem for vilkårlige linjeskift. Disse semantisk sammenhængende bidder bruges derefter til at bygge et mere effektivt indeks for RAG-systemer, hvilket muliggør mere præcis kodehentning og bedre kontekstbevarelse. Fast pass 🚀 - du kan finde den fulde kode . Kun ~ 50 linjer Python-kode til RAG-rørledningen, tjek det ud 🤗! her Giv venligst en stjerne for at støtte os, hvis du kan lide vores arbejde. Tusind tak med et varmt kokosnøddekram 🥥🤗. CocoIndex på Github Forudsætninger Hvis du ikke har Postgres installeret, se venligst . CocoIndex bruger Postgres til at administrere dataindekset, vi har det på vores køreplan for at understøtte andre databaser, inklusive de igangværende. Hvis du er interesseret i andre databaser, så lad os det vide ved at oprette et eller . installationsvejledningen GitHub-problem Discord Definer cocoIndex Flow Lad os definere cocoIndex-flowet til at læse fra en kodebase og indeksere det til RAG. Flowdiagrammet ovenfor illustrerer, hvordan vi behandler vores kodebase: Læs kodefiler fra det lokale filsystem Udpak filtypenavne Opdel kode i semantiske bidder ved hjælp af Tree-sitter Generer indlejringer for hver del Gem i en vektordatabase til hentning Lad os implementere dette flow trin for trin. 1. Tilføj kodebasen som en kilde . @cocoindex.flow_def(name="CodeEmbedding") def code_embedding_flow(flow_builder: cocoindex.FlowBuilder, data_scope: cocoindex.DataScope): """ Define an example flow that embeds files into a vector database. """ data_scope["files"] = flow_builder.add_source( cocoindex.sources.LocalFile(path="../..", included_patterns=["*.py", "*.rs", "*.toml", "*.md", "*.mdx"], excluded_patterns=[".*", "target", "**/node_modules"])) code_embeddings = data_scope.add_collector() I dette eksempel skal vi indeksere cocoindex-kodebasen fra rodmappen. Du kan ændre stien til den kodebase, du vil indeksere. Vi vil indeksere alle filerne med filtypenavnene , , , , , og springe mapper over startende med ., target (i roden) og node_modules (under enhver mappe). .py .rs .toml .md .mdx vil oprette en tabel med følgende underfelter, se her. flow_builder.add_source dokumentation (nøgle, type: ): filnavnet på filen, f.eks. filename str dir1/file1.md (type: hvis er , ellers ): indholdet af filen content str binary False bytes 2. Behandl hver fil og indsaml oplysningerne . 2.1 Udpak filtypenavnet Lad os først definere en funktion til at udtrække filtypenavnet, mens hver fil behandles. Du kan finde dokumentationen for brugerdefineret funktion . her @cocoindex.op.function() def extract_extension(filename: str) -> str: """Extract the extension of a filename.""" return os.path.splitext(filename)[1] Derefter skal vi behandle hver fil og indsamle oplysningerne. # ... with data_scope["files"].row() as file: file["extension"] = file["filename"].transform(extract_extension) Her udtrækker vi filtypenavnet og gemmer det i . for eksempel, hvis filnavnet er , vil være . extension spec.rs extension .rs 2.2 Del filen i bidder Dernæst skal vi opdele filen i bidder. Vi bruger funktionen til at opdele filen i bidder. Du kan finde dokumentationen til funktionen . SplitRecursively her CocoIndex giver indbygget support til Tree-sitter, så du kan videregive sproget til . For at se alle understøttede sprognavne og udvidelser, se dokumentationen . Alle de større sprog er understøttet, f.eks. Python, Rust, JavaScript, TypeScript, Java, C++ osv. Hvis det er uspecificeret, eller det angivne sprog ikke understøttes, vil det blive behandlet som almindelig tekst. language her with data_scope["files"].row() as file: # ... file["chunks"] = file["content"].transform( cocoindex.functions.SplitRecursively(), language=file["extension"], chunk_size=1000, chunk_overlap=300) 2.3 Integrer bidderne Vi vil bruge -funktionen til at indlejre bidderne. Du kan finde dokumentationen til funktionen . Der er 12k modeller understøttet af 🤗 . Du kan bare vælge din yndlingsmodel. SentenceTransformerEmbed her Hugging Face def code_to_embedding(text: cocoindex.DataSlice) -> cocoindex.DataSlice: """ Embed the text using a SentenceTransformer model. """ return text.transform( cocoindex.functions.SentenceTransformerEmbed( model="sentence-transformers/all-MiniLM-L6-v2")) Så for hver chunk vil vi indlejre den ved hjælp af funktionen. og saml indlejringerne til samleren. code_to_embedding code_embeddings Vi udtrækker denne code_to_embedding-funktion i stedet for direkte at kalde transform(cocoindex.functions.SentenceTransformerEmbed(...)) på plads. Dette er fordi vi ønsker at gøre denne delt mellem indekseringsflowbygningen og forespørgselshåndteringsdefinitionen. Alternativt for at gøre det nemmere. Det er også OK at undgå denne ekstra funktion og direkte gøre tingene på plads - ikke en big deal at kopiere indsætte en lille smule, vi gjorde dette til projektet. quickstart- with data_scope["files"].row() as file: # ... with file["chunks"].row() as chunk: chunk["embedding"] = chunk["text"].call(code_to_embedding) code_embeddings.collect(filename=file["filename"], location=chunk["location"], code=chunk["text"], embedding=chunk["embedding"]) 2.4 Saml indlejringerne Lad os endelig eksportere indlejringerne til en tabel. code_embeddings.export( "code_embeddings", cocoindex.storages.Postgres(), primary_key_fields=["filename", "location"], vector_index=[("embedding", cocoindex.VectorSimilarityMetric.COSINE_SIMILARITY)]) 3. Konfigurer forespørgselshandler til dit indeks Vi vil bruge til at forespørge indekset. Bemærk, at vi skal overføre funktionen til parameteren . Dette skyldes, at forespørgselshandleren vil bruge den samme indlejringsmodel som den, der blev brugt i flowet. SimpleSemanticsQueryHandler code_to_embedding query_transform_flow query_handler = cocoindex.query.SimpleSemanticsQueryHandler( name="SemanticsSearch", flow=code_embedding_flow, target_name="code_embeddings", query_transform_flow=code_to_embedding, default_similarity_metric=cocoindex.VectorSimilarityMetric.COSINE_SIMILARITY) Definer en hovedfunktion til at køre forespørgselshåndteringen. @cocoindex.main_fn() def _run(): # Run queries in a loop to demonstrate the query capabilities. while True: try: query = input("Enter search query (or Enter to quit): ") if query == '': break results, _ = query_handler.search(query, 10) print("\nSearch results:") for result in results: print(f"[{result.score:.3f}] {result.data['filename']}") print(f" {result.data['code']}") print("---") print() except KeyboardInterrupt: break if __name__ == "__main__": load_dotenv(override=True) _run() @cocoindex.main_fn() dekoratoren initialiserer biblioteket med indstillinger indlæst fra miljøvariabler. Se for flere detaljer. dokumentationen for initialisering Kør indeksopsætning og opdatering 🎉 Nu er du klar! Kør følgende kommandoer for at opsætte og opdatere indekset. python main.py cocoindex setup python main.py cocoindex update Du vil se status for indeksopdateringer i terminalen Test forespørgslen På dette tidspunkt kan du starte cocoindex-serveren og udvikle din RAG-runtime mod dataene. For at teste dit indeks er der to muligheder: Mulighed 1: Kør indeksserveren i terminalen python main.py Når du ser prompten, kan du indtaste din søgeforespørgsel. for eksempel: spec. Enter search query (or Enter to quit): spec Du kan finde søgeresultaterne i terminalen De returnerede resultater - hver post indeholder score (Cosinus-lighed), filnavn og kodestykket, der bliver matchet. På cocoindex bruger vi til at måle ligheden mellem forespørgslen og de indekserede data. Du kan også skifte til andre målinger og hurtigt teste det. cocoindex.VectorSimilarityMetric.COSINE_SIMILARITY For at lære mere om Consine Similarity, se . Wiki Mulighed 2: Kør CocoInsight for at forstå din datapipeline og dataindeks CocoInsight er et værktøj til at hjælpe dig med at forstå din datapipeline og dataindeks. Den opretter forbindelse til din lokale CocoIndex-server uden dataopbevaring. CocoInsight er i Early Access nu (gratis) 😊 Du fandt os! En hurtig 3 minutters videovejledning om CocoInsight: . Se på YouTube Kør CocoIndex -serveren python main.py cocoindex server -c https://cocoindex.io Når serveren kører, skal du åbne i din browser. Du vil være i stand til at oprette forbindelse til din lokale CocoIndex-server og udforske din datapipeline og indeks. CocoInsight På højre side kan du se det dataflow, vi definerede. I venstre side kan du se dataindekset i dataeksemplet. Du kan klikke på en hvilken som helst række for at se detaljerne for denne dataindtastning, inklusive det fulde indhold af kodestykker og deres indlejringer. Fællesskabet Vi elsker at høre fra fællesskabet! Du kan finde os på og . Github Discord Hvis du kan lide dette indlæg og vores arbejde, så støtte med en stjerne ⭐. Tak med et varmt kokosnøddekram 🥥🤗. CocoIndex på Github