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.

Utiliser l’API Azure OpenAI en Python

Nous avons vu dans un précédent post les possibilités des modèles basés sur GTP au travers du studio et du playground. Ce bac à sable n’est bien sûr destiné qu’à de premiers tests et une utilisation de l’inférence au sein d’une application se fera de manière programmatique, à l’aide de l’API de service disponible. (Il existe également une API dite de gestion pour la création, mise à jour ou suppression de la ressource Azure.)

Mais avant de nous lancer dans le code, nous allons réaliser un premier appel dans l’outil Postman.

Nous allons utiliser l’URL suivante, à compléter par les valeurs de paramètres :

  • YOUR_RESSOURCE_NAME : le nom de la ressource Azure OpenAI provisionnée
  • YOUR_DEPLOYMENT_NAME : le nom du déploiement de modèle (réalisé en amont dans le studio)
  • la version de l’API, exprimée sous forme de date (en février 2023, nous utilisons la version 2022-12-01)
POST https://YOUR_RESOURCE_NAME.openai.azure.com/openai/deployments/YOUR_DEPLOYMENT_NAME/completions?api-version=YYYY-MM-DD

Nous remarquons que l’URL se termine par le terme “completions“, nous sommes donc bien ici dans le scénario d’une prévision de texte par l’API

Il existe deux manières de s’authentifier :

  • clé d’API
  • jeton Azure Active Directory

Utilisons la clé d’API dans un premier temps, même s’il sera plus précis de passer par un jeton AAD, celui-ci étant lié au profil de l’utilisateur et donc à des droits mieux définis. Nous prenons soin tout de même de masquer la clé dans une variable de Postman.

Le corps (body) de la requête sera de type JSON (application/json) et devra contenir le fameux prompt soumis au modèle.

Au texte soumis “Postman is a tool for…“, nous obtenons une complétion “building APIs faster“, en quatre tokens (valeur précisée dans le body par le paramètre max_tokens). Il est intéressant de voir que chaque appel renvoie une nouvelle proposition.

Voici la syntaxe Curl correspondante.

curl --location 'https://methopenai.openai.azure.com/openai/deployments/davinci-summarize/completions?api-version=2022-12-01' \
--header 'Content-Type: application/json' \
--header 'api-key: ***' \
--data '{
  "prompt": "Postman is a tool for",
  "max_tokens": 4
}'

En Python, avec la librarie Request, nous obtenons le code ci-dessous.

import requests
import json

url = "https://methopenai.openai.azure.com/openai/deployments/davinci-summarize/completions?api-version=2022-12-01"

payload = json.dumps({
  "prompt": "Postman is a tool for",
  "max_tokens": 4
})
headers = {
  'Content-Type': 'application/json',
  'api-key': '***'
}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)

Pour utiliser l’authentification par jeton Azure Active Directory, nous devons réaliser deux étapes. Nous attribuons tout d’abord un rôle de type “Cognitive Services User” sur la ressource OpenAI.

Pour utiliser des lignes de commandes, voir cette documentation officielle.

Le token peut être obtenu par cette commande az cli :

az account get-access-token --resource https://cognitiveservices.azure.com | jq -r .accessToken

Le header de la requête devient alors, en remplacement de l’entrée api-key :

'Authorization': 'Bearer ***'

Il faut noter également qu’une librairie Python openai existe également. Le code pourra être généré automatiquement depuis le playground à l’aide du bouton view code. Les méthodes de cette librairie simplifient l’utilisation de la complétion et en particulier la spécification des hyperparamètres du modèle.

Peut-on utiliser ChatGPT pour Power BI ?

En ce début d’année 2023, l’intelligence artificielle est sur toutes les lèvres, avec l’apparition de ChatGPT, déclinaison sous forme d’agent conversationnel du modèle GPT 3.5, élaboré par la société OpenAI.

Il faut garder à l’esprit que ce modèle prédit les prochains mots probables mais son corpus d’entrainement est tel qu’il est possible d’imaginer des usages, en particulier avec les langages de programmation, comme peut le faire l’assistant GitHub Copilot dans Visual Studio Code.

ChatGPT pour le langage DAX

Nous pouvons imaginer deux usages autour du langage dédié aux mesures et aux colonnes calculées.

Faire expliquer une formule DAX complexe

L’exemple suivant est tiré d’une page de l’excellent site SQLBI.

Il faut noter que le modèle a été entrainé avant l’apparition de cette formule dans Power BI mais l’explication reste cohérente, sans doute grâce à la proximité de cette fonction avec sa version Excel.

Faire écrire une formule DAX à partir d’une description

Nous allons ici écrire un prompt avec un maximum d’informations sur le modèle sémantique : noms de tables, noms de champs, valeurs…

Réponse obtenue le 4 février 2023

En re-générant la réponse, suite à l’évolution du modèle, nous obtenons la formule suivante.

Si nous connaissons la famille de fonctions TIME INTELLIGENCE, nous pouvons réorienter la réponse.

Sur ces deux exemples, l’agent conversationnel ChatGPT se montre plutôt performant, et un très bon accompagnateur pour des personnes débutant dans le langage DAX. Toutefois, il faudra se méfier des syntaxes proposées, être critique et s’appuyer sur l’expérience… d’êtres humains, formateur.ices Power BI !

