Semantische Code-Suche
Auf dieser Seite
Code nach Bedeutung durchsuchen
Die traditionelle Code-Suche stützt sich auf Schlüsselwörter: Sie geben einen Funktionsnamen oder ein Wort aus einem Kommentar ein. Semantische Code-Suche geht einen Schritt weiter: Sie findet Code nach seiner Bedeutung oder Absicht, auch wenn die genauen Begriffe nicht übereinstimmen.
Mit codestral-embed können Sie Code mit natürlicher Sprache durchsuchen. Eine Abfrage wie „Funktion, die eine Liste sortiert” findet eine quicksort-Implementierung, auch wenn das Wort „sortieren” im Code nie vorkommt. Dies spiegelt die tägliche Realität wider, wenn ein Entwickler einem bestehenden Projekt beitreten muss: Sie wissen, wonach Sie suchen, haben aber keine Ahnung, wie das vorherige Team es benannt hat.
Indexierung eines Code-Verzeichnisses
Der erste Schritt besteht darin, jede Datei oder jede Funktion in einem Projekt zu extrahieren und zu kodieren. Die folgende Funktion durchläuft den Verzeichnisbaum und filtert Ordner aus, die den Index unnötig aufblähen würden. Allein node_modules kann das Zehnfache der Größe Ihres eigentlichen Codes erreichen, und keine seiner Dateien ist für Ihre Suche relevant.
import os
import numpy as np
from mistralai.client import Mistral
client = Mistral(api_key=api_key)
def extract_code_files(directory, extensions=(".py", ".js", ".ts")):
"""Extrahiert alle Code-Dateien aus einem Verzeichnis."""
code_files = []
for root, dirs, files in os.walk(directory):
# Ignoriert irrelevante Verzeichnisse
dirs[:] = [d for d in dirs if d not in ("node_modules", ".git", "__pycache__", "venv")]
for f in files:
if any(f.endswith(ext) for ext in extensions):
filepath = os.path.join(root, f)
with open(filepath, "r", encoding="utf-8", errors="ignore") as fh:
content = fh.read()
if content.strip():
code_files.append({
"path": filepath,
"content": content[:4000], # Abschneiden, falls zu lang
})
return code_files
# Dateien extrahieren
code_files = extract_code_files("./my-project/")
print(f"{len(code_files)} Code-Dateien gefunden")
Zwei Implementierungsdetails verdienen Aufmerksamkeit. Die Modifikation von dirs[:] am Ort ist nicht nur eine Abkürzung; sie ist der einzige Weg, um os.walk davon abzuhalten, in diese Verzeichnisse einzusteigen. Eine Neuweisung der Variable ohne Slicing hätte keine Wirkung. Was das Abschneiden bei 4.000 Zeichen betrifft, schützt dies davor, dass monströse Dateien den Aufruf sprengen, während gleichzeitig der Dateikopf – Importe, Hauptdefinitionen – erhalten bleibt, der das wichtigste Signal trägt.
Kodierung und Indexierung
Die Kodierung erfolgt in Batches von zwanzig Dateien, mit einer Anzeige des Fortschritts. Bei einem Repository mit mehreren hundert Dateien läuft dieser Loop mehrere Minuten. Ohne Zähler haben Sie keine Möglichkeit, langsame Verarbeitung von einem hängenden Aufruf zu unterscheiden.
def index_code_files(code_files, batch_size=20):
"""Erstellt Einbettungen für alle Code-Dateien."""
all_embeddings = []
for i in range(0, len(code_files), batch_size):
batch = code_files[i:i + batch_size]
inputs = [f["content"] for f in batch]
response = client.embeddings.create(
model="codestral-embed",
inputs=inputs,
)
all_embeddings.extend([d.embedding for d in response.data])
print(f"Kodiert {min(i + batch_size, len(code_files))}/{len(code_files)}")
return np.array(all_embeddings)
embeddings = index_code_files(code_files)
print(f"Index: {embeddings.shape}")
Die Reihenfolge der Einbettungen in der Matrix entspricht exakt der Reihenfolge von code_files. Diese implizite Korrespondenz ist der Dreh- und Angelpunkt für alles, was folgt: Sie erlaubt es, dass ein von der Rangliste zurückgegebener Index auf einen spezifischen Dateipfad verweist.
Suche mit natürlicher Sprache
Der wesentliche Vorteil von codestral-embed besteht darin, dass Sie mit einer Frage auf Französisch oder Englisch suchen können. Die Funktion kodiert die Abfrage mit demselben Modell, berechnet Ähnlichkeiten gegenüber dem gesamten Index und gibt die top_k besten Ergebnisse zusammen mit einem Vorschau-Text zurück.
from sklearn.metrics.pairwise import cosine_similarity
def search_code(query, code_files, embeddings, top_k=5):
"""Sucht nach Code unter Verwendung von natürlichen Sprachbeschreibungen."""
# Kodierung der Abfrage
response = client.embeddings.create(
model="codestral-embed",
inputs=[query],
)
query_emb = np.array(response.data[0].embedding)
# Berechnung der Ähnlichkeiten
sims = cosine_similarity([query_emb], embeddings)[0]
# Top-k-Ergebnisse
top_indices = np.argsort(sims)[::-1][:top_k]
results = []
for idx in top_indices:
results.append({
"path": code_files[idx]["path"],
"score": float(sims[idx]),
"preview": code_files[idx]["content"][:200],
})
return results
# Suchen mit natürlicher Sprache
queries = [
"email validation function",
"database connection",
"HTTP error handling",
"sorting algorithm",
]
for query in queries:
print(f"\n--- Abfrage: '{query}' ---")
results = search_code(query, code_files, embeddings, top_k=3)
for r in results:
print(f" [{r['score']:.3f}] {r['path']}")
Das Feld preview hat unmittelbaren praktischen Nutzen: Es spart Ihnen das Öffnen von fünf Dateien, um herauszufinden, welche tatsächlich übereinstimmt. In einer Editor-Integration werden diese zweihundert Zeichen zur Vorschauzeile unter jedem Ergebnis.
Suche über Sprachgrenzen hinweg
codestral-embed versteht Logik unabhängig von der Programmiersprache. Sie können nach einem Python-Muster suchen und das Äquivalent in JavaScript finden:
# Suche unter Verwendung eines Code-Beispiels in einer Sprache...
query_python = "def authenticate(username, password): check credentials and return token"
# ...und finden das Äquivalent in einer anderen Sprache
results = search_code(query_python, code_files, embeddings)
# Kann eine .js-Datei mit einer ähnlichen Funktion zurückgeben
Diese Fähigkeit ist für Anwendungen von unschätzbarem Wert, die zwischen einem Python-Backend und einem TypeScript-Frontend aufgespalten sind, wo dieselbe Geschäftsregel manchmal auf beiden Seiten implementiert wird. Das Finden beider Implementierungen aus einer einzigen Abfrage hilft Ihnen, Divergenzen zu erkennen, bevor ein Fehler sie in der Produktion offenbart.
Suche nach Funktions-Signatur
Sie können auch nach der erwarteten Form statt nach dem funktionalen Bereich suchen. Die Beschreibung der Struktur – eine asynchrone Funktion, eine Klasse, Middleware, ein Test – lenkt die Suche auf eine Art von Code-Objekt statt auf ein Thema.
technical_queries = [
"async function that fetches data from API and handles errors",
"class with CRUD methods for database operations",
"middleware that checks authentication token",
"unit test for user registration",
]
for q in technical_queries:
results = search_code(q, code_files, embeddings, top_k=2)
print(f"\n{q}:")
for r in results:
print(f" -> {r['path']} (score: {r['score']:.3f})")
Probieren Sie diese vier Abfragen in Ihrem eigenen Repository aus, bevor Sie fortfahren. Sie werden feststellen, dass die Ergebnisse bei sehr langen Dateien deutlich abnehmen, wo das Abschneiden auf 4.000 Zeichen den nützlichen Teil abgeschnitten hat. Dies ist der Moment, zu entscheiden, ob Sie ganze Dateien indizieren oder besser noch, Funktionen einzeln aufschlüsseln.
Kernaussagen
codestral-embedermöglicht die Suche nach Code unter Verwendung von natürlichen Sprachbeschreibungen- Die Indexierung beinhaltet das Kodieren aller Code-Dateien in Vektoren
- Die Suche über Sprachgrenzen hinweg funktioniert: Ein Python-Muster findet das JS-Äquivalent
- Filtern Sie irrelevante Verzeichnisse (node_modules, .git, venv) während der Extraktion
- Schneiden Sie sehr lange Dateien ab, um die Modellgrenzen einzuhalten