gemini-embedding-2 : préfixes de tâche, dimensions et pièges
Les « task types » version gemini-embedding-2
Un même texte n'a pas le même embedding idéal selon l'usage : pour une recherche, la question courte doit tomber près du document long qui y répond ; pour un clustering, on veut regrouper des textes de même nature. Avec l'ancien modèle gemini-embedding-001, on le précisait avec le paramètre task_type (RETRIEVAL_QUERY, RETRIEVAL_DOCUMENT, CLUSTERING…).
Avec gemini-embedding-2, ce paramètre ne s'utilise pas : la documentation demande d'écrire la tâche dans le texte lui-même, avec un préfixe.
| Usage | Format de la requête | Format du document |
|---|---|---|
| Recherche (asymétrique) | task: search result | query: {texte} | title: {titre} | text: {contenu} (title: none sans titre) |
| Question-réponse | task: question answering | query: {texte} | title: {titre} | text: {contenu} |
| Clustering (symétrique) | task: clustering | query: {texte} | même format |
| Similarité de phrases | task: sentence similarity | query: {texte} | même format (pas pour la recherche) |
| Classification | task: classification | query: {texte} | même format |
Asymétrique : la requête et le document ont des formats différents (une question courte contre une fiche). Symétrique : tous les textes ont le même rôle.
def texte_document(p: dict) -> str:
return f"title: {p['nom']} | text: {p['categorie']}. {p['description']}"
def texte_requete(q: str) -> str:
return f"task: search result | query: {q}"
def texte_symetrique(p: dict, tache: str) -> str:
"""Pour le clustering ou la similarité : même format des deux côtés."""
return f"task: {tache} | query: {p['nom']}. {p['description']}"Le piège de l'agrégation
flowchart LR A["contents = ['texte 1', 'texte 2', 'texte 3']"] --> B["1 seul vecteur agrégé"] C["contents = [Content(texte 1), Content(texte 2), Content(texte 3)]"] --> D["3 vecteurs, un par texte"]
Avec gemini-embedding-2, une liste de chaînes est vue comme un seul contenu en plusieurs morceaux : vous recevez un vecteur unique qui résume le tout. Pour obtenir un vecteur par texte, on envoie une liste d'objets Content, un par texte :
# Une Content par texte : une liste de str donnerait UN seul vecteur agrégé.
contents = [types.Content(parts=[types.Part(text=t)]) for t in textes[i:i + lot]]
r = client.models.embed_content(
model=EMBED_MODEL, contents=contents,
config=types.EmbedContentConfig(output_dimensionality=dim))Sur Vertex AI, l'appel avec plusieurs Content est refusé pour ce modèle (« only supports one content at a time ») : le lab passe alors à un texte par requête.
Choisir la dimension
Par défaut, le modèle renvoie 3072 nombres. output_dimensionality permet d'en demander moins (768 et 1536 sont recommandés par la documentation). C'est possible grâce à l'apprentissage Matryoshka (comme les poupées russes) : les premières valeurs du vecteur portent déjà l'essentiel du sens. gemini-embedding-2 renormalise automatiquement les vecteurs réduits.
| Dimension | Taille pour 1 million de fiches (float32) | Usage |
|---|---|---|
| 3072 | environ 12 Go | qualité maximale |
| 768 | environ 3 Go | bon compromis (choix du lab) |
| 256 | environ 1 Go | gros volumes, qualité un peu moindre |
Le calcul : 1 000 000 × dimension × 4 octets.
Vous appelez embed_content(model="gemini-embedding-2", contents=["a", "b", "c"]). Combien de vecteurs recevez-vous ?
gemini-embedding-2 agrège une liste de chaînes en un seul embedding. Pour 3 vecteurs, envoyez 3 objets Content.
Comment indiquer à gemini-embedding-2 que le texte est une requête de recherche ?
task_type est réservé à gemini-embedding-001. Pour gemini-embedding-2, la tâche s'écrit en tête du texte.
Exercice : préparer une FAQ
Vous indexez une FAQ RH (question + réponse) pour un moteur de question-réponse. Écrivez les deux fonctions de formatage, pour la requête de l'employé et pour chaque entrée de la FAQ.
Voir la solution
def texte_requete_qa(question: str) -> str:
return f"task: question answering | query: {question}"
def texte_faq(entree: dict) -> str:
return f"title: {entree['question']} | text: {entree['reponse']}"La question de la FAQ fait un excellent title : elle résume le document. La requête utilise la tâche question answering plutôt que search result, puisqu'on cherche une réponse.
Résultat obtenu
Vérifications exécutées le 2026-10-15 avec la clé d'API Gemini :
# démo de la leçon 1 : liste de chaînes
liste de str -> 1 vecteur(s)
# même appel avec deux objets Content
content list -> 2
# un texte : dimension et norme par défaut, puis avec output_dimensionality=768
3072 0.9999999373014921 768 0.9999997619101519
# cosinus entre la troncature locale (3072 -> 768, renormalisée) et le vecteur 768 natif
cos trunc vs 768 0.9999997619101513Et sur Vertex AI, gemini-embedding-2 répondait en global mais pas en europe-west1 (404 « Publisher model … not found ») : la région compte.
Je sais faire
- Formater requêtes et documents avec les préfixes de tâche de
gemini-embedding-2 - Envoyer une
Contentpar texte pour obtenir un vecteur par texte - Choisir
output_dimensionalityen fonction du volume - Tronquer et renormaliser un vecteur localement