Nous pourrions nous prendre à rêver que les visuels Q&A ou smart narrative soient boostés par ChatGPT et donnent alors des performances très élevées dans l’élaboration de visuels ainsi que dans leur interprétation.

ChatGPT pour le langage M ?

Dans l’interface Power Query, le langage M s’écrit déjà automatiquement grâce aux actions réalisées dans l’interface visuelle. Pour autant, il peut être efficace d’écrire ses propres fonctions qui pourront ensuite être utilisées pour générer de nouvelles colonnes.

Dans l’exemple suivant, nous allons écrire une fonction permettant de remplacer toutes les lettres accentuées par leur équivalent, sans accent. Posons la question de cette fonction à ChatGPT.

Wahou, cela semble très impressionnant ! Essayons tout de suite cette fonction dans Power Query.

Attention, la fonction Text.ReplaceEach() n’existe pas, ce que nous confirmera la documentation officielle ! ChatGPT est un outil créatif, cette fonction est donc une très bonne suggestion pour les équipes de développement du produit !

Nous pouvons faire part de cette erreur à ChatGPT et voir ce qu’il nous propose maintenant.

Essayons cette seconde proposition. Le code est bien validé mais l’appel à la fonction va déclencher une nouvelle erreur.

Mauvaise pioche à nouveau, il semble que l’exercice soit trop difficile, en l’état actuel des performances du modèles ChatGPT.

Une simple recherche sur le Web nous amère assez rapidement à cet échange sur StackOverflow.

Le code de la fonction est donc :

= (textToConvert) =>let
textBinary = Text.ToBinary (textToConvert, 1251),
textASCII = Text.FromBinary(textBinary , TextEncoding.Ascii)
in
textASCII

En conclusion, en ce début d’année 2023, nous pouvons dire que l’association formateur.ice + forum + ChatGPT est une excellente combinaison pour progresser dans la maîtrise des deux principaux langages de Power BI.

Découvrir Azure OpenAI et son studio

Lorsque votre souscription Azure aura été autorisée à déployer le service OpenAI (voir ce précédent article), vous pourrez accéder à l’écran ci-dessous.

Au cours de cet article, nous allons donner un premier aperçu des fonctionnalités disponibles et insister sur les différences entre le service OpenAI directement disponible et son intégration au sein du cloud Microsoft Azure.

Playground de OpenAI (hors Azure)

Afin d’expérimenter les différents modèles, nous allons tout d’abord nous connecter au studio Azure OpenAI sur l’URL https://oai.azure.com/

Studio Azure OpenAI

La page d’accueil fournit de nombreux liens d’exemples et de documentation.

Nous retrouvons le playground de OpenAI et la possibilité d’expérimenter des prompts dans différents scénarios :

  • résumé
  • classification
  • génération de code
  • etc.

Nous ne retrouvons toutefois pas, pour l’instant (février 2023), l’intégralité des exemples proposés dans le playground d’OpenAI.

Déployer un modèle

C’est la première opération à réaliser afin de pouvoir utiliser les différents services : déployer l’un des modèles disponibles. Par défaut, aucun modèle n’est déployé dans le studio.

Il faut tout d’abord sélectionner l’un des modèles de base.

Une description rapide des différents modèles est donnée, afin d’aider à la sélection. Les modèles dédiés au langage naturel, dérivant de GPT-3, sont décrits dans cette partie de la documentation officielle.

Il est alors possible de retourner dans le playground et de sélectionner le déploiement réalisé.

Complétion de texte

C’est ici que l’expérience avec un modèle GPT-3 peut s’avérer déstabilisante. En effet, nous sommes face à un outil destiné à traiter le langage naturel et également à interagir de la sorte. Nous n’avons donc d’un simple prompt pour exprimer notre demande. Attention à l’angoisse de la page blanche !

Le résultat généré est identifié par un surlignage vert. On remarquera l’indicateur du nombre de tokens, correspondant à la longueur du texte contenu dans le prompt.

Le paramètre de température permet de gérer l’aspect stochastique du modèle (comprendre que les prévisions peuvent changer même avec un prompt similaire). Dans l’exemple ci-dessous, le résultat est généré trois fois, avec une température de valeur 1.

Write a original prompt for image generation with DALL-E 2

What would DALL-E draw if you asked it to generate an image of a "perfect day"?

What if DALL-E was asked to generate an image of a world where everyone was happy and there was no conflict?

What if the world was made of candy?

Premiers scénarios d’utilisation

Approprions-nous maintenant le terrain de jeu !

Résumé

On soumet un texte long afin d’obtenir un résumé.

L’intention est ici exprimée par le terme “Tl;dr:” (“trop long; n’a pas lu) mais pourrait être formulée d’une autre façon, par exemple en précisant le public cible.

Les guillemets encadrent ici la partie de texte à résumer.

Classification

Nous donnons tout d’abord l’intention, celle d’établir un classifieur. La dizaine d’exemples ci-dessous est issue d’un jeu de données connu sur le sujet.

Il s’agit bien d’un spam !

