PHAROS: Vier Agenten, 60 Sekunden, eine übersehene Arzneimittelsicherheitswarnung von der Katastrophe entfernt

Elasticsearch Agent Builder Hackathon

pharos-blog.png

Die FDA erhält jährlich etwa zwei Millionen Meldungen über unerwünschte Arzneimittelwirkungen. Pharmaunternehmen sind gesetzlich verpflichtet, Sicherheitssignale innerhalb von 15 Kalendertagen nach Eingang einer schwerwiegenden Meldung zu erkennen. In der Praxis sichten Pharmakovigilanz-Analysten manuell Dokumente, die über das FDA-Meldesystem für unerwünschte Ereignisse (FAERS), EudraVigilance, elektronische Patientenakten (EHRs) und soziale Medien verstreut sind. Die Erkennung dauert Wochen bis Monate, und jedes Signal beansprucht mehr als 40 Stunden Analystenzeit.

Die Kosten für Langsamkeit sind nicht abstrakt. Mercks Versäumnis, Herzsignale von Vioxx zu erkennen, führte zu Vergleichen in Höhe von 4,85 Milliarden Dollar. Ein einziges übersehenes Signal kann Bußgelder zwischen 100 Millionen und 1 Milliarde Dollar nach sich ziehen. Doch die eigentlichen Kosten sind, dass Patienten Medikamente einnehmen, die hätten gemeldet werden müssen, während niemand schnell genug reagierte.

Ich bin Prajwal Sutar, ein unabhängiger Entwickler, der das vergangene Jahr damit verbracht hat, echte Daten durch große, auf Sprachmodellen (Large Language Models, LLMs) basierende Pipelines zu verarbeiten – von der Ingestion über die asynchrone Orchestrierung bis hin zur Multiagenten-Koordination. Ich konnte kein einziges bestehendes Tool finden, das Signalerkennung, Berichtserstellung und Eskalation in einer automatisierten Pipeline verbindet. Also habe ich während des Elasticsearch Agent Builder Hackathon einen erstellt.

Was PHAROS macht

PHAROS (Pharmacovigilance Autonomous Reasoning and Oversight System) ruft Berichte über unerwünschte Ereignisse aus der FDA-FAERS-API ab, führt statistische Analysen nach WHO-Standard durch, um Sicherheitssignale zu finden, generiert die eigentlichen regulatorischen Unterlagen (z. B. MedWatch 3500A-Formulare, PSUR-Abschnitte und Fallberichte) und sendet Warnmeldungen an Slack, Jira und E-Mail.

Von der Daten-Ingestion bis zum Senden der Alarmmeldung vergehen weniger als 60 Sekunden.

So sieht das von Anfang bis Ende aus. Es gehen 50 Berichte über unerwünschte Ereignisse für ein fiktives Medikament namens CARDIVEX ein, die alle über plötzlichen Sehverlust in Japan, Korea und Indien berichten. Sie werden indexiert. Innerhalb einer Minute hat das System ein proportionales Berichtsverhältnis (PRR) von 18,94 für CARDIVEX/Sehverlust festgestellt, den geografischen Cluster JP/KR/IN identifiziert, ein MedWatch 3500A-Formular und einen PSUR-Abschnitt erstellt, einen Slack-Alert an #safety-critical ausgelöst, ein Jira-P1-Ticket erstellt und eine E-Mail an den Arzneimittelsicherheitsbeauftragten geschickt. Jede Aktion wurde im pharos-audit-log protokolliert – denn in der Pharmaindustrie gilt: Was nicht protokolliert wurde, ist auch nicht passiert.

Vier Agenten sind dafür zuständig, jeder mit einer anderen Aufgabe.

Warum vier Agenten, nicht nur einer

Ich habe das System aufgeteilt, weil die Aufgaben derart unterschiedlich sind, dass ein einziger Agent in allen Bereichen nur mittelmäßig wäre. Die Überwachung von Volumenspitzen ist nicht dasselbe wie die Berechnung statistischer Kennzahlen, das Verfassen regulatorischer Dokumente und die Entscheidung, wen man nachts um 2 Uhr kontaktiert. Jeder Agent erhält einen Systemprompt, der auf seine spezifische Aufgabe abgestimmt ist, und Temperatureinstellungen, die übereinstimmen: ANALYST wird mit 0,0 ausgeführt, weil wir keine kreativen PRR-Nummern wünschen. SCRIBE läuft mit 0,2 für kontrollierte Textgenerierung. SENTINEL mit 0,1.

Der Wächter

SENTINEL überwacht den pharos-adverse-events-Index auf Volumenspitzen. Mithilfe von ES|QL vergleicht es das Berichtsvolumen der letzten 7 Tage mit einem 90-Tage-Basiswert. Bei einem dreifachen Anstieg der Meldungen bezüglich eines Medikaments startet SENTINEL einen Elastic-Workflow, der ANALYST aufruft. Im CARDIVEX-Lauf wurde ein 15-facher Anstieg festgestellt.

