Tous les guides
IntermédiaireÀ votre rythmeGuide gratuitSection 75/95

Embeddings et bases vectorielles

Pratiquez les fondations du développement : programmation, web, API, données et usages de l’IA. Des sections et exercices pour construire vos premiers projets.

💡

Contenu gratuit, accessible sans compte. Les outils et modèles évoluent : consultez le dossier actuel pour vérifier leurs versions. Modèles et sources

Section 11.4.16 : Embeddings et bases vectorielles

🎯 Objectif pédagogique

Comprendre les embeddings (représentations vectorielles), les bases vectorielles, et les opérations de similarité. Vous serez capable de créer, stocker et rechercher des embeddings pour alimenter vos systèmes RAG et de recommandation.


Les embeddings — L'ADN du texte

Marc a vu les embeddings dans la section RAG. Maintenant, on va en profondeur. Un embedding est un vecteur de nombres (ex: [0.12, -0.34, 0.56, ...]) qui capture le sens d'un texte. Deux textes similaires auront des embeddings proches dans l'espace vectoriel.

Créer et comparer des embeddings

from openai import OpenAI
import numpy as np

client = OpenAI()

def get_embedding(text, model="text-embedding-3-small"):
    """Obtenir l'embedding d'un texte."""
    response = client.embeddings.create(
        model=model,
        input=text
    )
    return np.array(response.data[0].embedding)

def cosine_similarity(a, b):
    """Calculer la similarité cosinus entre deux vecteurs."""
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

# Démonstration
texts = [
    "Data Analyst spécialisé en finance",
    "Analyste de données secteur financier",
    "Chef cuisinier passionné de gastronomie",
    "Python developer with SQL skills",
    "Développeur Python avec compétences SQL"
]

embeddings = \{text: get_embedding(text) for text in texts\}

# Matrice de similarité
print("Similarités :")
for i, t1 in enumerate(texts):
    for j, t2 in enumerate(texts):
        if j > i:
            sim = cosine_similarity(embeddings[t1], embeddings[t2])
            print(f"  \{sim:.3f\} | '\{t1[:40]\}' ↔ '\{t2[:40]\}'")

# Résultats attendus :
# ~0.95 | "Data Analyst finance" ↔ "Analyste données financier"  (synonymes)
# ~0.90 | "Python developer SQL" ↔ "Développeur Python SQL"       (traduction)
# ~0.30 | "Data Analyst finance" ↔ "Chef cuisinier"               (différents)

Modèles d'embedding

ModèleProviderDimensions$/M tokensQualité
text-embedding-3-smallOpenAI15360.02$Bon
text-embedding-3-largeOpenAI30720.13$Excellent
voyage-3Voyage AI10240.06$Très bon
all-MiniLM-L6-v2HuggingFace384Gratuit*Correct
nomic-embed-textNomic768Gratuit*Bon

*Gratuit si exécuté localement (GPU recommandé)

Bases vectorielles — Stocker et rechercher

# ═══ ChromaDB — Simple et local ═══
import chromadb

client = chromadb.PersistentClient(path="./vector_db")

# Créer une collection
collection = client.get_or_create_collection(
    name="job_offers",
    metadata=\{"hnsw:space": "cosine"\}  # Distance cosinus
)

# Indexer des offres d'emploi
offers = [
    \{"id": "offer_1", "text": "Data Analyst Python SQL Paris 50k", "company": "TechCorp"\},
    \{"id": "offer_2", "text": "ML Engineer TensorFlow Remote 70k", "company": "AIStartup"\},
    \{"id": "offer_3", "text": "Business Analyst Excel Finance Lyon 45k", "company": "BankCo"\},
    \{"id": "offer_4", "text": "Data Scientist Python R Deep Learning 65k", "company": "DataLab"\},
    \{"id": "offer_5", "text": "Analyste financier programmation Python 55k", "company": "FinTech"\},
]

collection.upsert(
    ids=[o["id"] for o in offers],
    documents=[o["text"] for o in offers],
    metadatas=[\{"company": o["company"]\} for o in offers]
)

