Hat sich schon jemand mit diesem Thema beschäftigt? - So ein Automation würde extrem viel Arbeit sparen. Wäre sicher kein Hexenwerk, wir machen das schon mit der Patientenzuordnung über ein kleines Programm das klappt ganz gut. Ich würde das gerne in Angriff nehmen und biete eine Beteiligung im Rahmen eines Crowdfundings an.
Gefragt in Frage von (9.9k Punkte)
+7 Punkte
läuft das dann über einen Drittanbieter? Oder was ist da der genaue Plan?
Mich würden auch Details interessieren...auch das "kleine Programm" zur Patientenzuordnung...

 

-js
Das kleine Programm sucht in einer pdf Datei welche vorher mit OCR lesbar gemacht wurde nach Patienten Name und Geburtsdatum und vergleicht es mit einer CSV Liste (Exell oder Numbers) in der Patientenname Geburtsdatum und die Patienten ID aus Tomedo hinterlegt sind (Export Liste aus Tomedo). Danach setzt es die Patienten ID in den Dateinamen vorne dran und legt die Datei in einen von Tomedo überwachten Hotfolder. Die Datei wird dann zum entsprechenden Pat. in die Kartei abgelegt.

Einen ähnlichen Weg stell ich mir auch für Diagnosen in eintreffenden Arztbriefen vor.....

3 Antworten

Ich hatte sowas mal vorgeschlagen. Wird wahrscheinlich nichts werden. 

https://forum.tomedo.de/index.php/77438/ki-fur-analyse-von-eingegangenen-befunden

Beantwortet von (22.2k Punkte)
+2 Punkte
Für gut definierte Briefe aus immer derselben Quelle habe ich mir ein paar regex-basierte Transfer-CKE erstellt. So kann ich z.B. beim immer gleich strukturierten Schlaflaborbrief die Diagnosen, CPAP- und Maskenparameter und Vorschläge zum weiteren Procedere automatisiert extrahieren. Für diesen (speziellen) Anwendungsfall, der bei mir recht viele eintreffende Briefe betrifft, ist das eine schöne Erleichterung.

Problem ist natürlich fehlende Möglichkeit zur einfachen Verallgemeinerung.
Beantwortet von (2.2k Punkte)
+1 Punkt
Ich stell mir das zunächst nur für eine begrenzte Zahl an Basisdiagnosen vor, die dann als "von extern übernommene Diagnose" in Tomedo automatisch einzutragen wären mit anschliessendem Vidierstatus versehen zum gegenchecken. Wäre bei hunderten von Briefen die eintreffen schon eine resen Erleichterung. Einfach eine Vergleichsdatenbank die man nach belieben modifizieren kann mit der dann der Inhalt des Arztbriefes verglichen wird und anschließend das Ergebnis in Tomedo eingetragen wird ...wo auch immer... am besten als externe DDI ... über die Vidier funktion dann die Freigabe zur Übernahme auf den Schein... Das kann alles im Hintergrund oder Nachts laufen...

Hallo,

 

irgendwie hat mich das Thema interessiert. Folgendes in Python ist dabei rausgekommen: 

 

from openai import OpenAI
from PyPDF2 import PdfReader
import os

# OpenAI API-Client initialisieren
client = OpenAI(api_key='Hier den Key für die Nutzung der openAI API einsetzen ')

def extract_text_from_pdf(pdf_path):
    if not os.path.isfile(pdf_path):
        print("Fehler: Datei existiert nicht.")
        return ""

    with open(pdf_path, 'rb') as file:
        reader = PdfReader(file)
        text = ""
        for page in reader.pages:
            text_content = page.extract_text()
            if text_content:
                text += text_content
    return text

def rename_pdf_based_on_content(pdf_path):
    if not pdf_path:
        print("Fehler: Kein Dateipfad angegeben.")
        return

    text = extract_text_from_pdf(pdf_path)
    if not text:
        print("Fehler: Text konnte nicht aus der PDF extrahiert werden.")
        return
    
    try:
        response = client.completions.create(
            model="gpt-3.5-turbo-instruct",  # Aktualisiertes Modell
            prompt="Extract the first name, last name, and birth date from the text: " + text,
            max_tokens=150
        )
        print("OpenAI API Response:", response)

        if response.choices:
            result_text = response.choices[0].text.strip()
            extracted_info = [info.split(': ')[1] for info in result_text.split('\n') if ': ' in info]
            new_name = "_".join(extracted_info[:2]) + ".pdf"  # Nur Vor- und Nachname für den Dateinamen verwenden
            new_path = os.path.join(os.path.dirname(pdf_path), new_name)
            os.rename(pdf_path, new_path)
            print(f"Datei umbenannt von {pdf_path} zu {new_path}")
        else:
            print("Keine Daten in der Antwort.")


    except Exception as e:
        print(f"Fehler bei der API-Anfrage: {e}")