Der Analyst

ANALYST ist der Ort, an dem die eigentliche Erkennung stattfindet. Es führt die WHO-PRR-Berechnung vollständig in ES|QL aus – STATS für die Zählungen, EVAL für die Verhältnisberechnung und WHERE für die Schwellenwerte – und zwar für alle Arzneimittel-Reaktionspaare. Dann führt es eine zeitliche Analyse mit BUCKET(report_date, 1 week) durch, um wöchentliche Cluster zu erkennen, eine geografische Aggregation auf der Grundlage von geo.country_code durchzuführen und eine hybride BM25- + dichte Vektorsuche zu nutzen, um ähnliche historische Signale zu finden. Die Klassifizierung des Schweregrads ist gestaffelt: PRR ≥ 5,0 mit 5+ Fällen ist KRITISCH, PRR ≥ 2,0 mit 3+ Fällen ist HOCH, und alles über 1,5 geht in die Kategorie ÜBERWACHUNG. Bestätigte Signale werden in pharos-signals gespeichert.

Der Schreiber

SCRIBE erfasst bestätigte Signale und generiert drei Dokumenttypen: MedWatch 3500A, PSUR Abschnitt VI und einen Fallbericht. Es ruft bis zu 100 unterstützende Fallberichte aus dem Index unerwünschter Ereignisse ab, erstellt die Dokumente und indexiert sie in pharos-regulatory-reports.

Der Herold

HERALD ist die Handlungsebene. KRITISCHE Signale erhalten eine Slack-Benachrichtigung (Block Kit-Formatierung), ein Jira P1-Ticket und E-Mails an den Sicherheitsbeauftragten und den Sicherheits-Vizepräsidenten. HOHE Signale erhalten Slack, Jira P2 und eine E-Mail an den Sicherheitsbeauftragten. ÜBERWACHUNGS-Signale werden in einem wöchentlichen Bericht zusammengefasst. Ein 2-stündiges Eskalations-Timeout informiert den Sicherheits-VP erneut, wenn ein KRITISCHES Signal unbestätigt bleibt.

Die Übergaben zwischen den Agenten erfolgen alle über Elastic-Workflows – insgesamt neun Workflows, die die Agenten-zu-Agenten-Koordination, die nächtliche FAERS-Ingestion nach einem Cron-Plan, den Versand über Slack/Jira/E-Mail, das Audit Logging und das Eskalations-Timeout abdecken.

Statistiken bleiben in Elasticsearch

Ich habe mich bewusst dafür entschieden, die PRR-Berechnung innerhalb von ES|QL durchzuführen, anstatt die Daten in Python zu laden. Anfangs dachte ich, dass ich pandas für die statistische Arbeit benötigen würde. Ich lag falsch.

Die vollständige WHO-PRR-Formel, Zählungen, Verhältnisberechnungen, Schwellenwerte und zeitliche Gruppierungen – all das wird als ES|QL-Abfragen ausgeführt. Die Agenten rufen ES|QL-Tools auf, interpretieren die Ergebnisse und schreiben zurück – kein pandas, keine externe Berechnung und kein Engpass beim Datentransfer. Die Kennzahlen skalieren mit dem Cluster.

ES|QL ist für beliebige Analysen weniger flexibel als pandas. Für die WHO-Formel und wöchentliche BUCKET-Aggregationen funktioniert es aber einwandfrei. Das Weglassen der zwischengeschalteten Python-Schicht hat die Architektur stärker vereinfacht als erwartet – die Agenten führen nur noch Abfragen und Schlussfolgerungen durch, und es gibt eine Fehlerquelle weniger.

Das Indexdesign, das dafür sorgt, dass es funktioniert

PHAROS läuft auf vier Elasticsearch-Serverless-Indizes, und der Hauptindex, pharos-adverse-events, ist der Ort, an dem ich die meiste Zeit für das Design aufgewendet habe.

Er verfügt über einen benutzerdefinierten clinical_text_analyzer mit Snowball Stemming für die narrative Suche, einen drug_name_analyzer auf Keyword-Tokenizer für die exakte Medikamentensuche, dense_vector-Felder (1.536 Dimensionen) für narrative Einbettungen, geo_point für geografisches Clustering und nested-Mappings für Reaktionen. Jede Abfrage, die die Agenten benötigen, Fuzzy-Suche, exakte Medikamentensuche, geografische Aggregation, semantische Ähnlichkeit, wird durch das Indexdesign unterstützt. Die anderen drei Indizes sind einfacher: pharos-signals speichert erkannte Signale mit PRR-Bewertungen und der Argumentationskette des Analysten, pharos-regulatory-reports enthält generierte Dokumente und pharos-audit-log erfasst den Zeitpunkt jeder Agentenaktion.

Das unscheinbare Problem, das die Pipeline beinahe zum Erliegen brachte.

