Aller au contenu principal

Types de Données et Dimensions

Mis à jour le 29 juillet 2026

Optimiser taille et qualité

codestral-embed offre un contrôle précis sur deux axes : le nombre de dimensions et le type de données (dtype) des valeurs. Ces paramètres permettent d’ajuster le compromis entre qualité de la recherche et coût de stockage/calcul.

L’enjeu devient concret dès que les volumes montent. Un index de deux millions de fonctions en 1536 dimensions float pèse environ douze gigaoctets et ne tient plus en mémoire sur une machine ordinaire ; le même index en int8 sur 768 dimensions descend sous le gigaoctet et redevient interrogeable en temps réel. C’est cette arithmétique, et non une préférence esthétique, qui doit guider vos choix.

Les cinq types de sortie

float (défaut)

Le type float produit des valeurs en virgule flottante 32 bits. C’est le format le plus précis, idéal quand la qualité prime sur l’espace de stockage.

from mistralai import Mistral

client = Mistral(api_key=api_key)

response = client.embeddings.create(
    model="codestral-embed",
    output_dtype="float",
    inputs=["def hello(): print('world')"],
)

embedding = response.data[0].embedding
print(f"Type: float, Valeurs: {embedding[:5]}")
# [0.0234375, -0.15625, 0.08984375, 0.01171875, -0.046875]

int8

Chaque dimension est un entier entre -128 et 127. Utilise 4x moins de mémoire que float32 avec une perte de qualité minime. Comparez les valeurs affichées avec celles de l’exemple précédent : c’est le même vecteur, quantifié sur une échelle plus grossière, et le classement des résultats reste presque inchangé.

response = client.embeddings.create(
    model="codestral-embed",
    output_dtype="int8",
    inputs=["def hello(): print('world')"],
)

embedding = response.data[0].embedding
print(f"Type: int8, Valeurs: {embedding[:5]}")
# [3, -20, 11, 1, -6]

uint8

Similaire à int8 mais avec des valeurs entre 0 et 255 (non signées). Utile pour certains moteurs de recherche vectorielle qui n’acceptent que des valeurs positives — une contrainte que vous découvrez généralement au moment de l’intégration, pas avant.

response = client.embeddings.create(
    model="codestral-embed",
    output_dtype="uint8",
    inputs=["def hello(): print('world')"],
)

embedding = response.data[0].embedding
print(f"Type: uint8, Valeurs: {embedding[:5]}")
# [131, 108, 139, 129, 122]

binary

Le format le plus compact. Chaque dimension est quantisée en 1 bit, puis les bits sont regroupés par paquets de 8 dans des valeurs int8. Le vecteur résultant est 32x plus petit que float — la longueur de 192 affichée ci-dessous correspond bien aux 1536 dimensions d’origine, empaquetées huit par huit.

response = client.embeddings.create(
    model="codestral-embed",
    output_dtype="binary",
    inputs=["def hello(): print('world')"],
)

embedding = response.data[0].embedding
print(f"Type: binary, Longueur: {len(embedding)}")
# Longueur: 192 (au lieu de 1536 en float)

ubinary

Identique à binary mais avec des valeurs uint8 (0-255) au lieu de int8 (-128 à 127). Le choix entre les deux relève de ce qu’accepte votre moteur de stockage en aval, pas de la qualité de recherche.

Impact sur la qualité

Les chiffres de compression ne disent rien de ce que vous perdez réellement. La fonction suivante mesure la chose sur un cas concret : un test de palindrome, interrogé en français, encodé successivement avec trois dtypes. Les similarités obtenues vous donnent l’ordre de grandeur de la dégradation sur votre propre matière.

import numpy as np
from sklearn.metrics.pairwise import cosine_similarity

