International Essays
Original-Beitrag
Dieses Notebook ist die deutschsprachige Übersetzung des Beitrags “Using AI for Thematic Analysis: Analyzing Coroner Reports with LLMs” vom 21. Januar 2025, die mithilfe eines LLM-Tools erstellt und von einer professionellen Übersetzerin überprüft wurde.

KI für thematische Analyse verwenden: Gerichtsmedizinische Berichte mit LLMs analysieren

21. Januar 2025
Harrison Boon, ehemaliger Praktikant & Gastautor und Ned Pratt, ehemaliger Praktikant & Gastautor
Im Vereinigten Königreich spielen Formulare zur Verhinderung zukünftiger Todesfälle (Prevention of Future Deaths-Berichte, kurz PFDs) eine entscheidende Rolle bei der Gewährleistung der öffentlichen Sicherheit. Dies ist eine spezielle Art von Gerichtsmedizinerbericht, der mehr als nur die Umstände des Todes einer Person dokumentiert. PFDs werden ausgestellt, wenn ein Gerichtsmediziner einen Todesfall untersucht und feststellt, dass ein spezifisches Risiko oder ein systemisches Versagen – das als vermeidbar eingestuft wird – eine bedeutende Rolle bei besagtem Todesfall gespielt hat.
Obwohl diese Berichte insofern strukturiert sind, als sie Abschnitte enthalten, die von Gerichtsmedizinerinnen und Gerichtsmedizinern auszufüllen sind, werden diese in freier, natürlicher Sprache verfasst. Dadurch gestaltet sich die Analyse der Formulare bislang sehr zeitaufwendig, da jeder Bericht einzeln von einer Person gelesen werden muss.
Die umfangreiche Liste eingebauter Funktionen von Wolfram Language ermöglicht es, Aufrufe an verschiedene große Sprachmodelle (LLMs) aus dem Wolfram-Kernel heraus zu machen. Die Implementierung von LLMs innerhalb von Wolfram bedeutet, dass die Extraktion unstrukturierter Daten, wie beispielsweise die Inhalte eines Gerichtsmedizinerberichts, in einem Bruchteil der Zeit durchgeführt wird. Wir können dann Wolframs Datenanalyse-Tools verwenden, um das zu verarbeiten, was wir gesammelt haben.

Daten sammeln

Die Judikative des Vereinigten Königreichs (UK Courts and Tribunals Judiciary) veröffentlicht eine Auswahl dieser PFDs auf ihrer Website. Leider haben sie keine öffentliche API für den Zugriff auf diese Dateien, was bedeutet, dass der einzige Weg, die Dateien anzusehen, darin besteht, die Seite zu besuchen und jede Datei zu finden. Dies würde von Hand sehr lange dauern, daher müssen wir einen Web Scraper erstellen, um durchzugehen und die PFDs automatisch herunterzuladen:
Hinweis: Alle Daten stammen aus den Courts and Tribunal Judiciary Prevention of Future Death Reports unter der 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​​ ]
Testen wir, dass dieser Code funktioniert, indem wir die ersten beiden Seiten mit Links abrufen:
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}
Ausgezeichnet! Verwenden wir nun den Code, um von mehr Seiten zu ziehen:
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"]
Lassen Sie uns nun alle Seiten importieren, um den kompletten Text des Dokuments zu erhalten:
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

Daten extrahieren

Nachdem die Daten nun erhoben wurden, bietet sich als interessante Anwendung an, die Dauer dieser Untersuchungen im Zeitverlauf darzustellen. Der traditionelle Ansatz bestünde darin, sämtliche Berichte manuell zu lesen und die jeweiligen Start- und Enddaten der Untersuchungen per Hand in eine Tabellenkalkulation zu übertragen. Dies klingt sehr zeitaufwändig (und langweilig). LLMs können hier äußerst hilfreich sein, da sie über genügend Wissen verfügen, um den Bericht zu lesen und nur die beiden Daten zu extrahieren, während sie bei weitem nicht so lange brauchen wie ein Mensch.
Ein Nachteil bei der Verwendung von LLMs ist, dass oft viel Prompting in sie investiert werden muss, um ihr Verhalten zu beschränken. Bei ungenauem oder vage formuliertem Prompting erweist sich das LLM oft als wenig hilfreich und produziert unerwartete Ergebnisse. Glücklicherweise hat Wolfram einen guten Weg, diesem Nachteil entgegenzuwirken.
LLMExampleFunction
nimmt nicht nur standardmäßiges Prompting als Argument entgegen, sondern ermöglicht es Ihnen auch, eine Liste von Beispielen zu übergeben, denen das LLM folgen soll:
Einige Beispiele in diesem Beitrag basieren auf einem großen Sprachmodell (LLM) und erfordern einen API-Schlüssel.
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