Dass ich LLMs dazu bringen musste, zuverlässig strukturiertes JSON zurückzugeben, war das Problem, das ich nicht erwartet hatte.

Wenn man ein LLM um JSON bittet, erhält man JSON, eingebettet in drei Absätze Erklärung, JSON innerhalb von Markdown-Code-Fences oder eine konversationelle Einleitung, gefolgt von JSON und einer hilfreichen Zusammenfassung. Die Agenten übergeben sich strukturierte Daten, daher muss jede Reaktion sauber geparst werden. Es spielt keine Rolle, wie gut Ihre Signalerkennung ist, wenn die Ausgabe des ANALYST nicht zuverlässig von SCRIBE gelesen werden kann.

Ich habe viel Zeit damit verbracht, Systemaufforderungen zu optimieren und habe schließlich eine JSON-Extraktionsfunktion geschrieben, die rohes JSON, Markdown-Code-Zäune und in natürlicher Sprache eingebettetes JSON verarbeiten kann. Es ist keine besonders interessante Arbeit, aber genau solche Dinge entscheiden darüber, ob eine Multiagenten-Pipeline tatsächlich funktioniert oder nur gut in Demos aussieht.

Was ich zuerst beheben würde

Die PRR-Berechnung ist derzeit eine Punktschätzung. Ein Produktions-Pharmakovigilanzsystem benötigt Chi-Quadrat-Konfidenzgrenzen und Bayesian IC-Scoring. Das Datenmodell hat bereits ein ic_score-Feld – es verwendet eine Näherung anstelle der korrekten Bayesian-Berechnung. Das wäre das Erste, was ich ändern würde.

Das System behandelt auch „verschwommenes Sehen“ und „Sehverlust“ als separate Ereignisse. Der nächste unmittelbare Schritt ist die MedDRA-Ontologie-basierte Reaktionsgruppierung, damit das System Signale über verwandte Begriffe hinweg erfassen kann, anstatt jede Zeichenfolge als unabhängig zu behandeln. Anschließend würde ich EudraVigilance-Daten zusammen mit FAERS-Daten für die kontinentübergreifende Korrelation einbeziehen.

Der umfassendere Punkt

2 Mio. Berichte über unerwünschte Ereignisse landen jedes Jahr auf dem Schreibtisch eines Mitarbeiters, und die aktuelle Antwort lautet: mehr Analysten, die mehr manuelle Überprüfungen durchführen. PHAROS ist ein Argument dafür, dass die Antwort Agenten sind, die die WHO-Statistiken ausführen, die Papierarbeit generieren und an die richtige Person eskalieren – alles, bevor der Analyst seinen Laptop geöffnet hat.

PHAROS ist Open Source unter MIT. Wenn Sie in der Pharmakovigilanz oder in regulatorischen Angelegenheiten arbeiten und dies mit echten Daten ausführen möchten, würde ich gerne von Ihnen hören.

Prajwal Sutar

Unabhängiger Entwickler ,

Prajwal Sutar ist ein unabhängiger Entwickler mit Schwerpunkt auf KI-Systemen und groß angelegten Daten-Pipelines.

GitHub · Demo · LinkedIn

Die Entscheidung über die Veröffentlichung der in diesem Blogeintrag beschriebenen Leistungsmerkmale und Features sowie deren Zeitpunkt liegt allein bei Elastic. Es ist möglich, dass noch nicht verfügbare Leistungsmerkmale oder Features nicht rechtzeitig oder überhaupt nicht veröffentlicht werden.

In diesem Blogpost haben wir möglicherweise generative KI-Tools von Drittanbietern verwendet oder darauf Bezug genommen, die von ihren jeweiligen Eigentümern betrieben werden. Elastic hat keine Kontrolle über die Drittanbieter-Tools und übernimmt keine Verantwortung oder Haftung für ihre Inhalte, ihren Betrieb oder ihre Anwendung sowie für etwaige Verluste oder Schäden, die sich aus Ihrer Anwendung solcher Tools ergeben. Gehen Sie vorsichtig vor, wenn Sie KI-Tools mit personenbezogenen, sensiblen oder vertraulichen Daten verwenden. Alle von Ihnen eingegebenen Daten können für das Training von KI oder andere Zwecke verwendet werden. Es gibt keine Garantie dafür, dass von Ihnen bereitgestellte Informationen sicher oder vertraulich behandelt werden. Setzen Sie sich vor Gebrauch mit den Datenschutzpraktiken und den Nutzungsbedingungen generativer KI-Tools auseinander. 

Elastic, Elasticsearch und zugehörige Marken sind Marken, Logos oder eingetragene Marken von Elasticsearch B.V. in den Vereinigten Staaten und anderen Ländern. Alle anderen Unternehmens- und Produktnamen sind Marken, Logos oder eingetragene Marken ihrer jeweiligen Eigentümer.