Utilisation de l’IA pour l’analyse thématique : analyse des rapports d’un coroner avec les LLM

21 janvier 2025
Harrison Boon, ancien stagiaire et auteur invité, et Ned Pratt, ancien stagiaire et auteur invité
Article original
Au Royaume-Uni, les formulaires de prévention des décès futurs (Prevention of Future Deaths forms - PFD) jouent un rôle crucial pour assurer la sécurité publique. Il s’agit d’un type particulier de rapport établi par un médecin légiste qui ne se limite pas aux circonstances du décès d’une personne. Les PFD sont établis lorsqu’un médecin légiste enquête sur un décès et décide qu’un risque spécifique ou une défaillance systémique jugée évitable a joué un rôle important dans ce décès.
Bien que ces formulaires aient une structure, dans la mesure où ils comportent des sections qui doivent être remplies par les médecins légistes, les médecins légistes remplissent ces sections en langage naturel, ce qui rend l’analyse de ces formulaires (jusqu’à présent) très fastidieuse, chaque rapport devant être lu par un humain.
La longue liste des fonctions intégrées de Wolfram Language permet d’appeler différents modèles de langage (LLM) à partir du noyau Wolfram. La mise en œuvre des LLM au sein de Wolfram signifie que l’extraction de données non structurées, telles que le contenu d’un rapport de médecin légiste, est réalisée en une fraction du temps. Nous pouvons ensuite utiliser les outils d’analyse de données de Wolfram pour traiter ce que nous avons recueilli.

Collecte des données