Avec si peu de données d’entrainement, le résultat peut paraitre impressionnant mais n’oublions pas qu’il y a une chance sur deux de trouver la bonne réponse (pile ou face) ! Contrairement à un classifieur issu par exemple du framework Scikit-Learn, nous ne pouvons pas accéder à la probabilité d’appartenance à la classe.

Génération

Nous demandons une liste, donnons un exemple puis débutons la suite de la liste par le chiffre 2.

Attention, tous ces produits ne sont pas réellement Open Source !

Parsing de données non structurées

Peut-être l’illustration la plus surprenante, le moteur va réussir à mettre en tableau un texte donné en langage naturel.

Seul le premier exemple a été soumis.

Extraction d’information

A nouveau, nous donnons une description du document qui sera soumis entre guillemets.

Toutefois, en essayant le même prompt dans ChatGPT (basé sur GPT 3.5), nous obtenons une réponse tout à fait correcte !

Code view

Prenons maintenant l’exemple d’un résumé de texte, avec pour objectif d’utiliser cette fonctionnalité en dehors du studio Azure OpenAI.

Le code correspondant à cet appel dans le playground est disponible (en Python).

Ce code utilise la librairie Python openai (à installer avec la commande pip install) et nécessitera de connaître une des clés du service.

Pourquoi ne pas demander au modèle de générer un code Python appelant cette API ? Voici le résultat obtenu.

Nous ne disposons pas ici d’un quota suffisant pour que le code s’écrive en entier. L’utilisation de GitHub Copilot sera plus adaptée dans ce cas de figure.

En résumé (et sans l’aide de GPT-3 !), nous pouvons successivement déployer un modèle, l’expérimenter à l’intérieur du terrain de jeu (playground) puis déployer une application qui s’appuiera sur l’API mise à disposition par Azure OpenAI.

Avantages d’Azure pour OpenAI

Utiliser OpenAI au travers d’Azure donne accès à trois pratiques d’entreprise :

  • la disponibilité régionale
  • la mise en réseau privé
  • le filtrage de contenu d’IA responsable

Une logique d’accès par RBAC (Role Based Access Control) pourra également être mise en place, tout comme l’authentification par identité managée (MSI).

Le portail Azure permet également une gestion des clés d’API par rotation.

Bien sûr, l’utilisation au travers d’Azure engendre une facturation dont les modalités sont détaillées sur cette page. Les coûts seront engendrés par l’inférence (utilisation prédictive) des modèles ainsi que par leur personnalisation (entrainement de type transfer learning).

Cette réponse n’est pas juste ! N’oubliez pas que GPT-3 ne scanne pas le web pour répondre.

Veuillez également prendre en compte les quotas et limites appliquées. Une demande au support permettra de lever certaines de ces limites.

Choix de la région

A ce jour (février 2023), seules trois régions Azure sont disponibles.

L’utilisation de deux régions différentes permet d’assurer une continuité d’activité. Ainsi, si un datacenter vient à être indisponible dans une région, il est possible de basculer (par modification du endpoint) vers une autre région Azure.

Utilisation dans un réseau privé

L’utilisation d’un réseau privé sécurise l’accès au studio Azure OpenAI, qui devra par exemple se faire au travers d’un VPN.

Il est également possible d’enclencher le pare-feu Azure (firewall) et de n’autoriser qu’une liste d’adresses IP à accéder au studio OpenAI.

IA responsable

Outre les engagements pris au travers du formulaire de demande du service, la documentation de Microsoft nous incite à respecter les points suivants lors d’une intégration des services Azure OpenAI :

  • Mettre en œuvre une surveillance humaine significative.
  • Mettre en place des limites techniques strictes sur les entrées et les sorties afin de réduire la probabilité d’une utilisation abusive au-delà de l’objectif prévu de l’application.
  • Tester les applications de manière approfondie afin de détecter et d’atténuer les comportements indésirables.
  • Établir des canaux de feedback.
  • Mettre en œuvre des mesures d’atténuation (bias mitigation) supplémentaires propres à chaque scénario.

A termes (ce n’est pas aujourd’hui le cas), un filtrage de contenu supplémentaire sera mis en place par Microsoft. Celui-ci est décrit dans la documentation. Concrètement, un utilisateur proposant un prompt avec un contenu inapproprié recevra, à l’appel de l’API, un code erreur HTTP 400 et une description “content_filter” dans le corps de la réponse. Une demande au support permet d’activer dès à présent ce filtrage.

EDIT : le filtrage de contenu sera activé le 13 février 2023.

With our latest update we’re providing content filters with significant quality and precision improvements. We have adjusted the system to filter at higher severity levels with each category (Hate and Fairness, Sexual, Violence, Self-harm) and expanded coverage across other languages. 

Once the filters are turned back on, the system will resume blocking harmful prompts and model generations.

email Azure OpenAI Support

S’inscrire au service OpenAI sous Azure

Est-il besoin de présenter la société Open AI dont le modèle GPT3 connaît une renommée planétaire, suite à la mise en service de ChatGPT ?

Au delà du buzz, des exemples humoristiques ou de la recherche des erreurs (souvent dans des cas d’utilisation pour lesquels il n’a pas été entrainé), nous disposons dorénavant d’un accès professionnel aux modèles d’Open AI sous Azure, et ce sous le statut de general availability (GA), c’est-à-dire avec tout le support et garantis de service (SLA) attendus.

