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

Datentypen und Dimensionen

Lektion 7 von 18 Aktualisiert am 2. November 2026 Entwickler
Auf dieser Seite
  1. Optimierung von Größe und Qualität
  2. Die fünf Ausgabetypen
  3. Auswirkungen auf die Qualität
  4. Reduzierung der Dimensionen
  5. Auswahlleitfaden
  6. Kernaussagen

Optimierung von Größe und Qualität

codestral-embed bietet Ihnen eine präzise Kontrolle über zwei Achsen: die Anzahl der Dimensionen und den Datentyp (dtype) der Werte. Diese Parameter ermöglichen es Ihnen, das Gleichgewicht zwischen Suchqualität und Speicher- oder Rechenkosten einzustellen.

Dies wird kritisch, wenn die Datenmengen wachsen. Ein Index mit zwei Millionen Funktionen bei 1536 Float-Dimensionen wiegt etwa zwölf Gigabyte und passt nicht mehr in den Arbeitsspeicher einer Standardmaschine; derselbe Index in int8 bei 768 Dimensionen fällt unter ein Gigabyte und wird wieder in Echtzeit abfragbar. Es ist diese Mathematik, keine ästhetische Präferenz, die Ihre Entscheidungen leiten sollte.

Die fünf Ausgabetypen

float (Standard)

Der float-Typ erzeugt 32-Bit-Gleitkommawerte. Dies ist das genaueste Format und ideal, wenn die Qualität Vorrang vor dem Speicherplatz hat.

from mistralai.client 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, Values: {embedding[:5]}")
# [0.0234375, -0.15625, 0.08984375, 0.01171875, -0.046875]

int8

Jede Dimension ist eine ganze Zahl zwischen -128 und 127. Dies verwendet viermal weniger Speicher als float32 mit minimaler Qualitätsverlust. Vergleichen Sie die angezeigten Werte mit denen im vorherigen Beispiel: Es ist derselbe Vektor, quantisiert auf eine gröbere Skala, und die Rangfolge der Ergebnisse bleibt nahezu unverändert.

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

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

uint8

Ähnlich wie int8, jedoch mit Werten zwischen 0 und 255 (vorzeichenlos). Nützlich für bestimmte Vektorsuchmaschinen, die nur positive Werte akzeptieren – eine Einschränkung, die Sie in der Regel erst während der Integration, nicht vorher, entdecken.

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

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

binary

Das kompakteste Format. Jede Dimension wird auf 1 Bit quantisiert, und Bits werden in Paketen von 8 zu int8-Werten gruppiert. Der resultierende Vektor ist 32-mal kleiner als float – die Länge von 192 unten entspricht exakt den ursprünglichen 1536 Dimensionen, acht für acht gepackt.

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

embedding = response.data[0].embedding
print(f"Type: binary, Length: {len(embedding)}")
# Length: 192 (instead of 1536 in float)

ubinary

Identisch zu binary, jedoch mit uint8-Werten (0–255) statt int8 (-128 bis 127). Die Wahl zwischen den beiden hängt davon ab, was Ihre nachgelagerte Speicherengine akzeptiert, nicht von der Suchqualität.

Auswirkungen auf die Qualität

Kompressionszahlen sagen Ihnen nicht, was Sie tatsächlich verlieren. Die folgende Funktion misst dies an einem konkreten Beispiel: ein Palindrom-Test, auf Französisch abgefragt, nacheinander mit drei dtypes codiert. Die resultierenden Ähnlichkeiten geben Ihnen die Größenordnung des Degradations auf Ihren eigenen Daten.

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

def compare_dtypes(code_snippet, query):
    """Compare search quality by dtype."""
    dtypes = ["float", "int8", "uint8"]
    results = {}

    for dtype in dtypes:
        # Encode code and query with the same 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

# Test
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}: similarity = {score:.4f}")

Beachten Sie, dass Code und Anfrage im Loop immer mit demselben Datentyp codiert werden. Das Mischen von Typen zwischen Index und Anfrage würde inkonsistente Scores erzeugen, und der Fehler ist noch heimtückischer, da er keine Ausnahme auslöst.

Reduzierung der Dimensionen

Der Parameter output_dimension steuert die Anzahl der Dimensionen im Vektor. Der folgende Loop iteriert durch sechs Werte und zeigt den Speicherfußabdruck eines einzelnen Vektors für jeden an, zuerst in float, dann in int8.

import numpy as np

# Compare different 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

    # Approximate memory size
    size_float32 = dim * 4  # 4 bytes per float32
    size_int8 = dim * 1     # 1 byte per int8

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

Ausgabe:

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

Multiplizieren Sie die rechte Spalte mit Ihrer tatsächlichen Anzahl an Vektoren, und Sie erhalten sofort Ihre Serverdimensionierung. Zwischen 3072 Dimensionen in float und 768 in int8 beträgt das Verhältnis sechzehn: derselbe Index geht von zwölf Gigabyte auf siebenhundertfünfzig Megabyte.

Auswahlleitfaden

Die folgenden Konfigurationen decken die häufigsten Szenarien ab:

KontextKonfigurationGrund
Prototyp / Entwicklungfloat + 1536 DimensionenStandard, keine Kompromisse
Standard-Produktionfloat + 1024 Dimensionengutes Verhältnis von Qualität zu Kosten
Hohe Volumina (Millionen Vektoren)int8 + 768 Dimensionen4-mal kompakter
Großskalige Echtzeitsuchebinary + 1536 Dimensionenschnelle Vorfilterung, dann Neurankierung in float
Embedded / Edgeint8 + 256 Dimensionenminimales Machbares

Die Zeile „Echtzeit” beschreibt eine zweistufige Architektur, die es zu verstehen gilt: Der sehr leichte binary-Index dient dazu, in Millisekunden ein paar hundert Kandidaten abzurufen; erst diese Kandidaten werden dann mit den float-Vektoren neu gerankt, die zwar kostspieliger, aber viel feiner sind. Sie erhalten die Geschwindigkeit von binary und an der Spitze der Liste die Präzision von float.

Kernaussagen

  • codestral-embed unterstützt 5 Ausgabetypen: float, int8, uint8, binary, ubinary
  • Der binary-Typ ist 32-mal kompakter als float, mit akzeptablem Qualitätsverlust für die Vorfilterung
  • Die ersten Dimensionen enthalten die meisten Informationen (Matryoshka-Darstellung)
  • Kombinieren Sie reduzierte Dimensionen + int8 für sehr kompakte Indizes
  • Testen Sie immer an Ihren echten Daten, bevor Sie Produktionsparameter wählen