Dieser Code verwendet LLMExampleFunction, um eine Funktion zu erstellen, die importierte PDFs als Eingabe nimmt und eine Liste mit den Start- und Enddaten der Untersuchungen zurückgibt:
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]&]​​];
Ein Zeitachsen-Diagramm einer zufälligen Stichprobe der Ergebnisse zeigt, dass es das zurückgab, was erwartet wurde (jede Linie im Diagramm repräsentiert eine Untersuchung):

Praxisanwendungen

Frühere akademische Forschung von Alison Leary et al. hat die Hauptbereiche der Besorgnis untersucht, die Gerichtsmediziner in ihren Berichten zum Ausdruck bringen. Hier verwenden wir die resultierenden Kategorien dieser Forschung und wenden sie auf unsere eigenen Daten an. Damit sind wir in der Lage, frühere Erkenntnisse aus der Wissenschaft, die Rechenkraft von Wolfram Language und die Sprachgewandtheit von LLMs zu kombinieren, um Erkenntnisse aus einem viel größeren Datenkorpus zu gewinnen:

Code zur Kategorisierung

Visuelle Darstellung

Indem wir jede Kategorie für jedes Jahr, für das wir Berichte haben, in einem Balkendiagramm darstellen, können wir die häufigsten PFDs sehen:
Ein gestapeltes Balkendiagramm ist eine alternative Möglichkeit, dieselben Daten zu visualisieren, die es uns ermöglicht, uns auf den Anteil jeder Kategorie innerhalb jedes Jahres zu konzentrieren. Obwohl über die Jahre hinweg grob konsistent, können wir einige zeitliche Trends erkennen, zum Beispiel den Höhepunkt bei Kommunikationsproblemen im Jahr 2020. Der Balken für 2024 ist viel kleiner, da die Daten im Sommer 2024 gesammelt wurden. Zu diesem Zeitpunkt waren meisten Berichte für dieses Jahr noch nicht eingereicht worden:
Um die aktuellen Trends besser zu visualisieren, können wir das gestapelte Balkendiagramm proportional zu 100% der jährlichen Bedenken erstellen. Dabei zeigt sich, dass Kommunikationsprobleme im Vergleich zu den Vorjahren einen zunehmenden Anteil am Gesamtaufkommen haben und möglicherweise wieder das Niveau des Jahres 2020 erreichen.
Interessanterweise spiegeln diese Ergebnisse größtenteils die in Learys Arbeit gefundenen wider. Dies deutet darauf hin, dass der Einsatz von LLMs in den Anfangsphasen von Aufgaben, die darauf abzielen, Erkenntnisse aus natürlicher Sprache zu extrahieren – wie thematische Analysen – ein wertvoller erster Schritt sein kann, um Bedeutung aus unstrukturierten Daten zu gewinnen. Das dürfte besonders in Fällen zutreffen, in denen breite Kategorien bereits durch frühere Arbeiten definiert wurden und diese Definitionen als Anweisungen an die LLMs weitergegeben werden können.

Ausblick

Mit Wolfram-Technologie können wir schnell Daten sammeln und aufbereiten, um mehr Zeit für Analysen und das Finden von Lösungen zur Verbesserung zukünftiger Praktiken zu haben.Zur weiteren Unterstützung bei der Umsetzung eines automatisierten und berechnungsbasierten Workflows schauen Sie sich unbedingt den neuen Wolfram Notebook Assistant an!