Version 2026-05
Licence CC–BY–NC–ND
JUPYTER-AI
Christophe Schlick
schlick ಄ u-bordeaux • fr
Pour pouvoir bénéficier efficacement de la récente amélioration de performance de la version gratuite de Gemini, fournie par Google via AIStudio, une extension appelée Jupyter-AI a été installée sur les deux environnements Jupyter du CREMI (autrement dit JupyterLab lors d'une connexion locale depuis un poste du CREMI et JupyterHub lors d'une connexion réseau depuis votre poste personnel). La combinaison de cette extension et d'une clé API personnelle, permet d'utiliser le moteur IAG Gemini-3.1-Flash-Lite directement dans les notebooks Jupyter, sans être obligé de faire des allers-retours incessants dans votre navigateur, entre un onglet Jupyter et un onglet sur un site de chatbot IAG. Les limites de ce modèle gratuit sont largement au-dessus de ce qui est nécessaire dans le cadre d'une aide à la programmation pour un étudiant en Master Sciences des Données :
- Limite de requêtes par minute (RPM) : 15
- Limite de requêtes par jour (RPD) : 500
- Limite de tokens par minute (TPM) : 250 000
- Limite de tokens pour le contexte actif : 1 000 000
L'objectif de ce chapitre est d'expliquer la démarche à effectuer pour configurer cet environnement, puis de fournir quelques exemples d'utilisation du moteur pour la création de données, la rédaction de documentation ou la génération, l'explication et la complétion de code.
import os, warnings; warnings.filterwarnings('ignore') # suppression des 'warning' de l'interpréteur
from SRC.tools import show, load, save # import fonctions utilitaires du module 'tools'
A - Installation de l'environnement
1 - Windows¶
- Télécharger Python 3.12.x depuis le site officiel
- Pendant l'installation, cocher la case Add python.exe to PATH
- Lancer une fenêtre de commandes
cmdoupowershell - Exécuter les commandes suivantes dans la fenêtre de commande :
python -m pip install numpy pandas matplotlib seaborn ipykernelpython -m pip install "jupyterlab>=4,<5" "jupyter-ai>=2,<3" "jupyter-ai-magics>=2,<3"python -m pip install langchain-google-genai
- Lancer l'environnement JupyterLab avec la commande
jupyter lab
2 - MacOS¶
- Télécharger Python 3.12.x depuis le site officiel Python.
- Lancer une fenêtre de commandes
Terminal - Exécuter les commandes suivantes dans la fenêtre de commande :
python -m pip install numpy pandas matplotlib seaborn ipykernelpython -m pip install "jupyterlab>=4,<5" "jupyter-ai>=2,<3" "jupyter-ai-magics>=2,<3"python -m pip install langchain-google-genai
- Lancer l'environnement JupyterLab avec la commande
jupyter lab
3 - Linux¶
- Lancer une fenêtre de commandes
Terminal - Exécuter les commandes suivantes dans la fenêtre de commande :
sudo apt install -y python3 python3-venv python3-pip build-essentialpython -m pip install numpy pandas matplotlib seaborn ipykernelpython -m pip install "jupyterlab>=4,<5" "jupyter-ai>=2,<3" "jupyter-ai-magics>=2,<3"python -m pip install langchain-google-genai
- Lancer l'environnement JupyterLab avec la commande
jupyter lab
B - Configuration de Jupyter-AI
1 - Téléchargement du fichier "ai.py"¶
- Exécuter la cellule de code ci-dessous pour récupérer le fichier
ai.pyet le stocker dans votre dossierSRC:
remote, local = 'https://www.labri.fr/perso/schlick/outinfo/SRC/ai.py', 'ai.py'
if not os.path.exists(local): save(local, load(remote, '')) # fetch remote config file
print(f"File '{local}' has been created")
File 'ai.py' has been created
2 - Création d'une clé AIStudio personnelle¶
Cliquer sur le lien suivant pour accéder à la page de création des clés API sur le site de AIStudio
A la première utilisation de AIStudio, il faut se connecter avec son compte Google et accepter les conditions générales (cf. zone gauche de la figure ci-dessous)
Sur la page principale, cliquer sur le bouton Créer une clé API (cf. zone droite, partie supérieure)
Dans le popup qui s'affiche, choisir un nom pour la clé et un nom pour le projet associé avant de cliquer sur le bouton Créer une clé (cf. zone droite, partie centrale)
Une nouvelle ligne, correspondant à la clé créée, s'affiche sur la page principale. Dans cette ligne, cliquer sur le bouton Copy API key pour copier la chaîne de caractères composant la clé dans le presse-papier

