
Augmentez la précision des systèmes de recommandation avec les LLM, à l’aide de Python
dans la culture américaine est la suivante :
« Vous ne pouvez pas avoir le gâteau et le manger en même temps. »
Je trouve cette phrase extrêmement poétique mais aussi très pratique et utile. Le message de ce dicton est simple : tout ce que vous accomplissez est obtenu grâce à un compromis, car tout a un prix.
La discussion philosophique sort du cadre de cet article, mais les conséquences pratiques de ces considérations sont tout à fait conformes à la science des données et au génie logiciel en général. Laissez-moi vous expliquer.
En génie logiciel et en science des données, la « conception parfaite » n’existe pas en soi. Le même algorithme qui est fantastique pour une application donnée échoue lamentablement dans d’autres.
Pensez aux compromis calcul/mémoire dans les cas suivants :
Il est tout à fait logique de précalculer la distance entre deux villes et de les stocker dans un ensemble de données, mais cela n’a aucun sens de les calculer pendant le vol. En effet, vous vous attendez à ce que l’ensemble de données nécessite relativement peu de maintenance (les villes ne se déplacent pas souvent) et il serait stupide de calculer la distance entre New York et San Francisco chaque fraction de seconde. [Case A]
Cependant, il serait tout aussi stupide (et probablement impossible) pour un chatbot de mémoriser toutes les questions possibles qu’un humain peut poser et d’obtenir la réponse à cette question chaque fois qu’elle est posée. En effet, la nature du problème est beaucoup plus dynamique et nécessite un calcul « à la volée ». [Case B]
Dans le cas A, nous sacrifions de la mémoire et obtenons un calcul extrêmement rapide. Dans le cas B, nous passons plus de temps de calcul, mais nous n’utilisons aucune mémoire « requête ».
Pouvez-vous obtenir ni temps de calcul ni mémoire ? Pas vraiment, car on ne peut pas avoir le gâteau et le manger en même temps 🙂
Mais prenons un exemple moins évident et plus « tendance ». Parlons des grands modèles linguistiques (LLM).
Les LLM sont les modèles d’IA les plus puissants dont nous disposons, et ils sont formés sur toutes les connaissances disponibles dans le monde. Ils sont également massif. Ils sont en fait si volumineux que nous les avons rarement en interne et nous les invoquons généralement via des API. Cependant, appel API = jetons = coût.
Imaginez maintenant que vous souhaitiez utiliser un système intelligent pour choisir le meilleur restaurant pour ce soir. Vous demanderiez à ChatGPT quelque chose comme : « Pouvez-vous me proposer un bon restaurant italien qui ne soit pas très cher mais romantique et bien situé ?
Maintenant, imaginez si le modèle GPT devait explorer tous les restaurants de l’univers et décider s’ils sont italiens, pas chers, bien situés et proches de chez vous. Dans le meilleur des cas : vous dépenseriez des millions en jetons et vous seriez déjà au lit au moment où le calcul est exécuté.
Cependant, nous ne voulons pas non plus abandonner complètement tout le pouvoir juteux d’interprétation en langage naturel et de récupération d’informations des LLM. La clé est que, pour utiliser le LLM et obtenir des informations intelligentes, nous ne pouvons pas utiliser la partie la plus intelligente du pipeline à tout moment (ce serait comme avoir le gâteau et le manger aussi).
Dans cet article, je vais vous donner une recette pour ces systèmes de recommandation intelligents améliorés par LLM, en utilisant l’exemple de recommandation de restaurant que nous faisions comme cas d’utilisation.
L’entrée de ce système sera la description par l’utilisateur de son restaurant idéal dans une ville spécifique, et le résultat sera un ensemble de restaurants recommandés.
Commençons !
1. Conception du système
Le dicton du gâteau dont nous avons discuté est également connu en ingénierie sous le nom de triangle Précision-Échelle-Temps :
- Vous pouvez créer quelque chose de précis et sur un ensemble de données massif, mais cela sera lent
- Vous pouvez créer quelque chose de précis et rapide, mais cela ne s’adaptera pas bien à un grand ensemble de données
- Vous pouvez créer quelque chose rapidement et bien évoluer, mais ce ne sera pas aussi précis.