# Beispielaufruf der Funktion
rename_pdf_based_on_content('/Users/jansmid/Desktop/Pythonprojekte/test.pdf') 
# Kann noch angepasst werden, damit eine beliebige Datei im Prompt übergeben werden kann 

Benötigt wird Python3, 

Ist alles mit ChatGPT und Google gemacht.

 

Was macht das Programm?

Es werden zwei Bibliotheken benutzt: PyPDF2 und openai. Die Nutzen von openai ist kostenpflichtig, 30 Anfragen kosten ungefähr ein Cent (über den Daumen gepeilt). PyPDF2 extrahiert den Text. Dann wird dieser Text an openai weitergeleitet und Vorname, Nachname und Geburtstag extrahiert. Das macht openai. Danach wird die Datei test.pdf umbenannt in vorname_nachnahme_geburtsdatum.pdf. 

Bisher wird nur die Datei test.pdf verwendet.

Die eigentlich Arbeit macht openai. Die Anfragen kann man flexibel verändert, im nächsten Schritt werde ich es mal mit Diagnosen von Max Muster probieren. Wie gesagt: alles "quick and dirty" hingebogen, mehr für mich, um es zu lernen. Aber vielleicht hat ja jemand Spass am basteln. 

Vom Arbeitsablauf würde dann in ein per Automator überwachter Ordner reingescannt werden. Automator würde dann die gescannte Datei mittels dem pythonskript umbennen.  Die Datei könnte dann mit dem Programm von dem Threadersteller automatisch erkannt werden.

Disclaimer: Datenschutz....komplett ungelöst und daher nur mit "Max Muster" verwendbar. Lt OpenAI werden Daten, die über die API empfangen werden, nicht weiterverwendet, aber natürlich darf man keine echten Daten verwenden. Ich hoffe, dass das Gerücht, dass Apple eine lokal laufende LLM zu in naher Zukunft zu Verfügung stellt, stimmt und damit die ganze Datenschutzproblematik umgangen werden kann.

 

Gruß

 

-js 

 

Beantwortet von (2.1k Punkte)
+1 Punkt

Cooles Programm, Respekt!

So etwas wollen wir alle haben. Ich kann mir aber tatsächlich keine datenschutzkonforme Lösung unter Verwendung von ChatGPT vorstellen. Wie Sie ja schon schreiben: das lokale LLM müsste es schon sein.

Ich stelle mir aber immer noch einen Haufen von Hand zu beurteilenden "Fehltreffer" vor. Z.B. dürfte allein die Information, dass es sich um eine Ausschluss-Diagnose (oder: "Asthma bei der Schwester") handelt, die im externen Text diskutiert wird, sicher nur schwer auf verlässliche Weise zu extrahieren sein. Vollautomatik ohne "händisches" Nachprüfen am Originaltext wird also kaum möglich sein. Eine Liste mit "zu vidierenden" Diagnosen ohne Verweis auf eine Fundstelle im 35-Seiten-PDF-Konvolut macht dann Probleme. 

Vielleicht hilft ein anderer Ansatz in überschaubarer Zeit weiter: Text wie bei Ihnen per PyPDF auslesen, dann simples Suchen nach Trigger-Begriffen wie "KHK", "Diabetes", "Pneumonie", "Cataract" etc. und natürlich ICD-10 Codes. Die Treffer könnten dann einen passenden Diagnose-Übernahme-Vorschlag auslösen. Die Liste dieser Diagnosenvorschläge könnte dann mit den jeweiligen Textabschnitten (+-2 Zeilen) angezeigt und per Klick "Übernahme ja/nein" gleich verifiziert werden. Wenn man diese Funktion in einen PDF-Reader packen könnte, wäre das Durchlesen des Briefes und das per Klick notwendige Übernehmen der Diagnosen ein Vorgang. Leider sind meine Programmierkünste für solche Träume zu limitiert.surprise