Une recherche de “openAI” dans la barre du portail Azure nous donne accès à la création de notre première ressource Azure OpenAI. Il faut remarquer ici que ce service est catégorisé comme un service cognitif, services qui représentent l’intelligence artificielle “appliquée” au sein des services Azure.

Un descriptif du service est donné, citant ses principales fonctionnalités (résumé, génération de contenu ou de code) :

Enable new business solutions with OpenAI’s language generation capabilities powered by GPT-3 models. These models have been pretrained with trillions of words and can easily adapt to your scenario with a few short examples provided at inference. Apply them to numerous scenarios, from summarization to content and code generation.

Azure portal

A ce jour, le modèle GPT est disponible ainsi que CODEX qui s’exprime au travers de GitHub Copilot. La génération d’images grâce au modèle DALL-E est encore en préversion (preview) sous Azure.

Avant de pouvoir réellement accéder à la création du service, un avertissement est donné :

Azure OpenAI Service is currently available to customers via an application process. Request access to Azure OpenAI Service.

Un formulaire sera nécessaire pour obtenir le droit de créer une ressource Azure OpenAI. Au bout d’un délai de quelques jours, vous serez informés de l’approbation ou du rejet de votre demande. Nous allons ici détailler quelques-unes des 35 questions posées afin de bien comprendre les cas d’usage autorisés et les garde-fous posés par Microsoft.


Description des cas d’usage

Please explain how you will use Azure OpenAI Service in your application.

  • Please explain the data you will use,
  • how you plan to use the models,
  • how people will consume or interact with the outputs,
  • and more details about the domain or industry in which you will use the application.

PLEASE PROVIDE AT LEAST 5+ SENTENCES. IF YOUR USE CASE IS TOO SHORT OR TOO VAGUE, YOU WILL BE DENIED.

Il s’agit tout d’abord de décrire l’usage qui sera fait du service Azure OpenAI, sur un principe de “bout en bout” : données en entrée, modèle(s) utilisé(s) et interactions avec l’utilisateur. Le cas d’usage doit être suffisamment détaillé et il convient de préciser le domaine ou le secteur d’activités concerné, même si ce dernier point fera l’objet de la question suivante.

Ce paragraphe est particulièrement important et vous devez démontrer qu’une réflexion a déjà été élaborée autour de l’application que vous souhaitez développer. Lorsque vous achetez des outils dans un magasin de bricolage, vous avez sans doute déjà une idée de ce pour quoi vous allez les utiliser !

Domaine(s) d’utilisation

Applications in these domains may require additional mitigations and will be approved only if the customer demonstrates that the risks associated with the application are well-managed and outweighed by the beneficial uses.

Le terme à retenir ici est celui de mitigation (atténuation) que l’on emploie dans l’expression “bias mitigation” pour éviter la correction des biais possibles d’un modèle d’apprentissage. Outre la détection des biais, des actions devront être entreprises pour éviter l’effet néfaste qu’ils pourraient avoir sur les utilisateurs. Des librairies spécifiques existent pour cela comme le produit Open Source FairLearn, développé par Microsoft.

Les différents domaines “à risque” ou dits encore “à enjeux élevés” sont :

  • Law enforcement, legal, and criminal justice
  • Healthcare and medicine Government and civil services, such as essential private and public services Politics
  • Financial services and banking Social media
  • Management and operation of critical infrastructure
  • Pollution and emission management and control
  • Migration, asylum, and border control management
  • Education, vocational training, hiring, and employment, such as applications in consequential decision making that impacts one’s opportunities
  • Therapy, wellness, relationship coaching or forecasting, such as relationship advice or bots for companionship, emotional support, or romance
  • Military or intelligence
  • Other scenario that could have a consequential impact on legal position, life opportunities, or result in physical or psychological injury to an individual if misused
  • None of the above. The domain, industry, or scenario do not have the potential to have a consequential impact on legal position, life opportunities, or result in physical or psychological injury to an individual if misused

Il conviendra de cocher “None of the above” si aucun de ces domaines n’est concerné.

Fonctionnalités attendues

Il serait tentant de tout cocher dans cette question 26 ! En effet, vous avez sûrement beaucoup d’idées d’utilisation des services d’OpenAI mais il faut ici se limiter à ceux qui seront réellement utiles à votre cas d’usage décrit ci-dessus. Il est peu probable qu’un agent conversationnel (chatbot), dans un scénario d’entreprise, propose des images générées par DALL-E ! Soyez donc raisonnables sur les fonctionnalités demandées et si besoin, remplissez plusieurs formulaires, en isolant les applications.

Fonctionnalités spécifiques de l’agent conversationnel

Si vous avez coché la case “Conversational AI” à la question 26, vous devez préciser les fonctionnalités attendues pour l’agent conversationnel.

Attention à nouveau si vous prévoyez de déployer ce bot dans un domaine “à enjeux élevés”.

Acceptation des conditions d’utilisation

Enfin, il sera nécessaire d’approuver explicitement les conditions d’utilisation (“Yes, I agree“) énoncées dans les questions 29 à 35. C’est tout particulièrement sur l’usage en production que vous allez devoir vous engager.