def compare_dtypes(code_snippet, query):
    """Comparer la qualité de recherche selon le dtype."""
    dtypes = ["float", "int8", "uint8"]
    results = {}

    for dtype in dtypes:
        # Encoder le code et la requête avec le même dtype
        resp_code = client.embeddings.create(
            model="codestral-embed",
            output_dtype=dtype,
            inputs=[code_snippet],
        )
        resp_query = client.embeddings.create(
            model="codestral-embed",
            output_dtype=dtype,
            inputs=[query],
        )

        emb_code = np.array(resp_code.data[0].embedding, dtype=np.float32)
        emb_query = np.array(resp_query.data[0].embedding, dtype=np.float32)

        sim = cosine_similarity([emb_code], [emb_query])[0][0]
        results[dtype] = sim

    return results

# Tester
code = "def is_palindrome(s): return s == s[::-1]"
query = "fonction qui vérifie si un mot est un palindrome"

scores = compare_dtypes(code, query)
for dtype, score in scores.items():
    print(f"  {dtype:8s}: similarité = {score:.4f}")

Notez que le code et la requête sont toujours encodés avec le même dtype à l’intérieur de la boucle. Mélanger les types entre l’index et la requête produirait des scores incohérents, et l’erreur est d’autant plus vicieuse qu’elle ne lève aucune exception.

Réduire les dimensions

Le paramètre output_dimension contrôle le nombre de dimensions du vecteur. La boucle ci-dessous parcourt six valeurs et affiche pour chacune l’empreinte mémoire d’un seul vecteur, en float puis en int8.

import numpy as np

# Comparer différentes dimensions
dims = [256, 512, 768, 1024, 1536, 3072]

for dim in dims:
    response = client.embeddings.create(
        model="codestral-embed",
        output_dimension=dim,
        inputs=["def quicksort(arr): ..."],
    )
    emb = response.data[0].embedding

    # Taille mémoire approximative
    size_float32 = dim * 4  # 4 octets par float32
    size_int8 = dim * 1     # 1 octet par int8

    print(f"  {dim:5d} dims -> {size_float32:6d} octets (float) | {size_int8:5d} octets (int8)")

Sortie :

    256 dims ->   1024 octets (float) |   256 octets (int8)
    512 dims ->   2048 octets (float) |   512 octets (int8)
    768 dims ->   3072 octets (float) |   768 octets (int8)
   1024 dims ->   4096 octets (float) |  1024 octets (int8)
   1536 dims ->   6144 octets (float) |  1536 octets (int8)
   3072 dims ->  12288 octets (float) |  3072 octets (int8)

Multipliez la colonne de droite par votre nombre réel de vecteurs et vous obtenez immédiatement le dimensionnement de votre serveur. Entre 3072 dimensions en float et 768 en int8, le rapport est de seize : le même index passe de douze gigaoctets à sept cent cinquante mégaoctets.

Guide de choix

Les configurations suivantes couvrent les situations les plus fréquentes :

ContexteConfigurationMotif
Prototype / développementfloat + 1536 dimsdéfaut, aucun compromis
Production standardfloat + 1024 dimsbon compromis qualité/coût
Gros volume (millions de vecteurs)int8 + 768 dims4x plus compact
Recherche en temps réel à grande échellebinary + 1536 dimspré-filtrage rapide, puis re-rank en float
Embarqué / edgeint8 + 256 dimsminimum viable

La ligne « temps réel » décrit une architecture en deux temps qu’il vaut la peine de comprendre : l’index binaire, très léger, sert à ramener quelques centaines de candidats en quelques millisecondes ; ces candidats seulement sont ensuite reclassés avec les vecteurs float, plus coûteux mais bien plus fins. Vous obtenez la vitesse du binaire et, sur la tête de liste, la précision du float.

Points clés à retenir

  • codestral-embed supporte 5 types de sortie : float, int8, uint8, binary, ubinary
  • Le type binary est 32x plus compact que float, avec une perte de qualité acceptable pour le pré-filtrage
  • Les premières dimensions contiennent le plus d’information (Matryoshka representation)
  • Combinez dimension réduite + int8 pour des index très compacts
  • Testez toujours sur vos données réelles avant de choisir les paramètres de production