Embeddings de texte pour RAG et recherche - Python, Ollama, API compatibles OpenAI

Intégration RAG - Python, Ollama, API OpenAI.

Sommaire

Si vous travaillez sur la génération augmentée par récupération (RAG), cette section explique les incorporations de texte (text embeddings) en termes simples : ce qu’elles sont, comment elles s’intègrent dans la recherche et la récupération, et comment appeler deux configurations locales courantes depuis Python en utilisant Ollama ou une API HTTP compatible OpenAI (comme le font de nombreux serveurs basés sur llama.cpp).

Incorporations de texte et récupération

Pour les clients Go et les comparaisons de SDK pour Ollama, consultez SDK Go pour Ollama — comparaison avec des exemples.

Qu’est-ce qu’une incorporation de texte ?

Une incorporation de texte est un vecteur (une liste de nombres à virgule flottante) produit par un modèle d’incorporation. Le modèle mappe du texte de longueur variable dans un espace à dimensions fixes, de sorte que les textes ayant un sens similaire tendent à se situer proche les uns des autres selon une mesure de distance ou de similarité (souvent la similarité cosinus sur des vecteurs normalisés en L2).

Les incorporations ne sont pas la même chose que les identifiants de jetons (token IDs) ni la même chose qu’une complétion de chat. Elles constituent une couche de représentation que vous utilisez pour la recherche, le regroupement (clustering), la déduplication et, dans le contexte de la RAG, la récupération.

Cas d’utilisation courants

Cas d’utilisation Rôle des incorporations
Recherche sémantique / Récupération RAG Incorporer les requêtes et les extraits de documents ; classer par similarité pour récupérer des passages pertinents.
Reclassement avec des modèles d’incorporation Incorporer la requête et chaque candidat ; noter les paires par similarité (voir Reclassement avec des modèles d’incorporation).
Regroupement et déduplication Regrouper ou dédupliciter des éléments dans l’espace d’incorporation sans étiqueter manuellement chaque exemple.
Notation de style classification Comparer le texte à des descriptions de prototypes ou à des noms de classes dans le même espace (les modèles varient selon le modèle).

Pour les configurations multimodales (image–texte et concepts connexes), consultez Incorporations intermodales.

Incorporations dans un pipeline RAG

Un parcours hors ligne typique est le suivant :

  1. Fragmenter les documents (la taille, le chevauchement et la structure comptent — voir Stratégies de fragmentation dans RAG).
  2. Incorporer chaque fragment ; stocker facultativement des métadonnées (ID source, section, ACL).
  3. Indexer les vecteurs en mémoire, dans un index de bibliothèque ou dans une base de données vectorielle (compromis dans Stores vectoriels pour RAG — comparaison).

Au moment de la requête :

  1. Incorporer la requête utilisateur (une courte chaîne ou un petit lot).
  2. Récupérer les k meilleurs fragments similaires par recherche vectorielle (facultativement avec recherche hybride / mots-clés).
  3. Construire un prompt à partir des fragments de texte brut récupérés et appeler votre modèle de chat.

Nuance importante — les grands modèles de langage dans les API de chat consomment du texte (et des outils), pas des tenseurs d’incorporation arbitraires. Vous utilisez les incorporations pour choisir quel texte injecter. Si vous voyez « interroger le LLM avec des incorporations précalculées », en pratique, cela signifie récupérer avec des incorporations, puis envoyer le texte sélectionné au LLM.

Obtenir des incorporations avec Ollama (Python)

Ollama expose une API HTTP. Pour les incorporations, appelez POST /api/embed sur votre hôte Ollama (par défaut http://127.0.0.1:11434). Le corps JSON inclut un nom de model et un input (une chaîne ou une liste de chaînes). La réponse inclut embeddings, une liste de vecteurs alignés avec vos entrées.

Installez httpx (ou utilisez requests de la même manière).

import httpx

OLLAMA = "http://127.0.0.1:11434"
MODEL = "nomic-embed-text"  # remplacez par un modèle d'incorporation que vous avez téléchargé

def embed_ollama(texts: list[str]) -> list[list[float]]:
    r = httpx.post(
        f"{OLLAMA}/api/embed",
        json={"model": MODEL, "input": texts},
        timeout=120.0,
    )
    r.raise_for_status()
    data = r.json()
    return data["embeddings"]

if __name__ == "__main__":
    q = "Qu'est-ce que la génération augmentée par récupération ?"
    chunks = [
        "RAG combine la récupération avec la génération.",
        "Les incorporations mappent le texte dans un espace vectoriel pour la recherche de similarité.",
    ]
    qv = embed_ollama([q])[0]
    doc_vs = embed_ollama(chunks)
    print(len(qv), len(doc_vs), len(doc_vs[0]))

Notes opérationnelles

Obtenir des incorporations avec un serveur compatible OpenAI (Python)

De nombreux serveurs locaux (y compris les configurations HTTP courantes de llama.cpp) exposent des routes compatibles OpenAI telles que POST /v1/embeddings. Vous pouvez utiliser le package Python officiel openai et pointer base_url vers la racine …/v1 de votre serveur.

from openai import OpenAI

# Exemple — remplacez l'hôte, le port et l'ID de modèle par les valeurs de votre serveur
client = OpenAI(
    base_url="http://127.0.0.1:8080/v1",
    api_key="not-needed",  # beaucoup de serveurs locaux ignorent ceci
)

def embed_openai_compatible(text: str, model: str) -> list[float]:
    r = client.embeddings.create(model=model, input=text)
    return r.data[0].embedding

if __name__ == "__main__":
    v = embed_openai_compatible("bonjour de llama.cpp", "your-embedding-model-id")
    print(len(v))

Pourquoi garder les deux modèles sur une seule page ? Les concepts (fragmenter, incorporer, indexer, requêter, récupérer le texte) sont identiques ; seule la surface HTTP change. Un article de style atelier évite de dupliquer le même récit sous deux URL.

Persister les vecteurs et les interroger

Au minimum, vous devez stocker trois éléments par fragment — le vecteur, le texte et les métadonnées (ID source, offsets, ACL). Pour un prototype rapide, vous pouvez tout conserver dans une liste Python et utiliser la similarité cosinus avec NumPy ou scikit-learn. Pour des données en croissance, utilisez une base de données vectorielle ou un index de bibliothèque (FAISS, etc.) ; consultez Stores vectoriels pour RAG — comparaison pour les compromis au niveau du produit.

Boucle de requête conceptuelle :

  1. query_vec = embed(query)
  2. neighbors = index.search(query_vec, k)
  3. context = "\n\n".join(chunk.text for chunk in neighbors)
  4. Envoyer context et la question de l’utilisateur à votre API de chat.

Reclassement après récupération

Un reclasseur (souvent un cross-encoder ou un second modèle de notation) peut réorganiser les meilleurs candidats après la récupération vectorielle. Ce site propose des exemples en Python et en Go, notamment Reclassement avec des modèles d’incorporation et Reclassement avec Ollama et Qwen3 Embedding en Go.

Sur ce site — articles connexes

Sujet Article
Architecture RAG complète Tutoriel RAG — architecture, implémentation, production
Fragmentation avant incorporation Stratégies de fragmentation dans RAG
Choix de la DB vectorielle Stores vectoriels pour RAG — comparaison
Qwen3 sur Ollama Qwen3 Embedding & Reranker sur Ollama
Intermodal Incorporations intermodales
CLI et astuces Ollama Fiche de référence Ollama
Go + Ollama Utiliser Ollama en Go — comparaison SDK

Liens utiles