Question 29

29. I understand that mitigations should be considered early in development and must be implemented prior to production.

N’attendez pas d’être en production pour atténuer les biais !

Question 30

30.My application will ensure human oversight prior to production.

This includes never automatically posting generated outputs and never automatically executing generated code. This may also include clearly disclosing AI’s role, communicating relevant limitations to stakeholders (including developers and end users), making sure people (e.g., end users) have a role in decision-making, highlighting inaccuracies in generated outputs, and letting people edit generated outputs.

Ce point nous alerte sur des chaines de CI/CD trop automatisées : un contrôle humain est nécessaire. (Si vous me connaissez bien, vous m’avez déjà entendu pester contre le Continuous Training :))

Question 31

31.My application will implement strong technical limits on inputs from end users and outputs from the system prior to production.

This increases the likelihood your application will perform as expected and decreases the likelihood it can be misused beyond its intended purpose. This may include limiting the length of inputs and outputs, exposing the service to end users through a front end, requiring that inputs and outputs follow a specific structure, returning outputs only from validated source materials, implementing blocklists or content filtering, and implementing rate limits.

En production, un contrôle fort sur les entrées et les sorties sera essentiel. Il s’agit par exemple d’éviter tout détournement de l’usage intial prévu. Ainsi, au démarrage de ChatGPT, il était possible de contourner certaines de ses limites en lui demandant de jouer un rôle.

Question 32

32.I will test my application thoroughly prior to production to ensure it responds in a way that is fit for the application’s purpose.

This includes conducting adversarial testing where trusted testers attempt to find system failures, undesirable behaviors such as producing offensive content, and ways that application can be misused by malicious actors beyond its intended purpose.

Non, tester n’est pas douter ! Ici, il s’agira même d’essayer de “hacker” votre propre application.

Question 33

33.My application will establish feedback channels for users and impacted groups prior to production.

This includes providing ways to report problematic content and misuse such as building feedback features into the user experience and providing an easy to remember email address for feedback submission. 

A minima, votre application devra donner un contact simple, par exemple par email, aux utilisateurs qui souhaiteraient faire part de leur réaction. Au mieux, vous pourrez penser une vraie boucle de feedback (human feedback loop), qui vous servira à termes à améliorer le modèle et l’expérience utilisateur.

Question 34

34.My application will follow the Microsoft guidelines for responsible development of conversational AI systems prior to production.

Prenez connaissance des principes pour une IA responsable, donnés par Microsoft.

Question 35

35.I will resubmit this form for a production review before going into production.

Avant le passage en production, et surtout si des changements sont apparus par rapport à l’expression du cas d’usage intial, il sera nécessaire de soumettre à nouveau le formulaire.

Maintenant que vous connaissez les conditions à remplir, vous voilà prêts à décider si l’expérience Azure OpenAI est une opportunité pour vous et votre organisation !

Exploiter le pool Spark d’Azure Synapse Analytics

Nous avons vu dans cet article d’introduction la dualité de Synapse Analytics entre SQL et Spark. Nous développons ici les aspects liés à Apache Spark, framework Open Source de calcul distribué, et recommandé pour le traitement de la Big Data (volume mais aussi vélocité et variété).

Apache Spark pool

L’exploration des données dans un notebook va requérir l’utilisation d’un pool Apache Spark pour exécuter les commandes, comme l’annonce le message d’alerte ci-dessous.

Please select a Spark pool to attach before running cell!

Nous naviguons dans le menu Manage pour créer un nouveau pool ou retrouver les pools existants.

Un pool correspond à un cluster (grappe) de plusieurs nodes (nœuds) pour lequel nous définissons le nombre de nœuds et leur “taille” (size) correspondant aux propriétés RAM, CPU des machines virtuelles.

La facturation de ce service dépend bien évidemment de ces deux paramètres, qui pourront être modifiés une fois le pool créé.

Je vous recommande de n’activer que l’autoscaling que si les charges de travail sont très variables, dans un sens comme dans l’autre. Débutez sur un petit nombre de nœuds que vous augmenterez au fur et à mesure, en vous assurant que le code écrit est bien en capacité de se distribuer sur les différents nœuds.

Dans le paramétrage additionnel, nous allons trouver la version principale du framework Spark et les différentes versions des langages associés.

Sur cette boîte de dialogues, nous retrouvons aussi la configuration de pause automatique, enclenchée par défaut et paramétrée pour un arrêt au bout d’une inactivité (aucun job en exécution) de 15 minutes.

Langages disponibles

Dans le notebook, nous pourrons utiliser plusieurs langages.

Il est même possible de changer de langage selon les cellules du notebook, à l’aide des commandes magiques comme %%sql, %%csharp, etc. mais cela ne doit pas être une pratique à pérenniser dans le cadre de travaux de production.

Au lancement de la première commande Spark, une nouvelle session débute et cela peut prendre quelques minutes.

La librairie mssparkutils

Un des premiers besoins va être de communiquer avec les services du workspace comme les bases SQL et les systèmes de fichiers de type data lake. Pour accéder à des services liés comme un data lake, nous allons nous appuyer sur une librairie pré-installée : mssparkutils pour Microsoft Spark Utilities. La documentation officielle est disponible sur ce lien. Cet outil est très proche de dbutils de Databricks.

