Affiner les Embeddings pour Votre Domaine

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

Auteur
Équipe de Recherche Ailog
Date de publication
Temps de lecture
14 min de lecture
Niveau
advanced
Étape du pipeline RAG
Embedding

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

``python 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

`python 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

`python 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 :

`python 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

`python 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 :

`python 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 :

`python 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

  • embedding
  • fine-tuning
  • custom
  • domain-specific
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 !