# Parameters
BATCH_MODE = "true"Code Interpreter : Exécution de Code avec OpenAI
Navigation : Index | << Précédent | Suivant >>
Le Code Interpreter est un outil intégré qui permet au modèle d’exécuter du code Python dans un environnement sandbox sécurisé. Il est particulièrement utile pour l’analyse de données, les calculs complexes, et la génération de visualisations.
Objectifs : - Activer et utiliser le code_interpreter - Analyser des données automatiquement - Générer des graphiques et visualisations - Manipuler des fichiers uploadés
Prérequis : Notebook 1 (OpenAI Intro)
Durée estimée : 55 minutes
Note d’exécution : ce notebook peut s’exécuter de deux façons. Via l’API OpenAI directe, l’Assistants API fournit un véritable Code Interpreter (sandbox Python côté serveur). Via un routeur tiers (OpenRouter), l’Assistants API n’étant pas supportée, le notebook bascule sur une alternative locale (pandas/numpy) qui reproduit les mêmes analyses. Les sorties committées reflètent le mode local. Pour activer le Code Interpreter réel, utilisez l’API OpenAI directe.
Références : le paradigme des LLM utilisant des outils externes (tool use) est formalisé par Schick et al. 2023, Toolformer: Language Models Can Teach Themselves to Use Tools, arXiv:2302.04761. Le Code Interpreter est documenté par OpenAI 2023, Assistants API — Code Interpreter, platform.openai.com/docs/assistants/tools/code-interpreter.
%pip install openai python-dotenv pandas matplotlib -q
from pathlib import Path
import os
from openai import OpenAI
from dotenv import load_dotenv
import pandas as pd
# Chargement robuste de la configuration .env
current_path = Path.cwd()
env_loaded = False
for _ in range(10):
env_path = current_path / ".env"
if env_path.exists():
load_dotenv(env_path)
print(f".env charge depuis: {env_path.name}")
env_loaded = True
break
if current_path.name == "GenAI" or len(current_path.parts) <= 1:
break
current_path = current_path.parent
if not env_loaded:
print("WARNING: .env non trouve, utilisation variables environnement")
# Initialiser le client OpenAI (detecte automatiquement OPENAI_API_KEY et OPENAI_BASE_URL)
client = OpenAI()
# Charger le modele depuis .env ou utiliser gpt-4.1-mini par defaut
DEFAULT_MODEL = os.getenv("OPENAI_MODEL", "gpt-5.6-luna")
BATCH_MODE = os.getenv("BATCH_MODE", "false").lower() == "true"
print("Client OpenAI initialise !")
print(f"Modele par defaut: {DEFAULT_MODEL}")
print(f"Mode: {'BATCH' if BATCH_MODE else 'INTERACTIF'}")Note: you may need to restart the kernel to use updated packages.
WARNING: .env non trouve, utilisation variables environnement
Client OpenAI initialise !
Modele par defaut: gpt-5.6-luna
Mode: INTERACTIF
Interprétation de l’initialisation
L’initialisation a chargé les composants suivants :
| Composant | Rôle |
|---|---|
openai |
Client API pour interagir avec OpenAI |
python-dotenv |
Chargement sécurisé des clés API depuis .env |
pandas |
Manipulation de données tabulaires |
matplotlib |
Génération de visualisations (graphiques) |
Variables d’environnement importantes : - OPENAI_API_KEY : Authentification API (obligatoire) - OPENAI_MODEL : Modèle par défaut (ex: gpt-5-mini) - BATCH_MODE : Mode non-interactif pour tests automatisés
Le message “Client OpenAI initialisé !” confirme que la connexion est établie et prête pour utiliser le Code Interpreter.
Configuration de l’environnement
Dans cette section, nous initialisons le client OpenAI avec les configurations nécessaires.
Variables d’environnement importantes : - OPENAI_API_KEY : Clé d’API OpenAI (obligatoire) - OPENAI_MODEL : Modèle par défaut (l’exécution committée utilise gpt-5.6-luna) - BATCH_MODE : Mode batch pour exécution automatisée sans interaction
Note : Le Code Interpreter nécessite un modèle supportant les outils avancés (de la famille GPT-4 / GPT-5).
Architecture du Code Interpreter
Le Code Interpreter fonctionne dans un environnement sandbox Python sécurisé qui offre :
Bibliothèques disponibles
- Analyse de données : pandas, numpy, scipy
- Visualisation : matplotlib, seaborn, plotly
- Machine Learning : scikit-learn
- Traitement d’images : PIL, opencv
- Mathématiques : sympy, statsmodels
Limitations importantes
- ❌ Pas d’accès réseau : impossible de télécharger des données externes
- ⏱️ Timeout : exécutions limitées dans le temps (environ 120 secondes)
- 💾 Stockage temporaire : les fichiers générés sont éphémères
- 🔒 Sandbox isolé : pas d’accès au système de fichiers externe
Cas d’usage typiques
- Analyse exploratoire de données (EDA)
- Création de graphiques et visualisations
- Calculs mathématiques complexes
- Transformation et nettoyage de données
- Génération de rapports automatisés
Activation du Code Interpreter
Le Code Interpreter est disponible uniquement via l’Assistants API (pas via Chat Completions).
Workflow typique : 1. Créer un Assistant avec tools=[{"type": "code_interpreter"}] 2. Uploader les fichiers nécessaires via Files API 3. Créer un Thread et envoyer des messages 4. Exécuter le Run et récupérer les résultats
Note importante : Contrairement aux functions/tools classiques de Chat Completions, le code_interpreter n’est pas directement accessible via client.chat.completions.create(). C’est une fonctionnalité exclusive de l’Assistants API.
Pourquoi utiliser l’Assistants API ?
Vous vous demandez peut-être : pourquoi cette complexité avec l’Assistants API au lieu de simplement utiliser Chat Completions ?
Réponse : Le Code Interpreter est un outil stateful qui nécessite : - Un environnement persistant pour exécuter du code - Une gestion de fichiers uploadés et générés - Un contexte partagé entre plusieurs exécutions - Des capacités sandbox sécurisées
L’Assistants API fournit cette infrastructure. Chat Completions est stateless (sans mémoire entre appels), donc inapproprié pour ce cas d’usage.
Analogie : - Chat Completions = conversation téléphonique (pas de mémoire) - Assistants API = session de travail collaborative (mémoire + ressources partagées)
# Note: Le Code Interpreter n'est pas disponible via Chat Completions
# Cette cellule démontre ce qui NE fonctionne PAS
print("=== Note importante sur Code Interpreter ===")
print()
print("Le code_interpreter n'est PAS disponible via Chat Completions:")
print(" tools=[{'type': 'code_interpreter'}] # ERREUR avec chat.completions.create")
print()
print("Seuls ces types d'outils sont supportés par Chat Completions:")
print(" - 'function' : Appel de fonctions personnalisées")
print(" - 'custom' : Outils personnalisés")
print()
print("Pour utiliser code_interpreter, utilisez l'Assistants API (voir cellules suivantes).")
print()
# Démonstration de ce qui fonctionne - calcul simple via le modèle lui-même
response = client.chat.completions.create(
model=DEFAULT_MODEL,
messages=[
{"role": "user", "content": "Calcule les 20 premiers nombres de Fibonacci et affiche-les sous forme de liste."}
],
max_completion_tokens=300
)
print("=== Alternative: Génération de code par le modèle (sans exécution) ===")
print(response.choices[0].message.content)=== Note importante sur Code Interpreter ===
Le code_interpreter n'est PAS disponible via Chat Completions:
tools=[{'type': 'code_interpreter'}] # ERREUR avec chat.completions.create
Seuls ces types d'outils sont supportés par Chat Completions:
- 'function' : Appel de fonctions personnalisées
- 'custom' : Outils personnalisés
Pour utiliser code_interpreter, utilisez l'Assistants API (voir cellules suivantes).
=== Alternative: Génération de code par le modèle (sans exécution) ===
Les 20 premiers nombres de Fibonacci (en commençant par 0) sont :
```text
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]
```
Interprétation de la démonstration
Cette démonstration illustre deux points importants :
1. Limitation de Chat Completions : - Le type 'code_interpreter' n’est PAS accepté dans tools=[] - Seuls 'function' et 'custom' sont supportés - Erreur typique : Invalid tool type: 'code_interpreter'
2. Alternative via génération de code : - Le modèle peut générer du code Python (comme démontré) - Mais il ne peut PAS exécuter ce code - C’est une limitation fondamentale de Chat Completions
Exemple de sortie : Le modèle génère le code pour calculer les nombres de Fibonacci, mais ne l’exécute pas. Vous devriez voir du code Python brut comme output, pas les résultats numériques.
Pourquoi cette architecture ? : - Chat Completions = stateless, rapide, conversationnel - Assistants API = stateful, avec ressources (fichiers, environnement d’exécution)
Pour exécuter réellement du code, passons à l’Assistants API dans les cellules suivantes.
Exercice 1 : Generation de code avec validation
L’objectif est de créer une fonction generate_and_validate qui demande au modèle de generer une fonction Python repondant a un cahier des charges, puis valide que le code genere est correct en l’executant avec des tests predefinis.
Indices : - # Étape 1 : Définir un prompt qui demande une fonction Python spécifique (ex: tri a bulles) - # Étape 2 : Appeler l’API Chat Completions pour generer le code - # Étape 3 : Extraire le bloc de code de la reponse (chercher les blocs python ...) - # Étape 4 : Executer le code extrait avec exec() et le tester avec des cas connus
# Exercice 1 : Generation de code avec validation
# TODO etudiant : Implementer generate_and_validate(spec, test_cases)
# - spec : description en francais de la fonction a generer (ex: "fonction qui inverse une chaine de caracteres")
# - test_cases : liste de tuples (input, expected_output) pour valider le code genere
# - Etape 1 : Construire un prompt qui demande UNIQUEMENT le code Python (pas d'explications)
# - Etape 2 : Appeler client.chat.completions.create() avec le prompt
# - Etape 3 : Extraire le code entre ```python et ``` avec une regex ou un split
# - Etape 4 : Executer le code avec exec() dans un namespace dedie, puis tester avec test_cases
# - Retourner {"code": code_extrait, "tests_passed": nb_passed, "tests_total": len(test_cases)}
def generate_and_validate(spec, test_cases):
return None # TODO etudiant : implementer
# Indice : utiliser re.search(r'```python\n(.*?)```', response, re.DOTALL) pour extraire le code
# Test :
# result = generate_and_validate(
# "Fonction is_palindrome(s) qui retourne True si s est un palindrome",
# [("radar", True), ("hello", False), ("", True), ("a", True)]
# )
# print(result)
print("Exercice a completer")Exercice a completer
Préparation du dataset de test
Avant de tester le Code Interpreter, créons un dataset réaliste de ventes sur 100 jours.
Caractéristiques du dataset : - 100 jours de ventes (Jan-Avril 2025) - Ventes aléatoires entre 100-500 avec une composante sinusoïdale (saisonnalité simulée) - 4 régions géographiques - 3 types de produits
Ce dataset servira de base pour démontrer les capacités d’analyse du Code Interpreter.
Analyse de données automatisée
Le Code Interpreter excelle dans l’analyse de datasets. Il peut : - Charger et explorer des fichiers CSV, Excel, JSON - Calculer des statistiques descriptives - Détecter des patterns et anomalies - Générer des rapports structurés
Commençons par créer un dataset de test représentant des ventes sur 100 jours.
# Créer un dataset de ventes
import pandas as pd
import numpy as np
np.random.seed(42)
dates = pd.date_range('2025-01-01', periods=100, freq='D')
data = {
'date': dates,
'ventes': np.random.randint(100, 500, 100) + np.sin(np.arange(100) * 0.1) * 50,
'region': np.random.choice(['Nord', 'Sud', 'Est', 'Ouest'], 100),
'produit': np.random.choice(['A', 'B', 'C'], 100)
}
df = pd.DataFrame(data)
df.to_csv('ventes_test.csv', index=False)
print(f"Dataset créé: {len(df)} lignes")
print("\nAperçu des données:")
print(df.head(10))
print("\nStatistiques de base:")
print(df.describe())Dataset créé: 100 lignes
Aperçu des données:
date ventes region produit
0 2025-01-01 202.000000 Nord B
1 2025-01-02 452.991671 Est B
2 2025-01-03 379.933467 Nord C
3 2025-01-04 220.776010 Nord B
4 2025-01-05 190.470917 Nord C
5 2025-01-06 311.971277 Est A
6 2025-01-07 148.232124 Nord C
7 2025-01-08 234.210884 Ouest B
8 2025-01-09 256.867805 Nord A
9 2025-01-10 353.166345 Ouest A
Statistiques de base:
date ventes
count 100 100.000000
mean 2025-02-19 12:00:00 321.043699
min 2025-01-01 00:00:00 70.315450
25% 2025-01-25 18:00:00 228.864279
50% 2025-02-19 12:00:00 334.475521
75% 2025-03-16 06:00:00 418.927476
max 2025-04-10 00:00:00 525.424820
std NaN 119.663838
Interprétation de la création du dataset
Le dataset a été créé avec succès. Analysons sa structure :
Dimensions : - 100 lignes (observations journalières) - 4 colonnes : date, ventes, region, produit
Caractéristiques des données : - Ventes : Valeurs entre ~70 et ~525 (moyenne ~321) - Composante aléatoire : np.random.randint(100, 500, 100) - Composante sinusoïdale : np.sin(...) * 50 simule une saisonnalité - Écart-type : ~120 indique une variabilité importante
Distribution géographique : - 4 régions équiprobables (Nord, Sud, Est, Ouest) - 3 types de produits (A, B, C)
Pourquoi cette structure ? : - Saisonnalité : Le terme sinusoïdal simule des cycles de vente réalistes - Randomisation : Reproduit la variabilité naturelle des ventes - Seed fixe (np.random.seed(42)) : Assure la reproductibilité des résultats
Ce dataset servira de base pour démontrer les capacités d’analyse du Code Interpreter dans les cellules suivantes.
Téléchargement et visualisation des images
Le Code Interpreter génère les graphiques comme fichiers PNG dans le sandbox. Ces images sont : - Accessibles via l’API avec leur file_id - Téléchargeables via client.files.content() - Temporaires : supprimés après un certain délai
Workflow de récupération : 1. Parcourir les messages du thread 2. Identifier les contenus de type image_file 3. Extraire le file_id 4. Télécharger avec files.content() 5. Sauvegarder localement
Astuce : Vous pouvez demander à l’assistant de créer plusieurs visualisations en un seul prompt pour gagner du temps.
Upload et analyse avec Code Interpreter
Pour analyser un fichier avec Code Interpreter : 1. Upload du fichier vers OpenAI avec purpose='assistants' 2. Passage de l’ID du fichier dans tool_resources 3. Prompt pour guider l’analyse
# Détection d'OpenRouter - L'Assistants API n'est pas supportée
import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)
# Vérifier si on utilise OpenRouter (qui ne supporte pas l'Assistants API)
base_url = os.getenv("OPENROUTER_BASE_URL", "https://openrouter.ai/api/v1")
is_openrouter = "openrouter" in base_url.lower()
if is_openrouter:
print("=== Mode OpenRouter détecté ===")
print("L'Assistants API (Code Interpreter) n'est PAS supportée par OpenRouter.")
print("Utilisation de l'alternative locale avec pandas/numpy.\n")
# Alternative locale : Analyse directe avec pandas
import pandas as pd
import numpy as np
# Charger le dataset
df = pd.read_csv('ventes_test.csv')
print("=== Analyse locale du dataset ===\n")
# 1. Statistiques descriptives
print("1. Statistiques descriptives:")
print(f" Moyenne des ventes: {df['ventes'].mean():.2f}")
print(f" Médiane des ventes: {df['ventes'].median():.2f}")
print(f" Écart-type: {df['ventes'].std():.2f}")
print(f" Min: {df['ventes'].min():.2f}, Max: {df['ventes'].max():.2f}")
# 2. Ventes par région
print("\n2. Ventes totales par région:")
ventes_region = df.groupby('region')['ventes'].sum().sort_values(ascending=False)
for region, total in ventes_region.items():
print(f" {region}: {total:.2f}")
# 3. Ventes par produit
print("\n3. Ventes totales par produit:")
ventes_produit = df.groupby('produit')['ventes'].sum().sort_values(ascending=False)
for produit, total in ventes_produit.items():
print(f" Produit {produit}: {total:.2f}")
# 4. Tendance temporelle
print("\n4. Tendance temporelle:")
df['date'] = pd.to_datetime(df['date'])
first_week = df.head(7)['ventes'].mean()
last_week = df.tail(7)['ventes'].mean()
variation = ((last_week - first_week) / first_week) * 100
print(f" Première semaine (moyenne): {first_week:.2f}")
print(f" Dernière semaine (moyenne): {last_week:.2f}")
print(f" Variation: {variation:+.1f}%")
print("\n=== Analyse terminée avec succès (mode local) ===")
print("\nNote: Pour utiliser le véritable Code Interpreter OpenAI,")
print("utilisez l'API OpenAI directe (pas OpenRouter).")
else:
# Code original pour l'API OpenAI directe
print("=== Mode API OpenAI directe ===")
print("Tentative d'utilisation de l'Assistants API...\n")
try:
with open('ventes_test.csv', 'rb') as f:
file = client.files.create(file=f, purpose='assistants')
print(f"Fichier uploadé: {file.id}")
assistant = client.beta.assistants.create(
name="Analyseur de ventes",
instructions="Tu es un expert en analyse de données.",
model=DEFAULT_MODEL,
tools=[{"type": "code_interpreter"}],
tool_resources={"code_interpreter": {"file_ids": [file.id]}}
)
thread = client.beta.threads.create()
message = client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content="Analyse ce fichier CSV de ventes et donne les statistiques."
)
run = client.beta.threads.runs.create_and_poll(
thread_id=thread.id,
assistant_id=assistant.id
)
if run.status == 'completed':
messages = client.beta.threads.messages.list(thread_id=thread.id)
for msg in messages:
if msg.role == "assistant":
for content in msg.content:
if hasattr(content, 'text'):
print(content.text.value)
# Nettoyage
client.beta.assistants.delete(assistant.id)
client.files.delete(file.id)
except Exception as e:
print(f"Erreur Assistants API: {e}")
print("L'analyse locale avec pandas est utilisée en fallback.")=== Mode OpenRouter détecté ===
L'Assistants API (Code Interpreter) n'est PAS supportée par OpenRouter.
Utilisation de l'alternative locale avec pandas/numpy.
=== Analyse locale du dataset ===
1. Statistiques descriptives:
Moyenne des ventes: 321.04
Médiane des ventes: 334.48
Écart-type: 119.66
Min: 70.32, Max: 525.42
2. Ventes totales par région:
Est: 11217.27
Nord: 8261.91
Ouest: 7342.53
Sud: 5282.66
3. Ventes totales par produit:
Produit C: 11443.71
Produit A: 11116.34
Produit B: 9544.32
4. Tendance temporelle:
Première semaine (moyenne): 272.34
Dernière semaine (moyenne): 292.03
Variation: +7.2%
=== Analyse terminée avec succès (mode local) ===
Note: Pour utiliser le véritable Code Interpreter OpenAI,
utilisez l'API OpenAI directe (pas OpenRouter).
Interprétation de l’analyse automatique
Les sorties committées ci-dessus sont produites en mode local (fallback pandas/numpy) : comme l’environnement actuel route les appels via OpenRouter, qui ne supporte pas l’Assistants API (Code Interpreter), le notebook bascule sur une alternative locale qui reproduit l’analyse que ferait le Code Interpreter. Le déroulé conceptuel est le suivant :
Étapes automatiques réalisées : 1. Chargement : Reconnaissance du format CSV et parsing automatique 2. Exploration : df.describe() pour statistiques descriptives 3. Agrégation : Groupement par région et par produit 4. Analyse temporelle : Comparaison première vs dernière semaine
Résultats attendus : - Statistiques globales : moyenne (~321), médiane, min/max, écart-type - Répartition par région : 4 totaux (un par région Nord/Sud/Est/Ouest) - Répartition par produit : 3 totaux (A, B, C) - Évolution temporelle : Tendance croissante/décroissante/stable
Avantages du Code Interpreter : - ✅ Zéro code manuel : Simple prompt en langage naturel - ✅ Analyse intelligente : Le modèle choisit les méthodes appropriées - ✅ Formatage structuré : Résultats présentés clairement - ✅ Reproductibilité : Même prompt → mêmes analyses
Note technique : l’output affiche === Analyse terminée avec succès (mode local) ===. Pour une exécution réelle dans le sandbox OpenAI (Code Interpreter), il faut utiliser l’API OpenAI directe plutôt que le routage OpenRouter.
Note importante (sandbox) : avec un véritable Code Interpreter OpenAI, le code généré par le modèle s’exécute dans un sandbox sécurisé et l’utilisateur ne voit que les résultats. Dans l’exécution committée ici (mode local fallback), le code pandas/numpy est visible dans la cellule source — le comportement observé est donc l’alternative locale, qui reproduit fidèlement les résultats qu’aurait produits le Code Interpreter.
Génération de visualisations
Le Code Interpreter peut créer des graphiques avec matplotlib, seaborn ou plotly. Les images générées sont accessibles via l’API.
# Génération de visualisations - Mode local (OpenRouter ne supporte pas l'Assistants API)
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use('Agg') # Backend non-interactif pour batch mode
if is_openrouter:
print("=== Génération de graphiques (mode local) ===\n")
# Graphique 1 : Ventes par région (barres)
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
ventes_region = df.groupby('region')['ventes'].sum().sort_values(ascending=False)
axes[0].bar(ventes_region.index, ventes_region.values, color=['#3498db', '#e74c3c', '#2ecc71', '#f39c12'])
axes[0].set_title('Ventes totales par région')
axes[0].set_xlabel('Région')
axes[0].set_ylabel('Ventes totales')
# Graphique 2 : Tendance temporelle avec moyenne mobile
df_sorted = df.sort_values('date')
df_sorted['ma_7j'] = df_sorted['ventes'].rolling(window=7, min_periods=1).mean()
axes[1].plot(df_sorted['date'], df_sorted['ventes'], alpha=0.3, label='Ventes brutes')
axes[1].plot(df_sorted['date'], df_sorted['ma_7j'], color='red', linewidth=2, label='Moyenne mobile 7j')
axes[1].set_title('Tendance des ventes')
axes[1].set_xlabel('Date')
axes[1].set_ylabel('Ventes')
axes[1].legend()
axes[1].tick_params(axis='x', rotation=45)
plt.tight_layout()
plt.savefig('graphique_analyse_ventes.png', dpi=100, bbox_inches='tight')
print("Graphiques sauvegardés: graphique_analyse_ventes.png")
plt.close()
print("\nNote: Ces graphiques sont générés localement avec matplotlib.")
print("Le Code Interpreter OpenAI génèrerait des graphiques similaires dans son sandbox.")
else:
# Code original pour l'API OpenAI directe avec Assistants
print("=== Génération de graphiques via Code Interpreter ===")
try:
message = client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content="Crée 2 graphiques: ventes par région (barres) et tendance avec moyenne mobile 7j."
)
run = client.beta.threads.runs.create_and_poll(
thread_id=thread.id,
assistant_id=assistant.id
)
if run.status == 'completed':
print("Graphiques générés avec succès via Code Interpreter.")
except Exception as e:
print(f"Erreur: {e}")=== Génération de graphiques (mode local) ===
Graphiques sauvegardés: graphique_analyse_ventes.png
Note: Ces graphiques sont générés localement avec matplotlib.
Le Code Interpreter OpenAI génèrerait des graphiques similaires dans son sandbox.
Exercice 2 : Visualisation personnalisee avec detection d’anomalies
L’objectif est de créer une fonction qui genere un graphique en deux sous-figures : un histogramme avec la distribution des ventes et un boxplot par region, avec mise en evidence des outliers.
Indices : - # Étape 1 : Créer la fonction plot_sales_analysis(df, value_col, group_col) - # Étape 2 : Utiliser plt.subplots(1, 2) pour les deux graphiques - # Étape 3 : Gauche : histogramme avec ax.hist() + lignes verticales pour moyenne et mediane - # Étape 4 : Droite : boxplot avec ax.boxplot() par groupe pour identifier les outliers
# Exercice 2 : Visualisation personnalisee avec detection d'anomalies
# TODO etudiant : Implementer plot_sales_analysis(df, value_col, group_col)
# - Sous-figure 1 : histogramme de value_col avec lignes verticales moyenne (rouge) et mediane (bleu)
# - Sous-figure 2 : boxplot de value_col par group_col (pour detecter les outliers)
# - Ajouter titre, legendes et labels
# - Sauvegarder en PNG et afficher
def plot_sales_analysis(df, value_col, group_col):
pass # TODO etudiant : implementer
# Indice : utiliser plt.subplots(1, 2, figsize=(12, 5))
# Test :
# np.random.seed(42)
# test_df = pd.DataFrame({
# 'ventes': np.random.randint(100, 500, 100) + np.sin(np.arange(100)*0.1)*50,
# 'region': np.random.choice(['Nord', 'Sud', 'Est', 'Ouest'], 100)
# })
# plot_sales_analysis(test_df, 'ventes', 'region')
print("Exercice a completer")Exercice a completer
Interprétation de la génération de visualisations
Le Code Interpreter a créé deux graphiques automatiquement :
Graphique 1 : Ventes par région (barres) : - Visualisation comparative des performances régionales - Permet d’identifier rapidement les régions sous-performantes ou sur-performantes - Format idéal pour présentations (facile à lire)
Graphique 2 : Tendance temporelle avec moyenne mobile : - Lissage de la courbe sur 7 jours pour éliminer le bruit - Révèle la tendance de fond (croissance, stabilité, déclin) - La moyenne mobile est calculée automatiquement par le Code Interpreter
Processus de récupération des images : 1. Parcourir les messages du thread 2. Identifier les contenus de type image_file 3. Extraire le file_id 4. Télécharger via client.files.content(file_id) 5. Sauvegarder localement en .png
Note importante : Les images sont temporaires dans le sandbox OpenAI. Il faut les télécharger immédiatement après génération, car elles peuvent être supprimées après un certain délai.
Cas d’usage typiques : - Rapports automatisés (génération de graphiques standards) - Dashboards dynamiques (visualisations basées sur données en temps réel) - Exploration de données (essayer différents types de graphiques rapidement)
Calculs mathématiques complexes
Le Code Interpreter peut résoudre des problèmes mathématiques avancés : - Systèmes d’équations linéaires - Calcul matriciel - Intégration et dérivation symbolique - Optimisation numérique
# Calculs mathématiques - Mode local (OpenRouter ne supporte pas l'Assistants API)
import numpy as np
if is_openrouter:
print("=== Résolution système d'équations (mode local) ===\n")
# Système d'équations:
# 2x + 3y - z = 1
# 4x + y + 2z = 2
# -x + 2y + 3z = 3
A = np.array([
[2, 3, -1],
[4, 1, 2],
[-1, 2, 3]
])
b = np.array([1, 2, 3])
# Résolution
solution = np.linalg.solve(A, b)
print("Système d'équations:")
print(" 2x + 3y - z = 1")
print(" 4x + y + 2z = 2")
print(" -x + 2y + 3z = 3")
print(f"\nSolution:")
print(f" x = {solution[0]:.6f}")
print(f" y = {solution[1]:.6f}")
print(f" z = {solution[2]:.6f}")
# Vérification
verification = A @ solution
print(f"\nVérification (A @ x):")
print(f" {verification}")
print(f" b = {b}")
print(f" Erreur: {np.abs(verification - b).max():.2e}")
print("\n=== Résolution terminée avec succès (mode local) ===")
else:
# Code original pour l'API OpenAI directe
print("=== Résolution via Code Interpreter ===")
try:
math_thread = client.beta.threads.create()
message = client.beta.threads.messages.create(
thread_id=math_thread.id,
role="user",
content="Résous ce système: 2x+3y-z=1, 4x+y+2z=2, -x+2y+3z=3"
)
run = client.beta.threads.runs.create_and_poll(
thread_id=math_thread.id,
assistant_id=assistant.id
)
if run.status == 'completed':
messages = client.beta.threads.messages.list(thread_id=math_thread.id)
for msg in messages:
if msg.role == "assistant":
for content in msg.content:
if hasattr(content, 'text'):
print(content.text.value)
except Exception as e:
print(f"Erreur: {e}")=== Résolution système d'équations (mode local) ===
Système d'équations:
2x + 3y - z = 1
4x + y + 2z = 2
-x + 2y + 3z = 3
Solution:
x = 0.037736
y = 0.528302
z = 0.660377
Vérification (A @ x):
[1. 2. 3.]
b = [1 2 3]
Erreur: 4.44e-16
=== Résolution terminée avec succès (mode local) ===
Interprétation de la résolution du système d’équations
Le Code Interpreter a résolu le système d’équations linéaires automatiquement. Voici ce qui s’est passé :
Système résolu :
2x + 3y - z = 1
4x + y + 2z = 2
-x + 2y + 3z = 3
Méthode utilisée : - Représentation matricielle : Ax = b - Résolution avec numpy.linalg.solve() (inversion matricielle ou décomposition LU) - Vérification : A @ x ≈ b (produit matriciel)
Résultats attendus : - Trois valeurs numériques pour x, y, z - Précision machine (~1e-15 pour la vérification)
Pourquoi utiliser le Code Interpreter ? : - ✅ Pas de setup manuel : numpy déjà disponible dans le sandbox - ✅ Code généré automatiquement : Le modèle écrit le code correct - ✅ Validation incluse : Vérification automatique de la solution
Applications pratiques : - Économie : Équilibres de marché (offre/demande multi-produits) - Physique : Lois de Kirchhoff pour circuits électriques - Chimie : Équilibres de réactions chimiques - Ingénierie : Analyse de structures (forces, contraintes) - Optimisation : Points critiques
Alternative pour systèmes complexes : Pour des systèmes non-linéaires, utiliser scipy.optimize.fsolve() ou sympy.solve().
Exemple avancé : Analyse statistique
Testons une analyse plus approfondie avec tests d’hypothèses et corrélations.
# Analyse statistique avancée - Mode local
from scipy import stats
if is_openrouter:
print("=== Analyse statistique avancée (mode local) ===\n")
# 1. Test de normalité (Shapiro-Wilk)
stat, p_shapiro = stats.shapiro(df['ventes'])
print(f"1. Test de Shapiro-Wilk (normalité):")
print(f" Statistique: {stat:.4f}, p-value: {p_shapiro:.4f}")
print(f" Conclusion: {'Distribution normale' if p_shapiro > 0.05 else 'Distribution non-normale'}")
# 2. ANOVA (comparaison régions)
regions = [group['ventes'].values for name, group in df.groupby('region')]
stat, p_anova = stats.f_oneway(*regions)
print(f"\n2. ANOVA (comparaison régions):")
print(f" F-statistique: {stat:.4f}, p-value: {p_anova:.4f}")
print(f" Conclusion: {'Pas de différence significative' if p_anova > 0.05 else 'Différences significatives entre régions'}")
# 3. Test du Chi-2 (indépendance région/produit)
contingency = pd.crosstab(df['region'], df['produit'])
stat, p_chi2, dof, expected = stats.chi2_contingency(contingency)
print(f"\n3. Test du Chi-2 (indépendance région/produit):")
print(f" Chi-2: {stat:.4f}, p-value: {p_chi2:.4f}")
print(f" Conclusion: {'Région et produit indépendants' if p_chi2 > 0.05 else 'Dépendance détectée'}")
# 4. Corrélation temporelle
df_sorted = df.sort_values('date')
jour_numero = np.arange(len(df_sorted))
r, p_corr = stats.pearsonr(jour_numero, df_sorted['ventes'])
print(f"\n4. Corrélation temporelle (jour vs ventes):")
print(f" Coefficient r: {r:.4f}, p-value: {p_corr:.4f}")
print(f" Conclusion: {'Pas de tendance' if abs(r) < 0.3 else ('Tendance positive' if r > 0 else 'Tendance négative')}")
print("\n=== Analyse statistique terminée (mode local) ===")
else:
print("=== Analyse statistique via Code Interpreter ===")
try:
message = client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content="Effectue une analyse statistique: Shapiro-Wilk, ANOVA, Chi-2, corrélation."
)
run = client.beta.threads.runs.create_and_poll(
thread_id=thread.id,
assistant_id=assistant.id
)
if run.status == 'completed':
messages = client.beta.threads.messages.list(thread_id=thread.id)
for msg in messages:
if msg.role == "assistant":
for content in msg.content:
if hasattr(content, 'text'):
print(content.text.value)
except Exception as e:
print(f"Erreur: {e}")=== Analyse statistique avancée (mode local) ===
1. Test de Shapiro-Wilk (normalité):
Statistique: 0.9649, p-value: 0.0091
Conclusion: Distribution non-normale
2. ANOVA (comparaison régions):
F-statistique: 0.6085, p-value: 0.6111
Conclusion: Pas de différence significative
3. Test du Chi-2 (indépendance région/produit):
Chi-2: 8.7535, p-value: 0.1879
Conclusion: Région et produit indépendants
4. Corrélation temporelle (jour vs ventes):
Coefficient r: 0.0775, p-value: 0.4436
Conclusion: Pas de tendance
=== Analyse statistique terminée (mode local) ===
Exercice 3 : Analyse statistique personnalisee
L’objectif est d’implementer une fonction analyze_dataframe qui prend un DataFrame et retourne un rapport statistique complet avec interpretation automatique.
Indices : - # Étape 1 : Créer la fonction qui accepte un DataFrame et une liste de colonnes numériques - # Étape 2 : Pour chaque colonne, calculer : moyenne, mediane, ecart-type, min, max, nb outliers (> 2 sigma) - # Étape 3 : Retourner un DataFrame recapitulatif avec une ligne par colonne analysee - # Étape 4 : Ajouter une colonne “interpretation” qui indique si la distribution est symetrique (moyenne proche de mediane)
# Exercice 3 : Analyse statistique personnalisee
# TODO etudiant : Implementer analyze_dataframe(df, columns)
# - Pour chaque colonne numerique : moyenne, mediane, ecart-type, min, max
# - Compter les outliers (valeurs > moyenne + 2*ecart_type ou < moyenne - 2*ecart_type)
# - Ajouter une interpretation : "symetrique" si |moyenne - mediane| < 0.1 * ecart_type, sinon "asymetrique"
# - Retourner un DataFrame avec une ligne par colonne analysee
def analyze_dataframe(df, columns=None):
return None # TODO etudiant : implementer
# Test avec le dataset de ventes :
# np.random.seed(42)
# test_df = pd.DataFrame({
# 'ventes': np.random.randint(100, 500, 100),
# 'temperature': np.random.normal(20, 5, 100)
# })
# rapport = analyze_dataframe(test_df, ['ventes', 'temperature'])
# print(rapport)
print("Exercice a completer")Exercice a completer
Interprétation de l’analyse statistique avancée
Le Code Interpreter a effectué une batterie complète de tests statistiques. Décryptons les résultats :
1. Test de Shapiro-Wilk (normalité) : - Hypothèse nulle (H0) : Les ventes suivent une distribution normale - Seuil : p > 0.05 → accepter H0 (distribution normale) - Interprétation : Détermine si on peut utiliser des tests paramétriques (t-test, ANOVA) - Si p < 0.05 : Distribution non-normale → utiliser tests non-paramétriques (Mann-Whitney, Kruskal-Wallis)
2. ANOVA (comparaison entre régions) : - Hypothèse nulle (H0) : Moyennes identiques entre toutes les régions - Seuil : p < 0.05 → rejeter H0 (différences significatives) - Utilité : Identifier si certaines régions performent mieux/moins bien - Post-hoc : Si significatif, faire des tests par paires (Tukey HSD)
3. Test du Chi-2 (indépendance région/produit) : - Hypothèse nulle (H0) : Région et produit sont indépendants - Seuil : p < 0.05 → rejeter H0 (dépendance détectée) - Interprétation : Certaines régions préfèrent certains produits - Application : Ciblage marketing, gestion des stocks par région
4. Corrélation temporelle (Pearson) : - Coefficient r : Entre -1 (anticorrélation) et +1 (corrélation parfaite) - Interprétation : - |r| > 0.7 : Forte corrélation - 0.3 < |r| < 0.7 : Corrélation modérée - |r| < 0.3 : Faible corrélation - Usage : Détecter tendances temporelles (croissance, saisonnalité)
Niveau de confiance : - α = 0.05 (95% de confiance) est standard en sciences sociales - Pour décisions critiques, utiliser α = 0.01 (99%) ou α = 0.001 (99.9%)
Automatisation clé : Le Code Interpreter choisit automatiquement les tests appropriés selon les données.
Limitations et bonnes pratiques
Limitations techniques
| Limitation | Impact | Solution |
|---|---|---|
| Pas d’accès réseau | Impossible de télécharger des données externes | Uploader tous les fichiers nécessaires |
| Timeout ~120s | Calculs longs peuvent échouer | Découper en étapes plus petites |
| Bibliothèques limitées | Certains packages spécialisés absents | Utiliser les alternatives standard |
| Stockage temporaire | Fichiers supprimés après session | Télécharger immédiatement les résultats |
| Pas de GPU | Pas d’accélération matérielle | Limiter la taille des modèles ML |
Bonnes pratiques
- Vérifier les fichiers uploadés : S’assurer que les données sont complètes
- Prompts précis : Décrire exactement l’analyse souhaitée
- Télécharger rapidement : Récupérer les images/fichiers générés avant expiration
- Validation externe : Vérifier les résultats critiques manuellement
- Gérer les erreurs : Prévoir des fallbacks si le code échoue
Nettoyage des ressources
Important : supprimer les fichiers et assistants pour éviter les coûts de stockage.
# Nettoyage des ressources
import os
print("=== Nettoyage ===")
# Supprimer le fichier local
if os.path.exists('ventes_test.csv'):
os.remove('ventes_test.csv')
print("Fichier ventes_test.csv supprimé")
# Supprimer les graphiques générés
for filename in os.listdir('.'):
if filename.startswith('graphique_') and filename.endswith('.png'):
os.remove(filename)
print(f"Image {filename} supprimée")
# Si mode OpenAI direct, nettoyer les ressources cloud
if not is_openrouter:
try:
if 'assistant' in dir():
client.beta.assistants.delete(assistant.id)
print(f"Assistant supprimé")
if 'file' in dir():
client.files.delete(file.id)
print(f"Fichier cloud supprimé")
except Exception as e:
print(f"Note: {e}")
print("\nNettoyage terminé !")=== Nettoyage ===
Fichier ventes_test.csv supprimé
Image graphique_analyse_ventes.png supprimée
Nettoyage terminé !
Interprétation du nettoyage
Le nettoyage a été effectué avec succès. Voici ce qui a été supprimé :
Fichiers locaux (l’output committé montre uniquement le nettoyage local, car l’exécution s’est faite en mode local — aucun assistant ni fichier côté serveur OpenAI n’a été créé dans cette session) : - ✅ Dataset : ventes_test.csv supprimé - ✅ Images générées : Tous les fichiers graphique_*.png supprimés
Pourquoi nettoyer ? : 1. Coûts : Les fichiers stockés sur OpenAI peuvent entraîner des frais 2. Espace disque : Éviter l’accumulation de fichiers temporaires 3. Sécurité : Supprimer les données sensibles après utilisation 4. Bonne pratique : Toujours nettoyer après les tests/démonstrations
Note importante : Dans un environnement de production, vous voudriez peut-être : - Sauvegarder les résultats importants avant de nettoyer - Archiver les images générées dans un dossier dédié - Logger les IDs des ressources supprimées pour audit
Statut final : Toutes les ressources temporaires ont été nettoyées. L’environnement est prêt pour une nouvelle session.
Conclusion et exercices
Ce que nous avons appris
Le Code Interpreter est un outil puissant pour : - ✅ Analyse de données : Statistiques, exploration, nettoyage - ✅ Visualisations : Graphiques automatiques avec matplotlib/seaborn - ✅ Calculs complexes : Mathématiques, algèbre linéaire, optimisation - ✅ Automatisation : Génération de rapports structurés
Cas d’usage professionnels
- Business Intelligence : Analyse de KPIs, reporting automatisé
- Data Science : EDA rapide, feature engineering, preprocessing
- Finance : Calculs actuariels, analyse de risque, backtesting
- Recherche : Validation d’hypothèses, visualisation de résultats
- Éducation : Démonstrations mathématiques, correction automatique
Exercices suggérés
Exercice 1 : Analyse de timeseries
Créez un dataset de températures quotidiennes et demandez au Code Interpreter de : - Détecter les anomalies (outliers) - Calculer la moyenne mobile sur 7 jours - Prédire les 7 prochains jours avec régression linéaire
Exercice 2 : Optimisation
Résolvez un problème d’optimisation linéaire avec scipy :
Maximiser: 3x + 2y
Contraintes:
x + y <= 4
2x + y <= 5
x, y >= 0
Exercice 3 : Machine Learning basique
Uploadez un dataset de classification (iris, wine) et demandez : - Entraînement d’un modèle k-NN - Évaluation avec matrice de confusion - Visualisation des frontières de décision
Ressources complémentaires
- OpenAI Code Interpreter Guide
- Assistants API Reference
- Notebook suivant : 08_Reasoning_Models.ipynb (génération JSON validée)