Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
228 changes: 191 additions & 37 deletions MyIA.AI.Notebooks/GenAI/Texte/02_PromptEngineering.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@
"output_type": "stream",
"text": [
".env charge depuis: .env\n",
"Configuration : repli autonome du carnet | fournisseur : openai | source de la cle : env:OPENAI_API_KEY\n",
"Modele par defaut : gpt-5-mini\n",
"Mode: BATCH\n"
]
}
Expand Down Expand Up @@ -224,12 +226,149 @@
" break\n",
" current_path = current_path.parent\n",
"if not env_loaded:\n",
" print(\"WARNING: .env non trouve, utilisation variables environnement\")\n",
" print(\"Aucun .env trouve : la cle vient de l'environnement ou des Secrets Colab.\")\n",
"\n",
"# --- Un seul point de resolution de la cle ---------------------------------\n",
"# Ordre de resolution : **par fournisseur d'abord**, puis par source dans le\n",
"# fournisseur -- la cle OpenAI (environnement, puis Secret Colab), puis la cle\n",
"# OpenRouter (environnement, puis Secret Colab), qui implique son adresse de\n",
"# base et un modele ouvert sur cette cle.\n",
"#\n",
"# L'organe de la serie est GenAI/shared/helpers/genai_helpers.py : meme\n",
"# contrat, memes messages d'aide. Un carnet telecharge seul dans Colab ne\n",
"# l'a pas sous la main, donc un repli autonome reprend ce contrat ci-dessous.\n",
"# Les deux doivent choisir le MEME fournisseur quand ils sont tous deux\n",
"# installes : c'est l'ordre par fournisseur (et non par emplacement) qui\n",
"# l'assure. La parite est verifiee hors reseau par\n",
"# shared/helpers/tests/test_colab_config_contract.py.\n",
"AIDE_CLE = \"\"\"Aucune cle d'API n'a ete trouvee.\n",
"\n",
"En local (Jupyter, VS Code) :\n",
" 1. copiez MyIA.AI.Notebooks/GenAI/.env.example en .env, dans le dossier du\n",
" carnet ou dans un dossier parent ;\n",
" 2. remplacez-y la valeur de OPENAI_API_KEY par la cle fournie en cours ;\n",
" 3. relancez la cellule.\n",
"\n",
"Sous Google Colab, il n'y a pas de fichier .env : utilisez les Secrets du\n",
"carnet (icone cle dans la barre de gauche) :\n",
" 1. ajoutez un secret nomme OPENAI_API_KEY -- ou OPENROUTER_API_KEY si la cle\n",
" qui vous a ete remise est une cle OpenRouter ;\n",
" 2. basculez l'interrupteur « Acces au notebook » sur ON ;\n",
" 3. relancez la cellule, sans redemarrer la session.\n",
"\n",
"Ne collez jamais une cle dans une cellule : le carnet partirait avec elle dans\n",
"un commit, et le depot est public.\"\"\"\n",
"\n",
"\n",
"def _lire_secret_colab(nom):\n",
" \"\"\"Lit un Secret de notebook Colab ; None hors Colab ou si absent.\"\"\"\n",
" try:\n",
" from google.colab import userdata\n",
" except Exception:\n",
" return None\n",
" try:\n",
" valeur = userdata.get(nom)\n",
" except Exception:\n",
" return None\n",
" return valeur.strip() if isinstance(valeur, str) and valeur.strip() else None\n",
"\n",
"\n",
"def _resoudre_config_autonome():\n",
" \"\"\"Repli autonome du carnet seul : meme contrat que l'organe de la serie.\n",
"\n",
" Appele quand l'organe n'est pas importable (carnet telecharge seul) ou\n",
" quand il echoue. Les valeurs par defaut sont des NOMS de modeles, jamais\n",
" des cles : la cle du module reste celle de l'environnement ou du Secret.\n",
" \"\"\"\n",
" adresse_openrouter = \"https://openrouter.ai/api/v1\"\n",
"\n",
" def _lire(nom):\n",
" \"\"\"Une cle, par fournisseur : l'environnement d'abord, puis le Secret\n",
" Colab. Meme ordre que `_read_key` de l'organe.\"\"\"\n",
" valeur = os.getenv(nom)\n",
" if valeur and valeur.strip():\n",
" return valeur.strip(), \"env:%s\" % nom\n",
" valeur = _lire_secret_colab(nom)\n",
" if valeur:\n",
" return valeur, \"colab:%s\" % nom\n",
" return None, None\n",
"\n",
" # Par fournisseur, puis par source : la cle OpenAI (env, puis Colab)\n",
" # avant la cle OpenRouter (env, puis Colab). Un ordre par emplacement\n",
" # choisirait un fournisseur different selon que l'organe soit importe.\n",
" cle, source = _lire(\"OPENAI_API_KEY\")\n",
" if not cle:\n",
" cle, source = _lire(\"OPENROUTER_API_KEY\")\n",
" if not cle:\n",
" raise ValueError(AIDE_CLE)\n",
" adresse = os.getenv(\"OPENAI_BASE_URL\")\n",
" if adresse:\n",
" fournisseur = \"openrouter\" if \"openrouter\" in adresse.lower() else \"openai\"\n",
" elif source.endswith(\"OPENROUTER_API_KEY\"):\n",
" adresse, fournisseur = adresse_openrouter, \"openrouter\"\n",
" else:\n",
" fournisseur = \"openai\"\n",
" if fournisseur == \"openrouter\":\n",
" modele = os.getenv(\"OPENAI_MODEL\") or \"qwen/qwen3.8-flash\"\n",
" raisonnement = os.getenv(\"OPENAI_REASONING_MODEL\") or \"deepseek/deepseek-v4.1-flash\"\n",
" else:\n",
" modele = os.getenv(\"OPENAI_MODEL\") or \"gpt-5-mini\"\n",
" raisonnement = os.getenv(\"OPENAI_REASONING_MODEL\") or \"gpt-5.6-sol\"\n",
" return {\n",
" \"api_key\": cle,\n",
" \"base_url\": adresse,\n",
" \"model\": modele,\n",
" \"reasoning_model\": raisonnement,\n",
" \"provider\": fournisseur,\n",
" \"key_source\": source,\n",
" }\n",
"\n",
"# Recupere la cle d'API\n",
"api_key = os.getenv(\"OPENAI_API_KEY\")\n",
"if not api_key:\n",
" raise ValueError(\"Cle API introuvable. Verifie ton fichier .env.\")\n",
"\n",
"# L'organe de la serie d'abord : il porte deja ce contrat.\n",
"for _base in [Path.cwd(), *Path.cwd().parents]:\n",
" if (_base / \"shared\" / \"helpers\" / \"genai_helpers.py\").exists():\n",
" if str(_base / \"shared\" / \"helpers\") not in sys.path:\n",
" sys.path.insert(0, str(_base / \"shared\" / \"helpers\"))\n",
" break\n",
"\n",
"config = None\n",
"organe = \"repli autonome du carnet\"\n",
"try:\n",
" from genai_helpers import resolve_openai_config, apply_openai_environment\n",
"except Exception:\n",
" resolve_openai_config = None\n",
" apply_openai_environment = None\n",
"\n",
"if resolve_openai_config is not None:\n",
" try:\n",
" _cfg = resolve_openai_config(required=True)\n",
" apply_openai_environment(_cfg)\n",
" config = {\n",
" \"api_key\": _cfg.api_key,\n",
" \"base_url\": _cfg.base_url,\n",
" \"model\": _cfg.model,\n",
" \"reasoning_model\": _cfg.reasoning_model,\n",
" \"provider\": _cfg.provider,\n",
" \"key_source\": _cfg.key_source,\n",
" }\n",
" organe = \"genai_helpers (GenAI/shared/helpers)\"\n",
" except Exception as exc:\n",
" if type(exc).__name__ == \"MissingApiKeyError\":\n",
" raise\n",
" organe = \"repli autonome du carnet (organe indisponible : %s)\" % type(exc).__name__\n",
"\n",
"if config is None:\n",
" config = _resoudre_config_autonome()\n",
" os.environ.setdefault(\"OPENAI_API_KEY\", config[\"api_key\"])\n",
" if config[\"base_url\"]:\n",
" os.environ.setdefault(\"OPENAI_BASE_URL\", config[\"base_url\"])\n",
" os.environ.setdefault(\"OPENAI_MODEL\", config[\"model\"])\n",
" os.environ.setdefault(\"OPENAI_REASONING_MODEL\", config[\"reasoning_model\"])\n",
"\n",
"api_key = config[\"api_key\"]\n",
"print(\"Configuration : %s | fournisseur : %s | source de la cle : %s\"\n",
" % (organe, config[\"provider\"], config[\"key_source\"]))\n",
"print(\"Modele par defaut : %s\" % config[\"model\"])\n",
"\n",
"# Mode batch pour execution non-interactive (Papermill, tests automatises)\n",
"def is_interactive():\n",
Expand Down Expand Up @@ -259,6 +398,19 @@
"\n",
"Avant de commencer les expérimentations, nous devons configurer l'accès à l'API OpenAI et gérer les modes d'exécution.\n",
"\n",
"### Où se trouve la clé ?\n",
"\n",
"La clé se cherche toujours au même endroit, dans cet ordre : la variable d'environnement `OPENAI_API_KEY`, puis un **Secret Colab** (`google.colab.userdata`), puis la clé `OPENROUTER_API_KEY` remise en cours — celle-ci est une clé **OpenRouter**, et le carnet bascule alors sur l'adresse OpenRouter avec un modèle ouvert (`qwen/qwen3.8-flash`).\n",
"\n",
"| Où vous travaillez | Comment faire |\n",
"|---|---|\n",
"| **Local** (Jupyter, VS Code) | copiez `MyIA.AI.Notebooks/GenAI/.env.example` en `.env` (dans le dossier du carnet ou dans un dossier parent) et remplacez `OPENAI_API_KEY` par la clé du cours |\n",
"| **Google Colab** | pas de `.env` : icône clé → *Secrets* → ajoutez `OPENAI_API_KEY` (ou `OPENROUTER_API_KEY`), **basculez « Accès au notebook » sur ON**, puis relancez la cellule |\n",
"\n",
"La cellule de configuration affiche la source de la clé qu'elle a retenue (`env:…`, `colab:…`) et le fournisseur choisi — **jamais la clé elle-même**. Si aucune clé n'est trouvée, le message d'erreur donne la marche à suivre dans les deux cas.\n",
"\n",
"**Attention :** ne collez jamais une clé dans une cellule — le carnet partirait avec elle dans un commit, et le dépôt est public.\n",
"\n",
"### Mode batch vs mode interactif\n",
"\n",
"Le notebook supporte deux modes d'exécution :\n",
Expand Down Expand Up @@ -290,7 +442,7 @@
"- `max_tokens` : Longueur maximale de la réponse (évite les réponses trop longues et coûteuses)\n",
"- `temperature` : Contrôle la créativité (0.0 = déterministe, 2.0 = très créatif)\n",
"\n",
"Par défaut, nous utilisons `gpt-5-mini` configuré dans le fichier `.env`."
"Par défaut, le carnet utilise le modèle **résolu par la configuration** : `gpt-5-mini` en local, ou un modèle ouvert (`qwen/qwen3.8-flash`) si la clé du cours est une clé OpenRouter."
]
},
{
Expand All @@ -311,15 +463,9 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Client OpenAI initialisé avec succès !"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"Modèle par défaut: gpt-5-mini\n"
"Client OpenAI initialisé avec succès !\n",
"Modèle par défaut: gpt-5-mini\n",
"Fournisseur: openai\n"
]
}
],
Expand All @@ -331,17 +477,21 @@
"import openai\n",
"from openai import OpenAI\n",
"\n",
"# Charger le modèle depuis .env ou utiliser gpt-5-mini par défaut\n",
"DEFAULT_MODEL = os.getenv(\"OPENAI_MODEL\", \"gpt-5-mini\")\n",
"# Modele par defaut : celui resolu par la configuration (variable\n",
"# d'environnement, Secret Colab, ou cle OpenRouter du module).\n",
"DEFAULT_MODEL = config[\"model\"]\n",
"MODEL_NAME = DEFAULT_MODEL\n",
"\n",
"# Instanciation du client\n",
"# Instanciation du client. base_url vaut None en local (adresse OpenAI) et\n",
"# l'adresse OpenRouter quand la cle du module est une cle OpenRouter.\n",
"client = OpenAI(\n",
" api_key=api_key,\n",
" api_key=config[\"api_key\"],\n",
" base_url=config[\"base_url\"],\n",
")\n",
"\n",
"print(\"Client OpenAI initialisé avec succès !\")\n",
"print(f\"Modèle par défaut: {MODEL_NAME}\")"
"print(f\"Modèle par défaut: {MODEL_NAME}\")\n",
"print(f\"Fournisseur: {config['provider']}\")"
]
},
{
Expand Down Expand Up @@ -1326,26 +1476,30 @@
"name": "stdout",
"output_type": "stream",
"text": [
"On suppose que les trains vont l’un vers l’autre.\n",
"\n",
"1) Distance parcourue par le train partant de Paris entre 8h00 et 9h00 :\n",
"- Vitesse = 120 km/h, durée = 1 h → distance = 120 × 1 = 120 km.\n",
"1) Distance parcourue par le train de Paris avant le départ du train de Lyon. \n",
"Le train de Paris part à 8h00 et le train de Lyon part à 9h00, donc le train de Paris roule pendant 1 heure avant 9h00. \n",
"Vitesse du train de Paris = 120 km/h. \n",
"Distance parcourue en 1 h = 120 km/h × 1 h = 120 km.\n",
"\n",
"2) Distance qui sépare encore les deux trains à 9h00 :\n",
"- Distance totale = 470 km, donc restante = 470 − 120 = 350 km.\n",
"2) Distance qui sépare encore les deux trains à 9h00. \n",
"Distance totale Paris–Lyon = 470 km. \n",
"Après 1 h le train de Paris a parcouru 120 km, il reste donc : \n",
"470 km − 120 km = 350 km.\n",
"\n",
"3) Vitesse à laquelle les deux trains se rapprochent ensuite :\n",
"- Vitesse relative = 120 + 100 = 220 km/h.\n",
"3) Vitesse à laquelle les deux trains se rapprochent ensuite. \n",
"Ils roulent l’un vers l’autre, donc vitesses additives : 120 km/h + 100 km/h = 220 km/h.\n",
"\n",
"4) Durée nécessaire pour couvrir 350 km à 220 km/h :\n",
"- Durée (heures) = 350 / 220 = 35/22 ≈ 1,590909... h.\n",
"- Décomposition : 35/22 = 1 + 13/22 h.\n",
"- Minutes = (13/22) × 60 = 780/22 ≈ 35,4545 min → 35 min et (0,4545×60) ≈ 27,27 s.\n",
"- Donc durée ≈ 1 h 35 min 27 s.\n",
"4) Durée nécessaire pour couvrir cette distance, convertie en heures et minutes. \n",
"Temps = distance / vitesse = 350 km / 220 km/h = 35/22 h ≈ 1,590909… h. \n",
"Convertissons en heures et minutes : \n",
"1 h + (35/22 − 1)h = 1 h + (13/22) h. \n",
"(13/22) h × 60 min/h = 780/22 min = 39*20/22? (calcul direct) = 35,4545… min. \n",
"Donc ≈ 1 h 35,4545 min → 1 h 35 min et 0,4545×60 ≈ 27,27 s. \n",
"Arrondie aux minutes : 1 h 35 min (ou plus précisément 1 h 35 min 27 s).\n",
"\n",
"5) Heure du croisement :\n",
"- Le second train part à 9h00, plus ≈ 1 h 35 min 27 s donne ≈ 10h35min27s.\n",
"- En arrondissant aux minutes pour le format demandé : 10h35.\n",
"5) Heure du croisement. \n",
"Le calcul commence à 9h00, donc ajouter 1 h 35 min 27 s donne environ 10h35m27s. \n",
"En heures et minutes : 9h00 + 1h35 = 10h35.\n",
"\n",
"Reponse finale : 10h35\n"
]
Expand Down Expand Up @@ -2900,4 +3054,4 @@
},
"nbformat": 4,
"nbformat_minor": 5
}
}
Loading
Loading