Aller au contenu principal

Codestral Embed : Embeddings de Code

Mis à jour le 29 juillet 2026

Codestral Embed : la recherche sémantique pour le code

Générer et compléter du code ne suffit pas : encore faut-il retrouver, dans un dépôt de plusieurs centaines de fichiers, celui qui traite déjà du problème. C’est le rôle du troisième outil spécialisé de Mistral AI, Codestral Embed (v25.05). Ce modèle d’embeddings transforme des extraits de code en vecteurs numériques et rend possible la recherche sémantique dans les repositories.

Qu’est-ce qu’un embedding de code ?

Un embedding est une représentation vectorielle dense d’un texte ou d’un morceau de code. La propriété qui nous intéresse est simple à énoncer : deux extraits sémantiquement proches produisent des vecteurs proches dans l’espace, même quand leur syntaxe n’a rien en commun. Les deux fonctions ci-dessous n’ont ni le même nom, ni les mêmes variables, ni la même implémentation.

# Fonction 1
def calculer_moyenne(nombres):
    return sum(nombres) / len(nombres)

# Fonction 2
def average(values):
    total = 0
    for v in values:
        total += v
    return total / len(values)

Un grep ne trouvera jamais la seconde à partir de la première. Codestral Embed, lui, produit pour ces deux fonctions des vecteurs voisins, parce qu’elles résolvent le même problème.

Caractéristiques techniques

Le modèle porte l’identifiant codestral-embed-latest (v25.05), s’invoque sur l’endpoint /v1/embeddings, et couvre le code source dans tous les langages supportés par Codestral. Il se distingue surtout par ses dimensions, configurables de 1536 à 3072. Le réglage à 1536 dimensions constitue un bon compromis qualité/coût et convient à la plupart des cas ; les 3072 dimensions visent la qualité maximale, pour les recherches les plus exigeantes. La règle sous-jacente est constante : plus de dimensions signifie une meilleure précision sémantique, mais aussi plus de stockage et plus de calcul à chaque comparaison. Sur un dépôt de taille moyenne, commencez à 1536 et ne montez que si les résultats vous paraissent flous.

Utilisation via l’API

L’appel de base ressemble à celui du chat : vous instanciez le client, vous passez un extrait, vous récupérez un vecteur.

from mistralai import Mistral
import os

client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])

code_snippet = """
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)
"""

response = client.embeddings.create(
    model="codestral-embed-latest",
    inputs=[code_snippet],
)

embedding = response.data[0].embedding
print(f"Dimensions : {len(embedding)}")
print(f"Premiers valeurs : {embedding[:5]}")

Le paramètre inputs est une liste, et ce détail compte : pour indexer un repository entier, vous envoyez plusieurs extraits en une seule requête plutôt qu’une requête par fichier. La différence sur un dépôt réel se compte en minutes.

extraits_code = [
    "def tri_bulle(liste): ...",
    "def tri_rapide(liste): ...",
    "def tri_fusion(liste): ...",
    "def recherche_binaire(liste, cible): ...",
]

response = client.embeddings.create(
    model="codestral-embed-latest",
    inputs=extraits_code,
)

embeddings = [item.embedding for item in response.data]

Recherche sémantique dans un codebase

Le cas d’usage principal découle directement de ce qui précède : au lieu de chercher par mots-clés, vous cherchez par intention. Le pipeline se décompose en deux temps. On indexe une fois le codebase, en attachant à chaque fichier son embedding ; puis on transforme la requête en vecteur et on classe les fichiers par similarité cosinus, la mesure standard de proximité entre deux vecteurs.

import numpy as np
from mistralai import Mistral

client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])

# 1. Indexer le codebase (à faire une fois)
def indexer_codebase(fichiers: list[dict]) -> list[dict]:
    """Indexe une liste de fichiers avec leurs embeddings."""
    contenus = [f["contenu"] for f in fichiers]

    response = client.embeddings.create(
        model="codestral-embed-latest",
        inputs=contenus,
    )

    for i, fichier in enumerate(fichiers):
        fichier["embedding"] = response.data[i].embedding

    return fichiers

# 2. Rechercher par intention
def rechercher_code(requete: str, index: list[dict], top_k: int = 5) -> list[dict]:
    """Recherche sémantique dans le codebase indexé."""
    response = client.embeddings.create(
        model="codestral-embed-latest",
        inputs=[requete],
    )
    vecteur_requete = np.array(response.data[0].embedding)

    # Calculer la similarité cosinus
    resultats = []
    for fichier in index:
        vecteur_fichier = np.array(fichier["embedding"])
        similarite = np.dot(vecteur_requete, vecteur_fichier) / (
            np.linalg.norm(vecteur_requete) * np.linalg.norm(vecteur_fichier)
        )
        resultats.append({**fichier, "score": similarite})

    resultats.sort(key=lambda x: x["score"], reverse=True)
    return resultats[:top_k]

# 3. Utilisation
resultats = rechercher_code(
    "fonction qui valide une adresse email",
    index=mon_index
)

Notez la requête finale : « fonction qui valide une adresse email ». Elle ne contient aucun identifiant du projet, aucun nom de fichier, aucun mot-clé du code. C’est toute la différence avec une recherche textuelle, et c’est ce qui la rend utilisable par quelqu’un qui découvre le dépôt.

Cas d’usage avancés

La combinaison la plus puissante consiste à chaîner Codestral Embed avec Codestral ou Devstral : c’est le pattern RAG (Retrieval-Augmented Generation) appliqué au code. On récupère d’abord les fichiers pertinents, on les injecte dans le message système, puis on pose la question. Le modèle répond alors à partir de votre codebase, et non de sa connaissance générale du langage.

# 1. Chercher les fichiers pertinents avec Codestral Embed
resultats = rechercher_code("gestion des erreurs HTTP", index)

# 2. Construire le contexte
contexte = "\n\n".join([r["contenu"] for r in resultats[:3]])

# 3. Générer une réponse avec Codestral
response = client.chat.complete(
    model="codestral-latest",
    messages=[
        {"role": "system", "content": f"Voici le code pertinent du projet :\n{contexte}"},
        {"role": "user", "content": "Comment améliorer la gestion des erreurs HTTP dans ce projet ?"}
    ],
)

Le même index sert à une tâche moins spectaculaire mais très rentable : la détection de code dupliqué. En comparant chaque paire de fonctions et en signalant celles dont la similarité dépasse un seuil, vous obtenez une liste de candidats au refactoring que personne dans l’équipe n’avait repérés.

# Comparer chaque paire de fonctions
for i, func_a in enumerate(fonctions):
    for j, func_b in enumerate(fonctions):
        if i >= j:
            continue
        similarite = cosinus(func_a["embedding"], func_b["embedding"])
        if similarite > 0.90:
            print(f"Duplication potentielle : {func_a['nom']} <-> {func_b['nom']}")

Le seuil de 0,90 mérite d’être ajusté sur votre propre code avant d’en tirer des conclusions : trop bas, il signale des fonctions qui se ressemblent sans faire la même chose ; trop haut, il ne retient que les copier-coller littéraux, ceux que vous auriez trouvés sans lui.

Points clés à retenir

  • Codestral Embed (v25.05) transforme du code en vecteurs pour la recherche sémantique
  • Il supporte de 1536 à 3072 dimensions selon le besoin de précision
  • La recherche sémantique permet de chercher par intention, pas par mots-clés
  • Le pattern RAG (recherche + génération) est le cas d’usage le plus puissant
  • Les embeddings permettent aussi la détection de duplication et le clustering de code