Maison développement back-end Tutoriel Python Construire un système de recherche sémantique rapide et efficace à l'aide d'OpenVINO et Postgres

Construire un système de recherche sémantique rapide et efficace à l'aide d'OpenVINO et Postgres

Oct 21, 2024 pm 04:31 PM

Building a Fast and Efficient Semantic Search System Using OpenVINO and Postgres

Photo de real-napster sur Pixabay

Dans l'un de mes récents projets, j'ai dû créer un système de recherche sémantique capable d'évoluer avec des performances élevées et de fournir des réponses en temps réel pour les recherches de rapports. Nous avons utilisé PostgreSQL avec pgvector sur AWS RDS, associé à AWS Lambda, pour y parvenir. Le défi était de permettre aux utilisateurs d'effectuer des recherches à l'aide de requêtes en langage naturel au lieu de s'appuyer sur des mots-clés rigides, tout en garantissant que les réponses duraient moins de 1 à 2 secondes, voire moins, et ne pouvaient exploiter que les ressources du processeur.

Dans cet article, je passerai en revue les étapes que j'ai suivies pour créer ce système de recherche, de la récupération au reclassement, ainsi que les optimisations réalisées à l'aide d'OpenVINO et du traitement par lots intelligent pour la tokenisation.

Présentation de la recherche sémantique : récupération et reclassement

Les systèmes de recherche modernes de pointe comprennent généralement deux étapes principales : récupération et reclassement.

1) Récupération : La première étape consiste à récupérer un sous-ensemble de documents pertinents en fonction de la requête de l'utilisateur. Cela peut être fait à l'aide de modèles d'intégration pré-entraînés, tels que les intégrations petites et grandes d'OpenAI, les modèles Embed de Cohere ou les intégrations mxbai de Mixbread. La récupération se concentre sur la réduction du pool de documents en mesurant leur similarité avec la requête.

Voici un exemple simplifié utilisant la bibliothèque de transformation de phrases de Huggingface pour la récupération, qui est l'une de mes bibliothèques préférées pour cela :

from sentence_transformers import SentenceTransformer
import numpy as np

# Load a pre-trained sentence transformer model
model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")

# Sample query and documents (vectorize the query and the documents)
query = "How do I fix a broken landing gear?"
documents = ["Report 1 on landing gear failure", "Report 2 on engine problems"]

# Get embeddings for query and documents
query_embedding = model.encode(query)
document_embeddings = model.encode(documents)

# Calculate cosine similarity between query and documents
similarities = np.dot(document_embeddings, query_embedding)

# Retrieve top-k most relevant documents
top_k = np.argsort(similarities)[-5:]
print("Top 5 documents:", [documents[i] for i in top_k])
Copier après la connexion
Copier après la connexion

2) Reclassement : Une fois les documents les plus pertinents récupérés, nous améliorons encore le classement de ces documents à l'aide d'un modèle de cross-encoder. Cette étape réévalue chaque document par rapport à la requête avec plus de précision, en se concentrant sur une compréhension contextuelle plus approfondie.
Le reclassement est bénéfique car il ajoute une couche de raffinement supplémentaire en notant plus précisément la pertinence de chaque document.

Voici un exemple de code pour le reclassement à l'aide de cross-encoder/ms-marco-TinyBERT-L-2-v2, un encodeur croisé léger :

from sentence_transformers import CrossEncoder

# Load the cross-encoder model
cross_encoder = CrossEncoder("cross-encoder/ms-marco-TinyBERT-L-2-v2")

# Use the cross-encoder to rerank top-k retrieved documents
query_document_pairs = [(query, doc) for doc in documents]
scores = cross_encoder.predict(query_document_pairs)

# Rank documents based on the new scores
top_k_reranked = np.argsort(scores)[-5:]
print("Top 5 reranked documents:", [documents[i] for i in top_k_reranked])
Copier après la connexion

Identifier les goulots d'étranglement : le coût de la tokenisation et de la prédiction

Pendant le développement, j'ai constaté que les étapes de tokenisation et de prédiction prenaient assez de temps lors de la gestion de 1 000 rapports avec des paramètres par défaut pour les transformateurs de phrases. Cela a créé un goulot d'étranglement en termes de performances, d'autant plus que nous visions des réponses en temps réel.

Ci-dessous j'ai profilé mon code à l'aide de SnakeViz pour visualiser les performances :

Building a Fast and Efficient Semantic Search System Using OpenVINO and Postgres

Comme vous pouvez le constater, les étapes de tokenisation et de prédiction sont disproportionnellement lentes, ce qui entraîne des retards importants dans la diffusion des résultats de recherche. Dans l’ensemble, cela a pris en moyenne 4 à 5 secondes. Cela est dû au fait qu’il existe des opérations de blocage entre les étapes de tokenisation et de prédiction. Si nous additionnons également d'autres opérations comme l'appel de base de données, le filtrage, etc., nous nous retrouvons facilement avec 8 à 9 secondes au total.

Optimiser les performances avec OpenVINO

La question à laquelle j'ai été confronté était : Pouvons-nous le rendre plus rapide ? La réponse est oui, en tirant parti de OpenVINO, un backend optimisé pour l'inférence CPU. OpenVINO permet d'accélérer l'inférence de modèles d'apprentissage profond sur le matériel Intel, que nous utilisons sur AWS Lambda.

