From 7c62416b2bf03acaf0424922ebcff50094aa9165 Mon Sep 17 00:00:00 2001 From: jsboige Date: Sun, 4 Oct 2026 02:27:35 +0200 Subject: [PATCH 1/4] feat(gametheory,#14032): banc humour consolide -- 18c absorbe 18d (ex-GT-28b) - 18c 27 -> 65 cellules : sections corpus/ranking/circularite/paires minimales de 18d transferees, 24 refs internes cell[N] renumerotees (mapping empirique +25/+24), cc[24] caduque supprimee, exercices preserves (17/19/21), 0 erreur volontaire (C.1) - re-execution papermill complete : appels LLM reels OpenRouter haiku, 33 cellules code, 0 erreur, lectures re-alignees sur la sortie fraiche (P=0,294 / F1=0,435 / FP=12 ; deterministe invariant par seed 42) - sweep consommateurs : plage corpus [0..10] de 18d -> [26..33] de 18c (ICT-35, ICT-35b, ICT-35d re-executes ; humor_pairs.py ; pytest 11/11), README GameTheory (2 lignes -> 1), README ICT-Series, _quarto.yml, docs/curriculum/recherche.md - 18d supprime APRES absorption ; catalogue byte-identique (automatisation) Co-Authored-By: Claude Sonnet 5.5 --- .../GameTheory-18c-Humour-Banc-Python.ipynb | 3086 +++++++++++++++-- ...ameTheory-18d-Humour-Banc-Dur-Python.ipynb | 2759 --------------- MyIA.AI.Notebooks/GameTheory/README.md | 3 +- ...ICT-35-HumorCausalProbe-Pilot-Python.ipynb | 285 +- .../ICT-35b-HumorCausalPairs-SAE-Python.ipynb | 207 +- ...5d-HumorTypologyBreakdown-SAE-Python.ipynb | 259 +- MyIA.AI.Notebooks/IIT/ICT-Series/README.md | 2 +- .../IIT/ICT-Series/ict/humor_pairs.py | 34 +- _quarto.yml | 3 +- docs/curriculum/recherche.md | 735 ++-- 10 files changed, 3640 insertions(+), 3733 deletions(-) delete mode 100644 MyIA.AI.Notebooks/GameTheory/GameTheory-18d-Humour-Banc-Dur-Python.ipynb diff --git a/MyIA.AI.Notebooks/GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb b/MyIA.AI.Notebooks/GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb index 133ea9c4c5..1f03d1103d 100644 --- a/MyIA.AI.Notebooks/GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb +++ b/MyIA.AI.Notebooks/GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb @@ -5,10 +5,10 @@ "id": "f9a487a0", "metadata": { "papermill": { - "duration": 0.00677, - "end_time": "2026-09-29T04:48:56.607450+00:00", + "duration": 0.011474, + "end_time": "2026-10-04T00:14:22.846404+00:00", "exception": false, - "start_time": "2026-09-29T04:48:56.600680+00:00", + "start_time": "2026-10-04T00:14:22.834930+00:00", "status": "completed" }, "tags": [] @@ -43,10 +43,10 @@ "id": "52d5d143", "metadata": { "papermill": { - "duration": 0.005568, - "end_time": "2026-09-29T04:48:56.620376+00:00", + "duration": 0.015471, + "end_time": "2026-10-04T00:14:22.877650+00:00", "exception": false, - "start_time": "2026-09-29T04:48:56.614808+00:00", + "start_time": "2026-10-04T00:14:22.862179+00:00", "status": "completed" }, "tags": [] @@ -81,16 +81,16 @@ "id": "1e8d6b93", "metadata": { "execution": { - "iopub.execute_input": "2026-09-29T04:48:56.633755Z", - "iopub.status.busy": "2026-09-29T04:48:56.633194Z", - "iopub.status.idle": "2026-09-29T04:48:56.648798Z", - "shell.execute_reply": "2026-09-29T04:48:56.647276Z" + "iopub.execute_input": "2026-10-04T00:14:22.910383Z", + "iopub.status.busy": "2026-10-04T00:14:22.909900Z", + "iopub.status.idle": "2026-10-04T00:14:22.922300Z", + "shell.execute_reply": "2026-10-04T00:14:22.920514Z" }, "papermill": { - "duration": 0.024591, - "end_time": "2026-09-29T04:48:56.650306+00:00", + "duration": 0.031583, + "end_time": "2026-10-04T00:14:22.923948+00:00", "exception": false, - "start_time": "2026-09-29T04:48:56.625715+00:00", + "start_time": "2026-10-04T00:14:22.892365+00:00", "status": "completed" }, "tags": [] @@ -138,16 +138,16 @@ "id": "24c5ceb2", "metadata": { "execution": { - "iopub.execute_input": "2026-09-29T04:48:56.666507Z", - "iopub.status.busy": "2026-09-29T04:48:56.665982Z", - "iopub.status.idle": "2026-09-29T04:48:56.683031Z", - "shell.execute_reply": "2026-09-29T04:48:56.680684Z" + "iopub.execute_input": "2026-10-04T00:14:22.944398Z", + "iopub.status.busy": "2026-10-04T00:14:22.944076Z", + "iopub.status.idle": "2026-10-04T00:14:22.956175Z", + "shell.execute_reply": "2026-10-04T00:14:22.955043Z" }, "papermill": { - "duration": 0.025929, - "end_time": "2026-09-29T04:48:56.684396+00:00", + "duration": 0.025841, + "end_time": "2026-10-04T00:14:22.957968+00:00", "exception": false, - "start_time": "2026-09-29T04:48:56.658467+00:00", + "start_time": "2026-10-04T00:14:22.932127+00:00", "status": "completed" }, "tags": [] @@ -282,10 +282,10 @@ "id": "f9a8451e", "metadata": { "papermill": { - "duration": 0.007914, - "end_time": "2026-09-29T04:48:56.699820+00:00", + "duration": 0.009028, + "end_time": "2026-10-04T00:14:22.976827+00:00", "exception": false, - "start_time": "2026-09-29T04:48:56.691906+00:00", + "start_time": "2026-10-04T00:14:22.967799+00:00", "status": "completed" }, "tags": [] @@ -313,16 +313,16 @@ "id": "6880afb5", "metadata": { "execution": { - "iopub.execute_input": "2026-09-29T04:48:56.716282Z", - "iopub.status.busy": "2026-09-29T04:48:56.715471Z", - "iopub.status.idle": "2026-09-29T04:48:56.725107Z", - "shell.execute_reply": "2026-09-29T04:48:56.723835Z" + "iopub.execute_input": "2026-10-04T00:14:22.996648Z", + "iopub.status.busy": "2026-10-04T00:14:22.996315Z", + "iopub.status.idle": "2026-10-04T00:14:23.002096Z", + "shell.execute_reply": "2026-10-04T00:14:23.000693Z" }, "papermill": { - "duration": 0.020481, - "end_time": "2026-09-29T04:48:56.726265+00:00", + "duration": 0.017426, + "end_time": "2026-10-04T00:14:23.003240+00:00", "exception": false, - "start_time": "2026-09-29T04:48:56.705784+00:00", + "start_time": "2026-10-04T00:14:22.985814+00:00", "status": "completed" }, "tags": [] @@ -364,10 +364,10 @@ "id": "3f0f4c54", "metadata": { "papermill": { - "duration": 0.006217, - "end_time": "2026-09-29T04:48:56.738316+00:00", + "duration": 0.010359, + "end_time": "2026-10-04T00:14:23.023273+00:00", "exception": false, - "start_time": "2026-09-29T04:48:56.732099+00:00", + "start_time": "2026-10-04T00:14:23.012914+00:00", "status": "completed" }, "tags": [] @@ -406,16 +406,16 @@ "id": "a3280304", "metadata": { "execution": { - "iopub.execute_input": "2026-09-29T04:48:56.755926Z", - "iopub.status.busy": "2026-09-29T04:48:56.755017Z", - "iopub.status.idle": "2026-09-29T04:48:56.764340Z", - "shell.execute_reply": "2026-09-29T04:48:56.762910Z" + "iopub.execute_input": "2026-10-04T00:14:23.043422Z", + "iopub.status.busy": "2026-10-04T00:14:23.043107Z", + "iopub.status.idle": "2026-10-04T00:14:23.049654Z", + "shell.execute_reply": "2026-10-04T00:14:23.048398Z" }, "papermill": { - "duration": 0.019204, - "end_time": "2026-09-29T04:48:56.765719+00:00", + "duration": 0.017412, + "end_time": "2026-10-04T00:14:23.050614+00:00", "exception": false, - "start_time": "2026-09-29T04:48:56.746515+00:00", + "start_time": "2026-10-04T00:14:23.033202+00:00", "status": "completed" }, "tags": [] @@ -464,10 +464,10 @@ "id": "gt24-matrix", "metadata": { "papermill": { - "duration": 0.006233, - "end_time": "2026-09-29T04:48:56.778866+00:00", + "duration": 0.00702, + "end_time": "2026-10-04T00:14:23.065566+00:00", "exception": false, - "start_time": "2026-09-29T04:48:56.772633+00:00", + "start_time": "2026-10-04T00:14:23.058546+00:00", "status": "completed" }, "tags": [] @@ -484,16 +484,16 @@ "id": "c0b708bb", "metadata": { "execution": { - "iopub.execute_input": "2026-09-29T04:48:56.797141Z", - "iopub.status.busy": "2026-09-29T04:48:56.796165Z", - "iopub.status.idle": "2026-09-29T04:48:56.807244Z", - "shell.execute_reply": "2026-09-29T04:48:56.805858Z" + "iopub.execute_input": "2026-10-04T00:14:23.087660Z", + "iopub.status.busy": "2026-10-04T00:14:23.087182Z", + "iopub.status.idle": "2026-10-04T00:14:23.096726Z", + "shell.execute_reply": "2026-10-04T00:14:23.095498Z" }, "papermill": { - "duration": 0.020864, - "end_time": "2026-09-29T04:48:56.808512+00:00", + "duration": 0.022638, + "end_time": "2026-10-04T00:14:23.098238+00:00", "exception": false, - "start_time": "2026-09-29T04:48:56.787648+00:00", + "start_time": "2026-10-04T00:14:23.075600+00:00", "status": "completed" }, "tags": [] @@ -544,10 +544,10 @@ "id": "gt24-shownaive", "metadata": { "papermill": { - "duration": 0.006311, - "end_time": "2026-09-29T04:48:56.822964+00:00", + "duration": 0.008422, + "end_time": "2026-10-04T00:14:23.117378+00:00", "exception": false, - "start_time": "2026-09-29T04:48:56.816653+00:00", + "start_time": "2026-10-04T00:14:23.108956+00:00", "status": "completed" }, "tags": [] @@ -564,16 +564,16 @@ "id": "259ab2ed", "metadata": { "execution": { - "iopub.execute_input": "2026-09-29T04:48:56.837121Z", - "iopub.status.busy": "2026-09-29T04:48:56.836290Z", - "iopub.status.idle": "2026-09-29T04:48:56.843562Z", - "shell.execute_reply": "2026-09-29T04:48:56.841752Z" + "iopub.execute_input": "2026-10-04T00:14:23.136043Z", + "iopub.status.busy": "2026-10-04T00:14:23.135703Z", + "iopub.status.idle": "2026-10-04T00:14:23.141576Z", + "shell.execute_reply": "2026-10-04T00:14:23.140094Z" }, "papermill": { - "duration": 0.016146, - "end_time": "2026-09-29T04:48:56.844772+00:00", + "duration": 0.016917, + "end_time": "2026-10-04T00:14:23.142849+00:00", "exception": false, - "start_time": "2026-09-29T04:48:56.828626+00:00", + "start_time": "2026-10-04T00:14:23.125932+00:00", "status": "completed" }, "tags": [] @@ -604,10 +604,10 @@ "id": "fd432887", "metadata": { "papermill": { - "duration": 0.005506, - "end_time": "2026-09-29T04:48:56.861321+00:00", + "duration": 0.006926, + "end_time": "2026-10-04T00:14:23.156571+00:00", "exception": false, - "start_time": "2026-09-29T04:48:56.855815+00:00", + "start_time": "2026-10-04T00:14:23.149645+00:00", "status": "completed" }, "tags": [] @@ -632,16 +632,16 @@ "id": "08864264", "metadata": { "execution": { - "iopub.execute_input": "2026-09-29T04:48:56.883143Z", - "iopub.status.busy": "2026-09-29T04:48:56.882474Z", - "iopub.status.idle": "2026-09-29T04:48:56.888596Z", - "shell.execute_reply": "2026-09-29T04:48:56.887185Z" + "iopub.execute_input": "2026-10-04T00:14:23.179096Z", + "iopub.status.busy": "2026-10-04T00:14:23.178629Z", + "iopub.status.idle": "2026-10-04T00:14:23.185136Z", + "shell.execute_reply": "2026-10-04T00:14:23.183394Z" }, "papermill": { - "duration": 0.02196, - "end_time": "2026-09-29T04:48:56.889727+00:00", + "duration": 0.022255, + "end_time": "2026-10-04T00:14:23.186520+00:00", "exception": false, - "start_time": "2026-09-29T04:48:56.867767+00:00", + "start_time": "2026-10-04T00:14:23.164265+00:00", "status": "completed" }, "tags": [] @@ -672,10 +672,10 @@ "id": "d58ebc6a", "metadata": { "papermill": { - "duration": 0.00661, - "end_time": "2026-09-29T04:48:56.907060+00:00", + "duration": 0.012065, + "end_time": "2026-10-04T00:14:23.207789+00:00", "exception": false, - "start_time": "2026-09-29T04:48:56.900450+00:00", + "start_time": "2026-10-04T00:14:23.195724+00:00", "status": "completed" }, "tags": [] @@ -683,18 +683,19 @@ "source": [ "### Lecture de la matrice par partage\n", "\n", - "Le détecteur par partage aligne la plupart des cellules sur la vérité. La\n", - "différence avec la naïve est là où le rire et le partage divergent :\n", + "Le détecteur par partage aligne la diagonale complète sur la vérité :\n", "\n", "- `rire_sans_recadrage` : correctement séparé (le rire seul ne suffit pas).\n", "- `recadrage_sans_rire` : correctement reconnu (la forme est partagée, sans rire).\n", "- `offensif_compris_non_partage` : correctement isolé (le refus d'entrer).\n", - "\n", - "L'erreur restante est instructive : sur `A3`, A tente un recadrage que B ne\n", - "reprend pas (`uptake=0`) — le détecteur le classe `recadrage_sans_rire`, la vérité\n", - "est `rien`. C'est la confusion entre « A a proposé un cadre » et « le cadre est\n", - "partagé ». Le banc n'est pas magique : `uptake` est le signal décisif, et quand il\n", - "est ambigu, il sur-estime." + "- Les cas `rien` (dont A3, où A tente un recadrage que B ne reprend pas) :\n", + " classés `rien` — `uptake` est le signal décisif, et son absence suffit.\n", + "\n", + "Une diagonale parfaite sur **12 cas posés à la main** n'est pas une preuve de\n", + "puissance : c'est le signe que l'instrument est calibré sur son propre corpus.\n", + "Mesurer ce qu'il vaut vraiment exige de sortir de ces 12 cas — c'est l'objet du\n", + "passage à l'échelle (corpus Argumentum, 120 instances) en seconde partie de ce\n", + "carnet.\n" ] }, { @@ -703,16 +704,16 @@ "id": "836e6906", "metadata": { "execution": { - "iopub.execute_input": "2026-09-29T04:48:56.933536Z", - "iopub.status.busy": "2026-09-29T04:48:56.932988Z", - "iopub.status.idle": "2026-09-29T04:48:56.952551Z", - "shell.execute_reply": "2026-09-29T04:48:56.949936Z" + "iopub.execute_input": "2026-10-04T00:14:23.230533Z", + "iopub.status.busy": "2026-10-04T00:14:23.230082Z", + "iopub.status.idle": "2026-10-04T00:14:23.239444Z", + "shell.execute_reply": "2026-10-04T00:14:23.237805Z" }, "papermill": { - "duration": 0.032668, - "end_time": "2026-09-29T04:48:56.953951+00:00", + "duration": 0.02284, + "end_time": "2026-10-04T00:14:23.240871+00:00", "exception": false, - "start_time": "2026-09-29T04:48:56.921283+00:00", + "start_time": "2026-10-04T00:14:23.218031+00:00", "status": "completed" }, "tags": [] @@ -754,10 +755,10 @@ "id": "ba9988df", "metadata": { "papermill": { - "duration": 0.006281, - "end_time": "2026-09-29T04:48:56.966749+00:00", + "duration": 0.009364, + "end_time": "2026-10-04T00:14:23.259413+00:00", "exception": false, - "start_time": "2026-09-29T04:48:56.960468+00:00", + "start_time": "2026-10-04T00:14:23.250049+00:00", "status": "completed" }, "tags": [] @@ -784,48 +785,15 @@ "> simultanés, dont l'un au moins le sait." ] }, - { - "cell_type": "code", - "execution_count": 9, - "id": "3d77d082", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-29T04:48:56.983819Z", - "iopub.status.busy": "2026-09-29T04:48:56.983242Z", - "iopub.status.idle": "2026-09-29T04:48:56.990699Z", - "shell.execute_reply": "2026-09-29T04:48:56.989112Z" - }, - "papermill": { - "duration": 0.01746, - "end_time": "2026-09-29T04:48:56.992056+00:00", - "exception": false, - "start_time": "2026-09-29T04:48:56.974596+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Fin du banc — fermeture du notebook.\n" - ] - } - ], - "source": [ - "print(\"Fin du banc — fermeture du notebook.\")" - ] - }, { "cell_type": "markdown", "id": "3793535e", "metadata": { "papermill": { - "duration": 0.007342, - "end_time": "2026-09-29T04:48:57.006503+00:00", + "duration": 0.010867, + "end_time": "2026-10-04T00:14:23.279150+00:00", "exception": false, - "start_time": "2026-09-29T04:48:56.999161+00:00", + "start_time": "2026-10-04T00:14:23.268283+00:00", "status": "completed" }, "tags": [] @@ -843,20 +811,20 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 9, "id": "f13adad2", "metadata": { "execution": { - "iopub.execute_input": "2026-09-29T04:48:57.023446Z", - "iopub.status.busy": "2026-09-29T04:48:57.023090Z", - "iopub.status.idle": "2026-09-29T04:48:57.030548Z", - "shell.execute_reply": "2026-09-29T04:48:57.029012Z" + "iopub.execute_input": "2026-10-04T00:14:23.308709Z", + "iopub.status.busy": "2026-10-04T00:14:23.308067Z", + "iopub.status.idle": "2026-10-04T00:14:23.315381Z", + "shell.execute_reply": "2026-10-04T00:14:23.313624Z" }, "papermill": { - "duration": 0.017718, - "end_time": "2026-09-29T04:48:57.031737+00:00", + "duration": 0.024142, + "end_time": "2026-10-04T00:14:23.317151+00:00", "exception": false, - "start_time": "2026-09-29T04:48:57.014019+00:00", + "start_time": "2026-10-04T00:14:23.293009+00:00", "status": "completed" }, "tags": [] @@ -889,10 +857,10 @@ "id": "e2b04a17", "metadata": { "papermill": { - "duration": 0.007416, - "end_time": "2026-09-29T04:48:57.046339+00:00", + "duration": 0.01173, + "end_time": "2026-10-04T00:14:23.341485+00:00", "exception": false, - "start_time": "2026-09-29T04:48:57.038923+00:00", + "start_time": "2026-10-04T00:14:23.329755+00:00", "status": "completed" }, "tags": [] @@ -915,20 +883,20 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 10, "id": "e2c59d20", "metadata": { "execution": { - "iopub.execute_input": "2026-09-29T04:48:57.064592Z", - "iopub.status.busy": "2026-09-29T04:48:57.064045Z", - "iopub.status.idle": "2026-09-29T04:48:57.072609Z", - "shell.execute_reply": "2026-09-29T04:48:57.071121Z" + "iopub.execute_input": "2026-10-04T00:14:23.367436Z", + "iopub.status.busy": "2026-10-04T00:14:23.367044Z", + "iopub.status.idle": "2026-10-04T00:14:23.374229Z", + "shell.execute_reply": "2026-10-04T00:14:23.372912Z" }, "papermill": { - "duration": 0.020162, - "end_time": "2026-09-29T04:48:57.073838+00:00", + "duration": 0.020936, + "end_time": "2026-10-04T00:14:23.375331+00:00", "exception": false, - "start_time": "2026-09-29T04:48:57.053676+00:00", + "start_time": "2026-10-04T00:14:23.354395+00:00", "status": "completed" }, "tags": [] @@ -970,10 +938,10 @@ "id": "e3a71c48", "metadata": { "papermill": { - "duration": 0.007025, - "end_time": "2026-09-29T04:48:57.088491+00:00", + "duration": 0.009747, + "end_time": "2026-10-04T00:14:23.395812+00:00", "exception": false, - "start_time": "2026-09-29T04:48:57.081466+00:00", + "start_time": "2026-10-04T00:14:23.386065+00:00", "status": "completed" }, "tags": [] @@ -994,20 +962,20 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 11, "id": "e3d86e35", "metadata": { "execution": { - "iopub.execute_input": "2026-09-29T04:48:57.104891Z", - "iopub.status.busy": "2026-09-29T04:48:57.104314Z", - "iopub.status.idle": "2026-09-29T04:48:57.113513Z", - "shell.execute_reply": "2026-09-29T04:48:57.112182Z" + "iopub.execute_input": "2026-10-04T00:14:23.414078Z", + "iopub.status.busy": "2026-10-04T00:14:23.413509Z", + "iopub.status.idle": "2026-10-04T00:14:23.423076Z", + "shell.execute_reply": "2026-10-04T00:14:23.421738Z" }, "papermill": { - "duration": 0.019406, - "end_time": "2026-09-29T04:48:57.114775+00:00", + "duration": 0.019893, + "end_time": "2026-10-04T00:14:23.425105+00:00", "exception": false, - "start_time": "2026-09-29T04:48:57.095369+00:00", + "start_time": "2026-10-04T00:14:23.405212+00:00", "status": "completed" }, "tags": [] @@ -1046,108 +1014,2798 @@ }, { "cell_type": "markdown", - "id": "165d10f3", + "id": "a8feaff4", "metadata": { "papermill": { - "duration": 0.00513, - "end_time": "2026-09-29T04:48:57.125396+00:00", + "duration": 0.011765, + "end_time": "2026-10-04T00:14:23.448859+00:00", "exception": false, - "start_time": "2026-09-29T04:48:57.120266+00:00", + "start_time": "2026-10-04T00:14:23.437094+00:00", "status": "completed" }, "tags": [] }, "source": [ - "## Suite — ce que GT-24b ajoute, et ce que cette PR n'absorbe pas\n", + "## Limites structurelles du détecteur par partage\n", + "\n", + "Le détecteur par partage de ce banc a une propriété **non explicite** dans les cellules ci-dessus mais **centrale** : ses features (`laugh`, `reframe`, `uptake`, `refus`) sont **posées à la main** sur le corpus minimal — un annotateur humain les a écrites en même temps que le label. Sur ce corpus de 12 instances, c'est défendable (chaque instance a une `justification` qui nomme les features).\n", + "\n", + "Le passage à l'échelle de 24b a montré que cette défendabilité **ne tient plus** :\n", "\n", - "Le compagnon `GameTheory-18d-Humour-Banc-Dur-Python.ipynb` (livré en #12756/#13984) prolonge ce banc sur **trois axes** :\n", + "- **Circularité structurelle** : quand les features sont dérivées du label par construction (la cellule de corpus dur de 24b appelle `features_from_label`), le détecteur inverse la dérivation et **ne peut plus se tromper** — F1=1,000 tautologique. C'est la limite que le test de circularité #13306 a explicitement nommée : « F1=1,000 ne mesure pas la théorie du partage, il mesure l'identité de construction features ↔ label ».\n", + "- **Raccourci lexical** : les négatives du corpus initial (déclarations factuelles : météo, bourse, administration) viennent d'un **autre domaine lexical** que les positives (blagues d'informaticiens). Un classifieur de surface y réussit par raccourci lexical, pas par compréhension de l'humour — c'est ce que les paires minimales « unfun » de 24b corrigent en appariant sujet, longueur et registre.\n", + "- **Annotation unique** : le corpus 24 porte les features d'un **seul annotateur**. L'appréciation (κ quadratique pondéré, ρ de Spearman) est **INCONCLUSIVE par construction** (règle de l'issue : un seul annotateur ne généralise pas une échelle de goût). La voie #12756 (campagne multi-annotateurs) reste la suite.\n", "\n", - "1. **Passage à l'échelle** : constitution d'un corpus de **120 instances** (60 manuelles + 60 échantillonnées d'un fetch authentique sur Argumentum `master @0af0511c58`, traçable par SHA).\n", - "2. **Comparaison LLM** : appel réel à `anthropic/claude-haiku-4.5` via OpenRouter (canal épinglé, `SOTA-OK`), opposé au détecteur maison — F1 macro et IC bootstrap.\n", - "3. **Test de circularité** (issue #13306) : application du détecteur inchangé aux **107 scénarios Argumentum non consommés** (prédicat reproductible + trois contrôles de disjonction prouvés). Le verdict `CIRCULARITE_GROSSIERE_ECARTEE` est posé avec une **réserve structurelle majeure** : sur les instances Argumentum, les features sont dérivées du label annoté, donc le F1=1,000 mesure l'identité de construction `features ↔ label`, pas la théorie du partage.\n", + "**Lecture honnête du banc de cette PR** : il montre que le détecteur par partage **est meilleur** que le détecteur naïf sur le corpus minimal. Il ne montre pas que le détecteur par partage **est bon** sur un corpus où les features ne sont pas posées à la main — c'est le trou que 24b a identifié, et la voie des paires minimales commence à le fermer.\n" + ] + }, + { + "cell_type": "markdown", + "id": "b30c3ee8", + "metadata": { + "papermill": { + "duration": 0.010677, + "end_time": "2026-10-04T00:14:23.471196+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:23.460519+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "## Conclusion — ce qui tient, ce qui reste à faire\n", "\n", - "4. **Paires minimales « unfun »** (issue #14033) : pour échapper à la circularité structurelle, 30 paires où les négatifs partagent sujet, longueur, registre et lexique des positifs — c'est la solution Horvitz et al. (ACL 2024) au raccourci lexical. Trois verdicts séparés : **détection** (macro-F1 par forme et par tranche OOD code-mixée FR/EN), **appréciation** (κ quadratique pondéré et ρ de Spearman — **INCONCLUSIVE** par construction, un seul annotateur), **explication** (grille humaine explicite, appariement de mots-clés).\n", + "**Ce qui tient** dans cette PR :\n", "\n", - "### Pourquoi cette PR ne consolide pas 24b dans 24\n", + "- Le détecteur par partage **est meilleur** que la naïve sur le corpus minimal (P=1.000 / R=1.000 vs P=0.40 / R=1.00), et la différence est localisée exactement là où rire et partage **divergent** : les trois cellules `rire_sans_recadrage` (chatouille, contagion, nervosité) que la naïve range dans `humour_reussi` à tort, et la cellule `recadrage_sans_rire` (ironie froide) que la naïve range dans `rien` à tort. **Le partage de forme est la grandeur, le rire est un témoin commode mais partiel.**\n", + "- Le cas offensif (`offensif_compris_non_partage`, O1/O2) est isolé correctement par les deux détecteurs — c'est l'instance la plus instructive : la forme est perçue, le cadre change pour un seul agent, l'autre refuse d'y entrer.\n", "\n", - "**Le scope honnête de cette PR est limité par ce qui peut s'exécuter depuis cette machine.** La lane CPU (`myia-po-2026:CoursIA-2`) n'a pas accès à :\n", + "**Ce qui reste à faire** (tranche RECOVERABLE-MACHINE, hors scope de cette PR) :\n", "\n", - "- **endpoint vLLM LAN `qwen3.6-35b-a3b` @ `192.168.0.47:5002`** — documenté **INJOIGNABLE depuis cette machine** (HTTP 000) ; RECOVERABLE-MACHINE = routeur vers une lane qui voit l'endpoint, **pas** de fallback dégradé ;\n", - "- **fetch réseau Argumentum** (submodule timeout, c.539) — le notebook 24b contourne par HTTP direct sur `upstream master @0af0511c58` ;\n", - "- **OPENAI_API_KEY** (clef locale non-production) et **`anthropic/claude-haiku-4.5`** via OpenRouter, requis par la comparaison LLM de 24b.\n", + "1. **Fusion physique** de 24b dans 24 — la matrice de préservation ci-dessus en est le contrat ; exécution sur une lane qui voit l'endpoint vLLM et le fetch Argumentum.\n", + "2. **Annotation indépendante des features** : annoter `laugh`/`reframe`/`uptake`/`refus` **depuis le texte**, sans voir le label, puis ré-appliquer ce détecteur inchangé. Sans cela, le F1=1,000 de 24b est tautologique.\n", + "3. **Campagne multi-annotateurs** (#12756) : faire porter le même corpus à ≥3 annotateurs et mesurer l'accord inter-annotateur avant toute conclusion sur l'appréciation.\n", "\n", - "**Ce que cette PR préserve**, donc, c'est l'instrument minimal (le détecteur par partage, la matrice de confusion, le cas offensif) — c'est ce qui s'exécute nativement. **Ce qui est différé** : la fusion physique du notebook 24b dans 24 (avec re-exécution de ses cellules) appartient à une **tranche RECOVERABLE-MACHINE** — typiquement po-2023 ou ai-01, qui voient l'endpoint.\n", + "**Pourquoi cette PR est honnête** : elle **n'absorbe pas** ce qu'elle ne peut pas ré-exécuter. La matrice de préservation est déposée comme **contrat** pour la tranche suivante, pas comme **résultat**. Le compagnon 24b reste en place pour la tranche RECOVERABLE-MACHINE.\n" + ] + }, + { + "cell_type": "markdown", + "id": "gt18c-transition-echelle", + "metadata": { + "papermill": { + "duration": 0.010966, + "end_time": "2026-10-04T00:14:23.494777+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:23.483811+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "## Passage à l'échelle — corpus Argumentum et 120 blagues annotées\n", + "\n", + "Les sections qui suivent absorbent l'ancien compagnon `GT-28b` (renommé\n", + "`GameTheory-18d`, livré par #12756/#13984 et clos par #14033) :\n", + "constitution d'un corpus de **120 instances** (dont 60 échantillonnées d'un fetch\n", + "Argumentum `master @0af0511c58`, traçable par SHA), comparaison\n", + "règle/partage/LLM (`anthropic/claude-haiku-4.5` via OpenRouter), puis test de\n", + "circularité (#13306) et paires minimales unfun (#14033) — l'auto-réfutation de\n", + "notre propre instrument.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "27ccb4b1", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:14:23.516976Z", + "iopub.status.busy": "2026-10-04T00:14:23.516642Z", + "iopub.status.idle": "2026-10-04T00:14:23.527512Z", + "shell.execute_reply": "2026-10-04T00:14:23.525714Z" + }, + "papermill": { + "duration": 0.024151, + "end_time": "2026-10-04T00:14:23.529323+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:23.505172+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[setup] Catégories : ['humour_reussi', 'rire_sans_recadrage', 'recadrage_sans_rire', 'offensif_compris_non_partage', 'rien']\n", + "[setup] LLM endpoint : https://openrouter.ai/api/v1\n", + "[setup] LLM model : anthropic/claude-haiku-4.5\n" + ] + } + ], + "source": [ + "# -*- coding: utf-8 -*-\n", + "# Imports + configuration. Pas de service externe lourd : csv, json, urllib.\n", + "import csv\n", + "import os\n", + "import json\n", + "import time\n", + "import urllib.request\n", + "import urllib.error\n", + "from collections import Counter\n", + "from pathlib import Path\n", "\n", - "### Matrice de préservation (à exécuter lors de la tranche RECOVERABLE-MACHINE)\n", + "# Catégories du banc — alignées sur le toy model GT-24\n", + "CATEGORIES = [\n", + " \"humour_reussi\", # rire + recadrage partagé\n", + " \"rire_sans_recadrage\", # rire mais pas de partage (chatouille, contagion, nerveux)\n", + " \"recadrage_sans_rire\", # partage sans rire (humour sec, anglo-saxon)\n", + " \"offensif_compris_non_partage\", # offensif compris mais refusé par le destinataire\n", + " \"rien\", # pas d'humour du tout\n", + "]\n", + "CAT_LABEL = {c: i for i, c in enumerate(CATEGORIES)}\n", + "\n", + "# Configuration LLM — canal de jugement epingle sur OpenRouter (#14033, dispatch\n", + "# ai-01 2026-09-13) : le endpoint LAN vLLM (http://192.168.0.47:5002/v1) est\n", + "# injoignable depuis cette lane (HTTP 000 mesure le 2026-09-13). Modele ET\n", + "# version epingles : identifiant exact ci-dessous + echo du champ 'model' de la\n", + "# premiere reponse capture dans les sorties (resolution provider visible).\n", + "OPENAI_COMPAT_URL = \"https://openrouter.ai/api/v1\"\n", + "# Cle lue dans l'environnement — jamais de litteral ici : ce depot est public.\n", + "# Renseigner OPENROUTER_API_KEY dans .secrets/master.env, puis :\n", + "# python scripts/secrets/render_envs.py\n", + "OPENAI_API_KEY = os.getenv(\"OPENROUTER_API_KEY\")\n", + "if not OPENAI_API_KEY:\n", + " raise ValueError(\n", + " \"OPENROUTER_API_KEY absente de l'environnement. \"\n", + " \"Renseignez-la dans .secrets/master.env puis executez \"\n", + " \"scripts/secrets/render_envs.py.\"\n", + " )\n", + "LLM_MODEL = \"anthropic/claude-haiku-4.5\"\n", + "\n", + "# Cache local pour éviter de retélécharger Argumentum\n", + "ARGUMENTUM_CACHE = Path(\"argumentum_scenarii.csv\")\n", + "print(f\"[setup] Catégories : {CATEGORIES}\")\n", + "print(f\"[setup] LLM endpoint : {OPENAI_COMPAT_URL}\")\n", + "print(f\"[setup] LLM model : {LLM_MODEL}\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "79340466", + "metadata": { + "papermill": { + "duration": 0.011681, + "end_time": "2026-10-04T00:14:23.554573+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:23.542892+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "## Corpus Argumentum — fetch raw GitHub\n", "\n", - "Lors de la consolidation complète, la matrice suivante s'applique — c'est le contrat d'absorption de 24b dans 24, **sans suppression de 24b avant vérification cellule par cellule** :\n", + "Le submodule `MyIA.AI.Notebooks/SymbolicAI/Argument_Analysis/Argumentum`\n", + "pointe le commit `7e72f3e5` mais **n'est pas initialisé** sur cet environnement\n", + "(mesure c.539 : `git submodule status` retourne le commit avec suffixe `-`,\n", + "worktree `Argumentum/` vide, et `git submodule update --init` timeout 2 min).\n", "\n", - "| Source (24b) | Apport unique à préserver | Destination dans 24 (survivant) | Preuve attendue |\n", - "|---|---|---|---|\n", - "| cells 0-3 (intro + configuration) | cadrage du passage à l'échelle, fetch Argumentum traçable par SHA, 167 scénarios, 7 catégories, 21 sous-catégories | section « passage à l'échelle » | SHA `0af0511c58`, distribution reproduite |\n", - "| cells 5-11 (corpus dur + détecteurs) | 120 instances, 4 sources, toy model répliqué, distribution par cellule (`humour_reussi` 48/40%, `offensif` 7) | avant la comparaison LLM | `assert ≥100` passe, distribution inchangée |\n", - "| cells 14-22 (ranking LLM + matrices) | appel Qwen/haiku réel, règle vs partage vs LLM, P/R/F1 côte à côte | section « comparaison LLM » | sorties réelles `pred`/`raw` committées |\n", - "| cells 23-28 (test circularité) | 60 consommés / 107 tenus à l'écart, 3 contrôles de disjonction, F1=[1.000, 1.000] bootstrap, verdict `CIRCULARITE_GROSSIERE_ECARTEE` avec réserve structurelle | section « auto-réfutation de la circularité » | trois `assert` passent, IC bootstrap dégénéré cité |\n", - "| cells 30-41 (paires minimales) | 30 paires (11 pun / 8 sociale / 11 topical), 8 OOD code-mixées FR/EN, split gelé avant mesure, 3 verdicts séparés | section « limites et suite » | SHA split, ratios longueur, sim chars, dédup cross-split |\n", + "**Solution** : fetch direct sur `raw.githubusercontent.com/ArgumentumGames/\n", + "Argumentum/master/Cards/Scenarii/Argumentum Scenarii - Cards.csv`. Le CSV\n", + "fait 555 KB ; SHA du dernier commit upstream vérifiable via l'API GitHub\n", + "(`/repos/ArgumentumGames/Argumentum/commits/master`).\n", "\n", - "**Cette matrice ne s'exécute pas dans cette PR.** Elle est déposée comme contrat pour la tranche suivante (RECOVERABLE-MACHINE).\n" + "Cette approche préserve l'acceptance « ≥1 corpus réel intégré, scénarios\n", + "Argumentum extraits du submodule » (#12756) sans dépendre de l'init submodule\n", + "(qui sera fait dans une PR séparée post-cycle, voir Conclusion).\n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "73d99644", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:14:23.581898Z", + "iopub.status.busy": "2026-10-04T00:14:23.581514Z", + "iopub.status.idle": "2026-10-04T00:14:23.993664Z", + "shell.execute_reply": "2026-10-04T00:14:23.992177Z" + }, + "papermill": { + "duration": 0.426289, + "end_time": "2026-10-04T00:14:23.995295+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:23.569006+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[fetch] cache hit : argumentum_scenarii.csv\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[fetch] upstream master @d68170c521 : docs(corpus): #458 liste de relecture native (38) -- 2 ouvertes, 6 confirmations\n" + ] + } + ], + "source": [ + "# -*- coding: utf-8 -*-\n", + "# Fetch Argumentum CSV. Si cache local présent (commit c.539), on l'utilise\n", + "# pour reproductibilité ; sinon on fetch raw GitHub.\n", + "if ARGUMENTUM_CACHE.exists():\n", + " print(f\"[fetch] cache hit : {ARGUMENTUM_CACHE}\")\n", + " src = \"cache-local\"\n", + "else:\n", + " url = (\"https://raw.githubusercontent.com/ArgumentumGames/Argumentum/master/\"\n", + " \"Cards/Scenarii/Argumentum%20Scenarii%20-%20Cards.csv\")\n", + " try:\n", + " req = urllib.request.Request(url, headers={\"User-Agent\": \"CoursIA-GT28b\"})\n", + " with urllib.request.urlopen(req, timeout=30) as r:\n", + " data = r.read()\n", + " ARGUMENTUM_CACHE.write_bytes(data)\n", + " print(f\"[fetch] downloaded {len(data)} bytes -> {ARGUMENTUM_CACHE}\")\n", + " src = url\n", + " except urllib.error.URLError as e:\n", + " print(f\"[fetch] ERREUR : {e}\")\n", + " raise\n", + "\n", + "# Vérifier le SHA upstream (pour traçabilité du corpus réel)\n", + "sha_url = \"https://api.github.com/repos/ArgumentumGames/Argumentum/commits/master\"\n", + "try:\n", + " req = urllib.request.Request(sha_url, headers={\"User-Agent\": \"CoursIA-GT28b\",\n", + " \"Accept\": \"application/vnd.github.v3+json\"})\n", + " with urllib.request.urlopen(req, timeout=10) as r:\n", + " sha_info = json.loads(r.read())\n", + " upstream_sha = sha_info[\"sha\"][:10]\n", + " upstream_msg = sha_info[\"commit\"][\"message\"].split(\"\\n\")[0][:80]\n", + " print(f\"[fetch] upstream master @{upstream_sha} : {upstream_msg}\")\n", + "except Exception as e:\n", + " print(f\"[fetch] SHA upstream non vérifié ({e}) — corpus tout de même chargé depuis cache\")\n", + " upstream_sha = \"n/a\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "7390cfad", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:14:24.015421Z", + "iopub.status.busy": "2026-10-04T00:14:24.015088Z", + "iopub.status.idle": "2026-10-04T00:14:24.038870Z", + "shell.execute_reply": "2026-10-04T00:14:24.037275Z" + }, + "papermill": { + "duration": 0.037459, + "end_time": "2026-10-04T00:14:24.040514+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:24.003055+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[parse] 167 scénarios Argumentum chargés\n", + "[parse] catégories : {'histoire': 17, 'mythologie': 27, 'relation intime': 36, 'vie professionnelle': 30, 'vie personnelle': 25, 'pop culture': 18, 'politique': 14}\n", + "[parse] sous-catégories (21) : {'antiquité': 6, 'moyen-âge et temps modernes': 6, '20e et 21e siècle': 5, 'contes': 10, 'religions': 11, 'littérature': 6, 'drague et séduction': 9, 'vie de couple': 16, 'romance': 11, 'interactions professionnelles': 14, 'relations au travail': 8, 'gestion et administration': 9, 'Bandes dessinées': 5, 'cinéma & télévision': 7, 'science': 6, 'gouvernance': 4, 'manoeuvres et collusion': 6, 'campagne': 4, 'famille et enfance': 8, 'voisins et amis': 11, 'loisirs et espace public': 5}\n", + "[parse] 167 instances retenues (champs FR)\n", + "[parse] exemple : id=1.1.1 titre='La mère de César et Cléopâtre'\n", + " baratineur='Aurelia Cotta, mère de César' -> piocheur='Jules César'\n" + ] + } + ], + "source": [ + "# -*- coding: utf-8 -*-\n", + "# Parse le CSV Argumentum. Conservation des colonnes FR + EN.\n", + "with open(ARGUMENTUM_CACHE, \"r\", encoding=\"utf-8\") as f:\n", + " rows = list(csv.DictReader(f))\n", + "\n", + "print(f\"[parse] {len(rows)} scénarios Argumentum chargés\")\n", + "\n", + "# Distribution par catégorie\n", + "cats = Counter(r[\"catégorie\"] for r in rows)\n", + "print(f\"[parse] catégories : {dict(cats)}\")\n", + "\n", + "# Distribution par sous-catégorie\n", + "subcats = Counter(r[\"sous-catégorie\"] for r in rows)\n", + "print(f\"[parse] sous-catégories ({len(subcats)}) : {dict(subcats)}\")\n", + "\n", + "# Pour le banc humour, on retient les colonnes FR (titre, baratineur, contexte,\n", + "# enjeu, suggestion) — le matériel humoristique brut.\n", + "fields = [\"path\", \"catégorie\", \"sous-catégorie\", \"titre\",\n", + " \"baratineur\", \"piocheur\", \"contexte\", \"enjeu\", \"suggestion\"]\n", + "argumentum = [{k: r[k] for k in fields} for r in rows]\n", + "print(f\"[parse] {len(argumentum)} instances retenues (champs FR)\")\n", + "print(f\"[parse] exemple : id={argumentum[0]['path']} titre='{argumentum[0]['titre']}'\")\n", + "print(f\" baratineur='{argumentum[0]['baratineur']}' -> piocheur='{argumentum[0]['piocheur']}'\")\n" ] }, { "cell_type": "markdown", - "id": "a8feaff4", + "id": "interp-parse", "metadata": { "papermill": { - "duration": 0.007221, - "end_time": "2026-09-29T04:48:57.140627+00:00", + "duration": 0.009127, + "end_time": "2026-10-04T00:14:24.061404+00:00", "exception": false, - "start_time": "2026-09-29T04:48:57.133406+00:00", + "start_time": "2026-10-04T00:14:24.052277+00:00", "status": "completed" }, "tags": [] }, "source": [ - "## Limites structurelles du détecteur par partage\n", + "### Lecture — 167 scénarios, 7 catégories, 21 sous-catégories\n", "\n", - "Le détecteur par partage de ce banc a une propriété **non explicite** dans les cellules ci-dessus mais **centrale** : ses features (`laugh`, `reframe`, `uptake`, `refus`) sont **posées à la main** sur le corpus minimal — un annotateur humain les a écrites en même temps que le label. Sur ce corpus de 12 instances, c'est défendable (chaque instance a une `justification` qui nomme les features).\n", + "La sortie détaille la structure du corpus Argumentum :\n", "\n", - "Le passage à l'échelle de 24b a montré que cette défendabilité **ne tient plus** :\n", + "- **167 scénarios** au total, répartis sur **7 catégories** (`histoire` 17, `mythologie` 27, `relation intime` 36, `vie professionnelle` 30, `vie personnelle` 25, `pop culture` 18, `politique` 14). `relation intime` est la plus nombreuse — c'est la catégorie la plus propice au matériel humoristique.\n", + "- **21 sous-catégories** affinent (ex. `antiquité`, `religions`, `drague et séduction`, `cinéma & télévision`). Ce grain fin servira à l'annotation heuristique de la cellule suivante.\n", + "- **Champs retenus** : `path`, `catégorie`, `sous-catégorie`, `titre`, `baratineur`, `piocheur`, `contexte`, `enjeu`, `suggestion`. Le `path` (ex. `7.3.2`) est l'identifiant de scénario utilisé pour le contrôle de disjonction de la section circularité (cell[43]).\n", "\n", - "- **Circularité structurelle** : quand les features sont dérivées du label par construction (la cellule de corpus dur de 24b appelle `features_from_label`), le détecteur inverse la dérivation et **ne peut plus se tromper** — F1=1,000 tautologique. C'est la limite que le test de circularité #13306 a explicitement nommée : « F1=1,000 ne mesure pas la théorie du partage, il mesure l'identité de construction features ↔ label ».\n", - "- **Raccourci lexical** : les négatives du corpus initial (déclarations factuelles : météo, bourse, administration) viennent d'un **autre domaine lexical** que les positives (blagues d'informaticiens). Un classifieur de surface y réussit par raccourci lexical, pas par compréhension de l'humour — c'est ce que les paires minimales « unfun » de 24b corrigent en appariant sujet, longueur et registre.\n", - "- **Annotation unique** : le corpus 24 porte les features d'un **seul annotateur**. L'appréciation (κ quadratique pondéré, ρ de Spearman) est **INCONCLUSIVE par construction** (règle de l'issue : un seul annotateur ne généralise pas une échelle de goût). La voie #12756 (campagne multi-annotateurs) reste la suite.\n", + "L'exemple imprimé (`baratineur` → `piocheur`) montre la structure d'un scénario Argumentum : un `baratineur` avance une interprétation, un `piocheur` doit la recadrer. C'est précisément la mécanique « recadrage partagé » que la cellule `humour_reussi` modélise." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "4161f8c4", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:14:24.078719Z", + "iopub.status.busy": "2026-10-04T00:14:24.078263Z", + "iopub.status.idle": "2026-10-04T00:14:24.088617Z", + "shell.execute_reply": "2026-10-04T00:14:24.087001Z" + }, + "papermill": { + "duration": 0.021521, + "end_time": "2026-10-04T00:14:24.089717+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:24.068196+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[label] distribution après annotation manuelle : {'rien': 46, 'recadrage_sans_rire': 27, 'humour_reussi': 55, 'rire_sans_recadrage': 25, 'offensif_compris_non_partage': 14}\n" + ] + } + ], + "source": [ + "# -*- coding: utf-8 -*-\n", + "# Mapping Argumentum → cellules du banc.\n", + "# Hypothèse : un scénario Argumentum avec \"enjeu\" absurde + \"suggestion\"\n", + "# inattendue = cellule \"humour_reussi\" (recadrage partagé typique du jeu).\n", + "# Un scénario \"histoire\" (César, Troie, etc.) = souvent \"rien\" (matériel\n", + "# sérieux) ou \"recadrage_sans_rire\" (anachronisme).\n", + "# Cette heuristique est appliquée ici comme **annotation manuelle** (par\n", + "# nous-mêmes, pas auto) ; elle est marquée clairement pour audit.\n", + "\n", + "def label_argumentum(row):\n", + " \"\"\"Annotation manuelle par catégorie + sous-catégorie Argumentum.\n", + " Règles appliquées (transparentes) :\n", + " - 'pop culture' → souvent humour_reussi (références décalées)\n", + " - 'mythologie' → recadrage_sans_rire (anachronisme classique)\n", + " - 'relation intime' → mixte, dépend contexte\n", + " - 'histoire' → souvent rien (matériel trop sérieux)\n", + " - 'politique' → offensif_compris_non_partage (sujet sensible)\n", + " \"\"\"\n", + " cat = row[\"catégorie\"]\n", + " subcat = row[\"sous-catégorie\"]\n", + " enjeu = row.get(\"enjeu\", \"\").lower()\n", + " suggestion = row.get(\"suggestion\", \"\").lower()\n", + " # Heuristiques transparentes\n", + " if cat == \"pop culture\":\n", + " return \"humour_reussi\" # par défaut pop culture = décalage\n", + " if cat == \"mythologie\":\n", + " return \"recadrage_sans_rire\" # mythologie = anachronisme sec\n", + " if cat == \"politique\":\n", + " return \"offensif_compris_non_partage\"\n", + " if cat == \"histoire\":\n", + " return \"rien\" # matériel historique = contexte trop sérieux\n", + " if cat == \"vie professionnelle\":\n", + " # Les sous-catégories varient ; défaut = humour_reussi si en jeu\n", + " return \"humour_reussi\" if any(w in enjeu + suggestion\n", + " for w in [\"absurd\", \"ridicul\", \"drôle\",\n", + " \"plaisant\", \"amusant\"]) else \"rien\"\n", + " if cat == \"vie personnelle\":\n", + " return \"rire_sans_recadrage\" # vie perso = souvent rire sans jeu partagé\n", + " if cat == \"relation intime\":\n", + " return \"humour_reussi\" # relation intime = registre humoristique fréquent\n", + " return \"rien\"\n", "\n", - "**Lecture honnête du banc de cette PR** : il montre que le détecteur par partage **est meilleur** que le détecteur naïf sur le corpus minimal. Il ne montre pas que le détecteur par partage **est bon** sur un corpus où les features ne sont pas posées à la main — c'est le trou que 24b a identifié, et la voie des paires minimales commence à le fermer.\n" + "labeled_arg = [{**r, \"label\": label_argumentum(r)} for r in argumentum]\n", + "labels_dist = Counter(r[\"label\"] for r in labeled_arg)\n", + "print(f\"[label] distribution après annotation manuelle : {dict(labels_dist)}\")\n" ] }, { "cell_type": "markdown", - "id": "b30c3ee8", + "id": "b2845630", "metadata": { "papermill": { - "duration": 0.00738, - "end_time": "2026-09-29T04:48:57.156441+00:00", + "duration": 0.008356, + "end_time": "2026-10-04T00:14:24.104932+00:00", "exception": false, - "start_time": "2026-09-29T04:48:57.149061+00:00", + "start_time": "2026-10-04T00:14:24.096576+00:00", "status": "completed" }, "tags": [] }, "source": [ - "## Conclusion — ce qui tient, ce qui reste à faire\n", - "\n", - "**Ce qui tient** dans cette PR :\n", + "## Corpus annoté blagues — ≥ 100 instances\n", + "\n", + "Objectif : dépasser le toy model (12 instances) pour une matrice de confusion\n", + "statistiquement significative. Construction **par annotation manuelle** (avec\n", + "justifications explicites par instance, conformément à C.1 : pas de fabrication\n", + "sans verdict — chaque blague est marquée `justification` qui dit pourquoi elle\n", + "tombe dans la cellule choisie).\n", + "\n", + "Composition visée :\n", + "- **Argumentum enrichi** (167 scénarios) → ~60 instances après filtrage\n", + "- **Blagues positives manuelles** (humour réussi) → 30 instances\n", + "- **Négatives explicites** (non-humour : phrases neutres, déclarations) → 20 instances\n", + "- **Edge cases** (chatouille/contagion, offensif refusé, humour sec) → 10 instances\n", + "\n", + "Total cible : 120+ instances, équilibrées par cellule (≥15 par cellule de la\n", + "matrice du toy model).\n" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "655305f9", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:14:24.124586Z", + "iopub.status.busy": "2026-10-04T00:14:24.124246Z", + "iopub.status.idle": "2026-10-04T00:14:24.152299Z", + "shell.execute_reply": "2026-10-04T00:14:24.150469Z" + }, + "papermill": { + "duration": 0.042017, + "end_time": "2026-10-04T00:14:24.153966+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:24.111949+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[corpus] total : 120 instances\n", + "[corpus] distribution par label : {'rire_sans_recadrage': 14, 'recadrage_sans_rire': 13, 'rien': 38, 'humour_reussi': 48, 'offensif_compris_non_partage': 7}\n", + "[corpus] distribution par source : {'ArgumentumGames/Argumentum': 60, 'blague-manuelle': 30, 'declaration-factuelle': 20, 'edge-case-curated': 10}\n", + "[corpus] humour_reussi : 48 instances OK\n", + "[corpus] rire_sans_recadrage : 14 instances OK\n", + "[corpus] recadrage_sans_rire : 13 instances OK\n", + "[corpus] offensif_compris_non_partage : 7 instances OK\n", + "[corpus] rien : 38 instances OK\n" + ] + } + ], + "source": [ + "# -*- coding: utf-8 -*-\n", + "# CORPUS_DUR — ≥ 100 instances annotées manuellement.\n", + "# Chaque instance = {id, texte, features, label, justification, source}.\n", + "\n", + "# --- 1. Argumentum enrichi : 60 scénarios échantillonnés ---\n", + "import random\n", + "random.seed(42) # reproductibilité\n", + "\n", + "arg_sample = random.sample(labeled_arg, k=60)\n", + "arg_instances = []\n", + "for r in arg_sample:\n", + " # Construire les features selon la cellule d'annotation\n", + " lab = r[\"label\"]\n", + " features = {\n", + " \"laugh\": lab == \"humour_reussi\" or lab == \"rire_sans_recadrage\",\n", + " \"reframe\": lab == \"humour_reussi\" or lab == \"recadrage_sans_rire\",\n", + " \"uptake\": lab == \"humour_reussi\",\n", + " \"refus\": lab == \"offensif_compris_non_partage\",\n", + " }\n", + " arg_instances.append({\n", + " \"id\": \"arg-\" + r[\"path\"],\n", + " \"texte\": \"[\" + r[\"catégorie\"] + \"/\" + r[\"sous-catégorie\"] + \"] \" + r[\"titre\"] + \" — baratineur: \" + r[\"baratineur\"] + \", contexte: \" + r[\"contexte\"][:60] + \"...\",\n", + " \"features\": features,\n", + " \"label\": lab,\n", + " \"justification\": \"Annotation manuelle Argumentum : catégorie \" + r[\"catégorie\"] + \" → heuristique cell[30] donne \" + lab,\n", + " \"source\": \"ArgumentumGames/Argumentum\",\n", + " })\n", + "\n", + "# --- 2. Blagues positives manuelles (humour réussi) : 30 ---\n", + "POSITIVE_JOKES = [\n", + " (\"joke-p01\", \"Un informaticien rentre dans un bar et dit : 'je voudrais une bière,\", \"humour_reussi\", \"Refrain 'je voudrais' x10 = structure répétitive absurde + callback\"),\n", + " (\"joke-p02\", \"Pourquoi les développeurs confondent Halloween et Noël ? Parce que Oct 31 == Dec 25.\", \"humour_reussi\", \"Anagramme numérique Octal/Décimal — recadrage par équivalence inattendue\"),\n", + " (\"joke-p03\", \"Il y a 10 types de personnes au monde : ceux qui comprennent le binaire et ceux qui ne le comprennent pas.\", \"humour_reussi\", \"Le '10' en base 2 = 2 en base 10 = recadrage meta + callback\"),\n", + " (\"joke-p04\", \"Un SQL entre dans un bar, voit deux tables et leur dit : 'SELECT * FROM...'\", \"humour_reussi\", \"Personnification SQL + jeu de mots 'SELECT *'\"),\n", + " (\"joke-p05\", \"Combien d'ingénieurs faut-il pour changer une ampoule ? Aucun, c'est un problème hardware.\", \"humour_reussi\", \"Inversion responsabilité dev/hardware + callout métier\"),\n", + " (\"joke-p06\", \"Je suis tombé amoureuse d'une fonction quadratique. Mais elle avait deux racines.\", \"humour_reussi\", \"Métaphore math + double sens 'racines'/'problèmes'\"),\n", + " (\"joke-p07\", \"Un null et un undefined entrent dans un bar. Le barman dit 'On accepte pas les non-définis ici'.\", \"humour_reussi\", \"Callback JS + référence culturelle programmeurs\"),\n", + " (\"joke-p08\", \"Je voulais te raconter une blague sur UDP... mais je sais si elle arrive.\", \"humour_reussi\", \"Métaphore protocole UDP = best-effort delivery\"),\n", + " (\"joke-p09\", \"Le père Noël a-t-il déjà eu un problème de pile ? Non, il a toujours des piles neuves.\", \"humour_reussi\", \"Jeu de mots 'pile' électrique/noël + absurdité\"),\n", + " (\"joke-p10\", \"Pourquoi le café est-il si bon au travail ? Parce qu'il est fraîchement moulu par l'échéance.\", \"humour_reussi\", \"Métaphore deadline = mouture + 'fraîchement' double sens\"),\n", + " (\"joke-p11\", \"J'ai essayé d'écrire une blague sur les coroutines, mais je n'arrive pas à la yield.\", \"humour_reussi\", \"Référence yield coroutine + jeu de mots 'je n'arrive pas à'\"),\n", + " (\"joke-p12\", \"Docker, Kubernetes, Prometheus, Grafana. On m'a dit que c'était simple, alors je stack.\", \"humour_reussi\", \"Accumulation noms outils + 'stack' double sens\"),\n", + " (\"joke-p13\", \"Mon compilateur et moi on a une relation stable : il compile, je pleure.\", \"humour_reussi\", \"Métaphore relation + inversion cause-effet\"),\n", + " (\"joke-p14\", \"J'ai un ami palindrome. On ne peut pas se différencier.\", \"humour_reussi\", \"Définition palindrome appliquée à la relation + absurde\"),\n", + " (\"joke-p15\", \"Les regex sont comme des licornes : tout le monde en parle, personne les a vues.\", \"humour_reussi\", \"Métaphore mythique + référence métier\"),\n", + " (\"joke-p16\", \"Un physicien, un biologiste et un chimiste voient 2 bâtiments. L'un entre, l'autre sort. 'Tiens, ils ont échangé.'\", \"humour_reussi\", \"Jeu de mots 'bâtiment entré/sorti' = observation absurde\"),\n", + " (\"joke-p17\", \"Que dit un informaticien quand il s'ennuie ? 'printf(mot)\\n'\", \"humour_reussi\", \"Référence C printf + absurdité minimale\"),\n", + " (\"joke-p18\", \"Si Dieu existe, il est Objective-C : tout est message.\", \"humour_reussi\", \"Paradoxe religieux + référence Apple dev\"),\n", + " (\"joke-p19\", \"Le temps est une illusion. Le décalage horaire, doublement.\", \"humour_reussi\", \"Référence Hitchhiker's Guide + jeu de mots\"),\n", + " (\"joke-p20\", \"Un photon entre dans un bar et commande une bière. Le barman dit 'Pour vous, c'est gratuit, on vous voit pas partir'.\", \"humour_reussi\", \"Physique quantique appliquée au bar + callback\"),\n", + " (\"joke-p21\", \"J'ai une blague sur les matrices, mais c'est hors de portée du public.\", \"humour_reussi\", \"Meta-blink humour + math\"),\n", + " (\"joke-p22\", \"Un chat roux dans une salle de serveurs est dangereux : il pourrait activer l'incident majeur.\", \"humour_reussi\", \"Internet cat roux = chaos + référence NOC\"),\n", + " (\"joke-p23\", \"Pourquoi les plongeurs plongent-ils toujours en arrière et jamais en avant ? Parce que sinon ils tomberaient dans le bateau.\", \"humour_reussi\", \"Logique absurde + inversion sens commun\"),\n", + " (\"joke-p24\", \"Le HTML n'est pas un langage de programmation. Et le plus dur, c'est de le dire à mon patron.\", \"humour_reussi\", \"Débat tech classique + référence hiérarchique\"),\n", + " (\"joke-p25\", \"Si vous pensez que personne ne s'intéresse à votre vie, regardez vos logs Git.\", \"humour_reussi\", \"Métaphore surveillance + callback dev\"),\n", + " (\"joke-p26\", \"Comment debug-on un avion ? On retire les composants un par un jusqu'à ce qu'il ne plante plus.\", \"humour_reussi\", \"Procédure debug absurde appliquée à l'avion\"),\n", + " (\"joke-p27\", \"Mieux vaut avoir un git pull que deux tu l'auras.\", \"humour_reussi\", \"Verbe 'avoir' double sens + référence git\"),\n", + " (\"joke-p28\", \"Mon chat a appris Python. Maintenant il chasse les exceptions au lieu des souris.\", \"humour_reussi\", \"Métaphore félin + référence Python try/except\"),\n", + " (\"joke-p29\", \"Les submodules Git, c'est comme les voisins : mieux vaut ne pas les déranger.\", \"humour_reussi\", \"Métaphore sociale + référence submodules (cf c.539 init)\"),\n", + " (\"joke-p30\", \"Il était une fois un UTF-8 qui ne savait pas où était la fin. Il était perdu dans un BOM.\", \"humour_reussi\", \"Référence BOM + métaphore conte initiatique\"),\n", + "]\n", + "positive_instances = [{\n", + " \"id\": j[0], \"texte\": j[1],\n", + " \"features\": {\"laugh\": True, \"reframe\": True, \"uptake\": True, \"refus\": False},\n", + " \"label\": j[2], \"justification\": j[3],\n", + " \"source\": \"blague-manuelle\",\n", + "} for j in POSITIVE_JOKES]\n", + "\n", + "# --- 3. Négatives (pas d'humour) : 20 ---\n", + "NEGATIVE_STATEMENTS = [\n", + " (\"neg-s01\", \"Il pleut aujourd'hui à Paris.\", \"rien\", \"Déclaration factuelle sans mécanisme humoristique\"),\n", + " (\"neg-s02\", \"Le PIB de la France en 2025 a augmenté de 0,3%.\", \"rien\", \"Statistique macro-économique, registre informatif\"),\n", + " (\"neg-s03\", \"Les soldes d'hiver commencent le 8 janvier 2026.\", \"rien\", \"Annonce commerciale factuelle\"),\n", + " (\"neg-s04\", \"Le périphérique parisien est fermé entre 22h et 6h ce soir.\", \"rien\", \"Information de circulation\"),\n", + " (\"neg-s05\", \"L'addition au restaurant était de 47 euros pour trois personnes.\", \"rien\", \"Récit factuel sans punchline\"),\n", + " (\"neg-s06\", \"Le cours de l'action a clôturé à 142,50 euros hier.\", \"rien\", \"Information boursière standard\"),\n", + " (\"neg-s07\", \"La réunion est reportée à mardi prochain à 14h.\", \"rien\", \"Communication administrative neutre\"),\n", + " (\"neg-s08\", \"Mon dentiste m'a donné rendez-vous le 15 mars.\", \"rien\", \"Information personnelle sans renversement\"),\n", + " (\"neg-s09\", \"Le livre fait 320 pages et pèse 450 grammes.\", \"rien\", \"Description physique factuelle\"),\n", + " (\"neg-s10\", \"La somme de deux et deux est quatre.\", \"rien\", \"Énoncé mathématique neutre\"),\n", + " (\"neg-s11\", \"L'avion décolle à 14h32 de la piste 27 droite.\", \"rien\", \"Annonce aéroport factuelle\"),\n", + " (\"neg-s12\", \"J'ai rendez-vous avec mon médecin à 10 heures demain.\", \"rien\", \"Information de planning\"),\n", + " (\"neg-s13\", \"Le train de 8h47 est supprimé ce matin.\", \"rien\", \"Information de trafic ferroviaire\"),\n", + " (\"neg-s14\", \"La température extérieure est de 7 degrés.\", \"rien\", \"Lecture thermométrique\"),\n", + " (\"neg-s15\", \"Mon numéro de téléphone est le 01 23 45 67 89.\", \"rien\", \"Énoncé de coordonnées\"),\n", + " (\"neg-s16\", \"Le mot 'table' a cinq lettres.\", \"rien\", \"Observation linguistique neutre\"),\n", + " (\"neg-s17\", \"L'année 2026 a commencé un jeudi.\", \"rien\", \"Information calendaire\"),\n", + " (\"neg-s18\", \"Le café coûte 2 euros à la machine de l'étage.\", \"rien\", \"Tarif sans contexte humoristique\"),\n", + " (\"neg-s19\", \"Mon chat s'appelle Pixel et il est roux.\", \"rien\", \"Information sur animal de compagnie\"),\n", + " (\"neg-s20\", \"J'ai fini mon rapport à 17 heures.\", \"rien\", \"Annonce de fin de tâche\"),\n", + "]\n", + "negative_instances = [{\n", + " \"id\": n[0], \"texte\": n[1],\n", + " \"features\": {\"laugh\": False, \"reframe\": False, \"uptake\": False, \"refus\": False},\n", + " \"label\": n[2], \"justification\": n[3],\n", + " \"source\": \"declaration-factuelle\",\n", + "} for n in NEGATIVE_STATEMENTS]\n", + "\n", + "# --- 4. Edge cases (4 catégories x 2-3) ---\n", + "EDGE_CASES = [\n", + " (\"edge-01\", \"Mon collègue a ri tellement fort pendant la réunion qu'il a éternué.\", \"rire_sans_recadrage\", \"Rire reflexe (éternuement) sans mécanisme de recadrage partagé\"),\n", + " (\"edge-02\", \"Elle riait nerveusement en attendant les résultats de l'analyse.\", \"rire_sans_recadrage\", \"Rire nerveux = réaction physiologique, pas partage de forme\"),\n", + " (\"edge-03\", \"J'ai chatouillé ma cousine et elle a ri aux éclats.\", \"rire_sans_recadrage\", \"Chatouille = stimulus physique direct, pas humour\"),\n", + " (\"edge-04\", \"'I told my wife she was drawing her eyebrows too high. She seemed surprised.' (Graham Chapman)\", \"recadrage_sans_rire\", \"Deadpan : le renversement est dans la chute, le ton reste neutre\"),\n", + " (\"edge-05\", \"'I'm on a whiskey diet. I've lost three days already.' (Tommy Cooper)\", \"recadrage_sans_rire\", \"Twist verbal sans rire explicite, registre sec britannique\"),\n", + " (\"edge-06\", \"'I used to think I was indecisive. But now I'm not so sure.'\", \"recadrage_sans_rire\", \"Recadrage meta sans marque d'humour audible\"),\n", + " (\"edge-07\", \"Mon oncle fait des blagues racistes à table. Tout le monde rit sauf moi.\", \"offensif_compris_non_partage\", \"Humour offensant, le mécanisme est compris (certains rient) mais l'auteur refuse d'y participer\"),\n", + " (\"edge-08\", \"'Vous les femmes, vous savez pas conduire.' J'ai entendu la blague, j'ai pas ri.\", \"offensif_compris_non_partage\", \"Sexisme ordinaire ; compréhension totale, refus de participation\"),\n", + " (\"edge-09\", \"Son copain a fait une blague sur mon poids. J'ai souri poliment.\", \"offensif_compris_non_partage\", \"Politesse vs refus ; le mécanisme est reconnu mais pas repris\"),\n", + " (\"edge-10\", \"Le chef a fait une blague blessante. Tout le service a ri par peur.\", \"offensif_compris_non_partage\", \"Rire de soumission (pas de partage authentique), registre professionnel\"),\n", + "]\n", + "edge_instances = [{\n", + " \"id\": e[0], \"texte\": e[1],\n", + " \"features\": {\"laugh\": e[2] == \"rire_sans_recadrage\",\n", + " \"reframe\": e[2] in (\"humour_reussi\", \"recadrage_sans_rire\"),\n", + " \"uptake\": e[2] == \"humour_reussi\",\n", + " \"refus\": e[2] == \"offensif_compris_non_partage\"},\n", + " \"label\": e[2], \"justification\": e[3],\n", + " \"source\": \"edge-case-curated\",\n", + "} for e in EDGE_CASES]\n", + "\n", + "CORPUS_DUR = arg_instances + positive_instances + negative_instances + edge_instances\n", + "\n", + "# Vérification acceptance #12756 : ≥100 instances\n", + "print(f\"[corpus] total : {len(CORPUS_DUR)} instances\")\n", + "assert len(CORPUS_DUR) >= 100, f\"acceptance ratée : {len(CORPUS_DUR)} < 100\"\n", + "\n", + "# Distribution par cellule\n", + "dist = Counter(c[\"label\"] for c in CORPUS_DUR)\n", + "print(f\"[corpus] distribution par label : {dict(dist)}\")\n", + "\n", + "# Distribution par source\n", + "src_dist = Counter(c[\"source\"] for c in CORPUS_DUR)\n", + "print(f\"[corpus] distribution par source : {dict(src_dist)}\")\n", + "\n", + "# Sanity check : au moins 5 instances par catégorie\n", + "for cat in CATEGORIES:\n", + " n = dist.get(cat, 0)\n", + " status = \"OK\" if n >= 5 else f\"⚠️ faible ({n})\"\n", + " print(f\"[corpus] {cat} : {n} instances {status}\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "interp-corpus", + "metadata": { + "papermill": { + "duration": 0.012466, + "end_time": "2026-10-04T00:14:24.177828+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:24.165362+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "### Lecture — 120 instances, 4 sources, distribution par cellule\n", "\n", - "- Le détecteur par partage **est meilleur** que la naïve sur le corpus minimal (P=1.000 / R=1.000 vs P=0.40 / R=1.00), et la différence est localisée exactement là où rire et partage **divergent** : les trois cellules `rire_sans_recadrage` (chatouille, contagion, nervosité) que la naïve range dans `humour_reussi` à tort, et la cellule `recadrage_sans_rire` (ironie froide) que la naïve range dans `rien` à tort. **Le partage de forme est la grandeur, le rire est un témoin commode mais partiel.**\n", - "- Le cas offensif (`offensif_compris_non_partage`, O1/O2) est isolé correctement par les deux détecteurs — c'est l'instance la plus instructive : la forme est perçue, le cadre change pour un seul agent, l'autre refuse d'y entrer.\n", + "La sortie confirme l'acceptance `≥ 100 instances` :\n", "\n", - "**Ce qui reste à faire** (tranche RECOVERABLE-MACHINE, hors scope de cette PR) :\n", + "- **Total : 120 instances** (60 Argumentum + 30 blagues positives manuelles + 20 déclarations factuelles + 10 edge cases), l'`assert` passe.\n", + "- **Distribution par label** : `humour_reussi` 48, `rien` 38, `recadrage_sans_rire` 13, `rire_sans_recadrage` 14, `offensif_compris_non_partage` 7. Aucune cellule n'est vide, toutes dépassent le seuil de 5 instances — le banc est statistiquement exploitable.\n", + "- **Distribution par source** : Argumentum 60, blague-manuelle 30, declaration-factuelle 20, edge-case-curated 10. Quatre sources, deux gratuites (Argumentum + manuel) et deux négatives (factuelle + edge) — la diversité protège contre le biais de source unique.\n", "\n", - "1. **Fusion physique** de 24b dans 24 — la matrice de préservation ci-dessus en est le contrat ; exécution sur une lane qui voit l'endpoint vLLM et le fetch Argumentum.\n", - "2. **Annotation indépendante des features** : annoter `laugh`/`reframe`/`uptake`/`refus` **depuis le texte**, sans voir le label, puis ré-appliquer ce détecteur inchangé. Sans cela, le F1=1,000 de 24b est tautologique.\n", - "3. **Campagne multi-annotateurs** (#12756) : faire porter le même corpus à ≥3 annotateurs et mesurer l'accord inter-annotateur avant toute conclusion sur l'appréciation.\n", + "Deux lectures structurelles pour la suite :\n", "\n", - "**Pourquoi cette PR est honnête** : elle **n'absorbe pas** ce qu'elle ne peut pas ré-exécuter. La matrice de préservation est déposée comme **contrat** pour la tranche suivante, pas comme **résultat**. Le compagnon 24b reste en place pour la tranche RECOVERABLE-MACHINE.\n" + "- **`humour_reussi` est surreprésentée (48/120 = 40 %)** parce qu'elle agrège l'Argumentum annoté `humour_reussi` (pop culture + relation intime par défaut) ET les 30 blagues positives manuelles. C'est attendu : la classe positive d'intérêt est enrichie pour avoir assez d'exemples.\n", + "- **`offensif_compris_non_partage` est la plus rare (7)** : seuls les 10 edge cases l'alimentent (moins les 3 attribués ailleurs). C'est la cellule qui testera le plus la discrimination fine du LLM en section 14." + ] + }, + { + "cell_type": "markdown", + "id": "4cc974f5", + "metadata": { + "papermill": { + "duration": 0.009235, + "end_time": "2026-10-04T00:14:24.197387+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:24.188152+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "## Détecteurs — règle vs partage (toy model, répliqué)\n", + "\n", + "On reprend les deux détecteurs du toy model GT-20 (ex-GT-24) :\n", + "\n", + "- **naïf** : stimulus = rire → `humour_reussi` si `laugh`, sinon `rien`\n", + "- **partage** : trois signaux (reframe + uptake + refus) → discrimination 5 cellules\n", + "\n", + "On y ajoute un **détecteur LLM** : `anthropic/claude-haiku-4.5` (canal épinglé\n", + "OpenRouter, cf cell[26]) reçoit le `texte` d'une\n", + "instance et doit répondre par une catégorie parmi les 5.\n", + "Verdict SOTA : SOTA-OK (endpoint OpenAI-compat invoqué HTTP, modèle et version\n", + "épinglés, écho provider capturé dans les sorties).\n", + "Pas de fallback dégradé ; en cas d'erreur réseau, on documente l'échec et\n", + "on NE PAS continuer avec un placeholder.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "bc3cafe6", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:14:24.217956Z", + "iopub.status.busy": "2026-10-04T00:14:24.217653Z", + "iopub.status.idle": "2026-10-04T00:14:24.226984Z", + "shell.execute_reply": "2026-10-04T00:14:24.225550Z" + }, + "papermill": { + "duration": 0.021508, + "end_time": "2026-10-04T00:14:24.228247+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:24.206739+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " arg-7.3.2 truth=rire_sans_recadrage naive=humour_reussi reframe=rire_sans_recadrage\n", + " arg-2.2.2 truth=recadrage_sans_rire naive=rien reframe=rien\n", + " arg-1.2.1 truth=rien naive=rien reframe=rien\n", + " arg-3.3.2 truth=humour_reussi naive=humour_reussi reframe=humour_reussi\n", + " arg-3.2.10 truth=humour_reussi naive=humour_reussi reframe=humour_reussi\n" + ] + } + ], + "source": [ + "# -*- coding: utf-8 -*-\n", + "# Réplication des deux détecteurs du toy model (naïf + partage)\n", + "def naive_detector(inst):\n", + " \"\"\"Détecteur naïf : tout rire est humour réussi.\"\"\"\n", + " return \"humour_reussi\" if inst[\"features\"][\"laugh\"] else \"rien\"\n", + "\n", + "def reframe_detector(inst):\n", + " \"\"\"Détecteur par partage : exige reframe + uptake, distingue refus.\"\"\"\n", + " f = inst[\"features\"]\n", + " if f[\"refus\"]:\n", + " return \"offensif_compris_non_partage\"\n", + " if f[\"reframe\"] and f[\"uptake\"]:\n", + " return \"humour_reussi\" if f[\"laugh\"] else \"recadrage_sans_rire\"\n", + " if f[\"laugh\"]:\n", + " return \"rire_sans_recadrage\"\n", + " return \"rien\"\n", + "\n", + "# Matrice de confusion générique\n", + "def confusion_matrix(instances, detector, cats=CATEGORIES):\n", + " M = {v: {p: 0 for p in cats} for v in cats}\n", + " for x in instances:\n", + " M[x[\"label\"]][detector(x)] += 1\n", + " return M\n", + "\n", + "def show_matrix(M, title):\n", + " print(f\"\\n=== {title} ===\")\n", + " cats = list(M.keys())\n", + " # En-tête (backslash évité pour compatibilité f-string Python <3.12)\n", + " header_label = \"Vérité / Prédit\"\n", + " print(f\"{header_label:<28}\" + \"\".join(f\"{c[:8]:>9}\" for c in cats))\n", + " for v in cats:\n", + " row = \"\".join(f\"{M[v][p]:>9d}\" for p in cats)\n", + " print(f\"{v:<28}{row}\")\n", + "\n", + "# Test rapide sur 5 instances\n", + "for inst in CORPUS_DUR[:5]:\n", + " print(f\" {inst['id']:<10} truth={inst['label']:<25} naive={naive_detector(inst):<25} reframe={reframe_detector(inst)}\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "d5841413", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:14:24.245710Z", + "iopub.status.busy": "2026-10-04T00:14:24.245339Z", + "iopub.status.idle": "2026-10-04T00:14:25.347888Z", + "shell.execute_reply": "2026-10-04T00:14:25.346444Z" + }, + "papermill": { + "duration": 1.112695, + "end_time": "2026-10-04T00:14:25.349313+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:24.236618+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[LLM test] arg-7.3.2 : truth=rire_sans_recadrage\n", + " pred='humour_reussi'\n", + " raw='humour_reussi'\n", + " latency=1087 ms\n" + ] + } + ], + "source": [ + "# -*- coding: utf-8 -*-\n", + "# Détecteur LLM — appel HTTP /chat/completions avec prompt structuré.\n", + "import json\n", + "import urllib.request\n", + "import urllib.error\n", + "\n", + "LLM_PROMPT_TEMPLATE = (\n", + "\n", + " \"Tu es un classifieur d'humour. Tu reçois un texte court (scénario, blague ou déclaration). \"\n", + "\n", + " \"Tu dois répondre UNIQUEMENT par une catégorie parmi :\\n\"\n", + "\n", + " \" - humour_reussi : rire + recadrage partagé\\n\"\n", + "\n", + " \" - rire_sans_recadrage : rire mais pas de partage\\n\"\n", + "\n", + " \" - recadrage_sans_rire : partage sans rire (humour sec)\\n\"\n", + "\n", + " \" - offensif_compris_non_partage : offensif, compris mais refusé\\n\"\n", + "\n", + " \" - rien : pas d'humour du tout\\n\"\n", + "\n", + " \"\\n\"\n", + "\n", + " \"Réponds UNIQUEMENT par le label exact, sans phrase ni explication.\\n\"\n", + "\n", + " \"\\n\"\n", + "\n", + " \"Texte : {texte}\\n\"\n", + "\n", + " \"Catégorie :\"\n", + "\n", + ")\n", + "\n", + "def llm_detector(inst, timeout=15):\n", + " \"\"\"Appel HTTP au endpoint OpenAI-compat (OpenRouter). Retourne (label, raw_response, latency_ms).\n", + " En cas d'erreur réseau, retourne (None, error_str, 0).\"\"\"\n", + " prompt = LLM_PROMPT_TEMPLATE.format(texte=inst[\"texte\"][:500])\n", + " body = {\n", + " \"model\": LLM_MODEL,\n", + " \"messages\": [{\"role\": \"user\", \"content\": prompt}],\n", + " \"max_tokens\": 50,\n", + " \"temperature\": 0.0,\n", + " }\n", + " # Qwen3.6 thinking mode consomme tout max_tokens en reasoning interne ;\n", + " # on le désactive pour obtenir la réponse directe au prompt. Paramètre\n", + " # limité aux familles qwen : inconnu d'autres fournisseurs (cf #14033).\n", + " if \"qwen\" in LLM_MODEL.lower():\n", + " body[\"chat_template_kwargs\"] = {\"enable_thinking\": False}\n", + " body = json.dumps(body).encode(\"utf-8\")\n", + " req = urllib.request.Request(\n", + " f\"{OPENAI_COMPAT_URL}/chat/completions\",\n", + " data=body,\n", + " headers={\n", + " \"Content-Type\": \"application/json\",\n", + " \"Authorization\": f\"Bearer {OPENAI_API_KEY}\",\n", + " },\n", + " )\n", + " t0 = time.time()\n", + " try:\n", + " with urllib.request.urlopen(req, timeout=timeout) as r:\n", + " resp = json.loads(r.read())\n", + " dt_ms = int((time.time() - t0) * 1000)\n", + " content = resp[\"choices\"][0][\"message\"][\"content\"].strip()\n", + " # Tolérance : le LLM peut ajouter du texte autour\n", + " label = None\n", + " for cat in CATEGORIES:\n", + " if cat in content.lower():\n", + " label = cat\n", + " break\n", + " if label is None and content.lower() in [c.lower() for c in CATEGORIES]:\n", + " label = next(c for c in CATEGORIES if c.lower() == content.lower())\n", + " return label, content, dt_ms\n", + " except urllib.error.URLError as e:\n", + " return None, f\"URLError: {e}\", 0\n", + " except Exception as e:\n", + " return None, f\"Error: {type(e).__name__}: {e}\", 0\n", + "\n", + "# Test 1 instance pour vérifier que le endpoint répond\n", + "test_inst = CORPUS_DUR[0]\n", + "test_label, test_raw, test_dt = llm_detector(test_inst)\n", + "print(f\"[LLM test] {test_inst['id']} : truth={test_inst['label']}\")\n", + "print(f\" pred={test_label!r}\")\n", + "print(f\" raw={test_raw!r}\")\n", + "print(f\" latency={test_dt} ms\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "d7d46a28", + "metadata": { + "papermill": { + "duration": 0.019933, + "end_time": "2026-10-04T00:14:25.384932+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:25.364999+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "## Ranking LLM — sous-ensemble pour mesure\n", + "\n", + "Pour ne pas consommer 120 appels LLM (et risquer de tomber sur le rate limit\n", + "ou un timeout réseau prolongé), on sélectionne un sous-ensemble **stratifié** de\n", + "30 instances : 6 par cellule de la matrice. Cela permet de mesurer les\n", + "tendances du LLM sans dépendance excessive à la disponibilité du endpoint.\n", + "\n", + "Critères : (1) stratification par label, (2) ≥2 sources représentées (Argumentum\n", + "+ manuel + edge), (3) ≤30 instances pour limiter latence cumulée.\n", + "\n", + "**Important — C.2 + C.4** : les sorties LLM sont committées dans le notebook\n", + "(papermill exécute la cellule ; les outputs sont dans le .ipynb). Les valeurs\n", + "citées dans le diagnostic sont issues de cette sortie committée.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "597cbf10", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:14:25.414703Z", + "iopub.status.busy": "2026-10-04T00:14:25.414217Z", + "iopub.status.idle": "2026-10-04T00:14:48.664043Z", + "shell.execute_reply": "2026-10-04T00:14:48.662661Z" + }, + "papermill": { + "duration": 23.26461, + "end_time": "2026-10-04T00:14:48.665154+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:25.400544+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[sample] ranking_set : 30 instances stratifiées\n", + "[sample] sources : {'blague-manuelle': 3, 'ArgumentumGames/Argumentum': 18, 'edge-case-curated': 6, 'declaration-factuelle': 3}\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[LLM batch] 5/30 traités — 0 échecs\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[LLM batch] 10/30 traités — 0 échecs\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[LLM batch] 15/30 traités — 0 échecs\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[LLM batch] 20/30 traités — 0 échecs\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[LLM batch] 25/30 traités — 0 échecs\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[LLM batch] 30/30 traités — 0 échecs\n", + "\n", + "[latence] min=557 ms, max=3803 ms, mean=774 ms, n=30\n", + "[latence] échecs : 0\n" + ] + } + ], + "source": [ + "# -*- coding: utf-8 -*-\n", + "# Sous-ensemble stratifié : 6 instances par cellule.\n", + "from collections import defaultdict\n", + "\n", + "by_label = defaultdict(list)\n", + "for inst in CORPUS_DUR:\n", + " by_label[inst[\"label\"]].append(inst)\n", + "\n", + "SAMPLE_SIZE = 6\n", + "ranking_set = []\n", + "for cat in CATEGORIES:\n", + " pool = by_label[cat]\n", + " if len(pool) >= SAMPLE_SIZE:\n", + " ranking_set.extend(random.sample(pool, SAMPLE_SIZE))\n", + " else:\n", + " # Si on n'a pas assez, on prend tout + on note le déficit\n", + " ranking_set.extend(pool)\n", + " print(f\"[sample] ⚠️ {cat} : seulement {len(pool)} instances (cible {SAMPLE_SIZE})\")\n", + "\n", + "print(f\"[sample] ranking_set : {len(ranking_set)} instances stratifiées\")\n", + "src_dist = Counter(c[\"source\"] for c in ranking_set)\n", + "print(f\"[sample] sources : {dict(src_dist)}\")\n", + "\n", + "# Appel LLM sur le sous-ensemble (avec mesure de latence)\n", + "llm_results = []\n", + "fails = []\n", + "for i, inst in enumerate(ranking_set, 1):\n", + " label, raw, dt_ms = llm_detector(inst)\n", + " llm_results.append({**inst, \"llm_pred\": label, \"llm_raw\": raw, \"latency_ms\": dt_ms})\n", + " if label is None:\n", + " fails.append((inst[\"id\"], raw))\n", + " if i % 5 == 0 or i == len(ranking_set):\n", + " print(f\"[LLM batch] {i}/{len(ranking_set)} traités — {len(fails)} échecs\")\n", + "\n", + "# Statistiques de latence\n", + "latencies = [r[\"latency_ms\"] for r in llm_results if r[\"latency_ms\"] > 0]\n", + "if latencies:\n", + " print(f\"\\n[latence] min={min(latencies)} ms, max={max(latencies)} ms, \"\n", + " f\"mean={sum(latencies)/len(latencies):.0f} ms, n={len(latencies)}\")\n", + "print(f\"[latence] échecs : {len(fails)}\")\n", + "for fid, fraw in fails:\n", + " print(f\" - {fid}: {fraw[:100]}\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "654ecae6", + "metadata": { + "papermill": { + "duration": 0.006578, + "end_time": "2026-10-04T00:14:48.679169+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:48.672591+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "## Matrices de confusion — règle vs partage vs LLM\n", + "\n", + "On compare trois détecteurs sur le sous-ensemble `ranking_set` :\n", + "\n", + "1. **Naïf** (règle : stimulus = rire)\n", + "2. **Partage** (règle : reframe + uptake)\n", + "3. **LLM** (`anthropic/claude-haiku-4.5` via OpenRouter, canal épinglé)\n", + "\n", + "Métrique clé : précision et recall sur la classe positive `humour_reussi`.\n", + "Le banc toy livrait déjà la structure ; on étend ici avec le LLM.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "751cceb1", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:14:48.702702Z", + "iopub.status.busy": "2026-10-04T00:14:48.702076Z", + "iopub.status.idle": "2026-10-04T00:14:48.712341Z", + "shell.execute_reply": "2026-10-04T00:14:48.710890Z" + }, + "papermill": { + "duration": 0.024367, + "end_time": "2026-10-04T00:14:48.714042+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:48.689675+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "=== Matrice — détecteur NAÏF (ranking_set) ===\n", + "Vérité / Prédit humour_r rire_san recadrag offensif rien\n", + "humour_reussi 6 0 0 0 0\n", + "rire_sans_recadrage 6 0 0 0 0\n", + "recadrage_sans_rire 0 0 0 0 6\n", + "offensif_compris_non_partage 0 0 0 0 6\n", + "rien 0 0 0 0 6\n", + "\n", + "=== Matrice — détecteur par PARTAGE (ranking_set) ===\n", + "Vérité / Prédit humour_r rire_san recadrag offensif rien\n", + "humour_reussi 6 0 0 0 0\n", + "rire_sans_recadrage 0 6 0 0 0\n", + "recadrage_sans_rire 0 0 0 0 6\n", + "offensif_compris_non_partage 0 0 0 6 0\n", + "rien 0 0 0 0 6\n", + "\n", + "[LLM] 30/30 instances classifiées par le LLM\n", + "\n", + "=== Matrice — détecteur LLM anthropic/claude-haiku-4.5 ===\n", + "Vérité / Prédit humour_r rire_san recadrag offensif rien\n", + "humour_reussi 5 0 0 0 1\n", + "rire_sans_recadrage 2 0 0 0 4\n", + "recadrage_sans_rire 6 0 0 0 0\n", + "offensif_compris_non_partage 3 2 0 1 0\n", + "rien 1 0 1 0 4\n" + ] + } + ], + "source": [ + "# -*- coding: utf-8 -*-\n", + "# Matrice de confusion naïve\n", + "M_naive = confusion_matrix(ranking_set, naive_detector)\n", + "show_matrix(M_naive, \"Matrice — détecteur NAÏF (ranking_set)\")\n", + "\n", + "# Matrice de confusion partage\n", + "M_reframe = confusion_matrix(ranking_set, reframe_detector)\n", + "show_matrix(M_reframe, \"Matrice — détecteur par PARTAGE (ranking_set)\")\n", + "\n", + "# Matrice de confusion LLM — sur les instances où le LLM a répondu\n", + "instances_with_pred = [r for r in llm_results if r[\"llm_pred\"] is not None]\n", + "print(f\"\\n[LLM] {len(instances_with_pred)}/{len(llm_results)} instances classifiées par le LLM\")\n", + "\n", + "if instances_with_pred:\n", + " M_llm = {v: {p: 0 for p in CATEGORIES} for v in CATEGORIES}\n", + " for r in instances_with_pred:\n", + " M_llm[r[\"label\"]][r[\"llm_pred\"]] += 1\n", + " show_matrix(M_llm, f\"Matrice — détecteur LLM {LLM_MODEL}\")\n", + "else:\n", + " print(\"[LLM] Aucun résultat exploitable — endpoint non accessible\")\n", + " M_llm = None\n" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "2aeeaa32", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:14:48.736853Z", + "iopub.status.busy": "2026-10-04T00:14:48.736245Z", + "iopub.status.idle": "2026-10-04T00:14:48.746728Z", + "shell.execute_reply": "2026-10-04T00:14:48.744971Z" + }, + "papermill": { + "duration": 0.022657, + "end_time": "2026-10-04T00:14:48.748028+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:48.725371+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Détecteur Precision Recall F1 TP FP FN TN\n", + "Naïf 0.500 1.000 0.667 6 6 0 18\n", + "Partage 1.000 1.000 1.000 6 0 0 24\n", + "LLM claude-haiku-4.5 0.294 0.833 0.435 5 12 1 12\n" + ] + } + ], + "source": [ + "# -*- coding: utf-8 -*-\n", + "# Précision et recall sur humour_reussi (la classe 'difficile').\n", + "def precision_recall(instances, detector, positive=\"humour_reussi\"):\n", + " tp = fp = fn = tn = 0\n", + " for x in instances:\n", + " pred = detector(x) == positive\n", + " truth = x[\"label\"] == positive\n", + " if pred and truth: tp += 1\n", + " elif pred and not truth: fp += 1\n", + " elif (not pred) and truth: fn += 1\n", + " else: tn += 1\n", + " prec = tp / (tp + fp) if (tp + fp) > 0 else 0\n", + " rec = tp / (tp + fn) if (tp + fn) > 0 else 0\n", + " f1 = 2 * prec * rec / (prec + rec) if (prec + rec) > 0 else 0\n", + " return prec, rec, f1, tp, fp, fn, tn\n", + "\n", + "print(f\"{'Détecteur':<20}{'Precision':>11}{'Recall':>9}{'F1':>7}{'TP':>5}{'FP':>5}{'FN':>5}{'TN':>5}\")\n", + "for name, det in [(\"Naïf\", naive_detector), (\"Partage\", reframe_detector)]:\n", + " p, r, f, tp, fp, fn, tn = precision_recall(ranking_set, det)\n", + " print(f\"{name:<20}{p:>11.3f}{r:>9.3f}{f:>7.3f}{tp:>5d}{fp:>5d}{fn:>5d}{tn:>5d}\")\n", + "\n", + "if instances_with_pred:\n", + " p, r, f, tp, fp, fn, tn = precision_recall(instances_with_pred, lambda x: x[\"llm_pred\"])\n", + " llm_row_label = f\"LLM {LLM_MODEL.split('/')[-1]}\"\n", + " print(f\"{llm_row_label:<20}{p:>11.3f}{r:>9.3f}{f:>7.3f}{tp:>5d}{fp:>5d}{fn:>5d}{tn:>5d}\")\n", + "else:\n", + " print(\"[LLM] Pas de mesure (endpoint non accessible)\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "interp-prf1", + "metadata": { + "papermill": { + "duration": 0.011101, + "end_time": "2026-10-04T00:14:48.768518+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:48.757417+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "### Lecture — trois détecteurs, trois régimes de performance\n", + "\n", + "Le tableau `Precision / Recall / F1` sur la classe positive `humour_reussi` (sous-ensemble 30 instances) :\n", + "\n", + "- **Naïf** : P=0,500, R=1,000, F1=0,667 — il attrape tous les vrais positifs (R=1) mais au prix de 6 faux positifs (toute cellule `rire_sans_recadrage` est classée `humour_reussi` parce que `laugh=True`). La moitié de ses prédictions `humour_reussi` est fausse.\n", + "- **Partage** : P=1,000, R=1,000, F1=1,000 — parfait sur le sous-ensemble. La section circularité (cell[43-45]) montrera **pourquoi ce chiffre n'est pas un résultat** : les features sont dérivées du label, l'identité est constructive.\n", + "- **LLM `anthropic/claude-haiku-4.5`** (canal épinglé OpenRouter) : P=0,294, R=0,833, F1=0,435 — un régime inverse du naïf : sur 6 vrais `humour_reussi`, il en attrape 5 (R=0,833), mais en prédisant la classe positive bien trop large — 12 faux positifs pour 5 vrais positifs (P=0,294). Il ratisse large : presque tout ce qui ressemble de près à une blague est classé positif.\n", + "\n", + "La lecture honnête : le LLM **n'est pas évalué sur le même terrain** que les détecteurs à règles. Ces derniers lisent des features booléennes dérivées du label ; le LLM ne voit que le texte. Le F1=0,435 du LLM n'est donc pas « moins bon que 1,000 » — il est **incomparable** au 1,000, qui mesure une identité algébrique, pas une capacité de classification. La section circularité (cell[43-45]) formalise exactement cette réserve." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "7edaced2", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:14:48.794471Z", + "iopub.status.busy": "2026-10-04T00:14:48.793739Z", + "iopub.status.idle": "2026-10-04T00:14:48.804686Z", + "shell.execute_reply": "2026-10-04T00:14:48.802882Z" + }, + "papermill": { + "duration": 0.026175, + "end_time": "2026-10-04T00:14:48.805803+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:48.779628+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "=== Diagnostic LLM — erreurs notables ===\n", + "\n", + "Total erreurs : 20/30\n", + "\n", + " id=arg-3.2.5 truth=humour_reussi pred=rien\n", + " texte : [relation intime/vie de couple] L’amoureux des bêtes — baratineur: L’ami des chats, contexte: Le bar\n", + " raw LLM : rien\n", + "\n", + " id=arg-7.2.2 truth=rire_sans_recadrage pred=rien\n", + " texte : [vie personnelle/voisins et amis] Le jardin empoisonné — baratineur: Le voisin envieux, contexte: Le\n", + " raw LLM : rien\n", + "\n", + " id=arg-7.1.1 truth=rire_sans_recadrage pred=humour_reussi\n", + " texte : [vie personnelle/famille et enfance] King size — baratineur: Le parent, contexte: Un jeune vient d’o\n", + " raw LLM : humour_reussi\n", + "\n", + " id=edge-03 truth=rire_sans_recadrage pred=rien\n", + " texte : J'ai chatouillé ma cousine et elle a ri aux éclats.\n", + " raw LLM : rien\n", + "\n", + " id=arg-7.2.7 truth=rire_sans_recadrage pred=rien\n", + " texte : [vie personnelle/voisins et amis] Un ami qui vous veut du bien — baratineur: Une personne quelconque\n", + " raw LLM : rien\n", + "\n", + "[diagnostic] Accuracy brute LLM : 33.3% (10/30)\n" + ] + } + ], + "source": [ + "# -*- coding: utf-8 -*-\n", + "# Diagnostic qualitatif : 5 exemples où le LLM se trompe (ou réussit)\n", + "if instances_with_pred:\n", + " print(\"=== Diagnostic LLM — erreurs notables ===\\n\")\n", + " errors = [r for r in instances_with_pred if r[\"label\"] != r[\"llm_pred\"]]\n", + " print(f\"Total erreurs : {len(errors)}/{len(instances_with_pred)}\")\n", + " print()\n", + " for err in errors[:5]:\n", + " print(f\" id={err['id']:<10} truth={err['label']:<25} pred={err['llm_pred']}\")\n", + " print(f\" texte : {err['texte'][:100]}\")\n", + " print(f\" raw LLM : {err['llm_raw'][:80]}\")\n", + " print()\n", + "\n", + " # Taux d'accord avec vérité\n", + " n_correct = sum(1 for r in instances_with_pred if r[\"label\"] == r[\"llm_pred\"])\n", + " accuracy = n_correct / len(instances_with_pred)\n", + " print(f\"[diagnostic] Accuracy brute LLM : {accuracy:.1%} ({n_correct}/{len(instances_with_pred)})\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "c6ad3354", + "metadata": { + "papermill": { + "duration": 0.013635, + "end_time": "2026-10-04T00:14:48.832791+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:48.819156+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "## Test de circularité — scénarios Argumentum tenus à l'écart (#13306)\n", + "\n", + "Le F1 = 1,000 du détecteur maison n'est pas un résultat tant qu'une circularité n'est\n", + "pas écartée : un détecteur à règles qui sature sur le corpus où ses règles ont été\n", + "écrites mesure sa proximité à la procédure d'annotation, pas sa théorie.\n", + "\n", + "Protocole (#13306) : appliquer le détecteur **sans aucune modification** aux scénarios\n", + "Argumentum **non consommés** par la construction du corpus, et publier les deux F1\n", + "côte à côte avec leur intervalle de confiance bootstrap (leçon #12936 : c'est\n", + "l'incertitude d'échantillonnage qu'il faut afficher, pas une variance inter-seeds).\n", + "\n", + "Arithmétique corrigée au passage : l'issue #13306 annonce « 167 - 120 = 47 » scénarios\n", + "non consommés — ceci concatène le total du corpus de travail (120 instances, dont 60\n", + "manuelles hors Argumentum) avec la consommation Argumentum réelle (60 scénarios\n", + "échantillonnés). Le tenu-à-l'écart vrai est 167 - 60 = **107**, identifié ci-dessous\n", + "par un prédicat reproductible avec contrôle positif de disjonction." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "682fbe54", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:14:48.853140Z", + "iopub.status.busy": "2026-10-04T00:14:48.852750Z", + "iopub.status.idle": "2026-10-04T00:14:48.864164Z", + "shell.execute_reply": "2026-10-04T00:14:48.862733Z" + }, + "papermill": { + "duration": 0.023157, + "end_time": "2026-10-04T00:14:48.865672+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:48.842515+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[circularité] Argumentum total : 167\n", + "[circularité] consommés par CORPUS_DUR (k=60, seed 42) : 60\n", + "[circularité] tenus à l'écart : 107\n", + "[disjonction] |consommés INTER tenu-à-l'écart| = 0 (attendu 0)\n", + "[disjonction] |consommés UNION tenu-à-l'écart| = 167 (attendu 167)\n", + "[disjonction] ids arg-* du CORPUS_DUR INTER tenu-à-l'écart = 0 (attendu 0)\n", + "[circularité] labels du tenu-à-l'écart : {'rien': 28, 'recadrage_sans_rire': 17, 'humour_reussi': 37, 'rire_sans_recadrage': 14, 'offensif_compris_non_partage': 11}\n" + ] + } + ], + "source": [ + "# -*- coding: utf-8 -*-\n", + "# Identification des scénarios NON consommés + contrôle POSITIF de disjonction (#13306).\n", + "# Prédicat reproductible : est consommé tout scénario de labeled_arg dont le path\n", + "# figure dans arg_sample (random.seed(42), k=60, cell[32]) ; tenu-à-l'écart = le reste.\n", + "consumed_paths = {r[\"path\"] for r in arg_sample}\n", + "heldout_arg = [r for r in labeled_arg if r[\"path\"] not in consumed_paths]\n", + "print(f\"[circularité] Argumentum total : {len(labeled_arg)}\")\n", + "print(f\"[circularité] consommés par CORPUS_DUR (k=60, seed 42) : {len(consumed_paths)}\")\n", + "print(f\"[circularité] tenus à l'écart : {len(heldout_arg)}\")\n", + "\n", + "# Contrôle positif de disjonction — montré, pas affirmé :\n", + "inter_paths = consumed_paths & {r[\"path\"] for r in heldout_arg}\n", + "union_paths = consumed_paths | {r[\"path\"] for r in heldout_arg}\n", + "corpus_arg_ids = {i[\"id\"] for i in CORPUS_DUR if i[\"id\"].startswith(\"arg-\")}\n", + "inter_ids = corpus_arg_ids & {\"arg-\" + r[\"path\"] for r in heldout_arg}\n", + "print(f\"[disjonction] |consommés INTER tenu-à-l'écart| = {len(inter_paths)} (attendu 0)\")\n", + "print(f\"[disjonction] |consommés UNION tenu-à-l'écart| = {len(union_paths)} (attendu {len(labeled_arg)})\")\n", + "print(f\"[disjonction] ids arg-* du CORPUS_DUR INTER tenu-à-l'écart = {len(inter_ids)} (attendu 0)\")\n", + "assert not inter_paths and len(union_paths) == len(labeled_arg) and not inter_ids\n", + "\n", + "# Construction des instances tenues à l'écart : IDENTIQUE à cell[32] — les features\n", + "# sont dérivées du label par la même fonction. Toute modification de cette\n", + "# construction invaliderait le test (acceptance #13306, critère 2).\n", + "def features_from_label(lab):\n", + " return {\n", + " \"laugh\": lab == \"humour_reussi\" or lab == \"rire_sans_recadrage\",\n", + " \"reframe\": lab == \"humour_reussi\" or lab == \"recadrage_sans_rire\",\n", + " \"uptake\": lab == \"humour_reussi\",\n", + " \"refus\": lab == \"offensif_compris_non_partage\",\n", + " }\n", + "heldout_instances = [{\n", + " \"id\": \"heldout-\" + r[\"path\"],\n", + " \"texte\": \"[\" + r[\"catégorie\"] + \"/\" + r[\"sous-catégorie\"] + \"] \" + r[\"titre\"],\n", + " \"features\": features_from_label(r[\"label\"]),\n", + " \"label\": r[\"label\"],\n", + " \"justification\": \"tenu à l'écart #13306 — construction identique à cell[32] (features dérivées du label)\",\n", + " \"source\": \"ArgumentumGames/Argumentum\",\n", + "} for r in heldout_arg]\n", + "print(f\"[circularité] labels du tenu-à-l'écart : {dict(Counter(x['label'] for x in heldout_instances))}\")" + ] + }, + { + "cell_type": "markdown", + "id": "interp-disjonction", + "metadata": { + "papermill": { + "duration": 0.012061, + "end_time": "2026-10-04T00:14:48.888703+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:48.876642+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "### Lecture — 60 consommés, 107 tenus à l'écart, disjonction prouvée\n", + "\n", + "Le contrôle de circularité #13306 repose sur un prédicat reproductible : tout scénario dont le `path` figure dans `arg_sample` (60 scénarios tirés avec `random.seed(42)` en cell[32]) est « consommé » ; les autres sont « tenus à l'écart ».\n", + "\n", + "- **60 consommés, 107 tenus à l'écart** (167 total) — l'arithmétique corrigée de l'issue #13306 (`167 - 60`, pas `167 - 120` qui concaténait corpus de travail et consommation Argumentum).\n", + "- **Disjonction prouvée par trois contrôles** : intersection des paths = 0, union = 167 (total), intersection des ids `arg-*` du `CORPUS_DUR` avec le tenu-à-l'écart = 0. L'`assert` passe — les ensembles sont mathématiquement disjoints, pas seulement « différents ».\n", + "- **Distribution du tenu-à-l'écart** : `humour_reussi` 37, `rien` 28, `recadrage_sans_rire` 17, `rire_sans_recadrage` 14, `offensif_compris_non_partage` 11 — proche de la distribution du consommé, donc le F1 sur le tenu-à-l'écart n'est pas trivialisé par une cellule vide.\n", + "\n", + "Le point critique pour la cellule suivante : les features des instances tenues à l'écart sont **construites par la même fonction** (`features_from_label`) que celles du corpus. C'est ce qui rend le F1=1,000 sur le tenu-à-l'écart **non informatif** — la circularité écartée est la plus grossière (surapprentissage des instances spécifiques), pas la structurelle (features dérivées du label)." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "92f330cc", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:14:48.907655Z", + "iopub.status.busy": "2026-10-04T00:14:48.907198Z", + "iopub.status.idle": "2026-10-04T00:14:50.158871Z", + "shell.execute_reply": "2026-10-04T00:14:50.157310Z" + }, + "papermill": { + "duration": 1.263616, + "end_time": "2026-10-04T00:14:50.160562+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:48.896946+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CORPUS_DUR (120, dont 60 manuelles) n= 120 TP= 48 FP= 0 FN= 0 P=1.000 R=1.000 F1=1.000 IC95=[1.000, 1.000]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Argumentum consommés (60) n= 60 TP= 18 FP= 0 FN= 0 P=1.000 R=1.000 F1=1.000 IC95=[1.000, 1.000]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Argumentum tenus à l'écart (107) n= 107 TP= 37 FP= 0 FN= 0 P=1.000 R=1.000 F1=1.000 IC95=[1.000, 1.000]\n", + "\n", + "=== Trace algébrique : label -> features (cell[32]) -> prédiction du détecteur (cell[34]) ===\n", + " humour_reussi -> détecteur : humour_reussi\n", + " rire_sans_recadrage -> détecteur : rire_sans_recadrage\n", + " recadrage_sans_rire -> détecteur : rien\n", + " offensif_compris_non_partage -> détecteur : offensif_compris_non_partage\n", + " rien -> détecteur : rien\n" + ] + } + ], + "source": [ + "# -*- coding: utf-8 -*-\n", + "# F1 côte à côte (métrique identique à cell[40]) + IC bootstrap + trace algébrique.\n", + "def bootstrap_f1_ci(instances, detector, n_draws=5000, seed=13306):\n", + " \"\"\"IC percentile 95% par bootstrap non paramétrique (rééchantillonnage des\n", + " instances avec remise). Mesure l'incertitude d'échantillonnage du F1 —\n", + " pas une variance inter-seeds (leçon #12936).\"\"\"\n", + " rng = random.Random(seed)\n", + " n = len(instances)\n", + " f1s = []\n", + " for _ in range(n_draws):\n", + " sample = [instances[rng.randrange(n)] for _ in range(n)]\n", + " f1s.append(precision_recall(sample, detector)[2])\n", + " f1s.sort()\n", + " return f1s[int(0.025 * n_draws)], f1s[int(0.975 * n_draws)]\n", + "\n", + "arg60 = [i for i in CORPUS_DUR if i[\"id\"].startswith(\"arg-\")]\n", + "for name, insts in [\n", + " (\"CORPUS_DUR (120, dont 60 manuelles)\", CORPUS_DUR),\n", + " (\"Argumentum consommés (60)\", arg60),\n", + " (\"Argumentum tenus à l'écart (107)\", heldout_instances),\n", + "]:\n", + " p, r, f1, tp, fp, fn, tn = precision_recall(insts, reframe_detector)\n", + " lo, hi = bootstrap_f1_ci(insts, reframe_detector)\n", + " print(f\"{name:<38} n={len(insts):>4} TP={tp:>3} FP={fp:>2} FN={fn:>2} \"\n", + " f\"P={p:.3f} R={r:.3f} F1={f1:.3f} IC95=[{lo:.3f}, {hi:.3f}]\")\n", + "\n", + "print()\n", + "print(\"=== Trace algébrique : label -> features (cell[32]) -> prédiction du détecteur (cell[34]) ===\")\n", + "for lab in CATEGORIES:\n", + " inst = {\"features\": features_from_label(lab)}\n", + " print(f\" {lab:<30} -> détecteur : {reframe_detector(inst)}\")" + ] + }, + { + "cell_type": "markdown", + "id": "interp-bootstrap", + "metadata": { + "papermill": { + "duration": 0.010788, + "end_time": "2026-10-04T00:14:50.183954+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:50.173166+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "### Lecture — F1=1,000 partout, IC dégénéré, et c'est précisément le problème\n", + "\n", + "Les lignes rendent le même verdict `P=1,000 R=1,000 F1=1,000` avec un **intervalle de confiance bootstrap `[1,000, 1,000]`** — c'est-à-dire dégénéré (largeur nulle).\n", + "\n", + "- **Sur le tenu-à-l'écart (107)** : le F1 tient, donc la circularité grossière (surapprentissage des instances spécifiques du corpus) est écartée — c'est la conclusion de #13306.\n", + "- **Mais l'IC dégénéré est la signature d'un pipeline déterministe**, pas d'une mesure confiante : un bootstrap non paramétrique sur un classifieur qui est une fonction déterministe des labels rend toujours la même valeur, donc un intervalle de largeur nulle. Ce n'est pas une forte confiance, c'est l'absence de stochasticité.\n", + "- **La trace algébrique** l'explique : `label → features_from_label → reframe_detector` est une **involution** (sauf pour `recadrage_sans_rire` qui tombe en `rien` — un cas où le détecteur est strictement plus conservateur que l'annotation). Le détecteur inverse la construction des features, donc il ne peut pas se tromper sur un Argumentum, fût-il tenu à l'écart.\n", + "\n", + "La réserve structurelle est posée en cell[45] : le F1=1,000 **ne mesure pas la théorie du partage sur le corpus Argumentum**, il mesure l'identité de construction features ↔ label. L'écart avec le LLM épinglé (haiku-4.5, F1 = 0,435) n'est pas un résultat : c'est l'écart entre un détecteur évalué sur son terrain de construction et un modèle évalué hors du sien. La voie de validation réelle est #12756 (features annotées depuis le texte, indépendamment du label)." + ] + }, + { + "cell_type": "markdown", + "id": "ff219036", + "metadata": { + "papermill": { + "duration": 0.013186, + "end_time": "2026-10-04T00:14:50.209606+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:50.196420+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "### Verdict : `CIRCULARITE_GROSSIERE_ECARTEE` — avec réserve structurelle majeure\n", + "\n", + "Par la règle de décision de #13306, le F1 tient sur le tenu-à-l'écart → la\n", + "circularité **la plus grossière** (surapprentissage des instances spécifiques du\n", + "corpus) est écartée. Mais la trace algébrique ci-dessus montre **pourquoi il ne\n", + "pouvait pas en être autrement** : sur les instances Argumentum, les features sont\n", + "calculées À PARTIR du label annoté (cell[32]), et le détecteur inverse cette\n", + "fonction — seul `humour_reussi` produit `reframe + uptake`, donc précision =\n", + "rappel = 1 **par construction**, sur n'importe quel échantillon Argumentum,\n", + "tenu-à-l'écart compris. L'intervalle bootstrap dégénéré `[1.000, 1.000]` est la\n", + "signature d'un pipeline déterministe, pas celle d'une mesure confiante.\n", + "\n", + "Conséquence directe : le F1 = 1,000 du banc **ne mesure pas la théorie du partage\n", + "sur le corpus Argumentum** — il mesure l'identité de construction features ↔\n", + "label. Tant que les features ne sont pas annotées indépendamment du label,\n", + "l'écart avec le LLM épinglé (haiku-4.5, F1 = 0,435) n'est pas un résultat : c'est l'écart entre un\n", + "détecteur évalué sur son terrain de construction et un modèle évalué hors du\n", + "sien.\n", + "\n", + "Suites (hors scope #13306, critère 5 — LLM non re-testé ici) :\n", + "1. **#12756** (campagne multi-annotateurs) reste la voie de validation réelle ;\n", + "2. variante bas coût : annoter les features **depuis le texte**, sans voir le\n", + " label, puis ré-appliquer ce détecteur inchangé — seule façon de donner un\n", + " contenu au chiffre." + ] + }, + { + "cell_type": "markdown", + "id": "gt24b-paires-intro", + "metadata": { + "papermill": { + "duration": 0.010997, + "end_time": "2026-10-04T00:14:50.231198+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:50.220201+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "## Paires minimales « unfun » — détection, appréciation et explication indépendantes (#14033)\n", + "\n", + "**Le défaut que cette section répare.** Le meilleur détecteur du banc ci-dessus est *circulaire par construction* : la cellule de corpus dérive les features (`laugh`, `reframe`, `uptake`, `refus`) **du label**, puis la règle inverse cette dérivation — d'où le F1 = 1,000 et son IC dégénéré. En outre, les négatives du corpus initial (déclarations factuelles : météo, bourse, administration) viennent d'un **autre domaine lexical** que les positives (blagues d'informaticiens) : un classifieur de surface y réussit par raccourci lexical, pas par compréhension de l'humour.\n", + "\n", + "**Le protocole (Horvitz et al., ACL 2024).** On construit des **paires minimales** : pour chaque blague humaine du corpus commité, une contrepartie « unfun » éditée à la main qui **conserve sujet, longueur et registre** et ne retire que le mécanisme (l'incongruité). Les négatifs du banc apparié ne proviennent donc **jamais d'un autre domaine**. Trois questions, mesurées **indépendamment** (Loakman et al., Findings EMNLP 2025 : détection, appréciation et explication sont des tâches distinctes qui se dégradent différemment) :\n", + "\n", + "1. **détection** — le texte porte-t-il un mécanisme humoristique ? (macro-F1, par forme) ;\n", + "2. **appréciation** — à quel degré est-il drôle ? (échelle ordinale 0–3 à la JEST ; κ quadratique pondéré + ρ de Spearman ; Toplyn & Amir, ICCC 2026, documentent que JEST est limitée aux textes conversationnels courts et aux adultes américains — réserve explicite) ;\n", + "3. **explication** — quelles incongruités, références et normes rendent le mécanisme intelligible ? (grille humaine explicite, exactitude/complétude).\n", + "\n", + "**Gel avant mesure.** Le split construction/test est gelé et haché (SHA-256) **avant toute évaluation** ; aucune règle ni aucun seuil n'est retouché après lecture du test. Le détecteur circulaire initial est **reproduit comme baseline de contrôle** — il doit rendre F1 = 1 sur ce split, ce qui démontre la vacuité de la métrique quand les features dérivent du label.\n", + "\n", + "**Canal de jugement épinglé.** Tous les appels LLM passent par OpenRouter, modèle **`anthropic/claude-haiku-4.5`** (écho de version capturé dans les sorties) — le endpoint LAN vLLM est injoignable depuis cette lane (HTTP 000 mesuré). La construction des paires est **humaine** (éditée à la main par l'auteur du corpus), pas générée par le modèle évalué.\n", + "\n", + "**Sources, chemins canoniques** (gisement partagé, jamais committées dans le dépôt) :\n", + "\n", + "- Horvitz et al., *Getting Serious about Humor* (ACL 2024) — `G:\\Mon Drive\\MyIA\\IA\\Bibliographie IA\\MachineLearning\\Computational Humor\\2024 - Horvitz et al - Getting Serious about Humor.pdf`\n", + "- Loakman, Thorne & Lin, *Comparing Apples to Oranges* (Findings EMNLP 2025) — `G:\\Mon Drive\\MyIA\\IA\\Bibliographie IA\\MachineLearning\\Computational Humor\\2025 - Loakman et al - Comparing Apples to Oranges.pdf`\n", + "- Toplyn & Amir, *JEST* (ICCC 2026) — `G:\\Mon Drive\\MyIA\\IA\\Bibliographie IA\\MachineLearning\\Computational Humor\\2026 - Toplyn and Amir - JEST.pdf`" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "gt24b-paires-data", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:14:50.257949Z", + "iopub.status.busy": "2026-10-04T00:14:50.257613Z", + "iopub.status.idle": "2026-10-04T00:14:50.303195Z", + "shell.execute_reply": "2026-10-04T00:14:50.301320Z" + }, + "papermill": { + "duration": 0.061761, + "end_time": "2026-10-04T00:14:50.304462+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:50.242701+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[paires] 30 paires, formes : {'sociale': 8, 'pun': 11, 'topical': 11}, tranche OOD code-mixé : 8\n", + "[paires] 30/30 textes humour verbatim du corpus (assert de fidélité passé)\n" + ] + } + ], + "source": [ + "# -*- coding: utf-8 -*-\n", + "# PAIRES_MINIMALES — 30 paires tirees du corpus commit (POSITIVE_JOKES, cell[35]).\n", + "# Les textes humour (4e champ) sont les textes EXACTS du corpus, accents reels\n", + "# compris. Chaque paire : (id, forme, ood, texte_humour, texte_unfun,\n", + "# note_annotateur_humour, note_annotateur_unfun,\n", + "# mecanisme_attendu, justification_edit)\n", + "# - forme : pun (jeu de mots) / sociale (blague sociale intemporelle) /\n", + "# topical (reference culturelle ou metier d'epoque)\n", + "# - ood : tranche hors distribution = texte code-mixe FR/EN\n", + "# - mecanisme_attendu : grille explicite [(element, [mots-cles FR/EN]), ...] ;\n", + "# le 1er element = le NOYAU (l'incongruite essentielle). Le scoring (cell\n", + "# explication) normalise casse + accents puis cherche les mots-cles.\n", + "# - notes 0-3 : annotation humaine unique, gelees a la construction AVANT toute\n", + "# evaluation (limite annotateur unique : cf tache appreciation).\n", + "# - justification_edit : ce que l'edition retire et ce qu'elle conserve.\n", + "# AUCUN champ ci-dessous ne derive d'une sortie de modele.\n", + "\n", + "PAIRES_MINIMALES = [\n", + " (\"paire-p01\", \"sociale\", False,\n", + " \"Un informaticien rentre dans un bar et dit : 'je voudrais une bière,\",\n", + " \"Un informaticien rentre dans un bar et dit : 'je voudrais une bière bien fraîche.'\",\n", + " 2, 0,\n", + " [(\"refrain inachevé 'je voudrais'\", [\"refrain\", \"repetition\", \"x10\", \"dix fois\", \"inacheve\"]),\n", + " (\"structure d'accumulation absurde\", [\"accumul\", \"absurd\", \"en boucle\", \"incantation\"])],\n", + " \"Achever la phrase platement ('bien fraîche') supprime le refrain suspendu ; sujet, citation et longueur conservés.\"),\n", + " (\"paire-p02\", \"pun\", False,\n", + " \"Pourquoi les développeurs confondent Halloween et Noël ? Parce que Oct 31 == Dec 25.\",\n", + " \"Pourquoi les développeurs évoquent Halloween et Noël ? Parce que Oct 31 vient avant Dec 25.\",\n", + " 3, 0,\n", + " [(\"lecture octale de 31\", [\"octal\", \"base 8\", \"base huit\"]),\n", + " (\"équivalence numérique inattendue\", [\"equival\", \"31\", \"25\", \"egale\", \"meme nombre\"]),\n", + " (\"double lecture de la notation\", [\"decimal\", \"notation\", \"double lecture\", \"deux sens\", \"ambigu\"])],\n", + " \"Remplacer l'égalité incongrue (==) par l'ordre calendaire littéral 'vient avant' ; notations Oct/Dec et fêtes conservées.\"),\n", + " (\"paire-p03\", \"pun\", False,\n", + " \"Il y a 10 types de personnes au monde : ceux qui comprennent le binaire et ceux qui ne le comprennent pas.\",\n", + " \"Il y a à peu près 10 types de personnes au monde : ceux qui comprennent le binaire et ceux qui ne le comprennent pas.\",\n", + " 3, 0,\n", + " [(\"le '10' lu en base 2\", [\"10\", \"binaire\", \"base 2\", \"zero un\", \"deux en base dix\"]),\n", + " (\"méta-récursivité de l'énoncé\", [\"meta\", \"lui-meme\", \"recursif\", \"auto\"]),\n", + " (\"double lecture du nombre\", [\"double lecture\", \"deux sens\", \"ambigu\", \"dix\"])],\n", + " \"L'approximation 'à peu près' force la lecture décimale triviale du '10' ; la phrase reste identique ailleurs.\"),\n", + " (\"paire-p04\", \"topical\", True,\n", + " \"Un SQL entre dans un bar, voit deux tables et leur dit : 'SELECT * FROM...'\",\n", + " \"Un SQL entre dans un bar, voit deux tables et demande laquelle est libre.\",\n", + " 2, 0,\n", + " [(\"double sens de 'tables'\", [\"table\", \"tables\", \"base de donnees\"]),\n", + " (\"requête SELECT\", [\"select\", \"requete\", \"from\", \"interroge\"]),\n", + " (\"personnification du langage\", [\"personnifi\", \"sql parle\", \"langage qui parle\"])],\n", + " \"Retirer la punchline 'SELECT * FROM...' au profit d'une question littérale de bar ; la personne (SQL) et le décor (tables) restent.\"),\n", + " (\"paire-p05\", \"sociale\", False,\n", + " \"Combien d'ingénieurs faut-il pour changer une ampoule ? Aucun, c'est un problème hardware.\",\n", + " \"Combien d'ingénieurs faut-il pour changer une ampoule ? Un seul, muni d'un escabeau.\",\n", + " 2, 0,\n", + " [(\"inversion de responsabilité\", [\"responsabilite\", \"rejet\", \"renvoi\", \"pas au\"]),\n", + " (\"clivage logiciel/matériel\", [\"hardware\", \"materiel\", \"software\", \"logiciel\"]),\n", + " (\"réponse 'aucun' déflationnaire\", [\"aucun\", \"zero\", \"pas besoin d'ingenieur\"])],\n", + " \"La réponse déflationnaire 'aucun + hardware' devient une réponse littérale ('un seul, escabeau') ; format question-réponse conservé.\"),\n", + " (\"paire-p06\", \"pun\", False,\n", + " \"Je suis tombé amoureuse d'une fonction quadratique. Mais elle avait deux racines.\",\n", + " \"Je suis tombé amoureuse d'une fonction quadratique. Mais elle avait deux zéros.\",\n", + " 2, 0,\n", + " [(\"double sens de 'racines'\", [\"racine\", \"root\", \"double sens\"]),\n", + " (\"métaphore amoureuse mathématique\", [\"amoureus\", \"relation\", \"coeur\", \"sentiment\"]),\n", + " (\"propriété de la quadratique\", [\"quadratique\", \"deux solutions\", \"deux racines\", \"polynome\"])],\n", + " \"'racines' (double lecture sentimentale/math) remplacé par 'zéros' (terme technique neutre) ; la confession amoureuse est intacte.\"),\n", + " (\"paire-p07\", \"topical\", True,\n", + " \"Un null et un undefined entrent dans un bar. Le barman dit 'On accepte pas les non-définis ici'.\",\n", + " \"Un null et un undefined entrent dans un bar. Le barman leur demande ce qu'ils veulent boire.\",\n", + " 2, 0,\n", + " [(\"référence JavaScript\", [\"null\", \"undefined\", \"javascript\", \"js\", \"typage\"]),\n", + " (\"double sens de 'non-définis'\", [\"non defini\", \"non-defini\", \"double sens\", \"exclu\"]),\n", + " (\"mécanisme de blague de bar\", [\"bar\", \"barman\", \"refus\", \"entrent\"])],\n", + " \"La réplique excluante ('on accepte pas les non-définis') devient un service ordinaire ; le couple null/undefined demeure.\"),\n", + " (\"paire-p08\", \"topical\", True,\n", + " \"Je voulais te raconter une blague sur UDP... mais je sais si elle arrive.\",\n", + " \"Je voulais te raconter une blague sur UDP... mais je ne sais pas si elle arrive.\",\n", + " 3, 0,\n", + " [(\"UDP sans garantie de livraison\", [\"udp\", \"best-effort\", \"best effort\", \"sans garantie\", \"livraison\", \"paquet\"]),\n", + " (\"négation manquante = paquet perdu\", [\"negation\", \"ne...pas manquant\", \"paquet perdu\", \"omis\"]),\n", + " (\"méta : la phrase incarne le protocole\", [\"meta\", \"la phrase elle-meme\", \"incarne\"])],\n", + " \"Restaurer la négation grammaticale ('ne...pas') désamorce la chute : la phrase redevient littérale.\"),\n", + " (\"paire-p09\", \"pun\", False,\n", + " \"Le père Noël a-t-il déjà eu un problème de pile ? Non, il a toujours des piles neuves.\",\n", + " \"Le père Noël a-t-il déjà eu un problème de pile ? Non, ses lampes fonctionnent toujours bien.\",\n", + " 1, 0,\n", + " [(\"double sens de 'pile(s)'\", [\"pile\", \"piles\", \"double sens\"]),\n", + " (\"réponse par l'objet électrique\", [\"batterie\", \"electrique\", \"neuve\"]),\n", + " (\"cadre Noël\", [\"noel\", \"pere noel\"])],\n", + " \"L'écho 'piles neuves' (reprise du mot de la question) remplacé par une réponse détournée ('lampes') ; le cadre questions-réponses reste.\"),\n", + " (\"paire-p10\", \"pun\", False,\n", + " \"Pourquoi le café est-il si bon au travail ? Parce qu'il est fraîchement moulu par l'échéance.\",\n", + " \"Pourquoi le café est-il si bon au travail ? Parce qu'il est fraîchement moulu chaque matin.\",\n", + " 2, 0,\n", + " [(\"métaphore échéance/mouture\", [\"echeance\", \"deadline\", \"moulu\", \"mouture\"]),\n", + " (\"double sens de 'fraîchement moulu'\", [\"fraichement\", \"double sens\", \"moulu par\"]),\n", + " (\"registre bureau\", [\"travail\", \"bureau\", \"cafe\"])],\n", + " \"'par l'échéance' (agent incongru) devient 'chaque matin' (circonstance banale) ; question et registre identiques.\"),\n", + " (\"paire-p11\", \"pun\", True,\n", + " \"J'ai essayé d'écrire une blague sur les coroutines, mais je n'arrive pas à la yield.\",\n", + " \"J'ai essayé d'écrire une blague sur les coroutines, mais je n'arrive pas à la terminer.\",\n", + " 2, 0,\n", + " [(\"yield : mot-clé et céder/livrer\", [\"yield\", \"ceder\", \"mot-cle\"]),\n", + " (\"référence coroutines\", [\"coroutine\", \"async\", \"generateur\"]),\n", + " (\"double lecture du verbe\", [\"double lecture\", \"deux sens\", \"je n'arrive pas\"])],\n", + " \"Le mot-clé 'yield' (double lecture) remplacé par le verbe banal 'terminer'.\"),\n", + " (\"paire-p12\", \"topical\", True,\n", + " \"Docker, Kubernetes, Prometheus, Grafana. On m'a dit que c'était simple, alors je stack.\",\n", + " \"Docker, Kubernetes, Prometheus, Grafana. On m'a dit que c'était simple, alors je m'y mets.\",\n", + " 2, 0,\n", + " [(\"double sens de 'stack'\", [\"stack\", \"empiler\", \"pile\", \"stacker\"]),\n", + " (\"accumulation d'outils DevOps\", [\"docker\", \"kubernetes\", \"prometheus\", \"grafana\", \"outils\"]),\n", + " (\"ironie de la promesse de simplicité\", [\"simple\", \"ironie\", \"promesse\"])],\n", + " \"'je stack' (anglicisme-jeu) remplacé par 'je m'y mets' (locution neutre) ; l'énumération d'outils reste.\"),\n", + " (\"paire-p13\", \"pun\", False,\n", + " \"Mon compilateur et moi on a une relation stable : il compile, je pleure.\",\n", + " \"Mon compilateur et moi on a une relation stable : il compile, je vérifie.\",\n", + " 2, 0,\n", + " [(\"double sens de 'stable'\", [\"stable\", \"build\", \"relation\"]),\n", + " (\"inversion émotionnelle (pleure alors que ça compile)\", [\"pleure\", \"inversion\", \"absurd\", \"alors que\"]),\n", + " (\"personnification du compilateur\", [\"compilateur\", \"relation\"])],\n", + " \"'je pleure' (réaction inversée, incongrue) devient 'je vérifie' (réaction attendue) ; 'relation stable' conservé.\"),\n", + " (\"paire-p14\", \"sociale\", False,\n", + " \"J'ai un ami palindrome. On ne peut pas se différencier.\",\n", + " \"J'ai un ami palindrome. C'est un mot comme un autre.\",\n", + " 2, 0,\n", + " [(\"propriété du palindrome appliquée à l'amitié\", [\"palindrome\", \"deux sens\", \"miroir\", \"endroit envers\"]),\n", + " (\"absurdité de la catégorie (ami palindrome)\", [\"ami\", \"absurd\", \"personne\", \"mot\"]),\n", + " (\"jeu sur la différenciation\", [\"differencier\", \"distinguer\", \"differents\"])],\n", + " \"La seconde phrase cesse d'appliquer la propriété du palindrome à la relation ; elle ramène le palindrome à un fait lexical.\"),\n", + " (\"paire-p15\", \"topical\", False,\n", + " \"Les regex sont comme des licornes : tout le monde en parle, personne les a vues.\",\n", + " \"Les regex sont comme des licornes : on en voit surtout dans les livres.\",\n", + " 2, 1,\n", + " [(\"simile absurde (les regex se voient partout)\", [\"regex\", \"licorne\", \"personne ne\", \"jamais vue\"]),\n", + " (\"véracité littérale fausse = incongruité\", [\"inversion\", \"faux\", \"exactement le contraire\"]),\n", + " (\"mythe du métier\", [\"mythe\", \"legende\", \"metier\", \"rumeur\"])],\n", + " \"La chute inversée ('personne les a vues') devient une vérité littérale sur les licornes ; le cadre de comparaison reste.\"),\n", + " (\"paire-p16\", \"sociale\", False,\n", + " \"Un physicien, un biologiste et un chimiste voient 2 bâtiments. L'un entre, l'autre sort. 'Tiens, ils ont échangé.'\",\n", + " \"Un physicien, un biologiste et un chimiste voient 2 bâtiments. L'un entre, l'autre sort. 'Tiens, ils se croisent.'\",\n", + " 1, 0,\n", + " [(\"trois corps de métier (format classique)\", [\"physicien\", \"biologiste\", \"chimiste\", \"trois\"]),\n", + " (\"non-séquence finale ('ils ont échangé')\", [\"echange\", \"echangent\", \"non-sequence\", \"absurd\"]),\n", + " (\"banalisation d'une observation triviale\", [\"observ\", \"tiens\", \"remarque\"])],\n", + " \"'échangé' (verbe impossible pour des bâtiments) devient 'se croisent' (description littérale des faits).\"),\n", + " (\"paire-p17\", \"topical\", True,\n", + " \"Que dit un informaticien quand il s'ennuie ? 'printf(mot)\\n'\",\n", + " \"Que dit un informaticien quand il s'ennuie ? 'Il regarde par la fenêtre.'\",\n", + " 1, 0,\n", + " [(\"printf = dire/afficher\", [\"printf\", \"affiche\", \"print\", \"impression\"]),\n", + " (\"réponse en code à une question de parole\", [\"code\", \"reponse en code\", \"dire\"]),\n", + " (\"minimalisme absurde\", [\"minimal\", \"absurd\", \"laconique\"])],\n", + " \"La réponse-code ('printf') remplacée par une réponse en parole ordinaire ; la question reste.\"),\n", + " (\"paire-p18\", \"topical\", False,\n", + " \"Si Dieu existe, il est Objective-C : tout est message.\",\n", + " \"Si Dieu existe, il est Objective-C : les conventions sont strictes.\",\n", + " 2, 0,\n", + " [(\"parallèle théologie/paradigme\", [\"dieu\", \"theolog\", \"religion\", \"objective-c\"]),\n", + " (\"double sens de 'message' (passage de messages/révélation)\", [\"message\", \"passage de message\", \"revelation\", \"double sens\"]),\n", + " (\"absorption : tout est X\", [\"tout est\", \"toute chose\", \"omni\"])],\n", + " \"La proposition totalisante 'tout est message' (double lecture) remplacée par une remarque technique plate sur les conventions.\"),\n", + " (\"paire-p19\", \"pun\", False,\n", + " \"Le temps est une illusion. Le décalage horaire, doublement.\",\n", + " \"Le temps est une illusion. Le décalage horaire aussi.\",\n", + " 2, 0,\n", + " [(\"référence Hitchhiker's Guide\", [\"hitchhiker\", \"guide\", \"adam\", \"douglas\"]),\n", + " (\"jeu sur l'adverbe 'doublement'\", [\"doublement\", \"double\", \"doubly\"]),\n", + " (\"amplification en cascade\", [\"cascade\", \"encore plus\", \"amplifie\"])],\n", + " \"L'adverbe inattendu 'doublement' (chute) devient l'extension plate 'aussi' ; la première phrase demeure.\"),\n", + " (\"paire-p20\", \"topical\", False,\n", + " \"Un photon entre dans un bar et commande une bière. Le barman dit 'Pour vous, c'est gratuit, on vous voit pas partir'.\",\n", + " \"Un photon entre dans un bar et commande une bière. Le barman lui sert la bière et lui souhaite la bonne soirée.\",\n", + " 3, 0,\n", + " [(\"physique du photon (vitesse c, temps propre)\", [\"photon\", \"lumiere\", \"vitesse\", \"temps propre\", \"relativite\"]),\n", + " (\"incongruité : le barman applique la physique\", [\"barman\", \"gratuit\", \"voit pas partir\", \"incongrui\"]),\n", + " (\"blague de bar détournée\", [\"bar\", \"biere\", \"commande\"])],\n", + " \"La réplique physique du barman ('on vous voit pas partir') devient un service et une formule de politesse ordinaires.\"),\n", + " (\"paire-p21\", \"pun\", False,\n", + " \"J'ai une blague sur les matrices, mais c'est hors de portée du public.\",\n", + " \"J'ai une blague sur les matrices, mais elle est trop longue à raconter.\",\n", + " 1, 0,\n", + " [(\"double sens de 'portée' (range math/accessible)\", [\"portee\", \"range\", \"matrice\", \"math\"]),\n", + " (\"méta-humour : retenir la blague\", [\"meta\", \"retient\", \"ne la raconte pas\", \"promesse\"]),\n", + " (\"registre mathématique\", [\"matrice\", \"matrices\", \"algebre\"])],\n", + " \"'hors de portée' (jeu mathématique) remplacé par le motif banal 'trop longue à raconter'.\"),\n", + " (\"paire-p22\", \"topical\", False,\n", + " \"Un chat roux dans une salle de serveurs est dangereux : il pourrait activer l'incident majeur.\",\n", + " \"Un chat roux dans une salle de serveurs est dangereux : il pourrait débrancher un câble.\",\n", + " 1, 0,\n", + " [(\"mème du chat roux = chaos\", [\"chat roux\", \"meme\", \"internet\", \"chaos\"]),\n", + " (\"vocabulaire NOC/production\", [\"incident\", \"noc\", \"production\", \"severite\"]),\n", + " (\"exagération absurde du risque\", [\"exagere\", \"absurd\", \"risque\"])],\n", + " \"L'aboutissant spectaculaire ('activer l'incident majeur') devient un risque physique banal et plausible ('débrancher un câble').\"),\n", + " (\"paire-p23\", \"sociale\", False,\n", + " \"Pourquoi les plongeurs plongent-ils toujours en arrière et jamais en avant ? Parce que sinon ils tomberaient dans le bateau.\",\n", + " \"Pourquoi les plongeurs plongent-ils toujours en arrière et jamais en avant ? Parce que c'est plus simple pour repartir du bateau.\",\n", + " 3, 0,\n", + " [(\"logique absurde de la chute\", [\"tomberaient\", \"bateau\", \"logique absurde\", \"inversion\"]),\n", + " (\"format devinette\", [\"pourquoi\", \"devinette\", \"question\"]),\n", + " (\"géométrie inversée (avant = bateau)\", [\"en avant\", \"arriere\", \"geometrie\", \"sens\"])],\n", + " \"La chute géométriquement absurde ('tomberaient dans le bateau') devient une raison mécanique plausible ('repartir du bateau').\"),\n", + " (\"paire-p24\", \"topical\", False,\n", + " \"Le HTML n'est pas un langage de programmation. Et le plus dur, c'est de le dire à mon patron.\",\n", + " \"Le HTML n'est pas un langage de programmation. Et le plus dur, c'est de le documenter proprement.\",\n", + " 2, 0,\n", + " [(\"débat tech canonique\", [\"html\", \"langage de programmation\", \"debat\"]),\n", + " (\"tension hiérarchique (patron)\", [\"patron\", \"hierarch\", \"travail\", \"dire\"]),\n", + " (\"déplacement : difficulté sociale d'un fait technique\", [\"le plus dur\", \"difficile de dire\", \"social\"])],\n", + " \"La difficulté sociale ('dire à mon patron') devient une difficulté technique ('documenter proprement') ; l'affirmation technique reste.\"),\n", + " (\"paire-p25\", \"topical\", False,\n", + " \"Si vous pensez que personne ne s'intéresse à votre vie, regardez vos logs Git.\",\n", + " \"Si vous pensez que personne ne s'intéresse à votre vie, regardez vos notifications.\",\n", + " 2, 0,\n", + " [(\"métaphore de surveillance\", [\"surveill\", \"trace\", \"espion\", \"interesse\"]),\n", + " (\"logs Git comme trace de vie\", [\"log\", \"git\", \"historique\", \"commits\"]),\n", + " (\"réconfort ironique\", [\"personne ne\", \"ironie\", \"regarde\"])],\n", + " \"'logs Git' (trace technique détournée en preuve d'intérêt) remplacé par 'notifications' (objet littéralement fait pour ça).\"),\n", + " (\"paire-p26\", \"sociale\", False,\n", + " \"Comment debug-on un avion ? On retire les composants un par un jusqu'à ce qu'il ne plante plus.\",\n", + " \"Comment répare-t-on un avion ? On remplace les composants défectueux selon la procédure certifiée.\",\n", + " 3, 0,\n", + " [(\"transfert de la procédure de debug\", [\"debug\", \"bisection\", \"un par un\", \"procedure\"]),\n", + " (\"double sens de 'plante' (crash)\", [\"plante\", \"crash\", \"double sens\", \"tomber en panne\"]),\n", + " (\"danger absurde (avion de prod)\", [\"avion\", \"danger\", \"absurd\"])],\n", + " \"'debug-on' devient 'répare-t-on', la bisection incongrue devient la maintenance certifiée ; le sujet (avion, composants) reste.\"),\n", + " (\"paire-p27\", \"pun\", True,\n", + " \"Mieux vaut avoir un git pull que deux tu l'auras.\",\n", + " \"Mieux vaut faire un git pull régulier que de tout merger d'un coup.\",\n", + " 3, 0,\n", + " [(\"paronomase du dicton\", [\"dicton\", \"proverbe\", \"mieux vaut\", \"tu l'auras\"]),\n", + " (\"git pull substitué au mot attendu\", [\"git pull\", \"tirer\", \"fusion\"]),\n", + " (\"double lecture de l'avoir\", [\"avoir\", \"double sens\", \"posseder\"])],\n", + " \"La paronomase ('un git pull' / 'un qui tu l'auras') défusionnée en conseil technique plat.\"),\n", + " (\"paire-p28\", \"sociale\", False,\n", + " \"Mon chat a appris Python. Maintenant il chasse les exceptions au lieu des souris.\",\n", + " \"Mon chat a appris Python. Maintenant il marche sur le clavier au lieu de chasser les souris.\",\n", + " 2, 0,\n", + " [(\"chasse redirect vers les exceptions\", [\"chasse\", \"exception\", \"proie\", \"souris\"]),\n", + " (\"anthropomorphisme technique\", [\"chat\", \"python\", \"appris\", \"anthropomorph\"]),\n", + " (\"métabole 'au lieu de'\", [\"au lieu\", \"remplace\", \"desormais\"])],\n", + " \"L'appariement absurde (chasser des exceptions) devient un comportement félin réel (marcher sur le clavier) ; la structure 'au lieu des souris' reste.\"),\n", + " (\"paire-p29\", \"sociale\", False,\n", + " \"Les submodules Git, c'est comme les voisins : mieux vaut ne pas les déranger.\",\n", + " \"Les submodules Git, c'est une fonctionnalité à manier avec précaution.\",\n", + " 2, 0,\n", + " [(\"métaphore sociale (voisins)\", [\"voisin\", \"voisins\", \"deranger\", \"social\"]),\n", + " (\"folklore des submodules\", [\"submodule\", \"sous-module\", \"git\"]),\n", + " (\"conseil de sagesse détourné\", [\"mieux vaut\", \"sagesse\", \"conseil\"])],\n", + " \"La comparaison sociale ('comme les voisins') supprimée ; il reste une phrase technique prudente.\"),\n", + " (\"paire-p30\", \"pun\", True,\n", + " \"Il était une fois un UTF-8 qui ne savait pas où était la fin. Il était perdu dans un BOM.\",\n", + " \"Il était une fois un UTF-8 qui ne savait pas où était la fin. Il a trouvé la réponse dans la norme.\",\n", + " 2, 0,\n", + " [(\"conte détourné + jargon d'encodage\", [\"utf-8\", \"encodage\", \"bom\", \"conte\", \"il etait une fois\"]),\n", + " (\"BOM : le délimiteur qui égare\", [\"bom\", \"marqueur\", \"octet\", \"debut\"]),\n", + " (\"double lecture de 'la fin' (fin de chaîne/fin du conte)\", [\"fin\", \"chaine\", \"terminaison\", \"double lecture\"])],\n", + " \"La chute technique ('perdu dans un BOM') remplacée par un dénouement plat ('la réponse dans la norme') ; le cadre du conte reste.\"),\n", + "]\n", + "\n", + "FORMES = [\"pun\", \"sociale\", \"topical\"]\n", + "assert len(PAIRES_MINIMALES) == 30\n", + "assert all(p[1] in FORMES for p in PAIRES_MINIMALES)\n", + "n_par_forme = Counter(p[1] for p in PAIRES_MINIMALES)\n", + "n_ood = sum(1 for p in PAIRES_MINIMALES if p[2])\n", + "print(f\"[paires] {len(PAIRES_MINIMALES)} paires, formes : {dict(n_par_forme)}, tranche OOD code-mixé : {n_ood}\")\n", + "# Fidelite au corpus, verifiee AU RUN contre le corpus execute (cell[35]) :\n", + "# chaque texte humour doit etre le texte EXACT de POSITIVE_JOKES.\n", + "_corpus_par_id = {inst[\"id\"]: inst[\"texte\"] for inst in positive_instances}\n", + "for p in PAIRES_MINIMALES:\n", + " ref = _corpus_par_id[\"joke-\" + p[0].replace(\"paire-\", \"\")]\n", + " assert p[3] == ref, f\"{p[0]} : texte humour != corpus\\n paire : {p[3]!r}\\n corpus: {ref!r}\"\n", + "print(\"[paires] 30/30 textes humour verbatim du corpus (assert de fidélité passé)\")" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "gt24b-paires-gel", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:14:50.328138Z", + "iopub.status.busy": "2026-10-04T00:14:50.327873Z", + "iopub.status.idle": "2026-10-04T00:14:50.356970Z", + "shell.execute_reply": "2026-10-04T00:14:50.355516Z" + }, + "papermill": { + "duration": 0.042413, + "end_time": "2026-10-04T00:14:50.358048+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:50.315635+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "=== Contrôles de construction ===\n", + "id forme mots H/U ratio lev mots sim chars ood\n", + "paire-p01 sociale 13/15 1.15 3 0.89 False\n", + "paire-p02 pun 15/16 1.07 3 0.87 False\n", + "paire-p03 pun 22/25 1.14 3 0.95 False\n", + "paire-p04 topical 16/14 1.14 6 0.70 True\n", + "paire-p05 sociale 13/13 1.00 5 0.78 False\n", + "paire-p06 pun 12/12 1.00 1 0.95 False\n", + "paire-p07 topical 18/17 1.06 7 0.65 True\n", + "paire-p08 topical 14/16 1.14 2 0.95 True\n", + "paire-p09 pun 18/17 1.06 6 0.77 False\n", + "paire-p10 pun 16/16 1.00 2 0.90 False\n", + "paire-p11 pun 15/15 1.00 1 0.95 True\n", + "paire-p12 topical 13/14 1.08 2 0.94 True\n", + "paire-p13 pun 14/14 1.00 1 0.94 False\n", + "paire-p14 sociale 10/10 1.00 6 0.62 False\n", + "paire-p15 topical 16/14 1.14 8 0.69 False\n", + "paire-p16 sociale 18/18 1.00 2 0.93 False\n", + "paire-p17 topical 10/13 1.30 5 0.77 True\n", + "paire-p18 topical 10/11 1.10 4 0.73 False\n", + "paire-p19 pun 9/9 1.00 2 0.88 False\n", + "paire-p20 topical 22/22 1.00 10 0.64 False\n", + "paire-p21 pun 13/13 1.00 6 0.71 False\n", + "paire-p22 topical 16/16 1.00 3 0.84 False\n", + "paire-p23 sociale 20/21 1.05 6 0.81 False\n", + "paire-p24 topical 19/17 1.12 4 0.86 False\n", + "paire-p25 topical 14/13 1.08 2 0.89 False\n", + "paire-p26 sociale 18/14 1.29 11 0.60 False\n", + "paire-p27 pun 10/13 1.30 7 0.69 True\n", + "paire-p28 sociale 14/17 1.21 7 0.79 False\n", + "paire-p29 sociale 14/10 1.40 10 0.56 False\n", + "paire-p30 pun 20/22 1.10 6 0.83 True\n", + "\n", + "ratio longueur max = 1.40 (cible <= 1.35, consigne 'autant que possible')\n", + "similarité car. min/max = 0.56/0.95 (des paires proches = voulu)\n", + "\n", + "=== Seuils de verdict (gels avant mesure) ===\n", + "{\n", + " \"detection\": {\n", + " \"generalise\": 0.8,\n", + " \"par_forme_min\": 0.7,\n", + " \"ne_generalise_pas\": 0.6\n", + " },\n", + " \"explication\": {\n", + " \"noyau_generalise\": 0.8,\n", + " \"completude_generalise\": 0.6,\n", + " \"noyau_ne_generalise_pas\": 0.5\n", + " },\n", + " \"appreciation\": \"INCONCLUSIVE_PAR_CONSTRUCTION (annotateur unique — règle de l'issue #14033)\"\n", + "}\n", + "\n", + "=== GEL ===\n", + "corpus gt24b-paires-v1 sha256 = 116425d0222c5cc1...\n", + "construction (16 paires) : ['paire-p04', 'paire-p05', 'paire-p06', 'paire-p08', 'paire-p09', 'paire-p11', 'paire-p13', 'paire-p14', 'paire-p15', 'paire-p16', 'paire-p17', 'paire-p19', 'paire-p20', 'paire-p21', 'paire-p23', 'paire-p24']\n", + "test (14 paires) : ['paire-p01', 'paire-p02', 'paire-p03', 'paire-p07', 'paire-p10', 'paire-p12', 'paire-p18', 'paire-p22', 'paire-p25', 'paire-p26', 'paire-p27', 'paire-p28', 'paire-p29', 'paire-p30']\n", + "split gelé sha256 = 2aab8cbb7e9982e5...\n", + "test : 14 paires = 28 textes ; construction : 16 paires\n" + ] + } + ], + "source": [ + "# -*- coding: utf-8 -*-\n", + "# Controles de construction + GEL du split AVANT toute evaluation.\n", + "# Rien dans ce qui suit (seuils, split) ne sera retouche apres lecture du test.\n", + "import hashlib\n", + "import difflib\n", + "\n", + "def lev_mots(a, b):\n", + " \"\"\"Distance de Levenshtein mot a mot (DP classique, sans dependance).\"\"\"\n", + " wa, wb = a.split(), b.split()\n", + " prev = list(range(len(wb) + 1))\n", + " for i, xa in enumerate(wa, 1):\n", + " cur = [i] + [0] * len(wb)\n", + " for j, yb in enumerate(wb, 1):\n", + " cur[j] = min(prev[j] + 1, cur[j - 1] + 1,\n", + " prev[j - 1] + (xa != yb))\n", + " prev = cur\n", + " return prev[-1]\n", + "\n", + "print(\"=== Contrôles de construction ===\")\n", + "print(f\"{'id':<12}{'forme':<9}{'mots H/U':<10}{'ratio':<7}{'lev mots':<9}{'sim chars':<10}ood\")\n", + "ratios, sims = [], []\n", + "for (pid, forme, ood, th, tu, _, _, _, _) in PAIRES_MINIMALES:\n", + " nh, nu = len(th.split()), len(tu.split())\n", + " ratio = max(nh, nu) / max(1, min(nh, nu))\n", + " lv = lev_mots(th, tu)\n", + " sim = difflib.SequenceMatcher(None, th, tu).ratio()\n", + " ratios.append(ratio)\n", + " sims.append(sim)\n", + " print(f\"{pid:<12}{forme:<9}{nh:>3}/{nu:<4}{ratio:<7.2f}{lv:<9}{sim:<10.2f}{ood}\")\n", + "print(f\"\\nratio longueur max = {max(ratios):.2f} (cible <= 1.35, consigne 'autant que possible')\")\n", + "print(f\"similarité car. min/max = {min(sims):.2f}/{max(sims):.2f} (des paires proches = voulu)\")\n", + "\n", + "# SEUILS DE VERDICT — declares et geles AVANT l'evaluation.\n", + "SEUILS = {\n", + " \"detection\": {\"generalise\": 0.80, \"par_forme_min\": 0.70, \"ne_generalise_pas\": 0.60},\n", + " \"explication\": {\"noyau_generalise\": 0.80, \"completude_generalise\": 0.60,\n", + " \"noyau_ne_generalise_pas\": 0.50},\n", + " \"appreciation\": \"INCONCLUSIVE_PAR_CONSTRUCTION (annotateur unique — règle de l'issue #14033)\",\n", + "}\n", + "print(\"\\n=== Seuils de verdict (gels avant mesure) ===\")\n", + "print(json.dumps(SEUILS, indent=2, ensure_ascii=False))\n", + "\n", + "# SPLIT GEL — stratifie par forme, moitie construction / moitie test\n", + "# (les effectifs impairs vont au CONSTRUCTION : pun 6/5, sociale 4/4, topical 6/5).\n", + "rng = random.Random(42)\n", + "construction_ids, test_ids = [], []\n", + "for f in FORMES:\n", + " ids = sorted(p[0] for p in PAIRES_MINIMALES if p[1] == f)\n", + " rng.shuffle(ids)\n", + " k = (len(ids) + 1) // 2\n", + " construction_ids.extend(ids[:k])\n", + " test_ids.extend(ids[k:])\n", + "construction_ids.sort()\n", + "test_ids.sort()\n", + "\n", + "CORPUS_VERSION = \"gt24b-paires-v1\"\n", + "corpus_blob = json.dumps(\n", + " [[p[0], p[1], p[2], p[3], p[4], p[5], p[6]] for p in PAIRES_MINIMALES],\n", + " ensure_ascii=False, sort_keys=True).encode(\"utf-8\")\n", + "CORPUS_SHA = hashlib.sha256(corpus_blob).hexdigest()\n", + "SPLIT_SHA = hashlib.sha256(json.dumps(\n", + " {\"version\": CORPUS_VERSION, \"construction\": construction_ids, \"test\": test_ids},\n", + " sort_keys=True).encode(\"utf-8\")).hexdigest()\n", + "print(\"\\n=== GEL ===\")\n", + "print(f\"corpus {CORPUS_VERSION} sha256 = {CORPUS_SHA[:16]}...\")\n", + "print(f\"construction ({len(construction_ids)} paires) : {construction_ids}\")\n", + "print(f\"test ({len(test_ids)} paires) : {test_ids}\")\n", + "print(f\"split gelé sha256 = {SPLIT_SHA[:16]}...\")\n", + "TEST_PAIRS = [p for p in PAIRES_MINIMALES if p[0] in set(test_ids)]\n", + "TEST_TEXTES = [(p[0], 1, p[3], p[5], p[1], p[2]) for p in TEST_PAIRS] + \\\n", + " [(p[0], 0, p[4], p[6], p[1], p[2]) for p in TEST_PAIRS]\n", + "CONSTR_PAIRS = [p for p in PAIRES_MINIMALES if p[0] in set(construction_ids)]\n", + "print(f\"test : {len(TEST_PAIRS)} paires = {len(TEST_TEXTES)} textes ; construction : {len(CONSTR_PAIRS)} paires\")" + ] + }, + { + "cell_type": "markdown", + "id": "gt24b-paires-lecture1", + "metadata": { + "papermill": { + "duration": 0.009943, + "end_time": "2026-10-04T00:14:50.377815+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:50.367872+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "### Lecture — 30 paires appariées, 3 formes, tranche OOD, split gelé avant mesure\n", + "\n", + "- **11 pun / 8 sociale / 11 topical** — les trois formes exigées ; la pun et la référence culturelle dominent (le corpus source est un corpus de blagues d'informaticiens : biais déclaré, pas caché).\n", + "- **Tranche OOD = 8 paires code-mixées FR/EN** (`SELECT`, `null`/`undefined`, `UDP`, `yield`, `stack`, `printf`, `git pull`, `UTF-8`/`BOM`) — le code-mixing est exactement le régime que Horvitz et al. identifient comme difficile ; il est isolé pour être rapporté séparément.\n", + "- **Les éditions unfun conservent le décor** : ratios de longueur et similarités caractères mesurés ci-dessus ; la distance mot-à-mot reste faible — l'édit retire le mécanisme, pas le sujet.\n", + "- **Le split (16 construction / 14 test, stratifié par forme) et les seuils de verdict sont hachés avant la moindre évaluation** — aucune retouche possible après lecture du test." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "gt24b-paires-baselines", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:14:50.404873Z", + "iopub.status.busy": "2026-10-04T00:14:50.404324Z", + "iopub.status.idle": "2026-10-04T00:14:53.434118Z", + "shell.execute_reply": "2026-10-04T00:14:53.432650Z" + }, + "papermill": { + "duration": 3.046377, + "end_time": "2026-10-04T00:14:53.435773+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:50.389396+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[contrôle circulaire] macro-F1 = 1.000 — attendu 1.000 par construction :\n", + " les features dérivent du label, la règle inverse la dérivation. La métrique\n", + " est VIDE ; c'est la démonstration du défaut que les paires minimales corrigent.\n", + "\n", + "[baseline lexicale] macro-F1 test = 0.535 (TF-IDF 1-2 grammes +\n", + " régression logistique, entraînée sur les 16 paires de construction uniquement).\n", + " Sur le banc initial (positives tech vs négatives administratives) ce type de\n", + " classifieur réussissait par raccourci lexical ; ici les négatifs partagent le\n", + " lexique des positifs — le raccourci est fermé, la performance mesure la vraie tâche.\n" + ] + } + ], + "source": [ + "# -*- coding: utf-8 -*-\n", + "# DEUX BASELINES sur EXACTEMENT le meme split test (aucune ne voit le test avant).\n", + "from sklearn.feature_extraction.text import TfidfVectorizer\n", + "from sklearn.linear_model import LogisticRegression\n", + "from sklearn.pipeline import make_pipeline\n", + "from sklearn.metrics import f1_score\n", + "\n", + "# --- Baseline 1 (controle) : le detecteur circulaire d'origine, reproduit ---\n", + "# On reconstruit les features DEPUIS LE LABEL, exactement comme la cellule de\n", + "# corpus initiale le faisait (cell[35]) : c'est le defaut que ce banc exhibe.\n", + "def features_circulaires(est_humour):\n", + " return {\"laugh\": est_humour, \"reframe\": est_humour,\n", + " \"uptake\": est_humour, \"refus\": False}\n", + "\n", + "circ_pred = []\n", + "for (pid, cote, texte, note, forme, ood) in TEST_TEXTES:\n", + " f = features_circulaires(cote == 1)\n", + " pred = reframe_detector({\"features\": f})\n", + " circ_pred.append(1 if pred == \"humour_reussi\" else 0)\n", + "circ_y = [t[1] for t in TEST_TEXTES]\n", + "f1_circ = f1_score(circ_y, circ_pred, average=\"macro\")\n", + "print(f\"[contrôle circulaire] macro-F1 = {f1_circ:.3f} — attendu 1.000 par construction :\")\n", + "print(\" les features dérivent du label, la règle inverse la dérivation. La métrique\")\n", + "print(\" est VIDE ; c'est la démonstration du défaut que les paires minimales corrigent.\")\n", + "\n", + "# --- Baseline 2 : classifieur lexical de surface, entraîné sur CONSTRUCTION seulement ---\n", + "constr_X = [p[3] for p in CONSTR_PAIRS] + [p[4] for p in CONSTR_PAIRS]\n", + "constr_y = [1] * len(CONSTR_PAIRS) + [0] * len(CONSTR_PAIRS)\n", + "lex = make_pipeline(TfidfVectorizer(ngram_range=(1, 2), lowercase=True),\n", + " LogisticRegression(max_iter=1000))\n", + "lex.fit(constr_X, constr_y)\n", + "test_X = [t[2] for t in TEST_TEXTES]\n", + "lex_pred = list(lex.predict(test_X))\n", + "f1_lex = f1_score(circ_y, lex_pred, average=\"macro\")\n", + "print(f\"\\n[baseline lexicale] macro-F1 test = {f1_lex:.3f} (TF-IDF 1-2 grammes +\")\n", + "print(\" régression logistique, entraînée sur les 16 paires de construction uniquement).\")\n", + "print(\" Sur le banc initial (positives tech vs négatives administratives) ce type de\")\n", + "print(\" classifieur réussissait par raccourci lexical ; ici les négatifs partagent le\")\n", + "print(\" lexique des positifs — le raccourci est fermé, la performance mesure la vraie tâche.\")" + ] + }, + { + "cell_type": "markdown", + "id": "gt24b-paires-lecture2", + "metadata": { + "papermill": { + "duration": 0.007854, + "end_time": "2026-10-04T00:14:53.453180+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:53.445326+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "### Lecture — la circularité rendue visible, le raccourci lexical fermé\n", + "\n", + "La baseline circulaire rend **F1 = 1,000 par construction** : ce n'est pas une performance, c'est une tautologie mesurée. La baseline lexicale, elle, perd son raccourci : les contreparties « unfun » partagent le vocabulaire, le sujet et le registre des blagues — un n-gramme ne peut plus séparer « Oct 31 == Dec 25 » de « Oct 31 vient avant Dec 25 » sans comprendre lequel porte l'incongruité. Ces deux nombres encadrent l'évaluation LLM qui suit : **tout score LLM ≤ baseline lexicale ne démontre rien ; tout score ≈ 1,000 doit être regardé avec le même soupçon que la baseline circulaire.**" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "gt24b-paires-canal", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:14:53.474328Z", + "iopub.status.busy": "2026-10-04T00:14:53.473609Z", + "iopub.status.idle": "2026-10-04T00:14:54.118220Z", + "shell.execute_reply": "2026-10-04T00:14:54.116594Z" + }, + "papermill": { + "duration": 0.654371, + "end_time": "2026-10-04T00:14:54.119544+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:53.465173+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[canal] épinglé = anthropic/claude-haiku-4.5\n", + "[canal] écho provider = anthropic/claude-haiku-4.5 (résolution de version servie)\n", + "[canal] latence = 634 ms ; usage = {'prompt_tokens': 14, 'completion_tokens': 4, 'total_tokens': 18, 'cost': 0, 'is_byok': True, 'prompt_tokens_details': {'cached_tokens': 0, 'cache_write_tokens': 0, 'audio_tokens': 0, 'video_tokens': 0}, 'cost_details': {'upstream_inference_cost': 3.4e-05, 'upstream_inference_prompt_cost': 1.4e-05, 'upstream_inference_completions_cost': 2e-05}, 'completion_tokens_details': {'reasoning_tokens': 0, 'image_tokens': 0, 'audio_tokens': 0}}\n" + ] + } + ], + "source": [ + "# -*- coding: utf-8 -*-\n", + "# Canal de jugement epingle : OpenRouter, modele ET version fixes (dispatch #14033).\n", + "def or_call(prompt, max_tokens=200, timeout=90):\n", + " \"\"\"Appel OpenRouter. Retourne (contenu, echo_modele, latence_ms, usage).\"\"\"\n", + " body = json.dumps({\n", + " \"model\": LLM_MODEL,\n", + " \"messages\": [{\"role\": \"user\", \"content\": prompt}],\n", + " \"max_tokens\": max_tokens,\n", + " \"temperature\": 0.0,\n", + " }).encode(\"utf-8\")\n", + " req = urllib.request.Request(\n", + " f\"{OPENAI_COMPAT_URL}/chat/completions\",\n", + " data=body,\n", + " headers={\n", + " \"Content-Type\": \"application/json\",\n", + " \"Authorization\": f\"Bearer {OPENAI_API_KEY}\",\n", + " \"HTTP-Referer\": \"https://github.com/jsboige/CoursIA\",\n", + " \"X-Title\": \"CoursIA-GT24b-banc-humour-14033\",\n", + " },\n", + " )\n", + " t0 = time.time()\n", + " with urllib.request.urlopen(req, timeout=timeout) as r:\n", + " resp = json.loads(r.read())\n", + " dt = int((time.time() - t0) * 1000)\n", + " content = resp[\"choices\"][0][\"message\"][\"content\"].strip()\n", + " return content, resp.get(\"model\", \"?\"), dt, resp.get(\"usage\", {})\n", + "\n", + "_ping, _echo, _dt, _usage = or_call(\"Réponds uniquement : OK\")\n", + "print(f\"[canal] épinglé = {LLM_MODEL}\")\n", + "print(f\"[canal] écho provider = {_echo} (résolution de version servie)\")\n", + "print(f\"[canal] latence = {_dt} ms ; usage = {_usage}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "gt24b-paires-detection", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:14:54.143820Z", + "iopub.status.busy": "2026-10-04T00:14:54.143377Z", + "iopub.status.idle": "2026-10-04T00:15:12.706431Z", + "shell.execute_reply": "2026-10-04T00:15:12.705099Z" + }, + "papermill": { + "duration": 18.578119, + "end_time": "2026-10-04T00:15:12.707890+00:00", + "exception": false, + "start_time": "2026-10-04T00:14:54.129771+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[détection] 28 appels, 28 réponses OUI/NON parsées\n", + "\n", + "=== DÉTECTION — macro-F1 (split test gelé) ===\n", + "global : 0.509\n", + "forme pun (10 txt) : 0.333\n", + "forme sociale ( 8 txt) : 0.750\n", + "forme topical (10 txt) : 0.333\n", + "tranche OOD code-mixé ( 8 txt) : 0.333\n", + "tranche FR pur (20 txt) : 0.560\n", + "\n", + "erreurs (12) :\n", + " paire-p25 côté=0 préd=1 forme=topical ood=False brut='OUI'\n", + " paire-p12 côté=0 préd=1 forme=topical ood=True brut='OUI'\n", + " paire-p30 côté=0 préd=1 forme=pun ood=True brut='OUI'\n", + " paire-p27 côté=0 préd=1 forme=pun ood=True brut='OUI'\n", + " paire-p28 côté=0 préd=1 forme=sociale ood=False brut='OUI'\n", + " paire-p02 côté=0 préd=1 forme=pun ood=False brut='OUI'\n", + " paire-p22 côté=0 préd=1 forme=topical ood=False brut='OUI'\n", + " paire-p01 côté=1 préd=0 forme=sociale ood=False brut='NON'\n", + " paire-p03 côté=0 préd=1 forme=pun ood=False brut='OUI'\n", + " paire-p10 côté=0 préd=1 forme=pun ood=False brut='OUI'\n", + " paire-p07 côté=0 préd=1 forme=topical ood=True brut='OUI'\n", + " paire-p18 côté=0 préd=1 forme=topical ood=False brut='OUI'\n" + ] + } + ], + "source": [ + "# -*- coding: utf-8 -*-\n", + "# TACHE 1 — DETECTION. Binaire : le texte porte-t-il un mecanisme humoristique ?\n", + "# Les deux cotes de chaque paire test, ordre mélangé (anti-biais de position).\n", + "import unicodedata\n", + "\n", + "def normaliser(s):\n", + " s = unicodedata.normalize(\"NFD\", s.lower())\n", + " return \"\".join(c for c in s if not unicodedata.combining(c))\n", + "\n", + "PROMPT_DETECTION = (\n", + " \"Tu es un détecteur d'humour. On te donne un texte court. Indique s'il contient \"\n", + " \"un mécanisme humoristique volontaire (jeu de mots, incongruité, absurdité, chute). \"\n", + " \"Réponds UNIQUEMENT par OUI ou NON.\\n\\nTexte : {texte}\\n\\nRéponse :\")\n", + "\n", + "rng_det = random.Random(7)\n", + "items_det = list(TEST_TEXTES)\n", + "rng_det.shuffle(items_det)\n", + "det_resultats = []\n", + "for (pid, cote, texte, note, forme, ood) in items_det:\n", + " rep, echo, dt, _ = or_call(PROMPT_DETECTION.format(texte=texte), max_tokens=8)\n", + " norm = normaliser(rep)\n", + " pred = 1 if \"oui\" in norm else (0 if \"non\" in norm else -1)\n", + " det_resultats.append({\"pid\": pid, \"cote\": cote, \"pred\": pred, \"forme\": forme,\n", + " \"ood\": ood, \"brut\": rep[:40], \"ms\": dt})\n", + "n_parse = sum(1 for r in det_resultats if r[\"pred\"] >= 0)\n", + "print(f\"[détection] {len(det_resultats)} appels, {n_parse} réponses OUI/NON parsées\")\n", + "\n", + "def macro_f1(rs):\n", + " y = [r[\"cote\"] for r in rs]\n", + " p = [r[\"pred\"] for r in rs]\n", + " if -1 in p:\n", + " p = [x if x >= 0 else 0 for x in p] # non-parsé = NON\n", + " return f1_score(y, p, average=\"macro\")\n", + "\n", + "f1_det = macro_f1(det_resultats)\n", + "print(f\"\\n=== DÉTECTION — macro-F1 (split test gelé) ===\")\n", + "print(f\"global : {f1_det:.3f}\")\n", + "for f in FORMES:\n", + " rs = [r for r in det_resultats if r[\"forme\"] == f]\n", + " print(f\"forme {f:<9} ({len(rs):>2} txt) : {macro_f1(rs):.3f}\")\n", + "rs_ood_det = [r for r in det_resultats if r[\"ood\"]]\n", + "rs_fr_det = [r for r in det_resultats if not r[\"ood\"]]\n", + "print(f\"tranche OOD code-mixé ({len(rs_ood_det):>2} txt) : {macro_f1(rs_ood_det):.3f}\")\n", + "print(f\"tranche FR pur ({len(rs_fr_det):>2} txt) : {macro_f1(rs_fr_det):.3f}\")\n", + "erreurs = [(r[\"pid\"], r[\"cote\"], r[\"pred\"], r[\"forme\"], r[\"ood\"], r[\"brut\"])\n", + " for r in det_resultats if r[\"pred\"] != r[\"cote\"]]\n", + "print(f\"\\nerreurs ({len(erreurs)}) :\")\n", + "for e in erreurs:\n", + " print(f\" {e[0]} côté={e[1]} préd={e[2]} forme={e[3]} ood={e[4]} brut={e[5]!r}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "gt24b-paires-appreciation", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:15:12.732301Z", + "iopub.status.busy": "2026-10-04T00:15:12.731856Z", + "iopub.status.idle": "2026-10-04T00:15:32.232185Z", + "shell.execute_reply": "2026-10-04T00:15:32.230933Z" + }, + "papermill": { + "duration": 19.513428, + "end_time": "2026-10-04T00:15:32.233461+00:00", + "exception": false, + "start_time": "2026-10-04T00:15:12.720033+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[appréciation] 28/28 notes 0-3 parsées\n", + "\n", + "=== APPRÉCIATION — accord LLM vs annotateur humain unique ===\n", + "kappa quadratique pondéré = 0.385\n", + "Spearman rho = 0.539 (p = 0.0031)\n", + "forme pun : kappa_q = 0.238 (n=10)\n", + "forme sociale : kappa_q = 0.564 (n=8)\n", + "forme topical : kappa_q = 0.444 (n=10)\n", + "\n", + "distribution annotateur : {0: 14, 3: 4, 2: 9, 1: 1}\n", + "distribution LLM : {1: 14, 2: 13, 0: 1}\n", + "\n", + "VERDICT APPRÉCIATION = INCONCLUSIVE_PAR_CONSTRUCTION : un seul annotateur\n", + "humain (l'auteur du corpus) — la règle de l'issue #14033 impose ce verdict ;\n", + "l'accord rapporté ci-dessus est une donnée, pas une généralisation. L'échelle\n", + "JEST (Toplyn & Amir 2026) est elle-même limitée aux textes conversationnels\n", + "courts et aux adultes américains : réserve doublée, non levée ici.\n" + ] + } + ], + "source": [ + "# -*- coding: utf-8 -*-\n", + "# TACHE 2 — APPRECIATION. Ordinal 0-3 (échelle à la JEST, réserves documentées).\n", + "from sklearn.metrics import cohen_kappa_score\n", + "from scipy.stats import spearmanr\n", + "\n", + "PROMPT_APPRECIATION = (\n", + " \"Tu es un évaluateur d'humour. Note à quel point ce texte est drôle pour un \"\n", + " \"public adulte francophone, sur l'échelle ordinale :\\n\"\n", + " \"0 = pas drôle du tout\\n1 = à peine drôle\\n2 = moyennement drôle\\n3 = très drôle\\n\"\n", + " \"Réponds UNIQUEMENT par le chiffre (0, 1, 2 ou 3).\\n\\nTexte : {texte}\\n\\nNote :\")\n", + "\n", + "rng_app = random.Random(11)\n", + "items_app = list(TEST_TEXTES)\n", + "rng_app.shuffle(items_app)\n", + "app_resultats = []\n", + "for (pid, cote, texte, note, forme, ood) in items_app:\n", + " rep, echo, dt, _ = or_call(PROMPT_APPRECIATION.format(texte=texte), max_tokens=4)\n", + " chiffres = [int(c) for c in rep if c in \"0123\"]\n", + " pred = chiffres[0] if chiffres else None\n", + " app_resultats.append({\"pid\": pid, \"cote\": cote, \"annotateur\": note,\n", + " \"llm\": pred, \"forme\": forme, \"ood\": ood})\n", + "valides = [r for r in app_resultats if r[\"llm\"] is not None]\n", + "print(f\"[appréciation] {len(valides)}/{len(app_resultats)} notes 0-3 parsées\")\n", + "\n", + "y_a = [r[\"annotateur\"] for r in valides]\n", + "y_l = [r[\"llm\"] for r in valides]\n", + "qwk = cohen_kappa_score(y_a, y_l, labels=[0, 1, 2, 3], weights=\"quadratic\")\n", + "rho, pval = spearmanr(y_a, y_l)\n", + "print(f\"\\n=== APPRÉCIATION — accord LLM vs annotateur humain unique ===\")\n", + "print(f\"kappa quadratique pondéré = {qwk:.3f}\")\n", + "print(f\"Spearman rho = {rho:.3f} (p = {pval:.4f})\")\n", + "for f in FORMES:\n", + " rs = [r for r in valides if r[\"forme\"] == f]\n", + " if len(rs) >= 3:\n", + " k = cohen_kappa_score([r[\"annotateur\"] for r in rs], [r[\"llm\"] for r in rs],\n", + " labels=[0, 1, 2, 3], weights=\"quadratic\")\n", + " print(f\"forme {f:<9} : kappa_q = {k:.3f} (n={len(rs)})\")\n", + "print(f\"\\ndistribution annotateur : {dict(Counter(y_a))}\")\n", + "print(f\"distribution LLM : {dict(Counter(y_l))}\")\n", + "print(\"\\nVERDICT APPRÉCIATION = INCONCLUSIVE_PAR_CONSTRUCTION : un seul annotateur\")\n", + "print(\"humain (l'auteur du corpus) — la règle de l'issue #14033 impose ce verdict ;\")\n", + "print(\"l'accord rapporté ci-dessus est une donnée, pas une généralisation. L'échelle\")\n", + "print(\"JEST (Toplyn & Amir 2026) est elle-même limitée aux textes conversationnels\")\n", + "print(\"courts et aux adultes américains : réserve doublée, non levée ici.\")" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "gt24b-paires-explication", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:15:32.250937Z", + "iopub.status.busy": "2026-10-04T00:15:32.250627Z", + "iopub.status.idle": "2026-10-04T00:16:02.626585Z", + "shell.execute_reply": "2026-10-04T00:16:02.624810Z" + }, + "papermill": { + "duration": 30.395971, + "end_time": "2026-10-04T00:16:02.637896+00:00", + "exception": false, + "start_time": "2026-10-04T00:15:32.241925+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[explication] 14 blagues du split test expliquées\n", + "\n", + "=== EXPLICATION — grille humaine explicite ===\n", + "exactitude (élément NOYAU nommé) = 0.857\n", + "complétude (moyenne des couvertures) = 0.762\n", + "forme pun : noyau 1.000 complétude 0.800 (n=5)\n", + "forme sociale : noyau 0.500 complétude 0.583 (n=4)\n", + "forme topical : noyau 1.000 complétude 0.867 (n=5)\n", + "tranche OOD : noyau 1.000 complétude 0.917 (n=4)\n", + "\n", + "exemples (2 premiers) :\n", + " paire-p22 [noyau=True couv=1.00] Le texte joue sur une homophonie entre \"incident majeur\" (problème informatique grave) et \"incident majeur\" prononcé comme \"in-chat-dent majeur\" (jeu de mots avec \"chat\"). L'incong\n", + " paire-p27 [noyau=True couv=1.00] Ce texte joue sur l'incongruité entre un proverbe français classique (\"Mieux vaut avoir un tiens que deux tu l'auras\") et le jargon informatique en remplaçant \"un tiens\" par \"un gi\n", + "\n", + "réserve de méthode : la grille est un appariement de mots-clés (normalisés),\n", + "pas une lecture sémantique — elle sous-compte les paraphrases correctes et\n", + "sur-compte les mentions de passage. Règle déclarée avant mesure, appliquée\n", + "mécaniquement : falsifiable, jamais retouchée après lecture du test.\n" + ] + } + ], + "source": [ + "# -*- coding: utf-8 -*-\n", + "# TACHE 3 — EXPLICATION. Grille humaine explicite : exactitude (noyau) + complétude.\n", + "PROMPT_EXPLICATION = (\n", + " \"Explique en 1 à 3 phrases le mécanisme humoristique de ce texte : quelle \"\n", + " \"incongruité, quelle(s) référence(s), quelle norme il joue. Si le texte ne \"\n", + " \"présente pas de mécanisme humoristique clair, écris uniquement : \"\n", + " \"PAS_DE_MECANISME\\n\\nTexte : {texte}\\n\\nExplication :\")\n", + "\n", + "def score_grille(explication, mecanisme):\n", + " \"\"\"Grille explicite : normalise (casse+accents), cherche les mots-clés.\n", + " Rend (noyau_trouvé, n_éléments_trouvés, n_éléments).\"\"\"\n", + " norm = normaliser(explication)\n", + " trouves = 0\n", + " noyau = False\n", + " for i, (element, mots) in enumerate(mecanisme):\n", + " hit = any(normaliser(m) in norm for m in mots)\n", + " trouves += hit\n", + " if i == 0 and hit:\n", + " noyau = True\n", + " return noyau, trouves, len(mecanisme)\n", + "\n", + "rng_exp = random.Random(23)\n", + "items_expl = sorted(TEST_PAIRS, key=lambda p: p[0])\n", + "rng_exp.shuffle(items_expl)\n", + "expl_resultats = []\n", + "for p in items_expl:\n", + " pid, forme, ood, th, tu, nh, nu, meca, jedit = p\n", + " rep, echo, dt, _ = or_call(PROMPT_EXPLICATION.format(texte=th), max_tokens=250)\n", + " noyau, nt, ntot = score_grille(rep, meca)\n", + " expl_resultats.append({\"pid\": pid, \"forme\": forme, \"ood\": ood,\n", + " \"noyau\": noyau, \"couverture\": nt / ntot,\n", + " \"pas_de_mecanisme\": \"PAS_DE_MECANISME\" in rep.upper(),\n", + " \"texte\": rep})\n", + "print(f\"[explication] {len(expl_resultats)} blagues du split test expliquées\")\n", + "\n", + "acc_noyau = sum(r[\"noyau\"] for r in expl_resultats) / len(expl_resultats)\n", + "completude = sum(r[\"couverture\"] for r in expl_resultats) / len(expl_resultats)\n", + "print(f\"\\n=== EXPLICATION — grille humaine explicite ===\")\n", + "print(f\"exactitude (élément NOYAU nommé) = {acc_noyau:.3f}\")\n", + "print(f\"complétude (moyenne des couvertures) = {completude:.3f}\")\n", + "for f in FORMES:\n", + " rs = [r for r in expl_resultats if r[\"forme\"] == f]\n", + " if rs:\n", + " print(f\"forme {f:<9} : noyau {sum(r['noyau'] for r in rs)/len(rs):.3f} \"\n", + " f\"complétude {sum(r['couverture'] for r in rs)/len(rs):.3f} (n={len(rs)})\")\n", + "rs_ood_expl = [r for r in expl_resultats if r[\"ood\"]]\n", + "if rs_ood_expl:\n", + " print(f\"tranche OOD : noyau {sum(r['noyau'] for r in rs_ood_expl)/len(rs_ood_expl):.3f} \"\n", + " f\"complétude {sum(r['couverture'] for r in rs_ood_expl)/len(rs_ood_expl):.3f} (n={len(rs_ood_expl)})\")\n", + "print(\"\\nexemples (2 premiers) :\")\n", + "for r in expl_resultats[:2]:\n", + " print(f\" {r['pid']} [noyau={r['noyau']} couv={r['couverture']:.2f}] {r['texte'][:180]}\")\n", + "print(\"\\nréserve de méthode : la grille est un appariement de mots-clés (normalisés),\")\n", + "print(\"pas une lecture sémantique — elle sous-compte les paraphrases correctes et\")\n", + "print(\"sur-compte les mentions de passage. Règle déclarée avant mesure, appliquée\")\n", + "print(\"mécaniquement : falsifiable, jamais retouchée après lecture du test.\")" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "gt24b-paires-verdicts", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:16:02.662278Z", + "iopub.status.busy": "2026-10-04T00:16:02.661977Z", + "iopub.status.idle": "2026-10-04T00:16:03.051621Z", + "shell.execute_reply": "2026-10-04T00:16:03.050090Z" + }, + "papermill": { + "duration": 0.403745, + "end_time": "2026-10-04T00:16:03.053036+00:00", + "exception": false, + "start_time": "2026-10-04T00:16:02.649291+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[dédup] similarité max construction<->test = 0.55 ('paire-p04', 'paire-p07')\n", + "[dédup] doublons exacts intra-corpus : 0\n", + "\n", + "[provenance] 30 textes humores + 30 contreparties unfun : contenu propre\n", + " écrit pour ce dépôt (lignée #12785, POSITIVE_JOKES cell[35]) ; les éditions\n", + " unfun sont inédites, créées pour #14033. Aucune donnée Reddit/Kaggle (les\n", + " verdicts REFERENCE_ONLY de l'issue restent en vigueur). Droits établis.\n", + "[contenu] aucune tranche offensive dans les 30 paires ; la catégorie\n", + " offensif_compris_non_partage du banc initial reste dans sa tranche séparée,\n", + " jamais assimilée à du non-humour.\n", + "[version] gt24b-paires-v1 sha256=116425d0222c5cc1... split sha256=2aab8cbb7e9982e5...\n", + "[contamination] dépôt public sur GitHub : tout modèle entraîné sur le web a pu\n", + " voir les textes HUMORES ; les contreparties unfun sont inédites et font écran.\n", + "\n", + "=== VERDICTS FERMES (règle #14033 : jamais 'promising') ===\n", + "DETECTION : NE_GENERALISE_PAS (global 0.509, formes {'pun': 0.3333333333333333, 'sociale': 0.75, 'topical': 0.3333333333333333}, OOD 0.333)\n", + "APPRECIATION : INCONCLUSIVE_PAR_CONSTRUCTION (annotateur unique, kappa_q = 0.385)\n", + "EXPLICATION : GENERALISE (noyau 0.857, complétude 0.762)\n", + "résiduel explicite : baselines sur 28 textes de test / 14 explications ;\n", + "corpus mono-culture (blagues d'informaticiens FR, auteur = unique annotateur)\n" + ] + } + ], + "source": [ + "# -*- coding: utf-8 -*-\n", + "# CONTROLES D'HONNETETE + VERDICTS FERMES (seuils gelés en amont).\n", + "import hashlib as _hl\n", + "\n", + "# Near-duplicate construction <-> test (hors paire elle-même : la ressemblance\n", + "# intra-paire est le DESSEIN du banc ; on vérifie qu'aucune paire de construction\n", + "# ne pré-crée une paire de test par quasi-doublon).\n", + "max_ratio, argmax = 0.0, None\n", + "for pc in CONSTR_PAIRS:\n", + " for pt in TEST_PAIRS:\n", + " for tc in (pc[3], pc[4]):\n", + " for tt in (pt[3], pt[4]):\n", + " r = difflib.SequenceMatcher(None, tc, tt).ratio()\n", + " if r > max_ratio:\n", + " max_ratio, argmax = r, (pc[0], pt[0])\n", + "print(f\"[dédup] similarité max construction<->test = {max_ratio:.2f} {argmax}\")\n", + "hashes = [_hl.sha256((p[3] + p[4]).encode(\"utf-8\")).hexdigest() for p in PAIRES_MINIMALES]\n", + "print(f\"[dédup] doublons exacts intra-corpus : {len(hashes) - len(set(hashes))}\")\n", + "\n", + "print(\"\\n[provenance] 30 textes humores + 30 contreparties unfun : contenu propre\")\n", + "print(\" écrit pour ce dépôt (lignée #12785, POSITIVE_JOKES cell[35]) ; les éditions\")\n", + "print(\" unfun sont inédites, créées pour #14033. Aucune donnée Reddit/Kaggle (les\")\n", + "print(\" verdicts REFERENCE_ONLY de l'issue restent en vigueur). Droits établis.\")\n", + "print(\"[contenu] aucune tranche offensive dans les 30 paires ; la catégorie\")\n", + "print(\" offensif_compris_non_partage du banc initial reste dans sa tranche séparée,\")\n", + "print(\" jamais assimilée à du non-humour.\")\n", + "print(f\"[version] {CORPUS_VERSION} sha256={CORPUS_SHA[:16]}... split sha256={SPLIT_SHA[:16]}...\")\n", + "print(\"[contamination] dépôt public sur GitHub : tout modèle entraîné sur le web a pu\")\n", + "print(\" voir les textes HUMORES ; les contreparties unfun sont inédites et font écran.\")\n", + "\n", + "print(\"\\n=== VERDICTS FERMES (règle #14033 : jamais 'promising') ===\")\n", + "s = SEUILS[\"detection\"]\n", + "f1_par_forme = {f: macro_f1([r for r in det_resultats if r[\"forme\"] == f]) for f in FORMES}\n", + "f1_ood = macro_f1(rs_ood_det)\n", + "if (f1_det >= s[\"generalise\"]\n", + " and all(v >= s[\"par_forme_min\"] for v in f1_par_forme.values())\n", + " and f1_ood >= s[\"par_forme_min\"]):\n", + " v_det = \"GENERALISE\"\n", + "elif f1_det < s[\"ne_generalise_pas\"]:\n", + " v_det = \"NE_GENERALISE_PAS\"\n", + "else:\n", + " v_det = \"INCONCLUSIVE\"\n", + "print(f\"DETECTION : {v_det} (global {f1_det:.3f}, formes {f1_par_forme}, OOD {f1_ood:.3f})\")\n", + "print(f\"APPRECIATION : INCONCLUSIVE_PAR_CONSTRUCTION (annotateur unique, kappa_q = {qwk:.3f})\")\n", + "se = SEUILS[\"explication\"]\n", + "if acc_noyau >= se[\"noyau_generalise\"] and completude >= se[\"completude_generalise\"]:\n", + " v_exp = \"GENERALISE\"\n", + "elif acc_noyau < se[\"noyau_ne_generalise_pas\"]:\n", + " v_exp = \"NE_GENERALISE_PAS\"\n", + "else:\n", + " v_exp = \"INCONCLUSIVE\"\n", + "print(f\"EXPLICATION : {v_exp} (noyau {acc_noyau:.3f}, complétude {completude:.3f})\")\n", + "print(f\"résiduel explicite : baselines sur 28 textes de test / 14 explications ;\")\n", + "print(f\"corpus mono-culture (blagues d'informaticiens FR, auteur = unique annotateur)\")" + ] + }, + { + "cell_type": "markdown", + "id": "gt24b-paires-conclusion", + "metadata": { + "papermill": { + "duration": 0.012516, + "end_time": "2026-10-04T00:16:03.077446+00:00", + "exception": false, + "start_time": "2026-10-04T00:16:03.064930+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "### Un banc falsifiable, trois verdicts séparés\n", + "\n", + "Le détecteur du banc initial ne démontrait rien : ses features dérivaient du label (F1 = 1,000 tautologique, reproduit ci-dessus comme **contrôle**). Sur des **paires minimales** dont les négatifs partagent lexique, sujet et registre des positifs, la baseline lexicale perd son raccourci et le score LLM redevient une **vraie mesure** — séparée en trois questions indépendantes :\n", + "\n", + "1. **détection** — macro-F1 global, par forme (pun / sociale / topical) et par tranche (code-mixé / FR pur), avec les erreurs listées une à une ;\n", + "2. **appréciation** — κ quadratique pondéré et ρ de Spearman contre l'annotateur humain unique, verdict **INCONCLUSIVE par construction** (règle de l'issue : un seul annotateur ne généralise pas une échelle de goût) ;\n", + "3. **explication** — grille humaine explicite (élément noyau + éléments secondaires), exactitude et complétude rapportées séparément, réserve de méthode déclarée (appariement de mots-clés, pas lecture sémantique).\n", + "\n", + "Les contrôles d'honnêteté (quasi-doublons construction↔test, hachage du corpus et du split gelé, provenance et droits, tranche offensive isolée, contamination déclarée) sont mesurés, pas affirmés. Les verdicts fermes — `GENERALISE` / `NE_GENERALISE_PAS` / `INCONCLUSIVE` — sont calculés par les seuils gelés **avant** mesure ; « promising » n'existe pas ici." + ] + }, + { + "cell_type": "markdown", + "id": "07f174d8", + "metadata": { + "papermill": { + "duration": 0.011314, + "end_time": "2026-10-04T00:16:03.101544+00:00", + "exception": false, + "start_time": "2026-10-04T00:16:03.090230+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "## Conclusion — placement, limites, suite\n", + "\n", + "### Bilan acceptance #12756\n", + "\n", + "| Critère | Statut | Preuve |\n", + "|---|---|---|\n", + "| ≥1 corpus réel intégré (Argumentum) | **OK** | 167 scénarios CSV + 60 échantillonnés |\n", + "| ≥100 instances annotées, négatifs inclus, équilibré | **OK** | `len(CORPUS_DUR)` cell[32] |\n", + "| ≥1 expérience ranking LLM, sorties committées | **OK** | cell[37] + cell[39] |\n", + "| Matrices confusion mises à jour | **OK** | cell[39] : naïve vs partage vs LLM |\n", + "| Placement tranché et documenté | **OK** | GT-24b (comment user 15:46Z) |\n", + "\n", + "> *Numérotation : le renommage #18001 a renuméroté ce carnet GT-24b → GT-18d et le toy model GT-24 → GT-20. La preuve de placement ci-dessus cite le numéro à la date du commentaire user.*\n", + "\n", + "### Verdict SOTA\n", + "\n", + "Le canal `anthropic/claude-haiku-4.5` via OpenRouter est invoqué, épinglé et\n", + "vérifié par écho provider (SOTA-OK). Le endpoint LAN vLLM `qwen3.6-35b-a3b`\n", + "d'origine est documenté injoignable (HTTP 000, 2026-09-13) — basculement\n", + "journalisé, pas de fallback dégradé : si l'endpoint échoue (réseau /\n", + "maintenance), le diagnostic le dit explicitement (cf cell[39], `[LLM] Pas de mesure`).\n", + "\n", + "### Limites et suite\n", + "\n", + "- **Argumentum submodule non initialisé** sur la machine (c.539 mesure). Le\n", + " fetch HTTP direct contourne ; une PR séparée pourra faire `git submodule\n", + " update --init` proprement quand l'environnement le permettra.\n", + "- **Circularité (audit #13306)** : le F1 = 1,000 du détecteur maison est une\n", + " identité de construction sur les instances Argumentum (features dérivées du\n", + " label), pas une performance — verdict `CIRCULARITE_GROSSIERE_ECARTEE` avec\n", + " réserve structurelle, cf section dédiée. Validation réelle : #12756 ou\n", + " features annotées depuis le texte.\n", + "- **Corpus annoté** = curation manuelle (avec justifications cell[32]).\n", + " Pas de corpus académique blagues publiquement annoté sur ce cycle. Si\n", + " dispo, intégrer par exemple le corpus `humour-classification` Kaggle\n", + " ou `short-jokes` dataset (post-cycle).\n", + "- **LLM ranking** limité à 30 instances pour éviter latence cumulée.\n", + " Suite : full-corpus LLM en mode async (papermill --workers 4) sur machine\n", + " GPU dédiée (po-2024 ?) pour 120+ instances en <5 min.\n", + "- **Placement** : GT-24b pour l'instant. La numérotation pourra basculer en\n", + " annexes `-b`, `-c` une fois la sous-série stabilisée (comment user 15:46Z).\n", + "\n", + "### Crédits\n", + "\n", + "- Argumentum upstream : github.com/ArgumentumGames/Argumentum (master,\n", + " `Cards/Scenarii/Argumentum Scenarii - Cards.csv`)\n", + "- Toy model livré par #12749 (PR `GameTheory-18c-Humour-Banc-Python.ipynb`)\n", + "- LLM : `qwen3.6-35b-a3b` (AWQ 4bit, vLLM local) puis `anthropic/claude-haiku-4.5` (OpenRouter, canal épinglé, écho provider capturé)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "3d77d082", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-04T00:16:03.123890Z", + "iopub.status.busy": "2026-10-04T00:16:03.123439Z", + "iopub.status.idle": "2026-10-04T00:16:03.127594Z", + "shell.execute_reply": "2026-10-04T00:16:03.126574Z" + }, + "papermill": { + "duration": 0.016228, + "end_time": "2026-10-04T00:16:03.128489+00:00", + "exception": false, + "start_time": "2026-10-04T00:16:03.112261+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Fin du banc — fermeture du notebook.\n" + ] + } + ], + "source": [ + "print(\"Fin du banc — fermeture du notebook.\")" ] } ], @@ -1167,18 +3825,18 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.13.7" + "version": "3.13.15" }, "papermill": { "default_parameters": {}, - "duration": 4.802203, - "end_time": "2026-09-29T04:48:57.848297+00:00", + "duration": 103.816991, + "end_time": "2026-10-04T00:16:03.699902+00:00", "environment_variables": {}, "exception": null, - "input_path": "MyIA.AI.Notebooks/GameTheory/GameTheory-24-Humour-Banc.ipynb", - "output_path": "MyIA.AI.Notebooks/GameTheory/GameTheory-24-Humour-Banc-exec.ipynb", + "input_path": "GameTheory-18c-Humour-Banc-Python.ipynb", + "output_path": "gt18c_output.ipynb", "parameters": {}, - "start_time": "2026-09-29T04:48:53.046094+00:00", + "start_time": "2026-10-04T00:14:19.882911+00:00", "version": "2.7.0" } }, diff --git a/MyIA.AI.Notebooks/GameTheory/GameTheory-18d-Humour-Banc-Dur-Python.ipynb b/MyIA.AI.Notebooks/GameTheory/GameTheory-18d-Humour-Banc-Dur-Python.ipynb deleted file mode 100644 index 38038e1f05..0000000000 --- a/MyIA.AI.Notebooks/GameTheory/GameTheory-18d-Humour-Banc-Dur-Python.ipynb +++ /dev/null @@ -1,2759 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "8d6c2059", - "metadata": { - "papermill": { - "duration": 0.007091, - "end_time": "2026-09-14T01:56:12.004686+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:11.997595+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "# GameTheory-18d : Banc humour — passer à l'échelle\n", - "\n", - "Suite du banc toy `GameTheory-18c-Humour-Banc-Python.ipynb` : le modèle passe ici du banc d'essai à l'échelle — matériel Argumentum, corpus annoté de blagues bonnes et mauvaises, et expériences de ranking avec de vrais LLM pour la partie « organique ».\n", - "\n", - "## Trois sources de données\n", - "\n", - "1. **Argumentum** — 167 scénarios « baratineur / piocheur » du jeu de cartes\n", - " rhétorique (github.com/ArgumentumGames/Argumentum). Le submodule upstream\n", - " `MyIA.AI.Notebooks/SymbolicAI/Argument_Analysis/Argumentum` n'est pas\n", - " initialisé sur toutes les machines ; on récupère le CSV `Cards/Scenarii/Argumentum Scenarii -\n", - " Cards.csv` par fetch HTTP direct (raw.githubusercontent).\n", - "2. **Corpus annoté blagues** — ≥ 100 instances positives + négatives, équilibré\n", - " par cellule de la matrice du toy model (4 cellules + hors matrice).\n", - " Sources : blagues courtes construites à la main avec justifications\n", - " explicites (cf C.1 : pas de fabrication sans verdict).\n", - "3. **LLM ranking** — canal de jugement épinglé `anthropic/claude-haiku-4.5` via\n", - " OpenRouter (modèle ET version fixés, écho provider capturé dans les sorties,\n", - " cf cell[1] et cell[36]). Le banc tournait à l'origine sur le endpoint LAN vLLM\n", - " `qwen3.6-35b-a3b` (`192.168.0.47:5002/v1`), injoignable depuis cette lane\n", - " (HTTP 000 mesuré le 2026-09-13) — basculement journalisé, pas de fallback.\n", - " Cible : reproduire le verdict\n", - " « humour_reussi » vs alternatives sur un sous-ensemble de 30 instances.\n", - "\n", - "**Placement** : GT-18d (ex-GT-24b, renommage #18001), à côté du toy model GT-20 (ex-GT-24) — la sous-série humour reste dans l'arc GameTheory, à proximité de Sandholm qui nourrit son axe de réflexion.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "27ccb4b1", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-14T01:56:12.021403Z", - "iopub.status.busy": "2026-09-14T01:56:12.021161Z", - "iopub.status.idle": "2026-09-14T01:56:12.031255Z", - "shell.execute_reply": "2026-09-14T01:56:12.029750Z" - }, - "papermill": { - "duration": 0.018954, - "end_time": "2026-09-14T01:56:12.032755+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:12.013801+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[setup] Catégories : ['humour_reussi', 'rire_sans_recadrage', 'recadrage_sans_rire', 'offensif_compris_non_partage', 'rien']\n", - "[setup] LLM endpoint : https://openrouter.ai/api/v1\n", - "[setup] LLM model : anthropic/claude-haiku-4.5\n" - ] - } - ], - "source": [ - "# -*- coding: utf-8 -*-\n", - "# Imports + configuration. Pas de service externe lourd : csv, json, urllib.\n", - "import csv\n", - "import os\n", - "import json\n", - "import time\n", - "import urllib.request\n", - "import urllib.error\n", - "from collections import Counter\n", - "from pathlib import Path\n", - "\n", - "# Catégories du banc — alignées sur le toy model GT-24\n", - "CATEGORIES = [\n", - " \"humour_reussi\", # rire + recadrage partagé\n", - " \"rire_sans_recadrage\", # rire mais pas de partage (chatouille, contagion, nerveux)\n", - " \"recadrage_sans_rire\", # partage sans rire (humour sec, anglo-saxon)\n", - " \"offensif_compris_non_partage\", # offensif compris mais refusé par le destinataire\n", - " \"rien\", # pas d'humour du tout\n", - "]\n", - "CAT_LABEL = {c: i for i, c in enumerate(CATEGORIES)}\n", - "\n", - "# Configuration LLM — canal de jugement epingle sur OpenRouter (#14033, dispatch\n", - "# ai-01 2026-09-13) : le endpoint LAN vLLM (http://192.168.0.47:5002/v1) est\n", - "# injoignable depuis cette lane (HTTP 000 mesure le 2026-09-13). Modele ET\n", - "# version epingles : identifiant exact ci-dessous + echo du champ 'model' de la\n", - "# premiere reponse capture dans les sorties (resolution provider visible).\n", - "OPENAI_COMPAT_URL = \"https://openrouter.ai/api/v1\"\n", - "# Cle lue dans l'environnement — jamais de litteral ici : ce depot est public.\n", - "# Renseigner OPENROUTER_API_KEY dans .secrets/master.env, puis :\n", - "# python scripts/secrets/render_envs.py\n", - "OPENAI_API_KEY = os.getenv(\"OPENROUTER_API_KEY\")\n", - "if not OPENAI_API_KEY:\n", - " raise ValueError(\n", - " \"OPENROUTER_API_KEY absente de l'environnement. \"\n", - " \"Renseignez-la dans .secrets/master.env puis executez \"\n", - " \"scripts/secrets/render_envs.py.\"\n", - " )\n", - "LLM_MODEL = \"anthropic/claude-haiku-4.5\"\n", - "\n", - "# Cache local pour éviter de retélécharger Argumentum\n", - "ARGUMENTUM_CACHE = Path(\"argumentum_scenarii.csv\")\n", - "print(f\"[setup] Catégories : {CATEGORIES}\")\n", - "print(f\"[setup] LLM endpoint : {OPENAI_COMPAT_URL}\")\n", - "print(f\"[setup] LLM model : {LLM_MODEL}\")\n" - ] - }, - { - "cell_type": "markdown", - "id": "79340466", - "metadata": { - "papermill": { - "duration": 0.002745, - "end_time": "2026-09-14T01:56:12.045124+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:12.042379+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "## Corpus Argumentum — fetch raw GitHub\n", - "\n", - "Le submodule `MyIA.AI.Notebooks/SymbolicAI/Argument_Analysis/Argumentum`\n", - "pointe le commit `7e72f3e5` mais **n'est pas initialisé** sur cet environnement\n", - "(mesure c.539 : `git submodule status` retourne le commit avec suffixe `-`,\n", - "worktree `Argumentum/` vide, et `git submodule update --init` timeout 2 min).\n", - "\n", - "**Solution** : fetch direct sur `raw.githubusercontent.com/ArgumentumGames/\n", - "Argumentum/master/Cards/Scenarii/Argumentum Scenarii - Cards.csv`. Le CSV\n", - "fait 555 KB ; SHA du dernier commit upstream vérifiable via l'API GitHub\n", - "(`/repos/ArgumentumGames/Argumentum/commits/master`).\n", - "\n", - "Cette approche préserve l'acceptance « ≥1 corpus réel intégré, scénarios\n", - "Argumentum extraits du submodule » (#12756) sans dépendre de l'init submodule\n", - "(qui sera fait dans une PR séparée post-cycle, voir Conclusion).\n" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "73d99644", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-14T01:56:12.051917Z", - "iopub.status.busy": "2026-09-14T01:56:12.051634Z", - "iopub.status.idle": "2026-09-14T01:56:13.734526Z", - "shell.execute_reply": "2026-09-14T01:56:13.733074Z" - }, - "papermill": { - "duration": 1.687617, - "end_time": "2026-09-14T01:56:13.735931+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:12.048314+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[fetch] downloaded 556796 bytes -> argumentum_scenarii.csv\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[fetch] upstream master @874a5d984f : docs(mindmap): provenance de la route cards FR — elle appartient au livrable #80\n" - ] - } - ], - "source": [ - "# -*- coding: utf-8 -*-\n", - "# Fetch Argumentum CSV. Si cache local présent (commit c.539), on l'utilise\n", - "# pour reproductibilité ; sinon on fetch raw GitHub.\n", - "if ARGUMENTUM_CACHE.exists():\n", - " print(f\"[fetch] cache hit : {ARGUMENTUM_CACHE}\")\n", - " src = \"cache-local\"\n", - "else:\n", - " url = (\"https://raw.githubusercontent.com/ArgumentumGames/Argumentum/master/\"\n", - " \"Cards/Scenarii/Argumentum%20Scenarii%20-%20Cards.csv\")\n", - " try:\n", - " req = urllib.request.Request(url, headers={\"User-Agent\": \"CoursIA-GT28b\"})\n", - " with urllib.request.urlopen(req, timeout=30) as r:\n", - " data = r.read()\n", - " ARGUMENTUM_CACHE.write_bytes(data)\n", - " print(f\"[fetch] downloaded {len(data)} bytes -> {ARGUMENTUM_CACHE}\")\n", - " src = url\n", - " except urllib.error.URLError as e:\n", - " print(f\"[fetch] ERREUR : {e}\")\n", - " raise\n", - "\n", - "# Vérifier le SHA upstream (pour traçabilité du corpus réel)\n", - "sha_url = \"https://api.github.com/repos/ArgumentumGames/Argumentum/commits/master\"\n", - "try:\n", - " req = urllib.request.Request(sha_url, headers={\"User-Agent\": \"CoursIA-GT28b\",\n", - " \"Accept\": \"application/vnd.github.v3+json\"})\n", - " with urllib.request.urlopen(req, timeout=10) as r:\n", - " sha_info = json.loads(r.read())\n", - " upstream_sha = sha_info[\"sha\"][:10]\n", - " upstream_msg = sha_info[\"commit\"][\"message\"].split(\"\\n\")[0][:80]\n", - " print(f\"[fetch] upstream master @{upstream_sha} : {upstream_msg}\")\n", - "except Exception as e:\n", - " print(f\"[fetch] SHA upstream non vérifié ({e}) — corpus tout de même chargé depuis cache\")\n", - " upstream_sha = \"n/a\"\n" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "7390cfad", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-14T01:56:13.764511Z", - "iopub.status.busy": "2026-09-14T01:56:13.764237Z", - "iopub.status.idle": "2026-09-14T01:56:13.787823Z", - "shell.execute_reply": "2026-09-14T01:56:13.786275Z" - }, - "papermill": { - "duration": 0.031114, - "end_time": "2026-09-14T01:56:13.788637+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:13.757523+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[parse] 167 scénarios Argumentum chargés\n", - "[parse] catégories : {'histoire': 17, 'mythologie': 27, 'relation intime': 36, 'vie professionnelle': 30, 'vie personnelle': 25, 'pop culture': 18, 'politique': 14}\n", - "[parse] sous-catégories (21) : {'antiquité': 6, 'moyen-âge et temps modernes': 6, '20e et 21e siècle': 5, 'contes': 10, 'religions': 11, 'littérature': 6, 'drague et séduction': 9, 'vie de couple': 16, 'romance': 11, 'interactions professionnelles': 14, 'relations au travail': 8, 'gestion et administration': 9, 'Bandes dessinées': 5, 'cinéma & télévision': 7, 'science': 6, 'gouvernance': 4, 'manoeuvres et collusion': 6, 'campagne': 4, 'famille et enfance': 8, 'voisins et amis': 11, 'loisirs et espace public': 5}\n", - "[parse] 167 instances retenues (champs FR)\n", - "[parse] exemple : id=1.1.1 titre='La mère de César et Cléopâtre'\n", - " baratineur='Aurelia Cotta, mère de César' -> piocheur='Jules César'\n" - ] - } - ], - "source": [ - "# -*- coding: utf-8 -*-\n", - "# Parse le CSV Argumentum. Conservation des colonnes FR + EN.\n", - "with open(ARGUMENTUM_CACHE, \"r\", encoding=\"utf-8\") as f:\n", - " rows = list(csv.DictReader(f))\n", - "\n", - "print(f\"[parse] {len(rows)} scénarios Argumentum chargés\")\n", - "\n", - "# Distribution par catégorie\n", - "cats = Counter(r[\"catégorie\"] for r in rows)\n", - "print(f\"[parse] catégories : {dict(cats)}\")\n", - "\n", - "# Distribution par sous-catégorie\n", - "subcats = Counter(r[\"sous-catégorie\"] for r in rows)\n", - "print(f\"[parse] sous-catégories ({len(subcats)}) : {dict(subcats)}\")\n", - "\n", - "# Pour le banc humour, on retient les colonnes FR (titre, baratineur, contexte,\n", - "# enjeu, suggestion) — le matériel humoristique brut.\n", - "fields = [\"path\", \"catégorie\", \"sous-catégorie\", \"titre\",\n", - " \"baratineur\", \"piocheur\", \"contexte\", \"enjeu\", \"suggestion\"]\n", - "argumentum = [{k: r[k] for k in fields} for r in rows]\n", - "print(f\"[parse] {len(argumentum)} instances retenues (champs FR)\")\n", - "print(f\"[parse] exemple : id={argumentum[0]['path']} titre='{argumentum[0]['titre']}'\")\n", - "print(f\" baratineur='{argumentum[0]['baratineur']}' -> piocheur='{argumentum[0]['piocheur']}'\")\n" - ] - }, - { - "cell_type": "markdown", - "id": "interp-parse", - "metadata": { - "papermill": { - "duration": 0.005736, - "end_time": "2026-09-14T01:56:13.800118+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:13.794382+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Lecture — 167 scénarios, 7 catégories, 21 sous-catégories\n", - "\n", - "La sortie détaille la structure du corpus Argumentum :\n", - "\n", - "- **167 scénarios** au total, répartis sur **7 catégories** (`histoire` 17, `mythologie` 27, `relation intime` 36, `vie professionnelle` 30, `vie personnelle` 25, `pop culture` 18, `politique` 14). `relation intime` est la plus nombreuse — c'est la catégorie la plus propice au matériel humoristique.\n", - "- **21 sous-catégories** affinent (ex. `antiquité`, `religions`, `drague et séduction`, `cinéma & télévision`). Ce grain fin servira à l'annotation heuristique de la cellule suivante.\n", - "- **Champs retenus** : `path`, `catégorie`, `sous-catégorie`, `titre`, `baratineur`, `piocheur`, `contexte`, `enjeu`, `suggestion`. Le `path` (ex. `7.3.2`) est l'identifiant de scénario utilisé pour le contrôle de disjonction de la section circularité (cell[18]).\n", - "\n", - "L'exemple imprimé (`baratineur` → `piocheur`) montre la structure d'un scénario Argumentum : un `baratineur` avance une interprétation, un `piocheur` doit la recadrer. C'est précisément la mécanique « recadrage partagé » que la cellule `humour_reussi` modélise." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "4161f8c4", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-14T01:56:13.811030Z", - "iopub.status.busy": "2026-09-14T01:56:13.810786Z", - "iopub.status.idle": "2026-09-14T01:56:13.817307Z", - "shell.execute_reply": "2026-09-14T01:56:13.816446Z" - }, - "papermill": { - "duration": 0.012606, - "end_time": "2026-09-14T01:56:13.818382+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:13.805776+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[label] distribution après annotation manuelle : {'rien': 46, 'recadrage_sans_rire': 27, 'humour_reussi': 55, 'rire_sans_recadrage': 25, 'offensif_compris_non_partage': 14}\n" - ] - } - ], - "source": [ - "# -*- coding: utf-8 -*-\n", - "# Mapping Argumentum → cellules du banc.\n", - "# Hypothèse : un scénario Argumentum avec \"enjeu\" absurde + \"suggestion\"\n", - "# inattendue = cellule \"humour_reussi\" (recadrage partagé typique du jeu).\n", - "# Un scénario \"histoire\" (César, Troie, etc.) = souvent \"rien\" (matériel\n", - "# sérieux) ou \"recadrage_sans_rire\" (anachronisme).\n", - "# Cette heuristique est appliquée ici comme **annotation manuelle** (par\n", - "# nous-mêmes, pas auto) ; elle est marquée clairement pour audit.\n", - "\n", - "def label_argumentum(row):\n", - " \"\"\"Annotation manuelle par catégorie + sous-catégorie Argumentum.\n", - " Règles appliquées (transparentes) :\n", - " - 'pop culture' → souvent humour_reussi (références décalées)\n", - " - 'mythologie' → recadrage_sans_rire (anachronisme classique)\n", - " - 'relation intime' → mixte, dépend contexte\n", - " - 'histoire' → souvent rien (matériel trop sérieux)\n", - " - 'politique' → offensif_compris_non_partage (sujet sensible)\n", - " \"\"\"\n", - " cat = row[\"catégorie\"]\n", - " subcat = row[\"sous-catégorie\"]\n", - " enjeu = row.get(\"enjeu\", \"\").lower()\n", - " suggestion = row.get(\"suggestion\", \"\").lower()\n", - " # Heuristiques transparentes\n", - " if cat == \"pop culture\":\n", - " return \"humour_reussi\" # par défaut pop culture = décalage\n", - " if cat == \"mythologie\":\n", - " return \"recadrage_sans_rire\" # mythologie = anachronisme sec\n", - " if cat == \"politique\":\n", - " return \"offensif_compris_non_partage\"\n", - " if cat == \"histoire\":\n", - " return \"rien\" # matériel historique = contexte trop sérieux\n", - " if cat == \"vie professionnelle\":\n", - " # Les sous-catégories varient ; défaut = humour_reussi si en jeu\n", - " return \"humour_reussi\" if any(w in enjeu + suggestion\n", - " for w in [\"absurd\", \"ridicul\", \"drôle\",\n", - " \"plaisant\", \"amusant\"]) else \"rien\"\n", - " if cat == \"vie personnelle\":\n", - " return \"rire_sans_recadrage\" # vie perso = souvent rire sans jeu partagé\n", - " if cat == \"relation intime\":\n", - " return \"humour_reussi\" # relation intime = registre humoristique fréquent\n", - " return \"rien\"\n", - "\n", - "labeled_arg = [{**r, \"label\": label_argumentum(r)} for r in argumentum]\n", - "labels_dist = Counter(r[\"label\"] for r in labeled_arg)\n", - "print(f\"[label] distribution après annotation manuelle : {dict(labels_dist)}\")\n" - ] - }, - { - "cell_type": "markdown", - "id": "b2845630", - "metadata": { - "papermill": { - "duration": 0.002919, - "end_time": "2026-09-14T01:56:13.827558+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:13.824639+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "## Corpus annoté blagues — ≥ 100 instances\n", - "\n", - "Objectif : dépasser le toy model (12 instances) pour une matrice de confusion\n", - "statistiquement significative. Construction **par annotation manuelle** (avec\n", - "justifications explicites par instance, conformément à C.1 : pas de fabrication\n", - "sans verdict — chaque blague est marquée `justification` qui dit pourquoi elle\n", - "tombe dans la cellule choisie).\n", - "\n", - "Composition visée :\n", - "- **Argumentum enrichi** (167 scénarios) → ~60 instances après filtrage\n", - "- **Blagues positives manuelles** (humour réussi) → 30 instances\n", - "- **Négatives explicites** (non-humour : phrases neutres, déclarations) → 20 instances\n", - "- **Edge cases** (chatouille/contagion, offensif refusé, humour sec) → 10 instances\n", - "\n", - "Total cible : 120+ instances, équilibrées par cellule (≥15 par cellule de la\n", - "matrice du toy model).\n" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "655305f9", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-14T01:56:13.835579Z", - "iopub.status.busy": "2026-09-14T01:56:13.835411Z", - "iopub.status.idle": "2026-09-14T01:56:13.849492Z", - "shell.execute_reply": "2026-09-14T01:56:13.848697Z" - }, - "papermill": { - "duration": 0.018797, - "end_time": "2026-09-14T01:56:13.849966+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:13.831169+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[corpus] total : 120 instances\n", - "[corpus] distribution par label : {'rire_sans_recadrage': 14, 'recadrage_sans_rire': 13, 'rien': 38, 'humour_reussi': 48, 'offensif_compris_non_partage': 7}\n", - "[corpus] distribution par source : {'ArgumentumGames/Argumentum': 60, 'blague-manuelle': 30, 'declaration-factuelle': 20, 'edge-case-curated': 10}\n", - "[corpus] humour_reussi : 48 instances OK\n", - "[corpus] rire_sans_recadrage : 14 instances OK\n", - "[corpus] recadrage_sans_rire : 13 instances OK\n", - "[corpus] offensif_compris_non_partage : 7 instances OK\n", - "[corpus] rien : 38 instances OK\n" - ] - } - ], - "source": [ - "# -*- coding: utf-8 -*-\n", - "# CORPUS_DUR — ≥ 100 instances annotées manuellement.\n", - "# Chaque instance = {id, texte, features, label, justification, source}.\n", - "\n", - "# --- 1. Argumentum enrichi : 60 scénarios échantillonnés ---\n", - "import random\n", - "random.seed(42) # reproductibilité\n", - "\n", - "arg_sample = random.sample(labeled_arg, k=60)\n", - "arg_instances = []\n", - "for r in arg_sample:\n", - " # Construire les features selon la cellule d'annotation\n", - " lab = r[\"label\"]\n", - " features = {\n", - " \"laugh\": lab == \"humour_reussi\" or lab == \"rire_sans_recadrage\",\n", - " \"reframe\": lab == \"humour_reussi\" or lab == \"recadrage_sans_rire\",\n", - " \"uptake\": lab == \"humour_reussi\",\n", - " \"refus\": lab == \"offensif_compris_non_partage\",\n", - " }\n", - " arg_instances.append({\n", - " \"id\": \"arg-\" + r[\"path\"],\n", - " \"texte\": \"[\" + r[\"catégorie\"] + \"/\" + r[\"sous-catégorie\"] + \"] \" + r[\"titre\"] + \" — baratineur: \" + r[\"baratineur\"] + \", contexte: \" + r[\"contexte\"][:60] + \"...\",\n", - " \"features\": features,\n", - " \"label\": lab,\n", - " \"justification\": \"Annotation manuelle Argumentum : catégorie \" + r[\"catégorie\"] + \" → heuristique cell[5] donne \" + lab,\n", - " \"source\": \"ArgumentumGames/Argumentum\",\n", - " })\n", - "\n", - "# --- 2. Blagues positives manuelles (humour réussi) : 30 ---\n", - "POSITIVE_JOKES = [\n", - " (\"joke-p01\", \"Un informaticien rentre dans un bar et dit : 'je voudrais une bière,\", \"humour_reussi\", \"Refrain 'je voudrais' x10 = structure répétitive absurde + callback\"),\n", - " (\"joke-p02\", \"Pourquoi les développeurs confondent Halloween et Noël ? Parce que Oct 31 == Dec 25.\", \"humour_reussi\", \"Anagramme numérique Octal/Décimal — recadrage par équivalence inattendue\"),\n", - " (\"joke-p03\", \"Il y a 10 types de personnes au monde : ceux qui comprennent le binaire et ceux qui ne le comprennent pas.\", \"humour_reussi\", \"Le '10' en base 2 = 2 en base 10 = recadrage meta + callback\"),\n", - " (\"joke-p04\", \"Un SQL entre dans un bar, voit deux tables et leur dit : 'SELECT * FROM...'\", \"humour_reussi\", \"Personnification SQL + jeu de mots 'SELECT *'\"),\n", - " (\"joke-p05\", \"Combien d'ingénieurs faut-il pour changer une ampoule ? Aucun, c'est un problème hardware.\", \"humour_reussi\", \"Inversion responsabilité dev/hardware + callout métier\"),\n", - " (\"joke-p06\", \"Je suis tombé amoureuse d'une fonction quadratique. Mais elle avait deux racines.\", \"humour_reussi\", \"Métaphore math + double sens 'racines'/'problèmes'\"),\n", - " (\"joke-p07\", \"Un null et un undefined entrent dans un bar. Le barman dit 'On accepte pas les non-définis ici'.\", \"humour_reussi\", \"Callback JS + référence culturelle programmeurs\"),\n", - " (\"joke-p08\", \"Je voulais te raconter une blague sur UDP... mais je sais si elle arrive.\", \"humour_reussi\", \"Métaphore protocole UDP = best-effort delivery\"),\n", - " (\"joke-p09\", \"Le père Noël a-t-il déjà eu un problème de pile ? Non, il a toujours des piles neuves.\", \"humour_reussi\", \"Jeu de mots 'pile' électrique/noël + absurdité\"),\n", - " (\"joke-p10\", \"Pourquoi le café est-il si bon au travail ? Parce qu'il est fraîchement moulu par l'échéance.\", \"humour_reussi\", \"Métaphore deadline = mouture + 'fraîchement' double sens\"),\n", - " (\"joke-p11\", \"J'ai essayé d'écrire une blague sur les coroutines, mais je n'arrive pas à la yield.\", \"humour_reussi\", \"Référence yield coroutine + jeu de mots 'je n'arrive pas à'\"),\n", - " (\"joke-p12\", \"Docker, Kubernetes, Prometheus, Grafana. On m'a dit que c'était simple, alors je stack.\", \"humour_reussi\", \"Accumulation noms outils + 'stack' double sens\"),\n", - " (\"joke-p13\", \"Mon compilateur et moi on a une relation stable : il compile, je pleure.\", \"humour_reussi\", \"Métaphore relation + inversion cause-effet\"),\n", - " (\"joke-p14\", \"J'ai un ami palindrome. On ne peut pas se différencier.\", \"humour_reussi\", \"Définition palindrome appliquée à la relation + absurde\"),\n", - " (\"joke-p15\", \"Les regex sont comme des licornes : tout le monde en parle, personne les a vues.\", \"humour_reussi\", \"Métaphore mythique + référence métier\"),\n", - " (\"joke-p16\", \"Un physicien, un biologiste et un chimiste voient 2 bâtiments. L'un entre, l'autre sort. 'Tiens, ils ont échangé.'\", \"humour_reussi\", \"Jeu de mots 'bâtiment entré/sorti' = observation absurde\"),\n", - " (\"joke-p17\", \"Que dit un informaticien quand il s'ennuie ? 'printf(mot)\\n'\", \"humour_reussi\", \"Référence C printf + absurdité minimale\"),\n", - " (\"joke-p18\", \"Si Dieu existe, il est Objective-C : tout est message.\", \"humour_reussi\", \"Paradoxe religieux + référence Apple dev\"),\n", - " (\"joke-p19\", \"Le temps est une illusion. Le décalage horaire, doublement.\", \"humour_reussi\", \"Référence Hitchhiker's Guide + jeu de mots\"),\n", - " (\"joke-p20\", \"Un photon entre dans un bar et commande une bière. Le barman dit 'Pour vous, c'est gratuit, on vous voit pas partir'.\", \"humour_reussi\", \"Physique quantique appliquée au bar + callback\"),\n", - " (\"joke-p21\", \"J'ai une blague sur les matrices, mais c'est hors de portée du public.\", \"humour_reussi\", \"Meta-blink humour + math\"),\n", - " (\"joke-p22\", \"Un chat roux dans une salle de serveurs est dangereux : il pourrait activer l'incident majeur.\", \"humour_reussi\", \"Internet cat roux = chaos + référence NOC\"),\n", - " (\"joke-p23\", \"Pourquoi les plongeurs plongent-ils toujours en arrière et jamais en avant ? Parce que sinon ils tomberaient dans le bateau.\", \"humour_reussi\", \"Logique absurde + inversion sens commun\"),\n", - " (\"joke-p24\", \"Le HTML n'est pas un langage de programmation. Et le plus dur, c'est de le dire à mon patron.\", \"humour_reussi\", \"Débat tech classique + référence hiérarchique\"),\n", - " (\"joke-p25\", \"Si vous pensez que personne ne s'intéresse à votre vie, regardez vos logs Git.\", \"humour_reussi\", \"Métaphore surveillance + callback dev\"),\n", - " (\"joke-p26\", \"Comment debug-on un avion ? On retire les composants un par un jusqu'à ce qu'il ne plante plus.\", \"humour_reussi\", \"Procédure debug absurde appliquée à l'avion\"),\n", - " (\"joke-p27\", \"Mieux vaut avoir un git pull que deux tu l'auras.\", \"humour_reussi\", \"Verbe 'avoir' double sens + référence git\"),\n", - " (\"joke-p28\", \"Mon chat a appris Python. Maintenant il chasse les exceptions au lieu des souris.\", \"humour_reussi\", \"Métaphore félin + référence Python try/except\"),\n", - " (\"joke-p29\", \"Les submodules Git, c'est comme les voisins : mieux vaut ne pas les déranger.\", \"humour_reussi\", \"Métaphore sociale + référence submodules (cf c.539 init)\"),\n", - " (\"joke-p30\", \"Il était une fois un UTF-8 qui ne savait pas où était la fin. Il était perdu dans un BOM.\", \"humour_reussi\", \"Référence BOM + métaphore conte initiatique\"),\n", - "]\n", - "positive_instances = [{\n", - " \"id\": j[0], \"texte\": j[1],\n", - " \"features\": {\"laugh\": True, \"reframe\": True, \"uptake\": True, \"refus\": False},\n", - " \"label\": j[2], \"justification\": j[3],\n", - " \"source\": \"blague-manuelle\",\n", - "} for j in POSITIVE_JOKES]\n", - "\n", - "# --- 3. Négatives (pas d'humour) : 20 ---\n", - "NEGATIVE_STATEMENTS = [\n", - " (\"neg-s01\", \"Il pleut aujourd'hui à Paris.\", \"rien\", \"Déclaration factuelle sans mécanisme humoristique\"),\n", - " (\"neg-s02\", \"Le PIB de la France en 2025 a augmenté de 0,3%.\", \"rien\", \"Statistique macro-économique, registre informatif\"),\n", - " (\"neg-s03\", \"Les soldes d'hiver commencent le 8 janvier 2026.\", \"rien\", \"Annonce commerciale factuelle\"),\n", - " (\"neg-s04\", \"Le périphérique parisien est fermé entre 22h et 6h ce soir.\", \"rien\", \"Information de circulation\"),\n", - " (\"neg-s05\", \"L'addition au restaurant était de 47 euros pour trois personnes.\", \"rien\", \"Récit factuel sans punchline\"),\n", - " (\"neg-s06\", \"Le cours de l'action a clôturé à 142,50 euros hier.\", \"rien\", \"Information boursière standard\"),\n", - " (\"neg-s07\", \"La réunion est reportée à mardi prochain à 14h.\", \"rien\", \"Communication administrative neutre\"),\n", - " (\"neg-s08\", \"Mon dentiste m'a donné rendez-vous le 15 mars.\", \"rien\", \"Information personnelle sans renversement\"),\n", - " (\"neg-s09\", \"Le livre fait 320 pages et pèse 450 grammes.\", \"rien\", \"Description physique factuelle\"),\n", - " (\"neg-s10\", \"La somme de deux et deux est quatre.\", \"rien\", \"Énoncé mathématique neutre\"),\n", - " (\"neg-s11\", \"L'avion décolle à 14h32 de la piste 27 droite.\", \"rien\", \"Annonce aéroport factuelle\"),\n", - " (\"neg-s12\", \"J'ai rendez-vous avec mon médecin à 10 heures demain.\", \"rien\", \"Information de planning\"),\n", - " (\"neg-s13\", \"Le train de 8h47 est supprimé ce matin.\", \"rien\", \"Information de trafic ferroviaire\"),\n", - " (\"neg-s14\", \"La température extérieure est de 7 degrés.\", \"rien\", \"Lecture thermométrique\"),\n", - " (\"neg-s15\", \"Mon numéro de téléphone est le 01 23 45 67 89.\", \"rien\", \"Énoncé de coordonnées\"),\n", - " (\"neg-s16\", \"Le mot 'table' a cinq lettres.\", \"rien\", \"Observation linguistique neutre\"),\n", - " (\"neg-s17\", \"L'année 2026 a commencé un jeudi.\", \"rien\", \"Information calendaire\"),\n", - " (\"neg-s18\", \"Le café coûte 2 euros à la machine de l'étage.\", \"rien\", \"Tarif sans contexte humoristique\"),\n", - " (\"neg-s19\", \"Mon chat s'appelle Pixel et il est roux.\", \"rien\", \"Information sur animal de compagnie\"),\n", - " (\"neg-s20\", \"J'ai fini mon rapport à 17 heures.\", \"rien\", \"Annonce de fin de tâche\"),\n", - "]\n", - "negative_instances = [{\n", - " \"id\": n[0], \"texte\": n[1],\n", - " \"features\": {\"laugh\": False, \"reframe\": False, \"uptake\": False, \"refus\": False},\n", - " \"label\": n[2], \"justification\": n[3],\n", - " \"source\": \"declaration-factuelle\",\n", - "} for n in NEGATIVE_STATEMENTS]\n", - "\n", - "# --- 4. Edge cases (4 catégories x 2-3) ---\n", - "EDGE_CASES = [\n", - " (\"edge-01\", \"Mon collègue a ri tellement fort pendant la réunion qu'il a éternué.\", \"rire_sans_recadrage\", \"Rire reflexe (éternuement) sans mécanisme de recadrage partagé\"),\n", - " (\"edge-02\", \"Elle riait nerveusement en attendant les résultats de l'analyse.\", \"rire_sans_recadrage\", \"Rire nerveux = réaction physiologique, pas partage de forme\"),\n", - " (\"edge-03\", \"J'ai chatouillé ma cousine et elle a ri aux éclats.\", \"rire_sans_recadrage\", \"Chatouille = stimulus physique direct, pas humour\"),\n", - " (\"edge-04\", \"'I told my wife she was drawing her eyebrows too high. She seemed surprised.' (Graham Chapman)\", \"recadrage_sans_rire\", \"Deadpan : le renversement est dans la chute, le ton reste neutre\"),\n", - " (\"edge-05\", \"'I'm on a whiskey diet. I've lost three days already.' (Tommy Cooper)\", \"recadrage_sans_rire\", \"Twist verbal sans rire explicite, registre sec britannique\"),\n", - " (\"edge-06\", \"'I used to think I was indecisive. But now I'm not so sure.'\", \"recadrage_sans_rire\", \"Recadrage meta sans marque d'humour audible\"),\n", - " (\"edge-07\", \"Mon oncle fait des blagues racistes à table. Tout le monde rit sauf moi.\", \"offensif_compris_non_partage\", \"Humour offensant, le mécanisme est compris (certains rient) mais l'auteur refuse d'y participer\"),\n", - " (\"edge-08\", \"'Vous les femmes, vous savez pas conduire.' J'ai entendu la blague, j'ai pas ri.\", \"offensif_compris_non_partage\", \"Sexisme ordinaire ; compréhension totale, refus de participation\"),\n", - " (\"edge-09\", \"Son copain a fait une blague sur mon poids. J'ai souri poliment.\", \"offensif_compris_non_partage\", \"Politesse vs refus ; le mécanisme est reconnu mais pas repris\"),\n", - " (\"edge-10\", \"Le chef a fait une blague blessante. Tout le service a ri par peur.\", \"offensif_compris_non_partage\", \"Rire de soumission (pas de partage authentique), registre professionnel\"),\n", - "]\n", - "edge_instances = [{\n", - " \"id\": e[0], \"texte\": e[1],\n", - " \"features\": {\"laugh\": e[2] == \"rire_sans_recadrage\",\n", - " \"reframe\": e[2] in (\"humour_reussi\", \"recadrage_sans_rire\"),\n", - " \"uptake\": e[2] == \"humour_reussi\",\n", - " \"refus\": e[2] == \"offensif_compris_non_partage\"},\n", - " \"label\": e[2], \"justification\": e[3],\n", - " \"source\": \"edge-case-curated\",\n", - "} for e in EDGE_CASES]\n", - "\n", - "CORPUS_DUR = arg_instances + positive_instances + negative_instances + edge_instances\n", - "\n", - "# Vérification acceptance #12756 : ≥100 instances\n", - "print(f\"[corpus] total : {len(CORPUS_DUR)} instances\")\n", - "assert len(CORPUS_DUR) >= 100, f\"acceptance ratée : {len(CORPUS_DUR)} < 100\"\n", - "\n", - "# Distribution par cellule\n", - "dist = Counter(c[\"label\"] for c in CORPUS_DUR)\n", - "print(f\"[corpus] distribution par label : {dict(dist)}\")\n", - "\n", - "# Distribution par source\n", - "src_dist = Counter(c[\"source\"] for c in CORPUS_DUR)\n", - "print(f\"[corpus] distribution par source : {dict(src_dist)}\")\n", - "\n", - "# Sanity check : au moins 5 instances par catégorie\n", - "for cat in CATEGORIES:\n", - " n = dist.get(cat, 0)\n", - " status = \"OK\" if n >= 5 else f\"⚠️ faible ({n})\"\n", - " print(f\"[corpus] {cat} : {n} instances {status}\")\n" - ] - }, - { - "cell_type": "markdown", - "id": "interp-corpus", - "metadata": { - "papermill": { - "duration": 0.003193, - "end_time": "2026-09-14T01:56:13.856441+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:13.853248+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Lecture — 120 instances, 4 sources, distribution par cellule\n", - "\n", - "La sortie confirme l'acceptance `≥ 100 instances` :\n", - "\n", - "- **Total : 120 instances** (60 Argumentum + 30 blagues positives manuelles + 20 déclarations factuelles + 10 edge cases), l'`assert` passe.\n", - "- **Distribution par label** : `humour_reussi` 48, `rien` 38, `recadrage_sans_rire` 13, `rire_sans_recadrage` 14, `offensif_compris_non_partage` 7. Aucune cellule n'est vide, toutes dépassent le seuil de 5 instances — le banc est statistiquement exploitable.\n", - "- **Distribution par source** : Argumentum 60, blague-manuelle 30, declaration-factuelle 20, edge-case-curated 10. Quatre sources, deux gratuites (Argumentum + manuel) et deux négatives (factuelle + edge) — la diversité protège contre le biais de source unique.\n", - "\n", - "Deux lectures structurelles pour la suite :\n", - "\n", - "- **`humour_reussi` est surreprésentée (48/120 = 40 %)** parce qu'elle agrège l'Argumentum annoté `humour_reussi` (pop culture + relation intime par défaut) ET les 30 blagues positives manuelles. C'est attendu : la classe positive d'intérêt est enrichie pour avoir assez d'exemples.\n", - "- **`offensif_compris_non_partage` est la plus rare (7)** : seuls les 10 edge cases l'alimentent (moins les 3 attribués ailleurs). C'est la cellule qui testera le plus la discrimination fine du LLM en section 14." - ] - }, - { - "cell_type": "markdown", - "id": "4cc974f5", - "metadata": { - "papermill": { - "duration": 0.004904, - "end_time": "2026-09-14T01:56:13.865202+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:13.860298+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "## Détecteurs — règle vs partage (toy model, répliqué)\n", - "\n", - "On reprend les deux détecteurs du toy model GT-20 (ex-GT-24) :\n", - "\n", - "- **naïf** : stimulus = rire → `humour_reussi` si `laugh`, sinon `rien`\n", - "- **partage** : trois signaux (reframe + uptake + refus) → discrimination 5 cellules\n", - "\n", - "On y ajoute un **détecteur LLM** : `anthropic/claude-haiku-4.5` (canal épinglé\n", - "OpenRouter, cf cell[1]) reçoit le `texte` d'une\n", - "instance et doit répondre par une catégorie parmi les 5.\n", - "Verdict SOTA : SOTA-OK (endpoint OpenAI-compat invoqué HTTP, modèle et version\n", - "épinglés, écho provider capturé dans les sorties).\n", - "Pas de fallback dégradé ; en cas d'erreur réseau, on documente l'échec et\n", - "on NE PAS continuer avec un placeholder.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "bc3cafe6", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-14T01:56:13.877761Z", - "iopub.status.busy": "2026-09-14T01:56:13.877560Z", - "iopub.status.idle": "2026-09-14T01:56:13.883301Z", - "shell.execute_reply": "2026-09-14T01:56:13.882533Z" - }, - "papermill": { - "duration": 0.012058, - "end_time": "2026-09-14T01:56:13.883837+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:13.871779+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " arg-7.3.2 truth=rire_sans_recadrage naive=humour_reussi reframe=rire_sans_recadrage\n", - " arg-2.2.2 truth=recadrage_sans_rire naive=rien reframe=rien\n", - " arg-1.2.1 truth=rien naive=rien reframe=rien\n", - " arg-3.3.2 truth=humour_reussi naive=humour_reussi reframe=humour_reussi\n", - " arg-3.2.10 truth=humour_reussi naive=humour_reussi reframe=humour_reussi\n" - ] - } - ], - "source": [ - "# -*- coding: utf-8 -*-\n", - "# Réplication des deux détecteurs du toy model (naïf + partage)\n", - "def naive_detector(inst):\n", - " \"\"\"Détecteur naïf : tout rire est humour réussi.\"\"\"\n", - " return \"humour_reussi\" if inst[\"features\"][\"laugh\"] else \"rien\"\n", - "\n", - "def reframe_detector(inst):\n", - " \"\"\"Détecteur par partage : exige reframe + uptake, distingue refus.\"\"\"\n", - " f = inst[\"features\"]\n", - " if f[\"refus\"]:\n", - " return \"offensif_compris_non_partage\"\n", - " if f[\"reframe\"] and f[\"uptake\"]:\n", - " return \"humour_reussi\" if f[\"laugh\"] else \"recadrage_sans_rire\"\n", - " if f[\"laugh\"]:\n", - " return \"rire_sans_recadrage\"\n", - " return \"rien\"\n", - "\n", - "# Matrice de confusion générique\n", - "def confusion_matrix(instances, detector, cats=CATEGORIES):\n", - " M = {v: {p: 0 for p in cats} for v in cats}\n", - " for x in instances:\n", - " M[x[\"label\"]][detector(x)] += 1\n", - " return M\n", - "\n", - "def show_matrix(M, title):\n", - " print(f\"\\n=== {title} ===\")\n", - " cats = list(M.keys())\n", - " # En-tête (backslash évité pour compatibilité f-string Python <3.12)\n", - " header_label = \"Vérité / Prédit\"\n", - " print(f\"{header_label:<28}\" + \"\".join(f\"{c[:8]:>9}\" for c in cats))\n", - " for v in cats:\n", - " row = \"\".join(f\"{M[v][p]:>9d}\" for p in cats)\n", - " print(f\"{v:<28}{row}\")\n", - "\n", - "# Test rapide sur 5 instances\n", - "for inst in CORPUS_DUR[:5]:\n", - " print(f\" {inst['id']:<10} truth={inst['label']:<25} naive={naive_detector(inst):<25} reframe={reframe_detector(inst)}\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "d5841413", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-14T01:56:13.897006Z", - "iopub.status.busy": "2026-09-14T01:56:13.896775Z", - "iopub.status.idle": "2026-09-14T01:56:15.110671Z", - "shell.execute_reply": "2026-09-14T01:56:15.109572Z" - }, - "papermill": { - "duration": 1.218608, - "end_time": "2026-09-14T01:56:15.111976+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:13.893368+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[LLM test] arg-7.3.2 : truth=rire_sans_recadrage\n", - " pred='humour_reussi'\n", - " raw='humour_reussi'\n", - " latency=1205 ms\n" - ] - } - ], - "source": [ - "# -*- coding: utf-8 -*-\n", - "# Détecteur LLM — appel HTTP /chat/completions avec prompt structuré.\n", - "import json\n", - "import urllib.request\n", - "import urllib.error\n", - "\n", - "LLM_PROMPT_TEMPLATE = (\n", - "\n", - " \"Tu es un classifieur d'humour. Tu reçois un texte court (scénario, blague ou déclaration). \"\n", - "\n", - " \"Tu dois répondre UNIQUEMENT par une catégorie parmi :\\n\"\n", - "\n", - " \" - humour_reussi : rire + recadrage partagé\\n\"\n", - "\n", - " \" - rire_sans_recadrage : rire mais pas de partage\\n\"\n", - "\n", - " \" - recadrage_sans_rire : partage sans rire (humour sec)\\n\"\n", - "\n", - " \" - offensif_compris_non_partage : offensif, compris mais refusé\\n\"\n", - "\n", - " \" - rien : pas d'humour du tout\\n\"\n", - "\n", - " \"\\n\"\n", - "\n", - " \"Réponds UNIQUEMENT par le label exact, sans phrase ni explication.\\n\"\n", - "\n", - " \"\\n\"\n", - "\n", - " \"Texte : {texte}\\n\"\n", - "\n", - " \"Catégorie :\"\n", - "\n", - ")\n", - "\n", - "def llm_detector(inst, timeout=15):\n", - " \"\"\"Appel HTTP au endpoint OpenAI-compat (OpenRouter). Retourne (label, raw_response, latency_ms).\n", - " En cas d'erreur réseau, retourne (None, error_str, 0).\"\"\"\n", - " prompt = LLM_PROMPT_TEMPLATE.format(texte=inst[\"texte\"][:500])\n", - " body = {\n", - " \"model\": LLM_MODEL,\n", - " \"messages\": [{\"role\": \"user\", \"content\": prompt}],\n", - " \"max_tokens\": 50,\n", - " \"temperature\": 0.0,\n", - " }\n", - " # Qwen3.6 thinking mode consomme tout max_tokens en reasoning interne ;\n", - " # on le désactive pour obtenir la réponse directe au prompt. Paramètre\n", - " # limité aux familles qwen : inconnu d'autres fournisseurs (cf #14033).\n", - " if \"qwen\" in LLM_MODEL.lower():\n", - " body[\"chat_template_kwargs\"] = {\"enable_thinking\": False}\n", - " body = json.dumps(body).encode(\"utf-8\")\n", - " req = urllib.request.Request(\n", - " f\"{OPENAI_COMPAT_URL}/chat/completions\",\n", - " data=body,\n", - " headers={\n", - " \"Content-Type\": \"application/json\",\n", - " \"Authorization\": f\"Bearer {OPENAI_API_KEY}\",\n", - " },\n", - " )\n", - " t0 = time.time()\n", - " try:\n", - " with urllib.request.urlopen(req, timeout=timeout) as r:\n", - " resp = json.loads(r.read())\n", - " dt_ms = int((time.time() - t0) * 1000)\n", - " content = resp[\"choices\"][0][\"message\"][\"content\"].strip()\n", - " # Tolérance : le LLM peut ajouter du texte autour\n", - " label = None\n", - " for cat in CATEGORIES:\n", - " if cat in content.lower():\n", - " label = cat\n", - " break\n", - " if label is None and content.lower() in [c.lower() for c in CATEGORIES]:\n", - " label = next(c for c in CATEGORIES if c.lower() == content.lower())\n", - " return label, content, dt_ms\n", - " except urllib.error.URLError as e:\n", - " return None, f\"URLError: {e}\", 0\n", - " except Exception as e:\n", - " return None, f\"Error: {type(e).__name__}: {e}\", 0\n", - "\n", - "# Test 1 instance pour vérifier que le endpoint répond\n", - "test_inst = CORPUS_DUR[0]\n", - "test_label, test_raw, test_dt = llm_detector(test_inst)\n", - "print(f\"[LLM test] {test_inst['id']} : truth={test_inst['label']}\")\n", - "print(f\" pred={test_label!r}\")\n", - "print(f\" raw={test_raw!r}\")\n", - "print(f\" latency={test_dt} ms\")\n" - ] - }, - { - "cell_type": "markdown", - "id": "d7d46a28", - "metadata": { - "papermill": { - "duration": 0.007752, - "end_time": "2026-09-14T01:56:15.127554+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:15.119802+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "## Ranking LLM — sous-ensemble pour mesure\n", - "\n", - "Pour ne pas consommer 120 appels LLM (et risquer de tomber sur le rate limit\n", - "ou un timeout réseau prolongé), on sélectionne un sous-ensemble **stratifié** de\n", - "30 instances : 6 par cellule de la matrice. Cela permet de mesurer les\n", - "tendances du LLM sans dépendance excessive à la disponibilité du endpoint.\n", - "\n", - "Critères : (1) stratification par label, (2) ≥2 sources représentées (Argumentum\n", - "+ manuel + edge), (3) ≤30 instances pour limiter latence cumulée.\n", - "\n", - "**Important — C.2 + C.4** : les sorties LLM sont committées dans le notebook\n", - "(papermill exécute la cellule ; les outputs sont dans le .ipynb). Les valeurs\n", - "citées dans le diagnostic sont issues de cette sortie committée.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "597cbf10", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-14T01:56:15.143651Z", - "iopub.status.busy": "2026-09-14T01:56:15.143380Z", - "iopub.status.idle": "2026-09-14T01:56:37.398188Z", - "shell.execute_reply": "2026-09-14T01:56:37.396816Z" - }, - "papermill": { - "duration": 22.26592, - "end_time": "2026-09-14T01:56:37.399550+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:15.133630+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[sample] ranking_set : 30 instances stratifiées\n", - "[sample] sources : {'blague-manuelle': 3, 'ArgumentumGames/Argumentum': 18, 'edge-case-curated': 6, 'declaration-factuelle': 3}\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[LLM batch] 5/30 traités — 0 échecs\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[LLM batch] 10/30 traités — 0 échecs\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[LLM batch] 15/30 traités — 0 échecs\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[LLM batch] 20/30 traités — 0 échecs\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[LLM batch] 25/30 traités — 0 échecs\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[LLM batch] 30/30 traités — 0 échecs\n", - "\n", - "[latence] min=560 ms, max=895 ms, mean=741 ms, n=30\n", - "[latence] échecs : 0\n" - ] - } - ], - "source": [ - "# -*- coding: utf-8 -*-\n", - "# Sous-ensemble stratifié : 6 instances par cellule.\n", - "from collections import defaultdict\n", - "\n", - "by_label = defaultdict(list)\n", - "for inst in CORPUS_DUR:\n", - " by_label[inst[\"label\"]].append(inst)\n", - "\n", - "SAMPLE_SIZE = 6\n", - "ranking_set = []\n", - "for cat in CATEGORIES:\n", - " pool = by_label[cat]\n", - " if len(pool) >= SAMPLE_SIZE:\n", - " ranking_set.extend(random.sample(pool, SAMPLE_SIZE))\n", - " else:\n", - " # Si on n'a pas assez, on prend tout + on note le déficit\n", - " ranking_set.extend(pool)\n", - " print(f\"[sample] ⚠️ {cat} : seulement {len(pool)} instances (cible {SAMPLE_SIZE})\")\n", - "\n", - "print(f\"[sample] ranking_set : {len(ranking_set)} instances stratifiées\")\n", - "src_dist = Counter(c[\"source\"] for c in ranking_set)\n", - "print(f\"[sample] sources : {dict(src_dist)}\")\n", - "\n", - "# Appel LLM sur le sous-ensemble (avec mesure de latence)\n", - "llm_results = []\n", - "fails = []\n", - "for i, inst in enumerate(ranking_set, 1):\n", - " label, raw, dt_ms = llm_detector(inst)\n", - " llm_results.append({**inst, \"llm_pred\": label, \"llm_raw\": raw, \"latency_ms\": dt_ms})\n", - " if label is None:\n", - " fails.append((inst[\"id\"], raw))\n", - " if i % 5 == 0 or i == len(ranking_set):\n", - " print(f\"[LLM batch] {i}/{len(ranking_set)} traités — {len(fails)} échecs\")\n", - "\n", - "# Statistiques de latence\n", - "latencies = [r[\"latency_ms\"] for r in llm_results if r[\"latency_ms\"] > 0]\n", - "if latencies:\n", - " print(f\"\\n[latence] min={min(latencies)} ms, max={max(latencies)} ms, \"\n", - " f\"mean={sum(latencies)/len(latencies):.0f} ms, n={len(latencies)}\")\n", - "print(f\"[latence] échecs : {len(fails)}\")\n", - "for fid, fraw in fails:\n", - " print(f\" - {fid}: {fraw[:100]}\")\n" - ] - }, - { - "cell_type": "markdown", - "id": "654ecae6", - "metadata": { - "papermill": { - "duration": 0.005732, - "end_time": "2026-09-14T01:56:37.413382+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:37.407650+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "## Matrices de confusion — règle vs partage vs LLM\n", - "\n", - "On compare trois détecteurs sur le sous-ensemble `ranking_set` :\n", - "\n", - "1. **Naïf** (règle : stimulus = rire)\n", - "2. **Partage** (règle : reframe + uptake)\n", - "3. **LLM** (`anthropic/claude-haiku-4.5` via OpenRouter, canal épinglé)\n", - "\n", - "Métrique clé : précision et recall sur la classe positive `humour_reussi`.\n", - "Le banc toy livrait déjà la structure ; on étend ici avec le LLM.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "751cceb1", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-14T01:56:37.421545Z", - "iopub.status.busy": "2026-09-14T01:56:37.421388Z", - "iopub.status.idle": "2026-09-14T01:56:37.426552Z", - "shell.execute_reply": "2026-09-14T01:56:37.425681Z" - }, - "papermill": { - "duration": 0.010264, - "end_time": "2026-09-14T01:56:37.427857+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:37.417593+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "=== Matrice — détecteur NAÏF (ranking_set) ===\n", - "Vérité / Prédit humour_r rire_san recadrag offensif rien\n", - "humour_reussi 6 0 0 0 0\n", - "rire_sans_recadrage 6 0 0 0 0\n", - "recadrage_sans_rire 0 0 0 0 6\n", - "offensif_compris_non_partage 0 0 0 0 6\n", - "rien 0 0 0 0 6\n", - "\n", - "=== Matrice — détecteur par PARTAGE (ranking_set) ===\n", - "Vérité / Prédit humour_r rire_san recadrag offensif rien\n", - "humour_reussi 6 0 0 0 0\n", - "rire_sans_recadrage 0 6 0 0 0\n", - "recadrage_sans_rire 0 0 0 0 6\n", - "offensif_compris_non_partage 0 0 0 6 0\n", - "rien 0 0 0 0 6\n", - "\n", - "[LLM] 30/30 instances classifiées par le LLM\n", - "\n", - "=== Matrice — détecteur LLM anthropic/claude-haiku-4.5 ===\n", - "Vérité / Prédit humour_r rire_san recadrag offensif rien\n", - "humour_reussi 5 0 0 0 1\n", - "rire_sans_recadrage 2 0 0 1 3\n", - "recadrage_sans_rire 5 0 0 0 1\n", - "offensif_compris_non_partage 3 2 0 1 0\n", - "rien 1 0 0 0 5\n" - ] - } - ], - "source": [ - "# -*- coding: utf-8 -*-\n", - "# Matrice de confusion naïve\n", - "M_naive = confusion_matrix(ranking_set, naive_detector)\n", - "show_matrix(M_naive, \"Matrice — détecteur NAÏF (ranking_set)\")\n", - "\n", - "# Matrice de confusion partage\n", - "M_reframe = confusion_matrix(ranking_set, reframe_detector)\n", - "show_matrix(M_reframe, \"Matrice — détecteur par PARTAGE (ranking_set)\")\n", - "\n", - "# Matrice de confusion LLM — sur les instances où le LLM a répondu\n", - "instances_with_pred = [r for r in llm_results if r[\"llm_pred\"] is not None]\n", - "print(f\"\\n[LLM] {len(instances_with_pred)}/{len(llm_results)} instances classifiées par le LLM\")\n", - "\n", - "if instances_with_pred:\n", - " M_llm = {v: {p: 0 for p in CATEGORIES} for v in CATEGORIES}\n", - " for r in instances_with_pred:\n", - " M_llm[r[\"label\"]][r[\"llm_pred\"]] += 1\n", - " show_matrix(M_llm, f\"Matrice — détecteur LLM {LLM_MODEL}\")\n", - "else:\n", - " print(\"[LLM] Aucun résultat exploitable — endpoint non accessible\")\n", - " M_llm = None\n" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "2aeeaa32", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-14T01:56:37.439806Z", - "iopub.status.busy": "2026-09-14T01:56:37.439371Z", - "iopub.status.idle": "2026-09-14T01:56:37.449415Z", - "shell.execute_reply": "2026-09-14T01:56:37.448065Z" - }, - "papermill": { - "duration": 0.017183, - "end_time": "2026-09-14T01:56:37.450963+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:37.433780+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Détecteur Precision Recall F1 TP FP FN TN\n", - "Naïf 0.500 1.000 0.667 6 6 0 18\n", - "Partage 1.000 1.000 1.000 6 0 0 24\n", - "LLM claude-haiku-4.5 0.312 0.833 0.455 5 11 1 13\n" - ] - } - ], - "source": [ - "# -*- coding: utf-8 -*-\n", - "# Précision et recall sur humour_reussi (la classe 'difficile').\n", - "def precision_recall(instances, detector, positive=\"humour_reussi\"):\n", - " tp = fp = fn = tn = 0\n", - " for x in instances:\n", - " pred = detector(x) == positive\n", - " truth = x[\"label\"] == positive\n", - " if pred and truth: tp += 1\n", - " elif pred and not truth: fp += 1\n", - " elif (not pred) and truth: fn += 1\n", - " else: tn += 1\n", - " prec = tp / (tp + fp) if (tp + fp) > 0 else 0\n", - " rec = tp / (tp + fn) if (tp + fn) > 0 else 0\n", - " f1 = 2 * prec * rec / (prec + rec) if (prec + rec) > 0 else 0\n", - " return prec, rec, f1, tp, fp, fn, tn\n", - "\n", - "print(f\"{'Détecteur':<20}{'Precision':>11}{'Recall':>9}{'F1':>7}{'TP':>5}{'FP':>5}{'FN':>5}{'TN':>5}\")\n", - "for name, det in [(\"Naïf\", naive_detector), (\"Partage\", reframe_detector)]:\n", - " p, r, f, tp, fp, fn, tn = precision_recall(ranking_set, det)\n", - " print(f\"{name:<20}{p:>11.3f}{r:>9.3f}{f:>7.3f}{tp:>5d}{fp:>5d}{fn:>5d}{tn:>5d}\")\n", - "\n", - "if instances_with_pred:\n", - " p, r, f, tp, fp, fn, tn = precision_recall(instances_with_pred, lambda x: x[\"llm_pred\"])\n", - " llm_row_label = f\"LLM {LLM_MODEL.split('/')[-1]}\"\n", - " print(f\"{llm_row_label:<20}{p:>11.3f}{r:>9.3f}{f:>7.3f}{tp:>5d}{fp:>5d}{fn:>5d}{tn:>5d}\")\n", - "else:\n", - " print(\"[LLM] Pas de mesure (endpoint non accessible)\")\n" - ] - }, - { - "cell_type": "markdown", - "id": "interp-prf1", - "metadata": { - "papermill": { - "duration": 0.005654, - "end_time": "2026-09-14T01:56:37.462360+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:37.456706+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Lecture — trois détecteurs, trois régimes de performance\n", - "\n", - "Le tableau `Precision / Recall / F1` sur la classe positive `humour_reussi` (sous-ensemble 30 instances) :\n", - "\n", - "- **Naïf** : P=0,500, R=1,000, F1=0,667 — il attrape tous les vrais positifs (R=1) mais au prix de 6 faux positifs (toute cellule `rire_sans_recadrage` est classée `humour_reussi` parce que `laugh=True`). La moitié de ses prédictions `humour_reussi` est fausse.\n", - "- **Partage** : P=1,000, R=1,000, F1=1,000 — parfait sur le sous-ensemble. La section circularité (cell[18-20]) montrera **pourquoi ce chiffre n'est pas un résultat** : les features sont dérivées du label, l'identité est constructive.\n", - "- **LLM `anthropic/claude-haiku-4.5`** (canal épinglé OpenRouter) : P=0,312, R=0,833, F1=0,455 — un régime inverse du naïf : sur 6 vrais `humour_reussi`, il en attrape 5 (R=0,833), mais en prédisant la classe positive bien trop large — 11 faux positifs pour 5 vrais positifs (P=0,312). Il ratisse large : presque tout ce qui ressemble de près à une blague est classé positif.\n", - "\n", - "La lecture honnête : le LLM **n'est pas évalué sur le même terrain** que les détecteurs à règles. Ces derniers lisent des features booléennes dérivées du label ; le LLM ne voit que le texte. Le F1=0,455 du LLM n'est donc pas « moins bon que 1,000 » — il est **incomparable** au 1,000, qui mesure une identité algébrique, pas une capacité de classification. La section circularité (cell[18-20]) formalise exactement cette réserve." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "7edaced2", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-14T01:56:37.477419Z", - "iopub.status.busy": "2026-09-14T01:56:37.476957Z", - "iopub.status.idle": "2026-09-14T01:56:37.486847Z", - "shell.execute_reply": "2026-09-14T01:56:37.484821Z" - }, - "papermill": { - "duration": 0.019533, - "end_time": "2026-09-14T01:56:37.488604+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:37.469071+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "=== Diagnostic LLM — erreurs notables ===\n", - "\n", - "Total erreurs : 19/30\n", - "\n", - " id=arg-3.2.5 truth=humour_reussi pred=rien\n", - " texte : [relation intime/vie de couple] L'amoureux des bêtes — baratineur: L'ami des chats, contexte: Le bar\n", - " raw LLM : rien\n", - "\n", - " id=arg-7.2.2 truth=rire_sans_recadrage pred=offensif_compris_non_partage\n", - " texte : [vie personnelle/voisins et amis] Le jardin empoisonné — baratineur: Le voisin envieux, contexte: Le\n", - " raw LLM : offensif_compris_non_partage\n", - "\n", - " id=arg-7.1.1 truth=rire_sans_recadrage pred=humour_reussi\n", - " texte : [vie personnelle/famille et enfance] King size — baratineur: Le parent, contexte: Un jeune vient d'o\n", - " raw LLM : humour_reussi\n", - "\n", - " id=edge-03 truth=rire_sans_recadrage pred=rien\n", - " texte : J'ai chatouillé ma cousine et elle a ri aux éclats.\n", - " raw LLM : rien\n", - "\n", - " id=arg-7.2.7 truth=rire_sans_recadrage pred=rien\n", - " texte : [vie personnelle/voisins et amis] Un ami qui vous veut du bien — baratineur: Une personne quelconque\n", - " raw LLM : rien\n", - "\n", - "[diagnostic] Accuracy brute LLM : 36.7% (11/30)\n" - ] - } - ], - "source": [ - "# -*- coding: utf-8 -*-\n", - "# Diagnostic qualitatif : 5 exemples où le LLM se trompe (ou réussit)\n", - "if instances_with_pred:\n", - " print(\"=== Diagnostic LLM — erreurs notables ===\\n\")\n", - " errors = [r for r in instances_with_pred if r[\"label\"] != r[\"llm_pred\"]]\n", - " print(f\"Total erreurs : {len(errors)}/{len(instances_with_pred)}\")\n", - " print()\n", - " for err in errors[:5]:\n", - " print(f\" id={err['id']:<10} truth={err['label']:<25} pred={err['llm_pred']}\")\n", - " print(f\" texte : {err['texte'][:100]}\")\n", - " print(f\" raw LLM : {err['llm_raw'][:80]}\")\n", - " print()\n", - "\n", - " # Taux d'accord avec vérité\n", - " n_correct = sum(1 for r in instances_with_pred if r[\"label\"] == r[\"llm_pred\"])\n", - " accuracy = n_correct / len(instances_with_pred)\n", - " print(f\"[diagnostic] Accuracy brute LLM : {accuracy:.1%} ({n_correct}/{len(instances_with_pred)})\")\n" - ] - }, - { - "cell_type": "markdown", - "id": "c6ad3354", - "metadata": { - "papermill": { - "duration": 0.007645, - "end_time": "2026-09-14T01:56:37.506431+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:37.498786+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "## Test de circularité — scénarios Argumentum tenus à l'écart (#13306)\n", - "\n", - "Le F1 = 1,000 du détecteur maison n'est pas un résultat tant qu'une circularité n'est\n", - "pas écartée : un détecteur à règles qui sature sur le corpus où ses règles ont été\n", - "écrites mesure sa proximité à la procédure d'annotation, pas sa théorie.\n", - "\n", - "Protocole (#13306) : appliquer le détecteur **sans aucune modification** aux scénarios\n", - "Argumentum **non consommés** par la construction du corpus, et publier les deux F1\n", - "côte à côte avec leur intervalle de confiance bootstrap (leçon #12936 : c'est\n", - "l'incertitude d'échantillonnage qu'il faut afficher, pas une variance inter-seeds).\n", - "\n", - "Arithmétique corrigée au passage : l'issue #13306 annonce « 167 - 120 = 47 » scénarios\n", - "non consommés — ceci concatène le total du corpus de travail (120 instances, dont 60\n", - "manuelles hors Argumentum) avec la consommation Argumentum réelle (60 scénarios\n", - "échantillonnés). Le tenu-à-l'écart vrai est 167 - 60 = **107**, identifié ci-dessous\n", - "par un prédicat reproductible avec contrôle positif de disjonction." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "682fbe54", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-14T01:56:37.522191Z", - "iopub.status.busy": "2026-09-14T01:56:37.521941Z", - "iopub.status.idle": "2026-09-14T01:56:37.531150Z", - "shell.execute_reply": "2026-09-14T01:56:37.529932Z" - }, - "papermill": { - "duration": 0.017504, - "end_time": "2026-09-14T01:56:37.532123+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:37.514619+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[circularité] Argumentum total : 167\n", - "[circularité] consommés par CORPUS_DUR (k=60, seed 42) : 60\n", - "[circularité] tenus à l'écart : 107\n", - "[disjonction] |consommés INTER tenu-à-l'écart| = 0 (attendu 0)\n", - "[disjonction] |consommés UNION tenu-à-l'écart| = 167 (attendu 167)\n", - "[disjonction] ids arg-* du CORPUS_DUR INTER tenu-à-l'écart = 0 (attendu 0)\n", - "[circularité] labels du tenu-à-l'écart : {'rien': 28, 'recadrage_sans_rire': 17, 'humour_reussi': 37, 'rire_sans_recadrage': 14, 'offensif_compris_non_partage': 11}\n" - ] - } - ], - "source": [ - "# -*- coding: utf-8 -*-\n", - "# Identification des scénarios NON consommés + contrôle POSITIF de disjonction (#13306).\n", - "# Prédicat reproductible : est consommé tout scénario de labeled_arg dont le path\n", - "# figure dans arg_sample (random.seed(42), k=60, cell[7]) ; tenu-à-l'écart = le reste.\n", - "consumed_paths = {r[\"path\"] for r in arg_sample}\n", - "heldout_arg = [r for r in labeled_arg if r[\"path\"] not in consumed_paths]\n", - "print(f\"[circularité] Argumentum total : {len(labeled_arg)}\")\n", - "print(f\"[circularité] consommés par CORPUS_DUR (k=60, seed 42) : {len(consumed_paths)}\")\n", - "print(f\"[circularité] tenus à l'écart : {len(heldout_arg)}\")\n", - "\n", - "# Contrôle positif de disjonction — montré, pas affirmé :\n", - "inter_paths = consumed_paths & {r[\"path\"] for r in heldout_arg}\n", - "union_paths = consumed_paths | {r[\"path\"] for r in heldout_arg}\n", - "corpus_arg_ids = {i[\"id\"] for i in CORPUS_DUR if i[\"id\"].startswith(\"arg-\")}\n", - "inter_ids = corpus_arg_ids & {\"arg-\" + r[\"path\"] for r in heldout_arg}\n", - "print(f\"[disjonction] |consommés INTER tenu-à-l'écart| = {len(inter_paths)} (attendu 0)\")\n", - "print(f\"[disjonction] |consommés UNION tenu-à-l'écart| = {len(union_paths)} (attendu {len(labeled_arg)})\")\n", - "print(f\"[disjonction] ids arg-* du CORPUS_DUR INTER tenu-à-l'écart = {len(inter_ids)} (attendu 0)\")\n", - "assert not inter_paths and len(union_paths) == len(labeled_arg) and not inter_ids\n", - "\n", - "# Construction des instances tenues à l'écart : IDENTIQUE à cell[7] — les features\n", - "# sont dérivées du label par la même fonction. Toute modification de cette\n", - "# construction invaliderait le test (acceptance #13306, critère 2).\n", - "def features_from_label(lab):\n", - " return {\n", - " \"laugh\": lab == \"humour_reussi\" or lab == \"rire_sans_recadrage\",\n", - " \"reframe\": lab == \"humour_reussi\" or lab == \"recadrage_sans_rire\",\n", - " \"uptake\": lab == \"humour_reussi\",\n", - " \"refus\": lab == \"offensif_compris_non_partage\",\n", - " }\n", - "heldout_instances = [{\n", - " \"id\": \"heldout-\" + r[\"path\"],\n", - " \"texte\": \"[\" + r[\"catégorie\"] + \"/\" + r[\"sous-catégorie\"] + \"] \" + r[\"titre\"],\n", - " \"features\": features_from_label(r[\"label\"]),\n", - " \"label\": r[\"label\"],\n", - " \"justification\": \"tenu à l'écart #13306 — construction identique à cell[7] (features dérivées du label)\",\n", - " \"source\": \"ArgumentumGames/Argumentum\",\n", - "} for r in heldout_arg]\n", - "print(f\"[circularité] labels du tenu-à-l'écart : {dict(Counter(x['label'] for x in heldout_instances))}\")" - ] - }, - { - "cell_type": "markdown", - "id": "interp-disjonction", - "metadata": { - "papermill": { - "duration": 0.005623, - "end_time": "2026-09-14T01:56:37.545100+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:37.539477+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Lecture — 60 consommés, 107 tenus à l'écart, disjonction prouvée\n", - "\n", - "Le contrôle de circularité #13306 repose sur un prédicat reproductible : tout scénario dont le `path` figure dans `arg_sample` (60 scénarios tirés avec `random.seed(42)` en cell[7]) est « consommé » ; les autres sont « tenus à l'écart ».\n", - "\n", - "- **60 consommés, 107 tenus à l'écart** (167 total) — l'arithmétique corrigée de l'issue #13306 (`167 - 60`, pas `167 - 120` qui concaténait corpus de travail et consommation Argumentum).\n", - "- **Disjonction prouvée par trois contrôles** : intersection des paths = 0, union = 167 (total), intersection des ids `arg-*` du `CORPUS_DUR` avec le tenu-à-l'écart = 0. L'`assert` passe — les ensembles sont mathématiquement disjoints, pas seulement « différents ».\n", - "- **Distribution du tenu-à-l'écart** : `humour_reussi` 37, `rien` 28, `recadrage_sans_rire` 17, `rire_sans_recadrage` 14, `offensif_compris_non_partage` 11 — proche de la distribution du consommé, donc le F1 sur le tenu-à-l'écart n'est pas trivialisé par une cellule vide.\n", - "\n", - "Le point critique pour la cellule suivante : les features des instances tenues à l'écart sont **construites par la même fonction** (`features_from_label`) que celles du corpus. C'est ce qui rend le F1=1,000 sur le tenu-à-l'écart **non informatif** — la circularité écartée est la plus grossière (surapprentissage des instances spécifiques), pas la structurelle (features dérivées du label)." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "92f330cc", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-14T01:56:37.554210Z", - "iopub.status.busy": "2026-09-14T01:56:37.553992Z", - "iopub.status.idle": "2026-09-14T01:56:38.114297Z", - "shell.execute_reply": "2026-09-14T01:56:38.113533Z" - }, - "papermill": { - "duration": 0.56572, - "end_time": "2026-09-14T01:56:38.114889+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:37.549169+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CORPUS_DUR (120, dont 60 manuelles) n= 120 TP= 48 FP= 0 FN= 0 P=1.000 R=1.000 F1=1.000 IC95=[1.000, 1.000]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "Argumentum consommés (60) n= 60 TP= 18 FP= 0 FN= 0 P=1.000 R=1.000 F1=1.000 IC95=[1.000, 1.000]\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Argumentum tenus à l'écart (107) n= 107 TP= 37 FP= 0 FN= 0 P=1.000 R=1.000 F1=1.000 IC95=[1.000, 1.000]\n", - "\n", - "=== Trace algébrique : label -> features (cell[7]) -> prédiction du détecteur (cell[9]) ===\n", - " humour_reussi -> détecteur : humour_reussi\n", - " rire_sans_recadrage -> détecteur : rire_sans_recadrage\n", - " recadrage_sans_rire -> détecteur : rien\n", - " offensif_compris_non_partage -> détecteur : offensif_compris_non_partage\n", - " rien -> détecteur : rien\n" - ] - } - ], - "source": [ - "# -*- coding: utf-8 -*-\n", - "# F1 côte à côte (métrique identique à cell[15]) + IC bootstrap + trace algébrique.\n", - "def bootstrap_f1_ci(instances, detector, n_draws=5000, seed=13306):\n", - " \"\"\"IC percentile 95% par bootstrap non paramétrique (rééchantillonnage des\n", - " instances avec remise). Mesure l'incertitude d'échantillonnage du F1 —\n", - " pas une variance inter-seeds (leçon #12936).\"\"\"\n", - " rng = random.Random(seed)\n", - " n = len(instances)\n", - " f1s = []\n", - " for _ in range(n_draws):\n", - " sample = [instances[rng.randrange(n)] for _ in range(n)]\n", - " f1s.append(precision_recall(sample, detector)[2])\n", - " f1s.sort()\n", - " return f1s[int(0.025 * n_draws)], f1s[int(0.975 * n_draws)]\n", - "\n", - "arg60 = [i for i in CORPUS_DUR if i[\"id\"].startswith(\"arg-\")]\n", - "for name, insts in [\n", - " (\"CORPUS_DUR (120, dont 60 manuelles)\", CORPUS_DUR),\n", - " (\"Argumentum consommés (60)\", arg60),\n", - " (\"Argumentum tenus à l'écart (107)\", heldout_instances),\n", - "]:\n", - " p, r, f1, tp, fp, fn, tn = precision_recall(insts, reframe_detector)\n", - " lo, hi = bootstrap_f1_ci(insts, reframe_detector)\n", - " print(f\"{name:<38} n={len(insts):>4} TP={tp:>3} FP={fp:>2} FN={fn:>2} \"\n", - " f\"P={p:.3f} R={r:.3f} F1={f1:.3f} IC95=[{lo:.3f}, {hi:.3f}]\")\n", - "\n", - "print()\n", - "print(\"=== Trace algébrique : label -> features (cell[7]) -> prédiction du détecteur (cell[9]) ===\")\n", - "for lab in CATEGORIES:\n", - " inst = {\"features\": features_from_label(lab)}\n", - " print(f\" {lab:<30} -> détecteur : {reframe_detector(inst)}\")" - ] - }, - { - "cell_type": "markdown", - "id": "interp-bootstrap", - "metadata": { - "papermill": { - "duration": 0.003648, - "end_time": "2026-09-14T01:56:38.122649+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:38.119001+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Lecture — F1=1,000 partout, IC dégénéré, et c'est précisément le problème\n", - "\n", - "Les lignes rendent le même verdict `P=1,000 R=1,000 F1=1,000` avec un **intervalle de confiance bootstrap `[1,000, 1,000]`** — c'est-à-dire dégénéré (largeur nulle).\n", - "\n", - "- **Sur le tenu-à-l'écart (107)** : le F1 tient, donc la circularité grossière (surapprentissage des instances spécifiques du corpus) est écartée — c'est la conclusion de #13306.\n", - "- **Mais l'IC dégénéré est la signature d'un pipeline déterministe**, pas d'une mesure confiante : un bootstrap non paramétrique sur un classifieur qui est une fonction déterministe des labels rend toujours la même valeur, donc un intervalle de largeur nulle. Ce n'est pas une forte confiance, c'est l'absence de stochasticité.\n", - "- **La trace algébrique** l'explique : `label → features_from_label → reframe_detector` est une **involution** (sauf pour `recadrage_sans_rire` qui tombe en `rien` — un cas où le détecteur est strictement plus conservateur que l'annotation). Le détecteur inverse la construction des features, donc il ne peut pas se tromper sur un Argumentum, fût-il tenu à l'écart.\n", - "\n", - "La réserve structurelle est posée en cell[20] : le F1=1,000 **ne mesure pas la théorie du partage sur le corpus Argumentum**, il mesure l'identité de construction features ↔ label. L'écart avec le LLM épinglé (haiku-4.5, F1 = 0,455) n'est pas un résultat : c'est l'écart entre un détecteur évalué sur son terrain de construction et un modèle évalué hors du sien. La voie de validation réelle est #12756 (features annotées depuis le texte, indépendamment du label)." - ] - }, - { - "cell_type": "markdown", - "id": "ff219036", - "metadata": { - "papermill": { - "duration": 0.004057, - "end_time": "2026-09-14T01:56:38.130445+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:38.126388+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Verdict : `CIRCULARITE_GROSSIERE_ECARTEE` — avec réserve structurelle majeure\n", - "\n", - "Par la règle de décision de #13306, le F1 tient sur le tenu-à-l'écart → la\n", - "circularité **la plus grossière** (surapprentissage des instances spécifiques du\n", - "corpus) est écartée. Mais la trace algébrique ci-dessus montre **pourquoi il ne\n", - "pouvait pas en être autrement** : sur les instances Argumentum, les features sont\n", - "calculées À PARTIR du label annoté (cell[7]), et le détecteur inverse cette\n", - "fonction — seul `humour_reussi` produit `reframe + uptake`, donc précision =\n", - "rappel = 1 **par construction**, sur n'importe quel échantillon Argumentum,\n", - "tenu-à-l'écart compris. L'intervalle bootstrap dégénéré `[1.000, 1.000]` est la\n", - "signature d'un pipeline déterministe, pas celle d'une mesure confiante.\n", - "\n", - "Conséquence directe : le F1 = 1,000 du banc **ne mesure pas la théorie du partage\n", - "sur le corpus Argumentum** — il mesure l'identité de construction features ↔\n", - "label. Tant que les features ne sont pas annotées indépendamment du label,\n", - "l'écart avec le LLM épinglé (haiku-4.5, F1 = 0,455) n'est pas un résultat : c'est l'écart entre un\n", - "détecteur évalué sur son terrain de construction et un modèle évalué hors du\n", - "sien.\n", - "\n", - "Suites (hors scope #13306, critère 5 — LLM non re-testé ici) :\n", - "1. **#12756** (campagne multi-annotateurs) reste la voie de validation réelle ;\n", - "2. variante bas coût : annoter les features **depuis le texte**, sans voir le\n", - " label, puis ré-appliquer ce détecteur inchangé — seule façon de donner un\n", - " contenu au chiffre." - ] - }, - { - "cell_type": "markdown", - "id": "07f174d8", - "metadata": { - "papermill": { - "duration": 0.005004, - "end_time": "2026-09-14T01:56:38.139720+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:38.134716+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "## Conclusion — placement, limites, suite\n", - "\n", - "### Bilan acceptance #12756\n", - "\n", - "| Critère | Statut | Preuve |\n", - "|---|---|---|\n", - "| ≥1 corpus réel intégré (Argumentum) | **OK** | 167 scénarios CSV + 60 échantillonnés |\n", - "| ≥100 instances annotées, négatifs inclus, équilibré | **OK** | `len(CORPUS_DUR)` cell[7] |\n", - "| ≥1 expérience ranking LLM, sorties committées | **OK** | cell[12] + cell[14] |\n", - "| Matrices confusion mises à jour | **OK** | cell[14] : naïve vs partage vs LLM |\n", - "| Placement tranché et documenté | **OK** | GT-24b (comment user 15:46Z) |\n", - "\n", - "> *Numérotation : le renommage #18001 a renuméroté ce carnet GT-24b → GT-18d et le toy model GT-24 → GT-20. La preuve de placement ci-dessus cite le numéro à la date du commentaire user.*\n", - "\n", - "### Verdict SOTA\n", - "\n", - "Le canal `anthropic/claude-haiku-4.5` via OpenRouter est invoqué, épinglé et\n", - "vérifié par écho provider (SOTA-OK). Le endpoint LAN vLLM `qwen3.6-35b-a3b`\n", - "d'origine est documenté injoignable (HTTP 000, 2026-09-13) — basculement\n", - "journalisé, pas de fallback dégradé : si l'endpoint échoue (réseau /\n", - "maintenance), le diagnostic le dit explicitement (cf cell[14], `[LLM] Pas de mesure`).\n", - "\n", - "### Limites et suite\n", - "\n", - "- **Argumentum submodule non initialisé** sur la machine (c.539 mesure). Le\n", - " fetch HTTP direct contourne ; une PR séparée pourra faire `git submodule\n", - " update --init` proprement quand l'environnement le permettra.\n", - "- **Circularité (audit #13306)** : le F1 = 1,000 du détecteur maison est une\n", - " identité de construction sur les instances Argumentum (features dérivées du\n", - " label), pas une performance — verdict `CIRCULARITE_GROSSIERE_ECARTEE` avec\n", - " réserve structurelle, cf section dédiée. Validation réelle : #12756 ou\n", - " features annotées depuis le texte.\n", - "- **Corpus annoté** = curation manuelle (avec justifications cell[7]).\n", - " Pas de corpus académique blagues publiquement annoté sur ce cycle. Si\n", - " dispo, intégrer par exemple le corpus `humour-classification` Kaggle\n", - " ou `short-jokes` dataset (post-cycle).\n", - "- **LLM ranking** limité à 30 instances pour éviter latence cumulée.\n", - " Suite : full-corpus LLM en mode async (papermill --workers 4) sur machine\n", - " GPU dédiée (po-2024 ?) pour 120+ instances en <5 min.\n", - "- **Placement** : GT-24b pour l'instant. La numérotation pourra basculer en\n", - " annexes `-b`, `-c` une fois la sous-série stabilisée (comment user 15:46Z).\n", - "\n", - "### Crédits\n", - "\n", - "- Argumentum upstream : github.com/ArgumentumGames/Argumentum (master,\n", - " `Cards/Scenarii/Argumentum Scenarii - Cards.csv`)\n", - "- Toy model livré par #12749 (PR `GameTheory-18c-Humour-Banc-Python.ipynb`)\n", - "- LLM : `qwen3.6-35b-a3b` (AWQ 4bit, vLLM local) puis `anthropic/claude-haiku-4.5` (OpenRouter, canal épinglé, écho provider capturé)\n" - ] - }, - { - "cell_type": "markdown", - "id": "gt24b-paires-intro", - "metadata": { - "papermill": { - "duration": 0.003696, - "end_time": "2026-09-14T01:56:38.147580+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:38.143884+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "## Paires minimales « unfun » — détection, appréciation et explication indépendantes (#14033)\n", - "\n", - "**Le défaut que cette section répare.** Le meilleur détecteur du banc ci-dessus est *circulaire par construction* : la cellule de corpus dérive les features (`laugh`, `reframe`, `uptake`, `refus`) **du label**, puis la règle inverse cette dérivation — d'où le F1 = 1,000 et son IC dégénéré. En outre, les négatives du corpus initial (déclarations factuelles : météo, bourse, administration) viennent d'un **autre domaine lexical** que les positives (blagues d'informaticiens) : un classifieur de surface y réussit par raccourci lexical, pas par compréhension de l'humour.\n", - "\n", - "**Le protocole (Horvitz et al., ACL 2024).** On construit des **paires minimales** : pour chaque blague humaine du corpus commité, une contrepartie « unfun » éditée à la main qui **conserve sujet, longueur et registre** et ne retire que le mécanisme (l'incongruité). Les négatifs du banc apparié ne proviennent donc **jamais d'un autre domaine**. Trois questions, mesurées **indépendamment** (Loakman et al., Findings EMNLP 2025 : détection, appréciation et explication sont des tâches distinctes qui se dégradent différemment) :\n", - "\n", - "1. **détection** — le texte porte-t-il un mécanisme humoristique ? (macro-F1, par forme) ;\n", - "2. **appréciation** — à quel degré est-il drôle ? (échelle ordinale 0–3 à la JEST ; κ quadratique pondéré + ρ de Spearman ; Toplyn & Amir, ICCC 2026, documentent que JEST est limitée aux textes conversationnels courts et aux adultes américains — réserve explicite) ;\n", - "3. **explication** — quelles incongruités, références et normes rendent le mécanisme intelligible ? (grille humaine explicite, exactitude/complétude).\n", - "\n", - "**Gel avant mesure.** Le split construction/test est gelé et haché (SHA-256) **avant toute évaluation** ; aucune règle ni aucun seuil n'est retouché après lecture du test. Le détecteur circulaire initial est **reproduit comme baseline de contrôle** — il doit rendre F1 = 1 sur ce split, ce qui démontre la vacuité de la métrique quand les features dérivent du label.\n", - "\n", - "**Canal de jugement épinglé.** Tous les appels LLM passent par OpenRouter, modèle **`anthropic/claude-haiku-4.5`** (écho de version capturé dans les sorties) — le endpoint LAN vLLM est injoignable depuis cette lane (HTTP 000 mesuré). La construction des paires est **humaine** (éditée à la main par l'auteur du corpus), pas générée par le modèle évalué.\n", - "\n", - "**Sources, chemins canoniques** (gisement partagé, jamais committées dans le dépôt) :\n", - "\n", - "- Horvitz et al., *Getting Serious about Humor* (ACL 2024) — `G:\\Mon Drive\\MyIA\\IA\\Bibliographie IA\\MachineLearning\\Computational Humor\\2024 - Horvitz et al - Getting Serious about Humor.pdf`\n", - "- Loakman, Thorne & Lin, *Comparing Apples to Oranges* (Findings EMNLP 2025) — `G:\\Mon Drive\\MyIA\\IA\\Bibliographie IA\\MachineLearning\\Computational Humor\\2025 - Loakman et al - Comparing Apples to Oranges.pdf`\n", - "- Toplyn & Amir, *JEST* (ICCC 2026) — `G:\\Mon Drive\\MyIA\\IA\\Bibliographie IA\\MachineLearning\\Computational Humor\\2026 - Toplyn and Amir - JEST.pdf`" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "gt24b-paires-data", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-14T01:56:38.156629Z", - "iopub.status.busy": "2026-09-14T01:56:38.156448Z", - "iopub.status.idle": "2026-09-14T01:56:38.174302Z", - "shell.execute_reply": "2026-09-14T01:56:38.173573Z" - }, - "papermill": { - "duration": 0.02283, - "end_time": "2026-09-14T01:56:38.174875+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:38.152045+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[paires] 30 paires, formes : {'sociale': 8, 'pun': 11, 'topical': 11}, tranche OOD code-mixé : 8\n", - "[paires] 30/30 textes humour verbatim du corpus (assert de fidélité passé)\n" - ] - } - ], - "source": [ - "# -*- coding: utf-8 -*-\n", - "# PAIRES_MINIMALES — 30 paires tirees du corpus commit (POSITIVE_JOKES, cell[10]).\n", - "# Les textes humour (4e champ) sont les textes EXACTS du corpus, accents reels\n", - "# compris. Chaque paire : (id, forme, ood, texte_humour, texte_unfun,\n", - "# note_annotateur_humour, note_annotateur_unfun,\n", - "# mecanisme_attendu, justification_edit)\n", - "# - forme : pun (jeu de mots) / sociale (blague sociale intemporelle) /\n", - "# topical (reference culturelle ou metier d'epoque)\n", - "# - ood : tranche hors distribution = texte code-mixe FR/EN\n", - "# - mecanisme_attendu : grille explicite [(element, [mots-cles FR/EN]), ...] ;\n", - "# le 1er element = le NOYAU (l'incongruite essentielle). Le scoring (cell\n", - "# explication) normalise casse + accents puis cherche les mots-cles.\n", - "# - notes 0-3 : annotation humaine unique, gelees a la construction AVANT toute\n", - "# evaluation (limite annotateur unique : cf tache appreciation).\n", - "# - justification_edit : ce que l'edition retire et ce qu'elle conserve.\n", - "# AUCUN champ ci-dessous ne derive d'une sortie de modele.\n", - "\n", - "PAIRES_MINIMALES = [\n", - " (\"paire-p01\", \"sociale\", False,\n", - " \"Un informaticien rentre dans un bar et dit : 'je voudrais une bière,\",\n", - " \"Un informaticien rentre dans un bar et dit : 'je voudrais une bière bien fraîche.'\",\n", - " 2, 0,\n", - " [(\"refrain inachevé 'je voudrais'\", [\"refrain\", \"repetition\", \"x10\", \"dix fois\", \"inacheve\"]),\n", - " (\"structure d'accumulation absurde\", [\"accumul\", \"absurd\", \"en boucle\", \"incantation\"])],\n", - " \"Achever la phrase platement ('bien fraîche') supprime le refrain suspendu ; sujet, citation et longueur conservés.\"),\n", - " (\"paire-p02\", \"pun\", False,\n", - " \"Pourquoi les développeurs confondent Halloween et Noël ? Parce que Oct 31 == Dec 25.\",\n", - " \"Pourquoi les développeurs évoquent Halloween et Noël ? Parce que Oct 31 vient avant Dec 25.\",\n", - " 3, 0,\n", - " [(\"lecture octale de 31\", [\"octal\", \"base 8\", \"base huit\"]),\n", - " (\"équivalence numérique inattendue\", [\"equival\", \"31\", \"25\", \"egale\", \"meme nombre\"]),\n", - " (\"double lecture de la notation\", [\"decimal\", \"notation\", \"double lecture\", \"deux sens\", \"ambigu\"])],\n", - " \"Remplacer l'égalité incongrue (==) par l'ordre calendaire littéral 'vient avant' ; notations Oct/Dec et fêtes conservées.\"),\n", - " (\"paire-p03\", \"pun\", False,\n", - " \"Il y a 10 types de personnes au monde : ceux qui comprennent le binaire et ceux qui ne le comprennent pas.\",\n", - " \"Il y a à peu près 10 types de personnes au monde : ceux qui comprennent le binaire et ceux qui ne le comprennent pas.\",\n", - " 3, 0,\n", - " [(\"le '10' lu en base 2\", [\"10\", \"binaire\", \"base 2\", \"zero un\", \"deux en base dix\"]),\n", - " (\"méta-récursivité de l'énoncé\", [\"meta\", \"lui-meme\", \"recursif\", \"auto\"]),\n", - " (\"double lecture du nombre\", [\"double lecture\", \"deux sens\", \"ambigu\", \"dix\"])],\n", - " \"L'approximation 'à peu près' force la lecture décimale triviale du '10' ; la phrase reste identique ailleurs.\"),\n", - " (\"paire-p04\", \"topical\", True,\n", - " \"Un SQL entre dans un bar, voit deux tables et leur dit : 'SELECT * FROM...'\",\n", - " \"Un SQL entre dans un bar, voit deux tables et demande laquelle est libre.\",\n", - " 2, 0,\n", - " [(\"double sens de 'tables'\", [\"table\", \"tables\", \"base de donnees\"]),\n", - " (\"requête SELECT\", [\"select\", \"requete\", \"from\", \"interroge\"]),\n", - " (\"personnification du langage\", [\"personnifi\", \"sql parle\", \"langage qui parle\"])],\n", - " \"Retirer la punchline 'SELECT * FROM...' au profit d'une question littérale de bar ; la personne (SQL) et le décor (tables) restent.\"),\n", - " (\"paire-p05\", \"sociale\", False,\n", - " \"Combien d'ingénieurs faut-il pour changer une ampoule ? Aucun, c'est un problème hardware.\",\n", - " \"Combien d'ingénieurs faut-il pour changer une ampoule ? Un seul, muni d'un escabeau.\",\n", - " 2, 0,\n", - " [(\"inversion de responsabilité\", [\"responsabilite\", \"rejet\", \"renvoi\", \"pas au\"]),\n", - " (\"clivage logiciel/matériel\", [\"hardware\", \"materiel\", \"software\", \"logiciel\"]),\n", - " (\"réponse 'aucun' déflationnaire\", [\"aucun\", \"zero\", \"pas besoin d'ingenieur\"])],\n", - " \"La réponse déflationnaire 'aucun + hardware' devient une réponse littérale ('un seul, escabeau') ; format question-réponse conservé.\"),\n", - " (\"paire-p06\", \"pun\", False,\n", - " \"Je suis tombé amoureuse d'une fonction quadratique. Mais elle avait deux racines.\",\n", - " \"Je suis tombé amoureuse d'une fonction quadratique. Mais elle avait deux zéros.\",\n", - " 2, 0,\n", - " [(\"double sens de 'racines'\", [\"racine\", \"root\", \"double sens\"]),\n", - " (\"métaphore amoureuse mathématique\", [\"amoureus\", \"relation\", \"coeur\", \"sentiment\"]),\n", - " (\"propriété de la quadratique\", [\"quadratique\", \"deux solutions\", \"deux racines\", \"polynome\"])],\n", - " \"'racines' (double lecture sentimentale/math) remplacé par 'zéros' (terme technique neutre) ; la confession amoureuse est intacte.\"),\n", - " (\"paire-p07\", \"topical\", True,\n", - " \"Un null et un undefined entrent dans un bar. Le barman dit 'On accepte pas les non-définis ici'.\",\n", - " \"Un null et un undefined entrent dans un bar. Le barman leur demande ce qu'ils veulent boire.\",\n", - " 2, 0,\n", - " [(\"référence JavaScript\", [\"null\", \"undefined\", \"javascript\", \"js\", \"typage\"]),\n", - " (\"double sens de 'non-définis'\", [\"non defini\", \"non-defini\", \"double sens\", \"exclu\"]),\n", - " (\"mécanisme de blague de bar\", [\"bar\", \"barman\", \"refus\", \"entrent\"])],\n", - " \"La réplique excluante ('on accepte pas les non-définis') devient un service ordinaire ; le couple null/undefined demeure.\"),\n", - " (\"paire-p08\", \"topical\", True,\n", - " \"Je voulais te raconter une blague sur UDP... mais je sais si elle arrive.\",\n", - " \"Je voulais te raconter une blague sur UDP... mais je ne sais pas si elle arrive.\",\n", - " 3, 0,\n", - " [(\"UDP sans garantie de livraison\", [\"udp\", \"best-effort\", \"best effort\", \"sans garantie\", \"livraison\", \"paquet\"]),\n", - " (\"négation manquante = paquet perdu\", [\"negation\", \"ne...pas manquant\", \"paquet perdu\", \"omis\"]),\n", - " (\"méta : la phrase incarne le protocole\", [\"meta\", \"la phrase elle-meme\", \"incarne\"])],\n", - " \"Restaurer la négation grammaticale ('ne...pas') désamorce la chute : la phrase redevient littérale.\"),\n", - " (\"paire-p09\", \"pun\", False,\n", - " \"Le père Noël a-t-il déjà eu un problème de pile ? Non, il a toujours des piles neuves.\",\n", - " \"Le père Noël a-t-il déjà eu un problème de pile ? Non, ses lampes fonctionnent toujours bien.\",\n", - " 1, 0,\n", - " [(\"double sens de 'pile(s)'\", [\"pile\", \"piles\", \"double sens\"]),\n", - " (\"réponse par l'objet électrique\", [\"batterie\", \"electrique\", \"neuve\"]),\n", - " (\"cadre Noël\", [\"noel\", \"pere noel\"])],\n", - " \"L'écho 'piles neuves' (reprise du mot de la question) remplacé par une réponse détournée ('lampes') ; le cadre questions-réponses reste.\"),\n", - " (\"paire-p10\", \"pun\", False,\n", - " \"Pourquoi le café est-il si bon au travail ? Parce qu'il est fraîchement moulu par l'échéance.\",\n", - " \"Pourquoi le café est-il si bon au travail ? Parce qu'il est fraîchement moulu chaque matin.\",\n", - " 2, 0,\n", - " [(\"métaphore échéance/mouture\", [\"echeance\", \"deadline\", \"moulu\", \"mouture\"]),\n", - " (\"double sens de 'fraîchement moulu'\", [\"fraichement\", \"double sens\", \"moulu par\"]),\n", - " (\"registre bureau\", [\"travail\", \"bureau\", \"cafe\"])],\n", - " \"'par l'échéance' (agent incongru) devient 'chaque matin' (circonstance banale) ; question et registre identiques.\"),\n", - " (\"paire-p11\", \"pun\", True,\n", - " \"J'ai essayé d'écrire une blague sur les coroutines, mais je n'arrive pas à la yield.\",\n", - " \"J'ai essayé d'écrire une blague sur les coroutines, mais je n'arrive pas à la terminer.\",\n", - " 2, 0,\n", - " [(\"yield : mot-clé et céder/livrer\", [\"yield\", \"ceder\", \"mot-cle\"]),\n", - " (\"référence coroutines\", [\"coroutine\", \"async\", \"generateur\"]),\n", - " (\"double lecture du verbe\", [\"double lecture\", \"deux sens\", \"je n'arrive pas\"])],\n", - " \"Le mot-clé 'yield' (double lecture) remplacé par le verbe banal 'terminer'.\"),\n", - " (\"paire-p12\", \"topical\", True,\n", - " \"Docker, Kubernetes, Prometheus, Grafana. On m'a dit que c'était simple, alors je stack.\",\n", - " \"Docker, Kubernetes, Prometheus, Grafana. On m'a dit que c'était simple, alors je m'y mets.\",\n", - " 2, 0,\n", - " [(\"double sens de 'stack'\", [\"stack\", \"empiler\", \"pile\", \"stacker\"]),\n", - " (\"accumulation d'outils DevOps\", [\"docker\", \"kubernetes\", \"prometheus\", \"grafana\", \"outils\"]),\n", - " (\"ironie de la promesse de simplicité\", [\"simple\", \"ironie\", \"promesse\"])],\n", - " \"'je stack' (anglicisme-jeu) remplacé par 'je m'y mets' (locution neutre) ; l'énumération d'outils reste.\"),\n", - " (\"paire-p13\", \"pun\", False,\n", - " \"Mon compilateur et moi on a une relation stable : il compile, je pleure.\",\n", - " \"Mon compilateur et moi on a une relation stable : il compile, je vérifie.\",\n", - " 2, 0,\n", - " [(\"double sens de 'stable'\", [\"stable\", \"build\", \"relation\"]),\n", - " (\"inversion émotionnelle (pleure alors que ça compile)\", [\"pleure\", \"inversion\", \"absurd\", \"alors que\"]),\n", - " (\"personnification du compilateur\", [\"compilateur\", \"relation\"])],\n", - " \"'je pleure' (réaction inversée, incongrue) devient 'je vérifie' (réaction attendue) ; 'relation stable' conservé.\"),\n", - " (\"paire-p14\", \"sociale\", False,\n", - " \"J'ai un ami palindrome. On ne peut pas se différencier.\",\n", - " \"J'ai un ami palindrome. C'est un mot comme un autre.\",\n", - " 2, 0,\n", - " [(\"propriété du palindrome appliquée à l'amitié\", [\"palindrome\", \"deux sens\", \"miroir\", \"endroit envers\"]),\n", - " (\"absurdité de la catégorie (ami palindrome)\", [\"ami\", \"absurd\", \"personne\", \"mot\"]),\n", - " (\"jeu sur la différenciation\", [\"differencier\", \"distinguer\", \"differents\"])],\n", - " \"La seconde phrase cesse d'appliquer la propriété du palindrome à la relation ; elle ramène le palindrome à un fait lexical.\"),\n", - " (\"paire-p15\", \"topical\", False,\n", - " \"Les regex sont comme des licornes : tout le monde en parle, personne les a vues.\",\n", - " \"Les regex sont comme des licornes : on en voit surtout dans les livres.\",\n", - " 2, 1,\n", - " [(\"simile absurde (les regex se voient partout)\", [\"regex\", \"licorne\", \"personne ne\", \"jamais vue\"]),\n", - " (\"véracité littérale fausse = incongruité\", [\"inversion\", \"faux\", \"exactement le contraire\"]),\n", - " (\"mythe du métier\", [\"mythe\", \"legende\", \"metier\", \"rumeur\"])],\n", - " \"La chute inversée ('personne les a vues') devient une vérité littérale sur les licornes ; le cadre de comparaison reste.\"),\n", - " (\"paire-p16\", \"sociale\", False,\n", - " \"Un physicien, un biologiste et un chimiste voient 2 bâtiments. L'un entre, l'autre sort. 'Tiens, ils ont échangé.'\",\n", - " \"Un physicien, un biologiste et un chimiste voient 2 bâtiments. L'un entre, l'autre sort. 'Tiens, ils se croisent.'\",\n", - " 1, 0,\n", - " [(\"trois corps de métier (format classique)\", [\"physicien\", \"biologiste\", \"chimiste\", \"trois\"]),\n", - " (\"non-séquence finale ('ils ont échangé')\", [\"echange\", \"echangent\", \"non-sequence\", \"absurd\"]),\n", - " (\"banalisation d'une observation triviale\", [\"observ\", \"tiens\", \"remarque\"])],\n", - " \"'échangé' (verbe impossible pour des bâtiments) devient 'se croisent' (description littérale des faits).\"),\n", - " (\"paire-p17\", \"topical\", True,\n", - " \"Que dit un informaticien quand il s'ennuie ? 'printf(mot)\\n'\",\n", - " \"Que dit un informaticien quand il s'ennuie ? 'Il regarde par la fenêtre.'\",\n", - " 1, 0,\n", - " [(\"printf = dire/afficher\", [\"printf\", \"affiche\", \"print\", \"impression\"]),\n", - " (\"réponse en code à une question de parole\", [\"code\", \"reponse en code\", \"dire\"]),\n", - " (\"minimalisme absurde\", [\"minimal\", \"absurd\", \"laconique\"])],\n", - " \"La réponse-code ('printf') remplacée par une réponse en parole ordinaire ; la question reste.\"),\n", - " (\"paire-p18\", \"topical\", False,\n", - " \"Si Dieu existe, il est Objective-C : tout est message.\",\n", - " \"Si Dieu existe, il est Objective-C : les conventions sont strictes.\",\n", - " 2, 0,\n", - " [(\"parallèle théologie/paradigme\", [\"dieu\", \"theolog\", \"religion\", \"objective-c\"]),\n", - " (\"double sens de 'message' (passage de messages/révélation)\", [\"message\", \"passage de message\", \"revelation\", \"double sens\"]),\n", - " (\"absorption : tout est X\", [\"tout est\", \"toute chose\", \"omni\"])],\n", - " \"La proposition totalisante 'tout est message' (double lecture) remplacée par une remarque technique plate sur les conventions.\"),\n", - " (\"paire-p19\", \"pun\", False,\n", - " \"Le temps est une illusion. Le décalage horaire, doublement.\",\n", - " \"Le temps est une illusion. Le décalage horaire aussi.\",\n", - " 2, 0,\n", - " [(\"référence Hitchhiker's Guide\", [\"hitchhiker\", \"guide\", \"adam\", \"douglas\"]),\n", - " (\"jeu sur l'adverbe 'doublement'\", [\"doublement\", \"double\", \"doubly\"]),\n", - " (\"amplification en cascade\", [\"cascade\", \"encore plus\", \"amplifie\"])],\n", - " \"L'adverbe inattendu 'doublement' (chute) devient l'extension plate 'aussi' ; la première phrase demeure.\"),\n", - " (\"paire-p20\", \"topical\", False,\n", - " \"Un photon entre dans un bar et commande une bière. Le barman dit 'Pour vous, c'est gratuit, on vous voit pas partir'.\",\n", - " \"Un photon entre dans un bar et commande une bière. Le barman lui sert la bière et lui souhaite la bonne soirée.\",\n", - " 3, 0,\n", - " [(\"physique du photon (vitesse c, temps propre)\", [\"photon\", \"lumiere\", \"vitesse\", \"temps propre\", \"relativite\"]),\n", - " (\"incongruité : le barman applique la physique\", [\"barman\", \"gratuit\", \"voit pas partir\", \"incongrui\"]),\n", - " (\"blague de bar détournée\", [\"bar\", \"biere\", \"commande\"])],\n", - " \"La réplique physique du barman ('on vous voit pas partir') devient un service et une formule de politesse ordinaires.\"),\n", - " (\"paire-p21\", \"pun\", False,\n", - " \"J'ai une blague sur les matrices, mais c'est hors de portée du public.\",\n", - " \"J'ai une blague sur les matrices, mais elle est trop longue à raconter.\",\n", - " 1, 0,\n", - " [(\"double sens de 'portée' (range math/accessible)\", [\"portee\", \"range\", \"matrice\", \"math\"]),\n", - " (\"méta-humour : retenir la blague\", [\"meta\", \"retient\", \"ne la raconte pas\", \"promesse\"]),\n", - " (\"registre mathématique\", [\"matrice\", \"matrices\", \"algebre\"])],\n", - " \"'hors de portée' (jeu mathématique) remplacé par le motif banal 'trop longue à raconter'.\"),\n", - " (\"paire-p22\", \"topical\", False,\n", - " \"Un chat roux dans une salle de serveurs est dangereux : il pourrait activer l'incident majeur.\",\n", - " \"Un chat roux dans une salle de serveurs est dangereux : il pourrait débrancher un câble.\",\n", - " 1, 0,\n", - " [(\"mème du chat roux = chaos\", [\"chat roux\", \"meme\", \"internet\", \"chaos\"]),\n", - " (\"vocabulaire NOC/production\", [\"incident\", \"noc\", \"production\", \"severite\"]),\n", - " (\"exagération absurde du risque\", [\"exagere\", \"absurd\", \"risque\"])],\n", - " \"L'aboutissant spectaculaire ('activer l'incident majeur') devient un risque physique banal et plausible ('débrancher un câble').\"),\n", - " (\"paire-p23\", \"sociale\", False,\n", - " \"Pourquoi les plongeurs plongent-ils toujours en arrière et jamais en avant ? Parce que sinon ils tomberaient dans le bateau.\",\n", - " \"Pourquoi les plongeurs plongent-ils toujours en arrière et jamais en avant ? Parce que c'est plus simple pour repartir du bateau.\",\n", - " 3, 0,\n", - " [(\"logique absurde de la chute\", [\"tomberaient\", \"bateau\", \"logique absurde\", \"inversion\"]),\n", - " (\"format devinette\", [\"pourquoi\", \"devinette\", \"question\"]),\n", - " (\"géométrie inversée (avant = bateau)\", [\"en avant\", \"arriere\", \"geometrie\", \"sens\"])],\n", - " \"La chute géométriquement absurde ('tomberaient dans le bateau') devient une raison mécanique plausible ('repartir du bateau').\"),\n", - " (\"paire-p24\", \"topical\", False,\n", - " \"Le HTML n'est pas un langage de programmation. Et le plus dur, c'est de le dire à mon patron.\",\n", - " \"Le HTML n'est pas un langage de programmation. Et le plus dur, c'est de le documenter proprement.\",\n", - " 2, 0,\n", - " [(\"débat tech canonique\", [\"html\", \"langage de programmation\", \"debat\"]),\n", - " (\"tension hiérarchique (patron)\", [\"patron\", \"hierarch\", \"travail\", \"dire\"]),\n", - " (\"déplacement : difficulté sociale d'un fait technique\", [\"le plus dur\", \"difficile de dire\", \"social\"])],\n", - " \"La difficulté sociale ('dire à mon patron') devient une difficulté technique ('documenter proprement') ; l'affirmation technique reste.\"),\n", - " (\"paire-p25\", \"topical\", False,\n", - " \"Si vous pensez que personne ne s'intéresse à votre vie, regardez vos logs Git.\",\n", - " \"Si vous pensez que personne ne s'intéresse à votre vie, regardez vos notifications.\",\n", - " 2, 0,\n", - " [(\"métaphore de surveillance\", [\"surveill\", \"trace\", \"espion\", \"interesse\"]),\n", - " (\"logs Git comme trace de vie\", [\"log\", \"git\", \"historique\", \"commits\"]),\n", - " (\"réconfort ironique\", [\"personne ne\", \"ironie\", \"regarde\"])],\n", - " \"'logs Git' (trace technique détournée en preuve d'intérêt) remplacé par 'notifications' (objet littéralement fait pour ça).\"),\n", - " (\"paire-p26\", \"sociale\", False,\n", - " \"Comment debug-on un avion ? On retire les composants un par un jusqu'à ce qu'il ne plante plus.\",\n", - " \"Comment répare-t-on un avion ? On remplace les composants défectueux selon la procédure certifiée.\",\n", - " 3, 0,\n", - " [(\"transfert de la procédure de debug\", [\"debug\", \"bisection\", \"un par un\", \"procedure\"]),\n", - " (\"double sens de 'plante' (crash)\", [\"plante\", \"crash\", \"double sens\", \"tomber en panne\"]),\n", - " (\"danger absurde (avion de prod)\", [\"avion\", \"danger\", \"absurd\"])],\n", - " \"'debug-on' devient 'répare-t-on', la bisection incongrue devient la maintenance certifiée ; le sujet (avion, composants) reste.\"),\n", - " (\"paire-p27\", \"pun\", True,\n", - " \"Mieux vaut avoir un git pull que deux tu l'auras.\",\n", - " \"Mieux vaut faire un git pull régulier que de tout merger d'un coup.\",\n", - " 3, 0,\n", - " [(\"paronomase du dicton\", [\"dicton\", \"proverbe\", \"mieux vaut\", \"tu l'auras\"]),\n", - " (\"git pull substitué au mot attendu\", [\"git pull\", \"tirer\", \"fusion\"]),\n", - " (\"double lecture de l'avoir\", [\"avoir\", \"double sens\", \"posseder\"])],\n", - " \"La paronomase ('un git pull' / 'un qui tu l'auras') défusionnée en conseil technique plat.\"),\n", - " (\"paire-p28\", \"sociale\", False,\n", - " \"Mon chat a appris Python. Maintenant il chasse les exceptions au lieu des souris.\",\n", - " \"Mon chat a appris Python. Maintenant il marche sur le clavier au lieu de chasser les souris.\",\n", - " 2, 0,\n", - " [(\"chasse redirect vers les exceptions\", [\"chasse\", \"exception\", \"proie\", \"souris\"]),\n", - " (\"anthropomorphisme technique\", [\"chat\", \"python\", \"appris\", \"anthropomorph\"]),\n", - " (\"métabole 'au lieu de'\", [\"au lieu\", \"remplace\", \"desormais\"])],\n", - " \"L'appariement absurde (chasser des exceptions) devient un comportement félin réel (marcher sur le clavier) ; la structure 'au lieu des souris' reste.\"),\n", - " (\"paire-p29\", \"sociale\", False,\n", - " \"Les submodules Git, c'est comme les voisins : mieux vaut ne pas les déranger.\",\n", - " \"Les submodules Git, c'est une fonctionnalité à manier avec précaution.\",\n", - " 2, 0,\n", - " [(\"métaphore sociale (voisins)\", [\"voisin\", \"voisins\", \"deranger\", \"social\"]),\n", - " (\"folklore des submodules\", [\"submodule\", \"sous-module\", \"git\"]),\n", - " (\"conseil de sagesse détourné\", [\"mieux vaut\", \"sagesse\", \"conseil\"])],\n", - " \"La comparaison sociale ('comme les voisins') supprimée ; il reste une phrase technique prudente.\"),\n", - " (\"paire-p30\", \"pun\", True,\n", - " \"Il était une fois un UTF-8 qui ne savait pas où était la fin. Il était perdu dans un BOM.\",\n", - " \"Il était une fois un UTF-8 qui ne savait pas où était la fin. Il a trouvé la réponse dans la norme.\",\n", - " 2, 0,\n", - " [(\"conte détourné + jargon d'encodage\", [\"utf-8\", \"encodage\", \"bom\", \"conte\", \"il etait une fois\"]),\n", - " (\"BOM : le délimiteur qui égare\", [\"bom\", \"marqueur\", \"octet\", \"debut\"]),\n", - " (\"double lecture de 'la fin' (fin de chaîne/fin du conte)\", [\"fin\", \"chaine\", \"terminaison\", \"double lecture\"])],\n", - " \"La chute technique ('perdu dans un BOM') remplacée par un dénouement plat ('la réponse dans la norme') ; le cadre du conte reste.\"),\n", - "]\n", - "\n", - "FORMES = [\"pun\", \"sociale\", \"topical\"]\n", - "assert len(PAIRES_MINIMALES) == 30\n", - "assert all(p[1] in FORMES for p in PAIRES_MINIMALES)\n", - "n_par_forme = Counter(p[1] for p in PAIRES_MINIMALES)\n", - "n_ood = sum(1 for p in PAIRES_MINIMALES if p[2])\n", - "print(f\"[paires] {len(PAIRES_MINIMALES)} paires, formes : {dict(n_par_forme)}, tranche OOD code-mixé : {n_ood}\")\n", - "# Fidelite au corpus, verifiee AU RUN contre le corpus execute (cell[10]) :\n", - "# chaque texte humour doit etre le texte EXACT de POSITIVE_JOKES.\n", - "_corpus_par_id = {inst[\"id\"]: inst[\"texte\"] for inst in positive_instances}\n", - "for p in PAIRES_MINIMALES:\n", - " ref = _corpus_par_id[\"joke-\" + p[0].replace(\"paire-\", \"\")]\n", - " assert p[3] == ref, f\"{p[0]} : texte humour != corpus\\n paire : {p[3]!r}\\n corpus: {ref!r}\"\n", - "print(\"[paires] 30/30 textes humour verbatim du corpus (assert de fidélité passé)\")" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "gt24b-paires-gel", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-14T01:56:38.183528Z", - "iopub.status.busy": "2026-09-14T01:56:38.183282Z", - "iopub.status.idle": "2026-09-14T01:56:38.199986Z", - "shell.execute_reply": "2026-09-14T01:56:38.199354Z" - }, - "papermill": { - "duration": 0.021989, - "end_time": "2026-09-14T01:56:38.200639+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:38.178650+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "=== Contrôles de construction ===\n", - "id forme mots H/U ratio lev mots sim chars ood\n", - "paire-p01 sociale 13/15 1.15 3 0.89 False\n", - "paire-p02 pun 15/16 1.07 3 0.87 False\n", - "paire-p03 pun 22/25 1.14 3 0.95 False\n", - "paire-p04 topical 16/14 1.14 6 0.70 True\n", - "paire-p05 sociale 13/13 1.00 5 0.78 False\n", - "paire-p06 pun 12/12 1.00 1 0.95 False\n", - "paire-p07 topical 18/17 1.06 7 0.65 True\n", - "paire-p08 topical 14/16 1.14 2 0.95 True\n", - "paire-p09 pun 18/17 1.06 6 0.77 False\n", - "paire-p10 pun 16/16 1.00 2 0.90 False\n", - "paire-p11 pun 15/15 1.00 1 0.95 True\n", - "paire-p12 topical 13/14 1.08 2 0.94 True\n", - "paire-p13 pun 14/14 1.00 1 0.94 False\n", - "paire-p14 sociale 10/10 1.00 6 0.62 False\n", - "paire-p15 topical 16/14 1.14 8 0.69 False\n", - "paire-p16 sociale 18/18 1.00 2 0.93 False\n", - "paire-p17 topical 10/13 1.30 5 0.77 True\n", - "paire-p18 topical 10/11 1.10 4 0.73 False\n", - "paire-p19 pun 9/9 1.00 2 0.88 False\n", - "paire-p20 topical 22/22 1.00 10 0.64 False\n", - "paire-p21 pun 13/13 1.00 6 0.71 False\n", - "paire-p22 topical 16/16 1.00 3 0.84 False\n", - "paire-p23 sociale 20/21 1.05 6 0.81 False\n", - "paire-p24 topical 19/17 1.12 4 0.86 False\n", - "paire-p25 topical 14/13 1.08 2 0.89 False\n", - "paire-p26 sociale 18/14 1.29 11 0.60 False\n", - "paire-p27 pun 10/13 1.30 7 0.69 True\n", - "paire-p28 sociale 14/17 1.21 7 0.79 False\n", - "paire-p29 sociale 14/10 1.40 10 0.56 False\n", - "paire-p30 pun 20/22 1.10 6 0.83 True\n", - "\n", - "ratio longueur max = 1.40 (cible <= 1.35, consigne 'autant que possible')\n", - "similarité car. min/max = 0.56/0.95 (des paires proches = voulu)\n", - "\n", - "=== Seuils de verdict (gels avant mesure) ===\n", - "{\n", - " \"detection\": {\n", - " \"generalise\": 0.8,\n", - " \"par_forme_min\": 0.7,\n", - " \"ne_generalise_pas\": 0.6\n", - " },\n", - " \"explication\": {\n", - " \"noyau_generalise\": 0.8,\n", - " \"completude_generalise\": 0.6,\n", - " \"noyau_ne_generalise_pas\": 0.5\n", - " },\n", - " \"appreciation\": \"INCONCLUSIVE_PAR_CONSTRUCTION (annotateur unique — règle de l'issue #14033)\"\n", - "}\n", - "\n", - "=== GEL ===\n", - "corpus gt24b-paires-v1 sha256 = 116425d0222c5cc1...\n", - "construction (16 paires) : ['paire-p04', 'paire-p05', 'paire-p06', 'paire-p08', 'paire-p09', 'paire-p11', 'paire-p13', 'paire-p14', 'paire-p15', 'paire-p16', 'paire-p17', 'paire-p19', 'paire-p20', 'paire-p21', 'paire-p23', 'paire-p24']\n", - "test (14 paires) : ['paire-p01', 'paire-p02', 'paire-p03', 'paire-p07', 'paire-p10', 'paire-p12', 'paire-p18', 'paire-p22', 'paire-p25', 'paire-p26', 'paire-p27', 'paire-p28', 'paire-p29', 'paire-p30']\n", - "split gelé sha256 = 2aab8cbb7e9982e5...\n", - "test : 14 paires = 28 textes ; construction : 16 paires\n" - ] - } - ], - "source": [ - "# -*- coding: utf-8 -*-\n", - "# Controles de construction + GEL du split AVANT toute evaluation.\n", - "# Rien dans ce qui suit (seuils, split) ne sera retouche apres lecture du test.\n", - "import hashlib\n", - "import difflib\n", - "\n", - "def lev_mots(a, b):\n", - " \"\"\"Distance de Levenshtein mot a mot (DP classique, sans dependance).\"\"\"\n", - " wa, wb = a.split(), b.split()\n", - " prev = list(range(len(wb) + 1))\n", - " for i, xa in enumerate(wa, 1):\n", - " cur = [i] + [0] * len(wb)\n", - " for j, yb in enumerate(wb, 1):\n", - " cur[j] = min(prev[j] + 1, cur[j - 1] + 1,\n", - " prev[j - 1] + (xa != yb))\n", - " prev = cur\n", - " return prev[-1]\n", - "\n", - "print(\"=== Contrôles de construction ===\")\n", - "print(f\"{'id':<12}{'forme':<9}{'mots H/U':<10}{'ratio':<7}{'lev mots':<9}{'sim chars':<10}ood\")\n", - "ratios, sims = [], []\n", - "for (pid, forme, ood, th, tu, _, _, _, _) in PAIRES_MINIMALES:\n", - " nh, nu = len(th.split()), len(tu.split())\n", - " ratio = max(nh, nu) / max(1, min(nh, nu))\n", - " lv = lev_mots(th, tu)\n", - " sim = difflib.SequenceMatcher(None, th, tu).ratio()\n", - " ratios.append(ratio)\n", - " sims.append(sim)\n", - " print(f\"{pid:<12}{forme:<9}{nh:>3}/{nu:<4}{ratio:<7.2f}{lv:<9}{sim:<10.2f}{ood}\")\n", - "print(f\"\\nratio longueur max = {max(ratios):.2f} (cible <= 1.35, consigne 'autant que possible')\")\n", - "print(f\"similarité car. min/max = {min(sims):.2f}/{max(sims):.2f} (des paires proches = voulu)\")\n", - "\n", - "# SEUILS DE VERDICT — declares et geles AVANT l'evaluation.\n", - "SEUILS = {\n", - " \"detection\": {\"generalise\": 0.80, \"par_forme_min\": 0.70, \"ne_generalise_pas\": 0.60},\n", - " \"explication\": {\"noyau_generalise\": 0.80, \"completude_generalise\": 0.60,\n", - " \"noyau_ne_generalise_pas\": 0.50},\n", - " \"appreciation\": \"INCONCLUSIVE_PAR_CONSTRUCTION (annotateur unique — règle de l'issue #14033)\",\n", - "}\n", - "print(\"\\n=== Seuils de verdict (gels avant mesure) ===\")\n", - "print(json.dumps(SEUILS, indent=2, ensure_ascii=False))\n", - "\n", - "# SPLIT GEL — stratifie par forme, moitie construction / moitie test\n", - "# (les effectifs impairs vont au CONSTRUCTION : pun 6/5, sociale 4/4, topical 6/5).\n", - "rng = random.Random(42)\n", - "construction_ids, test_ids = [], []\n", - "for f in FORMES:\n", - " ids = sorted(p[0] for p in PAIRES_MINIMALES if p[1] == f)\n", - " rng.shuffle(ids)\n", - " k = (len(ids) + 1) // 2\n", - " construction_ids.extend(ids[:k])\n", - " test_ids.extend(ids[k:])\n", - "construction_ids.sort()\n", - "test_ids.sort()\n", - "\n", - "CORPUS_VERSION = \"gt24b-paires-v1\"\n", - "corpus_blob = json.dumps(\n", - " [[p[0], p[1], p[2], p[3], p[4], p[5], p[6]] for p in PAIRES_MINIMALES],\n", - " ensure_ascii=False, sort_keys=True).encode(\"utf-8\")\n", - "CORPUS_SHA = hashlib.sha256(corpus_blob).hexdigest()\n", - "SPLIT_SHA = hashlib.sha256(json.dumps(\n", - " {\"version\": CORPUS_VERSION, \"construction\": construction_ids, \"test\": test_ids},\n", - " sort_keys=True).encode(\"utf-8\")).hexdigest()\n", - "print(\"\\n=== GEL ===\")\n", - "print(f\"corpus {CORPUS_VERSION} sha256 = {CORPUS_SHA[:16]}...\")\n", - "print(f\"construction ({len(construction_ids)} paires) : {construction_ids}\")\n", - "print(f\"test ({len(test_ids)} paires) : {test_ids}\")\n", - "print(f\"split gelé sha256 = {SPLIT_SHA[:16]}...\")\n", - "TEST_PAIRS = [p for p in PAIRES_MINIMALES if p[0] in set(test_ids)]\n", - "TEST_TEXTES = [(p[0], 1, p[3], p[5], p[1], p[2]) for p in TEST_PAIRS] + \\\n", - " [(p[0], 0, p[4], p[6], p[1], p[2]) for p in TEST_PAIRS]\n", - "CONSTR_PAIRS = [p for p in PAIRES_MINIMALES if p[0] in set(construction_ids)]\n", - "print(f\"test : {len(TEST_PAIRS)} paires = {len(TEST_TEXTES)} textes ; construction : {len(CONSTR_PAIRS)} paires\")" - ] - }, - { - "cell_type": "markdown", - "id": "gt24b-paires-lecture1", - "metadata": { - "papermill": { - "duration": 0.003704, - "end_time": "2026-09-14T01:56:38.208501+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:38.204797+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Lecture — 30 paires appariées, 3 formes, tranche OOD, split gelé avant mesure\n", - "\n", - "- **11 pun / 8 sociale / 11 topical** — les trois formes exigées ; la pun et la référence culturelle dominent (le corpus source est un corpus de blagues d'informaticiens : biais déclaré, pas caché).\n", - "- **Tranche OOD = 8 paires code-mixées FR/EN** (`SELECT`, `null`/`undefined`, `UDP`, `yield`, `stack`, `printf`, `git pull`, `UTF-8`/`BOM`) — le code-mixing est exactement le régime que Horvitz et al. identifient comme difficile ; il est isolé pour être rapporté séparément.\n", - "- **Les éditions unfun conservent le décor** : ratios de longueur et similarités caractères mesurés ci-dessus ; la distance mot-à-mot reste faible — l'édit retire le mécanisme, pas le sujet.\n", - "- **Le split (16 construction / 14 test, stratifié par forme) et les seuils de verdict sont hachés avant la moindre évaluation** — aucune retouche possible après lecture du test." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "gt24b-paires-baselines", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-14T01:56:38.218149Z", - "iopub.status.busy": "2026-09-14T01:56:38.217849Z", - "iopub.status.idle": "2026-09-14T01:56:55.288877Z", - "shell.execute_reply": "2026-09-14T01:56:55.288319Z" - }, - "papermill": { - "duration": 17.076964, - "end_time": "2026-09-14T01:56:55.289273+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:38.212309+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[contrôle circulaire] macro-F1 = 1.000 — attendu 1.000 par construction :\n", - " les features dérivent du label, la règle inverse la dérivation. La métrique\n", - " est VIDE ; c'est la démonstration du défaut que les paires minimales corrigent.\n", - "\n", - "[baseline lexicale] macro-F1 test = 0.535 (TF-IDF 1-2 grammes +\n", - " régression logistique, entraînée sur les 16 paires de construction uniquement).\n", - " Sur le banc initial (positives tech vs négatives administratives) ce type de\n", - " classifieur réussissait par raccourci lexical ; ici les négatifs partagent le\n", - " lexique des positifs — le raccourci est fermé, la performance mesure la vraie tâche.\n" - ] - } - ], - "source": [ - "# -*- coding: utf-8 -*-\n", - "# DEUX BASELINES sur EXACTEMENT le meme split test (aucune ne voit le test avant).\n", - "from sklearn.feature_extraction.text import TfidfVectorizer\n", - "from sklearn.linear_model import LogisticRegression\n", - "from sklearn.pipeline import make_pipeline\n", - "from sklearn.metrics import f1_score\n", - "\n", - "# --- Baseline 1 (controle) : le detecteur circulaire d'origine, reproduit ---\n", - "# On reconstruit les features DEPUIS LE LABEL, exactement comme la cellule de\n", - "# corpus initiale le faisait (cell[10]) : c'est le defaut que ce banc exhibe.\n", - "def features_circulaires(est_humour):\n", - " return {\"laugh\": est_humour, \"reframe\": est_humour,\n", - " \"uptake\": est_humour, \"refus\": False}\n", - "\n", - "circ_pred = []\n", - "for (pid, cote, texte, note, forme, ood) in TEST_TEXTES:\n", - " f = features_circulaires(cote == 1)\n", - " pred = reframe_detector({\"features\": f})\n", - " circ_pred.append(1 if pred == \"humour_reussi\" else 0)\n", - "circ_y = [t[1] for t in TEST_TEXTES]\n", - "f1_circ = f1_score(circ_y, circ_pred, average=\"macro\")\n", - "print(f\"[contrôle circulaire] macro-F1 = {f1_circ:.3f} — attendu 1.000 par construction :\")\n", - "print(\" les features dérivent du label, la règle inverse la dérivation. La métrique\")\n", - "print(\" est VIDE ; c'est la démonstration du défaut que les paires minimales corrigent.\")\n", - "\n", - "# --- Baseline 2 : classifieur lexical de surface, entraîné sur CONSTRUCTION seulement ---\n", - "constr_X = [p[3] for p in CONSTR_PAIRS] + [p[4] for p in CONSTR_PAIRS]\n", - "constr_y = [1] * len(CONSTR_PAIRS) + [0] * len(CONSTR_PAIRS)\n", - "lex = make_pipeline(TfidfVectorizer(ngram_range=(1, 2), lowercase=True),\n", - " LogisticRegression(max_iter=1000))\n", - "lex.fit(constr_X, constr_y)\n", - "test_X = [t[2] for t in TEST_TEXTES]\n", - "lex_pred = list(lex.predict(test_X))\n", - "f1_lex = f1_score(circ_y, lex_pred, average=\"macro\")\n", - "print(f\"\\n[baseline lexicale] macro-F1 test = {f1_lex:.3f} (TF-IDF 1-2 grammes +\")\n", - "print(\" régression logistique, entraînée sur les 16 paires de construction uniquement).\")\n", - "print(\" Sur le banc initial (positives tech vs négatives administratives) ce type de\")\n", - "print(\" classifieur réussissait par raccourci lexical ; ici les négatifs partagent le\")\n", - "print(\" lexique des positifs — le raccourci est fermé, la performance mesure la vraie tâche.\")" - ] - }, - { - "cell_type": "markdown", - "id": "gt24b-paires-lecture2", - "metadata": { - "papermill": { - "duration": 0.003294, - "end_time": "2026-09-14T01:56:55.296223+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:55.292929+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Lecture — la circularité rendue visible, le raccourci lexical fermé\n", - "\n", - "La baseline circulaire rend **F1 = 1,000 par construction** : ce n'est pas une performance, c'est une tautologie mesurée. La baseline lexicale, elle, perd son raccourci : les contreparties « unfun » partagent le vocabulaire, le sujet et le registre des blagues — un n-gramme ne peut plus séparer « Oct 31 == Dec 25 » de « Oct 31 vient avant Dec 25 » sans comprendre lequel porte l'incongruité. Ces deux nombres encadrent l'évaluation LLM qui suit : **tout score LLM ≤ baseline lexicale ne démontre rien ; tout score ≈ 1,000 doit être regardé avec le même soupçon que la baseline circulaire.**" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "gt24b-paires-canal", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-14T01:56:55.304525Z", - "iopub.status.busy": "2026-09-14T01:56:55.304210Z", - "iopub.status.idle": "2026-09-14T01:56:55.980229Z", - "shell.execute_reply": "2026-09-14T01:56:55.978760Z" - }, - "papermill": { - "duration": 0.681688, - "end_time": "2026-09-14T01:56:55.981471+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:55.299783+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[canal] épinglé = anthropic/claude-haiku-4.5\n", - "[canal] écho provider = anthropic/claude-haiku-4.5 (résolution de version servie)\n", - "[canal] latence = 667 ms ; usage = {'prompt_tokens': 14, 'completion_tokens': 4, 'total_tokens': 18, 'cost': 0, 'is_byok': True, 'prompt_tokens_details': {'cached_tokens': 0, 'cache_write_tokens': 0, 'audio_tokens': 0, 'video_tokens': 0}, 'cost_details': {'upstream_inference_cost': 3.4e-05, 'upstream_inference_prompt_cost': 1.4e-05, 'upstream_inference_completions_cost': 2e-05}, 'completion_tokens_details': {'reasoning_tokens': 0, 'image_tokens': 0, 'audio_tokens': 0}}\n" - ] - } - ], - "source": [ - "# -*- coding: utf-8 -*-\n", - "# Canal de jugement epingle : OpenRouter, modele ET version fixes (dispatch #14033).\n", - "def or_call(prompt, max_tokens=200, timeout=90):\n", - " \"\"\"Appel OpenRouter. Retourne (contenu, echo_modele, latence_ms, usage).\"\"\"\n", - " body = json.dumps({\n", - " \"model\": LLM_MODEL,\n", - " \"messages\": [{\"role\": \"user\", \"content\": prompt}],\n", - " \"max_tokens\": max_tokens,\n", - " \"temperature\": 0.0,\n", - " }).encode(\"utf-8\")\n", - " req = urllib.request.Request(\n", - " f\"{OPENAI_COMPAT_URL}/chat/completions\",\n", - " data=body,\n", - " headers={\n", - " \"Content-Type\": \"application/json\",\n", - " \"Authorization\": f\"Bearer {OPENAI_API_KEY}\",\n", - " \"HTTP-Referer\": \"https://github.com/jsboige/CoursIA\",\n", - " \"X-Title\": \"CoursIA-GT24b-banc-humour-14033\",\n", - " },\n", - " )\n", - " t0 = time.time()\n", - " with urllib.request.urlopen(req, timeout=timeout) as r:\n", - " resp = json.loads(r.read())\n", - " dt = int((time.time() - t0) * 1000)\n", - " content = resp[\"choices\"][0][\"message\"][\"content\"].strip()\n", - " return content, resp.get(\"model\", \"?\"), dt, resp.get(\"usage\", {})\n", - "\n", - "_ping, _echo, _dt, _usage = or_call(\"Réponds uniquement : OK\")\n", - "print(f\"[canal] épinglé = {LLM_MODEL}\")\n", - "print(f\"[canal] écho provider = {_echo} (résolution de version servie)\")\n", - "print(f\"[canal] latence = {_dt} ms ; usage = {_usage}\")" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "id": "gt24b-paires-detection", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-14T01:56:55.997628Z", - "iopub.status.busy": "2026-09-14T01:56:55.997357Z", - "iopub.status.idle": "2026-09-14T01:57:15.301083Z", - "shell.execute_reply": "2026-09-14T01:57:15.300221Z" - }, - "papermill": { - "duration": 19.31274, - "end_time": "2026-09-14T01:57:15.302057+00:00", - "exception": false, - "start_time": "2026-09-14T01:56:55.989317+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[détection] 28 appels, 28 réponses OUI/NON parsées\n", - "\n", - "=== DÉTECTION — macro-F1 (split test gelé) ===\n", - "global : 0.509\n", - "forme pun (10 txt) : 0.333\n", - "forme sociale ( 8 txt) : 0.750\n", - "forme topical (10 txt) : 0.333\n", - "tranche OOD code-mixé ( 8 txt) : 0.333\n", - "tranche FR pur (20 txt) : 0.560\n", - "\n", - "erreurs (12) :\n", - " paire-p25 côté=0 préd=1 forme=topical ood=False brut='OUI'\n", - " paire-p12 côté=0 préd=1 forme=topical ood=True brut='OUI'\n", - " paire-p30 côté=0 préd=1 forme=pun ood=True brut='OUI'\n", - " paire-p27 côté=0 préd=1 forme=pun ood=True brut='OUI'\n", - " paire-p28 côté=0 préd=1 forme=sociale ood=False brut='OUI'\n", - " paire-p02 côté=0 préd=1 forme=pun ood=False brut='OUI'\n", - " paire-p22 côté=0 préd=1 forme=topical ood=False brut='OUI'\n", - " paire-p01 côté=1 préd=0 forme=sociale ood=False brut='NON'\n", - " paire-p03 côté=0 préd=1 forme=pun ood=False brut='OUI'\n", - " paire-p10 côté=0 préd=1 forme=pun ood=False brut='OUI'\n", - " paire-p07 côté=0 préd=1 forme=topical ood=True brut='OUI'\n", - " paire-p18 côté=0 préd=1 forme=topical ood=False brut='OUI'\n" - ] - } - ], - "source": [ - "# -*- coding: utf-8 -*-\n", - "# TACHE 1 — DETECTION. Binaire : le texte porte-t-il un mecanisme humoristique ?\n", - "# Les deux cotes de chaque paire test, ordre mélangé (anti-biais de position).\n", - "import unicodedata\n", - "\n", - "def normaliser(s):\n", - " s = unicodedata.normalize(\"NFD\", s.lower())\n", - " return \"\".join(c for c in s if not unicodedata.combining(c))\n", - "\n", - "PROMPT_DETECTION = (\n", - " \"Tu es un détecteur d'humour. On te donne un texte court. Indique s'il contient \"\n", - " \"un mécanisme humoristique volontaire (jeu de mots, incongruité, absurdité, chute). \"\n", - " \"Réponds UNIQUEMENT par OUI ou NON.\\n\\nTexte : {texte}\\n\\nRéponse :\")\n", - "\n", - "rng_det = random.Random(7)\n", - "items_det = list(TEST_TEXTES)\n", - "rng_det.shuffle(items_det)\n", - "det_resultats = []\n", - "for (pid, cote, texte, note, forme, ood) in items_det:\n", - " rep, echo, dt, _ = or_call(PROMPT_DETECTION.format(texte=texte), max_tokens=8)\n", - " norm = normaliser(rep)\n", - " pred = 1 if \"oui\" in norm else (0 if \"non\" in norm else -1)\n", - " det_resultats.append({\"pid\": pid, \"cote\": cote, \"pred\": pred, \"forme\": forme,\n", - " \"ood\": ood, \"brut\": rep[:40], \"ms\": dt})\n", - "n_parse = sum(1 for r in det_resultats if r[\"pred\"] >= 0)\n", - "print(f\"[détection] {len(det_resultats)} appels, {n_parse} réponses OUI/NON parsées\")\n", - "\n", - "def macro_f1(rs):\n", - " y = [r[\"cote\"] for r in rs]\n", - " p = [r[\"pred\"] for r in rs]\n", - " if -1 in p:\n", - " p = [x if x >= 0 else 0 for x in p] # non-parsé = NON\n", - " return f1_score(y, p, average=\"macro\")\n", - "\n", - "f1_det = macro_f1(det_resultats)\n", - "print(f\"\\n=== DÉTECTION — macro-F1 (split test gelé) ===\")\n", - "print(f\"global : {f1_det:.3f}\")\n", - "for f in FORMES:\n", - " rs = [r for r in det_resultats if r[\"forme\"] == f]\n", - " print(f\"forme {f:<9} ({len(rs):>2} txt) : {macro_f1(rs):.3f}\")\n", - "rs_ood_det = [r for r in det_resultats if r[\"ood\"]]\n", - "rs_fr_det = [r for r in det_resultats if not r[\"ood\"]]\n", - "print(f\"tranche OOD code-mixé ({len(rs_ood_det):>2} txt) : {macro_f1(rs_ood_det):.3f}\")\n", - "print(f\"tranche FR pur ({len(rs_fr_det):>2} txt) : {macro_f1(rs_fr_det):.3f}\")\n", - "erreurs = [(r[\"pid\"], r[\"cote\"], r[\"pred\"], r[\"forme\"], r[\"ood\"], r[\"brut\"])\n", - " for r in det_resultats if r[\"pred\"] != r[\"cote\"]]\n", - "print(f\"\\nerreurs ({len(erreurs)}) :\")\n", - "for e in erreurs:\n", - " print(f\" {e[0]} côté={e[1]} préd={e[2]} forme={e[3]} ood={e[4]} brut={e[5]!r}\")" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "gt24b-paires-appreciation", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-14T01:57:15.311511Z", - "iopub.status.busy": "2026-09-14T01:57:15.311349Z", - "iopub.status.idle": "2026-09-14T01:57:35.502991Z", - "shell.execute_reply": "2026-09-14T01:57:35.501282Z" - }, - "papermill": { - "duration": 20.197125, - "end_time": "2026-09-14T01:57:35.504390+00:00", - "exception": false, - "start_time": "2026-09-14T01:57:15.307265+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[appréciation] 28/28 notes 0-3 parsées\n", - "\n", - "=== APPRÉCIATION — accord LLM vs annotateur humain unique ===\n", - "kappa quadratique pondéré = 0.355\n", - "Spearman rho = 0.493 (p = 0.0076)\n", - "forme pun : kappa_q = 0.238 (n=10)\n", - "forme sociale : kappa_q = 0.564 (n=8)\n", - "forme topical : kappa_q = 0.333 (n=10)\n", - "\n", - "distribution annotateur : {0: 14, 3: 4, 2: 9, 1: 1}\n", - "distribution LLM : {1: 15, 2: 12, 0: 1}\n", - "\n", - "VERDICT APPRÉCIATION = INCONCLUSIVE_PAR_CONSTRUCTION : un seul annotateur\n", - "humain (l'auteur du corpus) — la règle de l'issue #14033 impose ce verdict ;\n", - "l'accord rapporté ci-dessus est une donnée, pas une généralisation. L'échelle\n", - "JEST (Toplyn & Amir 2026) est elle-même limitée aux textes conversationnels\n", - "courts et aux adultes américains : réserve doublée, non levée ici.\n" - ] - } - ], - "source": [ - "# -*- coding: utf-8 -*-\n", - "# TACHE 2 — APPRECIATION. Ordinal 0-3 (échelle à la JEST, réserves documentées).\n", - "from sklearn.metrics import cohen_kappa_score\n", - "from scipy.stats import spearmanr\n", - "\n", - "PROMPT_APPRECIATION = (\n", - " \"Tu es un évaluateur d'humour. Note à quel point ce texte est drôle pour un \"\n", - " \"public adulte francophone, sur l'échelle ordinale :\\n\"\n", - " \"0 = pas drôle du tout\\n1 = à peine drôle\\n2 = moyennement drôle\\n3 = très drôle\\n\"\n", - " \"Réponds UNIQUEMENT par le chiffre (0, 1, 2 ou 3).\\n\\nTexte : {texte}\\n\\nNote :\")\n", - "\n", - "rng_app = random.Random(11)\n", - "items_app = list(TEST_TEXTES)\n", - "rng_app.shuffle(items_app)\n", - "app_resultats = []\n", - "for (pid, cote, texte, note, forme, ood) in items_app:\n", - " rep, echo, dt, _ = or_call(PROMPT_APPRECIATION.format(texte=texte), max_tokens=4)\n", - " chiffres = [int(c) for c in rep if c in \"0123\"]\n", - " pred = chiffres[0] if chiffres else None\n", - " app_resultats.append({\"pid\": pid, \"cote\": cote, \"annotateur\": note,\n", - " \"llm\": pred, \"forme\": forme, \"ood\": ood})\n", - "valides = [r for r in app_resultats if r[\"llm\"] is not None]\n", - "print(f\"[appréciation] {len(valides)}/{len(app_resultats)} notes 0-3 parsées\")\n", - "\n", - "y_a = [r[\"annotateur\"] for r in valides]\n", - "y_l = [r[\"llm\"] for r in valides]\n", - "qwk = cohen_kappa_score(y_a, y_l, labels=[0, 1, 2, 3], weights=\"quadratic\")\n", - "rho, pval = spearmanr(y_a, y_l)\n", - "print(f\"\\n=== APPRÉCIATION — accord LLM vs annotateur humain unique ===\")\n", - "print(f\"kappa quadratique pondéré = {qwk:.3f}\")\n", - "print(f\"Spearman rho = {rho:.3f} (p = {pval:.4f})\")\n", - "for f in FORMES:\n", - " rs = [r for r in valides if r[\"forme\"] == f]\n", - " if len(rs) >= 3:\n", - " k = cohen_kappa_score([r[\"annotateur\"] for r in rs], [r[\"llm\"] for r in rs],\n", - " labels=[0, 1, 2, 3], weights=\"quadratic\")\n", - " print(f\"forme {f:<9} : kappa_q = {k:.3f} (n={len(rs)})\")\n", - "print(f\"\\ndistribution annotateur : {dict(Counter(y_a))}\")\n", - "print(f\"distribution LLM : {dict(Counter(y_l))}\")\n", - "print(\"\\nVERDICT APPRÉCIATION = INCONCLUSIVE_PAR_CONSTRUCTION : un seul annotateur\")\n", - "print(\"humain (l'auteur du corpus) — la règle de l'issue #14033 impose ce verdict ;\")\n", - "print(\"l'accord rapporté ci-dessus est une donnée, pas une généralisation. L'échelle\")\n", - "print(\"JEST (Toplyn & Amir 2026) est elle-même limitée aux textes conversationnels\")\n", - "print(\"courts et aux adultes américains : réserve doublée, non levée ici.\")" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "gt24b-paires-explication", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-14T01:57:35.524661Z", - "iopub.status.busy": "2026-09-14T01:57:35.524310Z", - "iopub.status.idle": "2026-09-14T01:58:07.468347Z", - "shell.execute_reply": "2026-09-14T01:58:07.466632Z" - }, - "papermill": { - "duration": 31.960825, - "end_time": "2026-09-14T01:58:07.475369+00:00", - "exception": false, - "start_time": "2026-09-14T01:57:35.514544+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[explication] 14 blagues du split test expliquées\n", - "\n", - "=== EXPLICATION — grille humaine explicite ===\n", - "exactitude (élément NOYAU nommé) = 0.857\n", - "complétude (moyenne des couvertures) = 0.762\n", - "forme pun : noyau 1.000 complétude 0.800 (n=5)\n", - "forme sociale : noyau 0.750 complétude 0.583 (n=4)\n", - "forme topical : noyau 0.800 complétude 0.867 (n=5)\n", - "tranche OOD : noyau 1.000 complétude 0.917 (n=4)\n", - "\n", - "exemples (2 premiers) :\n", - " paire-p22 [noyau=True couv=1.00] Le texte joue sur une homophonie entre \"incident majeur\" (problème informatique grave) et \"incident majeur\" prononcé comme \"in-chat-dent majeur\" (jeu de mots avec \"chat\"). L'incong\n", - " paire-p27 [noyau=True couv=1.00] Ce texte joue sur l'incongruité entre un proverbe français classique (\"Mieux vaut avoir un tiens que deux tu l'auras\") et le jargon informatique en remplaçant \"un tiens\" par \"un gi\n", - "\n", - "réserve de méthode : la grille est un appariement de mots-clés (normalisés),\n", - "pas une lecture sémantique — elle sous-compte les paraphrases correctes et\n", - "sur-compte les mentions de passage. Règle déclarée avant mesure, appliquée\n", - "mécaniquement : falsifiable, jamais retouchée après lecture du test.\n" - ] - } - ], - "source": [ - "# -*- coding: utf-8 -*-\n", - "# TACHE 3 — EXPLICATION. Grille humaine explicite : exactitude (noyau) + complétude.\n", - "PROMPT_EXPLICATION = (\n", - " \"Explique en 1 à 3 phrases le mécanisme humoristique de ce texte : quelle \"\n", - " \"incongruité, quelle(s) référence(s), quelle norme il joue. Si le texte ne \"\n", - " \"présente pas de mécanisme humoristique clair, écris uniquement : \"\n", - " \"PAS_DE_MECANISME\\n\\nTexte : {texte}\\n\\nExplication :\")\n", - "\n", - "def score_grille(explication, mecanisme):\n", - " \"\"\"Grille explicite : normalise (casse+accents), cherche les mots-clés.\n", - " Rend (noyau_trouvé, n_éléments_trouvés, n_éléments).\"\"\"\n", - " norm = normaliser(explication)\n", - " trouves = 0\n", - " noyau = False\n", - " for i, (element, mots) in enumerate(mecanisme):\n", - " hit = any(normaliser(m) in norm for m in mots)\n", - " trouves += hit\n", - " if i == 0 and hit:\n", - " noyau = True\n", - " return noyau, trouves, len(mecanisme)\n", - "\n", - "rng_exp = random.Random(23)\n", - "items_expl = sorted(TEST_PAIRS, key=lambda p: p[0])\n", - "rng_exp.shuffle(items_expl)\n", - "expl_resultats = []\n", - "for p in items_expl:\n", - " pid, forme, ood, th, tu, nh, nu, meca, jedit = p\n", - " rep, echo, dt, _ = or_call(PROMPT_EXPLICATION.format(texte=th), max_tokens=250)\n", - " noyau, nt, ntot = score_grille(rep, meca)\n", - " expl_resultats.append({\"pid\": pid, \"forme\": forme, \"ood\": ood,\n", - " \"noyau\": noyau, \"couverture\": nt / ntot,\n", - " \"pas_de_mecanisme\": \"PAS_DE_MECANISME\" in rep.upper(),\n", - " \"texte\": rep})\n", - "print(f\"[explication] {len(expl_resultats)} blagues du split test expliquées\")\n", - "\n", - "acc_noyau = sum(r[\"noyau\"] for r in expl_resultats) / len(expl_resultats)\n", - "completude = sum(r[\"couverture\"] for r in expl_resultats) / len(expl_resultats)\n", - "print(f\"\\n=== EXPLICATION — grille humaine explicite ===\")\n", - "print(f\"exactitude (élément NOYAU nommé) = {acc_noyau:.3f}\")\n", - "print(f\"complétude (moyenne des couvertures) = {completude:.3f}\")\n", - "for f in FORMES:\n", - " rs = [r for r in expl_resultats if r[\"forme\"] == f]\n", - " if rs:\n", - " print(f\"forme {f:<9} : noyau {sum(r['noyau'] for r in rs)/len(rs):.3f} \"\n", - " f\"complétude {sum(r['couverture'] for r in rs)/len(rs):.3f} (n={len(rs)})\")\n", - "rs_ood_expl = [r for r in expl_resultats if r[\"ood\"]]\n", - "if rs_ood_expl:\n", - " print(f\"tranche OOD : noyau {sum(r['noyau'] for r in rs_ood_expl)/len(rs_ood_expl):.3f} \"\n", - " f\"complétude {sum(r['couverture'] for r in rs_ood_expl)/len(rs_ood_expl):.3f} (n={len(rs_ood_expl)})\")\n", - "print(\"\\nexemples (2 premiers) :\")\n", - "for r in expl_resultats[:2]:\n", - " print(f\" {r['pid']} [noyau={r['noyau']} couv={r['couverture']:.2f}] {r['texte'][:180]}\")\n", - "print(\"\\nréserve de méthode : la grille est un appariement de mots-clés (normalisés),\")\n", - "print(\"pas une lecture sémantique — elle sous-compte les paraphrases correctes et\")\n", - "print(\"sur-compte les mentions de passage. Règle déclarée avant mesure, appliquée\")\n", - "print(\"mécaniquement : falsifiable, jamais retouchée après lecture du test.\")" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "gt24b-paires-verdicts", - "metadata": { - "execution": { - "iopub.execute_input": "2026-09-14T01:58:07.493070Z", - "iopub.status.busy": "2026-09-14T01:58:07.492679Z", - "iopub.status.idle": "2026-09-14T01:58:07.637051Z", - "shell.execute_reply": "2026-09-14T01:58:07.636552Z" - }, - "papermill": { - "duration": 0.15373, - "end_time": "2026-09-14T01:58:07.637510+00:00", - "exception": false, - "start_time": "2026-09-14T01:58:07.483780+00:00", - "status": "completed" - }, - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[dédup] similarité max construction<->test = 0.55 ('paire-p04', 'paire-p07')\n", - "[dédup] doublons exacts intra-corpus : 0\n", - "\n", - "[provenance] 30 textes humores + 30 contreparties unfun : contenu propre\n", - " écrit pour ce dépôt (lignée #12785, POSITIVE_JOKES cell[10]) ; les éditions\n", - " unfun sont inédites, créées pour #14033. Aucune donnée Reddit/Kaggle (les\n", - " verdicts REFERENCE_ONLY de l'issue restent en vigueur). Droits établis.\n", - "[contenu] aucune tranche offensive dans les 30 paires ; la catégorie\n", - " offensif_compris_non_partage du banc initial reste dans sa tranche séparée,\n", - " jamais assimilée à du non-humour.\n", - "[version] gt24b-paires-v1 sha256=116425d0222c5cc1... split sha256=2aab8cbb7e9982e5...\n", - "[contamination] dépôt public sur GitHub : tout modèle entraîné sur le web a pu\n", - " voir les textes HUMORES ; les contreparties unfun sont inédites et font écran.\n", - "\n", - "=== VERDICTS FERMES (règle #14033 : jamais 'promising') ===\n", - "DETECTION : NE_GENERALISE_PAS (global 0.509, formes {'pun': 0.3333333333333333, 'sociale': 0.75, 'topical': 0.3333333333333333}, OOD 0.333)\n", - "APPRECIATION : INCONCLUSIVE_PAR_CONSTRUCTION (annotateur unique, kappa_q = 0.355)\n", - "EXPLICATION : GENERALISE (noyau 0.857, complétude 0.762)\n", - "résiduel explicite : baselines sur 28 textes de test / 14 explications ;\n", - "corpus mono-culture (blagues d'informaticiens FR, auteur = unique annotateur)\n" - ] - } - ], - "source": [ - "# -*- coding: utf-8 -*-\n", - "# CONTROLES D'HONNETETE + VERDICTS FERMES (seuils gelés en amont).\n", - "import hashlib as _hl\n", - "\n", - "# Near-duplicate construction <-> test (hors paire elle-même : la ressemblance\n", - "# intra-paire est le DESSEIN du banc ; on vérifie qu'aucune paire de construction\n", - "# ne pré-crée une paire de test par quasi-doublon).\n", - "max_ratio, argmax = 0.0, None\n", - "for pc in CONSTR_PAIRS:\n", - " for pt in TEST_PAIRS:\n", - " for tc in (pc[3], pc[4]):\n", - " for tt in (pt[3], pt[4]):\n", - " r = difflib.SequenceMatcher(None, tc, tt).ratio()\n", - " if r > max_ratio:\n", - " max_ratio, argmax = r, (pc[0], pt[0])\n", - "print(f\"[dédup] similarité max construction<->test = {max_ratio:.2f} {argmax}\")\n", - "hashes = [_hl.sha256((p[3] + p[4]).encode(\"utf-8\")).hexdigest() for p in PAIRES_MINIMALES]\n", - "print(f\"[dédup] doublons exacts intra-corpus : {len(hashes) - len(set(hashes))}\")\n", - "\n", - "print(\"\\n[provenance] 30 textes humores + 30 contreparties unfun : contenu propre\")\n", - "print(\" écrit pour ce dépôt (lignée #12785, POSITIVE_JOKES cell[10]) ; les éditions\")\n", - "print(\" unfun sont inédites, créées pour #14033. Aucune donnée Reddit/Kaggle (les\")\n", - "print(\" verdicts REFERENCE_ONLY de l'issue restent en vigueur). Droits établis.\")\n", - "print(\"[contenu] aucune tranche offensive dans les 30 paires ; la catégorie\")\n", - "print(\" offensif_compris_non_partage du banc initial reste dans sa tranche séparée,\")\n", - "print(\" jamais assimilée à du non-humour.\")\n", - "print(f\"[version] {CORPUS_VERSION} sha256={CORPUS_SHA[:16]}... split sha256={SPLIT_SHA[:16]}...\")\n", - "print(\"[contamination] dépôt public sur GitHub : tout modèle entraîné sur le web a pu\")\n", - "print(\" voir les textes HUMORES ; les contreparties unfun sont inédites et font écran.\")\n", - "\n", - "print(\"\\n=== VERDICTS FERMES (règle #14033 : jamais 'promising') ===\")\n", - "s = SEUILS[\"detection\"]\n", - "f1_par_forme = {f: macro_f1([r for r in det_resultats if r[\"forme\"] == f]) for f in FORMES}\n", - "f1_ood = macro_f1(rs_ood_det)\n", - "if (f1_det >= s[\"generalise\"]\n", - " and all(v >= s[\"par_forme_min\"] for v in f1_par_forme.values())\n", - " and f1_ood >= s[\"par_forme_min\"]):\n", - " v_det = \"GENERALISE\"\n", - "elif f1_det < s[\"ne_generalise_pas\"]:\n", - " v_det = \"NE_GENERALISE_PAS\"\n", - "else:\n", - " v_det = \"INCONCLUSIVE\"\n", - "print(f\"DETECTION : {v_det} (global {f1_det:.3f}, formes {f1_par_forme}, OOD {f1_ood:.3f})\")\n", - "print(f\"APPRECIATION : INCONCLUSIVE_PAR_CONSTRUCTION (annotateur unique, kappa_q = {qwk:.3f})\")\n", - "se = SEUILS[\"explication\"]\n", - "if acc_noyau >= se[\"noyau_generalise\"] and completude >= se[\"completude_generalise\"]:\n", - " v_exp = \"GENERALISE\"\n", - "elif acc_noyau < se[\"noyau_ne_generalise_pas\"]:\n", - " v_exp = \"NE_GENERALISE_PAS\"\n", - "else:\n", - " v_exp = \"INCONCLUSIVE\"\n", - "print(f\"EXPLICATION : {v_exp} (noyau {acc_noyau:.3f}, complétude {completude:.3f})\")\n", - "print(f\"résiduel explicite : baselines sur 28 textes de test / 14 explications ;\")\n", - "print(f\"corpus mono-culture (blagues d'informaticiens FR, auteur = unique annotateur)\")" - ] - }, - { - "cell_type": "markdown", - "id": "gt24b-paires-conclusion", - "metadata": { - "papermill": { - "duration": 0.003594, - "end_time": "2026-09-14T01:58:07.644411+00:00", - "exception": false, - "start_time": "2026-09-14T01:58:07.640817+00:00", - "status": "completed" - }, - "tags": [] - }, - "source": [ - "### Un banc falsifiable, trois verdicts séparés\n", - "\n", - "Le détecteur du banc initial ne démontrait rien : ses features dérivaient du label (F1 = 1,000 tautologique, reproduit ci-dessus comme **contrôle**). Sur des **paires minimales** dont les négatifs partagent lexique, sujet et registre des positifs, la baseline lexicale perd son raccourci et le score LLM redevient une **vraie mesure** — séparée en trois questions indépendantes :\n", - "\n", - "1. **détection** — macro-F1 global, par forme (pun / sociale / topical) et par tranche (code-mixé / FR pur), avec les erreurs listées une à une ;\n", - "2. **appréciation** — κ quadratique pondéré et ρ de Spearman contre l'annotateur humain unique, verdict **INCONCLUSIVE par construction** (règle de l'issue : un seul annotateur ne généralise pas une échelle de goût) ;\n", - "3. **explication** — grille humaine explicite (élément noyau + éléments secondaires), exactitude et complétude rapportées séparément, réserve de méthode déclarée (appariement de mots-clés, pas lecture sémantique).\n", - "\n", - "Les contrôles d'honnêteté (quasi-doublons construction↔test, hachage du corpus et du split gelé, provenance et droits, tranche offensive isolée, contamination déclarée) sont mesurés, pas affirmés. Les verdicts fermes — `GENERALISE` / `NE_GENERALISE_PAS` / `INCONCLUSIVE` — sont calculés par les seuils gelés **avant** mesure ; « promising » n'existe pas ici." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.13.15" - }, - "papermill": { - "default_parameters": {}, - "duration": 117.746526, - "end_time": "2026-09-14T01:58:07.990522+00:00", - "environment_variables": {}, - "exception": null, - "input_path": "MyIA.AI.Notebooks/GameTheory/GameTheory-18d-Humour-Banc-Dur-Python.ipynb", - "output_path": "GameTheory-18d-Humour-Banc-Dur-Python.ipynb", - "parameters": {}, - "start_time": "2026-09-14T01:56:10.243996+00:00", - "version": "2.6.0" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/MyIA.AI.Notebooks/GameTheory/README.md b/MyIA.AI.Notebooks/GameTheory/README.md index db8e3e63ad..e7d17c507e 100644 --- a/MyIA.AI.Notebooks/GameTheory/README.md +++ b/MyIA.AI.Notebooks/GameTheory/README.md @@ -359,8 +359,7 @@ Les notebooks numérotés de 18 à 25 ne prolongent pas le parcours principal. C | 22 | [Ensembles limites](GameTheory-06i-Ensembles-Limites-Poincare-Bendixson-Python.ipynb) | Poincaré-Bendixson en dimension 2 : point fixe, orbite périodique ou cycle hétérocline, classés mécaniquement, et l'échec du théorème au-delà du plan | Python | Recherche | | 23 | [Affectation de Kuhn-Munkres](GameTheory-16f-Munkres-Assignment-Python.ipynb) | L'affectation optimale en arithmétique entière exacte, certifiée par dualité LP, et le pont vers le cœur de Shapley-Shubik | Python | Licence | | 23b | [Affectation en Lean](GameTheory-16f-Lean-Assignment-Lean.ipynb) | Dualité et optimalité de Kuhn-Munkres exécutées depuis le lake `assignment_lean` | Lean | Recherche | -| 24 | [Banc humour](GameTheory-18c-Humour-Banc-Python.ipynb) | Banc de calibration : forme partagée contre stimulus, matrice de confusion | Python | Recherche | -| 24b | [Banc humour, passage à l'échelle](GameTheory-18d-Humour-Banc-Dur-Python.ipynb) | Comparaison de modèles de langage, circularité, paires minimales | Python | Recherche | +| 24 | [Banc humour](GameTheory-18c-Humour-Banc-Python.ipynb) | Banc de calibration (forme partagée contre stimulus, matrice de confusion) puis passage à l'échelle consolidé : corpus Argumentum 120 instances, comparaison LLM, circularité, paires minimales (#14032) | Python | Recherche | | 25 | [Persuasion bayésienne](GameTheory-17e-Bayesian-Persuasion-Python.ipynb) | La concavification évaluée par deux méthodes indépendantes (programme linéaire et enveloppe concave) dont l'accord est vérifié, avec un contrôle négatif | Python | Recherche | ## Installation diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35-HumorCausalProbe-Pilot-Python.ipynb b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35-HumorCausalProbe-Pilot-Python.ipynb index 91294ce0c3..8a6d171050 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35-HumorCausalProbe-Pilot-Python.ipynb +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35-HumorCausalProbe-Pilot-Python.ipynb @@ -6,16 +6,16 @@ "id": "14791a35", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:50:10.364257Z", - "iopub.status.busy": "2026-10-01T00:50:10.364091Z", - "iopub.status.idle": "2026-10-01T00:50:10.367013Z", - "shell.execute_reply": "2026-10-01T00:50:10.366523Z" + "iopub.execute_input": "2026-10-04T00:21:24.031253Z", + "iopub.status.busy": "2026-10-04T00:21:24.030882Z", + "iopub.status.idle": "2026-10-04T00:21:24.035721Z", + "shell.execute_reply": "2026-10-04T00:21:24.034524Z" }, "papermill": { - "duration": 0.006271, - "end_time": "2026-10-01T00:50:10.367594+00:00", + "duration": 0.00951, + "end_time": "2026-10-04T00:21:24.036711+00:00", "exception": false, - "start_time": "2026-10-01T00:50:10.361323+00:00", + "start_time": "2026-10-04T00:21:24.027201+00:00", "status": "completed" }, "tags": [ @@ -33,10 +33,10 @@ "id": "statut-epistemique", "metadata": { "papermill": { - "duration": 0.001726, - "end_time": "2026-10-01T00:50:10.370992+00:00", + "duration": 0.002142, + "end_time": "2026-10-04T00:21:24.041261+00:00", "exception": false, - "start_time": "2026-10-01T00:50:10.369266+00:00", + "start_time": "2026-10-04T00:21:24.039119+00:00", "status": "completed" }, "tags": [] @@ -50,10 +50,10 @@ "id": "acquis-renvoi", "metadata": { "papermill": { - "duration": 0.001327, - "end_time": "2026-10-01T00:50:10.373801+00:00", + "duration": 0.002344, + "end_time": "2026-10-04T00:21:24.045800+00:00", "exception": false, - "start_time": "2026-10-01T00:50:10.372474+00:00", + "start_time": "2026-10-04T00:21:24.043456+00:00", "status": "completed" }, "tags": [] @@ -67,10 +67,10 @@ "id": "frontmatter", "metadata": { "papermill": { - "duration": 0.001316, - "end_time": "2026-10-01T00:50:10.376634+00:00", + "duration": 0.002262, + "end_time": "2026-10-04T00:21:24.050808+00:00", "exception": false, - "start_time": "2026-10-01T00:50:10.375318+00:00", + "start_time": "2026-10-04T00:21:24.048546+00:00", "status": "completed" }, "tags": [] @@ -79,7 +79,7 @@ "## ICT-35 -- HumorCausalProbe-Pilot : substrat HLS, sans GPU, sans confusion explication/mecanisme\n", "\n", "> **Serie ICT** (*Integrated Causal Trajectories*, EPIC #4588) -- strate 5 : *extraction GPU-free*.\n", - "> Issue : **#14035**. prerequis livre : **GT-28b** banc humour dur (120 instances annotees, #12785 MERGED 2026-08-27).\n", + "> Issue : **#14035**. prerequis livre : banc humour dur **consolide dans GT-18c** (120 instances annotees, #12785 puis absorption #14032).\n", "> Aval : #5635 (Gate 24 workspace), #8236 (multi-echelle), #5105 (Inoculation).\n", "\n", "## Étage 0 -- baseline de shortcuts lexicaux (PAS Phase 1 SAE)\n", @@ -133,7 +133,7 @@ "\n", "## Sources\n", "\n", - "- `MyIA.AI.Notebooks/GameTheory/GameTheory-18d-Humour-Banc-Dur-Python.ipynb` : CORPUS_DUR 120 instances (cell[10]), labellisation manuelle par heuristique Argumentum (cf note methodo de l'acceptance).\n", + "- `MyIA.AI.Notebooks/GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb` : CORPUS_DUR 120 instances (cell[33], section echelle consolidee #14032), labellisation manuelle par heuristique Argumentum (cf note methodo de l'acceptance).\n", "- `G:\\Mon Drive\\MyIA\\IA\\Bibliographie IA\\MachineLearning\\Computational Humor\\` : sources HLS (Attardo/Raskin GTVH + Mihalcea/Pulido humor stylometry), **prevues comme reference** pour la taxonomie -- la mise en archive effective est a faire dans le scope de #14033, pas de ce notebook.\n", "\n", "\n", @@ -158,16 +158,16 @@ "id": "setup", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:50:10.380321Z", - "iopub.status.busy": "2026-10-01T00:50:10.380173Z", - "iopub.status.idle": "2026-10-01T00:50:11.763815Z", - "shell.execute_reply": "2026-10-01T00:50:11.763266Z" + "iopub.execute_input": "2026-10-04T00:21:24.057959Z", + "iopub.status.busy": "2026-10-04T00:21:24.057515Z", + "iopub.status.idle": "2026-10-04T00:21:26.205985Z", + "shell.execute_reply": "2026-10-04T00:21:26.204587Z" }, "papermill": { - "duration": 1.386153, - "end_time": "2026-10-01T00:50:11.764279+00:00", + "duration": 2.154108, + "end_time": "2026-10-04T00:21:26.207217+00:00", "exception": false, - "start_time": "2026-10-01T00:50:10.378126+00:00", + "start_time": "2026-10-04T00:21:24.053109+00:00", "status": "completed" }, "tags": [] @@ -177,7 +177,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "[setup] GT-28b present : MyIA.AI.Notebooks\\GameTheory\\GameTheory-18d-Humour-Banc-Dur-Python.ipynb\n", + "[setup] banc humour 18c (consolide #14032) present : MyIA.AI.Notebooks\\GameTheory\\GameTheory-18c-Humour-Banc-Python.ipynb\n", "[setup] seed = 13306\n", "[setup] sklearn LogisticRegression baseline (CPU)\n" ] @@ -207,9 +207,9 @@ "random.seed(SEED)\n", "np.random.seed(SEED)\n", "\n", - "GT28B = Path(\"MyIA.AI.Notebooks/GameTheory/GameTheory-18d-Humour-Banc-Dur-Python.ipynb\")\n", - "assert GT28B.exists(), f\"GT-28b manquant : {GT28B.resolve()}\"\n", - "print(f\"[setup] GT-28b present : {GT28B}\")\n", + "GT28B = Path(\"MyIA.AI.Notebooks/GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb\") # consolide #14032\n", + "assert GT28B.exists(), f\"banc humour 18c manquant : {GT28B.resolve()}\"\n", + "print(f\"[setup] banc humour 18c (consolide #14032) present : {GT28B}\")\n", "print(f\"[setup] seed = {SEED}\")\n", "print(f\"[setup] sklearn LogisticRegression baseline (CPU)\")\n" ] @@ -220,16 +220,16 @@ "id": "extract-corpus", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:50:11.768656Z", - "iopub.status.busy": "2026-10-01T00:50:11.768432Z", - "iopub.status.idle": "2026-10-01T00:50:12.510708Z", - "shell.execute_reply": "2026-10-01T00:50:12.510189Z" + "iopub.execute_input": "2026-10-04T00:21:26.214107Z", + "iopub.status.busy": "2026-10-04T00:21:26.213719Z", + "iopub.status.idle": "2026-10-04T00:21:28.244695Z", + "shell.execute_reply": "2026-10-04T00:21:28.243751Z" }, "papermill": { - "duration": 0.745183, - "end_time": "2026-10-01T00:50:12.511303+00:00", + "duration": 2.036255, + "end_time": "2026-10-04T00:21:28.246533+00:00", "exception": false, - "start_time": "2026-10-01T00:50:11.766120+00:00", + "start_time": "2026-10-04T00:21:26.210278+00:00", "status": "completed" }, "tags": [] @@ -239,7 +239,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "[extract] 5 cellules code GT-28b[0..10] a executer\n", + "[extract] 5 cellules code 18c[26..33] a executer\n", "[setup] Catégories : ['humour_reussi', 'rire_sans_recadrage', 'recadrage_sans_rire', 'offensif_compris_non_partage', 'rien']\n", "[setup] LLM endpoint : https://openrouter.ai/api/v1\n", "[setup] LLM model : anthropic/claude-haiku-4.5\n" @@ -249,14 +249,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "[fetch] downloaded 558592 bytes -> argumentum_scenarii.csv\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[fetch] upstream master @dd9026942b : feat(tools): #1485 harness for font substitution comparison on real faces (#1685\n", + "[fetch] downloaded 558592 bytes -> argumentum_scenarii.csv\n", + "[fetch] upstream master @d68170c521 : docs(corpus): #458 liste de relecture native (38) -- 2 ouvertes, 6 confirmations\n", "[parse] 167 scénarios Argumentum chargés\n", "[parse] catégories : {'histoire': 17, 'mythologie': 27, 'relation intime': 36, 'vie professionnelle': 30, 'vie personnelle': 25, 'pop culture': 18, 'politique': 14}\n", "[parse] sous-catégories (21) : {'antiquité': 6, 'moyen-âge et temps modernes': 6, '20e et 21e siècle': 5, 'contes': 10, 'religions': 11, 'littérature': 6, 'drague et séduction': 9, 'vie de couple': 16, 'romance': 11, 'interactions professionnelles': 14, 'relations au travail': 8, 'gestion et administration': 9, 'Bandes dessinées': 5, 'cinéma & télévision': 7, 'science': 6, 'gouvernance': 4, 'manoeuvres et collusion': 6, 'campagne': 4, 'famille et enfance': 8, 'voisins et amis': 11, 'loisirs et espace public': 5}\n", @@ -279,13 +273,14 @@ } ], "source": [ - "# Re-execute cell[1]..cell[10] de GT-28b pour obtenir CORPUS_DUR.\n", + "# Re-execute la section passage-a-l'echelle (cell[26..33]) du banc humour\n", + "# consolide (18c, ex-GT-28b absorbe par #14032) pour obtenir CORPUS_DUR.\n", "# C'est une REPRODUCTION : on n'edite pas le notebook source, on importe\n", - "# ses cellules et on les execute ici. Source de verite = GT-28b.ipynb.\n", + "# ses cellules et on les execute ici. Source de verite = 18c consolide.\n", "nb_src = json.loads(GT28B.read_text(encoding=\"utf-8\"))\n", "code_cells = [(i, ''.join(c['source'])) for i, c in enumerate(nb_src['cells'])\n", - " if c['cell_type'] == 'code' and i <= 10]\n", - "print(f\"[extract] {len(code_cells)} cellules code GT-28b[0..10] a executer\")\n", + " if c['cell_type'] == 'code' and 26 <= i <= 33]\n", + "print(f\"[extract] {len(code_cells)} cellules code 18c[26..33] a executer\")\n", "\n", "ns = {}\n", "for i, src in code_cells:\n", @@ -302,10 +297,10 @@ "id": "557db768", "metadata": { "papermill": { - "duration": 0.001641, - "end_time": "2026-10-01T00:50:12.514904+00:00", + "duration": 0.002551, + "end_time": "2026-10-04T00:21:28.252397+00:00", "exception": false, - "start_time": "2026-10-01T00:50:12.513263+00:00", + "start_time": "2026-10-04T00:21:28.249846+00:00", "status": "completed" }, "tags": [] @@ -313,7 +308,7 @@ "source": [ "## Lecture 1 -- Le sous-corpus : 120 instances, un label a 48\n", "\n", - "La sortie de l'extraction (5 cellules de GT-28b re-executees, aucune edition du notebook source) fixe le terrain : CORPUS_DUR = 120 instances, 5 categories ({'rire_sans_recadrage': 14, 'recadrage_sans_rire': 13, 'rien': 38, 'humour_reussi': 48, 'offensif_compris_non_partage': 7}) et 4 sources ({'ArgumentumGames/Argumentum': 60, 'blague-manuelle': 30, 'declaration-factuelle': 20, 'edge-case-curated': 10}).\n", + "La sortie de l'extraction (5 cellules du banc 18c re-executees, aucune edition du notebook source) fixe le terrain : CORPUS_DUR = 120 instances, 5 categories ({'rire_sans_recadrage': 14, 'recadrage_sans_rire': 13, 'rien': 38, 'humour_reussi': 48, 'offensif_compris_non_partage': 7}) et 4 sources ({'ArgumentumGames/Argumentum': 60, 'blague-manuelle': 30, 'declaration-factuelle': 20, 'edge-case-curated': 10}).\n", "\n", "Le label positif `humour_reussi` est la categorie la plus fournie du corpus brut (48 sur 120, soit 40 %) : la difficulte ne vient pas de sa rarete mais de la stratification du protocole, qui n'en retient que 6 (cellule suivante). C'est la premiere instance du motif « sous-corpus appauvri » du frontmatter : le protocole borne sa propre puissance statistique avant meme la premiere feature." ] @@ -324,16 +319,16 @@ "id": "stratify", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:50:12.518859Z", - "iopub.status.busy": "2026-10-01T00:50:12.518700Z", - "iopub.status.idle": "2026-10-01T00:50:12.522412Z", - "shell.execute_reply": "2026-10-01T00:50:12.521823Z" + "iopub.execute_input": "2026-10-04T00:21:28.261419Z", + "iopub.status.busy": "2026-10-04T00:21:28.261120Z", + "iopub.status.idle": "2026-10-04T00:21:28.268534Z", + "shell.execute_reply": "2026-10-04T00:21:28.267369Z" }, "papermill": { - "duration": 0.006461, - "end_time": "2026-10-01T00:50:12.522940+00:00", + "duration": 0.013084, + "end_time": "2026-10-04T00:21:28.270007+00:00", "exception": false, - "start_time": "2026-10-01T00:50:12.516479+00:00", + "start_time": "2026-10-04T00:21:28.256923+00:00", "status": "completed" }, "tags": [] @@ -350,7 +345,7 @@ } ], "source": [ - "# Stratification : 6 humour_reussi (cell[17] de GT-28b), tous les non-humour disponibles.\n", + "# Stratification : 6 humour_reussi (cell[42] du banc consolide), tous les non-humour disponibles.\n", "# 6 humour_reussi (le label 'humour_reussi') vs ~72 non-humour (4 autres labels).\n", "# Le ratio 1:12 maximise la variete des non-humour pour la diversite des negatifs.\n", "# ATTENTION (c.920, fixe en c.927) : la strategie d'echantillonnage est maintenant **par\n", @@ -387,16 +382,16 @@ "id": "match-pairs", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:50:12.526854Z", - "iopub.status.busy": "2026-10-01T00:50:12.526714Z", - "iopub.status.idle": "2026-10-01T00:50:12.533448Z", - "shell.execute_reply": "2026-10-01T00:50:12.532923Z" + "iopub.execute_input": "2026-10-04T00:21:28.278777Z", + "iopub.status.busy": "2026-10-04T00:21:28.278201Z", + "iopub.status.idle": "2026-10-04T00:21:28.292063Z", + "shell.execute_reply": "2026-10-04T00:21:28.290803Z" }, "papermill": { - "duration": 0.009506, - "end_time": "2026-10-01T00:50:12.533979+00:00", + "duration": 0.018903, + "end_time": "2026-10-04T00:21:28.293171+00:00", "exception": false, - "start_time": "2026-10-01T00:50:12.524473+00:00", + "start_time": "2026-10-04T00:21:28.274268+00:00", "status": "completed" }, "tags": [] @@ -483,10 +478,10 @@ "id": "a09b12e5", "metadata": { "papermill": { - "duration": 0.001517, - "end_time": "2026-10-01T00:50:12.537111+00:00", + "duration": 0.004013, + "end_time": "2026-10-04T00:21:28.301010+00:00", "exception": false, - "start_time": "2026-10-01T00:50:12.535594+00:00", + "start_time": "2026-10-04T00:21:28.296997+00:00", "status": "completed" }, "tags": [] @@ -505,16 +500,16 @@ "id": "lexical-features", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:50:12.541035Z", - "iopub.status.busy": "2026-10-01T00:50:12.540890Z", - "iopub.status.idle": "2026-10-01T00:50:12.547052Z", - "shell.execute_reply": "2026-10-01T00:50:12.546568Z" + "iopub.execute_input": "2026-10-04T00:21:28.310277Z", + "iopub.status.busy": "2026-10-04T00:21:28.310023Z", + "iopub.status.idle": "2026-10-04T00:21:28.319266Z", + "shell.execute_reply": "2026-10-04T00:21:28.318303Z" }, "papermill": { - "duration": 0.009048, - "end_time": "2026-10-01T00:50:12.547689+00:00", + "duration": 0.015228, + "end_time": "2026-10-04T00:21:28.320107+00:00", "exception": false, - "start_time": "2026-10-01T00:50:12.538641+00:00", + "start_time": "2026-10-04T00:21:28.304879+00:00", "status": "completed" }, "tags": [] @@ -606,16 +601,16 @@ "id": "build-Xy", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:50:12.551746Z", - "iopub.status.busy": "2026-10-01T00:50:12.551611Z", - "iopub.status.idle": "2026-10-01T00:50:12.596037Z", - "shell.execute_reply": "2026-10-01T00:50:12.595438Z" + "iopub.execute_input": "2026-10-04T00:21:28.328773Z", + "iopub.status.busy": "2026-10-04T00:21:28.328231Z", + "iopub.status.idle": "2026-10-04T00:21:28.457024Z", + "shell.execute_reply": "2026-10-04T00:21:28.455602Z" }, "papermill": { - "duration": 0.047145, - "end_time": "2026-10-01T00:50:12.596562+00:00", + "duration": 0.135694, + "end_time": "2026-10-04T00:21:28.458373+00:00", "exception": false, - "start_time": "2026-10-01T00:50:12.549417+00:00", + "start_time": "2026-10-04T00:21:28.322679+00:00", "status": "completed" }, "tags": [] @@ -714,16 +709,16 @@ "id": "cv-baseline", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:50:12.600846Z", - "iopub.status.busy": "2026-10-01T00:50:12.600648Z", - "iopub.status.idle": "2026-10-01T00:50:12.622427Z", - "shell.execute_reply": "2026-10-01T00:50:12.621886Z" + "iopub.execute_input": "2026-10-04T00:21:28.469639Z", + "iopub.status.busy": "2026-10-04T00:21:28.469222Z", + "iopub.status.idle": "2026-10-04T00:21:28.517956Z", + "shell.execute_reply": "2026-10-04T00:21:28.516513Z" }, "papermill": { - "duration": 0.024628, - "end_time": "2026-10-01T00:50:12.622974+00:00", + "duration": 0.055798, + "end_time": "2026-10-04T00:21:28.519313+00:00", "exception": false, - "start_time": "2026-10-01T00:50:12.598346+00:00", + "start_time": "2026-10-04T00:21:28.463515+00:00", "status": "completed" }, "tags": [] @@ -733,7 +728,13 @@ "name": "stdout", "output_type": "stream", "text": [ - "[cv-v5] fold 0 n_train=24 n_test=12 F1=0.000\n", + "[cv-v5] fold 0 n_train=24 n_test=12 F1=0.000\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ "[cv-v5] fold 1 n_train=24 n_test=12 F1=0.250\n", "[cv-v5] fold 2 n_train=24 n_test=12 F1=0.400\n", "[cv-v5] F1 group-level baseline = 0.217 +/- 0.165\n", @@ -785,10 +786,10 @@ "id": "8f964f59", "metadata": { "papermill": { - "duration": 0.001922, - "end_time": "2026-10-01T00:50:12.627028+00:00", + "duration": 0.004595, + "end_time": "2026-10-04T00:21:28.528791+00:00", "exception": false, - "start_time": "2026-10-01T00:50:12.625106+00:00", + "start_time": "2026-10-04T00:21:28.524196+00:00", "status": "completed" }, "tags": [] @@ -807,16 +808,16 @@ "id": "control-shuffle", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:50:12.631810Z", - "iopub.status.busy": "2026-10-01T00:50:12.631616Z", - "iopub.status.idle": "2026-10-01T00:50:14.136869Z", - "shell.execute_reply": "2026-10-01T00:50:14.136147Z" + "iopub.execute_input": "2026-10-04T00:21:28.537507Z", + "iopub.status.busy": "2026-10-04T00:21:28.537109Z", + "iopub.status.idle": "2026-10-04T00:21:32.017655Z", + "shell.execute_reply": "2026-10-04T00:21:32.015886Z" }, "papermill": { - "duration": 1.508749, - "end_time": "2026-10-01T00:50:14.137741+00:00", + "duration": 3.487771, + "end_time": "2026-10-04T00:21:32.019213+00:00", "exception": false, - "start_time": "2026-10-01T00:50:12.628992+00:00", + "start_time": "2026-10-04T00:21:28.531442+00:00", "status": "completed" }, "tags": [] @@ -917,10 +918,10 @@ "id": "f2d0d74d", "metadata": { "papermill": { - "duration": 0.00202, - "end_time": "2026-10-01T00:50:14.141946+00:00", + "duration": 0.004614, + "end_time": "2026-10-04T00:21:32.028846+00:00", "exception": false, - "start_time": "2026-10-01T00:50:14.139926+00:00", + "start_time": "2026-10-04T00:21:32.024232+00:00", "status": "completed" }, "tags": [] @@ -939,16 +940,16 @@ "id": "control-surface", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:50:14.147139Z", - "iopub.status.busy": "2026-10-01T00:50:14.146860Z", - "iopub.status.idle": "2026-10-01T00:50:14.177226Z", - "shell.execute_reply": "2026-10-01T00:50:14.176532Z" + "iopub.execute_input": "2026-10-04T00:21:32.040496Z", + "iopub.status.busy": "2026-10-04T00:21:32.039848Z", + "iopub.status.idle": "2026-10-04T00:21:32.108182Z", + "shell.execute_reply": "2026-10-04T00:21:32.106671Z" }, "papermill": { - "duration": 0.034249, - "end_time": "2026-10-01T00:50:14.178247+00:00", + "duration": 0.076482, + "end_time": "2026-10-04T00:21:32.109585+00:00", "exception": false, - "start_time": "2026-10-01T00:50:14.143998+00:00", + "start_time": "2026-10-04T00:21:32.033103+00:00", "status": "completed" }, "tags": [] @@ -1061,10 +1062,10 @@ "id": "2beff9d1", "metadata": { "papermill": { - "duration": 0.002727, - "end_time": "2026-10-01T00:50:14.183544+00:00", + "duration": 0.004188, + "end_time": "2026-10-04T00:21:32.117468+00:00", "exception": false, - "start_time": "2026-10-01T00:50:14.180817+00:00", + "start_time": "2026-10-04T00:21:32.113280+00:00", "status": "completed" }, "tags": [] @@ -1083,16 +1084,16 @@ "id": "verdict", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:50:14.189845Z", - "iopub.status.busy": "2026-10-01T00:50:14.189598Z", - "iopub.status.idle": "2026-10-01T00:50:14.197112Z", - "shell.execute_reply": "2026-10-01T00:50:14.196570Z" + "iopub.execute_input": "2026-10-04T00:21:32.128158Z", + "iopub.status.busy": "2026-10-04T00:21:32.127750Z", + "iopub.status.idle": "2026-10-04T00:21:32.142756Z", + "shell.execute_reply": "2026-10-04T00:21:32.141596Z" }, "papermill": { - "duration": 0.012737, - "end_time": "2026-10-01T00:50:14.198709+00:00", + "duration": 0.023132, + "end_time": "2026-10-04T00:21:32.144608+00:00", "exception": false, - "start_time": "2026-10-01T00:50:14.185972+00:00", + "start_time": "2026-10-04T00:21:32.121476+00:00", "status": "completed" }, "tags": [] @@ -1205,10 +1206,10 @@ "id": "732d3924", "metadata": { "papermill": { - "duration": 0.002319, - "end_time": "2026-10-01T00:50:14.203463+00:00", + "duration": 0.004437, + "end_time": "2026-10-04T00:21:32.153772+00:00", "exception": false, - "start_time": "2026-10-01T00:50:14.201144+00:00", + "start_time": "2026-10-04T00:21:32.149335+00:00", "status": "completed" }, "tags": [] @@ -1227,16 +1228,16 @@ "id": "phase2-perspective", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:50:14.208795Z", - "iopub.status.busy": "2026-10-01T00:50:14.208579Z", - "iopub.status.idle": "2026-10-01T00:50:14.213770Z", - "shell.execute_reply": "2026-10-01T00:50:14.213121Z" + "iopub.execute_input": "2026-10-04T00:21:32.164394Z", + "iopub.status.busy": "2026-10-04T00:21:32.163974Z", + "iopub.status.idle": "2026-10-04T00:21:32.171961Z", + "shell.execute_reply": "2026-10-04T00:21:32.170484Z" }, "papermill": { - "duration": 0.008593, - "end_time": "2026-10-01T00:50:14.214229+00:00", + "duration": 0.01629, + "end_time": "2026-10-04T00:21:32.173060+00:00", "exception": false, - "start_time": "2026-10-01T00:50:14.205636+00:00", + "start_time": "2026-10-04T00:21:32.156770+00:00", "status": "completed" }, "tags": [] @@ -1288,10 +1289,10 @@ "id": "navlinks", "metadata": { "papermill": { - "duration": 0.001972, - "end_time": "2026-10-01T00:50:14.218416+00:00", + "duration": 0.005215, + "end_time": "2026-10-04T00:21:32.183325+00:00", "exception": false, - "start_time": "2026-10-01T00:50:14.216444+00:00", + "start_time": "2026-10-04T00:21:32.178110+00:00", "status": "completed" }, "tags": [] @@ -1302,7 +1303,7 @@ "- **#14035** -- issue de reference, protocole falsifiable, acceptance (cible haute).\n", "- **#14032** -- consolidation de la methode de labellisation (GT-28 / GT-28b).\n", "- **#14033** -- substrat taxonomique croissant (corpus apparie + 3 labels + taxonomie sourcee).\n", - "- **`MyIA.AI.Notebooks/GameTheory/GameTheory-18d-Humour-Banc-Dur-Python.ipynb`** -- CORPUS_DUR 120 instances, source de verite.\n", + "- **`MyIA.AI.Notebooks/GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb`** -- banc humour consolide (#14032) : CORPUS_DUR 120 instances, source de verite.\n", "- **`MyIA.AI.Notebooks/IIT/ICT-Series/ICT-21-SAETrajectories.ipynb`** -- substrat S4 (SAE Qwen3.5-9B), aval + tard.\n", "- **`MyIA.AI.Notebooks/IIT/ICT-Series/ICT-24-WorkspaceIgnition-Python.ipynb`** -- Gate 24, gated etages superieurs (GPU).\n", "- **#5635, #8236, #5105, #4588** -- aval ICT-Series.\n", @@ -1331,19 +1332,19 @@ }, "papermill": { "default_parameters": {}, - "duration": 5.866062, - "end_time": "2026-10-01T00:50:14.550494+00:00", + "duration": 10.726753, + "end_time": "2026-10-04T00:21:32.758986+00:00", "environment_variables": {}, "exception": null, "input_path": "ICT-35-HumorCausalProbe-Pilot-Python.ipynb", - "output_path": "ICT-35-HumorCausalProbe-Pilot-Python.ipynb", + "output_path": "ICT-35-HumorCausalProbe-Pilot-Python_output.ipynb", "parameters": { "nb_name": "ICT-35-HumorCausalProbe-Pilot" }, - "start_time": "2026-10-01T00:50:08.684432+00:00", + "start_time": "2026-10-04T00:21:22.032233+00:00", "version": "2.6.0" } }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35b-HumorCausalPairs-SAE-Python.ipynb b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35b-HumorCausalPairs-SAE-Python.ipynb index 2b332ebb11..499efacc24 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35b-HumorCausalPairs-SAE-Python.ipynb +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35b-HumorCausalPairs-SAE-Python.ipynb @@ -6,16 +6,16 @@ "id": "9f5dffbc", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:54:13.817066Z", - "iopub.status.busy": "2026-10-01T00:54:13.816764Z", - "iopub.status.idle": "2026-10-01T00:54:13.821682Z", - "shell.execute_reply": "2026-10-01T00:54:13.820568Z" + "iopub.execute_input": "2026-10-04T00:21:41.018656Z", + "iopub.status.busy": "2026-10-04T00:21:41.018061Z", + "iopub.status.idle": "2026-10-04T00:21:41.025343Z", + "shell.execute_reply": "2026-10-04T00:21:41.023887Z" }, "papermill": { - "duration": 0.009997, - "end_time": "2026-10-01T00:54:13.822736+00:00", + "duration": 0.014149, + "end_time": "2026-10-04T00:21:41.026588+00:00", "exception": false, - "start_time": "2026-10-01T00:54:13.812739+00:00", + "start_time": "2026-10-04T00:21:41.012439+00:00", "status": "completed" }, "tags": [ @@ -33,10 +33,10 @@ "id": "statut-epistemique", "metadata": { "papermill": { - "duration": 0.001666, - "end_time": "2026-10-01T00:54:13.827015+00:00", + "duration": 0.003344, + "end_time": "2026-10-04T00:21:41.032987+00:00", "exception": false, - "start_time": "2026-10-01T00:54:13.825349+00:00", + "start_time": "2026-10-04T00:21:41.029643+00:00", "status": "completed" }, "tags": [] @@ -50,10 +50,10 @@ "id": "91c071ef", "metadata": { "papermill": { - "duration": 0.001333, - "end_time": "2026-10-01T00:54:13.829865+00:00", + "duration": 0.00263, + "end_time": "2026-10-04T00:21:41.039049+00:00", "exception": false, - "start_time": "2026-10-01T00:54:13.828532+00:00", + "start_time": "2026-10-04T00:21:41.036419+00:00", "status": "completed" }, "tags": [] @@ -78,16 +78,16 @@ "id": "daed5bc4", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:54:13.833310Z", - "iopub.status.busy": "2026-10-01T00:54:13.833123Z", - "iopub.status.idle": "2026-10-01T00:54:15.342606Z", - "shell.execute_reply": "2026-10-01T00:54:15.342110Z" + "iopub.execute_input": "2026-10-04T00:21:41.047128Z", + "iopub.status.busy": "2026-10-04T00:21:41.046674Z", + "iopub.status.idle": "2026-10-04T00:21:44.691720Z", + "shell.execute_reply": "2026-10-04T00:21:44.690193Z" }, "papermill": { - "duration": 1.511972, - "end_time": "2026-10-01T00:54:15.343113+00:00", + "duration": 3.651361, + "end_time": "2026-10-04T00:21:44.693268+00:00", "exception": false, - "start_time": "2026-10-01T00:54:13.831141+00:00", + "start_time": "2026-10-04T00:21:41.041907+00:00", "status": "completed" }, "tags": [] @@ -100,14 +100,14 @@ "[setup] Catégories : ['humour_reussi', 'rire_sans_recadrage', 'recadrage_sans_rire', 'offensif_compris_non_partage', 'rien']\n", "[setup] LLM endpoint : https://openrouter.ai/api/v1\n", "[setup] LLM model : anthropic/claude-haiku-4.5\n", - "[fetch] downloaded 558592 bytes -> argumentum_scenarii.csv\n" + "[fetch] cache hit : argumentum_scenarii.csv\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "[fetch] upstream master @dd9026942b : feat(tools): #1485 harness for font substitution comparison on real faces (#1685\n", + "[fetch] upstream master @d68170c521 : docs(corpus): #458 liste de relecture native (38) -- 2 ouvertes, 6 confirmations\n", "[parse] 167 scénarios Argumentum chargés\n", "[parse] catégories : {'histoire': 17, 'mythologie': 27, 'relation intime': 36, 'vie professionnelle': 30, 'vie personnelle': 25, 'pop culture': 18, 'politique': 14}\n", "[parse] sous-catégories (21) : {'antiquité': 6, 'moyen-âge et temps modernes': 6, '20e et 21e siècle': 5, 'contes': 10, 'religions': 11, 'littérature': 6, 'drague et séduction': 9, 'vie de couple': 16, 'romance': 11, 'interactions professionnelles': 14, 'relations au travail': 8, 'gestion et administration': 9, 'Bandes dessinées': 5, 'cinéma & télévision': 7, 'science': 6, 'gouvernance': 4, 'manoeuvres et collusion': 6, 'campagne': 4, 'famille et enfance': 8, 'voisins et amis': 11, 'loisirs et espace public': 5}\n", @@ -123,7 +123,7 @@ "[corpus] recadrage_sans_rire : 13 instances OK\n", "[corpus] offensif_compris_non_partage : 7 instances OK\n", "[corpus] rien : 38 instances OK\n", - "GT-24b : GameTheory-18d-Humour-Banc-Dur-Python.ipynb\n", + "banc humour : GameTheory-18c-Humour-Banc-Python.ipynb\n", "CORPUS_DUR : 120 instances\n", " humour_reussi 48\n", " rien 38\n", @@ -135,11 +135,12 @@ ], "source": [ "# -*- coding: utf-8 -*-\n", - "# Setup. Reproduction du corpus GT-24b (meme geste que le pilote ICT-35) :\n", - "# les cellules code [0..10] de GameTheory-24b-Humour-Banc-Dur.ipynb sont\n", + "# Setup. Reproduction du corpus humour (meme geste que le pilote ICT-35) :\n", + "# les cellules code [26..33] de la section echelle du banc consolide\n", + "# (GameTheory-18c, absorption #14032) sont\n", "# executees dans un namespace isole, sans editer le notebook source.\n", "# La reproduction exige OPENROUTER_API_KEY dans l'environnement (les cellules\n", - "# endpoint de GT-24b la verificent ; aucune n'appelle l'API ici).\n", + "# endpoint du banc la verificent ; aucune n'appelle l'API ici).\n", "from collections import Counter\n", "from pathlib import Path\n", "import json\n", @@ -159,7 +160,7 @@ "\n", "corpus = load_corpus_dur()\n", "dist = label_distribution(corpus)\n", - "print(f\"GT-24b : {gt24b_path().name}\")\n", + "print(f\"banc humour : {gt24b_path().name}\")\n", "print(f\"CORPUS_DUR : {len(corpus)} instances\")\n", "for lab, n in dist.most_common():\n", " print(f\" {lab:32s} {n}\")" @@ -170,10 +171,10 @@ "id": "553b2e82", "metadata": { "papermill": { - "duration": 0.001229, - "end_time": "2026-10-01T00:54:15.345840+00:00", + "duration": 0.00343, + "end_time": "2026-10-04T00:21:44.700999+00:00", "exception": false, - "start_time": "2026-10-01T00:54:15.344611+00:00", + "start_time": "2026-10-04T00:21:44.697569+00:00", "status": "completed" }, "tags": [] @@ -192,16 +193,16 @@ "id": "242dc539", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:54:15.348908Z", - "iopub.status.busy": "2026-10-01T00:54:15.348701Z", - "iopub.status.idle": "2026-10-01T00:54:15.364775Z", - "shell.execute_reply": "2026-10-01T00:54:15.364311Z" + "iopub.execute_input": "2026-10-04T00:21:44.709091Z", + "iopub.status.busy": "2026-10-04T00:21:44.708503Z", + "iopub.status.idle": "2026-10-04T00:21:44.736394Z", + "shell.execute_reply": "2026-10-04T00:21:44.735108Z" }, "papermill": { - "duration": 0.018305, - "end_time": "2026-10-01T00:54:15.365231+00:00", + "duration": 0.033132, + "end_time": "2026-10-04T00:21:44.737813+00:00", "exception": false, - "start_time": "2026-10-01T00:54:15.346926+00:00", + "start_time": "2026-10-04T00:21:44.704681+00:00", "status": "completed" }, "tags": [] @@ -353,10 +354,10 @@ "id": "615e72a4", "metadata": { "papermill": { - "duration": 0.001271, - "end_time": "2026-10-01T00:54:15.367912+00:00", + "duration": 0.001907, + "end_time": "2026-10-04T00:21:44.743088+00:00", "exception": false, - "start_time": "2026-10-01T00:54:15.366641+00:00", + "start_time": "2026-10-04T00:21:44.741181+00:00", "status": "completed" }, "tags": [] @@ -376,10 +377,10 @@ "id": "2e21cbd5", "metadata": { "papermill": { - "duration": 0.001155, - "end_time": "2026-10-01T00:54:15.370277+00:00", + "duration": 0.003091, + "end_time": "2026-10-04T00:21:44.749248+00:00", "exception": false, - "start_time": "2026-10-01T00:54:15.369122+00:00", + "start_time": "2026-10-04T00:21:44.746157+00:00", "status": "completed" }, "tags": [] @@ -406,16 +407,16 @@ "id": "bbdf78c4", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:54:15.373592Z", - "iopub.status.busy": "2026-10-01T00:54:15.373420Z", - "iopub.status.idle": "2026-10-01T00:54:15.392571Z", - "shell.execute_reply": "2026-10-01T00:54:15.392045Z" + "iopub.execute_input": "2026-10-04T00:21:44.757023Z", + "iopub.status.busy": "2026-10-04T00:21:44.756427Z", + "iopub.status.idle": "2026-10-04T00:21:44.792266Z", + "shell.execute_reply": "2026-10-04T00:21:44.791085Z" }, "papermill": { - "duration": 0.021832, - "end_time": "2026-10-01T00:54:15.393287+00:00", + "duration": 0.041723, + "end_time": "2026-10-04T00:21:44.793870+00:00", "exception": false, - "start_time": "2026-10-01T00:54:15.371455+00:00", + "start_time": "2026-10-04T00:21:44.752147+00:00", "status": "completed" }, "tags": [] @@ -457,10 +458,10 @@ "id": "ca2c2654", "metadata": { "papermill": { - "duration": 0.001421, - "end_time": "2026-10-01T00:54:15.396236+00:00", + "duration": 0.00317, + "end_time": "2026-10-04T00:21:44.800801+00:00", "exception": false, - "start_time": "2026-10-01T00:54:15.394815+00:00", + "start_time": "2026-10-04T00:21:44.797631+00:00", "status": "completed" }, "tags": [] @@ -479,16 +480,16 @@ "id": "57ebae47", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:54:15.399971Z", - "iopub.status.busy": "2026-10-01T00:54:15.399733Z", - "iopub.status.idle": "2026-10-01T00:54:34.015137Z", - "shell.execute_reply": "2026-10-01T00:54:34.014592Z" + "iopub.execute_input": "2026-10-04T00:21:44.809483Z", + "iopub.status.busy": "2026-10-04T00:21:44.809210Z", + "iopub.status.idle": "2026-10-04T00:22:14.591994Z", + "shell.execute_reply": "2026-10-04T00:22:14.590702Z" }, "papermill": { - "duration": 18.618028, - "end_time": "2026-10-01T00:54:34.015617+00:00", + "duration": 29.78889, + "end_time": "2026-10-04T00:22:14.593430+00:00", "exception": false, - "start_time": "2026-10-01T00:54:15.397589+00:00", + "start_time": "2026-10-04T00:21:44.804540+00:00", "status": "completed" }, "tags": [] @@ -532,10 +533,10 @@ "id": "08096102", "metadata": { "papermill": { - "duration": 0.001502, - "end_time": "2026-10-01T00:54:34.018817+00:00", + "duration": 0.003578, + "end_time": "2026-10-04T00:22:14.599730+00:00", "exception": false, - "start_time": "2026-10-01T00:54:34.017315+00:00", + "start_time": "2026-10-04T00:22:14.596152+00:00", "status": "completed" }, "tags": [] @@ -556,16 +557,16 @@ "id": "0468a3d2", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:54:34.023288Z", - "iopub.status.busy": "2026-10-01T00:54:34.023100Z", - "iopub.status.idle": "2026-10-01T00:54:52.971771Z", - "shell.execute_reply": "2026-10-01T00:54:52.971342Z" + "iopub.execute_input": "2026-10-04T00:22:14.606901Z", + "iopub.status.busy": "2026-10-04T00:22:14.606334Z", + "iopub.status.idle": "2026-10-04T00:22:42.869058Z", + "shell.execute_reply": "2026-10-04T00:22:42.867955Z" }, "papermill": { - "duration": 18.951643, - "end_time": "2026-10-01T00:54:52.972383+00:00", + "duration": 28.267545, + "end_time": "2026-10-04T00:22:42.869977+00:00", "exception": false, - "start_time": "2026-10-01T00:54:34.020740+00:00", + "start_time": "2026-10-04T00:22:14.602432+00:00", "status": "completed" }, "tags": [] @@ -607,10 +608,10 @@ "id": "74f472d1", "metadata": { "papermill": { - "duration": 0.001226, - "end_time": "2026-10-01T00:54:52.975083+00:00", + "duration": 0.001996, + "end_time": "2026-10-04T00:22:42.874232+00:00", "exception": false, - "start_time": "2026-10-01T00:54:52.973857+00:00", + "start_time": "2026-10-04T00:22:42.872236+00:00", "status": "completed" }, "tags": [] @@ -635,16 +636,16 @@ "id": "6144dedd", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:54:52.978419Z", - "iopub.status.busy": "2026-10-01T00:54:52.978235Z", - "iopub.status.idle": "2026-10-01T00:54:52.981163Z", - "shell.execute_reply": "2026-10-01T00:54:52.980722Z" + "iopub.execute_input": "2026-10-04T00:22:42.880330Z", + "iopub.status.busy": "2026-10-04T00:22:42.879920Z", + "iopub.status.idle": "2026-10-04T00:22:42.884366Z", + "shell.execute_reply": "2026-10-04T00:22:42.883476Z" }, "papermill": { - "duration": 0.00533, - "end_time": "2026-10-01T00:54:52.981667+00:00", + "duration": 0.009074, + "end_time": "2026-10-04T00:22:42.885340+00:00", "exception": false, - "start_time": "2026-10-01T00:54:52.976337+00:00", + "start_time": "2026-10-04T00:22:42.876266+00:00", "status": "completed" }, "tags": [] @@ -689,16 +690,16 @@ "id": "bb103042", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:54:52.985014Z", - "iopub.status.busy": "2026-10-01T00:54:52.984833Z", - "iopub.status.idle": "2026-10-01T00:54:52.987334Z", - "shell.execute_reply": "2026-10-01T00:54:52.986920Z" + "iopub.execute_input": "2026-10-04T00:22:42.890797Z", + "iopub.status.busy": "2026-10-04T00:22:42.890448Z", + "iopub.status.idle": "2026-10-04T00:22:42.895123Z", + "shell.execute_reply": "2026-10-04T00:22:42.894052Z" }, "papermill": { - "duration": 0.004739, - "end_time": "2026-10-01T00:54:52.987765+00:00", + "duration": 0.008763, + "end_time": "2026-10-04T00:22:42.896228+00:00", "exception": false, - "start_time": "2026-10-01T00:54:52.983026+00:00", + "start_time": "2026-10-04T00:22:42.887465+00:00", "status": "completed" }, "tags": [] @@ -742,16 +743,16 @@ "id": "4ce580d9", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:54:52.990895Z", - "iopub.status.busy": "2026-10-01T00:54:52.990719Z", - "iopub.status.idle": "2026-10-01T00:54:52.993145Z", - "shell.execute_reply": "2026-10-01T00:54:52.992738Z" + "iopub.execute_input": "2026-10-04T00:22:42.902386Z", + "iopub.status.busy": "2026-10-04T00:22:42.902103Z", + "iopub.status.idle": "2026-10-04T00:22:42.906884Z", + "shell.execute_reply": "2026-10-04T00:22:42.905777Z" }, "papermill": { - "duration": 0.004509, - "end_time": "2026-10-01T00:54:52.993533+00:00", + "duration": 0.009558, + "end_time": "2026-10-04T00:22:42.908111+00:00", "exception": false, - "start_time": "2026-10-01T00:54:52.989024+00:00", + "start_time": "2026-10-04T00:22:42.898553+00:00", "status": "completed" }, "tags": [] @@ -795,10 +796,10 @@ "id": "0e970a40", "metadata": { "papermill": { - "duration": 0.001174, - "end_time": "2026-10-01T00:54:52.996030+00:00", + "duration": 0.002113, + "end_time": "2026-10-04T00:22:42.913079+00:00", "exception": false, - "start_time": "2026-10-01T00:54:52.994856+00:00", + "start_time": "2026-10-04T00:22:42.910966+00:00", "status": "completed" }, "tags": [] @@ -813,7 +814,7 @@ "- **#14035** -- issue de reference : protocole falsifiable, pre-enregistrement (c.5743321902), ecarts c.5743498870 / c.5743512349\n", "- **ICT-35-HumorCausalProbe-Pilot-Python** -- le pilote HLS lexical (verdict INCONCLUSIVE borne, meme honnetete)\n", "- **ICT-21-SAETrajectoires-Python / ICT-21b-SAECalibration-Python** -- la strate SAE du pipeline #5101 et ses garde-fous (bf16, top-k)\n", - "- **GameTheory-18d-Humour-Banc-Dur-Python** -- le banc consolide CORPUS_DUR (120 instances annotees)\n", + "- **GameTheory-18c-Humour-Banc-Python** -- le banc humour consolide (#14032) : CORPUS_DUR (120 instances annotees)\n", "- `scripts/extract_sae_traces.py` -- l'extracteur GPU (seul composant torch) ; `ict/humor_pairs.py` -- corpus, paires, mesure" ] } @@ -838,17 +839,17 @@ }, "papermill": { "default_parameters": {}, - "duration": 40.515573, - "end_time": "2026-10-01T00:54:53.240871+00:00", + "duration": 66.382829, + "end_time": "2026-10-04T00:22:43.268691+00:00", "environment_variables": {}, "exception": null, "input_path": "ICT-35b-HumorCausalPairs-SAE-Python.ipynb", - "output_path": "ICT-35b-HumorCausalPairs-SAE-Python.ipynb", + "output_path": "ICT-35b-HumorCausalPairs-SAE-Python_output.ipynb", "parameters": {}, - "start_time": "2026-10-01T00:54:12.725298+00:00", + "start_time": "2026-10-04T00:21:36.885862+00:00", "version": "2.7.0" } }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35d-HumorTypologyBreakdown-SAE-Python.ipynb b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35d-HumorTypologyBreakdown-SAE-Python.ipynb index 3963acecb7..55f37f23d8 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35d-HumorTypologyBreakdown-SAE-Python.ipynb +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35d-HumorTypologyBreakdown-SAE-Python.ipynb @@ -6,16 +6,16 @@ "id": "452199a6", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:56:42.473865Z", - "iopub.status.busy": "2026-10-01T00:56:42.473603Z", - "iopub.status.idle": "2026-10-01T00:56:42.478906Z", - "shell.execute_reply": "2026-10-01T00:56:42.478052Z" + "iopub.execute_input": "2026-10-04T00:22:48.988057Z", + "iopub.status.busy": "2026-10-04T00:22:48.987760Z", + "iopub.status.idle": "2026-10-04T00:22:48.993464Z", + "shell.execute_reply": "2026-10-04T00:22:48.992310Z" }, "papermill": { - "duration": 0.010157, - "end_time": "2026-10-01T00:56:42.479937+00:00", + "duration": 0.011278, + "end_time": "2026-10-04T00:22:48.994597+00:00", "exception": false, - "start_time": "2026-10-01T00:56:42.469780+00:00", + "start_time": "2026-10-04T00:22:48.983319+00:00", "status": "completed" }, "tags": [] @@ -36,10 +36,10 @@ "id": "75013201", "metadata": { "papermill": { - "duration": 0.002114, - "end_time": "2026-10-01T00:56:42.484536+00:00", + "duration": 0.002216, + "end_time": "2026-10-04T00:22:48.999436+00:00", "exception": false, - "start_time": "2026-10-01T00:56:42.482422+00:00", + "start_time": "2026-10-04T00:22:48.997220+00:00", "status": "completed" }, "tags": [] @@ -53,10 +53,10 @@ "id": "e920c82e", "metadata": { "papermill": { - "duration": 0.001379, - "end_time": "2026-10-01T00:56:42.487480+00:00", + "duration": 0.002185, + "end_time": "2026-10-04T00:22:49.003946+00:00", "exception": false, - "start_time": "2026-10-01T00:56:42.486101+00:00", + "start_time": "2026-10-04T00:22:49.001761+00:00", "status": "completed" }, "tags": [] @@ -78,16 +78,16 @@ "id": "8603cbd8", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:56:42.491724Z", - "iopub.status.busy": "2026-10-01T00:56:42.491540Z", - "iopub.status.idle": "2026-10-01T00:56:43.974406Z", - "shell.execute_reply": "2026-10-01T00:56:43.973668Z" + "iopub.execute_input": "2026-10-04T00:22:49.013960Z", + "iopub.status.busy": "2026-10-04T00:22:49.013558Z", + "iopub.status.idle": "2026-10-04T00:22:51.284759Z", + "shell.execute_reply": "2026-10-04T00:22:51.283879Z" }, "papermill": { - "duration": 1.485598, - "end_time": "2026-10-01T00:56:43.974849+00:00", + "duration": 2.277582, + "end_time": "2026-10-04T00:22:51.285601+00:00", "exception": false, - "start_time": "2026-10-01T00:56:42.489251+00:00", + "start_time": "2026-10-04T00:22:49.008019+00:00", "status": "completed" }, "tags": [] @@ -107,7 +107,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "[fetch] upstream master @dd9026942b : feat(tools): #1485 harness for font substitution comparison on real faces (#1685\n", + "[fetch] upstream master @d68170c521 : docs(corpus): #458 liste de relecture native (38) -- 2 ouvertes, 6 confirmations\n", "[parse] 167 scénarios Argumentum chargés\n", "[parse] catégories : {'histoire': 17, 'mythologie': 27, 'relation intime': 36, 'vie professionnelle': 30, 'vie personnelle': 25, 'pop culture': 18, 'politique': 14}\n", "[parse] sous-catégories (21) : {'antiquité': 6, 'moyen-âge et temps modernes': 6, '20e et 21e siècle': 5, 'contes': 10, 'religions': 11, 'littérature': 6, 'drague et séduction': 9, 'vie de couple': 16, 'romance': 11, 'interactions professionnelles': 14, 'relations au travail': 8, 'gestion et administration': 9, 'Bandes dessinées': 5, 'cinéma & télévision': 7, 'science': 6, 'gouvernance': 4, 'manoeuvres et collusion': 6, 'campagne': 4, 'famille et enfance': 8, 'voisins et amis': 11, 'loisirs et espace public': 5}\n", @@ -445,8 +445,9 @@ ], "source": [ "# -*- coding: utf-8 -*-\n", - "# Setup. Reproduction du corpus GT-24b (meme geste que ICT-35b/35c) :\n", - "# les cellules code [0..10] de GameTheory-24b-Humour-Banc-Dur.ipynb sont\n", + "# Setup. Reproduction du corpus humour (meme geste que ICT-35b/35c) :\n", + "# les cellules code [26..33] de la section echelle du banc consolide\n", + "# (GameTheory-18c, absorption #14032) sont\n", "# executees dans un namespace isole. La reproduction exige OPENROUTER_API_KEY\n", "# dans l'environnement (verifiee par les cellules endpoint de GT-24b ; aucune\n", "# n'appelle l'API ici).\n", @@ -495,10 +496,10 @@ "id": "3d87fbcd", "metadata": { "papermill": { - "duration": 0.002156, - "end_time": "2026-10-01T00:56:43.978818+00:00", + "duration": 0.001971, + "end_time": "2026-10-04T00:22:51.289862+00:00", "exception": false, - "start_time": "2026-10-01T00:56:43.976662+00:00", + "start_time": "2026-10-04T00:22:51.287891+00:00", "status": "completed" }, "tags": [] @@ -516,10 +517,10 @@ "id": "a2d013e8", "metadata": { "papermill": { - "duration": 0.00174, - "end_time": "2026-10-01T00:56:43.982991+00:00", + "duration": 0.001719, + "end_time": "2026-10-04T00:22:51.293448+00:00", "exception": false, - "start_time": "2026-10-01T00:56:43.981251+00:00", + "start_time": "2026-10-04T00:22:51.291729+00:00", "status": "completed" }, "tags": [] @@ -540,16 +541,16 @@ "id": "f84d8b8e", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:56:43.987277Z", - "iopub.status.busy": "2026-10-01T00:56:43.987081Z", - "iopub.status.idle": "2026-10-01T00:56:44.195755Z", - "shell.execute_reply": "2026-10-01T00:56:44.195307Z" + "iopub.execute_input": "2026-10-04T00:22:51.298050Z", + "iopub.status.busy": "2026-10-04T00:22:51.297822Z", + "iopub.status.idle": "2026-10-04T00:22:51.690346Z", + "shell.execute_reply": "2026-10-04T00:22:51.689125Z" }, "papermill": { - "duration": 0.211176, - "end_time": "2026-10-01T00:56:44.196119+00:00", + "duration": 0.396801, + "end_time": "2026-10-04T00:22:51.692014+00:00", "exception": false, - "start_time": "2026-10-01T00:56:43.984943+00:00", + "start_time": "2026-10-04T00:22:51.295213+00:00", "status": "completed" }, "tags": [] @@ -560,24 +561,30 @@ "output_type": "stream", "text": [ "early L 4/24 trained: zones (30, 32768), d_sae=32768\n", - "early L 4/24 control: zones (30, 32768), d_sae=32768\n", - "mid L12/24 trained: zones (30, 32768), d_sae=32768\n", - "mid L12/24 control: zones (30, 32768), d_sae=32768\n" + "early L 4/24 control: zones (30, 32768), d_sae=32768\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "sae_traces.py:129: UserWarning: trace historique chargee sans 'instrument' ni 'lens' legacy ; infere instrument='sae' depuis les champs presents dans le manifeste (acceptance #4 retro-compat). Migrer l'extracteur GPU pour poser meta['instrument'] canoniquement -- le contrat v1 prefere la declaration explicite a l'inference.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "late L19/24 trained: zones (30, 32768), d_sae=32768\n", - "late L19/24 control: zones (30, 32768), d_sae=32768\n" + "mid L12/24 trained: zones (30, 32768), d_sae=32768\n", + "mid L12/24 control: zones (30, 32768), d_sae=32768\n" ] }, { - "name": "stderr", + "name": "stdout", "output_type": "stream", "text": [ - "sae_traces.py:129: UserWarning: trace historique chargee sans 'instrument' ni 'lens' legacy ; infere instrument='sae' depuis les champs presents dans le manifeste (acceptance #4 retro-compat). Migrer l'extracteur GPU pour poser meta['instrument'] canoniquement -- le contrat v1 prefere la declaration explicite a l'inference.\n" + "late L19/24 trained: zones (30, 32768), d_sae=32768\n", + "late L19/24 control: zones (30, 32768), d_sae=32768\n" ] } ], @@ -599,10 +606,10 @@ "id": "0837910e", "metadata": { "papermill": { - "duration": 0.001364, - "end_time": "2026-10-01T00:56:44.199135+00:00", + "duration": 0.002374, + "end_time": "2026-10-04T00:22:51.698421+00:00", "exception": false, - "start_time": "2026-10-01T00:56:44.197771+00:00", + "start_time": "2026-10-04T00:22:51.696047+00:00", "status": "completed" }, "tags": [] @@ -619,16 +626,16 @@ "id": "f86b63d6", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:56:44.202525Z", - "iopub.status.busy": "2026-10-01T00:56:44.202398Z", - "iopub.status.idle": "2026-10-01T00:58:26.580362Z", - "shell.execute_reply": "2026-10-01T00:58:26.579884Z" + "iopub.execute_input": "2026-10-04T00:22:51.708248Z", + "iopub.status.busy": "2026-10-04T00:22:51.707863Z", + "iopub.status.idle": "2026-10-04T00:26:00.178758Z", + "shell.execute_reply": "2026-10-04T00:26:00.177397Z" }, "papermill": { - "duration": 102.381577, - "end_time": "2026-10-01T00:58:26.582027+00:00", + "duration": 188.480247, + "end_time": "2026-10-04T00:26:00.181634+00:00", "exception": false, - "start_time": "2026-10-01T00:56:44.200450+00:00", + "start_time": "2026-10-04T00:22:51.701387+00:00", "status": "completed" }, "tags": [] @@ -926,10 +933,10 @@ "id": "96d7bbb3", "metadata": { "papermill": { - "duration": 0.001397, - "end_time": "2026-10-01T00:58:26.585001+00:00", + "duration": 0.005508, + "end_time": "2026-10-04T00:26:00.192410+00:00", "exception": false, - "start_time": "2026-10-01T00:58:26.583604+00:00", + "start_time": "2026-10-04T00:26:00.186902+00:00", "status": "completed" }, "tags": [] @@ -946,16 +953,16 @@ "id": "eb7e24fa", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:58:26.588491Z", - "iopub.status.busy": "2026-10-01T00:58:26.588355Z", - "iopub.status.idle": "2026-10-01T00:58:26.640682Z", - "shell.execute_reply": "2026-10-01T00:58:26.640194Z" + "iopub.execute_input": "2026-10-04T00:26:00.205232Z", + "iopub.status.busy": "2026-10-04T00:26:00.204783Z", + "iopub.status.idle": "2026-10-04T00:26:00.349675Z", + "shell.execute_reply": "2026-10-04T00:26:00.348397Z" }, "papermill": { - "duration": 0.054933, - "end_time": "2026-10-01T00:58:26.641371+00:00", + "duration": 0.153556, + "end_time": "2026-10-04T00:26:00.350994+00:00", "exception": false, - "start_time": "2026-10-01T00:58:26.586438+00:00", + "start_time": "2026-10-04T00:26:00.197438+00:00", "status": "completed" }, "tags": [] @@ -1132,10 +1139,10 @@ "id": "9b2abed5", "metadata": { "papermill": { - "duration": 0.001632, - "end_time": "2026-10-01T00:58:26.644701+00:00", + "duration": 0.002184, + "end_time": "2026-10-04T00:26:00.358164+00:00", "exception": false, - "start_time": "2026-10-01T00:58:26.643069+00:00", + "start_time": "2026-10-04T00:26:00.355980+00:00", "status": "completed" }, "tags": [] @@ -1152,16 +1159,16 @@ "id": "1e29b83b", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:58:26.648644Z", - "iopub.status.busy": "2026-10-01T00:58:26.648507Z", - "iopub.status.idle": "2026-10-01T00:58:46.426260Z", - "shell.execute_reply": "2026-10-01T00:58:46.425832Z" + "iopub.execute_input": "2026-10-04T00:26:00.365212Z", + "iopub.status.busy": "2026-10-04T00:26:00.364758Z", + "iopub.status.idle": "2026-10-04T00:26:44.974130Z", + "shell.execute_reply": "2026-10-04T00:26:44.973041Z" }, "papermill": { - "duration": 19.780596, - "end_time": "2026-10-01T00:58:46.426846+00:00", + "duration": 44.618011, + "end_time": "2026-10-04T00:26:44.978464+00:00", "exception": false, - "start_time": "2026-10-01T00:58:26.646250+00:00", + "start_time": "2026-10-04T00:26:00.360453+00:00", "status": "completed" }, "tags": [] @@ -1315,10 +1322,10 @@ "id": "b8bd561f", "metadata": { "papermill": { - "duration": 0.001661, - "end_time": "2026-10-01T00:58:46.430375+00:00", + "duration": 0.004663, + "end_time": "2026-10-04T00:26:44.987185+00:00", "exception": false, - "start_time": "2026-10-01T00:58:46.428714+00:00", + "start_time": "2026-10-04T00:26:44.982522+00:00", "status": "completed" }, "tags": [] @@ -1335,16 +1342,16 @@ "id": "0913b840", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:58:46.434469Z", - "iopub.status.busy": "2026-10-01T00:58:46.434305Z", - "iopub.status.idle": "2026-10-01T00:58:46.438053Z", - "shell.execute_reply": "2026-10-01T00:58:46.437487Z" + "iopub.execute_input": "2026-10-04T00:26:44.997567Z", + "iopub.status.busy": "2026-10-04T00:26:44.997129Z", + "iopub.status.idle": "2026-10-04T00:26:45.002298Z", + "shell.execute_reply": "2026-10-04T00:26:45.001405Z" }, "papermill": { - "duration": 0.006537, - "end_time": "2026-10-01T00:58:46.438508+00:00", + "duration": 0.01217, + "end_time": "2026-10-04T00:26:45.003664+00:00", "exception": false, - "start_time": "2026-10-01T00:58:46.431971+00:00", + "start_time": "2026-10-04T00:26:44.991494+00:00", "status": "completed" }, "tags": [] @@ -1386,10 +1393,10 @@ "id": "37ba970d", "metadata": { "papermill": { - "duration": 0.001606, - "end_time": "2026-10-01T00:58:46.441829+00:00", + "duration": 0.005379, + "end_time": "2026-10-04T00:26:45.014128+00:00", "exception": false, - "start_time": "2026-10-01T00:58:46.440223+00:00", + "start_time": "2026-10-04T00:26:45.008749+00:00", "status": "completed" }, "tags": [] @@ -1408,16 +1415,16 @@ "id": "e9a0020e", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:58:46.446138Z", - "iopub.status.busy": "2026-10-01T00:58:46.445984Z", - "iopub.status.idle": "2026-10-01T00:58:46.449696Z", - "shell.execute_reply": "2026-10-01T00:58:46.449181Z" + "iopub.execute_input": "2026-10-04T00:26:45.022233Z", + "iopub.status.busy": "2026-10-04T00:26:45.021962Z", + "iopub.status.idle": "2026-10-04T00:26:45.027675Z", + "shell.execute_reply": "2026-10-04T00:26:45.026495Z" }, "papermill": { - "duration": 0.006718, - "end_time": "2026-10-01T00:58:46.450331+00:00", + "duration": 0.010825, + "end_time": "2026-10-04T00:26:45.028712+00:00", "exception": false, - "start_time": "2026-10-01T00:58:46.443613+00:00", + "start_time": "2026-10-04T00:26:45.017887+00:00", "status": "completed" }, "tags": [] @@ -1456,10 +1463,10 @@ "id": "eda4ce67", "metadata": { "papermill": { - "duration": 0.001738, - "end_time": "2026-10-01T00:58:46.453701+00:00", + "duration": 0.005432, + "end_time": "2026-10-04T00:26:45.037257+00:00", "exception": false, - "start_time": "2026-10-01T00:58:46.451963+00:00", + "start_time": "2026-10-04T00:26:45.031825+00:00", "status": "completed" }, "tags": [] @@ -1478,16 +1485,16 @@ "id": "60b81135", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:58:46.458132Z", - "iopub.status.busy": "2026-10-01T00:58:46.457791Z", - "iopub.status.idle": "2026-10-01T00:58:46.460904Z", - "shell.execute_reply": "2026-10-01T00:58:46.460442Z" + "iopub.execute_input": "2026-10-04T00:26:45.048596Z", + "iopub.status.busy": "2026-10-04T00:26:45.048275Z", + "iopub.status.idle": "2026-10-04T00:26:45.053796Z", + "shell.execute_reply": "2026-10-04T00:26:45.052358Z" }, "papermill": { - "duration": 0.00596, - "end_time": "2026-10-01T00:58:46.461339+00:00", + "duration": 0.01208, + "end_time": "2026-10-04T00:26:45.055464+00:00", "exception": false, - "start_time": "2026-10-01T00:58:46.455379+00:00", + "start_time": "2026-10-04T00:26:45.043384+00:00", "status": "completed" }, "tags": [] @@ -1518,16 +1525,16 @@ "id": "77582004", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:58:46.465555Z", - "iopub.status.busy": "2026-10-01T00:58:46.465397Z", - "iopub.status.idle": "2026-10-01T00:58:46.468517Z", - "shell.execute_reply": "2026-10-01T00:58:46.467989Z" + "iopub.execute_input": "2026-10-04T00:26:45.064402Z", + "iopub.status.busy": "2026-10-04T00:26:45.063909Z", + "iopub.status.idle": "2026-10-04T00:26:45.069322Z", + "shell.execute_reply": "2026-10-04T00:26:45.067899Z" }, "papermill": { - "duration": 0.005957, - "end_time": "2026-10-01T00:58:46.469005+00:00", + "duration": 0.012096, + "end_time": "2026-10-04T00:26:45.071071+00:00", "exception": false, - "start_time": "2026-10-01T00:58:46.463048+00:00", + "start_time": "2026-10-04T00:26:45.058975+00:00", "status": "completed" }, "tags": [] @@ -1556,16 +1563,16 @@ "id": "9652ba2a", "metadata": { "execution": { - "iopub.execute_input": "2026-10-01T00:58:46.473467Z", - "iopub.status.busy": "2026-10-01T00:58:46.473312Z", - "iopub.status.idle": "2026-10-01T00:58:46.476128Z", - "shell.execute_reply": "2026-10-01T00:58:46.475543Z" + "iopub.execute_input": "2026-10-04T00:26:45.084270Z", + "iopub.status.busy": "2026-10-04T00:26:45.083988Z", + "iopub.status.idle": "2026-10-04T00:26:45.088705Z", + "shell.execute_reply": "2026-10-04T00:26:45.087422Z" }, "papermill": { - "duration": 0.005806, - "end_time": "2026-10-01T00:58:46.476575+00:00", + "duration": 0.013753, + "end_time": "2026-10-04T00:26:45.090753+00:00", "exception": false, - "start_time": "2026-10-01T00:58:46.470769+00:00", + "start_time": "2026-10-04T00:26:45.077000+00:00", "status": "completed" }, "tags": [] @@ -1593,10 +1600,10 @@ "id": "6224753a", "metadata": { "papermill": { - "duration": 0.001684, - "end_time": "2026-10-01T00:58:46.479996+00:00", + "duration": 0.006299, + "end_time": "2026-10-04T00:26:45.102900+00:00", "exception": false, - "start_time": "2026-10-01T00:58:46.478312+00:00", + "start_time": "2026-10-04T00:26:45.096601+00:00", "status": "completed" }, "tags": [] @@ -1609,7 +1616,7 @@ "- [ICT-35-HumorCausalProbe-Pilot-Python](ICT-35-HumorCausalProbe-Pilot-Python.ipynb) — étage 0, baseline de shortcuts lexicaux\n", "- [ICT-35b-HumorCausalPairs-SAE-Python](ICT-35b-HumorCausalPairs-SAE-Python.ipynb) — tranche 1, paires minimales sur SAE\n", "- [ICT-35c-HumorDepthProfile-SAE-Python](ICT-35c-HumorDepthProfile-SAE-Python.ipynb) — tranche 2, le verdict aux trois profondeurs\n", - "- [GameTheory-18d-Humour-Banc-Dur-Python](../../GameTheory/GameTheory-18d-Humour-Banc-Dur-Python.ipynb) — le banc source des paires\n", + "- [GameTheory-18c-Humour-Banc-Python](../../GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb) — le banc consolide (#14032), source des paires\n", "- Sources humor computationnel : `G:\\Mon Drive\\MyIA\\IA\\Bibliographie IA\\MachineLearning\\Computational Humor\\`" ] } @@ -1634,17 +1641,17 @@ }, "papermill": { "default_parameters": {}, - "duration": 125.834391, - "end_time": "2026-10-01T00:58:46.737098+00:00", + "duration": 238.726373, + "end_time": "2026-10-04T00:26:45.654235+00:00", "environment_variables": {}, "exception": null, "input_path": "ICT-35d-HumorTypologyBreakdown-SAE-Python.ipynb", - "output_path": "ICT-35d-HumorTypologyBreakdown-SAE-Python.ipynb", + "output_path": "ICT-35d-HumorTypologyBreakdown-SAE-Python_output.ipynb", "parameters": {}, - "start_time": "2026-10-01T00:56:40.902707+00:00", + "start_time": "2026-10-04T00:22:46.927862+00:00", "version": "2.6.0" } }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/README.md b/MyIA.AI.Notebooks/IIT/ICT-Series/README.md index d37b1f7976..8271c85975 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/README.md +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/README.md @@ -226,7 +226,7 @@ La **strate 5 commence ici** : le substrat mesuré n'est plus un système dynami | [ICT-21b-SAECalibration-Python](ICT-21b-SAECalibration-Python.ipynb) | **Calibration des SAE par echelle** — verite-terrain de reconstruction (FVU corpus, L0 mesure, features mortes) des SAE officiels Qwen-Scope W32K-L0_50 a profondeur appairee (frac 0.5) sur la batterie d'ICT-21 : 31,4 % (1.7B) vs 71,5 % (2B) de variance expliquee (couverture inversee selon l'echelle), L0 = 50.0 exact (garde release passee), largeur effective ~3 % — prealable Phase 0 a toute comparaison cross-echelle de forme *(GPU-free, traces commitees)* | [#8236](https://github.com/jsboige/CoursIA/issues/8236) | | [ICT-21c-SAECatastrophes-Python](ICT-21c-SAECatastrophes-Python.ipynb) | **Catastrophes du dictionnaire SAE — forme & dynamique** (livrable 2 de #8236) — perturbations appariées à trois échelles (1.7B/2B/9B) × deux régimes (trained/control), banc numpy-only sur les traces ICT-21 : forme (Gini, enrichissement top-500 par registre — le trained recrute 2-3× plus de features et les spécialise), dynamique (ablation vives/mortes/aléatoire : f50_vives 0.004→0.07 selon l'échelle trained, path-divergence 0.53-0.82), inoculation **absente** au banc figé (négatif propre), confrontation au FVU réel GPU (L0 constant, fidélité effondrée) *(GPU-free, traces committées)* | [#8236](https://github.com/jsboige/CoursIA/issues/8236) | | [ICT-25-InoculationRL-Python](ICT-25-InoculationRL-Python.ipynb) | **InoculationRL — GRPO à récompense hackable × inoculation** *(GPU)*. Capstone final de la strate 5 et **pont ICT↔PostTraining** : reproduit, dans les poids à échelle jouet, le phénomène de dérive de persona sous récompense hackable (arXiv 2511.18397). Deux bras d'entraînement GRPO identiques sauf le system prompt (N non inoculé / I inoculé), certifié `rewardspy` (le hack est appris dans les deux), panel persona + éval comportementale hors-domaine. Gates 20-21 falsifiables ; résultat négatif honnête possible (« non reproduit à cette échelle ») | [#5105](https://github.com/jsboige/CoursIA/issues/5105) | -| [ICT-35-HumorCausalProbe-Pilot-Python](ICT-35-HumorCausalProbe-Pilot-Python.ipynb) | **HumorCausalProbe-Pilot — étage 0 : baseline de shortcuts lexicaux** *(strate 5, GPU-free)* : substrat HLS (banc humour dur GT-28b, 120 instances annotées), sans confusion explication/mécanisme — l'étage 0 pose la baseline lexicale AVANT toute phase SAE, les phases suivantes restant aval ([#5635](https://github.com/jsboige/CoursIA/issues/5635), [#8236](https://github.com/jsboige/CoursIA/issues/8236), [#5105](https://github.com/jsboige/CoursIA/issues/5105)) | [#14035](https://github.com/jsboige/CoursIA/issues/14035) | +| [ICT-35-HumorCausalProbe-Pilot-Python](ICT-35-HumorCausalProbe-Pilot-Python.ipynb) | **HumorCausalProbe-Pilot — étage 0 : baseline de shortcuts lexicaux** *(strate 5, GPU-free)* : substrat HLS (banc humour dur consolidé GT-18c, 120 instances annotées), sans confusion explication/mécanisme — l'étage 0 pose la baseline lexicale AVANT toute phase SAE, les phases suivantes restant aval ([#5635](https://github.com/jsboige/CoursIA/issues/5635), [#8236](https://github.com/jsboige/CoursIA/issues/8236), [#5105](https://github.com/jsboige/CoursIA/issues/5105)) | [#14035](https://github.com/jsboige/CoursIA/issues/14035) | | [ICT-35b-HumorCausalPairs-SAE-Python](ICT-35b-HumorCausalPairs-SAE-Python.ipynb) | **HumorCausalPairs-SAE — paires minimales, substrat SAE** *(strate 5, tranche 1 de #14035)* : le pilote ICT-35 mesurait l'humour sur un substrat HLS lexical (verdict `INCONCLUSIVE` borné) ; ici le substrat devient le **SAE** Qwen-Scope avec un design expérimental plus fin — des **paires minimales** où seul varie le texte de punchline (humour committé vs punchline neutralisée « unfun », même setup token à token). 30 paires sur les blagues manuelles + 2 one-liners edges du banc GT-24b (instances Argumentum exclues du pairing, champ texte tronqué). Verdict : **INCONCLUSIVE** — amplitude du différentiel trained sous le bruit permuté, top-5 features disjoints du contrôle | [#14035](https://github.com/jsboige/CoursIA/issues/14035) | | [ICT-35c-HumorDepthProfile-SAE-Python](ICT-35c-HumorDepthProfile-SAE-Python.ipynb) | **HumorDepthProfile-SAE — le verdict survit-il à la profondeur ?** *(strate 5, tranche 2 de #14035)* : l'objection à un résultat mesuré à une seule profondeur — une incongruité comique peut être précoce (lexicale, couches 3-8) ou tardive (pragmatique, couches 18-22) — est levée en mesurant les mêmes 30 paires à **trois profondeurs** (early `--layer-frac 0.1667`, mid, late `0.8333`, captures early/late neuves GPU local, contrôle = permutation seedée des input embeddings à chaque couche) | [#14035](https://github.com/jsboige/CoursIA/issues/14035) | | [ICT-35d-HumorTypologyBreakdown-SAE-Python](ICT-35d-HumorTypologyBreakdown-SAE-Python.ipynb) | **HumorTypologyBreakdown-SAE — le verdict survit-il au découpage par type ?** *(strate 5, tranche finale de #14035)* : la dernière objection au verdict INCONCLUSIVE des tranches 1-2 — peut-être les features comiques existent-elles mais seulement dans un sous-type — est levée par l'annotation typologique **figée avant mesure** (13 pun / 12 topical / 5 sociale, plancher 5 par type, 5 cas borderline listés) et la mesure des mêmes statistiques pré-enregistrées sur 18 jambes (3 types × 3 profondeurs × trained/control). Jambes d'inference additionnelles : IC bootstrap 95 % + d de Cohen par type (les IC différentiel et contrôle se recouvrent partout) et contrôle familial du max \|z\| (sign-flip intra-paire). Verdict final : **AUCUNE_FEATURE_STABLE** — 0 jambe candidate, p_familial ≥ 0.116 partout, Phase 2 (levée causale) structurellement vide *(GPU-free, traces committées)* | [#14035](https://github.com/jsboige/CoursIA/issues/14035) | diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ict/humor_pairs.py b/MyIA.AI.Notebooks/IIT/ICT-Series/ict/humor_pairs.py index 7290e33cdf..6d11f10d57 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ict/humor_pairs.py +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ict/humor_pairs.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- """Couche d'acces au corpus humour consolide (CORPUS_DUR) pour #14035. -Reproduit le geste du pilote ICT-35 : les cellules code [0..10] de -``GameTheory-18d-Humour-Banc-Dur-Python.ipynb`` sont executees dans un namespace -isole, sans editer le notebook source, et ``CORPUS_DUR`` en est extrait. -La source de verite reste le notebook GT-24b, jamais copie. +Reproduit le geste du pilote ICT-35 : les cellules code [26..33] de la section +echelle de ``GameTheory-18c-Humour-Banc-Python.ipynb`` (absorption #14032) sont +executees dans un namespace isole, sans editer le notebook source, et +``CORPUS_DUR`` en est extrait. La source de verite reste le banc humour, jamais copie. """ from __future__ import annotations @@ -17,7 +17,7 @@ from pathlib import Path from typing import Any, Iterator -# Taxonomie de labels du banc consolide (GT-24b, verifiee sur le pilote ICT-35). +# Taxonomie de labels du banc consolide (verifiee sur le pilote ICT-35). LABELS: tuple[str, ...] = ( "humour_reussi", "rire_sans_recadrage", @@ -26,11 +26,12 @@ "rien", ) -# Derniere cellule code de GT-24b a executer : CORPUS_DUR est construit dans -# la cellule 10 (mesure firsthand sur le notebook source). -_CORPUS_CELL_END = 10 +# Plage de cellules code de la section echelle du banc consolide a executer : +# CORPUS_DUR est construit dans la cellule 33 (mesure firsthand, #14032). +_CORPUS_CELL_START = 26 +_CORPUS_CELL_END = 33 -# Champs du contrat d'instance (GT-24b cellule 10, verbe du banc). +# Champs du contrat d'instance (banc consolide cellule 33, verbe du banc). _REQUIRED_FIELDS = ("id", "texte", "features", "label", "justification", "source") @@ -39,14 +40,14 @@ def gt24b_path() -> Path: return ( Path(__file__).resolve().parents[3] / "GameTheory" - / "GameTheory-18d-Humour-Banc-Dur-Python.ipynb" + / "GameTheory-18c-Humour-Banc-Python.ipynb" # consolide #14032 ) def _corpus_cwd() -> Path: """Repertoire d'execution reproduisant le cwd du pilote ICT-35. - La cellule 4 de GT-24b resout son cache Argumentum en chemin RELATIF + La cellule 29 du banc consolide resout son cache Argumentum en chemin RELATIF (``Path("argumentum_scenarii.csv")``) : selon le cwd, elle fait un hit cache ou declenche un fetch GitHub raw. Le cache du pilote vit dans le dossier ICT-Series ; a defaut on retombe sur le dossier du notebook @@ -71,8 +72,8 @@ def _cwd(path: Path) -> Iterator[None]: def load_corpus_dur(path: Path | None = None) -> list[dict[str, Any]]: """Charge ``CORPUS_DUR`` en executant les cellules de GT-24b. - Reproduction deterministe (``random.seed(42)`` est pose par GT-24b - lui-meme dans la cellule 10) ; le notebook source n'est jamais modifie. + Reproduction deterministe (``random.seed(42)`` est pose par le banc + lui-meme dans la cellule 33) ; le notebook source n'est jamais modifie. L'exec se fait dans le cwd portant le cache Argumentum (cf :func:`_corpus_cwd`) pour ne pas dependre du repertoire appelant. """ @@ -81,7 +82,7 @@ def load_corpus_dur(path: Path | None = None) -> list[dict[str, Any]]: ns: dict[str, Any] = {} with _cwd(_corpus_cwd()): for i, cell in enumerate(nb["cells"]): - if cell["cell_type"] == "code" and i <= _CORPUS_CELL_END: + if cell["cell_type"] == "code" and _CORPUS_CELL_START <= i <= _CORPUS_CELL_END: exec("".join(cell["source"]), ns) # noqa: S102 - reproduction, motif du pilote ICT-35 cell[3] corpus = ns["CORPUS_DUR"] validate_corpus(corpus) @@ -113,7 +114,8 @@ def label_distribution(corpus: list[dict[str, Any]]) -> Counter: # --------------------------------------------------------------------------- # # Edits main : (setup verbatim, punchline verbatim, punchline_neutre, controle). -# - setup + punchline = le texte COMMITTE de l'instance (source de verite GT-24b), +# - setup + punchline = le texte COMMITTE de l'instance (source de verite : le +# banc humour consolide), # re-verifie au chargement (span unique, suffixe exact). # - punchline_neutre : continuation coherente attendue — tue l'incongruite, # conserve le lexique du registre, taille comparable. @@ -153,7 +155,7 @@ def label_distribution(corpus: list[dict[str, Any]]) -> Counter: "joke-p29": ("Les submodules Git, c'est comme les voisins : ", "mieux vaut ne pas les déranger.", "on les voit rarement.", "ils prennent de la place."), "joke-p30": ("Il était une fois un UTF-8 qui ne savait pas où était la fin. ", "Il était perdu dans un BOM.", "Il attendait son dernier octet.", "Il cherchait son marqueur de fin."), # Top-up a >=30 : les instances Argumentum sont TRONQUEES a ~150 c. par le - # banc GT-24b (punchline jamais committée) — inutilisables. Les one-liners + # banc humour (punchline jamais committée) — inutilisables. Les one-liners # edge-04/05 (label recadrage_sans_rire : incongruite vive, annotateur n'a # pas ri) completent — heterogeneite de label documentée, l'incongruite # portee par le texte est le critere du pairing. diff --git a/_quarto.yml b/_quarto.yml index 232a67c74d..96609ec8da 100644 --- a/_quarto.yml +++ b/_quarto.yml @@ -790,7 +790,6 @@ project: - "MyIA.AI.Notebooks/GameTheory/GameTheory-18-Open-Games-et-Lentilles-Python.ipynb" - "MyIA.AI.Notebooks/GameTheory/GameTheory-18b-Casser-la-Composition-Python.ipynb" - "MyIA.AI.Notebooks/GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb" - - "MyIA.AI.Notebooks/GameTheory/GameTheory-18d-Humour-Banc-Dur-Python.ipynb" - "MyIA.AI.Notebooks/GameTheory/GameTheory-19-Abstraction-a-Dette-Python.ipynb" - "MyIA.AI.Notebooks/GameTheory/GameTheory-20-Chemin-Minimal-Robinson-Goforth-Python.ipynb" - "MyIA.AI.Notebooks/GameTheory/GameTheory-20b-Chemin-Minimal-Temoins-Impossibilite-Python.ipynb" @@ -2192,4 +2191,4 @@ execute: echo: true warning: false -notebook-preview: false \ No newline at end of file +notebook-preview: false diff --git a/docs/curriculum/recherche.md b/docs/curriculum/recherche.md index 4783060e50..a078cb9ea4 100644 --- a/docs/curriculum/recherche.md +++ b/docs/curriculum/recherche.md @@ -1,368 +1,367 @@ - - -# Recherche Avancée - -**Inférence probabiliste, IIT et RL avancée** - -Inférence probabiliste (Infer.NET, Pyro, PyMC), théorie de l'information intégrée (IIT), reinforcement learning avancé, théorie des jeux (OpenSpiel). Pour étudiants en master/recherche. - -## Statistiques - -| Métrique | Valeur | -|----------|--------| -| Notebooks | 297 | -| PRODUCTION | 0 | -| BETA | 286 | -| ALPHA | 11 | - -## GameTheory (95 notebooks) - -| # | Notebook | Maturité | Exécutable | -|---|----------|----------|------------| -| 1 | [GameTheory-01-Setup-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-01-Setup-Python.ipynb) | BETA | Non | -| 2 | [GameTheory-2 : Jeux sous forme normale (C# / .NET) —…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-02-NormalForm-CSharp.ipynb) | BETA | Oui | -| 3 | [GameTheory-2 (Part 2) : Support Enumeration — Équilibre…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-02-NormalForm-Part2-CSharp.ipynb) | BETA | Oui | -| 4 | [GameTheory-2 (Part 2) : Support Enumeration — Équilibre…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-02-NormalForm-Part2-Python.ipynb) | BETA | Oui | -| 5 | [GameTheory-02-NormalForm-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-02-NormalForm-Python.ipynb) | BETA | Oui | -| 6 | [GameTheory 2b - Formalisation Lean : Definitions de…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-02b-Lean-Definitions-Lean.ipynb) | BETA | Non | -| 7 | [GameTheory-02c : Traveler's Dilemma en C# — le twin qui…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-02c-Travelers-Dilemma-CSharp.ipynb) | BETA | Oui | -| 8 | [GameTheory-02c-Travelers-Dilemma-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-02c-Travelers-Dilemma-Python.ipynb) | BETA | Oui | -| 9 | [GameTheory-3 : Topologie des Jeux 2×2 — Twin C#…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-03-Topology2x2-CSharp.ipynb) | BETA | Oui | -| 10 | [GameTheory-03-Topology2x2-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-03-Topology2x2-Python.ipynb) | BETA | Oui | -| 11 | [GameTheory-3a — Chemins de swaps : à quelle distance…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-03b-Chemins-de-Swaps-Lean-Python.ipynb) | BETA | Non | -| 12 | [GameTheory 3b : Chambres, murs, codimension — les jeux…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-03c-Chambres-et-Murs-Python.ipynb) | BETA | Oui | -| 13 | [GameTheory-3c — Le joueur LLM dans le tableau…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-03d-Le-Joueur-LLM-Python.ipynb) | BETA | Non | -| 14 | [GameTheory-03d — Biens publics non-lineaires : plan de…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-03e-Plan-de-deformation-Python.ipynb) | BETA | Oui | -| 15 | [GameTheory 3e : Meta-Actions Tarifees et Parcours…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-03f-Meta-Actions-Tarifees-Python.ipynb) | BETA | Oui | -| 16 | [GameTheory-03h — Deux espèces de flèches : quand une…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-03g-Deux-Especes-de-Fleches-Python.ipynb) | BETA | Oui | -| 17 | [GameTheory-04-NashEquilibrium-Python (C#)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-04-NashEquilibrium-CSharp.ipynb) | BETA | Oui | -| 18 | [GameTheory-04-NashEquilibrium-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-04-NashEquilibrium-Python.ipynb) | BETA | Oui | -| 19 | [GameTheory 4b - Theoreme d'Existence de Nash (Lean)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-04b-Lean-NashExistence-Lean.ipynb) | BETA | Non | -| 20 | [GameTheory 4c - Théorème d'Existence de Nash (C#)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-04c-NashExistence-CSharp.ipynb) | ALPHA | Oui | -| 21 | [GameTheory 4c - Theoreme d'Existence de Nash (Python)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-04c-NashExistence-Python.ipynb) | BETA | Non | -| 22 | [GameTheory-04d-Marchandage-Asymetrique-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-04d-Marchandage-Asymetrique-Python.ipynb) | ALPHA | Oui | -| 23 | [GameTheory 04e — Oracles réflexifs, décision causale et…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-04e-Reflective-Oracles-Python.ipynb) | BETA | Oui | -| 24 | [GameTheory 04f — Théories de la décision face à un…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-04f-Theories-Decision-Predicteur-Python.ipynb) | BETA | Oui | -| 25 | [GameTheory-05-ZeroSum-Minimax-Python (Twin C#)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-05-ZeroSum-Minimax-CSharp.ipynb) | BETA | Oui | -| 26 | [GameTheory-05-ZeroSum-Minimax-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-05-ZeroSum-Minimax-Python.ipynb) | BETA | Oui | -| 27 | [GameTheory-5b — Théorème minimax de von Neumann…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-05b-Lean-Minimax-Lean.ipynb) | BETA | Non | -| 28 | [GameTheory-6 : Évolution et Confiance — Twin C#…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06-EvolutionTrust-CSharp.ipynb) | BETA | Oui | -| 29 | [GameTheory-06-EvolutionTrust-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06-EvolutionTrust-Python.ipynb) | BETA | Oui | -| 30 | [GameTheory-6c (C#) : Jeux Répétés et Théorème Folk](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06c-RepeatedGames-FolkTheorem-CSharp.ipynb) | BETA | Oui | -| 31 | [GameTheory-6c : Jeux Répétés et Théorème Folk (Folk…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06c-RepeatedGames-FolkTheorem-Python.ipynb) | BETA | Oui | -| 32 | [GameTheory-06d : Sympathie contre Engagement — la…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06d-Sympathie-vs-Engagement-Python.ipynb) | BETA | Oui | -| 33 | [GameTheory-06e : Transparence des programmes et issue…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06e-Open-Source-Game-Theory-Python.ipynb) | ALPHA | Oui | -| 34 | [GameTheory-06g — Agents à budget explicite (companion…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06f-Bounded-Agents-Lean.ipynb) | BETA | Non | -| 35 | [GameTheory-06g — Équilibres de jeux-programmes fondés…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06g-Simulation-Based-Program-Equilibria-Python.ipynb) | BETA | Oui | -| 36 | [GameTheory-06h — Programmes transparents comme…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06h-Transparent-Institutions-Python.ipynb) | BETA | Oui | -| 37 | [GameTheory-06i — Ensembles limites : Poincaré-Bendixson…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06i-Ensembles-Limites-Poincare-Bendixson-Python.ipynb) | BETA | Oui | -| 38 | [GameTheory-06f — Preuves bornees et cout du…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06j-Bounded-Proofs-Reasoning-Costs-Python.ipynb) | BETA | Oui | -| 39 | [GameTheory-07-ExtensiveForm-Python (Twin C#)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-07-ExtensiveForm-CSharp.ipynb) | BETA | Oui | -| 40 | [GameTheory-07-ExtensiveForm-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-07-ExtensiveForm-Python.ipynb) | BETA | Oui | -| 41 | [GameTheory 8 - Jeux Combinatoires (Twin C#)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-08-CombinatorialGames-CSharp.ipynb) | BETA | Oui | -| 42 | [GameTheory 8 - Jeux Combinatoires](../../MyIA.AI.Notebooks/GameTheory/GameTheory-08-CombinatorialGames-Python.ipynb) | BETA | Oui | -| 43 | [GameTheory 8b - Jeux Combinatoires en Lean](../../MyIA.AI.Notebooks/GameTheory/GameTheory-08b-Lean-CombinatorialGames-Lean.ipynb) | BETA | Non | -| 44 | [GameTheory 8c - Jeux Combinatoires : Approfondissement…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-08c-CombinatorialGames-CSharp.ipynb) | BETA | Oui | -| 45 | [GameTheory 8c - Jeux Combinatoires : Approfondissement…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-08c-CombinatorialGames-Python.ipynb) | BETA | Oui | -| 46 | [GameTheory 8d - Combinatorial Games natif : le lake…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-08d-Lean-CGT-Lean.ipynb) | BETA | Non | -| 47 | [GameTheory-09-BackwardInduction-Python (C#)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-09-BackwardInduction-CSharp.ipynb) | BETA | Oui | -| 48 | [GameTheory-09-BackwardInduction-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-09-BackwardInduction-Python.ipynb) | BETA | Oui | -| 49 | [Stackelberg : la performativité sans mystère](../../MyIA.AI.Notebooks/GameTheory/GameTheory-09b-Commitment-Stackelberg-Python.ipynb) | BETA | Oui | -| 50 | [GameTheory-09c : Stackelberg Security Game —…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-09c-Stackelberg-SecurityGame-Python.ipynb) | BETA | Oui | -| 51 | [GameTheory-10 — Équilibres Parfaits de Sous-Jeux et…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-10-ForwardInduction-SPE-CSharp.ipynb) | BETA | Oui | -| 52 | [GameTheory-10-ForwardInduction-SPE-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-10-ForwardInduction-SPE-Python.ipynb) | BETA | Oui | -| 53 | [GameTheory-11-BayesianGames-CSharp](../../MyIA.AI.Notebooks/GameTheory/GameTheory-11-BayesianGames-CSharp.ipynb) | BETA | Oui | -| 54 | [GameTheory-11-BayesianGames-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-11-BayesianGames-Python.ipynb) | BETA | Oui | -| 55 | [GameTheory-11b — Jeux Bayésiens en Lean 4 (companion)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-11b-Lean-BayesianGamesExt-Lean.ipynb) | BETA | Non | -| 56 | [GameTheory-12 — Jeux de Réputation (twin C# du notebook…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-12-ReputationGames-CSharp.ipynb) | BETA | Oui | -| 57 | [GameTheory-12-ReputationGames-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-12-ReputationGames-Python.ipynb) | BETA | Oui | -| 58 | [GameTheory-13 : Jeux a Information Imparfaite et CFR…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-13-ImperfectInfo-CFR-CSharp.ipynb) | BETA | Oui | -| 59 | [GameTheory-13 : Jeux a Information Imparfaite et CFR](../../MyIA.AI.Notebooks/GameTheory/GameTheory-13-ImperfectInfo-CFR-Python.ipynb) | BETA | Non | -| 60 | [GameTheory-13b : Safe Subgame Solving -- quand le…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-13b-Safe-Subgame-Solving-Python.ipynb) | BETA | Oui | -| 61 | [GameTheory-13c : Safe Subgame Solving en C# — le twin…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-13c-Safe-Subgame-Solving-CSharp.ipynb) | BETA | Oui | -| 62 | [GameTheory-13d : Optimistic Counterfactual Regret…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-13d-Optimistic-CFR-Python.ipynb) | BETA | Oui | -| 63 | [GameTheory-14 : Jeux Differentiels et Equilibres de…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-14-DifferentialGames-CSharp.ipynb) | BETA | Oui | -| 64 | [GameTheory-14 : Jeux Differentiels et Equilibres de…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-14-DifferentialGames-Python.ipynb) | BETA | Oui | -| 65 | [GameTheory-15 — Jeux Coopératifs (Twin C#)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-15-CooperativeGames-CSharp.ipynb) | BETA | Oui | -| 66 | [GameTheory-15-CooperativeGames-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-15-CooperativeGames-Python.ipynb) | BETA | Oui | -| 67 | [GameTheory 15b - Jeux Cooperatifs en Lean :…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-15b-Lean-CooperativeGames-Lean.ipynb) | BETA | Non | -| 68 | [GameTheory 15c - Jeux Cooperatifs (C# / .NET)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-15c-CooperativeGames-CSharp.ipynb) | BETA | Oui | -| 69 | [GameTheory 15c - Jeux Cooperatifs Lean (Python)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-15c-CooperativeGames-Python.ipynb) | BETA | Oui | -| 70 | [GameTheory 15d - La decomposition de Mobius sur le…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-15d-Mobius-Coalitions-Lean-Python.ipynb) | BETA | Non | -| 71 | [GameTheory-15e — Pouvoir coalitionnel : calcul, SMT…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-15e-Coalition-Power-SMT-Python.ipynb) | BETA | Oui | -| 72 | [GameTheory 15f - Valeur de Shapley de groupe : évaluer…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-15f-Shapley-Groupes-Python.ipynb) | BETA | Oui | -| 73 | [GameTheory 15g - Assistance Games (résultat 2026)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-15g-AssistanceGames-2026-Python.ipynb) | BETA | Oui | -| 74 | [GameTheory-16-MechanismDesign-Python (C#)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-16-MechanismDesign-CSharp.ipynb) | BETA | Oui | -| 75 | [GameTheory-16 : Théorie des Mécanismes et Principe de…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-16-MechanismDesign-Python.ipynb) | BETA | Oui | -| 76 | [GameTheory-16b : Automated Mechanism Design (AMD)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-16b-Automated-Mechanism-Design-Python.ipynb) | BETA | Oui | -| 77 | [GameTheory-16c : La dimension paiement que le designer…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-16c-Extraction-de-Revenu-DSIC-IR-Python.ipynb) | BETA | Oui | -| 78 | [GameTheory-16d — L'echange de reins : de la valeur…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-16d-Echange-de-Reins-Lean-Python.ipynb) | BETA | Non | -| 79 | [GameTheory-16e : Pilote — joueurs LLM hétérogènes sur…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-16e-LLM-Players-Othman-Sandholm-Python.ipynb) | BETA | Non | -| 80 | [GameTheory 23b — Le lake assignment_lean par son…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-16f-Lean-Assignment-Lean.ipynb) | BETA | Non | -| 81 | [GameTheory-23 — L'algorithme de Kuhn-Munkres :…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-16f-Munkres-Assignment-Python.ipynb) | BETA | Oui | -| 82 | [GameTheory-17 (C#) : Multi-Agent Reinforcement Learning…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-17-MultiAgent-RL-CSharp.ipynb) | BETA | Oui | -| 83 | [GameTheory-17 : Apprentissage par Renforcement…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-17-MultiAgent-RL-Python.ipynb) | BETA | Oui | -| 84 | [Information asymétrique : types privés, antisélection…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-17b-Asymmetric-Information-Python.ipynb) | BETA | Oui | -| 85 | [Le marché des lemons : le certificat formel exécuté](../../MyIA.AI.Notebooks/GameTheory/GameTheory-17c-Lean-Lemons-Certificat-Lean.ipynb) | BETA | Non | -| 86 | [Screening, signal et anticipation : les trois réponses…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-17d-Lean-Screening-Signaling-Lean.ipynb) | BETA | Non | -| 87 | [Du marché au bilan : le pont théorie des jeux théorie…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-17f-Market-to-Balance-Sheet-Python.ipynb) | BETA | Oui | -| 88 | [GameTheory-18 : Open Games et Lentilles -- la…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-18-Open-Games-et-Lentilles-Python.ipynb) | BETA | Oui | -| 89 | [GameTheory-18b : Casser la composition — où la…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-18b-Casser-la-Composition-Python.ipynb) | BETA | Oui | -| 90 | [GameTheory-24 : Banc de calibration — humour, forme…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb) | BETA | Oui | -| 91 | [GameTheory-18d : Banc humour — passer à l'échelle](../../MyIA.AI.Notebooks/GameTheory/GameTheory-18d-Humour-Banc-Dur-Python.ipynb) | BETA | Non | -| 92 | [GameTheory-19 : L'abstraction a dette mesurable](../../MyIA.AI.Notebooks/GameTheory/GameTheory-19-Abstraction-a-Dette-Python.ipynb) | BETA | Oui | -| 93 | [GameTheory 24b : Le temoin d'impossibilite](../../MyIA.AI.Notebooks/GameTheory/GameTheory-20b-Chemin-Minimal-Temoins-Impossibilite-Python.ipynb) | BETA | Oui | -| 94 | [GameTheory 20c : Le chemin minimal sur un second…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-20c-Chemin-Minimal-3x2-Ordinal-Python.ipynb) | BETA | Oui | -| 95 | [GameTheory-21 — Loi II, seconde jambe : synthétiser un…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-20d-Loi-II-Translateur-Life-Python.ipynb) | BETA | Oui | - -## GameTheory/SocialChoice (10 notebooks) - -| # | Notebook | Maturité | Exécutable | -|---|----------|----------|------------| -| 1 | [SocialChoice 01 : Théorème d'impossibilité d'Arrow…](../../MyIA.AI.Notebooks/GameTheory/SocialChoice/01-Arrow-Impossibility-Theorem-Csharp.ipynb) | BETA | Oui | -| 2 | [SocialChoice 01 - Theoreme d'Arrow : Preuve Formelle et…](../../MyIA.AI.Notebooks/GameTheory/SocialChoice/01-Arrow-Impossibility-Theorem.ipynb) | BETA | Oui | -| 3 | [SocialChoice 01b - Choix Social Formel en Lean 4](../../MyIA.AI.Notebooks/GameTheory/SocialChoice/01b-Lean-SocialChoice-Formal.ipynb) | ALPHA | Non | -| 4 | [SocialChoice 03 : Méthodes de Vote et Paradoxes (twin…](../../MyIA.AI.Notebooks/GameTheory/SocialChoice/03-Voting-Methods-Csharp.ipynb) | ALPHA | Oui | -| 5 | [SocialChoice 03 - Méthodes de Vote et Paradoxes](../../MyIA.AI.Notebooks/GameTheory/SocialChoice/03-Voting-Methods.ipynb) | BETA | Oui | -| 6 | [SocialChoice 04 : Agregation Computationnelle - SAT et…](../../MyIA.AI.Notebooks/GameTheory/SocialChoice/04-Computational-Aggregation-SAT-Z3-Csharp.ipynb) | BETA | Oui | -| 7 | [SocialChoice 04 - Agrégation Computationnelle : SAT et…](../../MyIA.AI.Notebooks/GameTheory/SocialChoice/04-Computational-Aggregation-SAT-Z3.ipynb) | BETA | Oui | -| 8 | [SocialChoice-05 : Gibbard-Satterthwaite sans mystere -…](../../MyIA.AI.Notebooks/GameTheory/SocialChoice/05-Gibbard-Satterthwaite.ipynb) | BETA | Oui | -| 9 | [SocialChoice-06 : Mobius sur le treillis des coalitions…](../../MyIA.AI.Notebooks/GameTheory/SocialChoice/06-Mobius-Aggregation-Pouvoir-Manipulation.ipynb) | BETA | Oui | -| 10 | [07 - Élections de comité par approbation : le core…](../../MyIA.AI.Notebooks/GameTheory/SocialChoice/07-Committees-Core.ipynb) | BETA | Oui | - -## IIT (6 notebooks) - -| # | Notebook | Maturité | Exécutable | -|---|----------|----------|------------| -| 1 | [IIT - Introduction à PyPhi et Integrated Information…](../../MyIA.AI.Notebooks/IIT/IIT-01-IntroToPyPhi.ipynb) | BETA | Oui | -| 2 | [IIT - Sujets Avances : Partitionnement, Repertoires…](../../MyIA.AI.Notebooks/IIT/IIT-02-AdvancedTopics.ipynb) | BETA | Oui | -| 3 | [IIT-3. Coarse-graining, blackboxing et l'échelle du…](../../MyIA.AI.Notebooks/IIT/IIT-03-CoarseGrainingMacroPhi.ipynb) | BETA | Oui | -| 4 | [IIT-4. Le problème de frontière — qui décide où sont…](../../MyIA.AI.Notebooks/IIT/IIT-04-Le-Probleme-de-Frontiere.ipynb) | BETA | Oui | -| 5 | [IIT-5. Les lentilles de conscience comme bancs de…](../../MyIA.AI.Notebooks/IIT/IIT-05-Lentilles-et-Dissociations.ipynb) | BETA | Oui | -| 6 | [IIT-6. L'objet qui a mordu IIT — l'expander à Φ énorme,…](../../MyIA.AI.Notebooks/IIT/IIT-06-L-Objet-qui-a-Mordu-IIT.ipynb) | BETA | Oui | - -## IIT/ICT-Series (75 notebooks) - -| # | Notebook | Maturité | Exécutable | -|---|----------|----------|------------| -| 1 | [ICT-1 — Trajectoires de $\Phi$](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-01-PhiTrajectories-Python.ipynb) | BETA | Oui | -| 2 | [ICT-2 — Le tri comme morphogenèse minimale…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-02-SelfSortingMorphogenesis-Python.ipynb) | BETA | Oui | -| 3 | [ICT-3 — Robustesse & délai de gratification : étude…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-03-RobustnessDelayedGratification-Python.ipynb) | BETA | Oui | -| 4 | [ICT-4 — Tableaux chimériques & agrégation émergente («…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-04-ChimericArraysKinAggregation-Python.ipynb) | BETA | Oui | -| 5 | [ICT-5 : Émergence causale — quelle échelle décrit le…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-05-CausalEmergence-Python.ipynb) | BETA | Oui | -| 6 | [ICT-6 — Du tri a la chaîne de Markov : emergence…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-06-SortingToTPM-CausalEmergence-Python.ipynb) | BETA | Oui | -| 7 | [ICT-7 — Signatures *scale-free* & criticalite](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-07-ScaleFreeSignatures-Python.ipynb) | BETA | Oui | -| 8 | [ICT-8 — Paysages d'attracteurs & signaux precurseurs :…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-08-AttractorLandscapesEWS-Python.ipynb) | BETA | Oui | -| 9 | [ICT-9 — Agence & regeneration : *reparer sa forme, ou…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-09-AgencyRegeneration-Python.ipynb) | BETA | Oui | -| 10 | [ICT-10 — Grammaire des catastrophes : *l'obstacle qui…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-10-CatastropheGrammar-Python.ipynb) | BETA | Oui | -| 11 | [ICT-11 — Profils d'agence causale : à quelle échelle…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-11-CausalAgencyProfiles-Python.ipynb) | BETA | Oui | -| 12 | [ICT-12 — Champs de valence et animats : rôles mesures,…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-12-ValenceFieldsAndAnimats-Python.ipynb) | BETA | Oui | -| 13 | [ICT-12b — Valence APPRISE, transferable, reversible :…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-12b-LearnedValence-Python.ipynb) | BETA | Oui | -| 14 | [ICT-12c — Animat prégnance/valence incarné : la…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-12c-PregnanceAnimat-Python.ipynb) | BETA | Oui | -| 15 | [ICT-12d — Animat inhibé (Laborit) : contrôlabilité,…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-12d-InhibitedActionAnimat-Python.ipynb) | BETA | Oui | -| 16 | [ICT-12e — Valeur de l'information pour l'animat incarné…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-12e-Value-of-Information-Animat-Python.ipynb) | BETA | Oui | -| 17 | [ICT-13 — Morphodynamique stratégique : une stratégie…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-13-AxelrodStrategicMorphodynamics-Python.ipynb) | BETA | Oui | -| 18 | [ICT-13b — Décroisement dynamique × observable : d'où…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-13b-DecroisementDynamiqueObservable-Python.ipynb) | ALPHA | Oui | -| 19 | [ICT-14 — Énergie libre et surprise du représentant…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-14-FreeEnergySurprise-Python.ipynb) | BETA | Oui | -| 20 | [ICT-15 — Integrated Complexity : convergence Φ / F / K…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15-IntegratedComplexity-Python.ipynb) | BETA | Oui | -| 21 | [ICT-15c — Méta-proxy d'obstruction : structure des…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15c-MetaProxyObstruction-Python.ipynb) | BETA | Oui | -| 22 | [ICT-15d — Cochaîne de Čech pondérée : obstruction…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15d-CechObstruction-Python.ipynb) | BETA | Oui | -| 23 | [ICT-15e -- Bridge #2 : recouvrabilite *est* agentivite…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15e-Bridge2-RecoverabilityAgency-Python.ipynb) | BETA | Oui | -| 24 | [ICT-15f -- Pont #1-bis : la famille decouplee tranche…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15f-Bridge1bis-DecoupledFamily-Python.ipynb) | BETA | Oui | -| 25 | [ICT-15h -- Pont #1-bis (chantier 2/3) : le regime…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15h-Bridge1bis-AsymmetricFamily-Python.ipynb) | BETA | Oui | -| 26 | [ICT-15i -- Pont #1-bis : le paysage 2D anisotrope clot…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15i-Bridge1bis-2DLandscape-Python.ipynb) | BETA | Oui | -| 27 | [ICT-15j — Discriminant Čech par nerf simplicial (gudhi)](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15j-NerveDiscriminant-Python.ipynb) | BETA | Oui | -| 28 | [ICT-15k — Recollement des macrocells : le quadtree de…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15k-RecollementMacroCells-Python.ipynb) | BETA | Oui | -| 29 | [ICT-15l — Indépendance au générateur de nouveauté : le…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15l-IndependanceGenerateur-Python.ipynb) | BETA | Oui | -| 30 | [ICT-16 — MDL / code en deux parties et bosse…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-16-MDLTwoPartCode-Python.ipynb) | BETA | Oui | -| 31 | [ICT-17b — Grokking et compression-progress : la jambe K…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-17b-Grokking-CompressionProgress-Python.ipynb) | BETA | Oui | -| 32 | [ICT-18 -- Fleche du temps et reversibilisation (strate…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-18-ArrowOfTimeReversibilization-Python.ipynb) | BETA | Oui | -| 33 | [ICT-18b — Budget de réversibilité : la jambe « fin » de…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-18b-ReversibilityBudget-Python.ipynb) | BETA | Oui | -| 34 | [ICT-19 — La batterie de l'ENJEU : auto-maintien vs pur…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-19-EnjeuBattery-Python.ipynb) | BETA | Oui | -| 35 | [ICT-19b — Raffinement et résolution des stubs (tranche…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-19b-EnjeuBattery-Raffinement-Python.ipynb) | BETA | Non | -| 36 | [ICT-20 — FeatureCatastrophes : *calibration de méthode*](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-20-FeatureCatastrophes-Python.ipynb) | BETA | Non | -| 37 | [ICT-21 — SAETrajectoires : le substrat S4 entre au banc](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-21-SAETrajectoires-Python.ipynb) | BETA | Non | -| 38 | [ICT-21b-SAECalibration-Python — que reconstruit…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-21b-SAECalibration-Python.ipynb) | BETA | Non | -| 39 | [ICT-21c-SAECatastrophes-Python — forme et dynamique des…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-21c-SAECatastrophes-Python.ipynb) | BETA | Non | -| 40 | [ICT-22 — LLMSubstrat : le transformer comme quatrième…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-22-LLMSubstrat-Python.ipynb) | BETA | Non | -| 41 | [ICT-22b -- Moteur d'intervention causal : operer,…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-22b-CausalInterventionEngine-Python.ipynb) | BETA | Non | -| 42 | [ICT-23 — PersonaCatastrophe : la fronce de Thom…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-23-PersonaCatastrophe-Python.ipynb) | BETA | Oui | -| 43 | [ICT-24 — WorkspaceIgnition : l'axe Global Workspace et…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-24-WorkspaceIgnition-Python.ipynb) | BETA | Non | -| 44 | [ICT-25 — InoculationRL : GRPO à récompense *hackable*,…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-25-InoculationRL-Python.ipynb) | BETA | Non | -| 45 | [ICT-26 — Convention de signalisation (expérience A,…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-26-SignalingConvention-Python.ipynb) | BETA | Oui | -| 46 | [ICT-27 — Invention de symboles (expérience B, strate 7)](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-27-SymbolInvention-Python.ipynb) | BETA | Oui | -| 47 | [ICT-28 — Adoption collective et seuil de performativité…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-28-CollectiveAdoption-Python.ipynb) | BETA | Oui | -| 48 | [ICT-30 — Invention inhibée (expérience E, strate 7)](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-30-InhibitedInvention-Python.ipynb) | BETA | Oui | -| 49 | [ICT-31 — Le contraste mesuré à trois substrats :…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-31-ContrasteTroisSubstrats-Python.ipynb) | BETA | Oui | -| 50 | [ICT-32 — Stratification causale du Jeu de la Vie :…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-32-StratificationCausaleLife-Python.ipynb) | BETA | Oui | -| 51 | [ICT-33 — Ensembles ouverts : soupes, collisions, et la…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-33-SoupCollisions-Python.ipynb) | BETA | Oui | -| 52 | [ICT-34 — Le banc de recollement des lectures : quatre…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-34-BancRecollementLectures-Python.ipynb) | BETA | Oui | -| 53 | [ICT-35 -- HumorCausalProbe-Pilot : substrat HLS, sans…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35-HumorCausalProbe-Pilot-Python.ipynb) | BETA | Non | -| 54 | [ICT-35b -- HumorCausalPairs-SAE : paires minimales,…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35b-HumorCausalPairs-SAE-Python.ipynb) | BETA | Non | -| 55 | [ICT-35c -- HumorDepthProfile-SAE : le verdict survit-il…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35c-HumorDepthProfile-SAE-Python.ipynb) | BETA | Oui | -| 56 | [ICT-35d -- HumorTypologyBreakdown-SAE : le verdict…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35d-HumorTypologyBreakdown-SAE-Python.ipynb) | BETA | Non | -| 57 | [ICT-36 — F-Lens : mode factored-geometry, sous-espaces…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-36-FLens-FactoredGeometry-Python.ipynb) | BETA | Oui | -| 58 | [ICT-38 — S-Lens : la représentation porte-t-elle la…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-38-SLens-SelfLocation-Python.ipynb) | BETA | Non | -| 59 | [ICT-39 — Composition de regards](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-39-CompositionRegards-Python.ipynb) | BETA | Oui | -| 60 | [ICT-40b — Cognition analogique : les ondes cérébrales…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-40b-AnalogCognitionWaves-Python.ipynb) | BETA | Non | -| 61 | [Geometrie des features SAE : galaxy, atome, dense --…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-41-SAE-GeometrieFeatures-Python.ipynb) | BETA | Oui | -| 62 | [ICT-42 — Crosscoder : diffuser deux modèles, distilled…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-42-Crosscoder-Distillation-Python.ipynb) | BETA | Non | -| 63 | [ICT-44 — La géométrie de la vérité : une direction dans…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-44-GeometryOfTruth-Python.ipynb) | BETA | Non | -| 64 | [ICT-46 — Strate 7 : freebits de second ordre, le banc…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-46-Strate7-FreeCoordinates-Python.ipynb) | BETA | Oui | -| 65 | [ICT — Annexe : la contextualité du zoo de proxys est un…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-Annexe-ProxyContextuality.ipynb) | BETA | Oui | -| 66 | [ICT — Substrat argumentation : trajectoires de croyance…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-Argumentation-BeliefTrajectories.ipynb) | BETA | Oui | -| 67 | [Argumentation strate 6 — Acceptabilité QBF :…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-Argumentation-QBFAcceptance.ipynb) | BETA | Oui | -| 68 | [ICT — Substrat argumentation : maintenance de la…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-Argumentation-TruthMaintenance.ipynb) | BETA | Oui | -| 69 | [Boucle auto-referentielle p_hat (case 2 / Epic #9533)](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-Dissociation-PhatSelfReference.ipynb) | BETA | Oui | -| 70 | [ICT -- Dissociation saillance / pregnance (case s ⟂ π)](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-Dissociation-SaillancePregnance.ipynb) | BETA | Oui | -| 71 | [ICT-Greffe4 — Le vote argumenté sur chaîne : fermer la…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-Greffe4-VoteOnChain.ipynb) | BETA | Oui | -| 72 | [ICT-Life — Substrat de calibration certifié : le Jeu de…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-Life-SubstratCertifie.ipynb) | BETA | Oui | -| 73 | [ICT-MUH — Le texte où Tegmark cite Schmidhuber :…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-MUH-FibreTegmark.ipynb) | BETA | Oui | -| 74 | [Tete-a-tete SAE <-> J-space -- les deux lentilles du…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-SAE-JLens-TeteATete.ipynb) | BETA | Non | -| 75 | [ICT-Synthèse — un seul appareil de mesure, cinq…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-Synthese-CrossSubstrat.ipynb) | BETA | Non | - -## Probas/Applications (4 notebooks) - -| # | Notebook | Maturité | Exécutable | -|---|----------|----------|------------| -| 1 | [Percolation-Lean — le noyau fini de percolation, prouvé…](../../MyIA.AI.Notebooks/Probas/Applications/Percolation/Percolation-Lean.ipynb) | BETA | Oui | -| 2 | [Percolation supercritique : le géant au-dessus du seuil](../../MyIA.AI.Notebooks/Probas/Applications/Percolation/Percolation-Supercritique.ipynb) | ALPHA | Oui | -| 3 | [Le Framework Rational Speech Act (RSA)](../../MyIA.AI.Notebooks/Probas/Applications/Pyro_RSA_Hyperbole.ipynb) | BETA | Oui | -| 4 | [Quotients, fibres et recollement : ce qui survit à la…](../../MyIA.AI.Notebooks/Probas/Applications/Quotients-Fibres-Recollement-Python.ipynb) | BETA | Oui | - -## Probas/DecisionTheory (32 notebooks) - -| # | Notebook | Maturité | Exécutable | -|---|----------|----------|------------| -| 1 | [Actuariat-01 : Du risque à la prime — prime pure,…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Actuariat/Actuariat-01-Prime-Pure-Chargement.ipynb) | BETA | Oui | -| 2 | [Actuariat-02 — Fréquence × sévérité hiérarchique : le…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Actuariat/Actuariat-02-Freq-Sev-Hierarchique.ipynb) | BETA | Oui | -| 3 | [Actuariat-03 — Crédibilité actuarielle de…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Actuariat/Actuariat-03-Actuarial-Credibility.ipynb) | BETA | Oui | -| 4 | [Actuariat-04 : Ruine et capital — le processus de…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Actuariat/Actuariat-04-Ruine-Lundberg.ipynb) | BETA | Oui | -| 5 | [Actuariat-05 — Valeur de l'Information en Souscription](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Actuariat/Actuariat-05-Valeur-Info-Souscription.ipynb) | BETA | Oui | -| 6 | [Du graphe causal au do-calculus — le pont entre les…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Causal-Bridges/CausalBridges-01-Do-Calculus.ipynb) | BETA | Oui | -| 7 | [CausalBridges-02 — Exiger un estimand :…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Causal-Bridges/CausalBridges-02-Dowhy-Estimand-Intervention.ipynb) | BETA | Oui | -| 8 | [CausalBridges-03 — Le contrefactuel individuel : quand…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Causal-Bridges/CausalBridges-03-Dowhy-Contrefactuel-Individuel.ipynb) | BETA | Oui | -| 9 | [CausalBridges-04 — La découverte de structure : le…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Causal-Bridges/CausalBridges-04-Dowhy-Decouverte-Structure.ipynb) | BETA | Oui | -| 10 | [CausalBridges-05 — Le confondeur non observé :…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Causal-Bridges/CausalBridges-05-Dowhy-Sensibilite-Confounder.ipynb) | BETA | Oui | -| 11 | [CausalBridges-06 — L'instrument faible : quand le…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Causal-Bridges/CausalBridges-06-Dowhy-Instrument-Faible.ipynb) | BETA | Oui | -| 12 | [Méthodes quasi-expérimentales — identifier l'effet…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Causal-Bridges/CausalBridges-07-Quasi-Experimental.ipynb) | BETA | Oui | -| 13 | [Causal-Fairness — Décomposer la discrimination :…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Causal-Bridges/CausalBridges-08-Causal-Fairness.ipynb) | BETA | Oui | -| 14 | [DecInfer-01-Utility-Foundations : Axiomes et Fondements](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-01-Utility-Foundations.ipynb) | BETA | Oui | -| 15 | [DecInfer-02-Théorème de représentation de von…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-02-Lean-ExpectedUtility.ipynb) | BETA | Oui | -| 16 | [DecInfer-02b-Lean-Coherence : Dutch Book et bornes de…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-02b-Lean-Coherence.ipynb) | BETA | Oui | -| 17 | [DecInfer-03-Utility-Money : Utilite de l'Argent et…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-03-Utility-Money.ipynb) | BETA | Oui | -| 18 | [DecInfer-04-Multi-Attribute : Utilite Multi-Attributs](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-04-Multi-Attribute.ipynb) | BETA | Oui | -| 19 | [DecInfer-05-Decision-Networks : Reseaux de Decision](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-05-Decision-Networks.ipynb) | BETA | Oui | -| 20 | [DecInfer-06-Value-Information : Valeur de l'Information](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-06-Value-Information.ipynb) | BETA | Oui | -| 21 | [DecInfer-07-Expert-Systems : Decisions Robustes et…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-07-Expert-Systems.ipynb) | BETA | Oui | -| 22 | [DecInfer-08-Sequential : MDPs, Bandits et POMDPs](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-08-Sequential.ipynb) | BETA | Oui | -| 23 | [DecInfer-08b-Preuves formelles — Indice de Gittins](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-08b-Lean-Gittins.ipynb) | BETA | Oui | -| 24 | [DecInfer-10-Thompson-Sampling : Bandits bayesiens par…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-10-Thompson-Sampling.ipynb) | BETA | Oui | -| 25 | [DecPyMC-08 : Capstone — la sous-série Actuariat](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecPyMC/DecPyMC-08-Actuariat-Capstone.ipynb) | BETA | Oui | -| 26 | [DecPyMC-1-Utility-Foundations : Axiomes et Fondements](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecPyMC/DecPyMC-1-Utility-Foundations.ipynb) | BETA | Oui | -| 27 | [DecPyMC-2-Utility-Money : Utilite de l'Argent et…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecPyMC/DecPyMC-2-Utility-Money.ipynb) | BETA | Oui | -| 28 | [DecPyMC-3-Multi-Attribute : Utilite Multi-Attributs](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecPyMC/DecPyMC-3-Multi-Attribute.ipynb) | BETA | Oui | -| 29 | [DecPyMC-4-Decision-Networks : Reseaux de Decision](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecPyMC/DecPyMC-4-Decision-Networks.ipynb) | BETA | Oui | -| 30 | [DecPyMC-5-Valeur de l'Information](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecPyMC/DecPyMC-5-Value-Information.ipynb) | ALPHA | Oui | -| 31 | [DecPyMC-6-Systèmes Experts et Decisions Robustes](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecPyMC/DecPyMC-6-Expert-Systems.ipynb) | BETA | Oui | -| 32 | [DecPyMC-7-MDPs, Bandits et POMDPs](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecPyMC/DecPyMC-7-Sequential.ipynb) | BETA | Oui | - -## Probas/Infer (21 notebooks) - -| # | Notebook | Maturité | Exécutable | -|---|----------|----------|------------| -| 1 | [Infer-8b-TrueSkill-Formules-Fermees : la mise a jour…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-08b-TrueSkill-Formules-Fermees-CSharp.ipynb) | BETA | Oui | -| 2 | [Infer-1-Setup : Introduction et Installation](../../MyIA.AI.Notebooks/Probas/Infer/Infer-1-Setup.ipynb) | BETA | Oui | -| 3 | [Infer-10-Model-Sélection : Sélection et Comparaison de…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-10-Model-Selection.ipynb) | BETA | Oui | -| 4 | [Infer-11-Topic-Models : Latent Dirichlet Allocation…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-11-Topic-Models.ipynb) | BETA | Oui | -| 5 | [12. Modèles Hiérarchiques Bayésiens — Pooling Partiel…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-12-Modeles-Hierarchiques.ipynb) | BETA | Oui | -| 6 | [Infer-13-Crowdsourcing : Agregation de Labels et…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-13-Crowdsourcing.ipynb) | BETA | Oui | -| 7 | [Infer-14-Sequences : Hidden Markov Models et Series…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-14-Sequences.ipynb) | BETA | Oui | -| 8 | [Infer-15-Recommenders : systèmes de Recommandation](../../MyIA.AI.Notebooks/Probas/Infer/Infer-15-Recommenders.ipynb) | BETA | Oui | -| 9 | [Infer-16-Sparse-Gaussian-Process : Processus Gaussiens…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-16-Sparse-Gaussian-Process.ipynb) | BETA | Oui | -| 10 | [Infer-17 — Filtre de Kalman : systèmes dynamiques…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-17-Kalman-Filter.ipynb) | BETA | Oui | -| 11 | [Infer-18 — Détection de Rupture (Change-Point) :…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-18-Change-Point.ipynb) | BETA | Oui | -| 12 | [Infer-19 — Analyse de survie / fiabilite bayesienne :…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-19-Survival-Analysis.ipynb) | BETA | Oui | -| 13 | [Infer-1b : Introduction a Infer.NET](../../MyIA.AI.Notebooks/Probas/Infer/Infer-1b-Premiers-Modeles.ipynb) | BETA | Oui | -| 14 | [Infer-2-Gaussian-Mixtures : Distributions Gaussiennes…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-2-Gaussian-Mixtures.ipynb) | BETA | Oui | -| 15 | [Infer-2b-Debugging-Bonnes-Pratiques : Troubleshooting…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-2b-Debugging-Bonnes-Pratiques.ipynb) | BETA | Oui | -| 16 | [Infer-3-Factor-Graphs : Graphes de Facteurs et…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-3-Factor-Graphs.ipynb) | BETA | Oui | -| 17 | [Infer-4-Bayesian-Networks : Reseaux Bayesiens…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-4-Bayesian-Networks.ipynb) | BETA | Oui | -| 18 | [Infer-5-Causal-Inference : Inférence Causale et…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-5-Causal-Inference.ipynb) | BETA | Oui | -| 19 | [Infer-7-Skills-IRT : Evaluation de Competences et…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-7-Skills-IRT.ipynb) | BETA | Oui | -| 20 | [Infer-8-TrueSkill : Système de Classement et…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-8-TrueSkill.ipynb) | BETA | Oui | -| 21 | [Infer-9-Classification : Classification Bayesienne](../../MyIA.AI.Notebooks/Probas/Infer/Infer-9-Classification.ipynb) | BETA | Oui | - -## Probas/PyMC (19 notebooks) - -| # | Notebook | Maturité | Exécutable | -|---|----------|----------|------------| -| 1 | [PyMC-1 : Configuration et Premier Modèle](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-01-Setup.ipynb) | BETA | Oui | -| 2 | [PyMC-2 : Distributions Gaussiennes et Mélanges](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-02-Gaussian-Mixtures.ipynb) | BETA | Oui | -| 3 | [PyMC-02b-Debugging-Python : Troubleshooting et Bonnes…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-02b-Debugging-Python.ipynb) | BETA | Oui | -| 4 | [PyMC-3 : Graphes de Facteurs et Inference Discrete](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-03-Factor-Graphs.ipynb) | BETA | Oui | -| 5 | [PyMC-4 : Reseaux Bayesiens](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-04-Bayesian-Networks.ipynb) | BETA | Oui | -| 6 | [PyMC-05-Causal-Inference : Inference Causale et…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-05-Causal-Inference.ipynb) | BETA | Oui | -| 7 | [PyMC-7 : Modèles de Competences (IRT et DINA)](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-07-Skills-IRT.ipynb) | BETA | Oui | -| 8 | [PyMC-8 : TrueSkill - Classement et Apprentissage en…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-08-TrueSkill.ipynb) | BETA | Oui | -| 9 | [PyMC-9 : Classification Bayesienne et Tests A/B](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-09-Classification.ipynb) | BETA | Oui | -| 10 | [PyMC-10 : Sélection de Modèles et Comparaison…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-10-Model-Selection.ipynb) | BETA | Oui | -| 11 | [PyMC-11 : Modèles de Sujets (Topic Models) et LDA](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-11-Topic-Models.ipynb) | BETA | Oui | -| 12 | [12. Modèles Hiérarchiques Bayesiens -- Pooling Partiel…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-12-Modeles-Hierarchiques.ipynb) | BETA | Oui | -| 13 | [PyMC-13 : Crowdsourcing - Agregation de Labels et…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-13-Crowdsourcing.ipynb) | BETA | Oui | -| 14 | [PyMC-14 — Modèles de Sequences et Chaînes de Markov…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-14-Sequences.ipynb) | BETA | Oui | -| 15 | [PyMC-15-Recommenders : Systèmes de Recommandation…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-15-Recommenders.ipynb) | BETA | Oui | -| 16 | [PyMC-16 : Processus Gaussiens et frontières non…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-16-Sparse-Gaussian-Process.ipynb) | BETA | Oui | -| 17 | [17. Filtre de Kalman : systèmes dynamiques lineaires…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-17-Kalman-Filter.ipynb) | BETA | Oui | -| 18 | [18. Detection de Rupture (Change-Point) : inferer le…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-18-Change-Point.ipynb) | BETA | Oui | -| 19 | [19. Analyse de survie / fiabilite bayesienne : inferer…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-19-Survival-Analysis.ipynb) | BETA | Oui | - -## RL (35 notebooks) - -| # | Notebook | Maturité | Exécutable | -|---|----------|----------|------------| -| 1 | [RL-7b — Sur-généralisation relative dans le Climbing…](../../MyIA.AI.Notebooks/RL/RL-7b-Climbing-Game.ipynb) | BETA | Oui | -| 2 | [RL-10 : Reward Shaping et Curriculum Learning](../../MyIA.AI.Notebooks/RL/rl_10_reward_shaping.ipynb) | BETA | Oui | -| 3 | [RL-11 : POMDP - Partial Observability et Belief…](../../MyIA.AI.Notebooks/RL/rl_11_pomdp.ipynb) | BETA | Oui | -| 4 | [RL-12 : Distributional RL — C51 (Categorical DQN)…](../../MyIA.AI.Notebooks/RL/rl_12_distributional_rl.ipynb) | BETA | Non | -| 5 | [RL 13 - Exploration par curiosité : Random Network…](../../MyIA.AI.Notebooks/RL/rl_13_curiosity_exploration.ipynb) | BETA | Oui | -| 6 | [Hierarchical RL — l'Option framework de Sutton, Precup…](../../MyIA.AI.Notebooks/RL/rl_14_hierarchical_rl.ipynb) | BETA | Oui | -| 7 | [RL-15 — GRPO (Group Relative Policy Optimization) sur…](../../MyIA.AI.Notebooks/RL/rl_15_grpo_group_relative_policy.ipynb) | BETA | Non | -| 8 | [RL-16 : Dream-RSI — l'exploration comme code, évaluée…](../../MyIA.AI.Notebooks/RL/rl_16_dream_rsi.ipynb) | BETA | Oui | -| 9 | [RL 17 - k-server et work function : la conjecture…](../../MyIA.AI.Notebooks/RL/rl_17_k_server_wfa.ipynb) | BETA | Oui | -| 10 | [RL 18 - Le secrétaire matroïdal : la conjecture…](../../MyIA.AI.Notebooks/RL/rl_18_matroid_secretary.ipynb) | BETA | Oui | -| 11 | [RL 19 - Reward tampering : quand l'agent peut modifier…](../../MyIA.AI.Notebooks/RL/rl_19_reward_tampering.ipynb) | BETA | Oui | -| 12 | [Tutoriel Stable Baselines3 - Premiers pas](../../MyIA.AI.Notebooks/RL/rl_1_intro_cartpole.ipynb) | BETA | Oui | -| 13 | [Synthese logique d'un controleur CartPole : le bitwise…](../../MyIA.AI.Notebooks/RL/rl_1b_bitwise_logic_synthesis.ipynb) | BETA | Oui | -| 14 | [Distiller une politique RL en programme Prolog…](../../MyIA.AI.Notebooks/RL/rl_1c_prolog_distillation.ipynb) | BETA | Oui | -| 15 | [Notebook 2 – Wrappers Gym, Sauvegarde/Chargement,…](../../MyIA.AI.Notebooks/RL/rl_2_wrappers_sauvegarde_callbacks.ipynb) | BETA | Non | -| 16 | [Notebook 3 – Hindsight Experience Replay (HER) : du…](../../MyIA.AI.Notebooks/RL/rl_3_experience_replay_her.ipynb) | BETA | Oui | -| 17 | [RL-4 : Bandits Manchots et le Compromis…](../../MyIA.AI.Notebooks/RL/rl_4_multi_armed_bandits.ipynb) | BETA | Oui | -| 18 | [RL-5 : MDP, Programmation Dynamique et Q-Learning…](../../MyIA.AI.Notebooks/RL/rl_5_mdp_dp_qlearning.ipynb) | BETA | Oui | -| 19 | [RL-6 : Deep Q-Network (DQN) et Policy Gradient](../../MyIA.AI.Notebooks/RL/rl_6_dqn_policy_gradient.ipynb) | BETA | Oui | -| 20 | [RL-6b - Actor-Critic : unir valeur et politique](../../MyIA.AI.Notebooks/RL/rl_6b_actor_critic.ipynb) | BETA | Oui | -| 21 | [PPO (Proximal Policy Optimization) depuis zero](../../MyIA.AI.Notebooks/RL/rl_6c_ppo_from_scratch.ipynb) | BETA | Oui | -| 22 | [SAC (Soft Actor-Critic) depuis zero](../../MyIA.AI.Notebooks/RL/rl_6d_sac_from_scratch.ipynb) | BETA | Oui | -| 23 | [GRPO (Group Relative Policy Optimization) depuis zero](../../MyIA.AI.Notebooks/RL/rl_6e_grpo_from_scratch.ipynb) | BETA | Non | -| 24 | [RL-7 : Introduction a l'Apprentissage Multi-Agent](../../MyIA.AI.Notebooks/RL/rl_7_multi_agent_rl.ipynb) | BETA | Oui | -| 25 | [RL-8 : Model-Based RL — Dyna-Q et planification](../../MyIA.AI.Notebooks/RL/rl_8_model_based_dyna_q.ipynb) | BETA | Oui | -| 26 | [RL-9 : RL offline — Behavior Cloning et erreur…](../../MyIA.AI.Notebooks/RL/rl_9_offline_rl.ipynb) | BETA | Oui | -| 27 | [RL Post-Training — 0 : le reward model from scratch…](../../MyIA.AI.Notebooks/RL/rlpt_0_reward_model_from_scratch.ipynb) | ALPHA | Oui | -| 28 | [Biais d'un dataset de préférences — mesurés, pas…](../../MyIA.AI.Notebooks/RL/rlpt_0b_preference_dataset_bias.ipynb) | BETA | Oui | -| 29 | [RL Post-Training — 0c : l'anatomie d'un hack qui PREND…](../../MyIA.AI.Notebooks/RL/rlpt_0c_reward_hacking_case_study.ipynb) | BETA | Oui | -| 30 | [rlpt_0f — Le SOTA de l'alignement en ligne :…](../../MyIA.AI.Notebooks/RL/rlpt_0f_comparaison_GRPO_TRL_et_PPO_maison.ipynb) | ALPHA | Oui | -| 31 | [rlpt_0g -- Le troisieme bras :…](../../MyIA.AI.Notebooks/RL/rlpt_0g_ppo_TRL_experimental.ipynb) | ALPHA | Non | -| 32 | [RL Post-Training — 1 : PPO pour l'alignement d'un petit…](../../MyIA.AI.Notebooks/RL/rlpt_1_ppo_lm_rlhf.ipynb) | BETA | Oui | -| 33 | [RL Post-Training — 2 : GRPO minimal — alignement d'un…](../../MyIA.AI.Notebooks/RL/rlpt_2_grpo_minimal.ipynb) | BETA | Non | -| 34 | [RL Post-Training — 3 : Reward hacking — anatomie d'un…](../../MyIA.AI.Notebooks/RL/rlpt_3_reward_hacking.ipynb) | BETA | Non | -| 35 | [RL Post-Training — 4 : DPO offline vs RL online — même…](../../MyIA.AI.Notebooks/RL/rlpt_4_dpo_vs_ppo.ipynb) | BETA | Non | + + +# Recherche Avancée + +**Inférence probabiliste, IIT et RL avancée** + +Inférence probabiliste (Infer.NET, Pyro, PyMC), théorie de l'information intégrée (IIT), reinforcement learning avancé, théorie des jeux (OpenSpiel). Pour étudiants en master/recherche. + +## Statistiques + +| Métrique | Valeur | +|----------|--------| +| Notebooks | 297 | +| PRODUCTION | 0 | +| BETA | 286 | +| ALPHA | 11 | + +## GameTheory (95 notebooks) + +| # | Notebook | Maturité | Exécutable | +|---|----------|----------|------------| +| 1 | [GameTheory-01-Setup-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-01-Setup-Python.ipynb) | BETA | Non | +| 2 | [GameTheory-2 : Jeux sous forme normale (C# / .NET) —…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-02-NormalForm-CSharp.ipynb) | BETA | Oui | +| 3 | [GameTheory-2 (Part 2) : Support Enumeration — Équilibre…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-02-NormalForm-Part2-CSharp.ipynb) | BETA | Oui | +| 4 | [GameTheory-2 (Part 2) : Support Enumeration — Équilibre…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-02-NormalForm-Part2-Python.ipynb) | BETA | Oui | +| 5 | [GameTheory-02-NormalForm-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-02-NormalForm-Python.ipynb) | BETA | Oui | +| 6 | [GameTheory 2b - Formalisation Lean : Definitions de…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-02b-Lean-Definitions-Lean.ipynb) | BETA | Non | +| 7 | [GameTheory-02c : Traveler's Dilemma en C# — le twin qui…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-02c-Travelers-Dilemma-CSharp.ipynb) | BETA | Oui | +| 8 | [GameTheory-02c-Travelers-Dilemma-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-02c-Travelers-Dilemma-Python.ipynb) | BETA | Oui | +| 9 | [GameTheory-3 : Topologie des Jeux 2×2 — Twin C#…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-03-Topology2x2-CSharp.ipynb) | BETA | Oui | +| 10 | [GameTheory-03-Topology2x2-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-03-Topology2x2-Python.ipynb) | BETA | Oui | +| 11 | [GameTheory-3a — Chemins de swaps : à quelle distance…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-03b-Chemins-de-Swaps-Lean-Python.ipynb) | BETA | Non | +| 12 | [GameTheory 3b : Chambres, murs, codimension — les jeux…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-03c-Chambres-et-Murs-Python.ipynb) | BETA | Oui | +| 13 | [GameTheory-3c — Le joueur LLM dans le tableau…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-03d-Le-Joueur-LLM-Python.ipynb) | BETA | Non | +| 14 | [GameTheory-03d — Biens publics non-lineaires : plan de…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-03e-Plan-de-deformation-Python.ipynb) | BETA | Oui | +| 15 | [GameTheory 3e : Meta-Actions Tarifees et Parcours…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-03f-Meta-Actions-Tarifees-Python.ipynb) | BETA | Oui | +| 16 | [GameTheory-03h — Deux espèces de flèches : quand une…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-03g-Deux-Especes-de-Fleches-Python.ipynb) | BETA | Oui | +| 17 | [GameTheory-04-NashEquilibrium-Python (C#)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-04-NashEquilibrium-CSharp.ipynb) | BETA | Oui | +| 18 | [GameTheory-04-NashEquilibrium-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-04-NashEquilibrium-Python.ipynb) | BETA | Oui | +| 19 | [GameTheory 4b - Theoreme d'Existence de Nash (Lean)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-04b-Lean-NashExistence-Lean.ipynb) | BETA | Non | +| 20 | [GameTheory 4c - Théorème d'Existence de Nash (C#)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-04c-NashExistence-CSharp.ipynb) | ALPHA | Oui | +| 21 | [GameTheory 4c - Theoreme d'Existence de Nash (Python)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-04c-NashExistence-Python.ipynb) | BETA | Non | +| 22 | [GameTheory-04d-Marchandage-Asymetrique-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-04d-Marchandage-Asymetrique-Python.ipynb) | ALPHA | Oui | +| 23 | [GameTheory 04e — Oracles réflexifs, décision causale et…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-04e-Reflective-Oracles-Python.ipynb) | BETA | Oui | +| 24 | [GameTheory 04f — Théories de la décision face à un…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-04f-Theories-Decision-Predicteur-Python.ipynb) | BETA | Oui | +| 25 | [GameTheory-05-ZeroSum-Minimax-Python (Twin C#)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-05-ZeroSum-Minimax-CSharp.ipynb) | BETA | Oui | +| 26 | [GameTheory-05-ZeroSum-Minimax-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-05-ZeroSum-Minimax-Python.ipynb) | BETA | Oui | +| 27 | [GameTheory-5b — Théorème minimax de von Neumann…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-05b-Lean-Minimax-Lean.ipynb) | BETA | Non | +| 28 | [GameTheory-6 : Évolution et Confiance — Twin C#…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06-EvolutionTrust-CSharp.ipynb) | BETA | Oui | +| 29 | [GameTheory-06-EvolutionTrust-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06-EvolutionTrust-Python.ipynb) | BETA | Oui | +| 30 | [GameTheory-6c (C#) : Jeux Répétés et Théorème Folk](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06c-RepeatedGames-FolkTheorem-CSharp.ipynb) | BETA | Oui | +| 31 | [GameTheory-6c : Jeux Répétés et Théorème Folk (Folk…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06c-RepeatedGames-FolkTheorem-Python.ipynb) | BETA | Oui | +| 32 | [GameTheory-06d : Sympathie contre Engagement — la…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06d-Sympathie-vs-Engagement-Python.ipynb) | BETA | Oui | +| 33 | [GameTheory-06e : Transparence des programmes et issue…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06e-Open-Source-Game-Theory-Python.ipynb) | ALPHA | Oui | +| 34 | [GameTheory-06g — Agents à budget explicite (companion…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06f-Bounded-Agents-Lean.ipynb) | BETA | Non | +| 35 | [GameTheory-06g — Équilibres de jeux-programmes fondés…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06g-Simulation-Based-Program-Equilibria-Python.ipynb) | BETA | Oui | +| 36 | [GameTheory-06h — Programmes transparents comme…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06h-Transparent-Institutions-Python.ipynb) | BETA | Oui | +| 37 | [GameTheory-06i — Ensembles limites : Poincaré-Bendixson…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06i-Ensembles-Limites-Poincare-Bendixson-Python.ipynb) | BETA | Oui | +| 38 | [GameTheory-06f — Preuves bornees et cout du…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-06j-Bounded-Proofs-Reasoning-Costs-Python.ipynb) | BETA | Oui | +| 39 | [GameTheory-07-ExtensiveForm-Python (Twin C#)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-07-ExtensiveForm-CSharp.ipynb) | BETA | Oui | +| 40 | [GameTheory-07-ExtensiveForm-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-07-ExtensiveForm-Python.ipynb) | BETA | Oui | +| 41 | [GameTheory 8 - Jeux Combinatoires (Twin C#)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-08-CombinatorialGames-CSharp.ipynb) | BETA | Oui | +| 42 | [GameTheory 8 - Jeux Combinatoires](../../MyIA.AI.Notebooks/GameTheory/GameTheory-08-CombinatorialGames-Python.ipynb) | BETA | Oui | +| 43 | [GameTheory 8b - Jeux Combinatoires en Lean](../../MyIA.AI.Notebooks/GameTheory/GameTheory-08b-Lean-CombinatorialGames-Lean.ipynb) | BETA | Non | +| 44 | [GameTheory 8c - Jeux Combinatoires : Approfondissement…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-08c-CombinatorialGames-CSharp.ipynb) | BETA | Oui | +| 45 | [GameTheory 8c - Jeux Combinatoires : Approfondissement…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-08c-CombinatorialGames-Python.ipynb) | BETA | Oui | +| 46 | [GameTheory 8d - Combinatorial Games natif : le lake…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-08d-Lean-CGT-Lean.ipynb) | BETA | Non | +| 47 | [GameTheory-09-BackwardInduction-Python (C#)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-09-BackwardInduction-CSharp.ipynb) | BETA | Oui | +| 48 | [GameTheory-09-BackwardInduction-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-09-BackwardInduction-Python.ipynb) | BETA | Oui | +| 49 | [Stackelberg : la performativité sans mystère](../../MyIA.AI.Notebooks/GameTheory/GameTheory-09b-Commitment-Stackelberg-Python.ipynb) | BETA | Oui | +| 50 | [GameTheory-09c : Stackelberg Security Game —…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-09c-Stackelberg-SecurityGame-Python.ipynb) | BETA | Oui | +| 51 | [GameTheory-10 — Équilibres Parfaits de Sous-Jeux et…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-10-ForwardInduction-SPE-CSharp.ipynb) | BETA | Oui | +| 52 | [GameTheory-10-ForwardInduction-SPE-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-10-ForwardInduction-SPE-Python.ipynb) | BETA | Oui | +| 53 | [GameTheory-11-BayesianGames-CSharp](../../MyIA.AI.Notebooks/GameTheory/GameTheory-11-BayesianGames-CSharp.ipynb) | BETA | Oui | +| 54 | [GameTheory-11-BayesianGames-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-11-BayesianGames-Python.ipynb) | BETA | Oui | +| 55 | [GameTheory-11b — Jeux Bayésiens en Lean 4 (companion)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-11b-Lean-BayesianGamesExt-Lean.ipynb) | BETA | Non | +| 56 | [GameTheory-12 — Jeux de Réputation (twin C# du notebook…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-12-ReputationGames-CSharp.ipynb) | BETA | Oui | +| 57 | [GameTheory-12-ReputationGames-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-12-ReputationGames-Python.ipynb) | BETA | Oui | +| 58 | [GameTheory-13 : Jeux a Information Imparfaite et CFR…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-13-ImperfectInfo-CFR-CSharp.ipynb) | BETA | Oui | +| 59 | [GameTheory-13 : Jeux a Information Imparfaite et CFR](../../MyIA.AI.Notebooks/GameTheory/GameTheory-13-ImperfectInfo-CFR-Python.ipynb) | BETA | Non | +| 60 | [GameTheory-13b : Safe Subgame Solving -- quand le…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-13b-Safe-Subgame-Solving-Python.ipynb) | BETA | Oui | +| 61 | [GameTheory-13c : Safe Subgame Solving en C# — le twin…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-13c-Safe-Subgame-Solving-CSharp.ipynb) | BETA | Oui | +| 62 | [GameTheory-13d : Optimistic Counterfactual Regret…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-13d-Optimistic-CFR-Python.ipynb) | BETA | Oui | +| 63 | [GameTheory-14 : Jeux Differentiels et Equilibres de…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-14-DifferentialGames-CSharp.ipynb) | BETA | Oui | +| 64 | [GameTheory-14 : Jeux Differentiels et Equilibres de…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-14-DifferentialGames-Python.ipynb) | BETA | Oui | +| 65 | [GameTheory-15 — Jeux Coopératifs (Twin C#)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-15-CooperativeGames-CSharp.ipynb) | BETA | Oui | +| 66 | [GameTheory-15-CooperativeGames-Python](../../MyIA.AI.Notebooks/GameTheory/GameTheory-15-CooperativeGames-Python.ipynb) | BETA | Oui | +| 67 | [GameTheory 15b - Jeux Cooperatifs en Lean :…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-15b-Lean-CooperativeGames-Lean.ipynb) | BETA | Non | +| 68 | [GameTheory 15c - Jeux Cooperatifs (C# / .NET)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-15c-CooperativeGames-CSharp.ipynb) | BETA | Oui | +| 69 | [GameTheory 15c - Jeux Cooperatifs Lean (Python)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-15c-CooperativeGames-Python.ipynb) | BETA | Oui | +| 70 | [GameTheory 15d - La decomposition de Mobius sur le…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-15d-Mobius-Coalitions-Lean-Python.ipynb) | BETA | Non | +| 71 | [GameTheory-15e — Pouvoir coalitionnel : calcul, SMT…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-15e-Coalition-Power-SMT-Python.ipynb) | BETA | Oui | +| 72 | [GameTheory 15f - Valeur de Shapley de groupe : évaluer…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-15f-Shapley-Groupes-Python.ipynb) | BETA | Oui | +| 73 | [GameTheory 15g - Assistance Games (résultat 2026)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-15g-AssistanceGames-2026-Python.ipynb) | BETA | Oui | +| 74 | [GameTheory-16-MechanismDesign-Python (C#)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-16-MechanismDesign-CSharp.ipynb) | BETA | Oui | +| 75 | [GameTheory-16 : Théorie des Mécanismes et Principe de…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-16-MechanismDesign-Python.ipynb) | BETA | Oui | +| 76 | [GameTheory-16b : Automated Mechanism Design (AMD)](../../MyIA.AI.Notebooks/GameTheory/GameTheory-16b-Automated-Mechanism-Design-Python.ipynb) | BETA | Oui | +| 77 | [GameTheory-16c : La dimension paiement que le designer…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-16c-Extraction-de-Revenu-DSIC-IR-Python.ipynb) | BETA | Oui | +| 78 | [GameTheory-16d — L'echange de reins : de la valeur…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-16d-Echange-de-Reins-Lean-Python.ipynb) | BETA | Non | +| 79 | [GameTheory-16e : Pilote — joueurs LLM hétérogènes sur…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-16e-LLM-Players-Othman-Sandholm-Python.ipynb) | BETA | Non | +| 80 | [GameTheory 23b — Le lake assignment_lean par son…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-16f-Lean-Assignment-Lean.ipynb) | BETA | Non | +| 81 | [GameTheory-23 — L'algorithme de Kuhn-Munkres :…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-16f-Munkres-Assignment-Python.ipynb) | BETA | Oui | +| 82 | [GameTheory-17 (C#) : Multi-Agent Reinforcement Learning…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-17-MultiAgent-RL-CSharp.ipynb) | BETA | Oui | +| 83 | [GameTheory-17 : Apprentissage par Renforcement…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-17-MultiAgent-RL-Python.ipynb) | BETA | Oui | +| 84 | [Information asymétrique : types privés, antisélection…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-17b-Asymmetric-Information-Python.ipynb) | BETA | Oui | +| 85 | [Le marché des lemons : le certificat formel exécuté](../../MyIA.AI.Notebooks/GameTheory/GameTheory-17c-Lean-Lemons-Certificat-Lean.ipynb) | BETA | Non | +| 86 | [Screening, signal et anticipation : les trois réponses…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-17d-Lean-Screening-Signaling-Lean.ipynb) | BETA | Non | +| 87 | [Du marché au bilan : le pont théorie des jeux théorie…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-17f-Market-to-Balance-Sheet-Python.ipynb) | BETA | Oui | +| 88 | [GameTheory-18 : Open Games et Lentilles -- la…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-18-Open-Games-et-Lentilles-Python.ipynb) | BETA | Oui | +| 89 | [GameTheory-18b : Casser la composition — où la…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-18b-Casser-la-Composition-Python.ipynb) | BETA | Oui | +| 90 | [GameTheory-24 : Banc de calibration — humour, forme…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb) | BETA | Oui | +| 92 | [GameTheory-19 : L'abstraction a dette mesurable](../../MyIA.AI.Notebooks/GameTheory/GameTheory-19-Abstraction-a-Dette-Python.ipynb) | BETA | Oui | +| 93 | [GameTheory 24b : Le temoin d'impossibilite](../../MyIA.AI.Notebooks/GameTheory/GameTheory-20b-Chemin-Minimal-Temoins-Impossibilite-Python.ipynb) | BETA | Oui | +| 94 | [GameTheory 20c : Le chemin minimal sur un second…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-20c-Chemin-Minimal-3x2-Ordinal-Python.ipynb) | BETA | Oui | +| 95 | [GameTheory-21 — Loi II, seconde jambe : synthétiser un…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-20d-Loi-II-Translateur-Life-Python.ipynb) | BETA | Oui | + +## GameTheory/SocialChoice (10 notebooks) + +| # | Notebook | Maturité | Exécutable | +|---|----------|----------|------------| +| 1 | [SocialChoice 01 : Théorème d'impossibilité d'Arrow…](../../MyIA.AI.Notebooks/GameTheory/SocialChoice/01-Arrow-Impossibility-Theorem-Csharp.ipynb) | BETA | Oui | +| 2 | [SocialChoice 01 - Theoreme d'Arrow : Preuve Formelle et…](../../MyIA.AI.Notebooks/GameTheory/SocialChoice/01-Arrow-Impossibility-Theorem.ipynb) | BETA | Oui | +| 3 | [SocialChoice 01b - Choix Social Formel en Lean 4](../../MyIA.AI.Notebooks/GameTheory/SocialChoice/01b-Lean-SocialChoice-Formal.ipynb) | ALPHA | Non | +| 4 | [SocialChoice 03 : Méthodes de Vote et Paradoxes (twin…](../../MyIA.AI.Notebooks/GameTheory/SocialChoice/03-Voting-Methods-Csharp.ipynb) | ALPHA | Oui | +| 5 | [SocialChoice 03 - Méthodes de Vote et Paradoxes](../../MyIA.AI.Notebooks/GameTheory/SocialChoice/03-Voting-Methods.ipynb) | BETA | Oui | +| 6 | [SocialChoice 04 : Agregation Computationnelle - SAT et…](../../MyIA.AI.Notebooks/GameTheory/SocialChoice/04-Computational-Aggregation-SAT-Z3-Csharp.ipynb) | BETA | Oui | +| 7 | [SocialChoice 04 - Agrégation Computationnelle : SAT et…](../../MyIA.AI.Notebooks/GameTheory/SocialChoice/04-Computational-Aggregation-SAT-Z3.ipynb) | BETA | Oui | +| 8 | [SocialChoice-05 : Gibbard-Satterthwaite sans mystere -…](../../MyIA.AI.Notebooks/GameTheory/SocialChoice/05-Gibbard-Satterthwaite.ipynb) | BETA | Oui | +| 9 | [SocialChoice-06 : Mobius sur le treillis des coalitions…](../../MyIA.AI.Notebooks/GameTheory/SocialChoice/06-Mobius-Aggregation-Pouvoir-Manipulation.ipynb) | BETA | Oui | +| 10 | [07 - Élections de comité par approbation : le core…](../../MyIA.AI.Notebooks/GameTheory/SocialChoice/07-Committees-Core.ipynb) | BETA | Oui | + +## IIT (6 notebooks) + +| # | Notebook | Maturité | Exécutable | +|---|----------|----------|------------| +| 1 | [IIT - Introduction à PyPhi et Integrated Information…](../../MyIA.AI.Notebooks/IIT/IIT-01-IntroToPyPhi.ipynb) | BETA | Oui | +| 2 | [IIT - Sujets Avances : Partitionnement, Repertoires…](../../MyIA.AI.Notebooks/IIT/IIT-02-AdvancedTopics.ipynb) | BETA | Oui | +| 3 | [IIT-3. Coarse-graining, blackboxing et l'échelle du…](../../MyIA.AI.Notebooks/IIT/IIT-03-CoarseGrainingMacroPhi.ipynb) | BETA | Oui | +| 4 | [IIT-4. Le problème de frontière — qui décide où sont…](../../MyIA.AI.Notebooks/IIT/IIT-04-Le-Probleme-de-Frontiere.ipynb) | BETA | Oui | +| 5 | [IIT-5. Les lentilles de conscience comme bancs de…](../../MyIA.AI.Notebooks/IIT/IIT-05-Lentilles-et-Dissociations.ipynb) | BETA | Oui | +| 6 | [IIT-6. L'objet qui a mordu IIT — l'expander à Φ énorme,…](../../MyIA.AI.Notebooks/IIT/IIT-06-L-Objet-qui-a-Mordu-IIT.ipynb) | BETA | Oui | + +## IIT/ICT-Series (75 notebooks) + +| # | Notebook | Maturité | Exécutable | +|---|----------|----------|------------| +| 1 | [ICT-1 — Trajectoires de $\Phi$](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-01-PhiTrajectories-Python.ipynb) | BETA | Oui | +| 2 | [ICT-2 — Le tri comme morphogenèse minimale…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-02-SelfSortingMorphogenesis-Python.ipynb) | BETA | Oui | +| 3 | [ICT-3 — Robustesse & délai de gratification : étude…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-03-RobustnessDelayedGratification-Python.ipynb) | BETA | Oui | +| 4 | [ICT-4 — Tableaux chimériques & agrégation émergente («…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-04-ChimericArraysKinAggregation-Python.ipynb) | BETA | Oui | +| 5 | [ICT-5 : Émergence causale — quelle échelle décrit le…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-05-CausalEmergence-Python.ipynb) | BETA | Oui | +| 6 | [ICT-6 — Du tri a la chaîne de Markov : emergence…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-06-SortingToTPM-CausalEmergence-Python.ipynb) | BETA | Oui | +| 7 | [ICT-7 — Signatures *scale-free* & criticalite](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-07-ScaleFreeSignatures-Python.ipynb) | BETA | Oui | +| 8 | [ICT-8 — Paysages d'attracteurs & signaux precurseurs :…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-08-AttractorLandscapesEWS-Python.ipynb) | BETA | Oui | +| 9 | [ICT-9 — Agence & regeneration : *reparer sa forme, ou…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-09-AgencyRegeneration-Python.ipynb) | BETA | Oui | +| 10 | [ICT-10 — Grammaire des catastrophes : *l'obstacle qui…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-10-CatastropheGrammar-Python.ipynb) | BETA | Oui | +| 11 | [ICT-11 — Profils d'agence causale : à quelle échelle…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-11-CausalAgencyProfiles-Python.ipynb) | BETA | Oui | +| 12 | [ICT-12 — Champs de valence et animats : rôles mesures,…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-12-ValenceFieldsAndAnimats-Python.ipynb) | BETA | Oui | +| 13 | [ICT-12b — Valence APPRISE, transferable, reversible :…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-12b-LearnedValence-Python.ipynb) | BETA | Oui | +| 14 | [ICT-12c — Animat prégnance/valence incarné : la…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-12c-PregnanceAnimat-Python.ipynb) | BETA | Oui | +| 15 | [ICT-12d — Animat inhibé (Laborit) : contrôlabilité,…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-12d-InhibitedActionAnimat-Python.ipynb) | BETA | Oui | +| 16 | [ICT-12e — Valeur de l'information pour l'animat incarné…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-12e-Value-of-Information-Animat-Python.ipynb) | BETA | Oui | +| 17 | [ICT-13 — Morphodynamique stratégique : une stratégie…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-13-AxelrodStrategicMorphodynamics-Python.ipynb) | BETA | Oui | +| 18 | [ICT-13b — Décroisement dynamique × observable : d'où…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-13b-DecroisementDynamiqueObservable-Python.ipynb) | ALPHA | Oui | +| 19 | [ICT-14 — Énergie libre et surprise du représentant…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-14-FreeEnergySurprise-Python.ipynb) | BETA | Oui | +| 20 | [ICT-15 — Integrated Complexity : convergence Φ / F / K…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15-IntegratedComplexity-Python.ipynb) | BETA | Oui | +| 21 | [ICT-15c — Méta-proxy d'obstruction : structure des…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15c-MetaProxyObstruction-Python.ipynb) | BETA | Oui | +| 22 | [ICT-15d — Cochaîne de Čech pondérée : obstruction…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15d-CechObstruction-Python.ipynb) | BETA | Oui | +| 23 | [ICT-15e -- Bridge #2 : recouvrabilite *est* agentivite…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15e-Bridge2-RecoverabilityAgency-Python.ipynb) | BETA | Oui | +| 24 | [ICT-15f -- Pont #1-bis : la famille decouplee tranche…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15f-Bridge1bis-DecoupledFamily-Python.ipynb) | BETA | Oui | +| 25 | [ICT-15h -- Pont #1-bis (chantier 2/3) : le regime…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15h-Bridge1bis-AsymmetricFamily-Python.ipynb) | BETA | Oui | +| 26 | [ICT-15i -- Pont #1-bis : le paysage 2D anisotrope clot…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15i-Bridge1bis-2DLandscape-Python.ipynb) | BETA | Oui | +| 27 | [ICT-15j — Discriminant Čech par nerf simplicial (gudhi)](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15j-NerveDiscriminant-Python.ipynb) | BETA | Oui | +| 28 | [ICT-15k — Recollement des macrocells : le quadtree de…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15k-RecollementMacroCells-Python.ipynb) | BETA | Oui | +| 29 | [ICT-15l — Indépendance au générateur de nouveauté : le…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-15l-IndependanceGenerateur-Python.ipynb) | BETA | Oui | +| 30 | [ICT-16 — MDL / code en deux parties et bosse…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-16-MDLTwoPartCode-Python.ipynb) | BETA | Oui | +| 31 | [ICT-17b — Grokking et compression-progress : la jambe K…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-17b-Grokking-CompressionProgress-Python.ipynb) | BETA | Oui | +| 32 | [ICT-18 -- Fleche du temps et reversibilisation (strate…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-18-ArrowOfTimeReversibilization-Python.ipynb) | BETA | Oui | +| 33 | [ICT-18b — Budget de réversibilité : la jambe « fin » de…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-18b-ReversibilityBudget-Python.ipynb) | BETA | Oui | +| 34 | [ICT-19 — La batterie de l'ENJEU : auto-maintien vs pur…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-19-EnjeuBattery-Python.ipynb) | BETA | Oui | +| 35 | [ICT-19b — Raffinement et résolution des stubs (tranche…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-19b-EnjeuBattery-Raffinement-Python.ipynb) | BETA | Non | +| 36 | [ICT-20 — FeatureCatastrophes : *calibration de méthode*](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-20-FeatureCatastrophes-Python.ipynb) | BETA | Non | +| 37 | [ICT-21 — SAETrajectoires : le substrat S4 entre au banc](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-21-SAETrajectoires-Python.ipynb) | BETA | Non | +| 38 | [ICT-21b-SAECalibration-Python — que reconstruit…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-21b-SAECalibration-Python.ipynb) | BETA | Non | +| 39 | [ICT-21c-SAECatastrophes-Python — forme et dynamique des…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-21c-SAECatastrophes-Python.ipynb) | BETA | Non | +| 40 | [ICT-22 — LLMSubstrat : le transformer comme quatrième…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-22-LLMSubstrat-Python.ipynb) | BETA | Non | +| 41 | [ICT-22b -- Moteur d'intervention causal : operer,…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-22b-CausalInterventionEngine-Python.ipynb) | BETA | Non | +| 42 | [ICT-23 — PersonaCatastrophe : la fronce de Thom…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-23-PersonaCatastrophe-Python.ipynb) | BETA | Oui | +| 43 | [ICT-24 — WorkspaceIgnition : l'axe Global Workspace et…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-24-WorkspaceIgnition-Python.ipynb) | BETA | Non | +| 44 | [ICT-25 — InoculationRL : GRPO à récompense *hackable*,…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-25-InoculationRL-Python.ipynb) | BETA | Non | +| 45 | [ICT-26 — Convention de signalisation (expérience A,…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-26-SignalingConvention-Python.ipynb) | BETA | Oui | +| 46 | [ICT-27 — Invention de symboles (expérience B, strate 7)](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-27-SymbolInvention-Python.ipynb) | BETA | Oui | +| 47 | [ICT-28 — Adoption collective et seuil de performativité…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-28-CollectiveAdoption-Python.ipynb) | BETA | Oui | +| 48 | [ICT-30 — Invention inhibée (expérience E, strate 7)](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-30-InhibitedInvention-Python.ipynb) | BETA | Oui | +| 49 | [ICT-31 — Le contraste mesuré à trois substrats :…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-31-ContrasteTroisSubstrats-Python.ipynb) | BETA | Oui | +| 50 | [ICT-32 — Stratification causale du Jeu de la Vie :…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-32-StratificationCausaleLife-Python.ipynb) | BETA | Oui | +| 51 | [ICT-33 — Ensembles ouverts : soupes, collisions, et la…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-33-SoupCollisions-Python.ipynb) | BETA | Oui | +| 52 | [ICT-34 — Le banc de recollement des lectures : quatre…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-34-BancRecollementLectures-Python.ipynb) | BETA | Oui | +| 53 | [ICT-35 -- HumorCausalProbe-Pilot : substrat HLS, sans…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35-HumorCausalProbe-Pilot-Python.ipynb) | BETA | Non | +| 54 | [ICT-35b -- HumorCausalPairs-SAE : paires minimales,…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35b-HumorCausalPairs-SAE-Python.ipynb) | BETA | Non | +| 55 | [ICT-35c -- HumorDepthProfile-SAE : le verdict survit-il…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35c-HumorDepthProfile-SAE-Python.ipynb) | BETA | Oui | +| 56 | [ICT-35d -- HumorTypologyBreakdown-SAE : le verdict…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35d-HumorTypologyBreakdown-SAE-Python.ipynb) | BETA | Non | +| 57 | [ICT-36 — F-Lens : mode factored-geometry, sous-espaces…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-36-FLens-FactoredGeometry-Python.ipynb) | BETA | Oui | +| 58 | [ICT-38 — S-Lens : la représentation porte-t-elle la…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-38-SLens-SelfLocation-Python.ipynb) | BETA | Non | +| 59 | [ICT-39 — Composition de regards](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-39-CompositionRegards-Python.ipynb) | BETA | Oui | +| 60 | [ICT-40b — Cognition analogique : les ondes cérébrales…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-40b-AnalogCognitionWaves-Python.ipynb) | BETA | Non | +| 61 | [Geometrie des features SAE : galaxy, atome, dense --…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-41-SAE-GeometrieFeatures-Python.ipynb) | BETA | Oui | +| 62 | [ICT-42 — Crosscoder : diffuser deux modèles, distilled…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-42-Crosscoder-Distillation-Python.ipynb) | BETA | Non | +| 63 | [ICT-44 — La géométrie de la vérité : une direction dans…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-44-GeometryOfTruth-Python.ipynb) | BETA | Non | +| 64 | [ICT-46 — Strate 7 : freebits de second ordre, le banc…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-46-Strate7-FreeCoordinates-Python.ipynb) | BETA | Oui | +| 65 | [ICT — Annexe : la contextualité du zoo de proxys est un…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-Annexe-ProxyContextuality.ipynb) | BETA | Oui | +| 66 | [ICT — Substrat argumentation : trajectoires de croyance…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-Argumentation-BeliefTrajectories.ipynb) | BETA | Oui | +| 67 | [Argumentation strate 6 — Acceptabilité QBF :…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-Argumentation-QBFAcceptance.ipynb) | BETA | Oui | +| 68 | [ICT — Substrat argumentation : maintenance de la…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-Argumentation-TruthMaintenance.ipynb) | BETA | Oui | +| 69 | [Boucle auto-referentielle p_hat (case 2 / Epic #9533)](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-Dissociation-PhatSelfReference.ipynb) | BETA | Oui | +| 70 | [ICT -- Dissociation saillance / pregnance (case s ⟂ π)](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-Dissociation-SaillancePregnance.ipynb) | BETA | Oui | +| 71 | [ICT-Greffe4 — Le vote argumenté sur chaîne : fermer la…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-Greffe4-VoteOnChain.ipynb) | BETA | Oui | +| 72 | [ICT-Life — Substrat de calibration certifié : le Jeu de…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-Life-SubstratCertifie.ipynb) | BETA | Oui | +| 73 | [ICT-MUH — Le texte où Tegmark cite Schmidhuber :…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-MUH-FibreTegmark.ipynb) | BETA | Oui | +| 74 | [Tete-a-tete SAE <-> J-space -- les deux lentilles du…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-SAE-JLens-TeteATete.ipynb) | BETA | Non | +| 75 | [ICT-Synthèse — un seul appareil de mesure, cinq…](../../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-Synthese-CrossSubstrat.ipynb) | BETA | Non | + +## Probas/Applications (4 notebooks) + +| # | Notebook | Maturité | Exécutable | +|---|----------|----------|------------| +| 1 | [Percolation-Lean — le noyau fini de percolation, prouvé…](../../MyIA.AI.Notebooks/Probas/Applications/Percolation/Percolation-Lean.ipynb) | BETA | Oui | +| 2 | [Percolation supercritique : le géant au-dessus du seuil](../../MyIA.AI.Notebooks/Probas/Applications/Percolation/Percolation-Supercritique.ipynb) | ALPHA | Oui | +| 3 | [Le Framework Rational Speech Act (RSA)](../../MyIA.AI.Notebooks/Probas/Applications/Pyro_RSA_Hyperbole.ipynb) | BETA | Oui | +| 4 | [Quotients, fibres et recollement : ce qui survit à la…](../../MyIA.AI.Notebooks/Probas/Applications/Quotients-Fibres-Recollement-Python.ipynb) | BETA | Oui | + +## Probas/DecisionTheory (32 notebooks) + +| # | Notebook | Maturité | Exécutable | +|---|----------|----------|------------| +| 1 | [Actuariat-01 : Du risque à la prime — prime pure,…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Actuariat/Actuariat-01-Prime-Pure-Chargement.ipynb) | BETA | Oui | +| 2 | [Actuariat-02 — Fréquence × sévérité hiérarchique : le…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Actuariat/Actuariat-02-Freq-Sev-Hierarchique.ipynb) | BETA | Oui | +| 3 | [Actuariat-03 — Crédibilité actuarielle de…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Actuariat/Actuariat-03-Actuarial-Credibility.ipynb) | BETA | Oui | +| 4 | [Actuariat-04 : Ruine et capital — le processus de…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Actuariat/Actuariat-04-Ruine-Lundberg.ipynb) | BETA | Oui | +| 5 | [Actuariat-05 — Valeur de l'Information en Souscription](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Actuariat/Actuariat-05-Valeur-Info-Souscription.ipynb) | BETA | Oui | +| 6 | [Du graphe causal au do-calculus — le pont entre les…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Causal-Bridges/CausalBridges-01-Do-Calculus.ipynb) | BETA | Oui | +| 7 | [CausalBridges-02 — Exiger un estimand :…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Causal-Bridges/CausalBridges-02-Dowhy-Estimand-Intervention.ipynb) | BETA | Oui | +| 8 | [CausalBridges-03 — Le contrefactuel individuel : quand…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Causal-Bridges/CausalBridges-03-Dowhy-Contrefactuel-Individuel.ipynb) | BETA | Oui | +| 9 | [CausalBridges-04 — La découverte de structure : le…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Causal-Bridges/CausalBridges-04-Dowhy-Decouverte-Structure.ipynb) | BETA | Oui | +| 10 | [CausalBridges-05 — Le confondeur non observé :…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Causal-Bridges/CausalBridges-05-Dowhy-Sensibilite-Confounder.ipynb) | BETA | Oui | +| 11 | [CausalBridges-06 — L'instrument faible : quand le…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Causal-Bridges/CausalBridges-06-Dowhy-Instrument-Faible.ipynb) | BETA | Oui | +| 12 | [Méthodes quasi-expérimentales — identifier l'effet…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Causal-Bridges/CausalBridges-07-Quasi-Experimental.ipynb) | BETA | Oui | +| 13 | [Causal-Fairness — Décomposer la discrimination :…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/Causal-Bridges/CausalBridges-08-Causal-Fairness.ipynb) | BETA | Oui | +| 14 | [DecInfer-01-Utility-Foundations : Axiomes et Fondements](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-01-Utility-Foundations.ipynb) | BETA | Oui | +| 15 | [DecInfer-02-Théorème de représentation de von…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-02-Lean-ExpectedUtility.ipynb) | BETA | Oui | +| 16 | [DecInfer-02b-Lean-Coherence : Dutch Book et bornes de…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-02b-Lean-Coherence.ipynb) | BETA | Oui | +| 17 | [DecInfer-03-Utility-Money : Utilite de l'Argent et…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-03-Utility-Money.ipynb) | BETA | Oui | +| 18 | [DecInfer-04-Multi-Attribute : Utilite Multi-Attributs](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-04-Multi-Attribute.ipynb) | BETA | Oui | +| 19 | [DecInfer-05-Decision-Networks : Reseaux de Decision](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-05-Decision-Networks.ipynb) | BETA | Oui | +| 20 | [DecInfer-06-Value-Information : Valeur de l'Information](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-06-Value-Information.ipynb) | BETA | Oui | +| 21 | [DecInfer-07-Expert-Systems : Decisions Robustes et…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-07-Expert-Systems.ipynb) | BETA | Oui | +| 22 | [DecInfer-08-Sequential : MDPs, Bandits et POMDPs](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-08-Sequential.ipynb) | BETA | Oui | +| 23 | [DecInfer-08b-Preuves formelles — Indice de Gittins](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-08b-Lean-Gittins.ipynb) | BETA | Oui | +| 24 | [DecInfer-10-Thompson-Sampling : Bandits bayesiens par…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecInfer/DecInfer-10-Thompson-Sampling.ipynb) | BETA | Oui | +| 25 | [DecPyMC-08 : Capstone — la sous-série Actuariat](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecPyMC/DecPyMC-08-Actuariat-Capstone.ipynb) | BETA | Oui | +| 26 | [DecPyMC-1-Utility-Foundations : Axiomes et Fondements](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecPyMC/DecPyMC-1-Utility-Foundations.ipynb) | BETA | Oui | +| 27 | [DecPyMC-2-Utility-Money : Utilite de l'Argent et…](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecPyMC/DecPyMC-2-Utility-Money.ipynb) | BETA | Oui | +| 28 | [DecPyMC-3-Multi-Attribute : Utilite Multi-Attributs](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecPyMC/DecPyMC-3-Multi-Attribute.ipynb) | BETA | Oui | +| 29 | [DecPyMC-4-Decision-Networks : Reseaux de Decision](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecPyMC/DecPyMC-4-Decision-Networks.ipynb) | BETA | Oui | +| 30 | [DecPyMC-5-Valeur de l'Information](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecPyMC/DecPyMC-5-Value-Information.ipynb) | ALPHA | Oui | +| 31 | [DecPyMC-6-Systèmes Experts et Decisions Robustes](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecPyMC/DecPyMC-6-Expert-Systems.ipynb) | BETA | Oui | +| 32 | [DecPyMC-7-MDPs, Bandits et POMDPs](../../MyIA.AI.Notebooks/Probas/DecisionTheory/DecPyMC/DecPyMC-7-Sequential.ipynb) | BETA | Oui | + +## Probas/Infer (21 notebooks) + +| # | Notebook | Maturité | Exécutable | +|---|----------|----------|------------| +| 1 | [Infer-8b-TrueSkill-Formules-Fermees : la mise a jour…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-08b-TrueSkill-Formules-Fermees-CSharp.ipynb) | BETA | Oui | +| 2 | [Infer-1-Setup : Introduction et Installation](../../MyIA.AI.Notebooks/Probas/Infer/Infer-1-Setup.ipynb) | BETA | Oui | +| 3 | [Infer-10-Model-Sélection : Sélection et Comparaison de…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-10-Model-Selection.ipynb) | BETA | Oui | +| 4 | [Infer-11-Topic-Models : Latent Dirichlet Allocation…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-11-Topic-Models.ipynb) | BETA | Oui | +| 5 | [12. Modèles Hiérarchiques Bayésiens — Pooling Partiel…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-12-Modeles-Hierarchiques.ipynb) | BETA | Oui | +| 6 | [Infer-13-Crowdsourcing : Agregation de Labels et…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-13-Crowdsourcing.ipynb) | BETA | Oui | +| 7 | [Infer-14-Sequences : Hidden Markov Models et Series…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-14-Sequences.ipynb) | BETA | Oui | +| 8 | [Infer-15-Recommenders : systèmes de Recommandation](../../MyIA.AI.Notebooks/Probas/Infer/Infer-15-Recommenders.ipynb) | BETA | Oui | +| 9 | [Infer-16-Sparse-Gaussian-Process : Processus Gaussiens…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-16-Sparse-Gaussian-Process.ipynb) | BETA | Oui | +| 10 | [Infer-17 — Filtre de Kalman : systèmes dynamiques…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-17-Kalman-Filter.ipynb) | BETA | Oui | +| 11 | [Infer-18 — Détection de Rupture (Change-Point) :…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-18-Change-Point.ipynb) | BETA | Oui | +| 12 | [Infer-19 — Analyse de survie / fiabilite bayesienne :…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-19-Survival-Analysis.ipynb) | BETA | Oui | +| 13 | [Infer-1b : Introduction a Infer.NET](../../MyIA.AI.Notebooks/Probas/Infer/Infer-1b-Premiers-Modeles.ipynb) | BETA | Oui | +| 14 | [Infer-2-Gaussian-Mixtures : Distributions Gaussiennes…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-2-Gaussian-Mixtures.ipynb) | BETA | Oui | +| 15 | [Infer-2b-Debugging-Bonnes-Pratiques : Troubleshooting…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-2b-Debugging-Bonnes-Pratiques.ipynb) | BETA | Oui | +| 16 | [Infer-3-Factor-Graphs : Graphes de Facteurs et…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-3-Factor-Graphs.ipynb) | BETA | Oui | +| 17 | [Infer-4-Bayesian-Networks : Reseaux Bayesiens…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-4-Bayesian-Networks.ipynb) | BETA | Oui | +| 18 | [Infer-5-Causal-Inference : Inférence Causale et…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-5-Causal-Inference.ipynb) | BETA | Oui | +| 19 | [Infer-7-Skills-IRT : Evaluation de Competences et…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-7-Skills-IRT.ipynb) | BETA | Oui | +| 20 | [Infer-8-TrueSkill : Système de Classement et…](../../MyIA.AI.Notebooks/Probas/Infer/Infer-8-TrueSkill.ipynb) | BETA | Oui | +| 21 | [Infer-9-Classification : Classification Bayesienne](../../MyIA.AI.Notebooks/Probas/Infer/Infer-9-Classification.ipynb) | BETA | Oui | + +## Probas/PyMC (19 notebooks) + +| # | Notebook | Maturité | Exécutable | +|---|----------|----------|------------| +| 1 | [PyMC-1 : Configuration et Premier Modèle](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-01-Setup.ipynb) | BETA | Oui | +| 2 | [PyMC-2 : Distributions Gaussiennes et Mélanges](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-02-Gaussian-Mixtures.ipynb) | BETA | Oui | +| 3 | [PyMC-02b-Debugging-Python : Troubleshooting et Bonnes…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-02b-Debugging-Python.ipynb) | BETA | Oui | +| 4 | [PyMC-3 : Graphes de Facteurs et Inference Discrete](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-03-Factor-Graphs.ipynb) | BETA | Oui | +| 5 | [PyMC-4 : Reseaux Bayesiens](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-04-Bayesian-Networks.ipynb) | BETA | Oui | +| 6 | [PyMC-05-Causal-Inference : Inference Causale et…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-05-Causal-Inference.ipynb) | BETA | Oui | +| 7 | [PyMC-7 : Modèles de Competences (IRT et DINA)](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-07-Skills-IRT.ipynb) | BETA | Oui | +| 8 | [PyMC-8 : TrueSkill - Classement et Apprentissage en…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-08-TrueSkill.ipynb) | BETA | Oui | +| 9 | [PyMC-9 : Classification Bayesienne et Tests A/B](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-09-Classification.ipynb) | BETA | Oui | +| 10 | [PyMC-10 : Sélection de Modèles et Comparaison…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-10-Model-Selection.ipynb) | BETA | Oui | +| 11 | [PyMC-11 : Modèles de Sujets (Topic Models) et LDA](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-11-Topic-Models.ipynb) | BETA | Oui | +| 12 | [12. Modèles Hiérarchiques Bayesiens -- Pooling Partiel…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-12-Modeles-Hierarchiques.ipynb) | BETA | Oui | +| 13 | [PyMC-13 : Crowdsourcing - Agregation de Labels et…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-13-Crowdsourcing.ipynb) | BETA | Oui | +| 14 | [PyMC-14 — Modèles de Sequences et Chaînes de Markov…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-14-Sequences.ipynb) | BETA | Oui | +| 15 | [PyMC-15-Recommenders : Systèmes de Recommandation…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-15-Recommenders.ipynb) | BETA | Oui | +| 16 | [PyMC-16 : Processus Gaussiens et frontières non…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-16-Sparse-Gaussian-Process.ipynb) | BETA | Oui | +| 17 | [17. Filtre de Kalman : systèmes dynamiques lineaires…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-17-Kalman-Filter.ipynb) | BETA | Oui | +| 18 | [18. Detection de Rupture (Change-Point) : inferer le…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-18-Change-Point.ipynb) | BETA | Oui | +| 19 | [19. Analyse de survie / fiabilite bayesienne : inferer…](../../MyIA.AI.Notebooks/Probas/PyMC/PyMC-19-Survival-Analysis.ipynb) | BETA | Oui | + +## RL (35 notebooks) + +| # | Notebook | Maturité | Exécutable | +|---|----------|----------|------------| +| 1 | [RL-7b — Sur-généralisation relative dans le Climbing…](../../MyIA.AI.Notebooks/RL/RL-7b-Climbing-Game.ipynb) | BETA | Oui | +| 2 | [RL-10 : Reward Shaping et Curriculum Learning](../../MyIA.AI.Notebooks/RL/rl_10_reward_shaping.ipynb) | BETA | Oui | +| 3 | [RL-11 : POMDP - Partial Observability et Belief…](../../MyIA.AI.Notebooks/RL/rl_11_pomdp.ipynb) | BETA | Oui | +| 4 | [RL-12 : Distributional RL — C51 (Categorical DQN)…](../../MyIA.AI.Notebooks/RL/rl_12_distributional_rl.ipynb) | BETA | Non | +| 5 | [RL 13 - Exploration par curiosité : Random Network…](../../MyIA.AI.Notebooks/RL/rl_13_curiosity_exploration.ipynb) | BETA | Oui | +| 6 | [Hierarchical RL — l'Option framework de Sutton, Precup…](../../MyIA.AI.Notebooks/RL/rl_14_hierarchical_rl.ipynb) | BETA | Oui | +| 7 | [RL-15 — GRPO (Group Relative Policy Optimization) sur…](../../MyIA.AI.Notebooks/RL/rl_15_grpo_group_relative_policy.ipynb) | BETA | Non | +| 8 | [RL-16 : Dream-RSI — l'exploration comme code, évaluée…](../../MyIA.AI.Notebooks/RL/rl_16_dream_rsi.ipynb) | BETA | Oui | +| 9 | [RL 17 - k-server et work function : la conjecture…](../../MyIA.AI.Notebooks/RL/rl_17_k_server_wfa.ipynb) | BETA | Oui | +| 10 | [RL 18 - Le secrétaire matroïdal : la conjecture…](../../MyIA.AI.Notebooks/RL/rl_18_matroid_secretary.ipynb) | BETA | Oui | +| 11 | [RL 19 - Reward tampering : quand l'agent peut modifier…](../../MyIA.AI.Notebooks/RL/rl_19_reward_tampering.ipynb) | BETA | Oui | +| 12 | [Tutoriel Stable Baselines3 - Premiers pas](../../MyIA.AI.Notebooks/RL/rl_1_intro_cartpole.ipynb) | BETA | Oui | +| 13 | [Synthese logique d'un controleur CartPole : le bitwise…](../../MyIA.AI.Notebooks/RL/rl_1b_bitwise_logic_synthesis.ipynb) | BETA | Oui | +| 14 | [Distiller une politique RL en programme Prolog…](../../MyIA.AI.Notebooks/RL/rl_1c_prolog_distillation.ipynb) | BETA | Oui | +| 15 | [Notebook 2 – Wrappers Gym, Sauvegarde/Chargement,…](../../MyIA.AI.Notebooks/RL/rl_2_wrappers_sauvegarde_callbacks.ipynb) | BETA | Non | +| 16 | [Notebook 3 – Hindsight Experience Replay (HER) : du…](../../MyIA.AI.Notebooks/RL/rl_3_experience_replay_her.ipynb) | BETA | Oui | +| 17 | [RL-4 : Bandits Manchots et le Compromis…](../../MyIA.AI.Notebooks/RL/rl_4_multi_armed_bandits.ipynb) | BETA | Oui | +| 18 | [RL-5 : MDP, Programmation Dynamique et Q-Learning…](../../MyIA.AI.Notebooks/RL/rl_5_mdp_dp_qlearning.ipynb) | BETA | Oui | +| 19 | [RL-6 : Deep Q-Network (DQN) et Policy Gradient](../../MyIA.AI.Notebooks/RL/rl_6_dqn_policy_gradient.ipynb) | BETA | Oui | +| 20 | [RL-6b - Actor-Critic : unir valeur et politique](../../MyIA.AI.Notebooks/RL/rl_6b_actor_critic.ipynb) | BETA | Oui | +| 21 | [PPO (Proximal Policy Optimization) depuis zero](../../MyIA.AI.Notebooks/RL/rl_6c_ppo_from_scratch.ipynb) | BETA | Oui | +| 22 | [SAC (Soft Actor-Critic) depuis zero](../../MyIA.AI.Notebooks/RL/rl_6d_sac_from_scratch.ipynb) | BETA | Oui | +| 23 | [GRPO (Group Relative Policy Optimization) depuis zero](../../MyIA.AI.Notebooks/RL/rl_6e_grpo_from_scratch.ipynb) | BETA | Non | +| 24 | [RL-7 : Introduction a l'Apprentissage Multi-Agent](../../MyIA.AI.Notebooks/RL/rl_7_multi_agent_rl.ipynb) | BETA | Oui | +| 25 | [RL-8 : Model-Based RL — Dyna-Q et planification](../../MyIA.AI.Notebooks/RL/rl_8_model_based_dyna_q.ipynb) | BETA | Oui | +| 26 | [RL-9 : RL offline — Behavior Cloning et erreur…](../../MyIA.AI.Notebooks/RL/rl_9_offline_rl.ipynb) | BETA | Oui | +| 27 | [RL Post-Training — 0 : le reward model from scratch…](../../MyIA.AI.Notebooks/RL/rlpt_0_reward_model_from_scratch.ipynb) | ALPHA | Oui | +| 28 | [Biais d'un dataset de préférences — mesurés, pas…](../../MyIA.AI.Notebooks/RL/rlpt_0b_preference_dataset_bias.ipynb) | BETA | Oui | +| 29 | [RL Post-Training — 0c : l'anatomie d'un hack qui PREND…](../../MyIA.AI.Notebooks/RL/rlpt_0c_reward_hacking_case_study.ipynb) | BETA | Oui | +| 30 | [rlpt_0f — Le SOTA de l'alignement en ligne :…](../../MyIA.AI.Notebooks/RL/rlpt_0f_comparaison_GRPO_TRL_et_PPO_maison.ipynb) | ALPHA | Oui | +| 31 | [rlpt_0g -- Le troisieme bras :…](../../MyIA.AI.Notebooks/RL/rlpt_0g_ppo_TRL_experimental.ipynb) | ALPHA | Non | +| 32 | [RL Post-Training — 1 : PPO pour l'alignement d'un petit…](../../MyIA.AI.Notebooks/RL/rlpt_1_ppo_lm_rlhf.ipynb) | BETA | Oui | +| 33 | [RL Post-Training — 2 : GRPO minimal — alignement d'un…](../../MyIA.AI.Notebooks/RL/rlpt_2_grpo_minimal.ipynb) | BETA | Non | +| 34 | [RL Post-Training — 3 : Reward hacking — anatomie d'un…](../../MyIA.AI.Notebooks/RL/rlpt_3_reward_hacking.ipynb) | BETA | Non | +| 35 | [RL Post-Training — 4 : DPO offline vs RL online — même…](../../MyIA.AI.Notebooks/RL/rlpt_4_dpo_vs_ppo.ipynb) | BETA | Non | From fee5e8845562d79d89c22c4d8022ab24875fb1ee Mon Sep 17 00:00:00 2001 From: jsboige Date: Sun, 4 Oct 2026 02:46:01 +0200 Subject: [PATCH 2/4] Fix: #19040 rouges CI - tags sota-notice (renvois SOTA), compteurs prose retires, lien 18d->18c - split-reading : cellules 35/51 de 18c portent des renvois de verdict SOTA (echo provider capture dans les sorties) - carve-out meta-note #18606, tag sota-notice sur cellules ajoutees (absorption #14032) - prose-counts (#9377) : 'discrimination 5 cellules' -> 'des 5 categories' (18c cell 35) ; '5 cellules du banc 18c re-executees' -> sans compteur (ICT-35 cell 6) - la plage exacte vit dans l'output '[extract] 5 cellules code 18c[26..33]' tenu par le code - check-links : docs/grothendieckian-lens.md:87 pointait le 18d supprime -> banc humour consolide 18c Markdown/metadata uniquement, aucune cellule code touchee. Co-Authored-By: Claude Sonnet 5.5 --- .../GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb | 10 +++++++--- .../ICT-35-HumorCausalProbe-Pilot-Python.ipynb | 2 +- docs/grothendieckian-lens.md | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/MyIA.AI.Notebooks/GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb b/MyIA.AI.Notebooks/GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb index 1f03d1103d..47c31eb487 100644 --- a/MyIA.AI.Notebooks/GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb +++ b/MyIA.AI.Notebooks/GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb @@ -1687,7 +1687,9 @@ "start_time": "2026-10-04T00:14:24.188152+00:00", "status": "completed" }, - "tags": [] + "tags": [ + "sota-notice" + ] }, "source": [ "## Détecteurs — règle vs partage (toy model, répliqué)\n", @@ -1695,7 +1697,7 @@ "On reprend les deux détecteurs du toy model GT-20 (ex-GT-24) :\n", "\n", "- **naïf** : stimulus = rire → `humour_reussi` si `laugh`, sinon `rien`\n", - "- **partage** : trois signaux (reframe + uptake + refus) → discrimination 5 cellules\n", + "- **partage** : trois signaux (reframe + uptake + refus) → discrimination des 5 catégories\n", "\n", "On y ajoute un **détecteur LLM** : `anthropic/claude-haiku-4.5` (canal épinglé\n", "OpenRouter, cf cell[26]) reçoit le `texte` d'une\n", @@ -2606,7 +2608,9 @@ "start_time": "2026-10-04T00:14:50.220201+00:00", "status": "completed" }, - "tags": [] + "tags": [ + "sota-notice" + ] }, "source": [ "## Paires minimales « unfun » — détection, appréciation et explication indépendantes (#14033)\n", diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35-HumorCausalProbe-Pilot-Python.ipynb b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35-HumorCausalProbe-Pilot-Python.ipynb index 8a6d171050..09ffafe6d5 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35-HumorCausalProbe-Pilot-Python.ipynb +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-35-HumorCausalProbe-Pilot-Python.ipynb @@ -308,7 +308,7 @@ "source": [ "## Lecture 1 -- Le sous-corpus : 120 instances, un label a 48\n", "\n", - "La sortie de l'extraction (5 cellules du banc 18c re-executees, aucune edition du notebook source) fixe le terrain : CORPUS_DUR = 120 instances, 5 categories ({'rire_sans_recadrage': 14, 'recadrage_sans_rire': 13, 'rien': 38, 'humour_reussi': 48, 'offensif_compris_non_partage': 7}) et 4 sources ({'ArgumentumGames/Argumentum': 60, 'blague-manuelle': 30, 'declaration-factuelle': 20, 'edge-case-curated': 10}).\n", + "La sortie de l'extraction (cellules du banc 18c re-executees, aucune edition du notebook source) fixe le terrain : CORPUS_DUR = 120 instances, 5 categories ({'rire_sans_recadrage': 14, 'recadrage_sans_rire': 13, 'rien': 38, 'humour_reussi': 48, 'offensif_compris_non_partage': 7}) et 4 sources ({'ArgumentumGames/Argumentum': 60, 'blague-manuelle': 30, 'declaration-factuelle': 20, 'edge-case-curated': 10}).\n", "\n", "Le label positif `humour_reussi` est la categorie la plus fournie du corpus brut (48 sur 120, soit 40 %) : la difficulte ne vient pas de sa rarete mais de la stratification du protocole, qui n'en retient que 6 (cellule suivante). C'est la premiere instance du motif « sous-corpus appauvri » du frontmatter : le protocole borne sa propre puissance statistique avant meme la premiere feature." ] diff --git a/docs/grothendieckian-lens.md b/docs/grothendieckian-lens.md index eb7a1f4c67..c1ddb9f2dc 100644 --- a/docs/grothendieckian-lens.md +++ b/docs/grothendieckian-lens.md @@ -84,7 +84,7 @@ Jusqu'ici, on a lu le dépôt série par série. Il a pourtant deux versants. D' Ce dialogue obéit à deux règles simples. La première est de patience : une idée venue d'ailleurs n'entre pas d'emblée dans ICT. Elle mûrit d'abord dans une série d'enseignement, sous la forme d'un notebook puis de variantes qui l'éprouvent, jusqu'à devenir un objet qui s'exécute ; alors seulement elle nourrit la recherche ([#12208](https://github.com/jsboige/CoursIA/issues/12208)). La seconde est de politesse : quand ICT a besoin d'une opération qu'une autre série sait déjà faire, elle ne la réécrit pas. Elle pose le problème, et laisse l'outil de cette série calculer ([#13564](https://github.com/jsboige/CoursIA/issues/13564)). C'est le deuxième mouvement, appliqué au dépôt lui-même : on y reviendra. -Dans le sens de l'enseignement vers la recherche, les ponts sont désormais nombreux. Pour savoir ce qu'un agent peut atteindre, ICT interroge les planificateurs de la série Planners au lieu d'en écrire un ([ICT-Greffe2](../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-Greffe2-EspaceAtteignable.ipynb)). La valeur d'une information pour un petit animat y est calculée deux fois, avec Infer.NET et avec PyMC, par les outils de la théorie de la décision ([ICT-12e](../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-12e-Value-of-Information-Animat-Python.ipynb)). Les extensions d'un cadre d'argumentation de Dung y sont calculées telles que la série Tweety les outille ([`ict/argumentation.py`](../MyIA.AI.Notebooks/IIT/ICT-Series/ict/argumentation.py)), et le banc d'humour le plus exigeant de la théorie des jeux ([GameTheory-18d](../MyIA.AI.Notebooks/GameTheory/GameTheory-18d-Humour-Banc-Dur-Python.ipynb)) y est exécuté tel quel. +Dans le sens de l'enseignement vers la recherche, les ponts sont désormais nombreux. Pour savoir ce qu'un agent peut atteindre, ICT interroge les planificateurs de la série Planners au lieu d'en écrire un ([ICT-Greffe2](../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-Greffe2-EspaceAtteignable.ipynb)). La valeur d'une information pour un petit animat y est calculée deux fois, avec Infer.NET et avec PyMC, par les outils de la théorie de la décision ([ICT-12e](../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-12e-Value-of-Information-Animat-Python.ipynb)). Les extensions d'un cadre d'argumentation de Dung y sont calculées telles que la série Tweety les outille ([`ict/argumentation.py`](../MyIA.AI.Notebooks/IIT/ICT-Series/ict/argumentation.py)), et le banc d'humour le plus exigeant de la théorie des jeux ([GameTheory-18c](../MyIA.AI.Notebooks/GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb)) y est exécuté tel quel. Et il y a la noix. Suivie jusqu'ici comme un pur problème de mathématiques, elle est devenue le sol sur lequel ICT mesure l'émergence dans le Jeu de la Vie, en s'appuyant sur le théorème `hashlife_correct` ([ICT-Life](../MyIA.AI.Notebooks/IIT/ICT-Series/ICT-Life-SubstratCertifie.ipynb)). Mais un pont ne vaut que son pilier le plus faible : ce théorème est vrai mais **vide là où HashLife saute** — son hypothèse de cadre ne peut jamais être satisfaite quand le saut s'exerce (`p5_large_n_hyps_unsat`, [`HashlifeCorrectness.lean`](../MyIA.AI.Notebooks/SymbolicAI/Lean/conway_lean/Conway/Life/HashlifeCorrectness.lean)). C'est une autre face de la même obstruction : le cadre était trop étroit. Le théorème qui couvre vraiment les sauts existe pourtant (celui de la route neuve, déjà déposé dans la vitrine [#17465](https://github.com/jsboige/CoursIA/issues/17465)) ; le pont reste à reposer sur ce pilier-là, et ICT a raison, en attendant, de doubler la preuve d'une calibration contre les motifs canoniques. Un problème de mathématiques pures se retrouve ainsi au cœur de la recherche. From d8b2feac64d12fb73e62268f712aa5cadb00700a Mon Sep 17 00:00:00 2001 From: jsboige Date: Sun, 4 Oct 2026 13:44:15 +0200 Subject: [PATCH 3/4] fix(gametheory,#14032): retirer la ligne 18d de docs/curriculum/recherche.md La PR supprime GameTheory-18d-Humour-Banc-Dur-Python.ipynb, mais l'index gere docs/curriculum/recherche.md (derive de COURSE_CATALOG.generated.json, regenere chaque jour sur main par catalog-cron.yml) portait encore sa ligne : l'organe check-links rougissait sur 1 nouveau lien casse. Edition chirurgicale de la ligne seule, sans renumerotation -- c'est la forme du precedent merged #16829 (fusion 03f -> 03e), et c'est l'etat que le cron reproduira apres que le catalogue aura absorbe la suppression. `_quarto.yml` et le README GameTheory etaient deja traites par la branche. Preuve locale (commande CI exacte) : python scripts/check_docs_links.py --check --base origin/main -> rc=0, OK: No new broken links (0 pre-existing, 8139 total). See #14032 Co-Authored-By: Claude Sonnet 5.5 --- docs/curriculum/recherche.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/curriculum/recherche.md b/docs/curriculum/recherche.md index 13a7101184..b9bde98cb4 100644 --- a/docs/curriculum/recherche.md +++ b/docs/curriculum/recherche.md @@ -119,7 +119,6 @@ Inférence probabiliste (Infer.NET, Pyro, PyMC), théorie de l'information inté | 88 | [GameTheory-18 : Open Games et Lentilles -- la…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-18-Open-Games-et-Lentilles-Python.ipynb) | BETA | Oui | | 89 | [GameTheory-18b : Casser la composition — où la…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-18b-Casser-la-Composition-Python.ipynb) | BETA | Oui | | 90 | [GameTheory-24 : Banc de calibration — humour, forme…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb) | BETA | Oui | -| 91 | [GameTheory-18d : Banc humour — passer à l'échelle](../../MyIA.AI.Notebooks/GameTheory/GameTheory-18d-Humour-Banc-Dur-Python.ipynb) | BETA | Non | | 92 | [GameTheory-19 : L'abstraction a dette mesurable](../../MyIA.AI.Notebooks/GameTheory/GameTheory-19-Abstraction-a-Dette-Python.ipynb) | BETA | Oui | | 93 | [GameTheory 24b : Le temoin d'impossibilite](../../MyIA.AI.Notebooks/GameTheory/GameTheory-20b-Chemin-Minimal-Temoins-Impossibilite-Python.ipynb) | BETA | Oui | | 94 | [GameTheory 20c : Le chemin minimal sur un second…](../../MyIA.AI.Notebooks/GameTheory/GameTheory-20c-Chemin-Minimal-3x2-Ordinal-Python.ipynb) | BETA | Oui | From ad28051b67647dde62422788b31ab809acf105cc Mon Sep 17 00:00:00 2001 From: jsboige Date: Sun, 4 Oct 2026 15:55:55 +0200 Subject: [PATCH 4/4] fix(gametheory,#14032): re-ancrer les citations cell[N] perimees du 18c Releve 1 de la review NanoClaw (11:45Z) : le remappage de numerotation n'avait pas converge sur tous les renvois internes. 7 re-ancrages verifies firsthand contre la numerotation absolue du head : - md 30 : controle de disjonction (cell[43] -> cell[46], site des 4 occurrences du mot et des prints [disjonction]) - md 47 : tirage random.seed(42) (cell[32] -> cell[33]) - md 50 : features calculees du label annote (cell[32] -> cell[33]) - md 63 x4 : len(CORPUS_DUR) et justifications (-> cell[33]), matrices de confusion (cell[39] -> cell[41]), print [LLM] Pas de mesure (cell[39] -> cell[42], site reel de l'impression) Conserveres car verifies corrects : md 35 cell[26] (config OpenRouter), md 49 cell[45] (section circularite), ligne acceptance cell[37]+cell[39] (experience ranking). Markdown-only, exempt C.2 ; organes rejoues : md_hierarchy drift +0, nav_chain 0 NEW, split_reading clean. Co-Authored-By: Claude Sonnet 5.5 --- .../GameTheory-18c-Humour-Banc-Python.ipynb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/MyIA.AI.Notebooks/GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb b/MyIA.AI.Notebooks/GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb index 47c31eb487..f47cbe2d8e 100644 --- a/MyIA.AI.Notebooks/GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb +++ b/MyIA.AI.Notebooks/GameTheory/GameTheory-18c-Humour-Banc-Python.ipynb @@ -1355,7 +1355,7 @@ "\n", "- **167 scénarios** au total, répartis sur **7 catégories** (`histoire` 17, `mythologie` 27, `relation intime` 36, `vie professionnelle` 30, `vie personnelle` 25, `pop culture` 18, `politique` 14). `relation intime` est la plus nombreuse — c'est la catégorie la plus propice au matériel humoristique.\n", "- **21 sous-catégories** affinent (ex. `antiquité`, `religions`, `drague et séduction`, `cinéma & télévision`). Ce grain fin servira à l'annotation heuristique de la cellule suivante.\n", - "- **Champs retenus** : `path`, `catégorie`, `sous-catégorie`, `titre`, `baratineur`, `piocheur`, `contexte`, `enjeu`, `suggestion`. Le `path` (ex. `7.3.2`) est l'identifiant de scénario utilisé pour le contrôle de disjonction de la section circularité (cell[43]).\n", + "- **Champs retenus** : `path`, `catégorie`, `sous-catégorie`, `titre`, `baratineur`, `piocheur`, `contexte`, `enjeu`, `suggestion`. Le `path` (ex. `7.3.2`) est l'identifiant de scénario utilisé pour le contrôle de disjonction de la section circularité (cell[46]).\n", "\n", "L'exemple imprimé (`baratineur` → `piocheur`) montre la structure d'un scénario Argumentum : un `baratineur` avance une interprétation, un `piocheur` doit la recadrer. C'est précisément la mécanique « recadrage partagé » que la cellule `humour_reussi` modélise." ] @@ -2439,7 +2439,7 @@ "source": [ "### Lecture — 60 consommés, 107 tenus à l'écart, disjonction prouvée\n", "\n", - "Le contrôle de circularité #13306 repose sur un prédicat reproductible : tout scénario dont le `path` figure dans `arg_sample` (60 scénarios tirés avec `random.seed(42)` en cell[32]) est « consommé » ; les autres sont « tenus à l'écart ».\n", + "Le contrôle de circularité #13306 repose sur un prédicat reproductible : tout scénario dont le `path` figure dans `arg_sample` (60 scénarios tirés avec `random.seed(42)` en cell[33]) est « consommé » ; les autres sont « tenus à l'écart ».\n", "\n", "- **60 consommés, 107 tenus à l'écart** (167 total) — l'arithmétique corrigée de l'issue #13306 (`167 - 60`, pas `167 - 120` qui concaténait corpus de travail et consommation Argumentum).\n", "- **Disjonction prouvée par trois contrôles** : intersection des paths = 0, union = 167 (total), intersection des ids `arg-*` du `CORPUS_DUR` avec le tenu-à-l'écart = 0. L'`assert` passe — les ensembles sont mathématiquement disjoints, pas seulement « différents ».\n", @@ -2577,7 +2577,7 @@ "circularité **la plus grossière** (surapprentissage des instances spécifiques du\n", "corpus) est écartée. Mais la trace algébrique ci-dessus montre **pourquoi il ne\n", "pouvait pas en être autrement** : sur les instances Argumentum, les features sont\n", - "calculées À PARTIR du label annoté (cell[32]), et le détecteur inverse cette\n", + "calculées À PARTIR du label annoté (cell[33]), et le détecteur inverse cette\n", "fonction — seul `humour_reussi` produit `reframe + uptake`, donc précision =\n", "rappel = 1 **par construction**, sur n'importe quel échantillon Argumentum,\n", "tenu-à-l'écart compris. L'intervalle bootstrap dégénéré `[1.000, 1.000]` est la\n", @@ -3736,9 +3736,9 @@ "| Critère | Statut | Preuve |\n", "|---|---|---|\n", "| ≥1 corpus réel intégré (Argumentum) | **OK** | 167 scénarios CSV + 60 échantillonnés |\n", - "| ≥100 instances annotées, négatifs inclus, équilibré | **OK** | `len(CORPUS_DUR)` cell[32] |\n", + "| ≥100 instances annotées, négatifs inclus, équilibré | **OK** | `len(CORPUS_DUR)` cell[33] |\n", "| ≥1 expérience ranking LLM, sorties committées | **OK** | cell[37] + cell[39] |\n", - "| Matrices confusion mises à jour | **OK** | cell[39] : naïve vs partage vs LLM |\n", + "| Matrices confusion mises à jour | **OK** | cell[41] : naïve vs partage vs LLM |\n", "| Placement tranché et documenté | **OK** | GT-24b (comment user 15:46Z) |\n", "\n", "> *Numérotation : le renommage #18001 a renuméroté ce carnet GT-24b → GT-18d et le toy model GT-24 → GT-20. La preuve de placement ci-dessus cite le numéro à la date du commentaire user.*\n", @@ -3749,7 +3749,7 @@ "vérifié par écho provider (SOTA-OK). Le endpoint LAN vLLM `qwen3.6-35b-a3b`\n", "d'origine est documenté injoignable (HTTP 000, 2026-09-13) — basculement\n", "journalisé, pas de fallback dégradé : si l'endpoint échoue (réseau /\n", - "maintenance), le diagnostic le dit explicitement (cf cell[39], `[LLM] Pas de mesure`).\n", + "maintenance), le diagnostic le dit explicitement (cf cell[42], `[LLM] Pas de mesure`).\n", "\n", "### Limites et suite\n", "\n", @@ -3761,7 +3761,7 @@ " label), pas une performance — verdict `CIRCULARITE_GROSSIERE_ECARTEE` avec\n", " réserve structurelle, cf section dédiée. Validation réelle : #12756 ou\n", " features annotées depuis le texte.\n", - "- **Corpus annoté** = curation manuelle (avec justifications cell[32]).\n", + "- **Corpus annoté** = curation manuelle (avec justifications cell[33]).\n", " Pas de corpus académique blagues publiquement annoté sur ce cycle. Si\n", " dispo, intégrer par exemple le corpus `humour-classification` Kaggle\n", " ou `short-jokes` dataset (post-cycle).\n",