Zum Hauptinhalt springen
Lektion 8 von 18 · Embeddings, RAG und semantische Suche

Anwendungsfälle: Code-Einbettungen

Lektion 8 von 18 Aktualisiert am 2. November 2026 Entwickler
Auf dieser Seite
  1. Über die Suche hinaus
  2. Repository-Analysen
  3. Duplikaterkennung
  4. Clustering nach Funktionalität
  5. Kontextueller Code-Assistent
  6. Code-Qualitätsmetriken
  7. Kernaussagen

Über die Suche hinaus

Code-Einbettungen dienen nicht nur der semantischen Suche. Sie ermöglichen erweiterte Anwendungen: Repository-Analysen, Clustering, Duplikaterkennung und Entwicklungsassistenten. In dieser Lektion erkunden Sie diese Anwendungsfälle mit konkretem Python-Code.

Diese vier Anwendungsfälle teilen ein gemeinsames Merkmal: Sie nutzen die Geometrie des Index statt einer Abfrage. Sobald Ihre Dateien im Vektorraum platziert sind, erzählen ihre relativen Positionen eine Geschichte über das Projekt selbst: was ähnelt wem, was sich wiederholt und was auffällt.

Repository-Analysen

Analysieren Sie die semantische Struktur eines Projekts, um zu verstehen, wie der Code organisiert ist. K-Means gruppiert Dateien in fünf Familien basierend auf ihrer Vektor-Nähe, ohne den Ordnerbaum jemals zu betrachten. Das Ergebnis ist oft lehrreich: In einem unübersichtlichen Projekt werden Dateien aus sehr unterschiedlichen Verzeichnissen in derselben Cluster landen, weil sie tatsächlich denselben Sachverhalt behandeln.

import numpy as np
from sklearn.cluster import KMeans
from mistralai.client import Mistral

client = Mistral(api_key=api_key)

def analyze_repo(code_files, n_clusters=5):
    """Analysiert die semantische Struktur eines Repositories."""
    # Kodiert alle Dateien
    inputs = [f["content"][:3000] for f in code_files]
    response = client.embeddings.create(
        model="codestral-embed",
        inputs=inputs,
    )
    embeddings = np.array([d.embedding for d in response.data])

    # K-Means Clustering
    kmeans = KMeans(n_clusters=n_clusters, random_state=42, n_init=10)
    labels = kmeans.fit_predict(embeddings)

    # Gruppierung von Dateien nach Cluster
    clusters = {}
    for i, label in enumerate(labels):
        if label not in clusters:
            clusters[label] = []
        clusters[label].append(code_files[i]["path"])

    return clusters

# Nutzung
clusters = analyze_repo(code_files, n_clusters=5)
for cluster_id, files in clusters.items():
    print(f"\nCluster {cluster_id} ({len(files)} Dateien):")
    for f in files[:5]:
        print(f"  - {f}")

Der Parameter random_state=42 fixiert die Initialisierung: Ohne ihn würden zwei aufeinanderfolgende Ausführungen unterschiedliche Cluster-Nummern ergeben, was einen Vergleich von Analysen über die Zeit unmöglich macht.

Duplikaterkennung

Identifizieren Sie duplizierte oder nahezu duplizierte Code-Schnipsel in Ihrer Basis. Im Gegensatz zu einem klassischen Erkennungstool, das Text vergleicht, erfasst dieser Ansatz auch umgeschriebene Duplikate – die Datei, die von einem Modul in ein anderes kopiert, umbenannt und mit anderen Variablen, aber derselben Logik versehen wurde.

from sklearn.metrics.pairwise import cosine_similarity

