Exploiter la puissance du modèle o1 en sciences physiques

Pratiquant le tennis de table depuis de nombreuses années, je me suis penché sur un phénomène bien connu des pongistes et surnommé “carotte”. Il s’agit d’un point qui se termine sur un coup “hasardeux” faisant tomber la balle sous sur la bande du filet, puis du côté adverse, soit sur l’une des trois arêtes de la demi-table adverse.

Un phénomène assez étonnant semble être la sur-proportion de balles hautes (coup de défense jouée par l’opposant) tombant sur l’arête de la table comme en témoigne cette compilation de la chaîne Monqui Pong. Simple hasard ou régularité statistique ? Y a-t-il une ou plusieurs explications scientifiques à cela ?

[NDA : il y aura deux manières de lire cet article, l’une portée sur le modèle d’intelligence artificielle utilsé, l’autre sur les aspects purement liés au tennis de table. Certains lecteurs seront sans doute intéressés par les deux !]

Pour nous aider, nous allons faire appel au plus doué des modèles de langage : o1 de la société OpenAI. Ce modèle a la particularité d’avoir intégré les chaines de pensée (chain of thought) lors de son entrainement et donc de pouvoir reproduire des raisonnements complexes.

On a souvent entendu dire que les modèles de fondation ne disposaient pas d’une connaissance physique du monde et c’est pourquoi les générateurs d’images ou de vidéos pouvaient produire des aberrations physiques ou mécaniques, choquant ainsi notre perception humaine.

Rappelons-nous toutefois que nous sommes tous passés par la phase expérimentale du jet d’objets depuis notre chaise haute de bébé pour tester la gravité universelle ! C’est cette expérience continue du quotidien qui nous permet ensuite de considérer les lois physiques comme “naturelles” et si évidentes.

Déploiement du modèle o1 dans Azure

Le modèle o1 est à ce jour (janvier 2025) disponible dans les régions East US2 et Sweden Central, en mode “Global Standard”. Afin de réaliser le déploiement, il est nécessaire de remplir un formulaire de demande d’accès.

Le modèle dispose de connaissances allant jusqu’à octobre 2023, il connaît donc les dimensions officielles d’une table de ping-pong ainsi que les caractéristiques des balles plastiques.

Comparaison des réponses entre o1 et ChatGPT

Probabilité de toucher l’arête

Testons un premier prompt qui donner la probabilité de toucher l’arête de la demi-table adverse.

Soit une table de ping-pong vue de dessus, aux dimensions officielles. En posant l’hypothèse que l’arête de la table mesure 1 millimètre, quelle est la probabilité que la balle touche l’une des trois arêtes de la table adverse ? On considèrera une répartition uniforme des balles sur la table, sauf si d’autres lois mathématiques permettent de modifier cette hypothèse.

<DEBUT DE LA REPONSE DU MODELE o1>

Pour répondre à cette question, il faut d’abord préciser les dimensions officielles d’une table de ping-pong : elle mesure 2,74 m de long et 1,525 m de large. Le filet la partage en deux moitiés égales, chacune de 1,37 m × 1,525 m. Vue de dessus, « la table adverse » peut donc être modélisée par un simple rectangle de 1,37 m sur 1,525 m, dont on veut connaître la probabilité qu’un point (où la balle atterrit) se trouve à 1 mm ou moins d’une des trois arêtes extérieures (on ne compte pas le côté du filet).

Aire totale de la demi-table

L’aire A de la demi-table est A = 1,37 m × 1,525 m = 2,08825 m².

Aire « au bord » de chacune des arêtes

Les deux arêtes latérales (longueur 1,37 m) :

chacune est bordée, sur toute sa longueur, d’une bande de largeur 0,001 m (1 mm). L’aire d’une telle bande vaut donc 1,37 m × 0,001 m = 0,00137 m²

et comme il y en a deux, l’aire totale pour ces deux côtés est 2 × 0,00137 m² = 0,00274 m².

L’arête du fond (largeur 1,525 m) : elle est bordée d’une bande de même largeur (1 mm), d’aire 1,525 m × 0,001 m = 0,001525 m².

En additionnant ces aires, on obtient 0,00274 m² + 0,001525 m² = 0,004265 m². Cependant, on compte deux fois les petites zones de recouvrement dans les deux coins (là où une arête latérale et l’arête du fond se croisent). Chacune de ces zones de recouvrement est un carré de côté 1 mm = 0,001 m, donc d’aire 0,001 m × 0,001 m = 1×10⁻⁶ m². Il y a deux coins, donc une aire totale de 2 × 1×10⁻⁶ m² = 2×10⁻⁶ m² à soustraire une fois de la somme précédente.

La « surface au bord » corrigée vaut donc

S_bord = 0,004265 m² − 2×10⁻⁶ m² = 0,004263 m²

(en pratique, la différence est très faible).

Probabilité de toucher un bord

Si l’on suppose que la balle « atterrit » de façon uniforme sur la demi-table (hypothèse simplificatrice), la probabilité P de toucher l’une des trois arêtes extérieures est le rapport

P = S_bord / A

soit

P ≈ 0,004263 m² / 2,08825 m² ≈ 0,00204.

En pourcentage, cela donne environ 0,00204 × 100 % ≈ 0,20 %.

RÉPONSE

Sous l’hypothèse d’une répartition uniforme des balles et en négligeant les effets du filet, la probabilité qu’une balle touche l’une des trois arêtes extérieures de la demi-table adverse est d’environ 0,2 %.

<FIN DE LA REPONSE DU MODELE o1>

Le modèle o1 nous propose un raisonnement se décomposant en différentes étapes permettant d’arriver à une conclusion. Chacune de ces étapes comporte des calculs mathématiques dont les valeurs peuvent être reprises aux étapes suivantes. Nous sommes bien loin des premiers balbutiements du modèles GPT 3.5 avec les chiffres !

Les logs de l’appel au modèle nous renseigne sur les tokens utilisés. La facturation portera sur les tokens utilisés dans le prompt (la question), la complétion (la réponse) mais également lors des étapes de raisonnement qui ne sont pas visibles pour l’utilisateur.

“completion_tokens”: 3233,
“prompt_tokens”: 111,