Sehr spannende Aktion Herr Dr. Smid. Da musss man schon Informatik studiert haben nehme ich an .... aber genau an sowas hab ich gedacht .... wird dann nacgh und nach verfeinert.... z.B. kann man nach ICD Codes suchen lassen, und nicht nach namentlichen Doiagnosetexten .... ICDs sind sicher nur da wenn es den Pat. betrifft und nicht die Fan´milienanamnese.

Wie kann ich dieses skript testen ???

Hi,

 

man muss python3 auf dem Mac installieren und bei openai einen Zugang haben. Die Benutzung der openai-API kostet Geld (token), ich habe mal 10$ draufgeladen, dass sind meiner Erinnung nach 1 Mio token - also genug zum ausprobieren. Der dann generierten Key muss man in
 

client = OpenAI(api_key='Hier den Key für die Nutzung der openAI API einsetzen ')

eintragen.

Den ganzen Code dann als 

rename_pdf_based_on_content.py abspeichern.

Dann braucht man ein PDF zum testen. 

Statt /User/jansmid/desktop/... den Pfad zu dem zu testen pdf mit dem korrekten Dateinamen angeben.

rename_pdf_based_on_content('/Users/jansmid/Desktop/Pythonprojekte/test.pdf') 

Dann 

python3 rename_pdf_based_on_content

Dann geht es bei mir.

Werde das ganze mal mit ICD versuchen. Erster Test in ChatGPT 4 war problemlos.

 

Falls das Skript spinnt, einfach mal copy and paste in ChatGPT - mehr mache ich auch nicht, mit den Fehlermeldungen kann man sich dann langhangeln. Ist wie gesagt ein Spielprojekt ;-)

Gruß

-js

Ist vermutlich für die Pythoncracks von Zollsoft leicht verdaulich :)

@Dr. Marks

Geht auch mit ICD-Codes:

 

import os
import fitz  # PyMuPDF
from openai import OpenAI

# Stellen Sie sicher, dass Sie Ihren OpenAI API-Key sicher speichern und laden
api_key = os.getenv('OPENAI_API_KEY')
if not api_key:
    raise ValueError("OPENAI_API_KEY is not set")
client = OpenAI(api_key=api_key)

def extract_text_from_pdf(pdf_path):
    if not os.path.isfile(pdf_path):
        print("Fehler: Datei existiert nicht.")
        return ""

    text = ""
    with fitz.open(pdf_path) as doc:
        for page in doc:
            text += page.get_text()

    return text

def extract_patient_info_and_icd_codes_to_text_file(pdf_path):
    if not pdf_path:
        print("Fehler: Kein Dateipfad angegeben.")
        return

    text = extract_text_from_pdf(pdf_path)
    if not text:
        print("Fehler: Text konnte nicht aus der PDF extrahiert werden.")
        return

    try:
        prompt_text = (
            f"Extract the patient's first name, last name, birth date, "
            f"and list all ICD codes from the diagnoses section in the text:\n\n{text}"
        )

        response = client.completions.create(
            model="gpt-3.5-turbo-instruct",
            prompt=prompt_text,
            max_tokens=1024
        )

        if response.choices:
            result_text = response.choices[0].text.strip()
            print("Verarbeiteter Text aus der API:")
            print(result_text)

            # Textdatei schreiben
            with open('patient_info_and_icd_codes.txt', 'w', encoding='utf-8') as textfile:
                textfile.write(result_text)
            print("Textdatei mit Patienteninformationen und ICD-Codes wurde erfolgreich erstellt.")
        else:
            print("Keine Daten in der Antwort.")
    except Exception as e:
        print(f"Fehler bei der API-Anfrage: {e}")

# Beispielaufruf der Funktion
extract_patient_info_and_icd_codes_to_text_file('/meinPfadinsUserverzeichnis/Analyse.pdf')

Man muss Python3 und  die Bibliothek PyMuPDF (mittels pip3 pymupdf) installiert haben. Und man braucht ein guthaben bei openai. Das Beispiel-PDF, welches ich analysiert habe, ist ein Arztbrief von mir über Max Muster (schicke ich wenn gewünscht per PM, da sind noch die Kontonummer etc drin).  Der output ist: 