# Recherche sémantique
results = collection.query(
    query_texts=["Poste data avec Python pour quelqu'un venant de la finance"],
    n_results=3,
    where=None  # Pas de filtre metadata
)

print("Top 3 offres similaires :")
for i, (doc, meta) in enumerate(zip(results["documents"][0], results["metadatas"][0])):
    print(f"  \{i+1\}. [\{meta['company']\}] \{doc\}")

# Résultat : "Analyste financier Python" et "Data Analyst Python SQL" en top

Recherche hybride — Sémantique + Filtres

# Combiner similarité sémantique et filtres metadata
results = collection.query(
    query_texts=["Machine learning engineer"],
    n_results=5,
    where=\{"company": \{"$ne": "BankCo"\}\},  # Exclure BankCo
    # Ou : where=\{"salary_min": \{"$gte": 50000\}\}
)

# ChromaDB supporte les opérateurs :
# $eq, $ne : égal, différent
# $gt, $gte, $lt, $lte : comparaisons
# $in, $nin : dans / pas dans une liste
# $and, $or : combinaisons

Applications des embeddings au-delà du RAG

# 1. Système de recommandation
def recommend_similar_offers(offer_id, collection, n=5):
    """Recommander des offres similaires."""
    offer = collection.get(ids=[offer_id])
    
    results = collection.query(
        query_texts=offer["documents"],
        n_results=n + 1  # +1 car l'offre elle-même sera dans les résultats
    )
    
    # Exclure l'offre d'origine
    return [(doc, meta) for doc, meta, id_ in 
            zip(results["documents"][0], results["metadatas"][0], results["ids"][0])
            if id_ != offer_id]

# 2. Détection de doublons
def find_duplicates(collection, threshold=0.95):
    """Trouver les documents quasi-identiques."""
    all_docs = collection.get()
    duplicates = []
    
    for i, doc in enumerate(all_docs["documents"]):
        results = collection.query(query_texts=[doc], n_results=5)
        for j, (sim_doc, distance) in enumerate(
            zip(results["documents"][0], results["distances"][0])
        ):
            if distance < (1 - threshold) and results["ids"][0][j] != all_docs["ids"][i]:
                duplicates.append((all_docs["ids"][i], results["ids"][0][j], 1 - distance))
    
    return duplicates

# 3. Clustering sémantique
def cluster_by_topic(texts, n_clusters=3):
    """Grouper des textes par thème."""
    from sklearn.cluster import KMeans
    
    embeddings = [get_embedding(t) for t in texts]
    kmeans = KMeans(n_clusters=n_clusters, random_state=42)
    labels = kmeans.fit_predict(embeddings)
    
    clusters = \{\}
    for text, label in zip(texts, labels):
        clusters.setdefault(label, []).append(text)
    
    return clusters

Coût des embeddings : dérisoire

text-embedding-3-small coûte 0.02$ par million de tokens. Indexer 10 000 offres d'emploi (~500k tokens) coûte ~0.01$. La recherche est gratuite (calcul local). Les embeddings sont la brique IA la moins chère et la plus utile.

🏋️ Exercice pratique (25 minutes)

  1. →Créez des embeddings pour 10 textes variés et comparez les similarités
  2. →Stockez-les dans ChromaDB et implémentez la recherche
  3. →Testez la recherche hybride (similarité + filtre)
  4. →Implémentez un mini-système de recommandation
Vérification rapide

Pourquoi deux textes en langues différentes ("Data Analyst" et "Analyste de données") ont-ils des embeddings similaires ?

Vérification rapide

Quelle est la différence entre une base de données classique et une base vectorielle ?

Votre progression

Cette progression est déclarative et conservée dans votre navigateur. L’attestation finale ne constitue pas un diplôme ni une évaluation indépendante.

Voir ma progression et mon attestation

Apprendre l’IA, du premier prompt aux agents

15 guides gratuitsQuiz, schémas et ateliersSans compte

Un cas pratique IA dans votre boîte mail

Méthodes, ressources et nouveaux exercices. Gratuit, avec désinscription à tout moment.