Nous allons nous concentrer en particulier sur les commandes liées au file system (fs) : list, copy, move, rm, put…

Nous commençons par “monter” le data lake par défaut afin d’accéder aux fichiers. Nous utilisons pour cela le modèle de code ci-dessous.

mssparkutils.fs.mount( 
    "abfss://<containername>@<accountname>.dfs.core.windows.net", 
    "</mountname>", 
    {"linkedService":<linkedServiceName>} 
)

A noter que le nom attribué au point de montage doit débuter par un caractère /.

La commande mounts() permet de vérifier les points de montage existants et si besoin, unmount(<mountname>) s’utiliserait pour “démonter” ce point.

Attention, si nous utilisons la syntaxe seule du point de montage pour faire une lecture, nous obtenons une erreur de type PathNotFound. En effet, une première différence apparait ici pour les utilisateurs habitués au dbutils de Databricks.

Nous devons constituer un chemin débutant par le mot clé synfs, suivant de l’identifiant du job, qui se trouve être une variable d’environnement.

Prenez soin de variabiliser ces éléments car le job id changera à chaque démarrage d’une nouvelle session !

Les points de montage ne sont malheureusement pas pérennes ! A chaque nouvelle session, il sera nécessaire de relance la commande mount.

Le résultat de la commande fs est une liste et les différentes propriétés des fichiers peuvent être isolées par du code :

for file in files:
    print(file.name, file.isDir, file.isFile, file.path, file.size)

Les commandes Python de la librairie os peuvent également utiliser ce point de montage. Attention, la syntaxe du path change légèrement avec la disparition du symbole : et l’ajout d’un / avant synfs.

Réalisons maintenant quelques tâches courantes.

Lister et compter tous les fichiers des sous-répertoires

Une simple recherche Google nous montre que la première problématique avec cette librairie mssparkutils est la recherche récursive dans les répertoires !

Heureusement, la recherche nous amène rapidement à découvrir cet excellent repository GitHub : Recursively listing Data Lake files with `display` implemented · GitHub (donnez-lui une étoile :)).

L’exécution imbriquée des deux fonctions deep_ls et convertfiles2df permet d’obtenir un dataframe Pandas avec la liste des fichiers, leur path et la taille en octets.

Nous affichons une synthèse à l’aide du print ci-dessous.

print(f"{df.shape[0]} files for a total size of {df['size'].sum()} bytes")
Afficher les premières lignes d’un fichier .csv ou .parquet

La commande mssparkutils.fs.head() répond à ce besoin.

Toutefois, il est difficile d’interpréter les sauts de ligne et de faire par exemple la différence entre les noms de colonne et les valeurs.

Nous allons nous faire aider ici par la génération automatique de syntaxe, en clic droit sur un nom de fichier ou de dossier.

Nous savons que la première ligne constitue les entêtes du fichier.

La commande df.printSchema() va nous montrer les types de colonnes. Venant d’un fichier .csv, il n’est pas étonnant de ne retrouver que des chaines de caractères (string).

En appliquant l’option inferSchema = True, nous pouvons demander au moteur de déterminer le type le plus probable de chaque colonne.

Il est important de rappeler que le format de fichier .parquet conserve les types de colonnes, nous privilégierons donc ce format pour le stockage de données dite “raffinées”.

Utiliser des packages supplémentaires

Les packages disponibles par défaut ne sont généralement pas suffisants pour traiter tous les aspects d’un projet de Data Engineering ou de Data Science. Nous allons donc charger de nouvelles librairies au moyen d’un fichier local requirements.txt.

Le fichier liste tout simplement les packages, avec, idéalement, leur numéro de version.

great-expectations==0.15.44
xgboost==1.7.3

Par défaut, l’installation de packages pour une session n’est pas activée.

Difficile de réaliser une vérification de l’installation autrement qu’en réalisant une commande d’import du package voulu.

Convertir le contenu d’une table SQL en un dataframe

Nous pouvons établir une connexion JDBC à toute base de données mais ici, nous allons de nouveau profiter, pour un scénario en lecture seule, générer le code Spark dans un notebook.

La méthode spark.read.synapsesql() est mise à profit pour créer un Spark Dataframe en mémoire. Attention, il s’agit d’une commande Scala.

Cette ressource de formation donne également un exemple d’écriture d’un dataframe vers la base de données.

Pour utiliser au mieux Spark et l’API pyspark, je vous recommande la certification Apache Spark developer associate, décrite dans cet article.

Voici un schéma récapitulatif des commandes disponibles avec la librairie MSSparkUtilities.

Découvrir toutes les fonctionnalités d’Azure Synapse Analytics

Azure Synapse Analytics (ASA) a remplacé depuis quelques temps Azure SQL Data Warehouse. Mais au delà d’une base SQL de type MPP (“massive parallel processing“), nous avons maintenant accès à des fonctionnalités offrant une vision “bout en bout” des projets data.

Une fois la ressource Azure provisionnée, nous pouvons lancer le Synapse Studio, dans une fenêtre de navigateur Web.