First name: Max
Last name: Muster
Birth date: 01.11.1970
ICD codes: N18.4, R07.4, D50.9, I25.5, I25.13, I25.19, R00.2

Das ist wirklich erstaunlich, weil das alles nur von ChatGPT stammt, nach meinen Vorgaben. Ich habe vorher keien einzige Zeile Python selbst geschrieben. Hat mit ca. 1h gekostet....

 

Gruß

-js

Am Wochenende habe ich (angefixt von den oben gezeigten, schon mal sehr vielversprechenden Ergebnissen) mit diversen Python-Tools wie Textblob, SpaCy etc. herumgespielt, um ohne Datenschutzprobleme (und damit ohne ChatGPT) lokal die Texte auswerten zu können. Ein sehr weites Feld. Man kommt von Hölzken auf Stöksken, wenn man es exakt und verlässlich haben will... Da habe ich mir die Zähne dran ausgebissen, wenn es nicht nur für Spezialfälle, sondern allgemeingültig funktionieren soll. Gerade auch komplizierte Namen (Doppelnamen mit Bindestrich, Adelstitel wie Lothar de Maiziére oder Namen aus fernen Ländern) machen Probleme wie auch die Variation "Name, Vorname" vs. "Vorname, Name". In der gezeigten Variante des Programms wurde zuletzt der Vorname wieder nicht mehr erkannt, was zwischenzeitlich schon klappte. Ich wäre daher an dem "kleinen" und offenbar funktionierenden Programm vom Kollegen Marks für diese Thematik sehr interessiert.

Mit dem unten gezeigten (auch mit ChatGPT-Hilfe) gebastelten Programm klappt das Herausfischen von ICD-10-Codes dagegen schon sehr gut und zuverlässig. Es geht mittels simplem regex ohne ChatGPT lokal im Text sehr einfach, da diese Textfigur (Buchstabe-Zahl-Zahl-Punkt-Zahl-Zahl) sehr einzigartig ist. 

 

import PyPDF2 
import os
import re


# Name des Pfads zur PDF-Datei
pdf_path = "/Users/hansjoerg/Python/MustermannMax2.PDF"

def extract_text_from_pdf(pdf_path):
    try:
        # PDF-Datei öffnen
        with open(pdf_path, 'rb') as file:
            # PDF-Reader erstellen
            reader = PyPDF2.PdfReader(file)
            # Textvariable initialisieren
            text = ''
            # Durch alle Seiten des PDFs iterieren
            for page_num in range(len(reader.pages)):
                # Seite extrahieren
                page = reader.pages[page_num]
                # Text von der Seite extrahieren und zur Textvariable hinzufügen
                text += page.extract_text()
                print(text)
            return text
    except Exception as e:
        print(f"Fehler beim Öffnen oder Lesen des PDFs: {e}")
        return None

if __name__ == "__main__":

    # Text aus der PDF-Datei extrahieren
    extracted_text = extract_text_from_pdf(pdf_path)
    # Wenn der Text erfolgreich extrahiert wurde, anzeigen
    if extracted_text:
        print()
        print("Extrahierter Text:")
        print(extracted_text)
    
        
    name_pattern = r"(Frau|Herr|Herrn)\s*(\w+\s\w+)"
    birthdate_pattern = r"geb.\s*am\s*(\d{2}\.\d{2}\.\d{4})"
    diagnosis_pattern = r"\b[A-Z]\d{2}\.\d{1,2}\b"

    # Suchen nach Namen, Vornamen und Geburtsdatum
    if extracted_text:
        name_match = re.search(name_pattern, extracted_text)
        birthdate_match = re.search(birthdate_pattern, extracted_text)
    
        if name_match and birthdate_match:
            gender = name_match.group(1)
            name = name_match.group(2)
            birthdate = birthdate_match.group(1)
            if gender == "Herr" or gender == "Herrn":
                gender_output = "M"
            elif gender == "Frau":
                gender_output = "W"
            else:
                gender_output = "Unknown"
        print("Geschlecht:", gender_output)
        print("Name:", name)
        print("Geburtsdatum:", birthdate)
        
        # Suchen nach Diagnosecodes
        diagnosis_codes = re.findall(diagnosis_pattern, extracted_text)
        if diagnosis_codes:
            print("\nDiagnosecodes:")
            for code in diagnosis_codes:
                print(code)
            
    else:
        print("Fehler: Extrahierter Text ist None.")