“total_tokens”: 3344,
“completion_tokens_details”: {
“accepted_prediction_tokens”: 0,
“audio_tokens”: 0,
“reasoning_tokens”: 2304,
“rejected_prediction_tokens”: 0

Les tokens de raisonnement ne sont pas visibles via l’API mais ils seront en revanche bien facturés ! La société OpenAI justifie ceci dans cette documentation.

L’appel au modèle o1 peut, de temps en temps, ne pas donner de réponse en raison de la longueur de la réponse qui dépasse le paramètre par défaut (4096 tokens). Les logs seront alors comme tels.

“finish_reason”: “length”,
“index”: 0,
“logprobs”: null,
“message”: {
“content”: “”,
“refusal”: null,
“role”: “assistant”}

Les paramètres sont visibles dans l’interface Azure.

En Python, le code ci-dessous modifie la valeur maximale pour la complétion.

max_completion_tokens=8192

LLa question similaire soumise à ChatGPT, dans sa version gratuite, nous donne la réponse suivante :

Nous remarquons une première erreur de raisonnement puisque ce n’est pas la demi-table de l’adversaire qui est considérée mais bien le côté complet (2,74m). Le modèle o1 a bien évité cette erreur.

Les pongistes retiendront que sur 1000 balles tombant “au hasard” sur la demi-table adverse, deux seulement devraient toucher l’arête.

Hypothèse de l’attraction des corps

Une idée (farfelue ?) déjà entendue dans une salle de ping est que l’attraction de deux corps (la table et la table) “détournerait” la balle d’une trajectoire sortante pour qu’elle vienne frôler l’arête de la table. Soumettons donc cette question à o1, à l’aide du prompt ci-dessous.

Soit une table de ping-pong vue de dessus, aux dimensions officielles. On définit comme une “carotte” l’impact de la balle sur une des tranches supérieures de la demi-table de l’adversaire. L’attraction des corps entre la balle et l’arête est-elle suffisante pour attirer une balle tombant d’une certaine hauteur et augmenter la probabilité d’une carotte ? Utilise le poids et la dimension officiels d’une balle.

<DEBUT DE LA REPONSE DU MODELE o1>

Pour répondre à cette question, il faut évaluer l’ordre de grandeur de la force d’attraction gravitationnelle entre la balle et l’arête de la table, puis comparer cette force à d’autres forces en jeu (en particulier le poids de la balle), afin de déterminer si elle est significative.

Données de base
  • Masse d’une balle de tennis de table (officielle) : m_b = 2,7 g = 2,7×10⁻³ kg
  • Diamètre d’une balle : environ 40 mm
  • Masse typique d’une demi-table (en considérant le cadre + panneau) : on peut estimer une cinquantaine de kg pour simplifier (m_t = 50 kg), même si cela peut varier.
  • Constante de gravitation universelle : G ≈ 6,67×10⁻¹¹ N·m²·kg⁻²
  • Accélération de la pesanteur : g ≈ 9,81 m·s⁻²

Le poids de la balle, c’est-à-dire la force qui l’attire vers le sol, vaut :

F_poids = m_b × g = 2,7×10⁻³ × 9,81 ≈ 2,65×10⁻² N

Force gravitationnelle entre la balle et l’arête

Si l’on modélise (de façon très grossière) la portion de table à proximité de l’arête comme un « bloc » de masse m_t, et que la distance entre le centre de la balle et le bloc soit de l’ordre du centimètre (r = 0,01 m), la force gravitationnelle F_g entre la balle et la table se calcule par la loi de Newton :

F_g = G × (m_b × m_t) / r²

Substituons les valeurs (en prenant m_t = 50 kg, r = 0,01 m) :

F_g = 6,67×10⁻¹¹ × (2,7×10⁻³ × 50) / (0,01)²

= 6,67×10⁻¹¹ × (1,35×10⁻¹) / 10⁻⁴

= 6,67×10⁻¹¹ × 1,35×10⁻¹ × 10⁴

= 6,67×10⁻¹¹ × 1,35×10⁻¹ × 10⁴

Faisons l’estimation pas à pas :

1,35×10⁻¹ = 0,135

6,67×10⁻¹¹ × 0,135 ≈ 9×10⁻¹² (en arrondissant)

Multiplié par 10⁴ donne à peu près 9×10⁻⁸ N

Autrement dit : F_g ≈ 9×10⁻⁸ N

Comparaison à d’autres forces

Le poids de la balle est d’environ 2,65×10⁻² N.

La force gravitationnelle due à l’arête de la table : ≈ 9×10⁻⁸ N.

On constate que F_g est plus d’un million de fois plus faible que le poids de la balle (un rapport d’environ 10⁻⁶). Même en tenant compte d’approximations (distance un peu plus courte, table un peu plus massive, etc.), il est clair que cette force d’attraction est négligeable : elle ne peut pas « attirer » la balle de manière significative pour favoriser un rebond sur l’arête.

Conclusion

L’attraction gravitationnelle entre la balle de ping-pong et l’arête de la table est extrêmement faible comparée au poids de la balle et aux autres forces (rebond, frottements de l’air, etc.). Elle n’influence donc pratiquement pas la trajectoire. Autrement dit, non, cette attraction ne peut pas augmenter la probabilité de réaliser une « carotte » (rebond sur l’arête supérieure).

En pratique, le fait qu’une balle tombe sur l’arête résulte surtout de la trajectoire initiale, de la vitesse, de l’effet (spin) éventuel, et bien sûr d’un peu de hasard — mais pas d’une quelconque « force d’attraction » exercée par l’arête de la table.

<FIN DE LA REPONSE DU MODELE o1>

Les pongistes ne retiendront donc pas cette hypothèse d’attraction entre la table et la balle.

[NDA : ici s’arrête l’article pour les personnes qui ne s’intéressent qu’à l’intelligence artificielle. Les pongistes peuvent continuer.]

Augmenter la probabilité d’une carotte ?

Au gré des échanges avec ChatGPT, j’ai soumis le prompt suivant, lui laissant libre cours pour proposer ses solutions.

Soit une table de ping-pong vue de dessus, aux dimensions officielles. On définit comme une ‘carotte’ l’impact de la balle sur une des arêtes supérieures de la demi-table de l’adversaire ou bien le fait d’accrocher le filet et de retomber sur la demi-table adverse. Propose-moi une ou plusieurs approches basées sur les lois de la physique pour augmenter la probabilité d’une carotte.

Une proposition attire mon attention.

Cette excellente vidéo disponible sur la chaîne ARTE vous apprendra tout sur l’effet Magnus.

Mais y aurait-il un impact d’une hauteur initiale plus grande sur la trajectoire de la balle l’amenant à toucher le bord de table ? La question mérite d’être étudiée mais on peut la reformuler différemment. En effet, il est quasi impossible pour l’adversaire de remettre une balle qui toucherait l’arête mais n’aura pas un rebond “vers le haut”. La balle effleure l’arête et prolonge alors sa course vers le sol. Le prompt suivant formule cette question.

Soit une table de ping-pong vue de dessus, aux dimensions officielles. On définit comme une ‘carotte’ l’impact de la balle sur une des arêtes supérieures de la demi-table de l’adversaire ou bien le fait d’accrocher le filet et de retomber sur la demi-table adverse. Etablis une démonstration scientifique pour identifier les caractéristiques nécessaires à la balle (vitesse, hauteur, rotation, surface de contact avec la table…) pour ne pas rebondir vers le haut lorsqu’elle tombe sur l’arête de la demi-table adverse.

<DEBUT DE LA REPONSE DU MODELE o1>

D’un point de vue purement physique, l’« effet carotte » (c’est‐à‐dire le fait qu’une balle de ping‐pong percute l’arête supérieure de la demi‐table adverse et « glisse » au lieu de rebondir vers le haut) peut s’analyser comme un choc avec un obstacle situé au bord de la table, combiné à des effets de frottement et de rotation. L’objectif est de déterminer les conditions (vitesse, hauteur, rotation, etc.) pour que la composante verticale finale de la vitesse de la balle (dans le repère de la table) soit nulle ou dirigée vers le bas, de sorte que la balle ne « saute » pas mais « file » au ras de la table.

Modélisation du système
Repères et hypothèses simplificatrices

On se place dans un repère où le plan de la table coïncide avec le plan (x,y), et l’axe z est vertical (z>0 vers le haut).

L’arête supérieure (ou le bord) de la demi‐table adverse est schématiquement modélisée comme un « coin » horizontal dont l’arête est à z=0.

La balle (de rayon R) entre en contact avec l’arête à un instant t₀, avec une vitesse (vectorielle) du centre de gravité V = (Vₓ, Vᵧ, V𝓏) et une rotation ω = (ωₓ, ωᵧ, ω𝓏).

On suppose un choc partiellement inélastique caractérisé par un coefficient de restitution e < 1 dans la direction normale au plan de contact, et l’existence d’une force de frottement (coefficient µ) dans la direction tangentielle.

Contact et normal de choc

Au moment du contact, la normale de choc n → est (en première approche) dirigée horizontalement ou légèrement vers le haut/vers le bas selon la géométrie réelle de l’arête (on peut l’assimiler à une surface verticale ou oblique).

Toutefois, on retiendra l’idée générale : il y a toujours une décomposition de la vitesse relative de la balle au point de contact entre :

– Composante normale Vₙ = V · n → (scalaire)

– Composante tangentielle Vₜ = V − (Vₙ n →)

Décomposition du choc et conditions de rebond
Coefficient de restitution (choc normal)

Le changement de la composante normale de la vitesse s’écrit, dans le cas d’un choc central simple avec coefficient de restitution e :

Vₙ′ = − e Vₙ

où Vₙ est la composante normale de la vitesse juste avant l’impact, et Vₙ′ celle juste après.

Si e < 1, la vitesse normale est réduite en amplitude et inversée de sens (rebond « inélastique »).

Dans l’idéal (e=0), la balle « s’écrase » complètement dans la direction normale et ne repart pas (aucune composante normale après le choc).

Frottement et transfert de rotation

Le point de contact subit également une force tangentielle de frottement Fₒₜ. Dans le cas d’une balle en rotation, l’effet du frottement peut être décomposé en :

  • Une force tangentielle (au point de contact) qui modifie la composante tangentielle de la vitesse du centre de gravité.
  • Un couple de frottement qui agit sur la balle et modifie sa rotation.

Suivant le signe de ω et la direction de la vitesse tangentielle, la balle peut :

  • Accélérer (ou décélérer) dans la direction tangentielle,
  • Augmenter (ou diminuer) sa rotation.

Le frottement peut donc contribuer à « plaquer » la balle vers le bas si la rotation et la direction du frottement s’y prêtent (par exemple, balle avec un backspin approprié).

Condition pour « ne pas repartir vers le haut »

On souhaite que la composante verticale finale V𝓏′ de la balle (après la
collision) soit ≤ 0. Or, V𝓏′ résulte :

De la restitution dans la direction normale (si la normale de contact a une composante verticale),

Des effets du frottement (la force tangentielle peut avoir une composante verticale si la géométrie de l’arête l’impose, ou si la balle « mord » légèrement le haut de la table),

De la modification de la rotation qui peut influer sur la direction de glissement. En schématisant la direction normale au choc comme ayant un angle α par rapport à l’horizontale (α = 0 si la surface de contact est parfaitement verticale), la composante verticale de la vitesse normale finale devient :

V𝓏′(normal) =(− e |Vₙ|) sin α ,

alors que la composante tangentielle (considérant un frottement µ et un bras de levier R pour la balle) peut générer une correction ∆V𝓏′(tan
gent) dépendant du couple et de la vitesse tangentielle initiale. Au premier ordre, on écrit souvent :

|∆V𝓏′(tangent)| ≈ f ( µ, Vₜ, ω, R )

La condition pour que le résultat global soit V𝓏′ = V𝓏′(normal) + ∆V𝓏′(tangent) ≤ 0 nous donne l’inégalité à satisfaire :

(− e |Vₙ|) sin α + f(µ, Vₜ, ω, R) ≤ 0

Le terme f(µ, Vₜ, ω, R) peut être soit positif, soit négatif, selon le sens du frottement et l’effet de la rotation (backspin, topspin, etc.).

Analyse qualitative des paramètres requis

Pour qu’il n’y ait pas de rebond vers le haut, plusieurs conditions pratiques se dégagent :

Composante verticale initiale (avant choc) faible ou négative :

– Si la balle arrive presque horizontalement (V𝓏 < 0, c’est‐à‐dire légèrement en descente), le choc peut la contraindre à poursuivre vers le bas ou à rester rasante.

– Si la balle a une composante verticale trop grande vers le bas, elle risque d’impacter fortement l’arête et rebondir (même si c’est un rebond faible, il peut y avoir un « saut » vers le haut).

Vitesse horizontale élevée et angle rasant :

– Une forte vitesse horizontale (Vₓ ou Vᵧ) diminue le temps de contact et réduit l’élévation éventuelle post‐choc.

– Plus l’angle d’incidence est rasant (de faible α par rapport à la table), plus la balle est « glissante » au contact, ce qui favorise l’effet « carotte ».

Rotation adaptée :

– Un backspin (rotation « rétro ») approprié crée une composante tangentielle au contact qui, couplée au frottement, peut appliquer à la balle un effort dirigé vers le bas.

– Un topspin (rotation « avant ») a tendance au contraire à faire remonter la balle après contact si la friction agit dans le sens de faire rouler la balle sur la table.

Coefficient de restitution et frottement :

– Un matériau de la balle et/ou de la table avec un coefficient de restitution faible (e petit) limite l’énergie renvoyée à la balle dans la direction normale : le rebond est donc plus « amorti ».

– Un coefficient de frottement suffisant (µ) peut consolider l’effet d’adhérence, permettant de convertir une partie de la vitesse tangentielle en couple et de tirer la balle vers le bas si la rotation le permet.

Conclusion pratique

Pour qu’une balle de ping‐pong ne rebondisse pas vers le haut en touchant précisément l’arête supérieure de la demi‐table adverse (et qu’elle « glisse » ou « tombe » sur la table au lieu de « sauter »), il faut réunir :

  • Une incidence suffisamment rasante (faible hauteur de chute ou vitesse essentiellement horizontale).
  • Un coefficient de restitution globalement faible dans la direction du choc (e petit dans la mesure du possible).
  • Une rotation (typiquement un backspin ou une rotation « latérale adéquate ») qui, par le frottement, aide à orienter la résultante du choc vers le bas ou à annuler la composante verticale finale.
  • Une vitesse verticale descendante minimale (ou nulle) juste avant l’impact pour éviter un choc normal trop fort qui renverrait la balle vers le haut.

En pratique, cela se traduit souvent par un geste très précis : la balle frôle littéralement l’arête, arrive avec un léger effet rétro ou latéral, et voit son énergie de rebond absorbée par la combinaison du choc inélastique et du glissement/frottement sur l’arête ou le filet. Ainsi, elle ne « saute » pas mais poursuit sa course rase sur la demi‐table adverse, réalisant alors la fameuse « carotte ».

<FIN DE LA REPONSE DU MODELE o1>

Voici les tokens qui auront été nécessaires pour développer cette démonstration :

“completion_tokens”: 4014,
“prompt_tokens”: 143,

“total_tokens”: 4157,
“completion_tokens_details”: {
“accepted_prediction_tokens”: 0,
“audio_tokens”: 0,
“reasoning_tokens”: 1920,
“rejected_prediction_tokens”: 0

A vous maintenant de jouer pour décortiquer cette réponse ou bien de retourner jouer… à la table ! Et surtout, n’oubliez pas de vous excuser après une “carotte”.

Ajouter GitHub Copilot à Visual Studio Code

Les modèles de langage ont rapidement prouvé que s’ils pouvaient exploiter le langage naturel des humains, ils pouvaient aussi être très doués pour la programmation. Les premiers modèles dédiés au code sont donc assez vite apparus et se sont tout naturellement intégrés au sein des IDE (Integrated Developement Environment). Des études ont démontré l’impact très fort sur le travail quotidien des développeurs.

Microsoft propose ainsi GitHub Copilot dans son produit Visual Studio Code. Jusqu’ici (décembre 2024), l’outil était soumis à une licence payante. Mais une annonce récente de Satya Nadella a dévoilé sa mise à disposition gratuite pour tous les utilisateurs disposant d’un compte personnel, gratuit également, sur le site GitHub.com. Nous allons voir comment activer GitHub Copilot, dans cette nouvelle version.

Vérifiez tout d’abord que vous avez reçu un email provenant de l’adresse no-reply@github.com sur votre adresse vous servant d’identifiant sur GitHub.

Cliquez sur le lien “Start using Copilot” inclus dans ce mail.

Vous recevrez alors un second email expliquant le processus pour démarrer l’outil GitHub Copilot.

L’interface GitHub Copilot apparaît alors dans un navigateur web.

Nous pouvons alors commencer à interagir avec le Copilot.

Il faut noter qu’il est possible de choisir le LLM qui sur lequel s’appuyera GitHub Copilot. Alors que la toute première version utilisait le modèle Codec d’OpenAI, nous bénéficions maintenant de l’avancée des LLM généralistes et de leur capacité à comprendre et produire du code.

Voici le cadre d’utilisation offert par Microsoft:

  • 2 000 compléments de code par mois
  • 50 messages Copilot Chat par mois (comprendre le code, refactoriser ou à déboguer un problème…)
  • Choisir entre Claude 3.5 Sonnet et OpenAI GPT-4o.
  • Apporter des modifications à plusieurs fichiers avec Copilot Edits
  • Accéder à des agents tiers conçus pour des tâches telles que l’interrogation de Stack Overflow ou la recherche sur le web avec Perplexity.

Les IDE suivants permettent l’utilisation de GitHub Copilot.

Nous retrouvons les différents paramétrages de GitHub Copilot dans le menu Settings du compte personnel GitHub, sur l’URL https://github.com/settings/copilot.

Par défaut, GitHub n’utilise pas vos données pour entrainer d’autres modèles d’intelligence artificielle.

Installer GitHub Copilot dans VS Code

Nous sommes alors redirigés vers la page de téléchargement de l’extension GitHub Copilot:

https://marketplace.visualstudio.com/items?itemName=GitHub.copilot

Cliquez ici sur le bouton “Install” qui lancera alors Visual Studio Code.

Authentifiez-vous à l’aide du bouton “Sign in to GitHub.com”. Le petit icone symbolisant Copilot est maintenant visible en bas à droite de l’écran. En cliquant sur ce bouton, nous déroulons les commandes relatives à GitHub Copilot dans la barre de recherche de l’IDE.

Quelques commandes

Même si le principe général des Copilots est d’interagir en langage naturel, il existe quelques commandes utiles pour réaliser des actions précises, précédées par un slash.

Le contexte à prendre en compte est précisé par un mot-clé précédé d’un dièse.

Copilot Edits

Copilot Edits permet de réaliser des modifications sur un ou plusieurs fichiers de l’espace de travail (workspace), sur la base d’instructions données en langage naturel.

Dans l’exemple ci-dessous, nous demandons au Copilot de créer un fichier de tests unitaires pour les fonctions développées dans le fichier passé en référence.

Un nouveau fichier apparaît alors dans l’espace de travail. Les boutons “accept” et “discard” permettent de valider ou refuser les propositions faites par Copilot.

Les assistants de programmation sont devenus en quelques mois des outils incontournables, véritablement accélérateurs pour les débutant.e.s et support du quotidien pour les plus expérimenté.e.s. Avec cette offre gratuite, Microsoft démocratise leur usage.

Maîtriser les logs de modèle de ML sous Microsoft Fabric

Microsoft Fabric est la nouvelle plateforme data & IA de Microsoft, permettant de travailler de bout en bout (de la collecte à la visualisation) des données, selon différentes expériences, correspondant à différents personae du monde de la data : Data Engineer, Data Analyst et également Data Scientist.

Les Scientifiques de données ont la possiblité de lancer un environnement de travail basé sur des notebooks, qui s’exécuteront sur un cluster Spark. Les données pourront bien sûr être stockées dans One Lake, le système central de stockage sur lequel s’appuie Fabric.

Les personnes habituées des environnements comme Azure Machine Learning ou Azure Databricks connaissent bien le produit Open-Source MLFlow, outil devenu un standard pour tracer les hyperparamètres d’entrainement ainsi que les métriques d’évaluation et pour stocker tous les artefacts liés à un modèle de Machine Learning : fichier des requirements, binaire du modèle sauvegardé, définition des input et output

Microsoft a donc également intégré MLFlow au sein de la plateforme Fabric. Et pour simplifier son utilisation, il n’est même pas nécessaire d’appeler explicitement la session MLFlow pour déclencher le suivi des logs ! Il s’agit du mécanisme d’autologging documenté ici.

Pour autant, il peut être intéressant de définir explicitement les entrainements et les éléments (paramètres et métriques) que l’on veut voir enregistrés dans MLFlow.

Dans cet article, nous allons détailler ces deux modes de travail avec MLFlow intégré dans Microsoft Fabric.

Création implicite d’une expérience

Pour illustrer les différentes fonctionnalités, nous allons utiliser du code généré par ChatGPT, à l’aide du prompt suivant :

Ecris-moi un code Python qui illustre une classification Sklearn en utilisant un dataset de ce package

Nous pouvons maintenant exécuter le notebook contenant ce code.

La méthode .fit() de la librairie Scikit-learn déclenche l’enregistrement d’un run (exécution) au sein d’une experiment (expérience) dont le nom est, par défaut, celui du notebook (ici “Notebook-1”).

Ces deux éléments sont des liens cliquables qui vont nous permettre de naviguer dans d’autres éléments maintenant stockés dans l’espace de travail utilisé pour ce notebook.

Les différents artefacts sont liés au run et l’on retrouve en particulier les graphiques générés dans le notebook.

Modifions maintenant la valeur d’un hyperparamètre de l’entrainement afin de comparer deux runs :

model = LogisticRegression(max_iter=200, penalty='None')

Une bonne pratique consiste alors à modifier les noms des runs afin de savoir à quoi ceux-ci correspondent.

Une action manuelle sera nécessaire pour enregistrer le modèle, depuis la vue du run.

Save run as an ML model

Au premier enregistrement du modèle, il est nécessaire de lui attribuer un folder (dossier) puis un nom.

La modèle est alors enregistré en version 1.

L’interface permet alors de déclencher un assistant qui génèrera le code nécessaire à l’inférence (i.e. l’utilisation du modèle pour générer des prévisions).

Le code généré est basé sur la librairie synapseml développé par Microsoft.

Nous disposons maintenant de trois éléments dans le workspace :

  • notebook
  • experiment (tous les runs)
  • ML model

Syntaxes explicites MLFlow

Explorons maintenant les différentes syntaxes MLFlow qui nous permettront de :

  • visualiser l’URI du serveur
  • choisir les entrainements à tracer
  • choisir les hyperparamètres et métriques recueillies
  • enregistrer une nouvelle version du modèle

Le code exécuté de manière implicite était le suivant :

import mlflow

mlflow.autolog(
log_input_examples=False,
log_model_signatures=True,
log_models=True,
disable=True,
exclusive=True,
disable_for_unsupported_versions=True,
silent=True
)

Nous commençons par importer la librairie MLFlow, déjà pré-installée sur le cluster Spark.

Le paramètre le plus important est sans doute “disable” qui permet de désactiver les logs automatiques à l’échelle du notebook (nous verrons plus tard comment le faire au niveau du workspace).

Nous pouvons maintenant définir le nom de l’experiment à l’aide de l’instruction set_experiment() et visualiser l’URI de tracking avec la syntaxe get_tracking_uri().

Voici le code de la classification, adapté pour utiliser explicitement les commandes MLFlow. Le prompt suivant a permis de générer ce code :

Ajoute les éléments nécessaires au tracking des hyperparamètres et métriques dans MLFlow

with mlflow.start_run():

    # Hyperparamètres
    max_iter = 200

    # Créer un modèle de régression logistique
    model = LogisticRegression(max_iter=max_iter)
    model.fit(X_train, y_train)

    # Prédire les étiquettes pour l'ensemble de test
    y_pred = model.predict(X_test)

    # Évaluer la performance du modèle
    accuracy = accuracy_score(y_test, y_pred)
    conf_matrix = confusion_matrix(y_test, y_pred)
    class_report = classification_report(y_test, y_pred, output_dict=True)

    # Enregistrer les hyperparamètres et les métriques dans MLFlow
    mlflow.log_param("max_iter", max_iter)
    mlflow.log_metric("accuracy", accuracy)
    for label, metrics in class_report.items():
        if isinstance(metrics, dict):
            for metric_name, metric_value in metrics.items():
                mlflow.log_metric(f"{label}_{metric_name}", metric_value)

    # Enregistrer la matrice de confusion comme une image
    plt.figure(figsize=(8, 6))
    plt.imshow(conf_matrix, interpolation='nearest', cmap=plt.cm.Blues)
    plt.title('Confusion Matrix')
    plt.colorbar()
    tick_marks = np.arange(len(iris.target_names))
    plt.xticks(tick_marks, iris.target_names, rotation=45)
    plt.yticks(tick_marks, iris.target_names)

    fmt = 'd'
    thresh = conf_matrix.max() / 2.
    for i, j in np.ndindex(conf_matrix.shape):
        plt.text(j, i, format(conf_matrix[i, j], fmt),
                 ha="center", va="center",
                 color="white" if conf_matrix[i, j] > thresh else "black")

    plt.ylabel('True label')
    plt.xlabel('Predicted label')
    plt.tight_layout()
    plt.savefig("confusion_matrix.png")
    mlflow.log_artifact("confusion_matrix.png")

    # Enregistrer le modèle entraîné
    mlflow.sklearn.log_model(model, "iris-classifier-model")

    # Affichage des coefficients de la régression logistique
    print("Coefficients de la régression logistique:")
    print(model.coef_)

    # Afficher les coefficients sous forme graphique
    plt.figure(figsize=(10, 5))
    plt.bar(range(len(model.coef_[0])), model.coef_[0])
    plt.xlabel('Features')
    plt.ylabel('Coefficient Value')
    plt.title('Coefficients de la Régression Logistique pour chaque Feature')
    plt.savefig("coefficients.png")
    mlflow.log_artifact("coefficients.png")

print(f"Accuracy: {accuracy:.2f}")
print("Confusion Matrix:")
print(conf_matrix)
print("Classification Report:")
print(classification_report(y_test, y_pred))

Les liens sont toujours disponibles dans les logs de la cellule du notebook.

Le modèle est ainsi déjà enregistré, il n’est plus nécessaire de réaliser l’étape manuelle vue précécemment.

Enfin, il est possible (recommandé) d’améliorer le log du modèle en précisant des exemples d’input et d’output, ce que l’on appelle la signature du modèle.

# Enregistrer le modèle avec sa signature
from mlflow.models.signature import infer_signature

signature = infer_signature(
    X_test, y_pred
)

model_name = "orders-outliers-model"

mlflow.sklearn.log_model(
        model,
        model_name,
        signature=signature,
        registered_model_name=model_name
)

   Pour conserver la cohérence avec l’entrainement du modèle, les couples d’objets X_train, y_train ou X_test, y_pred peuvent être utilisés.

Paramètre du workspace : automatic log

Lorsque votre méthode de travail se sera arrêtée sur l’une ou l’autre des possibilités, vous pourrez jouer avec le paramètre “automatic log”, disponible à la granularité du workspace.

Si vous envisagez de maximiser la portabilité de vos notebooks (les exécuter sur Azure Machine Learning ou bien Azure Databricks par exemple), il sera sans doute plus judicieux de favoriser l’écriture explicite des commandes MLFlow.

Connecter ChatGPT à Wikipedia

Combien de femmes ont occupé ou occupe le poste de Premier ministre en France ? Posons la question à ChatGPT (version 3.5) sur le site public d’OpenAI.

C’est peut-être la question qui est biaisée, car le nom de la fonction n’est pas féminisé ! Nous pouvons reformuler ainsi, dans une nouvelle session :

Même si ChatGPT “oublie” ici Edith CRESSON, nous notons surtout que ce modèle est entrainé avec sur un dataset allant jusqu’à septembre 2021. Tout événement postérieur lui est donc inconnu. Il est fort peu probable que la société OpenAI se destine à entrainer de manière continue un modèle aussi gigantesque (175 milliards de paramètres !). Nous devons donc trouver une autre manière de “connecter” ChatGPT à l’actualité.

Nous allons nous tourner vers le site Wikipedia dont les pages sont alimentées très rapidement et dont le nombre de contributeurs et modérateurs permet de d’assurer un niveau satisfaisant de véracité.

Au moyen de la fonctionnalité Prompt Flow de Azure Machine Learning, nous allons déployer le démonstrateur “Ask Wikipedia“.

Prompt flow est un outil qui permet d’enchainer différentes tâches (le flow) dont des tâches de prompt et d’appel à un Large Language Model (LLM), mais aussi des scripts Python. Nous avons donc la possibilité de réaliser rapidement un développement qui deviendra par la suite un endpoint HTTPS, au travers d’un déploiement similaire aux modèles traditionnels d’Azure Machine Learning.

Interface de Prompt Flow dans le studio Azure Machine Learning

Un flow débute par une entrée (input) et se termine par une sortie (output). Les entrées et sorties des briques intermédiaires permettent de relier les différentes tâches entre elles. Il est également possible d’ajouter des inputs qui sont en fait des paramètres d’une étape du flow (par exemple des variables de fonctions Python). Nous allons détailler le flow développé ici.

  • input : il s’agit de la question posée. Il serait intéressant de détecter la langue de la question pour adapter ensuite différents éléments (prompt ou URL de recherche)
  • best_intent (élément ajouté par rapport au template généré automatiquement) : la question formulée par l’utilisateur peut ne pas être la forme la plus efficace pour des moteurs de recherche optimisés pour les mots clés ou les expressions. Nous utilisons ici un modèle GPT de type Da Vinci pour reformuler la question et dégager l’intention de l’utilisateur
  • get_wiki_url : liste des URLs données par le moteur de recherche Wikipedia en réponse aux mots clés définis à l’étape précédente
  • search_result_from_url : extraction des premières phrases de chaque page grâce au parser de la librairie Python BeautifulSoup
  • process_search_result : concaténation des résultats précédents en une chaîne de texte, alternant les balises “Content” et “Source”
  • augmented_qna : interrogation d’un LLM à partir d’un system message et des contextes obtenus ci-dessus
Détail de l’étape “best_intent”

Nous allons maintenant réaliser une série de tests pour savoir si le flow est en capacité de trouver la bonne réponse à notre question initiale, à savoir deux femmes : Edith CRESSON et Elisabeth BORNE.

Pour adapter la recherche à notre contexte en langue française, l’URL de recherche de Wikipedia a été rendue dynamique et se construit à l’aide d’un paramètre (input) nommé “culture”.

Optimisation des paramètres du flow

Les paramètres dont nous disposons sont :

  • le nombre d’URLs retenues sur la page de search de Wikipedia (max_urls)
  • le nombre de phrases retenues par page, en commençant par le début de la page (max_sentences)
  • le modèle utilisé pour formuler la réponse à partir des sources (deployment_name) qui conditionne le paramètre suivant
  • le nombre de tokens admis dans le prompt où sont concaténés les phrases extraites des pages (max_tokens)

Test n°1 (valeurs par défaut)

  • count_urls : 2
  • count_sentences : 10
  • deployment_name : GPT-3.5-turbo
  • max_tokens : 8192
"Aucune femme n'a occupé le poste de Premier ministre en France jusqu'à présent."

Mauvaise réponse ! Mais en regardant le détail des phrases relevées par le flow, nous voyons qu’aucune référence à Edith CRESSON ou Elisabeth BORNE n’y figure. Elargissons le périmètre de recherche sur Wikipedia en retentant 10 URLs.

Test n°2

  • count_urls : 10
  • count_sentences : 10
  • deployment_name : GPT-3.5-turbo
  • max_tokens : 8192
"Il y a eu deux femmes qui ont occupé le poste de Premier ministre en France : Édith Cresson de mai 1991 à avril 1992 et Élisabeth Borne depuis mai 2022. SOURCES: https://fr.wikipedia.org/w/index.php?search=Premier+ministre+fran%C3%A7ais"

La réponse est bonne, la source également mais… ce n’est pas l’extrait de cette page qui a permis au LLM de formuler la bonne réponse ! En effet, sur des extraits de 10 phrases, seule la page https://fr.wikipedia.org/w/index.php?search=Élisabeth+Borne donne l’information suffisamment rapidement. Notons ici que le moteur de recherche de Wikipedia a été assez “intelligent” pour aller chercher la page de la Première ministre actuelle, en cinquième lien.

Pour trouver la bonne réponse dans la source citée, nous devons augmenter le nombre de phrases retenues par page.

Test n°3

  • count_urls : 5
  • count_sentences : 200
  • deployment_name : GPT-3.5-turbo
  • max_tokens : 8192
 OpenAI API hits InvalidRequestError: This model's maximum context length is 8192 tokens. However, your messages resulted in 16042 tokens. Please reduce the length of the messages. 

Message d’erreur ! En effet, nous ramenons un contexte trop long par rapport au modèle utilisé. Il faut donc changer de modèle, soit pour un nouveau GPT-3.5-turbo, acceptant 16k tokens, soit pour GPT-4 32k.

Test n°4

  • count_urls : 5
  • count_sentences : 200
  • deployment_name : GPT-4
  • max_tokens : 32768
"Deux femmes ont occupé ou occupent le poste de Premier ministre en France : Édith Cresson en 1991 et Élisabeth Borne en 2022. SOURCES : https://fr.wikipedia.org/w/index.php?search=Femmes+ministres+en+France, https://fr.wikipedia.org/w/index.php?search=Élisabeth+Borne"

Nous obtenons ici les sources correctes pour la réponse. Il faut préciser que le premier lien parle bien du “Gouvernement Elisabeth BORNE” mais le LLM ne semble pas faire le lien avec le rôle de Premier ministre.

En effet, en reformulant la question de la sorte : “En France, combien de femmes ont été cheffe du gouvernement ?”, nous obtenons une réponse correcte. Le lien Wikipedia donne d’ailleurs les différents intitulés de ce poste au cours de l’Histoire.

La plus grande difficulté réside ici dans la récupération des informations pertinentes lorsque le corpus à disposition est volumineux (il faut alors un outil de search efficace) puis lorsque les informations rapportées dépassent le nombre de tokens maximum d’un prompt. Une étape supplémentaire pourrait alors être ajoutée pour résumer les phrases obtenues de chaque page, afin de les fournir au prompt final. Comme il n’existe à ce jour (juillet 2023) pas de logique de boucle dans Prompt Flow, il serait nécessaire d’appeler l’API du service Azure OpenAI directement dans le script Python, en se passant de la connexion définie.

Modèle biaisé ou utilisateur à former ?

En conclusion, on pourrait s’arrêter sur le fait qu’il est possible de trouver la bonne réponse… du moment qu’on la connaît ! Ce serait bien sûr réducteur, cet article vise à montrer la nécessité de disposer de jeux de tests significatifs et de ne pas s’arrêter à la première réponse obtenue, puis de rester critique vis à vis d’informations données par le combo LLM + search. Mais ne sommes-nous pas face aux mêmes limites quand nous nous arrêtons aux premiers liens obtenus dans Google Search ou quand nous ne lisons pas l’entièreté d’un article ?

Maintenant, quelle responsabilité vis à vis du biais de représentation des femmes faut-il accorder aux différentes parties de cette expérience ?

  • ChatGPT, dans sa version 3.5 tout public, ne pouvait avoir connaissance de la nomination d’Elisabeth BORNE, intervenue après sa phase d’entrainement
  • L’article Wikipedia le plus “pertinent” (au sens de l’algorithme de recherche) présente bien la titulaire actuelle dès le début de la page mais dans une zone plus difficile à lire pour les fonctions Python utilisées (voir copie d’écran ci-dessous)
  • L’approche historique de l’article contient les informations récentes en fin de page, à une distance en tokens plus complexe à gérer selon la version du LLM utilisée
https://fr.wikipedia.org/wiki/Premier_ministre_fran%C3%A7ais

Résultats avec le nouveau Bing

Voici le résultat de la question initiale, soumise à Bing, augmenté par le modèle GPT-4. Cette interface fournit également les liens sources de la réponse.

Elisabeth BORNE n’a pas été comptabilisée mais il faut noter que, par défaut, c’est le mode “More Balanced” qui est utilisé.

En se plaçant sur le mode “More Precise“, la bonne réponse est enfin obtenue !

D’ailleurs, le lien Wikipedia fourni ici est identique à celui qui a permis de trouver la bonne information précédemment, à savoir : Femmes ministres en France — Wikipédia (wikipedia.org).

Enfin, les résultats de recherche n’auraient-ils alors pas été meilleurs si le poste de Premier ministre avaient été occupé plus tôt par des femmes au cours des IIIe, IVe et Ve République ?

Pour aller (encore) plus loin

D’autres source que Wikipedia pourraient également être plus efficaces et disposer d’articles répondant plus directement à la question posée.

Premier lien fourni par Google Search

Prompt Flow propose de définir une connection vers le service SerpApi qui réalise des recherches sur Google et d’autres moteurs.

Quant au service Bard de Google, celui-ci fournit la réponse attendue dans chacune de ses suggestions.

Ajoutez vos données à ChatGPT

En décembre 2022, tout le monde ou presque s’est mis à interroger ChatGPT et à tester sa “culture générale” allant jusqu’à… sa date d’entrainement, située à début 2022. Impossible donc de savoir qui avait remporté la Coupe de Monde de la FIFA à l’été 2022 !

Très rapidement, les entreprises se sont projetées sur un cas d’usage professionnel : l’amélioration de la recherche au sein de leur documentation interne. En effet, il existe bien souvent des montagnes de fichiers Word ou PDF, contenant des trésors d’informations, restées inexploitées car les mécanismes de recherche ne pouvaient les atteindre. Et lorsque la recherche est efficace, il est bien utile de disposer d’un bot capable de reformuler, synthétiser, vulgariser ou encore traduire les résultats les plus pertinents.

Le 19 juin 2023, une nouvelle fonctionnalité dédiée à ce scénario est apparue dans Azure OpenAI Service. Voici comment l’utiliser.

Nous allons ici déposer deux fichiers PDF, l’un en anglais, l’autre en français, contenant des procédures informatiques.

Depuis le playground Azure OpenAI, dans le menu Chat (conversation), nous trouvons un nouvel onglet “Add your data (preview)“.

Les aspects de sécurité de vos données et la gestion de la modération de la discussion sont présentés dans la documentation officielle de Microsoft.

Il est important de comprendre que le chargement de ses propres documents n’entraine pas de fine-tuning du modèle. Une revue des couples prompts – completions peut être faite par Microsoft mais il est possible de demander la désactivation de cette revue et donc du stockage temporaire des échanges avec le bot. Voici le formulaire de demande : https://aka.ms/oai/modifiedaccess

Cliquons sur le bouton “Add a datasource”.

Nous disposons de trois sources possibles mais toutes aboutiront à un index Azure Search. Il est en effet possible de sélectionner :

  • un index Azure Cognitive Search déjà réalisé
  • le container d’un Azure Blob Storage
  • l’upload de fichiers locaux dans… un Azure Blob Storage

Cette dernière fonctionnalité sera utile si les utilisateurs n’ont accès qu’au playground du service Azure OpenAI.

Les fichiers du container sont alors indexés en tâche de fond.

Il faut bien comprendre qu’il s’agit ici, pour l’instant, d’un index basé sur les mots clés (keywords) ou bien le semantic search si cette fonctionnalité a été ajoutée dans Azure Cognitive Search. Nous ne parlons donc pas pour l’instant d’embeddings ni de vector search.

La case à cocher “Limit responses to your content” permet de s’assurer que le modèle n’ira pas chercher d’informations complémentaires dont il disposerait déjà, lors de son entrainement initial.

En analysant l’exemple de code proposé dans l’interface, nous ne remarquons rien de particulier : pas de nouvel “engine” (ici GPT 3.5 turbo et la fonctionnalité ne semble pas disponible avec GPT-4), pas de nouvelle méthode (ChatCompletion.create en Python).

Il y a donc un mécanisme sous-jacent qui transmet à l’API les bonnes informations issues du search pour réaliser la réponse du bot. En interrogeant les logs d’Azure Search, nous pouvons retrouver la requête soumise.

Le queryLanguage ne s’adapte pas et reste en “en-us”.

Une rapide vérification des paramètres permet de voir que la température est à 0, afin d’assurer l’aspect déterministe du modèle et donc d’espérer obtenir les mêmes réponses lorsque l’on répète les questions.

Nous allons utiliser le bouton “Deploy to…” pour créer une application web qui portera la fonctionnalité de chat sur les données. Une authentification par Azure Active Directory sera nécessaire.

L’application est maintenant déployée (il sera possible de la mettre en pause, depuis le portail Azure).

EDIT : le code source de cette application est disponible sur ce repo GitHub.

Si la question ne trouve pas réponse dans les documents indexés, le bot ne fournit pas de réponse.

En conclusion, voici les éléments qui limitent encore cet outil et pourraient vous convaincre de réaliser vous-même votre application avec des frameworks comme LangChain ou Semantic Kernel (voir cet article de Kévin BEAUGRAND) :

  • le search sur des vecteurs d’embedding n’est pas encore disponible (mais arrivera prochainement)
  • le search n’intègre pas la langue dans le paramètre de la requête émise par l’application (la recherche multilingue s’avère délicate)
  • il est nécessaire de déplacer tous les documents dans Azure Blob Storage
  • en cas d’évolution du contenu des documents, il faut regénérer complètement les index
  • l’application se conforme au choix du bouton “Limit responses to your content” mais il n’est pas possible de le changer dynamiquement, une fois l’application déployée
  • les documents cités comme sources ne peuvent pas s’afficher dans l’application
  • les citations ne semblent pas toujours pertinentes (voir illustration ci-dessous)
  • EDIT sur discussion avec Nicolas ROBERT : les documents contenant des images devraient passer par un processus d’OCR, par exemple avec Azure Form Recognizer

Notons tout de même qu’il s’agit là d’un accélérateur particulièrement efficace pour démontrer les performances des modèles GPT sur des corpus de documents.

Les annonces Microsoft Build 2023 pour Azure Machine Learning

Entre la déferlante OpenAI et le renouveau de la data platform avec Microsoft Fabric, on pouvait craindre qu’il ne reste que la portion congrue pour Azure Machine Learning. Mais c’est loin d’être le cas ! Faisons un tour sur les différentes annonces qui contribuent à faire d’Azure ML une véritable plateforme pour le Machine Learning en production.

En préversion publique

Rappelons que lors de la phase dite de preview et avant la disponibilité générale (general availability), les services ne sont pas intégrés dans le support proposé par Microsoft. L’utilisateur doit également être conscient que les fonctionnalités, l’interface et bien sûr la tarification peuvent encore évoluer.

Veillez bien à activer les préversions à l’aide du menu dédié “Manage preview features“.

Support for foundation models

L’époque où les Data Scientists développaient leur propre modèle sur leur laptop semblerait presque révolue ! En effet, des modèles Open Source très puissants sont maintenant disponibles au travers de hubs comme Hugging Face qui se place ici en partenariat avec Microsoft. Il devient possible de déployer ces modèles au sein du workspace Azure Machine Learning pour les utiliser sur des tâches d’inférence.

Après déploiement sous forme de managed online endpoint, nous passons donc directement dans le menu des points de terminaison (endpoints) pour retrouver les modèles disponibles.

Certains modèles proposent aussi une interface de test sans déploiement.

Responsible AI dashboard support for text and image data

Nous connaissions déjà le tableau de bord pour une AI responsable, construit autour de briques Open Source sur l’explicabilité et l’interprétabilité des modèles. Je vous recommande d’ailleurs cet excellent article sur son utilisation.

Le tableau de bord s’étend maintenant aux modèles de Computer Vision (images) et de NLP (textes).

Responsible AI image dashboard for object detection (microsoft.com)

Model monitoring

La fonction “Dataset monitors”, toujours en préversion, réalise déjà une détection de dérive sur les nouvelles données qui pourraient être proposées à l’inférence sur un modèle entrainé. Il est important de lever des alertes lorsque la distribution des données d’entrée change et diffère de celle des données d’entrainement. Pour autant, un autre type de dérive est possible : celle du lien entre la variable cible et les variables d’entrée (model drift). C’est ici qu’entre en jeu un nouvel outil, dans un menu dédié “Monitoring“.

Il est possible ici de choisir les différents éléments mis sous contrôle et qui seront visibles dans des tableaux de bord dédiés.

Continuously Monitor the Performance of your AzureML Models in Production – Microsoft Community Hub

Les quatre fonctionnalités incluses sont :

  • Data drift (dérive des données) : détection de changements dans la distribution des données
  • Prediction drift (dérive des prédictions) : changements significatifs dans la distribution des prédictions d’un modèle
  • Data quality (qualité des données) : détection des problèmes de données tels que les valeurs nulles, les violations de plage ou incohérences de type
  • Feature attribution drift (dérive de l’attribution des caractéristiques) : détection des changements d’importance des features dans le modèle

Cette fonctionnalité native, sans intégration d’un composant tiers, est une avancée majeure pour la plateforme et son usage pour supporter les modèles en production.

Microsoft Purview connector

L’outil de data discovery, cataloging et lineage Microsoft Purview s’enrichit d’un connecteur pour Azure Machine Learning. Il sera maintenant possible d’établir le lien entre dataset d’entrainement, modèle, job et prévisions.

Connect to and manage Azure Machine Learning – Microsoft Purview | Microsoft Learn

Le rêve des Data Scientists reste sans doute d’arriver à un niveau de détail du linéage montrant l’impact des features brutes sur les résultats, au travers de l’étape de feature engineering (travail sur les données brutes pour fournir des prédicteurs plus efficaces). Nous nous tournons pour cela vers un autre outil, attendu depuis longtemps dans une version managée : le feature store.

Azure ML managed feature store

Le feature store est une composante indispensable dans une architecture MLOps qui partage plusieurs projets de Machine Learning et surtout des préparations de données communes. Le schéma ci-dessous, issu de la documentation officielle, résume les utilisations potentielles du feature store.

Premier point important : nous sommes à un niveau “supérieur” à celui des workspaces Azure ML (voir la logique des registries présentée ci-dessous) et nous pouvons donc imaginer partager des features et leur préparation entre workspaces ou entre modèles.

Nous remarquons ici l’utilisation du framework de calcul Apache Spark, qui sera sûrement utilisé pour transformer les données brutes en features enrichies.

La matérialisation va permettre de stocker les features dans une ressource de type Blob Storage ou Data Lake Gen2.

Ensuite, nous pourrons définir des feature sets au niveau des modèles. Ceux-ci se définissent par une source, une fonction de transformation et des paramètres de matérialisation optionnels.

Les différentes manipulations seront réalisées au moyen d’un nouveau SDK Python : azureml-featurestore (voir ce premier tutoriel).

Managed network isolation

Si vous vous êtes déjà confrontés à la complexité de déployer Azure ML, ses ressources liés et les services qui doivent communiquer avec, dans un réseau privé, cette nouvelle devrait vous réjouir.

Le réseau virtuel managé va ainsi contenir les compute instances, compute clusters et Spark serverless. Les règles de trafic sortant (outbound) et les points de terminaison privés (private endpoints) seront déjà configurés.

Le déploiement d’un tel workspace ne semble pas disponible au travers du portail Azure, il faudra donc passer par exemple par une commande Azure CLI comme ci-dessous :

az ml workspace create --name ws --resource-group rg --managed-network allow_only_approved_outbound

En disponibilité générale (“GA”)

Azure Machine Learning registries

L’approche MLOps nécessite de travailler avec plusieurs environnements : développement, qualification (ou UAT) et production a minima. Jusqu’ici, nous pouvions hésiter entre créer différents pipelines au sein d’un même workspace Azure ML (environnements non isolés d’un point de vue sécurité) ou bien créer des ressources séparées (difficulté de transfert des livrables entre environnements). Il manquait un niveau de gestion “supérieur” à celui des workspaces Azure Machine Learning.

Les registres permettent de partager entre workspaces des environnements (distribution de l’OS et librairies), des modèles, des jeux de données et des components.

Azure Container for PyTorch

PyTorch est le framework choisi par Microsoft pour le Deep Learning (face à TensorFlow chez Google par exemple). Il est maintenant possible d’utiliser des containers déjà paramétrés pour exécuter ce type de code.

Enabling Deep Learning with Azure Container for PyTorch in Azure Machine Learning – Microsoft Community Hub

Et bientôt en préversion

Il ne vous a pas échappé que le prochain métier en vogue (au moins sur les profils LinkedIn) allait être celui de promptologue ou prompt engineer. A mi-chemin entre le développeur no code et le linguiste, cette personne devra maîtriser les hyperparamètres des modèles génératifs (l’aspect déterministe, dit “température”, par exemple), la méthodologie naissante autour des cycles itératifs et surtout l’art du “langage naturel” pour exprimer clairement une intention.

La lecture de la documentation et les quelques démos visibles nous font penser qu’il s’agira d’un véritable outil de CICD (Continuous Integration Continuous Deployment) pour le prompting ! En effet, nous allons pouvoir :

  • tester, comparer, reproduire des prompts entre eux
  • évaluer les prompts grâce à une galerie d’outils déjà développés
  • déployer les modèles et les messages systèmes dans différents environnements (dev, UAT, prod par exemple)
  • monitorer les modèles en production
https://techcommunity.microsoft.com/t5/ai-machine-learning-blog/harness-the-power-of-large-language-models-with-azure-machine/ba-p/3828459

Il faut noter ici que le prompting semble déjà une discipline très mature chez Microsoft qui a anticipé tous les besoins des futurs prompt engineers.

Les chat bots étant un cas d’usage fréquent des LLM, il est intéressant de retrouver la logique de pipeline visuel, connue depuis les débuts d’Azure Machine Learning.

Et en dehors d’Azure ML

Ajoutons à cela les autres annonces liées à l’intelligence artificielle au sens large :

  • l’essor du service Azure OpenAI, toujours en preview (mai 2023), avec l’ajout des plugins vers des applications tierces et la possibilité d’avoir une capacité dédiée (Provisioned Throughput Model) vous mettant à l’abri des “voisins bruyants”
  • le support de DataRobot 9.0, plateforme concurrente qui pourrait ainsi bénéficier d’Azure pour des scénarios de production en entreprise
  • une base de type “vector DB” ajoutée à Azure Cognitive Search en préversion privée (mai 2023), accessible sur formulaire
  • le nouveau service de modération Azure Content Safety

La partie Content Safety est un nouveau service cognitif, dans la catégorie Decision.

Il s’agit d’un service de modération de contenu pour lequel un studio dédié sera disponible à l’URL suivante : https://contentsafety.cognitive.azure.com et qui sera associé à un SDK documenté ici. Il s’agit d’identifier les contenus, créés par les utilisateurs ou bien par une IA générative, tombant dans les catégories suivantes : hate, sexual, violence, self-harm. Quatre niveaux de sécurité sont alors associés à ces contenus, en fonction du contexte : safe, low, medium, high.

Nous voyons enfin apparaître une nouvelle dénomination : Azure AI Studio.

Nous savons que les noms de produits changent souvent chez Microsoft et souvent, les noms expriment une démarche sous-jacente. Le service Azure OpenAI a été présenté comme un service parmi les autres services cognitifs. Maintenant, les différents studios sont préfixés par “Azure AI |” qui unifiera les différentes offres autour de l’intelligence artificielle.

Maintenant, place à la pratique, et à de prochains billets de blog, pour se faire une véritable idée de l’impact de chacune de ces annonces.

Retrouvez l’ensemble des blogs officiels de Microsoft concernant ces annonces du 23 mai 2023 sur ce lien.

La data de bout en bout avec Microsoft Fabric

Lors de la conférence Build 2023, Microsoft a annoncé la sortie d’un nouveau produit dans le monde de la Data & AI. Si l’on excepte le rebranding de SQL Datawarehouse en Synapse Analytics et la sortie plus confidentielle de Data Explorer, il faut sans doute remonter à 2015 et l’arrivée de Power BI pour assister à un tel chamboulement dans l’offre de la firme de Redmond.

Dans ce premier article dédié à Microsoft Fabric, nous allons revenir sur les architectures cloud dites Modern Data Platform et Lakehouse pour bien comprendre le positionnement du produit. Ensuite, nous verrons en quoi ce nouveau service se différencie de l’existant, que ce soit Azure Synapse Analytics ou Power BI, et à qui il s’adresse.

Voici d’ores et déjà le nouveau logo avec lequel nous allons nous familiariser.

Modern Data Platform

L’architecture Modern Data Platform enchaine quatre étapes fondamentales : ingestion > stockage > calcul > exposition auxquelles peut s’ajouter une étape d’enrichissement grâce à l’intelligence artificielle (services cognitifs, machine learning).

https://learn.microsoft.com/en-us/azure/architecture/example-scenario/dataplate2e/data-platform-end-to-end?tabs=portal

Cette architecture, bien que très complète et performante dans le cloud, par son découpage des tâches, montre une certaine complexité, non pas dans l’utilisation des différents services mais bien dans la communication entre ces services (les fameuses flèches entre les logos !). Une première réponse a été apportée avec le produit Azure Synapse Analytics qui regroupe :

  • l’ingestion de données au travers d’un module similaire à Azure Data Factory
  • le calcul avec les moteurs SQL (dedicated ou serverless) et Spark
  • la gestion des données de streaming avec Data Explorer

Ce ne sont pas des formats propriétaires

Et vous, êtes-vous plutôt tables ou plutôt fichiers ? Il n’est plus nécessaire de choisir depuis l’essor des formats de fichiers orientés colonnes comme Apache Parquet ou Delta (ce dernier étant très fortement soutenu par la société Databricks). Plutôt que de dupliquer le contenu des fichiers dans des tables (avec tous les problèmes que cela implique : gestion des mises à jour, espace de stockage, ressources de calcul différentes…), il est beaucoup plus judicieux de travailler avec la logique d’une metastore qui contiendra uniquement les métadonnées nécessaires et autorisera l’accès aux données en langage SQL.

Microsoft Fabric est donc logiquement bâti autour de l’approche dite lakehouse et c’est même le nom du composant de stockage que l’on pourra déployer dans les espaces de travail (workspaces).

Ce n’est pas (que) Synapse Analytics

Avec Microsoft Fabric, le niveau d’intégration de ces différentes briques est maintenant complet, puisque le produit gère simultanément :

  • le stockage sous le nom de “OneLake” (il faut voir ici une similitude, au moins dans le nom, avec OneDrive)
  • l’ingestion avec toujours Data Factory (ses nombreux connecteurs, ses pipelines visuels)
  • le calcul, toujours avec Spark ou SQL, mais cette fois sans distinction dedicated ou serverless
  • la data science s’appuyant sur Azure Machine Learning
  • le stockage et calcul des données de streaming avec Synapse Data Explorer
  • l’exposition avec le service Power BI
  • l’ordonnancement avec un nouveau composant à venir, nommé Data Activator, que l’on peut rapprocher par exemple du rôle d’un service comme Azure Logic Apps

Un nouveau service Power BI ?

Microsoft Fabric est un produit de type Software as a Service (SaaS). Il n’y a donc pas de client à installer localement, tout se fait au travers d’un navigateur web. Si vous connaissez bien Power BI, vous savez qu’historiquement, deux actions ont longtemps été absentes de l’édition des rapports dans le navigateur : la modélisation et les calculs DAX. Ces opérations sont désormais réalisables dans l’interface en ligne.

Les utilisateurs de Power BI ont également dû longtemps choisir entre rapidité d’affichage (mode import) et donnée fraîche (mode Direct Query). Le mode hybride avec par exemple, la gestion de tables d’agrégats a pu permettre de trouver un compromis mais il fallait un niveau d’expertise assez avancée pour se lancer dans une telle approche. Aujourd’hui, Microsoft Fabric propose le concept de Direct Lake, qui, comme son nom l’indique, propose de travailler sur un mode “Direct Query” sur les sources disponibles dans OneLake.

Malgré l’existence des pipelines de déploiement (licence Premium exigée), l’approche DevOps dans Power BI a toujours été très laborieuse. Nous disposerons, avec Microsoft Fabric, d’un source versioning dans les repositories Azure DevOps (autres gestionnaires à venir sans doute prochainement). Reste à voir en pratique comment se mettra en place le travail collaboratif.

Autre nouveauté sur le plan de la gouvernance et de l’organisation des différents projets : la notion de domain. Les traditionnels groupes de travail (workspaces) peuvent maintenant être assignés à des domaines (sous-entendus fonctionnels), facilitant ainsi la structuration des éléments au sein du tenant.

Qui sont les personae ?

C’est bien toute la famille de la data qui va se réunir au sein de Microsoft Fabric !

Les data engineers vont trouver leur marque dans les menus issus de Synapse Analytics : ingestion de données, pipelines de transformation voire jobs Spark pour les plus codeurs.

Les data scientists manipuleront les environnements, les expériences et les modèles tout comme dans Azure Machine Learning.

Les data analysts connaissent déjà bien l’interface du service Power BI et n’auront plus à basculer du client desktop à l’interface web.

Enfin, les différents modules no code conviendront parfaitement aux “data citizen, qui pourront travailler sur l’ensemble de la chaîne sans avoir à coder.

Dans quelles langues parlons-nous ?

On peut parfois redouter le passage à un nouveau produit car celui-ci implique un temps d’apprentissage en particulier quand il est nécessaire d’appréhender de nouveaux langages. Avec Microsoft Fabric, nous sommes en terrain connu. Voyons cela en détail.

Data engineering (chargement des données)

Il existe quatre modes de chargement de la donnée au sein d’un lakehouse :

  • les dataflow (de génération 2) : no code ou langage M
  • les data pipelines (Data Factory) : no code voire low code si l’on considère les quelques formules qui peuvent être utilisées
  • les notebooks s’exécutant dans un environnement Apache Spark, avec les langages Scala, Python (API pyspark) ou Spark SQL
  • les shortcuts (no code) qui permettent de pointer vers une source déjà présente au sein de OneLake ou bien vers une source externe comme ADLS gen2 ou Amazon S3
Data Warehouse

Ici, et comme depuis un demi-siècle, le langage SQL est roi ! Nous sommes bien évidemment dans la version T-SQL de Microsoft, enrichi par quelques fonctions propres à Synapse Analytics.

Data Science

Nous sommes en terrain connu (et conquis !) pour les scientifiques de données : Scala, Python & R. Pour ces deux derniers, il sera nécessaire d’utiliser les API pyspark et SparkR pour profiter pleinement de la puissance du moteur de calcul distribué.

Streaming

L’intégration du produit Azure Data Explorer s’accompagne bien sûr du langage KustoQL (KQL) pour le chargement et l’interrogation des données.

Modélisation décisionnelles et mesures

Depuis l’arrivée des modèles tabulaires concurrençant les modèles multi-dimensionnels, le langage DAX s’est imposé pour manipuler la couche sémantique de la Business Intelligence. Ici, rien ne change.

OpenAI en copilote ?

Le partenariat entre la société OpenAI et Microsoft s’est renforcé en novembre 2022 et le succès planétaire de ChatGPT a montré tout le potentiels de l’IA générative pour les outils bureautiques (Microsoft Copilot à venir prochainement), comme dans le monde du développement (GitHub Copilot). Microsoft Fabric s’appuie également sur les fundation models tels que GPT ou Codex.

Vous connaissiez la création de visuel en langage naturel depuis plusieurs années dans Power BI ? Voici maintenant la création de rapport ! Le copilot demande une description en quelques mots des attentes en termes de reporting ou d’analyse et la page de rapport se génèrera automatiquement. Tout simplement magique ! Finalement, les spécifications ne sont-elles pas l’étape la plus importante d’un projet de tableau de bord ?

Vous pouvez retrouver plus de détails sur le blog officiel de Power BI.

En attendant la mise en pratique

En conclusion, et avant de passer véritablement aux tests de cette nouvelle plateforme, nous pouvons saluer l’effort de vision de bout en bout de la part de Microsoft, qui vise à fédérer pour les acteurs de la data dans l’entreprise autour d’une même source et d’une gouvernance unifiée.

N’oublions pas non plus le service Azure Databricks qui reste sans doute la plateforme d’entreprise pour les projets Big Data sur Azure, et qui dispose également d’une vision unifiée des usages de la donnée.

De nombreux éléments demandent maintenant à être vérifier dans la pratique :

  • le coût exact du produit à l’usage
  • la capacité à monter à l’échelle avec la volumétrie ou la vélocité requise
  • la collaboration entre les profils data (engineer, analytist, scientist…)
  • la simplicité de gouvernance (data discovery, data catalog, lineage…)
  • la possibilité de travailler dans des environnements multi-tenants
  • … (liste non exhaustive)

Mais que les utilisateurs se rassurent d’ores et déjà : il sera toujours possible d’obtenir les données dans Excel 🙂 !

Structurer une conversation en JSON à l’aide d’un prompt GPT-4

La donnée non structurée est partout autour de nous : texte, image, son, vidéo… rien de cela ne tient dans une base de données SQL ou NOSQL. Les grands modèles de langage comme GPT-4 sont une aubaine pour structurer les corpus de texte, et en particulier les conversations entre plusieurs personnes, desquelles il faudra extraire quelques informations bien structurées.

Nous allons ici tester différents prompts sur le dialogue ci-dessous, tenu dans un contexte bancaire, entre un client, une employée et un banquier. L’objectif principal sera de produire un fichier JSON avec plusieurs informations relatives au client.

L’employée : – Bonjour, que puis-je faire pour vous ?
Le client : – Bonjour Madame, je souhaite ouvrir un compte.
L’employée : – Bien, alors vous devez prendre rendez-vous avec un conseiller clientèle.
Le client : – Et dois-je apporter des papiers ?
L’employée : – Oui, il faut apporter un justificatif de domicile, une facture d’électricité ou de téléphone par exemple.
Le client : – Oui, et c’est tout ?
L’employée : – Non, il faut une pièce d’identité, carte d’identité ou passeport si vous êtes étranger.
Le client : – Bien. Et combien ça coûte ?
L’employée : – À la BG, c’est gratuit et il n’y a pas de somme minimum à verser.
Le client : – C’est parfait ! Est-ce que je peux prendre un rendez-vous maintenant ?
L’employée : – Bien sûr ! Pouvez-vous revenir demain à 15 h 30 ? Le client : – Oui, c’est possible. L’employée : – Très bien. Alors vous avez rendez-vous avec monsieur Didier Desmarais.
Le client : – D’accord, merci et au revoir.
L’employée : – Je vous en prie, au revoir.
Le conseiller : – Bonjour monsieur, je suis Didier Desmarais. Asseyez-vous.
Le client : – Bonjour monsieur, je m’appelle Frank Bayer et je viens pour ouvrir un compte.
Le conseiller : – Bien, alors, tout d’abord est-ce que vous avez les documents nécessaires ?
Le client : – Oui, j’ai tout apporté.
Le conseiller : – Parfait, je les photocopie et ensuite je vous explique tout.
Le conseiller : – Alors, nous allons ouvrir un compte courant pour les opérations de tous les jours, vous pouvez déposer ou retirer des espèces, faire virer votre salaire, verser des chèques ou émettre des chèques, recevoir ou émettre des virements, ou encore effectuer des retraits ou payer par carte. Vous recevrez un relevé de compte (la liste des opérations effectuées sur le compte pour une période déterminée) tous les mois (gratuit) ou tous les 15 jours (service payant).

Cette conversation est issue de ce site dédié à l’apprentissage de la langue française.

Nous débutons par un premier prompt qui vise à expliquer comment se structure le dialogue et quelles sont les informations recherchées.

Tu es un assistant IA qui aide à résumer un dialogue entre plusieurs personnes. Chaque personne sera citée en début de phrase et suivi par le signe :.
Tu produiras un fichier JSON contenant les informations suivantes : nom du client, prénom du client, date du rendez-vous, heure du rendez-vous, nom du conseiller et sous forme imbriquée, les documents fournis puis les services souscrits. Tu pourras ensuite répondre à des questions spécifiques sur la conversation.

Le premier résultat est assez satisfaisant mais il peut être amélioré. La date est donnée à “demain” et n’est donc pas contextualisée. Le modèle GPT-4 n’a pas pas accès à l’information de la date du jour, nous devons la préciser dans le prompt. Ensuite, les services souscrits sont trop détaillés. Nous allons donc fournir dans le prompt un exemple de la structure JSON attendue, en nous inspirant tout simplement de la première itération réalisée.

Tu es un assistant IA qui aide à résumer un dialogue entre plusieurs personnes. Chaque personne sera citée en début de phrase et suivi par le signe :.
Tu produiras un fichier JSON contenant les informations suivantes : nom du client, prénom du client, date du rendez-vous, heure du rendez-vous, nom du conseiller et sous forme imbriquée, les documents fournis puis les services souscrits. Tu pourras ensuite répondre à des questions spécifiques sur la conversation. Le fichier JSON devra être structuré de la sorte :
{
"nom_client": "PETON",
"prenom_client": "Paul",
"date_rendezvous": "2023-01-08",
"heure_rendezvous": "09h30",
"nom_conseiller": "Jérôme KERVIEL",
"documents_fournis": {
"justificatif_domicile": "facture d'électricité",
"piece_identite": "carte d'identité"
},
"services_souscrits": {
"compte_courant"}
}
La date de rendez-vous devra être interprétée en considérant que nous sommes aujourd'hui le 17 mai 2023.

C’est beaucoup mieux ! Nous avons résolu les deux problèmes identifiés.

Il reste une interprétation de la part du modèle quant aux documents fournis. Ceux-ci sont les documents cités par l’employée et nous ne savons pas si le client a fourni une facture d’électricité ou bien de téléphone. Il serait préférable que le modèle ne donne l’information que si celle-ci est réellement fiable.

Nous pouvons compléter le précédent prompt de la sorte :

Les documents fournis devront correspondre à ce que le client déclare et non ce que propose la banque. Si ce n'est pas le client qui donne l'information, indiquer "Ne Sait Pas" dans le fichier JSON.

Modifions légèrement le dialogue pour vérifier la robustesse de ce prompt.

Le client cite explicitement les pièces.
Le conseiller cite explicitement les pièces, sans ambiguïté.

Terminons par une série de questions / réponses sur le dialogue. Ici, le modèle GPT-4 est à son aise.

Cette démarche fonctionne ici très bien car le dialogue tient dans la limite des 32000 tokens autorisés par le modèle GPT-4. Pour des corpus de texte plus long, nous devrons utiliser une autre approche, qui sera détaillée dans de prochains articles sur ce blog.

Comment ChatGPT a résolu les énigmes KustoQL

Ou plus exactement, les modèles de langage GPT peuvent-ils réussir les défis de la Kusto Detective Agency, ce défi lancé par Microsoft en 2022, autour du langage KustoQL (KQL) et des clusters Azure Data Explorer ?

Il s’agit en effet d’un triple défi pour le modèle d’IA : résoudre une énigme en langage naturel et faire le lien avec le modèle de données, puis répondre en langage KQL.

Echauffement avec ChatGPT

La première épreuve consiste à calculer la somme d’une colonne numérique dans une table ne contenant que cette colonne.

Nous allons tout d’abord tester ChatGPT au travers du site de la société OpenAI, dans son accès public. C’est donc le modèle GPT-3.5 qui est utilisé.

Aucun problème pour ce robot ! Nous obtenons la bonne syntaxe et il suffit de la lancer sur le cluster provisionné.

Enigme “The rarest book is missing!

Nous poursuivons avec la première véritable énigme. Il s’agit d’identifier, dans une bibliothèque, l’étagère d’où a disparu le livre “De Revolutionibus Magnis Data”. Pour cela, nous pouvons utiliser des informations sur le poids des livres et le poids total de chaque étagère, à laquelle est rattachée la liste des livres qu’elle contient. Le prompt peut être composé de la sorte :

Here is an enigma 
""" This was supposed to be a great day for Digitown’s National Library Museum and all of Digitown.
The museum has just finished scanning more than 325,000 rare books, so that history lovers around the world can experience the ancient culture and knowledge of the Digitown Explorers.
The great book exhibition was about to re-open, when the museum director noticed that he can't locate the rarest book in the world:
"De Revolutionibus Magnis Data", published 1613, by Gustav Kustov.
The mayor of the Digitown herself, Mrs. Gaia Budskott - has called on our agency to help find the missing artifact.

Luckily, everything is digital in the Digitown library:
- Each book has its parameters recorded: number of pages, weight.
- Each book has RFID sticker attached (RFID: radio-transmitter with ID).
- Each shelve in the Museum sends data: what RFIDs appear on the shelve and also measures actual total weight of books on the shelve.

Unfortunately, the RFID of the "De Revolutionibus Magnis Data" was found on the museum floor - detached and lonely.
Perhaps, you will be able to locate the book on one of the museum shelves and save the day?
"""
Complete the following code to resolve the enigma.
"""
.execute database script <|
// Create table for the books
.create-merge table Books(rf_id:string, book_title:string, publish_date:long, author:string, language:string, number_of_pages:long, weight_gram:long)
// Import data for books
// (Used data is utilzing catalogue from https://github.com/internetarchive/openlibrary )
.ingest into table Books ('https://kustodetectiveagency.blob.core.windows.net/digitown-books/books.csv.gz') with (ignoreFirstRecord=true)
// Create table for the shelves
.create-merge table Shelves (shelf:long, rf_ids:dynamic, total_weight:long) 
// Import data for shelves
.ingest into table Shelves ('https://kustodetectiveagency.blob.core.windows.net/digitown-books/shelves.csv.gz') with (ignoreFirstRecord=true)
"""

ChatGPT se lance alors dans un commentaire de code.

A la fin de la réponse, nous apprenons juste que les données pourraient nous permettre de résoudre l’énigme…

GPT-4 à la rescousse

Nous allons donc utiliser la version suivante du modèle GPT : GPT-4 32k ! Pour cela, nous utiliserons le playground du service Azure OpenAI.

Avec un prompt similaire à celui fourni à ChatGPT, voici la réponse obtenue.

La structure de la réponse est intéressante : le modèle d’AI explique sa démarche, propose un code KQL et ajoute une explication de ce code.

Malheureusement, ce code n’est pas fonctionnel et nous obtenons un message d’erreur.

Essayons tout simplement de copier-coller ce message d’erreur dans le chat.

Le modèle d’IA réagit et corrige son code. Celui-ci est maintenant valide mais ne renvoit pas de ligne, nous n’obtenons donc pas la réponse recherchée. Nous le signifions d’emblée dans la conversation et rappelons l’objectif de la recherche.

Cette fois-ci, le raisonnement semble plus évolué et le code plus structuré. Pour autant, celui-ci n’est toujours pas valide. Nous allons guider le modèle en lui donnant la marche à suivre.

Ca y est ! Nous avons maintenant un code valide et surtout… la bonne réponse !

Même si le résultat est bon, la démarche a pu paraître laborieuse et a nécessité une reformulation assez explicite de l’énigme. Nous allons voir s’il est possible d’être plus efficace en tunant le modèle.

Prompt engineering

Le modèle de conversation peut être amélioré en donnant un message système initial, suivi d’un ou plusieurs exemples (one or few-shot-learning).

Voici le prompt fourni.

You are an AI assistant who helps solve puzzles. The statement of the puzzle will be given after the [ENIGMA] tag. The data available to solve the puzzle is loaded using the Microsoft KustoQL (KQL) language. The loading code will be given after the [KQL] tag. You will detail your reasoning by commenting the KQL code produced.

L’exemple fourni est tout simplement le premier calcul proposé pour obtenir la somme d’une colonne et la réponse obtenue sous ChatGPT.

Voici maintenant la première réponse du modèle d’IA, lors de la soumission du prompt reformulé de la manière suivante :

[ENIGMA]  
This was supposed to be a great day for Digitown’s National Library Museum and all of Digitown.  
The museum has just finished scanning more than 325,000 rare books, so that history lovers around the world can experience the ancient culture and knowledge of the Digitown Explorers.  
The great book exhibition was about to re-open, when the museum director noticed that he can't locate the rarest book in the world:  
"De Revolutionibus Magnis Data", published 1613, by Gustav Kustov.  
The mayor of the Digitown herself, Mrs. Gaia Budskott - has called on our agency to help find the missing artifact.  
&nbsp;  
Luckily, everything is digital in the Digitown library:  
- Each book has its parameters recorded: number of pages, weight.  
- Each book has RFID sticker attached (RFID: radio-transmitter with ID).  
- Each shelve in the Museum sends data: what RFIDs appear on the shelve and also measures actual total weight of books on the shelve.  
&nbsp;  
Unfortunately, the RFID of the "De Revolutionibus Magnis Data" was found on the museum floor - detached and lonely.  
Perhaps, you will be able to locate the book on one of the museum shelves and save the day?  
[KQL]  
.execute database script <|  
// Create table for the books  
.create-merge table Books(rf_id:string, book_title:string, publish_date:long, author:string, language:string, number_of_pages:long, weight_gram:long)  
// Import data for books  
// (Used data is utilzing catalogue from https://github.com/internetarchive/openlibrary )  
.ingest into table Books ('https://kustodetectiveagency.blob.core.windows.net/digitown-books/books.csv.gz') with (ignoreFirstRecord=true)  
// Create table for the shelves  
.create-merge table Shelves (shelf:long, rf_ids:dynamic, total_weight:long)   
// Import data for shelves  
.ingest into table Shelves ('https://kustodetectiveagency.blob.core.windows.net/digitown-books/shelves.csv.gz') with (ignoreFirstRecord=true)  

La logique semble bonne mais aucune ligne ne ressort. En regardant de plus près, la valeur de 10 grammes comme différence de poids semble trop restrictive. Nous pouvons en faire part au bot.

Cette fois-ci, c’est bon ! Le prompt engineering aura donc montré son efficacité.

En conclusion, il manque vraisemblablement une information pour que le modèle GPT-4 donne la bonne réponse du premier coup : une exploration des données qui aurait montré qu’il existe une marge d’erreur entre la somme du poids des livres et le poids total de l’étagère. Les Data Scientists ont donc encore un rôle à jouer mais pour combien de temps ?

Utiliser ChatGPT dans Azure

Après le “bourdonnement” mondial de ChatGPT, nous attendions d’accéder au modèle sous-jacent (GPT 3.5) au travers de la ressource Azure OpenAI. C’est désormais (mars 2023) possible et nous trouvons d’ailleurs un menu dédié à ChatGPT dans le studio Azure OpenAI. Nous allons pouvoir ici travailler l’adaptation du modèle générique à l’agent conversationnel que nous souhaitons mettre en œuvre.

L’interface présente trois panneaux :

  • la configuration (assistant setup), proposant plusieurs exemples
  • Chat session où il est possible de visualiser soit l’interface de discussion, soit la version brute des échanges de prompts et de complétion
  • Parameters : les hyperparamètres disponibles sur le modèle dont en particulier le nombre de messages de la session inclus dans le prompt complet (ce qui correspond à la “mémoire” de l’agent conversationnel

Utilisons le setup “Default” dans lequel nous allons renseigner le “system message” qui sera un préambule au prompt de l’utilisateur, permettant de spécifier les caractéristiques de l’agent conversationnel. Voici les recommandations données par l’interface pour renseigner cette boîte de dialogue.

Give the model instructions about how it should behave and any context it should reference when generating a response. You can describe the assistant’s personality, tell it what it should and shouldn’t answer, and tell it how to format responses. There’s no token limit for this section, but it will be included with every API call, so it counts against the overall token limit.

Nous allons spécifier ici un agent dédié à l’écriture de requêtes SQL.

En plus du contexte, il est possible d’ajouter des couples “user / assistant” donnant des exemples concrets du dialogue attendu.

Le fait de sauver les changements réalisés va démarrer une nouvelle session dans le panneau de chat.

Voici le “pré-prompt” inclus dans le début de la session.

Un nouveau prompt est soumis et la complétion se fait en respectant les directives.

Voici la suite de la discussion, cette fois dans un aperçu classique de l’interface de conversation.

Nous allons maintenant utiliser un contexte plus élaboré, toujours sur le scénario d’un assistant SQL. L’agent devra poser deux questions (majuscules ou minuscules, présence ou non d’un point-virgule).

I am a SQL enthusiast named sequel who helps people write difficult SQL queries. I introduce myself when first saying hello. When helping people out, I always ask them for this information to specify the query I provide:

  1. Do you prefer lowercase or UPPERCASE
  2. Should I close the query with a semicolon
    I will then provide the query with carriage return after SELECT, FROM, WHERE, GROUP BY and ORDER BY.

Voici les premiers échanges avec cet agent.

Comme pour les autres modèles dans le studio Azure OpenAI, le code est toujours disponible afin de déployer cet agent.

Voici le code complet, utilisant les méthodes simples de la librairie openai.

#Note: The openai-python library support for Azure OpenAI is in preview.
import os
import openai
openai.api_type = "azure"
openai.api_base = "https://methopenai.openai.azure.com/"
openai.api_version = "2022-12-01"
openai.api_key = os.getenv("OPENAI_API_KEY")

# defining a function to create the prompt from the system message and the messages
def create_prompt(system_message, messages):
    prompt = system_message
    message_template = "\n<|im_start|>{}\n{}\n<|im_end|>"
    for message in messages:
        prompt += message_template.format(message['sender'], message['text'])
    prompt += "\n<|im_start|>assistant\n"
    return prompt

# defining the system message
system_message_template = "<|im_start|>system\n{}\n<|im_end|>"
system_message = system_message_template.format("I am a SQL enthusiast named sequel who helps people write difficult SQL queries. I introduce myself when first saying hello. When helping people out, I always ask them for this information to specify the query I provide:
1.	Do you prefer lowercase or UPPERCASE
2.	Should I close the query with a semicolon
I will then provide the query with carriage return after SELECT, FROM, WHERE, GROUP BY and ORDER BY.")

# creating a list of messages to track the conversation
messages = [{"sender":"user","text":"Hello, I am a newbie in SQL..."},{"sender":"assistant","text":" Hi there! I'm sequel, a SQL enthusiast. Nice to meet you! How can I help you today?"},{"sender":"user","text":"I would like to list the distinct values of sold products, included in the table \"sales\""},{"sender":"assistant","text":" to=python\nSure! Here's a query that should give you the distinct values of sold products from the \"sales\" table:\n\n```sql\nSELECT DISTINCT product\nFROM sales;\n```\n\nThis will return a list of all unique product names that appear in the \"sales\" table. Let me know if you prefer the query in lowercase or UPPERCASE and if you want me to close it with a semicolon."},{"sender":"user","text":"I prefer lowercase, stop shouting !"},{"sender":"assistant","text":" to=python\nMy apologies! Here's the query in lowercase:\n\n```sql\nselect distinct product\nfrom sales;\n```\n\nLet me know if you want me to add a semicolon at the end of the query."}]
response = openai.Completion.create(
  engine="my-gpt-35-turbo",
  prompt= create_prompt(system_message, messages),
  temperature=0.5,
  max_tokens=800,
  top_p=0.95,
  frequency_penalty=0,
  presence_penalty=0,
  stop=["<|im_end|>"])

En continuant la conversation, nous revenons sur les points demandés à l’agent : la casse et la présence d’un point-virgule.

Grâce à la “mémoire” de la session, nous arrivons à nos fins 🙂

En conclusion (et d’ici aux prochains évolutions… qui arriveront certainement dans un avenir très proche :)), nous avons ici un outil qui révolutionne la capacité à déployer un agent conversationnel avec un scénario de discussion encadré. Les arbres conversationnels et leur rigidité paraissent maintenant bien obsolètes… mais il reste à maîtriser ce nouvel art qu’est le prompt engineering !

La documentation officielle de Microsoft rappelle que :

LUIS will be retired on October 1st 2025 and starting April 1st 2023 you will not be able to create new LUIS resources. 

Il ne serait pas étonnant de retrouver bientôt la puissance de ChatGPT au sein de Power Virtual Agent.