Le studio présente un menu latéral qui permettra de naviguer entre les différents outils composant Azure Synapse Analytics.

Dans ce premier article introductif, nous allons nous focaliser sur les trois menus Data, Integrate et Develop. Nous traiterons par la suite les aspects de Management et de Monitoring. Nous terminerons cette série sur les bonnes pratiques collaboratives : versioning et intégration / déploiement continus.

Data: le stockage

Si les bases de données (BDD) sont présentes dans notre quotidien depuis plusieurs décennies, le Data Lake (qui reste fondamentalement un système de fichiers…) reste plus récent mais est porté par la dynamique autour des formats de fichiers optimisés pour l’analytique (Parquet, Delta, Iceberg…) et autorisant les transactions (insert, update, delete), opérations qui restaient jusque-là la prérogative des BDD.

Ces deux approches vont se retrouver au sein des services internes à ASA ou en lien (“linked“).

Workspace

De manière “intégrée” dans l’espace de travail (workspace) Synapse, nous retrouvons les bases de données SQL MPP (ex SQL DWH).

Tous les objets classiques d’une BDD sont disponibles (tables, vues, procédures stockées…) et nous ferons un focus sur la notion de tables externes.

La ressource SQL dite “dédiée” apparaît également dans le groupe de ressources Azure. C’est une ressource dont la performance et l’espace de stockage disponible dépendront du niveau choisi (entre DW100c et DW30000c) et qui pourra être arrêtée ou démarrée. Sa facturation sera fonction de ces éléments.

Les tables externes : un fichier “vu” en SQL

Grâce aux tables externes, nous allons pouvoir interroger un système de fichier (Blob Storage, Data Lake) à l’aide d’instructions SQL. Le langage SQL étant si répandu dans le monde professionnel de la data, il s’agit là d’une fonctionnalité particulièrement intéressante.

Création d’une table externe (script automatiquement généré)

Un article dédié sera nécessaire pour décrire les cas d’usage des tables externes, différencier tables externes et vues, ainsi que noter les différences entre les deux pools SQL (dédié et serverless).

La nouveauté (2022) : le lake database

Nous avons vu qu’il est désormais facile d’interroger un fichier comme si l’on utilisait une table (plutôt une vue non matérialisée) d’une base de données. Une difficulté va tout de même se présenter lorsqu’il s’agira de bien appréhender le dictionnaire des données (tous les champs disponibles, associés à leur type respectif) ainsi que les relations entre les différents fichiers (au sens des cardinalités : un à plusieurs, plusieurs à plusieurs, etc.).

Le Lake Database vient proposer une solution à cette problématique, en proposant de mieux visualiser toutes les métadonnées, tout en conservant un stockage de type fichier. De manière sous-jacente, ce sont les ressources SQL Pool serverless ou Spark Pool qui seront utilisées.

Nous créons pour cela une base de type lake, en définissant le container de stockage des données (input folder) ainsi que le format à utiliser (.csv ou .parquet, Delta à venir).

Nous pouvons maintenant utiliser l’interface visuelle pour définir des tables:

  • personnalisées (custom), c’est-à-dire en renseignant chaque champ manuellement
  • depuis des modèles (template) proposés
  • depuis des fichiers du Data Lake

Visitons la galerie de modèles, ceux-ci couvrent de nombreux domaines fonctionnels.

Par domaine, nous disposons d’un grand nombre de schémas de tables, pour lesquelles les clés primaires et étrangères sont déjà déterminées. Nous obtenons donc déjà des relations dans le modèle en cours de création.

Les tables (vides pour l’instant) sont maintenant visibles dans le menu latéral de navigation.

Il sera alors nécessaire de remplir les tables, soit par des instructions SQL INSERT, soit au moyen de l’outil de mapping présenté dans la documentation officielle.

Un bon cas d’usage consiste à mapper les champs du Dataverse utilisé par les produits de la Power Platform. En effet, nous découvrirons ci-dessous la fonctionnalité Synapse Link qui permettra une synchronisation des données en quasi temps réel.

Linked

Les ressources liées sont par définition extérieures à la ressource Synapse Analytics. On utilisera ici principalement un ou plusieurs Data Lake Azure (de génération 2 uniquement) dont les différents file systems seront visibles.

Les notions bronze, silver et god correspondent à l’approche dite “medallion”.

La liste des services externes est présentée ci-dessous.

Il n’est étonnant de retrouver le stockage Blob car le Data Lake de génération 2 n’est autre qu’un Blob Storage augmenté par un “hierarchical namespace“. Nous retrouvons également deux APIs de la base Cosmos DB : l’API native pour le NoSQL et l’API pour MongoDB. Nous écartons donc les APIs PostgreSQL, Cassandra ou Gremlin.

Les integration datasets listeront toutes les sources ou destinations (sink) des pipelines de données qui seront abordés dans le prochain paragraphe. Ainsi, pour une source de type file system, nous disposerons des formats de fichiers suivants:

Integrate : les pipelines “no code”

L’intégration de données consiste à faire entrer dans un environnement de destination des données issues d’une ou plusieurs sources, et ce, à des intervalles de temps réguliers ou sur la détection d’événements (par l’exemple, l’arrivée de fichiers dans un data lake déclenche leur intégration en base de données).