Beispieltext Inhalt:

Sehr geehrte Frau Dr. Pustekuchen,  

Max Mustermann, geb. am 02.05.1955, wohnhaft Am Hundekuchen 25 in 28007 Bremen, stellte sich am 08.04.2024 in meiner Praxis vor.

Diagnosen:
gemischtförmiges Asthma bronchiale, schwergradig, gut kontrolliert (J45.83)
Allergische Rhinitis durch Pollen (Gräser, Frühblüher, Ragweed) (J30.1)
Nahrungsmittelintoleranz (K90.4)
Ganzjährig bestehende allergische Rhinitis [Tierhaare, Hausstaubmilbe] (J30.3)
Hyposensibilisierung gegenüber Allergenen (SLIT Gräser ab 04/2023; Birke 10/2023) (Z51.6)
Adipositas Grad I [WHO] (E66.90)
Arterielle Hypertonie (I95.9)
Hypothyreose (E03.9)

Aktuelle Anamnese: Routinemäßige Wiedervorstellung. Respiratorisch konstant, seltener Giemen, verminderte Allergiebeschwerden. SLIT seit 11/23, Itulazax, guter Effekt. Das Asthma ist (bezogen auf die letzten 4 Wochen) gemäß NVL-Kriterien teilweise kontrolliert, gemäß Asthma-Kontroll-Test (ACT) mit 18 von max. 25 Punkten eher nicht kontrolliert.

_____________________________________________________________________________________


Analyse-Ergebnis:

Geschlecht: M
Name: n Mustermann
Geburtsdatum: 02.05.1955

Diagnosecodes:
J45.83
J30.1
K90.4
J30.3
Z51.6
E66.90
I95.9
E03.9

Auch ChatGPT selbst hat aber Schwierigkeiten, aus unstruktierten und nicht standisiertem Text Namen und Geburtsdaten zu extrahieren, wenn ich meinen, mit fiesen Namen gespickten Test-Text bei ChatGPT eingebe, gelingt die korrekte Zuordnung auch eher mäßig. Evtl. kann man das mit Prompt-Optimierung noch weiter verbessern, zeigt aber auch, dass ChatGPT auch eher nicht der Goldstandard für das Problem ist.

Hallo,

 

 Regex und den ICD-Diagnosen funktioniert sicher sehr gut! (gerade keine Zeit zum Testen)...

Vermutlich wird man mit regex bei den arztbriefen schnell an die Grenzen kommen (andere Formatierungen, gefaxt + OCR mit mieser Qualität etc.).  

ich werde mal je nach verfügbarer Zeit am Wochenende als Modell openai 4 nehmen und einen etwas anderen Ansatz testen: keine Extraktion mit PythonPDF o.ä. sondern das PDF direkt von openai verarbeiten lassen.

Es gibt ja durchaus KI, die auch lokal laufen. Eine datenschutzkonforme Lösung wäre der Betrieb einer KI durch Zollsoft - gibt es ja bei der Spracherkennung schon. Diese KI kann dann für Arztbriefe entsprechend optimiert sein. Auch wenn irgendwann die EPA kommt: eine Software, die Daten aus Briefen teilautomatisiert verarbeitet, wäre eine sehr schöne Arbeitserleichterung.

Es muss meine Meinung nach auch gar nicht zu 100% korrekt sein; 85% sind absolut ausreichend - gemäß dem Zollsoftmotto auf der Homepage: "better done than perfect" :-)

 

-js
Hallo,

 

ich habe am Wochenende mal probiert, openai GPT-4 Vision zu nutzen, um den Umweg über eine Textextraktion aus dem PDF zu umgehen. Kurz zusammengefasst: geht nicht zw. habe ich nicht hinbekommen.

Die einzige datenschutztechnische Möglichkeit, ML zur Texterkennung zu nutzen wäre eine lokale Verarbeitung, ähnlich wie Zollsoft es mit der Spracherkennung macht (Containerlösung in Docker auf Intel-Macs, bei Apple Silikon scheint es direkt ohne Docker zu laufen).

Vielleicht wird so etwas seitens Zollsoft ja mal realisiert... so ein Modul würde ich abonnieren.

Gruß

 

-js
16,088 Beiträge
23,864 Antworten
42,004 Kommentare
11,699 Nutzer