Code Interpreter : Exécution de Code avec OpenAI

# Parameters
BATCH_MODE = "true"

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

  1. Analyse exploratoire de données (EDA)
  2. Création de graphiques et visualisations
  3. Calculs mathématiques complexes
  4. Transformation et nettoyage de données
  5. 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

  1. Vérifier les fichiers uploadés : S’assurer que les données sont complètes
  2. Prompts précis : Décrire exactement l’analyse souhaitée
  3. Télécharger rapidement : Récupérer les images/fichiers générés avant expiration
  4. Validation externe : Vérifier les résultats critiques manuellement
  5. 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

  1. Business Intelligence : Analyse de KPIs, reporting automatisé
  2. Data Science : EDA rapide, feature engineering, preprocessing
  3. Finance : Calculs actuariels, analyse de risque, backtesting
  4. Recherche : Validation d’hypothèses, visualisation de résultats
  5. É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

Retour au sommet