def find_duplicates(code_files, embeddings, threshold=0.95):
    """Findet Paare von nahezu identischen Dateien."""
    sim_matrix = cosine_similarity(embeddings)
    duplicates = []

    for i in range(len(code_files)):
        for j in range(i + 1, len(code_files)):
            if sim_matrix[i][j] >= threshold:
                duplicates.append({
                    "file_a": code_files[i]["path"],
                    "file_b": code_files[j]["path"],
                    "similarity": float(sim_matrix[i][j]),
                })

    # Sortierung nach absteigender Ähnlichkeit
    duplicates.sort(key=lambda x: x["similarity"], reverse=True)
    return duplicates

# Duplikate finden
dupes = find_duplicates(code_files, embeddings, threshold=0.92)
print(f"{len(dupes)} potenzielle Duplikat-Paare gefunden:")
for d in dupes[:10]:
    print(f"  {d['similarity']:.3f} : {d['file_a']} <-> {d['file_b']}")

Der innere Schleife beginnt bei i + 1, um jedes Paar nur einmal zu vergleichen. Beachten Sie jedoch die Kosten: Die Ähnlichkeitsmatrix ist quadratisch, und bei mehr als einigen tausend Dateien müssen Sie auf einen approximierten Index statt auf eine erschöpfende Berechnung umsteigen. Das Absenken des Schwellenwerts von 0,95 auf 0,92 wirft ein breiteres Netz für umgeschriebene Duplikate auf, zum Preis einiger falsch positiver Ergebnisse, die manuell sortiert werden müssen.

Clustering nach Funktionalität

K-Means erfordert, dass Sie die Anzahl der Gruppen im Voraus kennen, was bei der Entdeckung eines Projekts selten der Fall ist. DBSCAN adressiert diese Einschränkung: Es bestimmt die Anzahl der Gruppen selbst und ermöglicht entscheidend, dass eine Datei keiner Gruppe angehören kann – was der Bedeutung des Labels “Unclassified” (Nicht klassifiziert) im folgenden Code entspricht.

from sklearn.cluster import DBSCAN

def cluster_by_functionality(code_files, embeddings, eps=0.3, min_samples=2):
    """Gruppieren Sie Code nach Funktionalität unter Verwendung von DBSCAN."""
    # DBSCAN auf Kosinus-Abständen
    distance_matrix = 1 - cosine_similarity(embeddings)
    clustering = DBSCAN(eps=eps, min_samples=min_samples, metric="precomputed")
    labels = clustering.fit_predict(distance_matrix)

    # Organisation nach Cluster
    groups = {}
    for i, label in enumerate(labels):
        group_name = f"Group {label}" if label >= 0 else "Unclassified"
        if group_name not in groups:
            groups[group_name] = []
        groups[group_name].append(code_files[i]["path"])

    return groups

groups = cluster_by_functionality(code_files, embeddings)
for name, files in groups.items():
    print(f"\n{name} ({len(files)} Dateien):")
    for f in files[:3]:
        print(f"  - {f}")

Die Umwandlung über 1 - cosine_similarity verwandelt Ähnlichkeit in Abstand, das Format, das DBSCAN mit metric="precomputed" erwartet. Der Parameter eps=0.3 bedeutet daher, dass zwei Dateien Nachbarn sind, beginnend bei einer Kosinus-Ähnlichkeit von 0,7.

Kontextueller Code-Assistent

Dieses letzte Beispiel setzt die vorherigen Bausteine zu einem echten RAG-System für Code zusammen: Suche nach relevanten Dateien, Aufbau eines Kontexts und Aufruf des LLM. Der Schwellenwert von 0,5 filtert upstream – es ist besser, dem Modell zwei Dateien zu geben, die wirklich mit der Frage zu tun haben, als drei, von denen eine vom Thema abweicht und es irreführen würde.