Pipeline

Nous voici dans un univers bien connu des utilisateur.ices d’Azure Data Factory, même si la parité des fonctions n’est pas encore totalement établie (janvier 2023).

Un pipeline est composé d’une ou plusieurs activités, s’exécutant en parallèle ou bien s’enchaînant selon des règles définies.

L’activité de base est la copie de données (copy data) et nous retrouvons également trois activités permettant d’ordonnancer d’autres éléments propres à ASA : les jobs Spark et les procédures stockées SQL.

Synapse Link Connection

Azure Synapse Link est un outil permettant un transfert rapide de données vers une base SQL dédiée (SQL dedicated pool) depuis des sources comme :

  • Azure SQL DB
  • SQL Server 2022 (on premises)
  • Azure Cosmos DB (APIs NoSQL, Cosmos DB & Gremlin)
  • Dataverse

L’objectif est ici de réaliser, “near real time“, des travaux analytiques depuis les données enregistrées dans des bases dont l’usage est plutôt transactionnel. Il n’est plus nécessaire ici de déployer des pipelines ou jobs d’intégration.

Copy Data Tool

Il s’agit sans doute de la manière la plus simple pour copier des données d’une source à une destination (sink).

Ici, il n’est pas envisageable d’ajouter des transformations plus poussées lors de la copie. Nous retrouvons toutefois les propriétés de déclenchement :

  • unique
  • planifié
  • sur des fenêtres glissantes (tumbling windows)

Develop : l’approche “full code”

Les différents scripts compatibles avec les éléments de ASA sont présentés ci-dessous.

Les data flows pourraient sembler être un intrus dans cette liste car c’est bien une interface de type “no code” qui va permettre de les développer. La justification tient sans doute dans le fait que les data flows sont convertis en langage Spark lors de leur exécution.

De même, les jobs Apache Spark fonctionnent à partir de fichiers .JAR qui ne seront pas développés directement dans le studio ASA.

Les scripts SQL travaillent sur les bases de données de type SQL Pools (serverless ou dedicated).

Les scripts KQL (KustoQL) travaillent uniquement sur les bases de données Azure Data Explorer.

Les notebooks s’exécutent grâce à un Pool Spark et peuvent interagir avec les données, qu’elles soient sous forme de fichiers ou intégrées dans les bases de données de type SQL (et non KQL), à l’aide d’un connecteur JDBC.

Nous devons tout d’abord instancier un pool Apache Spark, tout comme nous avons dû créer un pool SQL dédié. Seul le pool SQL serverless est présent par défaut dans le workspace ASA.

Le pool est une grappe (cluster) de plusieurs machines virtuelles (nodes), puisque Spark est un framework distribué.

La version de Spark est modifiable, elle conditionne les versions des langages sous-jacents (Python, Scala, Java, .NET, R…)

La propriété “automatic pausing” est intéressante afin de réduire les coûts d’utilisation mais nous verrons, dans un prochain article, qu’elle implique une gestion fine des sessions Spark.

Premier exemple “de bout en bout”

Prenons l’exemple d’un fichier .csv “brut” qui a été uploadé dans le container Bronze du Data Lake.

Notre premier objectif sera de stoker le fichier dans un format optimisé comme Parquet dans le container Silver. Nous avons pour cela plusieurs possibilités.

Lire avec OPENROWSET

Un clic droit sur un fichier ou un répertoire propose les options suivantes.

Voici le code automatiquement généré par un “Select TOP 100 rows”.

Il est nécessaire d’ajouter l’option HEADER_ROW = TRUE afin de considérer la première ligne du fichier comme l’en-tête. Les autres bulk options sont données dans cette documentation officielle.

Pipeline de copie de CSV vers Parquet

Il s’agit ici de réaliser une copie conforme de la source mais nous allons utiliser pour cela l’outil “copy data tool” car l’objectif est de changer de format de fichier. Nous définissons donc une activité de copie dans un pipeline de type Azure Data Factory.

Le mapping permet de définir le type de données contenues dans chaque champ. C’est en effet une propriété des fichiers .parquet que de pouvoir stocker cette information.

Pipeline de copie du fichier Parquet dans une table

Posons l’objectif de matérialiser les données au sein de la BDD. Nous allons donc utiliser le pool SQL dédié. En effet, dans sa version serverless, nous ne faisons que créer des métadonnées facilitant l’interprétation des fichiers comme des vues.

Nous faisons de nouveau appel à une activité de copie dans un pipeline de type Azure Data Factory. Nous allons laisser le soin à l’activité de copie de créer directement le schéma de table attendu. Pour cela, nous choisissons le mode “Bulk insert” et l’option “Auto create table”.

Nous pouvons maintenant visualiser la table de destination dans le pool dédié et l’interroger au moyen du langage SQL.

En guise de conclusion, et avant de rentrer plus en détails dans certains aspects de cette ressource Azure, nous avons montré ici la polyvalence de l’outil pour les scénarios analytiques :

  • à partir de fichiers de données ou de tables contenues dans une base de données
  • avec la simplicité de la syntaxe SQL directement sur le contenu des fichiers
  • dans une démarche no code ou full code, selon les compétences des utilisateurs.