3. EmbeddingAvancé

Affiner les Embeddings pour Votre Domaine

17 novembre 2025
14 min de lecture
Équipe de Recherche Ailog

Augmentez la précision de récupération de 30% : affinez les modèles d'embeddings sur vos documents et requêtes spécifiques.

Pourquoi Faire du Fine-Tuning ?

Les embeddings génériques fonctionnent bien, mais le fine-tuning spécifique au domaine donne un gain de précision de 30-50% :

Avant (générique) :

  • Requête médicale : "MI treatment" → ❌ correspond à "Michigan"

Après (fine-tuné) :

  • Requête médicale : "MI treatment" → ✅ correspond à "Myocardial Infarction protocols"

Quand Faire du Fine-Tuning

Fine-tuner quand :

  • Jargon spécifique au domaine (juridique, médical, technique)
  • 1000+ paires requête-document étiquetées
  • Le modèle de base sous-performe (< 70% de recall)

Éviter le fine-tuning quand :

  • Domaine général
  • < 500 exemples d'entraînement
  • Le modèle de base fonctionne déjà bien

Format des Données d'Entraînement

DEVELOPERpython
# Paires positives (requête → document pertinent) train_data = [ { "query": "What causes diabetes?", "positive": "Type 2 diabetes is caused by insulin resistance...", "negative": "Diabetic retinopathy affects the eyes..." # Optionnel }, { "query": "How to lower blood pressure?", "positive": "Lifestyle changes like diet and exercise reduce BP...", "negative": "High blood pressure symptoms include headaches..." } ]

Méthode 1 : Sentence Transformers

DEVELOPERpython
from sentence_transformers import SentenceTransformer, InputExample, losses from torch.utils.data import DataLoader # Charger le modèle de base model = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2') # Préparer les données d'entraînement train_examples = [ InputExample(texts=[item['query'], item['positive']]) for item in train_data ] # Créer le dataloader train_dataloader = DataLoader(train_examples, shuffle=True, batch_size=16) # Définir la fonction de perte (apprentissage contrastif) train_loss = losses.MultipleNegativesRankingLoss(model) # Fine-tuner model.fit( train_objectives=[(train_dataloader, train_loss)], epochs=3, warmup_steps=100, output_path='./fine-tuned-model' )

Méthode 2 : Fine-Tuning OpenAI

DEVELOPERpython
import openai # Préparer les données au format JSONL with open('training_data.jsonl', 'w') as f: for item in train_data: f.write(json.dumps({ "input": item['query'], "output": item['positive'] }) + '\n') # Télécharger le fichier d'entraînement file = openai.File.create( file=open("training_data.jsonl", "rb"), purpose='fine-tune' ) # Créer le job de fine-tuning job = openai.FineTuningJob.create( training_file=file.id, model="text-embedding-3-small" ) # Attendre la complétion status = openai.FineTuningJob.retrieve(job.id) print(status.status) # 'succeeded' # Utiliser le modèle fine-tuné embeddings = openai.Embedding.create( input="your query", model=f"ft:{job.fine_tuned_model}" )

Méthode 3 : Mining de Négatifs Difficiles

Améliorer l'apprentissage contrastif avec des négatifs difficiles :

DEVELOPERpython
from sentence_transformers import losses # Générer des négatifs difficiles (documents similaires mais non pertinents) def mine_hard_negatives(query, candidates, model, k=5): query_emb = model.encode(query) cand_embs = model.encode(candidates) # Trouver les documents les plus similaires mais incorrects scores = cosine_similarity([query_emb], cand_embs)[0] hard_neg_indices = np.argsort(scores)[-k:] return [candidates[i] for i in hard_neg_indices] # Entraînement avec négatifs difficiles train_examples = [] for item in train_data: hard_negs = mine_hard_negatives( item['query'], all_documents, base_model ) for neg in hard_negs: train_examples.append( InputExample(texts=[ item['query'], item['positive'], neg # Négatif difficile ]) ) # Utiliser TripletLoss train_loss = losses.TripletLoss(model)

Évaluation

DEVELOPERpython
from sklearn.metrics import ndcg_score def evaluate_model(model, test_queries, test_docs, relevance_labels): predictions = [] for query in test_queries: query_emb = model.encode(query) doc_embs = model.encode(test_docs) scores = cosine_similarity([query_emb], doc_embs)[0] predictions.append(scores) # nDCG@10 ndcg = ndcg_score(relevance_labels, predictions, k=10) return ndcg # Comparer le modèle de base vs fine-tuné base_model = SentenceTransformer('all-MiniLM-L6-v2') fine_tuned_model = SentenceTransformer('./fine-tuned-model') print(f"Base model nDCG@10: {evaluate_model(base_model, ...)}") print(f"Fine-tuned nDCG@10: {evaluate_model(fine_tuned_model, ...)}")

Fine-Tuning Incrémental

Mettre à jour le modèle au fur et à mesure de l'arrivée de nouvelles données :

DEVELOPERpython
# Charger le modèle précédemment fine-tuné model = SentenceTransformer('./fine-tuned-model') # Ajouter de nouvelles données d'entraînement new_train_examples = [...] # Continuer l'entraînement (démarrage à chaud) model.fit( train_objectives=[(new_dataloader, train_loss)], epochs=1, warmup_steps=50, output_path='./fine-tuned-model-v2' )

Distillation (Inférence Rapide)

Fine-tuner un grand modèle, puis le distiller en un petit :

DEVELOPERpython
from sentence_transformers import models, SentenceTransformer, losses # Enseignant : grand modèle fine-tuné teacher = SentenceTransformer('fine-tuned-large-model') # Étudiant : petit modèle de base student = SentenceTransformer('all-MiniLM-L6-v2') # Perte de distillation train_loss = losses.MSELoss(student, teacher) # Entraîner l'étudiant à imiter l'enseignant student.fit( train_objectives=[(train_dataloader, train_loss)], epochs=3 ) # Maintenant l'étudiant est rapide mais performe comme l'enseignant

Le fine-tuning des embeddings est l'arme secrète pour un RAG spécifique au domaine. Investissez-y tôt.

Tags

embeddingfine-tuningcustomdomain-specific

Articles connexes

Ailog Assistant

Ici pour vous aider

Salut ! Pose-moi des questions sur Ailog et comment intégrer votre RAG dans vos projets !