Exemple de code pour l'optimisation OpenVINO
Voici comment j'ai intégré OpenVINO dans le système de recherche pour accélérer l'inférence :

from sentence_transformers import SentenceTransformer
import numpy as np

# Load a pre-trained sentence transformer model
model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")

# Sample query and documents (vectorize the query and the documents)
query = "How do I fix a broken landing gear?"
documents = ["Report 1 on landing gear failure", "Report 2 on engine problems"]

# Get embeddings for query and documents
query_embedding = model.encode(query)
document_embeddings = model.encode(documents)

# Calculate cosine similarity between query and documents
similarities = np.dot(document_embeddings, query_embedding)

# Retrieve top-k most relevant documents
top_k = np.argsort(similarities)[-5:]
print("Top 5 documents:", [documents[i] for i in top_k])
Copier après la connexion
Copier après la connexion

Avec cette approche, nous pourrions obtenir une accélération de 2 à 3 fois, réduisant les 4 à 5 secondes d'origine à 1 à 2 secondes. Le code de travail complet est sur Github.

Optimisation de la vitesse : taille des lots et tokenisation

Un autre facteur critique dans l'amélioration des performances était l'optimisation du processus de tokenisation et l'ajustement de la taille du lot et de la longueur du jeton. En augmentant la taille du lot (batch_size=16) et en réduisant la longueur du jeton (max_length=512), nous pourrions paralléliser la tokenisation et réduire la surcharge des opérations répétitives. Dans nos expériences, nous avons constaté qu'une valeur batch_size comprise entre 16 et 64 fonctionnait bien, toute valeur supérieure dégradant les performances. De même, nous avons opté pour une max_length de 128, ce qui est viable si la longueur moyenne de vos rapports est relativement courte. Grâce à ces changements, nous avons atteint une accélération globale de 8x, réduisant le temps de reclassement à moins d'une seconde, même sur le processeur.

En pratique, cela signifiait expérimenter différentes tailles de lots et longueurs de jetons pour trouver le bon équilibre entre vitesse et précision pour vos données. Ce faisant, nous avons constaté des améliorations significatives des temps de réponse, rendant le système de recherche évolutif même avec 1 000 rapports.

Conclusion

En utilisant OpenVINO et en optimisant la tokenisation et le traitement par lots, nous avons pu créer un système de recherche sémantique hautes performances qui répond aux exigences en temps réel sur une configuration uniquement CPU. En fait, nous avons connu une accélération globale de 8x. La combinaison de la récupération à l'aide de transformateurs de phrases et du reclassement avec un modèle d'encodeur croisé crée une expérience de recherche puissante et conviviale.

Si vous construisez des systèmes similaires avec des contraintes de temps de réponse et de ressources de calcul, je vous recommande fortement d'explorer OpenVINO et le traitement par lots intelligent pour débloquer de meilleures performances.

J'espère que vous avez apprécié cet article. Si vous avez trouvé cet article utile, donnez-moi un like pour que d'autres puissent le trouver également et partagez-le avec vos amis. Suivez-moi sur Linkedin pour rester au courant de mon travail. Merci d'avoir lu !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Article chaud

Combien de temps faut-il pour battre Split Fiction?
3 Il y a quelques semaines By DDD
Repo: Comment relancer ses coéquipiers
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Comment obtenir des graines géantes
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
1 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Article chaud

Combien de temps faut-il pour battre Split Fiction?
3 Il y a quelques semaines By DDD
Repo: Comment relancer ses coéquipiers
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Comment obtenir des graines géantes
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
1 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Tags d'article chaud

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Comment utiliser la belle soupe pour analyser HTML? Comment utiliser la belle soupe pour analyser HTML? Mar 10, 2025 pm 06:54 PM

Comment utiliser la belle soupe pour analyser HTML?

Filtrage d'image en python Filtrage d'image en python Mar 03, 2025 am 09:44 AM

Filtrage d'image en python

Comment télécharger des fichiers dans Python Comment télécharger des fichiers dans Python Mar 01, 2025 am 10:03 AM

Comment télécharger des fichiers dans Python

Comment utiliser Python pour trouver la distribution ZIPF d'un fichier texte Comment utiliser Python pour trouver la distribution ZIPF d'un fichier texte Mar 05, 2025 am 09:58 AM

Comment utiliser Python pour trouver la distribution ZIPF d'un fichier texte

Comment travailler avec des documents PDF à l'aide de Python Comment travailler avec des documents PDF à l'aide de Python Mar 02, 2025 am 09:54 AM

Comment travailler avec des documents PDF à l'aide de Python

Comment se cacher en utilisant Redis dans les applications Django Comment se cacher en utilisant Redis dans les applications Django Mar 02, 2025 am 10:10 AM

Comment se cacher en utilisant Redis dans les applications Django

Comment effectuer l'apprentissage en profondeur avec TensorFlow ou Pytorch? Comment effectuer l'apprentissage en profondeur avec TensorFlow ou Pytorch? Mar 10, 2025 pm 06:52 PM

Comment effectuer l'apprentissage en profondeur avec TensorFlow ou Pytorch?

Présentation de la boîte à outils en langage naturel (NLTK) Présentation de la boîte à outils en langage naturel (NLTK) Mar 01, 2025 am 10:05 AM

Présentation de la boîte à outils en langage naturel (NLTK)

See all articles