3 - Sauvegarde de la clé AIStudio¶
Cliquer sur le lien suivant pour ouvrir le fichier ai.py, puis sur la ligne 9 du fichier, coller les caractères de la clé à la place des ●●● qui se trouvent entre les guillemets (cf. zone droite, partie inférieure)
Finir par CTRL + S pour sauvegarder le fichier modifié
C - Utilisation de Jupyter-AI
Lorsque la clé personnelle a été insérée dans le fichier ai.py, l'accès au moteur Gemini-3.1-Flash-Lite via l'extension Jupyter-AI devient directement accessible par la commande import :
import ai # configuration de jupyter-ai et import de l'ensemble des 'prompt patterns'
# Note : l'exécution de la cellule nécessite quelques secondes pour finaliser la configuration
L'apport principal de l'extension Jupyter-AI est de fournir une commande magique %%ai qui permet de transformer une cellule de code du notebook, en une cellule de dialogue avec le moteur IAG sélectionné :
%%ai
qui es-tu ?
Je suis un modèle linguistique étendu, entraîné par Google.
Tu peux me voir comme un assistant virtuel polyvalent capable de :
- Répondre à des questions sur une multitude de sujets.
- Rédiger et corriger des textes (e-mails, articles, essais, poèmes, etc.).
- Traduire des langues.
- Aider à la programmation informatique.
- Synthétiser des informations complexes.
- Brainstormer des idées créatives.
Je n'ai pas de conscience, de sentiments ou d'opinions personnelles. Mon objectif est de t'aider à accomplir tes tâches ou à satisfaire ta curiosité grâce aux vastes quantités de données sur lesquelles j'ai été entraîné.
Comment puis-je t'aider aujourd'hui ?
1 - Contrôle du format de sortie (option -f)¶
La commande magique %%ai possède une option -f format qui permet de choisir le format de sortie parmi les suivants :
Les 5 premiers formats vont générer la réponse dans une cellule de texte, en utilisant respectivement les formats Markdown (= format par défaut), Markdown brut, HTML, LaTeX et JSON, alors que le dernier va créer une cellule de code contenant la réponse, ce qui permettra d'exécuter directement le code généré. Il faut noter que Jupyter-AI connait le noyau actif dans le notebook, et il va donc automatiquement générer le code dans le langage de programmation correspondant au noyau.
%%ai
écrire une liste en 5 points résumant la méthode des moindres carrés sur une base de fonctions prédéfinie
Voici un résumé en 5 points de la méthode des moindres carrés appliquée à une base de fonctions :
- Définition du modèle : On cherche à approximer une fonction inconnue par une combinaison linéaire d'une base de fonctions prédéfinies $\{ \phi_1(x), \phi_2(x), \dots, \phi_n(x) \}$, soit $f(x) \approx \sum_{j=1}^{n} c_j \phi_j(x)$.
- Mesure de l'erreur : L'objectif est de minimiser la somme des carrés des écarts (résidus) entre les valeurs observées $y_i$ et les valeurs prédites par le modèle aux points $x_i$ : $S = \sum_{i=1}^{m} \left( y_i - \sum_{j=1}^{n} c_j \phi_j(x_i) \right)^2$.
- Formulation matricielle : Le problème se ramène à résoudre le système linéaire $A\mathbf{c} = \mathbf{y}$, où $A$ est la matrice de design (ou matrice de Vandermonde généralisée) dont les éléments sont $A_{ij} = \phi_j(x_i)$.
- Équations normales : Pour minimiser $S$, on annule le gradient par rapport aux coefficients $c_j$, ce qui conduit aux équations normales : $(A^T A)\mathbf{c} = A^T \mathbf{y}$.
- Résolution : Si les fonctions de base sont linéairement indépendantes, la matrice $A^T A$ est inversible, permettant d'obtenir la solution unique $\mathbf{c} = (A^T A)^{-1} A^T \mathbf{y}$, qui minimise l'erreur quadratique totale.
%%ai -f text
écrire une liste en 5 points résumant la méthode des moindres carrés sur une base de fonctions prédéfinie
Voici un résumé en 5 points de la méthode des moindres carrés appliquée à une base de fonctions :
1. **Définition du modèle :** On cherche à approximer une fonction inconnue par une combinaison linéaire d'une base de fonctions prédéfinies $\{ \phi_1(x), \phi_2(x), \dots, \phi_n(x) \}$, soit $f(x) \approx \sum_{j=1}^{n} c_j \phi_j(x)$.
2. **Mesure de l'erreur :** L'objectif est de minimiser la somme des carrés des écarts (résidus) entre les valeurs observées $y_i$ et les valeurs prédites par le modèle aux points $x_i$ : $S = \sum_{i=1}^{m} \left( y_i - \sum_{j=1}^{n} c_j \phi_j(x_i) \right)^2$.
3. **Formulation matricielle :** Le problème se ramène à résoudre le système linéaire $A\mathbf{c} = \mathbf{y}$, où $A$ est la matrice de design dont les éléments sont $A_{ij} = \phi_j(x_i)$.
4. **Équations normales :** Pour minimiser $S$, on annule le gradient par rapport aux coefficients $c_j$, ce qui conduit au système des équations normales : $(A^T A)\mathbf{c} = A^T \mathbf{y}$.
5. **Résolution :** Si les fonctions de base sont linéairement indépendantes, la matrice $A^T A$ est inversible, permettant d'obtenir la solution unique $\mathbf{c} = (A^T A)^{-1} A^T \mathbf{y}$, qui minimise l'erreur quadratique totale.
%%ai -f math
écrire l'équation de minimisation de l'erreur résiduelle par la méthode des moindres carrés
sur une base de fonctions prédéfinie
%%ai -f text
écrire le code LaTeX de l'équation de minimisation de l'erreur résiduelle par la méthode des moindres carrés
sur une base de fonctions prédéfinie
```latex
\min_{c_1, \dots, c_n} \sum_{i=1}^{m} \left( y_i - \sum_{j=1}^{n} c_j \phi_j(x_i) \right)^2
```
2 - Contrôle des paramètres du modèle (option -m)¶
La commande magique %%ai possède également une option -m {key:val, key:val...} qui permet de configurer les différents paramètres utilisés par le moteur IAG sélectionné, sous la forme d'un dictionnaire JSON combinant une série de couple clés-valeurs. La liste suivante fournit les noms, les valeurs par défaut ainsi que le rôle de chacun des paramètres utilisables :
- temperature=1.0 (réel $\in [0,2]$) : contrôle de la variabilité des réponses (bas = plus stable, haut = plus varié)
- top_k=64 (entier ≥ 1) : élagage pour le choix des tokens (uniquement les
ktokens les plus probables) - max_tokens=65536 (entier ≥ 1) : nombre maximum de tokens à générer pour la réponse
- thinking_level="high" (chaîne) : niveau de réflexion, à choisir parmi
minimal, low, medium, high - include_thoughts=false (booléen) : inclusion ou non du raisonnement dans la réponse
- seed=none (entier) : amélioration de la reproductibilité des réponses (sans garantie parfaite)
- max_retries=6 (entier ≥ 1) : nombre de tentatives en cas d’erreur (timeout réseau, quota dépassé...)
- stop=none (liste de chaînes) : définition des motifs d'arrêt pour la génération (e.g.
["\n\n", "###"]) - response_mime_type="text/plain" (chaîne MIME) : format utilisé pour la réponse, au standard MIME
%%ai -m {"temperature":0,"seed":0,"thinking_level":"minimal"} -f text
reformuler cette phrase avec les 5 styles suivants : académique, technique, ironique, humoristique, hyper-concis :
> Longtemps, je me suis couché de bonne heure. Parfois, à peine ma bougie éteinte, mes yeux se fermaient si vite
que je n’avais pas le temps de me dire : je m’endors.
Voici la reformulation de la phrase selon les cinq styles demandés : ### 1. Académique « Pendant une période prolongée, j'ai adopté une routine de sommeil précoce. Il arrivait fréquemment que, sitôt la source lumineuse éteinte, le passage à l'état de sommeil soit si soudain qu'il m'empêchait de prendre conscience du processus d'endormissement en cours. » ### 2. Technique « J'ai instauré un protocole de coucher anticipé. La latence d'endormissement était alors si réduite que la transition entre l'état de veille et l'état de sommeil se produisait instantanément après l'extinction de la source lumineuse, rendant impossible toute auto-observation cognitive du phénomène. » ### 3. Ironique « J'ai passé une éternité à me coucher comme une poule. Apparemment, mon cerveau était tellement pressé de s'éteindre que je n'avais même pas la politesse de me prévenir avant de sombrer dans l'inconscience. » ### 4. Humoristique « Je me couchais tellement tôt que mon sommeil me sautait dessus avant même que j'aie pu dire "ouf" — ou plutôt "je m'endors". C'était une véritable course contre la montre perdue d'avance contre mes propres paupières. » ### 5. Hyper-concis « Coucher précoce, endormissement instantané : aucune conscience de la transition. »
%%ai -m {"temperature":2,"thinking_level":"high"} -f text
faire un `reset memory` sur la réponse précédente
reformuler cette phrase avec les 5 styles suivants : académique, technique, ironique, humoristique, hyper-concis :
> Longtemps, je me suis couché de bonne heure. Parfois, à peine ma bougie éteinte, mes yeux se fermaient si vite
que je n’avais pas le temps de me dire : je m’endors.
Mémoire réinitialisée. Voici la reformulation de la phrase demandée selon les cinq styles : ### 1. Académique « J'ai maintenu pendant une période significative une discipline de sommeil précoce. Il advenait régulièrement que, dès l'extinction de la chandelle, le basculement vers l'inconscience fût d'une telle célérité qu'il rendait impossible toute formalisation cognitive de l'instant précis de l'endormissement. » ### 2. Technique « L'instauration d'un cycle circadien débutant systématiquement tôt a entraîné une latence d'endormissement négligeable. Le passage de la veille au sommeil post-extinction lumineuse s'effectuait via un déclenchement instantané, empêchant l'encodage temporel du seuil de somnolence par le sujet. » ### 3. Ironique « C'est une discipline fascinante que d'aller se coucher à une heure de retraités. On frôle l'exploit technologique : s'éteindre si vite après la bougie que le cerveau n'a même pas le loisir d'admirer sa propre chute dans le vide. » ### 4. Humoristique « Je m'étais fait une spécialité des couchers express. Si bien qu'à peine la bougie rendait l'âme, je le faisais aussi ; une vraie performance de sommeil ninja où mon conscient se faisait prendre en flagrant délit de somnolence par mes propres paupières. » ### 5. Hyper-concis « Coucher matinal. Endormissement réflexe avant toute auto-analyse. »
3 - Accès au contexte du notebook¶
L'autre apport de l'extension Jupyter-AI est de pouvoir accéder à toutes les variables et fonctions qui ont été définies ou importées dans le notebook, y compris tous les contenus des cellulles de code et tous les résultats d'exécution de ces cellules. Ainsi pour injecter le contenu d'une variable var dans un prompt, il suffit d'utiliser la syntaxe {var}, équivalente à celle utilisée par la langage Python pour la création des chaînes formatées (f-strings).
Le contenu des cellules du notebook est accessible par deux dictionnaires constamment mis à jour par le noyau ipykernel : In[k] contient le texte de la cellule numéro k et Out[k] contient le texte de l'exécution de la cellule numéro k. Le noyau définit également six raccourcis particulièrement utiles dans le contexte de Jupyter-AI :
_ / __ / ___= résultat de l'exécution de la dernière / pénultième / antépénultième cellule de code
_i / _ii / _iii= code contenu dans la dernière / pénultième / antépénultième cellule de code
%%ai
reset memory
Mémoire réinitialisée.
lang = 'french'
%%ai
write a sonnet in {lang}, about Master students in Data Science
Voici un sonnet en français sur les étudiants en Master de Data Science :
Jeunes esprits ardents, plongés dans l'océan, Où les flots de données sans cesse se déchaînent, Leur quête est de percer les mystères qui traînent, Pour extraire le sens d'un monde bruyant.
Devant les écrans, leur savoir est géant, Python, R, SQL, des langages qui enchaînent Les lignes de code où les logiques s'égrènent, Bâtissant des modèles, un futur triomphant.
Ils domptent l'aléatoire, les biais insidieux, Cherchent la corrélation, le lien précieux, Pour que la vérité enfin brille à leurs yeux.
De l'apprentissage profond aux arbres de décision, Ils forgent la connaissance, avec précision, Guidant le monde vers une nouvelle vision.
%%ai
reformat {_} as follows :
- put action verbs in bold and adjectives in bold italics
- one line per verse (use <br>) and one paragraph per quatrain and tercet
Jeunes esprits ardents, plongés dans l'océan,
Où les flots de données sans cesse se déchaînent,
Leur quête est de percer les mystères qui traînent,
Pour extraire le sens d'un monde bruyant.
Devant les écrans, leur savoir est géant,
Python, R, SQL, des langages qui enchaînent
Les lignes de code où les logiques s'égrènent,
Bâtissant des modèles, un futur triomphant.
Ils domptent l'aléatoire, les biais insidieux,
Cherchent la corrélation, le lien précieux,
Pour que la vérité enfin brille à leurs yeux.
De l'apprentissage profond aux arbres de décision,
Ils forgent la connaissance, avec précision,
Guidant le monde vers une nouvelle vision.
%%ai -f text
translate {_} in spanish but keep rhymes
Jóvenes mentes ***ardientes***, **sumergidas** en el océano,<br> Donde los flujos de datos sin cesar se **desatan**,<br> Su búsqueda **es** **penetrar** los secretos que **tratan**,<br> Para **extraer** el sentido de un saber ***arcano***. Frente a las pantallas, su saber **es** ***gigante***,<br> Python, R, SQL, lenguajes que **encadenan**<br> Las líneas de código donde lógicas se **ordenan**,<br> **Construyendo** modelos, un futuro ***brillante***. Ellos **doman** el azar, los sesgos ***insidiosos***,<br> **Buscan** la correlación, el nexo ***precioso***,<br> Para que la verdad **brille** en datos ***luminosos***. Del aprendizaje ***profundo*** a los árboles de decisión,<br> Ellos **forjan** el saber, con ***gran*** precisión,<br> **Guiando** al mundo hacia una ***nueva*** visión.
D - Utilisation des Prompt Patterns
Le fichier ai.py contient une série de variables globales qui contiennent des patterns, formatés en Mardown, pouvant être inclus dans les prompts via la syntaxe {var} mentionnée plus haut :
ai.BASE: regroupe les règles de base (à inclure en entête de toute cellule%%ai)ai.TNS, ... , ai.TMDS: le préfixeTidentifie les règles pour la section TARGETai.FTXT, ..., ai.FSC: le préfixeFidentifie les règles pour la section FORMATai.COCO: règles globales spécifiquement adaptées pour le pattern Code Completion
1 - Liste des patterns¶
Les cellules ci-dessous montrent le contenu de ces différentes variables, mais il est important de souligner que ces variables sont simplement fournies à titre d'exemple, il est évidemment fortement recommandé de compléter le fichier avec vos propres patterns, pour avoir une interface avec le moteur IAG qui soit la plus efficace et la plus productive possible.
show("ai.BASE") # règles de base, à inclure systématiquement en tête de prompt
ai.BASE ➤ - **MANDATORY** : All rules given in these instructions must never be broken, and any generated answer (either code or documentation) must be **fully and strictly compliant**. - All user prompts in this session are always organized using from 1 to 7 **sections** (entitled TASK / PROCESS / TARGET / FORMAT / CONTEXT / EXAMPLES / CODE in capitals). When a section is missing, it must be considered as empty. When a section contains the single word "same", the whole content of the same section in the previous prompt must be used again. - The generated answer must **always answer exactly** the TASK given in the prompt, and must **never include additional content** (unwanted content includes comments about the task, suggestions or questions about additional tasks). In other words : "straight to the point".
show("ai.TNS; ai.TBDS; ai.TMDS") # règles permettant d'adapter la réponse aux compétences du lecteur
ai.TNS ➤ TARGET : - target the answer for non-specialists (assume no prerequisites, explain basic stuff) ai.TBDS ➤ TARGET : - target the answer for a Bachelor student in Data Science ai.TMDS ➤ TARGET : - target the answer for a Master student in Data Science
show("ai.FTXT; ai.FRMD; ai.FCSV; ai.FJSON") # règles de formatage pour le texte ou les données
ai.FTXT ➤ FORMAT : - format answer as a standard Unicode string ai.FRMD ➤ FORMAT : - format answer as a raw Markdown string ai.FCSV ➤ FORMAT : - format answer as a CSV string ai.FJSON ➤ FORMAT : - format answer as a JSON string
show("ai.FCC; ai.FSC") # règles de formatage pour le code (CC = Clean Code, SC = Storytelling Code)
ai.FCC ➤ FORMAT : - produce only code without any explanation about it - optimize code by importing any useful function from the standard library - write compact but legible code with no blank lines - use short but explicit english identifiers - use 2-space indentation and 1-line docstrings - structure docstring as "imperative_verb complements", all in lowercase - use list comprehension instead of `for` loops, when it may simplify code - prefer one statement per line, but to improve compactness, multiple short statements are allowed on the same line, using `;` separators - put small blocks on the same line as `if/while/for/with` statements - do not include any comment or annotation in code - keep code lines under 80 characters - do not add space char before or after these operators `+ - * / %` - add one space char after these operators `, ; :` - add one space char before and after all other operators `= == < <= > >=`, etc - use double quotes for f-strings but single quotes for standard strings ai.FSC ➤ FORMAT : - produce only code without any explanation about it - optimize code by importing any useful function from the standard library - write compact but legible code with no blank lines - use short but explicit english identifiers - use 2-space indentation and 1-line docstrings - structure docstring as "imperative_verb complements", all in lowercase - use list comprehension instead of `for` loops, when it may simplify code - prefer one statement per line, but to improve compactness, multiple short statements are allowed on the same line, using `;` separators - put small blocks on the same line as `if/while/for/with` statements - add a short "storytelling comment" at the end of each code line, except for lines containing import statements, function definitions or doctrings - structure these storytelling comments as "imperative_verb complements", all in lowercase - keep code lines under 80 characters, without counting storytelling comments - keep code lines under 120 characters, when including storytelling comments - use multi-line comments only for complex algorithmic parts - do not add space char before or after these operators `+ - * / %` - add one space char after these operators `, ; :` - add one space char before and after all other operators `= == < <= > >=`, etc - use double quotes for f-strings but single quotes for standard strings
show("ai.COCO") # règles complètes pour le pattern "Code Completion"
ai.COCO ➤ - **MANDATORY** : All rules given in these instructions must never be broken, and any generated answer (either code or documentation) must be **fully and strictly compliant**. - All user prompts in this session are always organized using from 1 to 7 **sections** (entitled TASK / PROCESS / TARGET / FORMAT / CONTEXT / EXAMPLES / CODE in capitals). When a section is missing, it must be considered as empty. When a section contains the single word "same", the whole content of the same section in the previous prompt must be used again. - The generated answer must **always answer exactly** the TASK given in the prompt, and must **never include additional content** (unwanted content includes comments about the task, suggestions or questions about additional tasks). In other words : "straight to the point". TASK : - complete and improve the provided code PROCESS : - enforce all instructions written in 'TODO' comments embedded in code - only use existing variables or variables mentionned in 'TODO' comments - keep existing code lines as is - keep existing comments as is, except when they contain either 'TODO' or 'NOTE' - always search for the shortest and the most optimized implementation - always check code on provided example, if present FORMAT : - produce only code without any explanation about it - optimize code by importing any useful function from the standard library - write compact but legible code with no blank lines - use short but explicit english identifiers - use 2-space indentation and 1-line docstrings - structure docstring as "imperative_verb complements", all in lowercase - use list comprehension instead of `for` loops, when it may simplify code - prefer one statement per line, but to improve compactness, multiple short statements are allowed on the same line, using `;` separators - put small blocks on the same line as `if/while/for/with` statements - add a short "storytelling comment" at the end of each code line, except for lines containing import statements, function definitions or doctrings - structure these storytelling comments as "imperative_verb complements", all in lowercase - keep code lines under 80 characters, without counting storytelling comments - keep code lines under 120 characters, when including storytelling comments - use multi-line comments only for complex algorithmic parts - do not add space char before or after these operators `+ - * / %` - add one space char after these operators `, ; :` - add one space char before and after all other operators `= == < <= > >=`, etc - use double quotes for f-strings but single quotes for standard strings CODE :
2 - Mise en oeuvre des patterns¶
Dans cette section, on va reprendre quelques uns des exemples vus en cours, lorsque j'avais commenté quelques sessions avec ChatGPT, et montrer que le moteur Gemini, mis en oeuvre via Jupyter-AI, permet d'obtenir des résultats tout à fait similaires, en utilisant exactement la même architecture de prompts
Génération de documentation (réponse en anglais pour étudiant en Master Data Science)¶
%%ai
{ai.BASE}
TASK :
- explain the main role of the Python package "random" in a 100-word long paragraph
- select the 5 most useful functions and explain their role and use case, using 1 ou 2 sentences
{ai.TMDS}
The random package in Python is crucial for generating pseudo-random numbers, which are essential across various data science domains. It provides functions to simulate stochastic processes, perform statistical sampling, and generate synthetic datasets. Data scientists leverage this package for tasks ranging from creating reproducible research environments by setting seeds, to implementing Monte Carlo simulations, conducting A/B testing, and ensuring fairness in data splitting. Its utility extends to machine learning for initializing weights, cross-validation, and creating randomized feature subsets, making it a foundational tool for experimentation and robust model evaluation.
Here are 5 useful functions from the random package:
random.random()- Role: Returns a random floating-point number in the range [0.0, 1.0).
- Use Case: Fundamental for generating probabilities, simulating continuous uniform distributions, or as a base to create custom random number generators for more complex distributions.
random.randint(a, b)- Role: Returns a random integer N such that
a <= N <= b. - Use Case: Useful for generating random indices, selecting a random number of items, or creating discrete random variables within a specified inclusive range.
- Role: Returns a random integer N such that
random.choice(seq)- Role: Returns a random element from a non-empty sequence.
- Use Case: Ideal for selecting a single random observation from a dataset, choosing a random class label for a synthetic sample, or picking a random configuration in an optimization process.
random.sample(population, k)- Role: Returns a new list containing
kunique elements chosen randomly from thepopulationsequence, without replacement. - Use Case: Essential for tasks like creating train/test splits, performing bootstrap sampling without replacement, or selecting a subset of features for a random forest.
- Role: Returns a new list containing
random.shuffle(x)- Role: Shuffles the elements of a list
xin place, modifying the original list. - Use Case: Crucial for randomizing the order of a dataset before training to prevent bias from data order, or for shuffling data for cross-validation folds.
- Role: Shuffles the elements of a list
Génération de documentation (réponse en français pour lecteur non-spécialiste)¶
%%ai
{ai.BASE}
TASK :
- explain the main role of the Python package "random" in a 100-word long paragraph
- select the 5 most useful functions and explain their role and use case, using 1 ou 2 sentences
{ai.TNS} + answer in french
Le module random en Python est essentiel pour créer ce qui ressemble à du hasard sur un ordinateur. Les ordinateurs sont très logiques et ne peuvent pas générer de "vrai" hasard par eux-mêmes. Ce module leur permet de simuler des événements imprévisibles, comme tirer à pile ou face, lancer un dé, ou mélanger un jeu de cartes. Il est utilisé dans de nombreux domaines : pour des jeux vidéo, des simulations (par exemple, comment une foule se déplace ou comment une maladie se propage), pour choisir des éléments de manière équitable, ou même pour créer des exemples variés. C'est un outil fondamental pour introduire de l'incertitude contrôlée et rendre les programmes plus dynamiques et réalistes.
Voici 5 fonctions utiles du module random :
random.random()- Rôle : Donne un nombre à virgule entre 0 (inclus) et 1 (exclus), comme 0.345 ou 0.99.
- Cas d'utilisation : Utile pour simuler des probabilités (par exemple, une chance sur deux), ou pour obtenir un nombre aléatoire dans une plage simple.
random.randint(a, b)- Rôle : Donne un nombre entier au hasard entre
aetb,aetbétant inclus. - Cas d'utilisation : Parfait pour simuler le lancer d'un dé (par exemple,
randint(1, 6)) ou pour choisir un numéro de loterie.
- Rôle : Donne un nombre entier au hasard entre
random.choice(seq)- Rôle : Choisit un élément au hasard parmi une liste ou une séquence donnée.
- Cas d'utilisation : Idéal pour piocher une carte dans un jeu, sélectionner un nom dans une liste de participants, ou choisir une option aléatoire.
random.sample(population, k)- Rôle : Sélectionne
kéléments différents au hasard dans une liste, sans les remettre dedans. - Cas d'utilisation : Utile pour tirer plusieurs numéros gagnants uniques, ou pour choisir un petit groupe de personnes dans un grand ensemble pour une étude.
- Rôle : Sélectionne
random.shuffle(x)- Rôle : Mélange l'ordre des éléments d'une liste directement, comme si on mélangeait un paquet de cartes.
- Cas d'utilisation : Essentiel pour mélanger les questions d'un quiz, ou pour s'assurer que l'ordre des éléments n'influence pas un résultat.
Explication de code¶
%%ai -f text
{ai.BASE}
TASK :
- explain the role of the provided code in a short paragraph (100 words max)
PROCESS :
- give details about the role of each variable and each function (1 sentence per item)
- provide various usage examples and some use cases
{ai.TMDS}
CODE :
def show(string):
"""split, eval, print a string containing python expressions separated by semi-colons
- optional prefix for expression : '*' = unpack items for iterable expression
- optional suffix for expression : '#' = insert newline before printing expression"""
from inspect import stack
namespace = stack()[1][0].f_globals # get global namespace from caller
namespace = dict((k,v) for (k,v) in namespace.items() if k[0] != '_')
for exp in string.split(';'):
exp = exp.strip(); head, tail = exp[:1], exp[-1:]
head, exp = ('*', exp[1:]) if head == '*' else ('', exp)
tail, exp = (' ➤\n', exp[:-1]) if tail == '#' else (' ➤ ', exp)
if not exp: print(); continue # insert blank line if expression is empty
val = eval(exp, namespace); print(head + exp + tail, end='')
print(*val) if head else print(val)
The `show` function acts as a specialized interactive evaluation and display utility. It allows users to define and execute multiple Python expressions within a single string, separated by semicolons. Its core utility lies in providing enhanced output formatting: it can automatically unpack iterable results with a `*` prefix and control line breaks with a `#` suffix. This makes it particularly effective for quickly inspecting variable states, debugging, and presenting concise, formatted outputs in interactive data science environments like Jupyter notebooks, facilitating rapid data exploration and analysis.
Here are the roles of the variables and the function:
* **`show(string)`**: This function evaluates a semicolon-separated string of Python expressions, printing their results with optional formatting for clarity.
* **`string`**: This parameter is the input string containing one or more Python expressions that the function will parse and execute.
* **`stack`**: This function from the `inspect` module is used to retrieve information about the current call stack, specifically to access the global namespace of the calling scope.
* **`namespace`**: This dictionary stores the global variables available in the scope from which `show` was invoked, serving as the execution context for `eval()`.
* **`k`**: Within the dictionary comprehension, `k` represents a key (variable name) from the caller's global namespace.
* **`v`**: Within the dictionary comprehension, `v` represents a value associated with a key `k` from the caller's global namespace.
* **`exp`**: This variable holds a single Python expression, extracted from the input `string` after splitting by semicolons and stripping whitespace.
* **`head`**: This temporary variable initially stores the first character of `exp` to check for the `*` prefix, and later stores the formatted output prefix (`''` or `'*'`).
* **`tail`**: This temporary variable initially stores the last character of `exp` to check for the `#` suffix, and later stores the formatted output suffix (`' ➤ '` or `' ➤\n'`).
* **`val`**: This variable stores the result obtained from evaluating a Python expression using the `eval()` function within the specified `namespace`.
**Usage Examples and Use Cases:**
Let's define some variables for demonstration:
```python
x = 10
y = [1, 2, 3, 4]
data_dict = {'alpha': 100, 'beta': 200}
import pandas as pd
df = pd.DataFrame({'col1': [1, 2, 3], 'col2': ['A', 'B', 'C']})
```
* **Basic Evaluation:**
```python
show("x + 5")
# Output: x + 5 ➤ 15
```
*Use Case:* Quickly checking the value of a variable or the result of a simple operation during interactive data exploration or debugging.
* **Multiple Expressions:**
```python
show("x; len(y); data_dict['alpha']")
# Output:
# x ➤ 10
# len(y) ➤ 4
# data_dict['alpha'] ➤ 100
```
*Use Case:* Efficiently inspecting multiple related variables or properties in a single line, common in Jupyter notebooks for quick state checks.
* **Unpacking Iterables (`*` prefix):**
```python
show("*y; *data_dict.keys()")
# Output:
# *y ➤ 1 2 3 4
# *data_dict.keys() ➤ alpha beta
```
*Use Case:* Displaying individual elements of lists, tuples, or dictionary keys/values without explicit loops, which is useful for rapid sanity checks on data structures.
* **Forcing a Newline (`#` suffix):**
```python
show("x * 2#; y[0]")
# Output:
# x * 2 ➤
# 20
# y[0] ➤ 1
```
*Use Case:* Improving readability by ensuring the result of an expression appears on a new line, especially for outputs that might be long or require visual separation.
* **Combined Formatting:**
```python
show("*y#; data_dict['beta']")
# Output:
# *y ➤
# 1 2 3 4
# data_dict['beta'] ➤ 200
```
*Use Case:* Combining the benefits of unpacking iterable results with clear line separation, ideal for presenting structured data followed by a specific metric.
* **Using Empty Expression for Blank Line:**
```python
show("x; ; y")
# Output:
# x ➤ 10
#
# y ➤ [1, 2, 3, 4]
```
*Use Case:* Inserting visual spacing between outputs for better organization and readability in console logs or reports.
* **Interacting with Data Structures (e.g., Pandas DataFrame):**
```python
show("df.head(); df.shape")
# Output:
# df.head() ➤ col1 col2
# 0 1 A
# 1 2 B
# 2 3 C
# df.shape ➤ (3, 2)
```
*Use Case:* Directly inspecting attributes and methods of complex data structures like Pandas DataFrames or NumPy arrays that are already defined in the global scope, a common task in data science workflows.
Génération de données (formats classiques : CSV et JSON)¶
%%ai -f text
{ai.BASE}
TASK :
- generate a CSV multi-line string containing 25 famous French authors born during the
18th, 19th and 20th centuries
PROCESS :
- generate the following fields for each line :
'nom', 'prénom', 'date_naissance', 'lieu_naissance', 'date_décès', 'lieu_décès'
- sort all lines by increasing date of birth (sort key = year then month then day)
{ai.FCSV}
```csv "nom","prénom","date_naissance","lieu_naissance","date_décès","lieu_décès" "Voltaire","François-Marie","1694-11-21","Paris","1778-05-30","Paris" "Rousseau","Jean-Jacques","1712-06-28","Genève","1778-07-02","Ermenonville" "Diderot","Denis","1713-10-05","Langres","1784-07-31","Paris" "Beaumarchais","Pierre-Augustin Caron de","1732-01-24","Paris","1799-05-18","Paris" "Sade","Donatien Alphonse François de","1740-06-02","Paris","1814-12-02","Charenton-Saint-Maurice" "Laclos","Pierre Choderlos de","1741-10-18","Amiens","1803-09-05","Tarente" "Stendhal","Henri","1783-01-23","Grenoble","1842-03-23","Paris" "Balzac","Honoré de","1799-05-20","Tours","1850-08-18","Paris" "Hugo","Victor","1802-02-26","Besançon","1885-05-22","Paris" "Dumas","Alexandre","1802-07-24","Villers-Cotterêts","1870-12-05","Puys (Dieppe)" "Sand","George","1804-07-01","Paris","1876-06-08","Nohant-Vic" "Musset","Alfred de","1810-12-11","Paris","1857-05-02","Paris" "Baudelaire","Charles","1821-04-09","Paris","1867-08-31","Paris" "Flaubert","Gustave","1821-12-12","Rouen","1880-05-08","Croisset (Canteleu)" "Verne","Jules","1828-02-08","Nantes","1905-03-24","Amiens" "Zola","Émile","1840-04-02","Paris","1902-09-29","Paris" "Verlaine","Paul","1844-03-30","Metz","1896-01-08","Paris" "Maupassant","Guy de","1850-08-05","Tourville-sur-Arques","1893-07-06","Paris" "Rimbaud","Arthur","1854-10-20","Charleville","1891-11-10","Marseille" "Gide","André","1869-11-22","Paris","1951-02-19","Paris" "Proust","Marcel","1871-07-10","Auteuil (Paris)","1922-11-18","Paris" "Saint-Exupéry","Antoine de","1900-06-29","Lyon","1944-07-31","Méditerranée" "Sartre","Jean-Paul","1905-06-21","Paris","1980-04-15","Paris" "Beauvoir","Simone de","1908-01-09","Paris","1986-04-14","Paris" "Camus","Albert","1913-11-07","Mondovi, Algérie française","1960-01-04","Villeblevin" ```
%%ai -f text
TASK :
- convert {_} into a JSON string
- put all fields from a record on the same line
{ai.FJSON}
```json
[
{"nom": "Voltaire", "prénom": "François-Marie", "date_naissance": "1694-11-21", "lieu_naissance": "Paris", "date_décès": "1778-05-30", "lieu_décès": "Paris"},
{"nom": "Rousseau", "prénom": "Jean-Jacques", "date_naissance": "1712-06-28", "lieu_naissance": "Genève", "date_décès": "1778-07-02", "lieu_décès": "Ermenonville"},
{"nom": "Diderot", "prénom": "Denis", "date_naissance": "1713-10-05", "lieu_naissance": "Langres", "date_décès": "1784-07-31", "lieu_décès": "Paris"},
{"nom": "Beaumarchais", "prénom": "Pierre-Augustin Caron de", "date_naissance": "1732-01-24", "lieu_naissance": "Paris", "date_décès": "1799-05-18", "lieu_décès": "Paris"},
{"nom": "Sade", "prénom": "Donatien Alphonse François de", "date_naissance": "1740-06-02", "lieu_naissance": "Paris", "date_décès": "1814-12-02", "lieu_décès": "Charenton-Saint-Maurice"},
{"nom": "Laclos", "prénom": "Pierre Choderlos de", "date_naissance": "1741-10-18", "lieu_naissance": "Amiens", "date_décès": "1803-09-05", "lieu_décès": "Tarente"},
{"nom": "Stendhal", "prénom": "Henri", "date_naissance": "1783-01-23", "lieu_naissance": "Grenoble", "date_décès": "1842-03-23", "lieu_décès": "Paris"},
{"nom": "Balzac", "prénom": "Honoré de", "date_naissance": "1799-05-20", "lieu_naissance": "Tours", "date_décès": "1850-08-18", "lieu_décès": "Paris"},
{"nom": "Hugo", "prénom": "Victor", "date_naissance": "1802-02-26", "lieu_naissance": "Besançon", "date_décès": "1885-05-22", "lieu_décès": "Paris"},
{"nom": "Dumas", "prénom": "Alexandre", "date_naissance": "1802-07-24", "lieu_naissance": "Villers-Cotterêts", "date_décès": "1870-12-05", "lieu_décès": "Puys (Dieppe)"},
{"nom": "Sand", "prénom": "George", "date_naissance": "1804-07-01", "lieu_naissance": "Paris", "date_décès": "1876-06-08", "lieu_décès": "Nohant-Vic"},
{"nom": "Musset", "prénom": "Alfred de", "date_naissance": "1810-12-11", "lieu_naissance": "Paris", "date_décès": "1857-05-02", "lieu_décès": "Paris"},
{"nom": "Baudelaire", "prénom": "Charles", "date_naissance": "1821-04-09", "lieu_naissance": "Paris", "date_décès": "1867-08-31", "lieu_décès": "Paris"},
{"nom": "Flaubert", "prénom": "Gustave", "date_naissance": "1821-12-12", "lieu_naissance": "Rouen", "date_décès": "1880-05-08", "lieu_décès": "Croisset (Canteleu)"},
{"nom": "Verne", "prénom": "Jules", "date_naissance": "1828-02-08", "lieu_naissance": "Nantes", "date_décès": "1905-03-24", "lieu_décès": "Amiens"},
{"nom": "Zola", "prénom": "Émile", "date_naissance": "1840-04-02", "lieu_naissance": "Paris", "date_décès": "1902-09-29", "lieu_décès": "Paris"},
{"nom": "Verlaine", "prénom": "Paul", "date_naissance": "1844-03-30", "lieu_naissance": "Metz", "date_décès": "1896-01-08", "lieu_décès": "Paris"},
{"nom": "Maupassant", "prénom": "Guy de", "date_naissance": "1850-08-05", "lieu_naissance": "Tourville-sur-Arques", "date_décès": "1893-07-06", "lieu_décès": "Paris"},
{"nom": "Rimbaud", "prénom": "Arthur", "date_naissance": "1854-10-20", "lieu_naissance": "Charleville", "date_décès": "1891-11-10", "lieu_décès": "Marseille"},
{"nom": "Gide", "prénom": "André", "date_naissance": "1869-11-22", "lieu_naissance": "Paris", "date_décès": "1951-02-19", "lieu_décès": "Paris"},
{"nom": "Proust", "prénom": "Marcel", "date_naissance": "1871-07-10", "lieu_naissance": "Auteuil (Paris)", "date_décès": "1922-11-18", "lieu_décès": "Paris"},
{"nom": "Saint-Exupéry", "prénom": "Antoine de", "date_naissance": "1900-06-29", "lieu_naissance": "Lyon", "date_décès": "1944-07-31", "lieu_décès": "Méditerranée"},
{"nom": "Sartre", "prénom": "Jean-Paul", "date_naissance": "1905-06-21", "lieu_naissance": "Paris", "date_décès": "1980-04-15", "lieu_décès": "Paris"},
{"nom": "Beauvoir", "prénom": "Simone de", "date_naissance": "1908-01-09", "lieu_naissance": "Paris", "date_décès": "1986-04-14", "lieu_décès": "Paris"},
{"nom": "Camus", "prénom": "Albert", "date_naissance": "1913-11-07", "lieu_naissance": "Mondovi, Algérie française", "date_décès": "1960-01-04", "lieu_décès": "Villeblevin"}
]
```
Nettoyage de code¶
%%ai
reset memory
Okay, memory reset. How can I help you now?
%%ai -f code
{ai.BASE}
TASK :
- improve readability of the following code
PROCESS :
- focus only on readability
- keep existing code structure as is
- add comment about the role of each main variable
- use type hints for ALL variables and functions
- include assert statements to check type and domain for each input data
- extend docstring to include test statements following the syntax of the standard 'doctest' module
- try to get a reasonable code coverage for the 'doctest' statements
{ai.FSC}
CODE :
def fibo(n):
"""return the n-th Fibonacci number"""
a, b = 0, 1
for _ in range(n): a, b = b, a + b
return a
def fibo(n: int) -> int: # define function to calculate Fibonacci number
"""
calculate the n-th Fibonacci number.
>>> fibo(0)
0
>>> fibo(1)
1
>>> fibo(2)
1
>>> fibo(3)
2
>>> fibo(6)
8
"""
assert isinstance(n, int), 'ensure input is an integer' # validate input type
assert n >= 0, 'ensure input is non-negative' # validate input domain
a: int = 0; b: int = 1 # initialize first (a) and second (b) Fibonacci numbers
for _ in range(n): a, b = b, a+b # iterate n times, update Fibonacci numbers
return a # return the n-th Fibonacci number
Complétion de code¶
%%ai
reset memory
Okay, memory reset. How can I help you now?
def prime_divloop(n): # version alpha
"return primes up to n"
primes = [2] if n > 1 else [] # setup list of known primes
for p in range(3, n+1, 2): # loop over odd numbers
for q in primes: # loop over known primes
pass
# TODO : find optimal stop condition when 'p' is not prime
# TODO : find optimal stop condition when 'p' is prime, then add 'p' to 'primes'
return primes # return list of primes
%%ai -f code
{ai.COCO} {_i}
EXAMPLES :
>>> prime_divloop(50)
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
def prime_divloop(n): # version finale
"""return primes up to n"""
primes = [2] if n > 1 else [] # setup list of known primes
for p in range(3, n + 1, 2): # loop over odd numbers
for q in primes: # loop over known primes
if p %% q == 0: break # if p is divisible by q, it is not prime; stop checking
if q * q > p: primes.append(p); break # if q*q > p, p is prime; add p to primes and stop checking
return primes # return list of primes
def prime_eratos(n): # version alpha
"""compute all prime numbers from 2 to n, using the sieve of Eratosthenes"""
primes, not_primes = [2] if n > 1 else [], set() # use list for primes, set for not_primes
for p in range(3, n+1, 2): # loop over odd numbers
if p in not_primes: continue # 'p' is not prime, so switch to next number
# TODO: append 'p' to 'primes' and add all odd multiples of 'p' into 'not_primes'
return primes # return list of primes
%%ai -f code
{ai.COCO} {_i}
EXAMPLES :
>>> prime_eratos(50)
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
def prime_eratos(n): # version finale
"""compute all prime numbers from 2 to n, using the sieve of Eratosthenes"""
primes, not_primes = [2] if n > 1 else [], set() # setup list for primes and set for composites
for p in range(3, n + 1, 2): # iterate over odd numbers starting from 3 up to n
if p in not_primes: continue # skip number if already marked as composite
primes.append(p) # add current odd number to list of primes
for multiple in range(p*p, n+1, 2*p): # iterate through odd multiples of p
not_primes.add(multiple) # mark current multiple as composite
return primes # return the list of found prime numbers