def code_assistant(question, code_files, embeddings, top_k=3):
    """Findet relevanten Code, um eine Frage zu beantworten."""
    # Kodiert die Frage
    response = client.embeddings.create(
        model="codestral-embed",
        inputs=[question],
    )
    query_emb = np.array(response.data[0].embedding)

    # Findet den relevantesten Code
    sims = cosine_similarity([query_emb], embeddings)[0]
    top_indices = np.argsort(sims)[::-1][:top_k]

    context_parts = []
    for idx in top_indices:
        if sims[idx] > 0.5:  # Mindestenschwellenwert
            context_parts.append(
                f"# File: {code_files[idx]['path']}\n"
                f"{code_files[idx]['content'][:1500]}"
            )

    context = "\n\n---\n\n".join(context_parts)

    # Baut den Prompt für das LLM
    prompt = f"""Hier ist relevanter Code aus unserem Projekt:

{context}

Entwicklerfrage: {question}

Beantworten Sie basierend auf dem obigen Code."""

    # Ruft das LLM mit Kontext auf
    chat_response = client.chat.complete(
        model="mistral-large-latest",
        messages=[{"role": "user", "content": prompt}],
    )

    return chat_response.choices[0].message.content

# Nutzung
answer = code_assistant(
    "Wie funktioniert Authentifizierung in diesem Projekt?",
    code_files,
    embeddings,
)
print(answer)

Der Dateipfad wird als Kommentar über jedem Snippet injiziert. Dies ist nicht dekorativ: Das Modell nutzt ihn, um seine Quellen anzuführen, und der Entwickler, der die Antwort liest, weiß sofort, wo er zur Überprüfung hinfahren kann.

Code-Qualitätsmetriken

Schließlich helfen Einbettungen dabei, das Auffällige zu erkennen. Die Funktion berechnet den Schwerpunkt des Index – den “durchschnittlichen Code” des Projekts – und misst, wie weit jede davon abweicht. Ein z-Score größer als 2 signalisiert eine Datei, die nichts anderem ähnelt: manchmal ein Stück Code, das generiert oder von außen kopiert wurde, manchmal einfach die einzige Datei, die in einem alten Stil geschrieben wurde. In beiden Fällen ist sie ein guter Kandidat für eine Überprüfung.

def detect_outliers(code_files, embeddings, threshold=2.0):
    """Erkennt atypische Code-Dateien."""
    # Berechnet den Schwerpunkt (Mittelvektor)
    centroid = embeddings.mean(axis=0)

    # Abstand jeder Datei zum Schwerpunkt
    distances = np.linalg.norm(embeddings - centroid, axis=1)

    # Dateien jenseits von N Standardabweichungen
    mean_dist = distances.mean()
    std_dist = distances.std()

    outliers = []
    for i, dist in enumerate(distances):
        z_score = (dist - mean_dist) / std_dist
        if z_score > threshold:
            outliers.append({
                "path": code_files[i]["path"],
                "z_score": float(z_score),
            })

    outliers.sort(key=lambda x: x["z_score"], reverse=True)
    return outliers

outliers = detect_outliers(code_files, embeddings)
print(f"{len(outliers)} atypische Dateien:")
for o in outliers:
    print(f"  z={o['z_score']:.2f} : {o['path']}")

Denken Sie daran, dass “atypisch” nicht “schlecht” bedeutet. Das Werkzeug gibt Ihnen eine Liste von Dateien, die Sie ansehen sollen, kein Urteil: Es ist ein Ausgangspunkt für die menschliche Überprüfung, niemals eine Metrik, die auf einem Qualitäts-Dashboard angezeigt wird.

Kernaussagen

  • Code-Einbettungen ermöglichen automatisches Clustering nach Funktionalität
  • Die Duplikaterkennung nutzt einen Schwellenwert für die Kosinus-Ähnlichkeit (0,92–0,95)
  • Ein Code-Assistent kombiniert semantische Suche mit einem LLM für Code-RAG
  • Atypische Dateien (Ausreißer) können Code signalisieren, der einer Überprüfung bedarf
  • DBSCAN ist gegenüber K-Means vorzuziehen, wenn die Anzahl der Gruppen unbekannt ist