L’administration judiciaire des cours et tribunaux britanniques publie un échantillon de ces PFD sur son site web. Malheureusement, ils n’ont pas d’API publique pour accéder à ces fichiers, ce qui signifie que la seule façon de les visualiser est de visiter la page et de trouver chaque fichier. Cela prendrait beaucoup de temps à faire à la main, c’est pourquoi nous devrons créer une extraction de données web pour aller chercher et télécharger automatiquement les PFD :
Remarque : toutes les données sont tirées de Courts and Tribunal Judiciary Prevention of Future Death Reports sous Open Government Licence v3 .0.
In[]:=
(* To keep things simple, I'm only collecting pfd reports of a certain type *) ​​pfdReportTypes=​​ "hospital-death-clinical-procedures-and-medical-management-related-deaths",​​ "alcohol-drug-and-medication-related-deaths",​​ "care-home-health-related-deaths",​​ "community-health-care-and-emergency-services-related-deaths",​​ "emergency-services-related-deaths-2019-onwards",​​ "mental-health-related-deaths"​​;​​​​getPFDList[start_, end_] :=​​ Block[{htmlDocs, individualPageLinks, individualPages},​​ htmlDocs = Table[Import[URLBuild[<|​​ "Scheme" -> "https",​​ "Domain" -> "www.judiciary.uk",​​ "Path" -> {"page", ToString[i]}, (* Iterate through the pages *)​​ "Query" -> ​​ "pfd_report_type" -> #, (* Cycle throught just the report types we want *)​​ "post_type" -> "pfd",​​ "order" -> "desc"​​ ,​​ "Fragment" -> None​​ |>], "Text"]& /@ pfdReportTypes, {i, start, end}];​​ ​​ (* Now that we've got a list of the results pages, we need to grab each individual report's page *)​​ ​​ individualPageLinks = Flatten[StringCases[#, "<a class=\"card__link\" href=\"" ~~ Shortest[url___] ~~ "\"" :> url]& /@ htmlDocs];​​ individualPageLinks = DeleteDuplicates[individualPageLinks]; (* The searches may have had overlapping results, which should be removed *)​​ ​​ (* Each of these pages contains a link to a PDF file with the reports we want *)​​ ​​ individualPages = Import[#, "Text"]& /@ individualPageLinks;​​ First[StringCases[#, "related-content__link\" href=\"" ~~ Shortest[url___] ~~ "\"" :> url] ]& /@ individualPages​​ ]
Testons le fonctionnement de ce code en obtenant les deux premières pages de liens :
In[]:=
getPFDList[1,2]//Short
Out[]//Short=
{https://www.judiciary.uk/wp-content/uploads/2024/08/Beverley-Stanisauskis-Prevention-of-Future-Deaths-Report-2024-0466.pdf,114,https://www.judiciary.uk/wp-content…aths-report-2024-0087_Published.pdf}
C’est génial ! Utilisons-le maintenant pour extraire d’autres pages :
In[]:=
pfdLinks=getPFDList[1,2];
In[]:=
pfdLinks=getPFDList[1,60];
In[]:=
pfdLinks//Short
Out[]//Short=
{https://www.judiciary.uk/wp-content/uploads/2024/10/Kingsley-Imafidon-Prevention-of-Future-Deaths-Report-2024-0554.pdf,2216,https://www.judici…-0195-Redacted.pdf}
In[]:=
pfdLinks>>pfdtexts
In[]:=
Export["links.txt",<<pfdtexts]
Out[]=
links.txt
In[]:=
SystemOpen["links.txt"]
Importons-les toutes pour obtenir le texte du document :
In[]:=
pdfs=Import[#,"Plaintext"]&/@pfdLinks
In[]:=
pdfsWithLinks=<|"Link"->#1,"Text"->#2|>&@@@Thread[{#1,#2}&[pfdLinks,pdfs]];​​pdfsWithLinks=Select[pdfsWithLinks,StringLength[#Text]>150&];(*Filteroutanyemptyorincompletereports*)​​pdfsWithLinks//Dataset

Extraction des données

Les données étant désormais collectées, il est intéressant d’examiner la durée de ces enquêtes dans le temps. La méthode traditionnelle consisterait à demander à quelqu’un de lire tous ces rapports et de saisir manuellement les dates de début et de fin d’une enquête dans une feuille de calcul. Cela semble très long (et ennuyeux). Les LLM peuvent être extrêmement utiles dans ce cas, car ils possèdent suffisamment de connaissances pour pouvoir lire le rapport et en extraire uniquement les deux dates, tout en prenant beaucoup moins de temps qu’un être humain.
L’un des inconvénients de l’utilisation des LLM c’est qu’ils doivent souvent être accompagnés d’un grand nombre de requêtes afin de limiter leur comportement. Avec des consignes imprécises ou formulées en termes vagues, les LLM finissent souvent par être très peu utiles et par produire des résultats inattendus. Heureusement, Wolfram dispose d’un bon moyen de remédier à cet inconvénient.
LLMExampleFunction
ne prend pas seulement l’invite standard comme argument, mais vous permet également de transmettre une liste d’exemples à suivre par les LLM :
Certains exemples de ce post s’appuient sur un grand modèle linguistique (LLM) et nécessitent une clé API.
In[]:=
extractDates = LLMExampleFunction[​​ "Extract the dates of both the start of an investigation and the end of an investigation. If you cannot find a date, return None",​​ ​​ Import["https://www.judiciary.uk/wp-content/uploads/2024/07/Paula-Elsley-Prevention-of-future-deaths-report-2024-0361_Published.pdf", "Plaintext"] ->​​ "{{2022,4,11},{2024,2,6}}",​​ Import["https://www.judiciary.uk/wp-content/uploads/2024/07/Lee-McHale-Prevention-of-future-deaths-report-2024-0356_Published.pdf", "Plaintext"] ->​​ "{{2023,11,28},{2024,6,17}}"​​ ​​ ​​]
Out[]=
LLMFunction
​
Parameters: 1

Ce morceau de code utilise LLMExampleFunction pour créer une fonction qui prend en entrée des PDF importés et fournit une liste contenant les dates de début et de fin des enquêtes :
In[]:=
datePairs=Monitor[Table[extractDates[pdfsWithLinks[[i,"Text"]]],{i,Length@pdfsWithLinks}],i]
Out[]=
In[]:=
datePairs=ToExpression/@datePairs
In[]:=
datePairs=extractDates/@pdfsWithLinks[[All,"Text"]];​​datePairs=ToExpression/@datePairs(*TurnsthestringstheLLMreturnedintoWolframexpressions*)
​
In[]:=
pfdsWithDates=Block[{pfd,newList,datePair},​​newList={};​​Table[​​pfd=pdfsWithLinks[[i]];​​datePair=datePairs[[i]];​​Quiet@AssociateTo[pfd,{"StartDate"->DateObject[datePair[[1]]],"EndDate"->DateObject[datePair[[2]]]}];​​AppendTo[newList,pfd];​​,{i,Length[pdfsWithLinks]}​​];​​Select[newList,FreeQ[#,None]&]​​];
Le tracé chronologique d’un échantillon aléatoire des résultats montre qu’il a renvoyé les résultats escomptés (chaque ligne du tracé représente une enquête) :

Applications du monde réel

Des recherches universitaires antérieures menées par Alison Leary et al. ont porté sur les principaux sujets de préoccupation exprimés par les médecins légistes dans leurs rapports. Nous utilisons ici les catégories obtenues dans le cadre de cette recherche et les appliquons à nos propres données. Nous sommes ainsi en mesure de combiner les connaissances acquises dans le monde universitaire, la puissance de calcul de Wolfram Language et la fluidité des LLM pour recueillir des informations sur un corpus de données beaucoup plus important :

Code de catégorisation

Traçage

En traçant un diagramme à barres pour chaque catégorie et chaque année pour laquelle nous disposons de rapports, nous pouvons voir quels sont les PFD les plus courants :
Une autre manière de visualiser les mêmes données est d’utiliser un diagramme à barres empilées, ce qui nous permet de nous concentrer sur la proportion de chaque catégorie au sein de chaque année. Bien que les données soient à peu près constantes d’une année à l’autre, nous pouvons déceler certaines tendances temporelles, par exemple le pic des problèmes de communication en 2020. La barre pour 2024 est beaucoup plus petite car les données ont été collectées au cours de l’été 2024, alors que la plupart des rapports pour cette année-là n’avaient pas encore été soumis :
Pour mieux visualiser les tendances actuelles, nous pouvons faire en sorte que le diagramme à barres empilées soit proportionnel à 100 % par rapport aux préoccupations de l’année. Nous constatons alors que les questions de communication sont en passe de représenter une part plus importante du total des préoccupations par rapport aux années précédentes, et qu’elles pourraient atteindre le niveau de 2020 :
Il est intéressant de constater que ces résultats reflètent en grande partie ceux trouvés dans les travaux de Leary. Cela suggère que l’utilisation des LLM dans les étapes initiales des tâches qui visent à extraire des informations du langage naturel, telles que les analyses thématiques, peut constituer une première étape précieuse pour comprendre le sens des données non structurées. Cela devrait être particulièrement vrai dans les cas où de grandes catégories ont déjà été définies par des travaux antérieurs, et où ces définitions peuvent être transmises aux LLM sous forme de consignes.

Pour aller de l’avant

Grâce aux technologies Wolfram, nous pouvons rapidement rassembler et préparer des données afin de passer plus de temps à faire des analyses et à trouver des solutions pour améliorer les pratiques à l’avenir. Pour obtenir de l’aide supplémentaire afin d’apprendre à calculer votre flux de travail, n’oubliez pas de consulter le tout nouveau Wolfram Notebook Assistant !