Bien sûr, nous voulons que nos résultats soient finalement précis, donc l’option 3 à elle seule ne suffira pas. Cependant, nous pouvons affiner l’option 3 avec un modèle plus précis en plus du premier. En d’autres termes, l’option 3 peut nous donner une bonne liste de candidats avec un faible temps de calcul, et nous pouvons sélectionner la liste de recommandations la plus précise à l’aide d’un grand modèle linguistique.
En d’autres termes, le design ressemble à ceci :
- Une recherche simple et rapide permettra de trouver les K restaurants les plus proches (basé sur des règles, rappel élevé, faible précision)
- Un Large Language Model lent et très intelligent nous aidera à choisir, parmi les K premiers, le meilleur en fonction de la requête. (Basé sur l’IA, haute précision)
En faisant cela, nous ne perdons pas de temps et d’argent sur le lent LLM, mais nous obtenons toujours leur intelligence en les utilisant sur une liste sélectionnée de candidats.
Assez de japper. Commençons à coder !
2. Le scénario
2.1 La configuration
J’ai fait le sale boulot en coulisses pour toi 🙂
Tout est écrit selon une programmation orientée objet (POO), avec des scripts et un pipeline qui prendront en charge l’ensemble du processus. Le dossier GitHub est celui-ciet afin de générer le reste du code, vous pouvez le cloner et utiliser ce bloc d’import ici :
2.2 Génération de données
Avant de pouvoir recommander quoi que ce soit, nous avons besoin de quelque chose à recommander. Dans un système réel, nous utiliserions une base de données de restaurants dans un emplacement S3. Pour cet article, nous en générons un synthétique afin que le tout soit entièrement reproductible et gratuit.
C’est le travail du RestaurantDataGenerator classe à l’intérieur datagenerator.py. Il construit un tableau reproductible de ~10 000 restaurants répartis dans huit villes (New York, San Francisco, Chicago, Austin, Seattle, Boston, Miami et Denver). Chaque restaurant obtient :
– un assemblé au hasard nom
– un ville et un latitude/longitude échantillonné autour du centre de cette ville (dans un rayon d’environ 13 km),
– un style de cuisine (italien, japonais, mexicain, thaï, français, …),
– un diététique profil (omnivore/végétarien/végétalien)
– un note moyenne
– un nombre de voix
– un fourchette de prix (10/100/1000, un ticket moyen d’un ordre de grandeur par personne).
Ce générateur est destiné à fonctionner une fois. Générer les données est aussi simple que :
Ce seul appel écrit la table dans data/restaurants.csvça ressemble à ça :
Parfait, maintenant que nous avons nos restaurants, voyons comment nous pouvons les recommander.
2.3 Générer les candidats
C’est Étape 1 de l’entonnoir : la liste de candidats bon marché, rapide et basée sur des règles. L’utilisateur nous indique dans quelle ville il se trouve, et nous ne gardons que les restaurants les plus proches géographiquement. Le code filtre la table jusqu’à la ville, calcule la distance orthodromique entre l’utilisateur et chaque restaurant et identifie le N_DISTANCE_CANDIDATES (50 par défaut).
Cette étape est délibérément rappel élevé, faible précision. Avec cette approche, nous pouvons parcourir toute la table (10 000 restaurants) sans un seul appel API ni coûts de jeton. Bien sûr, nous ne faisons rien de particulièrement intelligent ou sophistiqué ici, mais nous filtrons en fait toutes les données qui ne sont pas réalisables pour l’utilisateur. Cela seul est un gros problème.
Par exemple, essayons une vraie requête de recherche :
“Tacos végétaliens bon marché avec une atmosphère animée” dans plusieurs villes
Voici le résultat :
Remarquez que la liste ci-dessous n’a aucune idée de « végétalien », « bon marché » ou « tacos » : elle ne connaît que la distance. Cependant, ce n’est pas grave, car le but de cette étape est de créer un point de départ dans la bonne ville que le LLM reclassera lors de l’étape 2.
Préparons-nous pour le LLM !
2.4 Sélection des candidats
C’est Étape 2l’extrémité lente, intelligente, pilotée par LLM et de haute précision de l’entonnoir. Cela s’ajoute directement à la liste restreinte de 50 restaurants de la version 2.3. Le LLM ne voit jamais le tableau complet de 10 000 lignes ; il ne voit que la petite tranche déjà pertinente que le filtre de distance lui a remise.
Nous parlons au modèle via un petit client OpenAI. La clé est lue depuis OPENAI_API_KEY (enregistré dans l’environnement). Le recommandateur, défini comme RestaurantRecommenders’exécute sur la requête et sur la ville via RestaurantRecommender.recommender(query,city):
Quelques points méritent d’être soulignés :
- La précision augmente. L’étape 1 était un rappel élevé, une faible précision : elle renvoyait les 50 restaurants les plus proches quelle que soit la demande. L’étape 2 lit réellement la requête (tacos végétaliens bon marché avec une atmosphère animée), rejette tout ce qui ne rentre pas et renvoie uniquement les 5 à 10 meilleurs avec un honnête
fit_score.
- Sortie structurée avec Pydantic. Nous n’analysons jamais de texte de forme libre. Le modèle est obligé de répondre sous la forme d’un modèle Pydantic (via des sorties structurées OpenAI), de sorte que chaque réponse est garantie de correspondre au schéma.
Le schéma de sortie porte le restaurant_id et name (parmi les candidats), un fit_scorevaleur comprise entre 0 et 100, et un court reason. La réponse est également accompagnée d’un message amical summary. Lancer l’appel pour nos trois villes donne par exemple :
Si vous remarquez, c’est bien mieux que les listes restreintes de distance brute de la version 2.3. Là, le restaurant le plus proche de chaque ville était une correspondance essentiellement aléatoire (coréen, libanais, mexicain mais végétarien). Ici, le modèle a réorganisé les même 50 candidats autour de ce que nous avons réellement demandé : les établissements végétaliens et mexicains arrivent en tête avec un haut niveau de popularité.fit_scoreset le modèle est honnête lorsque rien ne correspond parfaitement, marquant les correspondances partielles et expliquant pourquoi dans le reason. C’est la précision que le LLM nous achète, appliquée à une liste suffisamment petite pour rester bon marché à grande échelle.
3. Résultats
Prenons du recul et regardons ce que l’entonnoir en deux étapes nous a réellement apporté, en utilisant la même requête dans trois villes : “Tacos végétaliens bon marché avec une atmosphère animée”.
- L’étape 1 nous donne la liste des candidats. Les listes restreintes de distance de 2.3 étaient de par leur conception un rappel élevé et une faible précision.
- L’étape 2 identifie les véritables recommandations. Nourrir les 50 candidats de l’étape 1 au LLM les réorganise autour de ce qui a été réellement demandé.
Voici les choix finaux renvoyés par le modèle pour chaque ville :
- New York: Cuillère dorée (végétalien, 4,9) et Fourchette Maison (Mexicain, dans le budget) se hisse au sommet avec des scores d’ajustement de 90 et 85.
- Miami: Taverne Royale & Co. (végétalien, mexicain, abordable) mène à 85.
- Boston: Cuillère urbaine et Petite maisondeux spots mexicains à petit budget, occupent les deux premières places à 90 et 85.
Dans chaque ville, le modèle promouvait les candidats qui correspondaient aux intentions végétaliennes, bon marché et mexicaines/tacos, et il était honnête sur les ajustements imparfaits : les endroits qui répondaient parfaitement au régime mais pas à la cuisine (ou vice versa) étaient conservés comme sauvegardes avec des prix visiblement inférieurs. fit_scores.
4. Conclusions
Merci de passer du temps avec moi, cela signifie beaucoup. ❤️ Voici ce que nous avons réalisé ensemble :
– Création d’un entonnoir de recommandation en deux étapes, à la fois évolutif et intelligent.
– Utilisation d’un filtre de distance bon marché basé sur des règles (étape 1) pour réduire 10 000 restaurants aux 50 les plus proches.
– Utilisation d’un reclassement LLM (étape 2) pour transformer ces 50 candidats parmi les 5 à 10 meilleurs, avec un score honnête et une raison pour chacun.
Dans de nombreux projets réels, un entonnoir comme celui que nous avons construit ici est généralement très populaire. Ces types de systèmes sont très évolutifs, car le LLM est utilisé de manière judicieuse et intelligente, car nous utilisons des modèles capables de comprendre le contexte de manière très efficace.
7. Avant de partir !
Merci encore pour votre temps. Cela signifie beaucoup. Je m’appelle Piero Paialunga et je suis ce type ici :

Je suis originaire d’Italie, je suis titulaire d’un doctorat. de la Université de Cincinnatiet travaille comme Data Scientist chez The Trade Desk à New York. J’écris sur IA, apprentissage automatique et rôle évolutif des data scientists à la fois ici sur TDS et sur LinkedIn. Si l’article vous a plu et souhaitez en savoir plus sur le machine learning et suivre mes études, vous pouvez :
A. Suivez-moi sur Linkedinoù je publie toutes mes histoires
B. Suivez-moi sur GitHuboù vous pouvez voir tout mon code
C. Pour toute question, vous pouvez m’envoyer un email à piero.paialunga@hotmail



