De CLIP à JinaCLIP : apprentissage général de représentations texte-image pour la recherche et le RAG multimodal
Récemment, l’essor des modèles d’embeddings multimodaux a attiré l’attention dans divers secteurs, transformant la manière dont les machines interprètent le texte et les images. Cependant, malgré des progrès significatifs, ces modèles font face à des défis fondamentaux, dont l’un est le fossé de modalité. Ce fossé se manifeste par le fait que les embeddings d’images et de texte sont spatialement éloignés dans l’espace latent, même lorsqu’ils décrivent le même objet.
Lors d’un récent Unstructured Data Meetup organisé par Zilliz, Bo Wang, Engineering Manager chez Jina AI, nous a expliqué les complexités du fossé de modalité et la transition du modèle CLIP d’OpenAI vers JinaCLIP.
Dans ce blog, nous récapitulerons ses principaux points et implémenterons également un système de recherche de similarité multimodale. Ce système utilisera JinaCLIP pour générer des embeddings multimodaux et la base de données vectorielle Milvus pour stocker et récupérer des embeddings similaires à partir d’une requête donnée. Pour plus de détails, nous vous recommandons de regarder l’intégralité de l’intervention de Bo sur YouTube.
Qu’est-ce qui fait un bon modèle d’embedding ?
La fonction principale d’un modèle d’embedding est de projeter des éléments comme des textes et des images dans des vecteurs, des représentations numériques qui capturent les relations sémantiques au sein des données. Par exemple, la distance entre deux vecteurs devrait refléter la similarité des deux éléments qu’ils représentent, qu’il s’agisse de deux images, de deux textes ou de l’un de chaque.
Les modèles d’embedding sont au cœur des tâches d’IA modernes telles que la recherche sémantique, la récupération d’images, et bien plus encore. Mais qu’est-ce qui rend un modèle d’embedding performant ?
Polyvalence entre les domaines
Un bon modèle d’embedding devrait bien fonctionner dans un large éventail de domaines sans nécessiter de fine-tuning. Cette adaptabilité garantit que les embeddings sont universellement utiles, que l’entrée soit du texte, des images ou d’autres types de données. Par exemple, si une image est intégrée dans un espace vectoriel et qu’un texte associé est intégré dans le même espace, les deux embeddings devraient être proches l’un de l’autre, indiquant leur similarité sémantique. Cette large applicabilité est essentielle pour les tâches d’IA telles que la recherche de similarité, la récupération d’images et les applications inter-domaines.
Similarité sémantique précise
Une caractéristique clé d’un bon modèle d’embedding est sa capacité à relier la gauche et la droite en produisant des embeddings avec des scores de similarité élevés pour des éléments sémantiquement liés. Cela va au-delà des seules données textuelles : cela s’applique à toutes les entrées multimodales. Qu’il s’agisse de comparer du texte à du texte, une image à une image ou du texte à une image, le modèle devrait refléter les bonnes relations grâce à la proximité des embeddings dans l’espace vectoriel.
Cependant, les modèles plus anciens qui reliaient les modalités texte et image avaient plus de difficulté à atteindre cet objectif. Ils s’appuyaient sur des processus manuels, comme l’étiquetage des images ou l’utilisation du texte environnant, pour établir des connexions. Ces méthodes entraînaient une mauvaise généralisation, en particulier dans les scénarios hors distribution.
Le défi des tâches multimodales
Avant l’introduction de modèles comme CLIP, connecter des modalités (texte et images) était une tâche très manuelle et guidée par des hypothèses. Qu’il s’agisse de tags Flickr ou de descriptions textuelles ajoutées par les utilisateurs, le processus était loin d’être fluide. Les approches supervisées, utilisant souvent des étiquettes de classificateurs, étaient sujettes à l’instabilité, et leurs performances hors domaine étaient insatisfaisantes. Cela signifiait que, même si vous pouviez connecter images et textes, les résultats n’étaient pas toujours cohérents, surtout lorsque l’entrée était complexe.
Pour résoudre ce problème, CLIP, un modèle de préentraînement contrastif langage-image, a été développé afin d’améliorer les performances des modèles multimodaux en les entraînant sur des paires image-texte. La capacité de CLIP à aligner les deux modalités dans un espace d’embedding partagé était innovante. Cependant, ce modèle a également ses limites.
Modèle CLIP : une percée avec des restrictions
CLIP a établi une nouvelle norme en entraînant deux encodeurs distincts, l’un pour le texte et l’autre pour les images. L’idée centrale était d’apprendre un espace d’embedding partagé où les vecteurs de texte et d’image pouvaient coexister, les textes et images sémantiquement similaires étant plus proches les uns des autres. Les résultats étaient impressionnants : CLIP permettait des tâches multimodales à l’aide d’une simple fonction de similarité cosinus.
Figure : fonctionnement du modèle CLIP
Cependant, CLIP présente des lacunes. Un problème important est son incapacité à gérer efficacement les tâches uniquement textuelles. Étant donné que CLIP a été principalement optimisé pour de courtes légendes (souvent moins de 77 caractères), les textes plus longs posent un défi. En outre, CLIP manquait d’exemples négatifs difficiles dans son processus d’entraînement. Les négatifs difficiles sont des exemples proches mais incorrects, et ils sont essentiels pour affiner les modèles, en particulier dans des tâches comme la recherche de texte. Sans eux, les performances de CLIP ont plafonné sur les tâches nécessitant une compréhension détaillée du texte.
Transition vers JinaCLIP : remédier aux lacunes de CLIP
JinaCLIP s’appuie sur l’architecture CLIP originale pour remédier à ses limites. Il étend l’entrée textuelle et utilise une architecture BERT v2 adaptée pour l’encodage du texte. Pour le traitement des images, JinaCLIP intègre le modèle EVA-02. Le processus d’entraînement de JinaCLIP se concentre sur le dépassement des défis posés par les entrées textuelles courtes dans les légendes d’images et sur l’introduction de négatifs difficiles. Ce processus se déroule en trois étapes, comme indiqué ci-dessous :
Figure : processus d’entraînement de JinaCLIP
Les étapes sont l’apprentissage de l’alignement, l’intégration de textes longs et l’ajustement fin :
Apprentissage de l’alignement avec des textes courts et des légendes : à cette étape, le modèle est entraîné à l’aide de données d’images légendées et de paires de textes aux significations similaires. L’objectif est d’aligner les embeddings d’image et de texte en optimisant conjointement la similarité texte-image et texte-texte. Ce processus de co-entraînement garantit que, tandis que le modèle apprend à associer le texte aux images, il conserve également ses capacités uniquement textuelles. Bien que les performances uniquement textuelles diminuent légèrement par rapport à un entraînement exclusivement sur des paires de textes, cette phase préserve une approche équilibrée.
Intégration de descriptions textuelles longues : au cours de la deuxième étape, des données synthétiques sont introduites pour entraîner le modèle. Ces données alignent les images avec des textes plus longs générés par des modèles d’IA, décrivant le contenu plus en détail. En parallèle, des paires uniquement textuelles continuent d’être utilisées pour l’entraînement. Le modèle apprend à gérer des descriptions textuelles plus étendues tout en maintenant l’alignement avec les images, renforçant ainsi sa capacité à comprendre les relations image-texte courtes comme longues.
Ajustement fin avec des triplets de textes et des négatifs difficiles : La dernière étape se concentre sur l’utilisation de triplets de textes qui incluent des négatifs difficiles, des paires de textes dont deux sont sémantiquement similaires, mais dont l’un est délibérément différent. Cela aide le modèle à établir des distinctions sémantiques plus fines, en particulier dans les scénarios uniquement textuels. Dans le même temps, le modèle continue de s’entraîner avec des paires synthétiques image-texte long. Cette phase améliore considérablement les performances du modèle en mode texte seul, tout en garantissant que l’alignement image-texte appris lors des étapes précédentes reste robuste.
Cette approche maintient de solides performances dans les tâches multimodales tout en améliorant les capacités dans les scénarios uniquement textuels. Voyons comment cette nouvelle approche se compare au Clip original.
Les métriques de performance indiquent des changements dans les performances de récupération par rapport au modèle CLIP original : une variation de 165 % en texte-vers-texte, 12 % en image-vers-image, 6 % en image-vers-texte et 2 % en texte-vers-image, comme le montre l’image ci-dessous.
Figure : Comparaison des performances du modèle entre jina-clip, openai-clip-vit-b-16 et jina-embeddings-v2-base-en
Le nouveau processus d’entraînement améliore la généralisation entre les tâches et aide à réduire l’écart de modalité. Discutons de l’écart de modalité, un obstacle majeur dans les modèles d’IA multimodaux, et des raisons pour lesquelles ce problème survient.
L’écart de modalité : pourquoi il se produit
L’écart de modalité est la séparation spatiale entre les plongements provenant de différents types d’entrée, tels que des textes et des images qui sont sémantiquement similaires mais éloignés dans l’espace vectoriel. Cet écart affaiblit l’efficacité des systèmes de récupération multimodale, car les plongements ne reflètent pas pleinement la véritable relation entre les entrées liées. Comme vous pouvez le voir dans l’image ci-dessous, la représentation ressemble à un cône tronqué, avec les plongements d’images à une extrémité et les plongements de textes à l’autre, montrant clairement l’écart de modalité.
Figure : Les positions initiales des plongements d’images et de textes dans Jina CLIP, avec des poids entièrement randomisés et aucun entraînement préalable, projetées en deux dimensions
Il existe quelques raisons clés pour lesquelles cet écart apparaît, même dans les modèles modernes :
L’effet de cône lors de l’initialisation
Les modèles multimodaux, en particulier ceux qui traitent des entrées textuelles et visuelles, utilisent souvent des encodeurs distincts pour chaque modalité. Ces encodeurs sont généralement initialisés avec des poids aléatoires ou préentraînés, ce qui amène les plongements de textes à se regrouper dans une région de l’espace vectoriel et les plongements d’images dans une autre, comme on le voit dans l’image ci-dessus. Cette séparation initiale, appelée effet de cône, rend difficile l’alignement correct des plongements issus de différentes modalités (par exemple, des images et des textes associés). Par exemple, le plongement textuel pour un chat duveteux et le plongement d’image d’un chat peuvent commencer très éloignés l’un de l’autre en raison de ce biais d’initialisation, même s’ils sont sémantiquement liés.
Mise à l’échelle par température
Pendant l’entraînement, les modèles d’IA utilisent une technique appelée mise à l’échelle par température dans leur fonction de perte contrastive pour ajuster le degré d’alignement des plongements. Bien qu’elle aide à affiner les distances entre les plongements, la mise à l’échelle par température peut aussi préserver involontairement la séparation initiale entre les modalités, renforçant ainsi l’écart de modalité. Par exemple, si la mise à l’échelle par température n’est pas soigneusement réglée, les plongements pour un chiot joueur et l’image d’un chien peuvent rester trop éloignés dans l’espace vectoriel, même s’ils décrivent le même concept.
Faux négatifs au sein du lot
Lors de l’entraînement avec de grands ensembles de données, les paires de points de données non correspondantes (par exemple, une image de chien associée au texte “une pomme rouge”) sont traitées comme des exemples négatifs. Cependant, ces faux négatifs peuvent tout de même partager un certain chevauchement sémantique. Par exemple, si les deux éléments se rapportent à une vaste catégorie d’animaux (par exemple, une image de chien et le texte “un loup joueur”), le modèle pourrait éloigner ces embeddings plus que nécessaire, aggravant davantage l’écart de modalité en les traitant à tort comme totalement sans rapport.
Comprendre pourquoi l’écart de modalité se produit n’est que la première étape. Pour combler cet écart, diverses stratégies d’entraînement ont été développées afin de rapprocher les embeddings de différentes modalités, garantissant une récupération plus précise dans les tâches multimodales.
Combler l’écart de modalité : techniques d’entraînement et au-delà
L’écart de modalité est un problème structurel qui n’a pas de solution facile, mais il existe des stratégies pour en atténuer l’impact. L’essentiel est de réduire la séparation entre les embeddings de différentes modalités pendant l’entraînement, en veillant à ce que les images et les textes qui vont ensemble soient mappés plus près les uns des autres dans l’espace vectoriel.
Mise à l’échelle avec une température plus élevée
En pratique, augmenter la température pendant l’entraînement peut encourager les embeddings de différentes modalités à se rapprocher en ajoutant davantage d’aléatoire au processus d’apprentissage du modèle. Par exemple, augmenter la température peut aider à aligner plus étroitement les embeddings d’une image de chat et du texte “un chat duveteux”. Cependant, cela se fait au prix d’une convergence plus lente et nécessite davantage de ressources de calcul. Bien que les modèles entraînés avec une mise à l’échelle à haute température tendent à améliorer l’alignement des embeddings de texte et d’image, le compromis se traduit souvent par des temps d’entraînement plus longs et des exigences de calcul plus importantes.
Échantillonnage de négatifs difficiles
Introduire des exemples de négatifs difficiles, des paires non correspondantes qui sont sémantiquement proches, est une autre technique pour réduire l’écart de modalité. Ces paires de négatifs difficiles poussent le modèle à apprendre des distinctions plus fines entre des concepts liés, améliorant ainsi la précision de la récupération. Par exemple, associer une image de chat au texte “un petit tigre” peut sembler être une non-correspondance, mais le modèle apprend que ces deux entrées présentent des sémantiques qui se chevauchent (ce sont toutes deux des félins) et devraient tout de même être quelque peu alignées dans l’espace d’embedding. Ce processus apprend au modèle à reconnaître à la fois les similitudes et les différences entre des concepts liés, affinant sa capacité à différencier les correspondances proches.
Récupération multimodale avec Milvus et JinaCLIP : un exemple pratique
Maintenant que nous avons exploré les raisons techniques derrière l’écart de modalité, examinons un exemple pratique de création d’un système de récupération multimodale à l’aide de Milvus, une base de données vectorielle open source, et de JinaCLIP.
Milvus gère, recherche et interroge des vecteurs de grande dimension, ce qui en fait une solution idéale pour les tâches de récupération multimodale et les tâches de génération augmentée par récupération (RAG). Que vous travailliez avec du texte, des images ou d’autres types de données, Milvus vous permet de stocker efficacement des embeddings et de récupérer des résultats pertinents à l’aide de techniques avancées de recherche de similarité.
Dans cette section, nous allons parcourir le processus d’utilisation de Milvus pour créer un système de récupération multimodale qui gère des embeddings de texte et d’image. Le système permettra aux utilisateurs de saisir soit du texte, soit des images, et de récupérer les résultats les plus pertinents sur le plan sémantique à partir d’un ensemble de données mixte.
Étape 1 : Configuration de l’environnement
Tout d’abord, nous devons installer dans notre environnement les bibliothèques dont nous aurons besoin pour notre système :
!pip install pymilvus transformers torch timm
Ensuite, nous devons importer les bibliothèques nécessaires et configurer notre classe d’encodeur.
# Import necessary libraries
from transformers import AutoModel
from pymilvus import MilvusClient
import torch
# Définir la classe Encoder pour gérer la génération d’embeddings de texte et d’image
class Encoder:
def __init__(self, model_name: str):
# Initialiser le modèle (AutoModel de transformers au lieu de SentenceTransformer)
self.model = AutoModel.from_pretrained(model_name, trust_remote_code=True)
def encode_text(self, text: list[str]) -> list[float]:
# Générer des embeddings uniquement pour le texte
with torch.no_grad():
text_emb = self.model.encode_text(text)
return text_emb
def encode_image(self, image_urls: list[str]) -> list[list[float]]:
# Générer des embeddings uniquement pour les images
with torch.no_grad():
image_emb = self.model.encode_image(image_urls)
return image_emb
# Initialiser l’encodeur avec le modèle jinaai/jina-clip-v1
model_name = "jinaai/jina-clip-v1"
encoder = Encoder(model_name)
Dans le code ci-dessus, nous importons d’abord les bibliothèques requises : AutoModel de transformers pour notre modèle d’encodage, MilvusClient pour interagir avec Milvus, et torch pour les opérations sur les tenseurs.
Nous définissons ensuite une classe Encoder qui encapsule l’AutoModel de transformers. Les méthodes encode_text et encode_image utilisent le modèle pour générer des embeddings pour le texte et les images, respectivement. Le gestionnaire de contexte torch.no_grad() est utilisé pour désactiver le calcul des gradients, qui n’est pas nécessaire pour l’inférence et permet d’économiser de la mémoire.
Enfin, nous initialisons l’encodeur avec le modèle jinaai/jina-clip-v1, qui peut encoder à la fois du texte et des images dans un espace d’embedding partagé.
Étape 2 : Préparation des données
Ensuite, nous allons préparer nos données d’exemple pour l’embedding et l’insertion dans Milvus.
# Charger les données : images et texte pour les embeddings
sentences = ['A blue cat', 'A red cat', 'A red cat generated by AI', 'A dog biting on a stick']
image_urls = [
'https://i.pinimg.com/600x315/21/48/7e/21487e8e0970dd366dafaed6ab25d8d8.jpg',
'https://i.pinimg.com/736x/c9/f2/3e/c9f23e212529f13f19bad5602d84b78b.jpg',
'https://images.fineartamerica.com/images/artworkimages/mediumlarge/1/red-cat-art-3771-bb-james-ahn.jpg',
'https://images.squarespace-cdn.com/content/v1/54822a56e4b0b30bd821480c/29708160-9b39-42d0-a5ed-4f8b9c85a267/labrador+retriever+dans+pet+care.jpeg?format=1500w'
]
# Générer des embeddings pour le texte et les images
text_embeddings = encoder.encode_text(sentences)
image_embeddings = encoder.encode_image(image_urls)
# Garantir des dimensions cohérentes
dim = len(image_embeddings[0])
Ici, nous définissons des listes de phrases d’exemple et d’URL d’images. Les URL contiennent des images de chats rouges, de chats bleus et d’un chien. Nous utilisons ensuite notre encodeur pour générer des embeddings à la fois pour le texte et les images. La variable dim stocke la dimension des embeddings, dont nous aurons besoin lors de la création de notre collection Milvus.
Étape 3 : Configuration de Milvus
Maintenant, nous allons configurer notre client Milvus et créer une collection pour nos données multimodales.
# Insérer les embeddings dans Milvus
collection_name = "multimodal_rag_demo"
milvus_client = MilvusClient(uri="./milvus_demo.db")
# Vérifier si la collection existe et la supprimer si c’est le cas
if milvus_client.has_collection(collection_name):
print(f"Collection {collection_name} already exists. Deleting it...")
milvus_client.drop_collection(collection_name)
# Créer la collection Milvus
milvus_client.create_collection(
collection_name=collection_name,
auto_id=True,
dimension=dim,
enable_dynamic_field=True,
)
Nous initialisons un client Milvus et nous connectons à un fichier de base de données local. Nous vérifions si une collection portant le nom souhaité existe déjà et, si c’est le cas, nous la supprimons afin de repartir sur une base propre.
Nous créons ensuite une nouvelle collection avec le nom spécifié. Le paramètre auto_id=True indique à Milvus de générer automatiquement des ID pour nos entrées. Nous définissons la dimension pour qu’elle corresponde à nos embeddings et activons les champs dynamiques, ce qui nous permet d’ajouter des métadonnées supplémentaires à nos entrées.
Étape 4 : Création d’un index
Avant d’insérer des données, nous allons créer un index pour optimiser les performances de recherche :
index_params = MilvusClient.prepare_index_params()
index_params.add_index(
field_name="vector", # The field to be indexed (your embedding field)
metric_type="COSINE", # Can be L2, COSINE, etc.
index_type="FLAT", # FLAT ensures exact search, ideal for small datasets
)
# Create the index for the collection
milvus_client.create_index(collection_name, index_params)
print(f"Index created successfully for collection: {collection_name}")
Le code ci-dessus crée un index FLAT en utilisant la similarité cosinus comme métrique de distance.
Étape 5 : Insérer des données dans Milvus
Une fois notre collection et notre index configurés, nous pouvons maintenant insérer nos données dans Milvus.
data_to_insert = []
# Insert text embeddings
for idx, txt_emb in enumerate(text_embeddings):
data_to_insert.append({"text": sentences[idx], "vector": txt_emb})
# Insert image embeddings
for idx, img_emb in enumerate(image_embeddings):
data_to_insert.append({"image_url": image_urls[idx], "vector": img_emb})
# Insert data into Milvus
insert_result = milvus_client.insert(
collection_name=collection_name,
data=data_to_insert,
)
print(f"Insert result: {insert_result}")
milvus_client.load_collection(collection_name)
Dans le code ci-dessus, nous créons une liste de dictionnaires, chacun contenant soit une phrase de texte, soit une URL d’image, ainsi que son vecteur d’embedding correspondant. Nous utilisons ensuite la méthode insert du client Milvus pour ajouter ces données à notre collection. Après l’insertion, nous chargeons la collection en mémoire afin de la préparer à la recherche.
Étape 6 : Effectuer une recherche multimodale
Enfin, nous effectuons une recherche multimodale en utilisant à la fois des requêtes d’image et de texte.
# Multimodal search with a combination of image and text query
query_image_url = 'https://imgcdn.stablediffusionweb.com/2024/4/5/5e70d71c-a7f6-44e9-972d-8c5a27d45c3d.jpg'
query_text = "Give me similar red cats"
# Generate query embedding (image + text)
query_embedding_image = encoder.encode_image([query_image_url])[0]
query_embedding_text = encoder.encode_text([query_text])[0]
# Perform search in Milvus using image embedding
search_results_image = milvus_client.search(
collection_name=collection_name,
data=[query_embedding_image],
output_fields=["image_url", "text"], # Ensure both fields are included in the results
limit=5, # Number of results to return
search_params={"metric_type": "COSINE", "params": {"nprobe": 10}}
)
# Perform search in Milvus using text embedding
search_results_text = milvus_client.search(
collection_name=collection_name,
data=[query_embedding_text],
output_fields=["image_url", "text"], # Ensure both fields are included in the results
limit=5, # Number of results to return
search_params={"metric_type": "COSINE", "params": {"nprobe": 10}}
)
# Retrieve and print results from image query
print("Image Query Results:")
for result in search_results_image:
for hit in result:
image_url = hit['entity'].get('image_url')
text = hit['entity'].get('text')
if image_url:
print(f"Retrieved Image URL (from image query): {image_url}")
if text:
print(f"Retrieved Text (from image query): {text}")
# Retrieve and print results from text query
print("Text Query Results:")
for result in search_results_text:
for hit in result:
image_url = hit['entity'].get('image_url')
text = hit['entity'].get('text')
if image_url:
print(f"Retrieved Image URL (from text query): {image_url}")
if text:
print(f"Retrieved Text (from text query): {text}")
Dans le code ci-dessus, nous démontrons le processus de réalisation d’une recherche multimodale. Nous commençons par définir à la fois une URL d’image de requête et un texte de requête. L’image de requête ressemble à ceci :
Figure 2 : Image d’entrée de requête d’un chat rouge et blanc
Nous encodons ensuite ces requêtes à l’aide de notre encodeur afin de générer leurs embeddings respectifs. Nous effectuons ensuite deux recherches distinctes dans Milvus : l’une utilisant l’embedding de l’image et l’autre utilisant l’embedding du texte. Pour chaque recherche, nous demandons les champs image_url et text dans la sortie, ce qui nous permet de récupérer les deux types de données. Nous limitons nos résultats à 5 pour chaque recherche et utilisons la similarité cosinus comme métrique de distance. Le paramètre nprobe dans nos paramètres de recherche nous permet d’affiner le nombre de clusters à rechercher, offrant un équilibre entre la vitesse de recherche et la précision. Enfin, nous affichons les résultats, montrant quelles images ou quels textes ont été récupérés pour chaque type de requête, démontrant ainsi la capacité du système à gérer et à corréler à la fois des requêtes textuelles et des requêtes basées sur l’image.
Vous pouvez trouver le code complet ici.
Voici des exemples de résultats :
Comme vous pouvez le voir, lorsque nous utilisons une image pour effectuer une recherche vectorielle, nous obtenons à la fois des URL d’images et du texte liés à l’image, et inversement. C’est la puissance de la recherche multimodale. Voici l’une des images récupérées comme image similaire dans les deux cas.
Figure 3 : Image de sortie d’un chat rouge après une recherche de similarité dans Milvus
Comme vous pouvez le voir, l’image est similaire à l’image du chat rouge que nous avons fournie au système comme requête.
Vous pouvez ajouter un reranker à ce système pour organiser les résultats de recherche en fonction de leur pertinence, les résultats les plus pertinents apparaissant en premier. Bien que, comme c’est évident, Milvus fasse déjà du bon travail pour récupérer d’abord les meilleures correspondances. Vous pouvez également faire évoluer ce système pour créer un système RAG multimodal.
Conclusion
Bo Wang a expliqué les subtilités du rapprochement du fossé de modalité dans les modèles multimodaux et a présenté la transition de CLIP à JinaCLIP. Il a décomposé les principaux défis de l’alignement texte-image et a démontré comment JinaCLIP répond à ces problèmes.
Dans cet article, nous avons approfondi ses idées en construisant un système de recherche de similarité multimodale utilisant JinaCLIP pour générer des embeddings et Milvus pour obtenir une récupération efficace. Avec ces connaissances, vous pouvez désormais implémenter vos applications de recherche multimodale, garantissant des performances fluides pour les requêtes textuelles comme pour celles basées sur l’image, et même aller plus loin en intégrant des techniques de recherche avancées comme le reranking.
Ressources supplémentaires
Continuer à lire

Milvus 2.6.x Now Generally Available on Zilliz Cloud, Making Vector Search Faster, Smarter, and More Cost-Efficient for Production AI
Milvus 2.6.x is now GA on Zilliz Cloud, delivering faster vector search, smarter hybrid queries, and lower costs for production RAG and AI applications.

Migrating from S3 Vectors to Zilliz Cloud: Unlocking the Power of Tiered Storage
Learn how Zilliz Cloud bridges cost and performance with tiered storage and enterprise-grade features, and how to migrate data from AWS S3 Vectors to Zilliz Cloud.

Data Deduplication at Trillion Scale: How to Solve the Biggest Bottleneck of LLM Training
Explore how MinHash LSH and Milvus handle data deduplication at the trillion-scale level, solving key bottlenecks in LLM training for improved AI model performance.


