Startseite / Artikel

Ein vollständig lokaler GraphRAG-Pipeline mit LangExtract, Neo4j, Qdrant und Ollama

GraphRAG mit lokalen Modellen aufbauen: Entitäten mithilfe von LangExtract extrahieren, sie in Neo4j speichern, in Qdrant indizieren und anschließend Untergraphen erweitern, um graphbasierte Antworten zu erhalten.

Verlag: REACTAPP.TOP39 Min. Lesezeit9040 Wörter

Quellen: A Practical GraphRAG Architecture Using LangExtract, Neo4j, Qdrant, and Ollama

Diese Version ist ein GraphRAG-System, das vollständig mit lokalen Modellen läuft. Die Komponenten sind Ollama für Sprach- und Embedding-Modelle, Neo4j für das Graphen, Qdrant für die Vektorsuche sowie LangExtract zur Extraktion von Strukturen aus Texten. Anstelle des Herunterladens von Dokumententeilen wie es herkömmliche RAG-Systeme tun, wandelt es Rohtext in ein Wissensgraphen um und holt Entitäten ab, die semantisch einer Frage nahekommen, bevor es den damit verbundenen Beziehungen folgt.

Der Star dieses Designs ist LangExtract, das Entitäten und Beziehungen in unstrukturiertem Text findet und sie in einer Form zurückgibt, die von einem Graphen gespeichert werden kann. Qdrant trägt durch Vektorähnlichkeit zum Verständnis bei, während Neo4j durch das Durchlaufen der Beziehungen Kontext liefert. Gemeinsam bilden sie einen Suchprozess, der sowohl das Thema einer Frage als auch die Verbindungen zwischen den Fakten berücksichtigt.

Wie die Architektur funktioniert

Der Rohtext gelangt zunächst in die LangExtract-Schicht. Herkömmliche Pipelines würden die Dokumente sofort in Blöcke aufteilen und diese einbetten. Hier wird der Text erst einmal in strukturiertes Wissen umgewandelt. LangExtract, das von einem im Ollama gehosteten Modell unterstützt wird, erkennt Entitäten sowie die Beziehungen zwischen ihnen. Im angezeigten Beispiel handelt es sich um Medikamentendaten: Medikamente, Dosen, Anwendungshäufigkeiten sowie Krankheitszustände werden extrahiert, und ihre Verbindungen bleiben durch eine gemeinsame Gruppierung erhalten. Die natürliche Sprache wird somit zu einer strukturierten Aufzeichnung von Fakten und nicht zu einem Haufen gespeicherter Abschnitte.

Dann werden die extrahierten Entitäten und Beziehungen zu Teilen des Graphen. Jedes Konzept wird zu einem Knoten mit einer eindeutigen ID, und Beziehungen wie Dosis, Häufigkeit oder Zustand werden zu expliziten Kanten zwischen den Knoten. Die Informationen sind nun um die Entitäten und ihre Verbindungen herum organisiert, nicht um die Grenzen der Dokumente, wodurch der Kontext erhalten bleibt, den eine auf Blöcken basierende Suche normalerweise verlieren würde.

Anschließend wird der Graph in Neo4j geladen, die Hauptdatenbank für strukturiertes Wissen. Entitäten werden zu Knoten und Beziehungen zu nativen Kanten. Da Neo4j in der Lage ist, effizient zwischen miteinander verbundenen Konzepten zu navigieren, kann das System später mehrstufige Pfade verfolgen und Kontexte aufzeigen, die jenseits des Punktes liegen, an dem die Extraktion begann.

Sobald das Graph erstellt ist, wird für jeden Knoten ein Embedding generiert. Das Embedding-Modell liest direkt Entity-Namen und Konzepte ein, anstatt ganze Dokumente oder Abschnitte. Das Ergebnis ist ein semantischer Index über die Graph-Entitys, wodurch die Suche auf Konzepten statt auf Textpassagen ausgerichtet ist.

Diese Vektoren werden zusammen mit den entsprechenden Neo4j-Node-IDen in Qdrant eingegeben. Qdrant fungiert als schnelle semantische Schicht, während Neo4j weiterhin die strukturierte Schicht bleibt. Da jede Qdrant-Übertragung eine Neo4j-Node-ID enthält, wird ein Vektor-Erfolg direkt auf eine Graph-Entity abgebildet. Diese Trennung ermöglicht es jeder Datenbank, das zu tun, wofür sie am besten geeignet ist: die Ähnlichkeitssuche in einer Datenbank und das Durchlaufen von Beziehungen sowie graphisches Reasoning in der anderen.

Zum Zeitpunkt der Abfrage stellt ein Benutzer eine Frage in natürlicher Sprache. Dasselbe Embedding-Modell wandelt sie in einen Vektor um, der anschließend in Qdrant durchsucht wird, um die am relevantestenen Grapheneinheiten zu finden. Anstelle von Dokumentabschnitten liefert die Suche Node-Identifikatoren zurück. Diese Nodes dienen als semantische Eingangspunkte in den Graphen und stehen für die Konzepte, die am nächsten an dem liegen, was der Benutzer sucht.

Anschließend werden diese Identifikatoren verwendet, um eine Abfrage in Neo4j durchzuführen. Statt bei den gefundenen Einheiten zu stoppen, erweitert das System die Suche über benachbarte Nodes und Beziehungen hinaus und sammelt einen relevanten Teilgraphen ein, der sowohl die Treffer als auch ihren umgebenden Kontext enthält. Durch diese Erweiterung können unterstützende Fakten erfasst werden, die allein durch Vektorähnlichkeit nicht gefunden worden wären; somit trägt der Kontext sowohl semantische Relevanz als auch Struktur in sich.

Der Untergraph wird anschließend für ein Sprachmodell umgestaltet. Die Knoten werden in eine strukturierte Liste zusammengefasst, und die Beziehungen werden zu lesbaren Tripeln umgewandelt, die explizite Verbindungen angeben, wie beispielsweise „Lisinopril-Dosis 10 mg“ oder „Metformin bei Diabetes“. Dieser Schritt verbindet Graphdatenbanken mit Sprachmodellen, indem er die Graphstruktur in Text umwandelt, den das Modell interpretieren kann.

Schließlich wird der formatierte Graphkontext an das LLM übermittelt. Das Modell erhält Entitäten und Beziehungen – nicht abgerufene Textabschnitte –, wodurch es über die angegebenen Fakten nachdenken kann und nicht gezwungen ist, Verbindungen aus fragmentierten Passagen abzuleiten. Da der Kontext aus einer Graphdurchquerung stammt, ist er außerdem erklärbarer und nachvollziehbarer als herkömmliche Vektorabfragen.

Insgesamt handelt es sich um ein hybrides Suchsystem. LangExtract kümmert sich um die Wissensextraktion, Neo4j verwaltet strukturierte Beziehungen, Qdrant sucht semantisch nach Entitäten, und das LLM handelt auf der Grundlage eines graphbasierten Kontexts. Die Kombination von Ähnlichkeitsanalyse und Durchquerung ermöglicht es, Fragen aus vernetztem Wissen statt aus isolierten Textfragmenten zu beantworten. Dadurch ist dieser Ansatz insbesondere in Bereichen wie Gesundheitswesen, Finanzen, Recht, Unternehmenswissensmanagement und wissenschaftlicher Forschung stark, wo die Beziehungen zwischen Entitäten oft wichtiger sind als einzelne Abschnitte.

Methode für Methode

__init__() ist der Eingangspunkt für das gesamte System. Es liest Konfigurationen aus Umgebungsvariablen ein, darunter die Anmeldeinformationen für Neo4j, die Verbindungsdaten zu Qdrant sowie Einstellungen für Ollama. Es öffnet Verbindungen zu Neo4j und Qdrant, die der Rest des Pipelines wiederverwendet, und erstellt den Ollama-Client, der für die Extraktion, Erstellung von Vektoren sowie die Synthese von Antworten verwendet wird. Modellnamen und Vektordimensionen werden als Parameter gespeichert, wodurch die Einrichtung anpassbar bleibt.

def __init__(self,env_path: str = ".env",ollama_model_extract: str = "gemma3:latest",
            ollama_model_answer: str = "gemma3:latest",ollama_embedding_model: str = "embeddinggemma:latest",
            ollama_host: str | None = None,vector_dimension: int = 768,
    ):

        load_dotenv(env_path)

        self.qdrant_key = os.getenv("QDRANT_KEY")
        self.qdrant_url = os.getenv("QDRANT_URL")
        self.neo4j_uri = os.getenv("NEO4J_URI")
        self.neo4j_username = os.getenv("NEO4J_USERNAME")
        self.neo4j_password = os.getenv("NEO4J_PASSWORD")

        self.neo4j_driver = GraphDatabase.driver(
            self.neo4j_uri, auth=(self.neo4j_username, self.neo4j_password)
        )

        self.qdrant_client = QdrantClient(
            url=self.qdrant_url,
            api_key=self.qdrant_key,
        )

        # Ollama client for local embeddings (embeddinggemma:latest)
        self.ollama_client = ollama.Client(host=ollama_host) if ollama_host else ollama.Client()

        # langextract needs a plain URL string, not a client object
        self.ollama_url = ollama_host or os.environ.get("OLLAMA_HOST", "http://localhost:11434")

        # Model / config knobs
        self.ollama_model_extract = ollama_model_extract
        self.ollama_model_answer = ollama_model_answer
        self.ollama_embedding_model = ollama_embedding_model
        self.vector_dimension = vector_dimension

extract_graph_components() wandelt Rohtext in strukturiertes Wissen um. Es liefert Extraktionsanweisungen zusammen mit Beispielen, die LangExtract zu den richtigen Entitäten und Beziehungen führen. Ein auf Ollama gehostetes Modell verarbeitet anschließend die Eingabe und extrahiert Medikamente, Dosen, Häufigkeiten sowie Erkrankungen. Das Ergebnis ist weiterhin eine Sammlung extrahierter Elemente und kein Graph, weshalb die Methode diese zur Graphenerstellung weiterleitet.

def extract_graph_components(self, raw_data: str):
        """Extract medication entities and relationships using langextract + Ollama."""

        prompt_description = textwrap.dedent("""
            Extract medications with their details, using attributes to group related information:
            1. Extract entities in the order they appear in the text
            2. Each entity must have a 'medication_group' attribute linking it to its medication
            3. All details about a medication should share the same medication_group value
            """).strip()

        examples = [
            lx.data.ExampleData(
                text=(
                    "Patient takes Aspirin 100mg daily for heart health and"
                    " Simvastatin 20mg at bedtime."
                ),
                extractions=[
                    lx.data.Extraction(
                        extraction_class="medication",
                        extraction_text="Aspirin",
                        attributes={"medication_group": "Aspirin"},
                    ),
                    lx.data.Extraction(
                        extraction_class="dosage",
                        extraction_text="100mg",
                        attributes={"medication_group": "Aspirin"},
                    ),
                    lx.data.Extraction(
                        extraction_class="frequency",
                        extraction_text="daily",
                        attributes={"medication_group": "Aspirin"},
                    ),
                    lx.data.Extraction(
                        extraction_class="condition",
                        extraction_text="heart health",
                        attributes={"medication_group": "Aspirin"},
                    ),
                    lx.data.Extraction(
                        extraction_class="medication",
                        extraction_text="Simvastatin",
                        attributes={"medication_group": "Simvastatin"},
                    ),
                    lx.data.Extraction(
                        extraction_class="dosage",
                        extraction_text="20mg",
                        attributes={"medication_group": "Simvastatin"},
                    ),
                    lx.data.Extraction(
                        extraction_class="frequency",
                        extraction_text="at bedtime",
                        attributes={"medication_group": "Simvastatin"},
                    ),
                ],
            )
        ]

        result = lx.extract(
            text_or_documents=raw_data,
            prompt_description=prompt_description,
            examples=examples,
            model_id=self.ollama_model_extract,
            model_url=self.ollama_url,
            resolver_params={"format_handler": lx_ollama.OLLAMA_FORMAT_HANDLER},
            max_char_buffer=4000,
            show_progress=True,
        )

        return self._convert_extractions_to_graph(result.extractions)

_convert_extractions_to_graph() formt die Extraktionen in eine Graphenstruktur um. Dabei werden verwandte Elemente zusammengefasst und das primäre Element jeder Gruppe als Ankerknoten ausgewählt. Jeder Knoten erhält eine eindeutige Identifikation, damit Neo4j und Qdrant konsistent bleiben. Kanten verbinden anschließend die Ankerknoten mit ihren Attributen und bewahren so die ursprüngliche Bedeutung. Das Ergebnis ist eine Ansammlung von Knoten und Kanten, die für eine Graphen-Datenbank bereit sind.

def _convert_extractions_to_graph(self, extractions: list):
        """Convert langextract's flat, grouped extractions into (nodes, relationships)."""

        groups: dict[str, list] = {}
        for ext in extractions:
            if not ext.attributes or "medication_group" not in ext.attributes:
                continue
            group_name = ext.attributes["medication_group"]
            groups.setdefault(group_name, []).append(ext)

        nodes: dict[str, str] = {}
        relationships: list[dict] = []

        for group_name, group_extractions in groups.items():
            anchor_ext = next(
                (e for e in group_extractions if e.extraction_class == "medication"),
                None,
            )

            # Fall back to the group name itself if no explicit "medication"
            # extraction was found in this group, so we still get an anchor.
            anchor_text = anchor_ext.extraction_text if anchor_ext else group_name

            if anchor_text not in nodes:
                nodes[anchor_text] = str(uuid.uuid4())

            for ext in group_extractions:
                if ext is anchor_ext:
                    continue

                target_text = ext.extraction_text
                if target_text not in nodes:
                    nodes[target_text] = str(uuid.uuid4())

                relationships.append(
                    {
                        "source": nodes[anchor_text],
                        "target": nodes[target_text],
                        "type": ext.extraction_class,
                    }
                )

        return nodes, relationships

ingest_to_neo4j() schreibt das Graph in Neo4j, wobei jede Entität als Knoten und jede Beziehung als Kante gespeichert wird. Diese Struktur ermöglicht ein effizientes Durchqueren und Erkunden des Graphs später. Jeder Knoten behält seinen eindeutigen Identifikator bei, der es ihm ermöglicht, mit den Ergebnissen einer Vektorsuche verknüpft zu werden. Wenn die Methode abgeschlossen ist, stellt das Graph den strukturierten Wissensspeicher des Systems dar.

def ingest_to_neo4j(self, nodes: dict, relationships: list):
        """
        Ingest nodes and relationships into Neo4j.
        """
        with self.neo4j_driver.session() as session:
            # Create nodes in Neo4j
            for name, node_id in nodes.items():
                session.run(
                    "CREATE (n:Entity {id: $id, name: $name})",
                    id=node_id,
                    name=name,
                )

            # Create relationships in Neo4j, using the semantic type
            # (dosage/frequency/condition/etc.) as the actual relationship
            # label instead of a generic "RELATIONSHIP" type.
            for relationship in relationships:
                rel_type = self._sanitize_relationship_type(relationship["type"])
                session.run(
                    "MATCH (a:Entity {id: $source_id}), (b:Entity {id: $target_id}) "
                    f"CREATE (a)-[:{rel_type} {{type: $type}}]->(b)",
                    source_id=relationship["source"],
                    target_id=relationship["target"],
                    type=relationship["type"],
                )

        return nodes

_sanitize_relationship_type() existiert, weil Beziehungsnamen aus den Ausgaben von KI-Modellen stammen und ungültige Zeichen oder ungewöhnliche Formate enthalten können. Es reinigt und standardisiert die Bezeichnungen, bevor sie Neo4j erreichen, wodurch sichere Großbuchstaben-Identifikatoren entstehen, die den Regeln von Cypher entsprechen. Zudem schützt es vor fehlerhaften Namen sowie den dadurch entstehenden Abfragenproblemen. Die Methode ist zwar klein, trägt aber dazu bei, das Graphen-Modell intakt zu halten.

@staticmethod
    def _sanitize_relationship_type(raw_type: str) -> str:
        """
        Cypher relationship types can't be passed as query parameters, so
        they have to be interpolated into the query string directly. Since
        raw_type comes from LLM-extracted text, sanitize it to a safe
        UPPER_SNAKE_CASE identifier before interpolation, to avoid Cypher
        injection or syntax errors from unexpected characters.
        """
        safe = "".join(ch if ch.isalnum() else "_" for ch in raw_type.strip())
        safe = safe.upper().strip("_") or "RELATIONSHIP"
        if safe[0].isdigit():
            safe = f"REL_{safe}"
        return safe

create_collection() stellt sicher, dass eine Qdrant-Kollektion vor dem Speichern beliebiger Vektoren existiert. Es prüft, ob die benannte Kollektion bereits vorhanden ist, und erstellt sie bei Bedarf, wobei die Vektordimension sowie die für die Suche verwendete Ähnlichkeitsmetrik konfiguriert werden. Diese Vorprüfung verhindert unnötiges Erstellen von Kollektionen und stellt die Vektorlage vor Beginn der Eingabe bereit.

def create_collection(self, collection_name: str, vector_dimension: int = None):
        vector_dimension = vector_dimension or self.vector_dimension

        try:
            # Try to fetch the collection status
            self.qdrant_client.get_collection(collection_name)
            print(f"Skipping creating collection; '{collection_name}' already exists.")
        except Exception as e:
            # If collection does not exist, an error will be thrown, so we create the collection
            if "Not found: Collection" in str(e) or "doesn't exist" in str(e) or "404" in str(e):
                print(f"Collection '{collection_name}' not found. Creating it now...")

                self.qdrant_client.create_collection(
                    collection_name=collection_name,
                    vectors_config=models.VectorParams(
                        size=vector_dimension, distance=models.Distance.COSINE
                    ),
                )

                print(f"Collection '{collection_name}' created successfully.")
            else:
                print(f"Error while checking collection: {e}")

ollama_embeddings() erzeugt dichte Vektoren mithilfe von Ollamas Embedding-Modell. Jede Graphenentität sowie jede Benutzeranfrage wird daran verarbeitet. Die Vektoren drücken Bedeutungen numerisch aus, sodass sie effizient verglichen werden können – dies ermöglicht die Ähnlichkeitssuche in Qdrant. Im Grunde ist diese Methode die Brücke zwischen natürlicher Sprache und Vektorabruf.

def ollama_embeddings(self, text: str) -> list[float]:
        response = self.ollama_client.embeddings(
            model=self.ollama_embedding_model,
            prompt=text,
        )
        return response["embedding"]

ingest_to_qdrant() erstellt für jede Entität ein Embedding, sobald die Graphenknoten vorhanden sind, und speichert es in Qdrant. Neben jedem Vektor werden Metadaten aufbewahrt, nämlich die Identifikationsnummer des Neo4j-Knotens sowie der Name der Entität. Diese Zuordnung verbindet die Vektordatenbank mit der Graphendatenbank, sodass Suchergebnisse später wieder in Graphenentitäten umgewandelt werden können. Diese Methode bildet die semantische Suchschicht der Architektur.

def ingest_to_qdrant(self, collection_name: str, raw_data: str, node_id_mapping: dict):
        names = list(node_id_mapping.keys())
        embeddings = [self.ollama_embeddings(name) for name in names]

        self.qdrant_client.upsert(
            collection_name=collection_name,
            points=[
                {
                    "id": str(uuid.uuid4()),
                    "vector": embedding,
                    "payload": {"id": node_id_mapping[name], "name": name},
                }
                for name, embedding in zip(names, embeddings)
            ],
        )

retriever_search() führt zur Zeit der Abfrage eine semantische Suche durch. Die Abfrage wird eingebettet und mit den Vektoren in Qdrant verglichen. Es werden Graph-Entitäten zurückgegeben, die der Abfrage ähneln und keine Textabschnitte sind; diese dienen als Eingangspunkte in das Wissensgraph. Die Suche wird daher durch Konzepte und nicht durch Dokumente gesteuert.

def retriever_search(self, collection_name: str, query: str, top_k: int = 5):
        retriever = QdrantNeo4jRetriever(
            driver=self.neo4j_driver,
            client=self.qdrant_client,
            collection_name=collection_name,
            id_property_external="id",
            id_property_neo4j="id",
        )

        results = retriever.search(
            query_vector=self.ollama_embeddings(query), top_k=top_k
        )

        return results

fetch_related_graph() bittet Neo4j um die Umgebung der gerade gefundenen Entitäten. Es durchläuft das Graph, um benachbarte Knoten sowie die Beziehungen zu sammeln, die sie mit den abgerufenen Entitäten verbinden. Dadurch wird Kontext hinzugefügt, den die Vektorabgleichmethode möglicherweise übersehen hat, und es entsteht ein sinnvoller Teilgraph anstelle isolierter Entitäten. Dieser Schritt ermöglicht es GraphRAG, über Beziehungen zu reasoningen.

def fetch_related_graph(self, entity_ids: list):
        query = """
        MATCH (e:Entity)-[r1]-(n1)-[r2]-(n2)
        WHERE e.id IN $entity_ids
        RETURN e, r1 as r, n1 as related, r2, n2
        UNION
        MATCH (e:Entity)-[r]-(related)
        WHERE e.id IN $entity_ids
        RETURN e, r, related, null as r2, null as n2
        """
        with self.neo4j_driver.session() as session:
            result = session.run(query, entity_ids=entity_ids)
            subgraph = []
            for record in result:
                subgraph.append(
                    {
                        "entity": record["e"],
                        "relationship": record["r"],
                        "related_node": record["related"],
                    }
                )
                if record["r2"] and record["n2"]:
                    subgraph.append(
                        {
                            "entity": record["related"],
                            "relationship": record["r2"],
                            "related_node": record["n2"],
                        }
                    )
        return subgraph

format_graph_context() bereitet den Teilgraphen für das Modell vor, da die rohe Graphenausgabe nicht direkt für ein LLM geeignet ist. Es wandelt die Struktur in sauberen Text um, der aus Knoten und Beziehungsangaben besteht, die als lesbare Tripel dargestellt werden, die zeigen, wie Entitäten miteinander verbunden sind. Die Formatierung bewahrt die Struktur des Graphen bei, bleibt aber für ein Sprachmodell leicht verständlich. Es handelt sich um die letzte Phase der Kontextvorbereitung vor der Beantwortung.

def format_graph_context(self, subgraph: list):
        nodes = set()
        edges = []

        for entry in subgraph:
            entity = entry["entity"]
            related = entry["related_node"]
            relationship = entry["relationship"]

            nodes.add(entity["name"])
            nodes.add(related["name"])

            edges.append(f"{entity['name']} {relationship['type']} {related['name']}")

        return {"nodes": list(nodes), "edges": edges}

graphRAG_run() erzeugt die endgültige Antwort. Es verbindet den formatierten Graphenkontext mit der Frage des Benutzers zu einem Prompt. Das Modell erhält graphbasierte Informationen und nicht rohe Dokumentabschnitte, sodass es über Beziehungen und miteinander verbundene Fakten nachdenken kann, wobei seine Antwort auf den abgerufenen Graphenwissen beruht. Dies ist die Überlegungsschicht am Ende des Pipelines.

def graphRAG_run(self, graph_context: dict, user_query: str):
        nodes_str = ", ".join(graph_context["nodes"])
        edges_str = "; ".join(graph_context["edges"])
        prompt = f"""
        You are an intelligent assistant with access to the following knowledge graph:

        Nodes: {nodes_str}

        Edges: {edges_str}

        Using this graph, Answer the following question:

        User Query: "{user_query}"
        """

        try:
            response = chat(
                model=self.ollama_model_answer,
                messages=[
                    {
                        "role": "system",
                        "content": "Provide the answer for the following question:",
                    },
                    {"role": "user", "content": prompt},
                ],
            )
            return response.message.content

        except Exception as e:
            return f"Error querying LLM: {str(e)}"

create_and_ingest() koordiniert den gesamten Eingabeprozess: Er erstellt die Vektorkollektion, extrahiert Graphkomponenten, speichert sie in Neo4j, erzeugt Embeddings und indiziert die Entitäten in Qdrant. Durch seine Ausführung wird Rohtext in eine suchbare GraphRAG-Wissensdatenbank umgewandelt. In der Regel wird er einmal während der Datenvorbereitung ausgeführt, danach kann das System Anfragen beantworten.

def create_and_ingest(self, raw_data: str, query: str, collection_name: str = "medicationGraphRAGstore"):
        print("Creating collection...")
        self.create_collection(collection_name, self.vector_dimension)
        print("Collection created/verified")

        print("Extracting graph components...")
        nodes, relationships = self.extract_graph_components(raw_data)
        print("Nodes:", nodes)
        print("Relationships:", relationships)

        print("Ingesting to Neo4j...")
        node_id_mapping = self.ingest_to_neo4j(nodes, relationships)
        print("Neo4j ingestion complete")

        print("Ingesting to Qdrant...")
        self.ingest_to_qdrant(collection_name, raw_data, node_id_mapping)
        print("Qdrant ingestion complete")

run_pipeline() koordiniert die Abrufung von Informationen sowie das logische Schließen vom Anfang bis zum Ende. Zunächst werden semantische Daten aus Qdrant abgerufen, die entsprechenden Graphenentitäten ermittelt und anschließend wird Neo4j durchsucht. Der resultierende Teilgraph wird für das Reasoning-Modell in einen geeigneten Kontext formatiert, und die erzeugte Antwort wird an den Benutzer zurückgesendet. Damit wird der gesamte Weg von der Frage bis zur Antwort dargestellt.

def run_pipeline(self, raw_data: str, query: str, collection_name: str = "medicationGraphRAGstore"):

        # run only the first time, comment this for subsequent runs
        # self.create_and_ingest(raw_data, query, collection_name)

        print("Starting retriever search...")
        retriever_result = self.retriever_search(collection_name, query)
        print("Retriever results:", retriever_result)

        print("Extracting entity IDs...")
        entity_ids = [
            item.content.split("'id': '")[1].split("'")[0]
            for item in retriever_result.items
        ]
        print("Entity IDs:", entity_ids)

        print("Fetching related graph...")
        subgraph = self.fetch_related_graph(entity_ids)
        print("Subgraph:", subgraph)

        print("Formatting graph context...")
        graph_context = self.format_graph_context(subgraph)
        print("Graph context:", graph_context)

        print("Running GraphRAG...")
        answer = self.graphRAG_run(graph_context, query)
        print("Final Answer:", answer)

        return answer

close() kümmert sich um die Aufräumarbeiten. Es schließt die Verbindung zum Neo4j-Driver und befreit damit verbundene Ressourcen, wodurch Verbindungslecks verhindert und ein reibungsloser Abschluss ermöglicht wird. Es ist einfach, sollte aber stets bei Beendigung der Verarbeitung aufgerufen werden.

def close(self):
        self.neo4j_driver.close()

Der Treibercode verbindet die Klasse miteinander:

if __name__ == "__main__":
    print("Script started")

    graph_rag = MedicationGraphRAG(env_path="../.env")

    # Example-1
    # raw_data = textwrap.dedent("""
    #     The patient was prescribed Lisinopril and Metformin last month.
    #     He takes the Lisinopril 10mg daily for hypertension, but often misses
    #     his Metformin 500mg dose which should be taken twice daily for diabetes.
    #     """).strip()

    # Example-2
    raw_data = textwrap.dedent("""
    The patient is a 62-year-old man with a history of multiple chronic conditions
    being managed through an extensive medication regimen. He was prescribed
    Lisinopril, Metformin, Atorvastatin, Aspirin, Levothyroxine, and Sertraline
    over the course of the past year, with his treatment plan adjusted several
    times based on follow-up visits.

    He takes Lisinopril 10mg daily for hypertension, but often misses his
    Metformin 500mg dose which should be taken twice daily for diabetes. His
    cardiologist also started him on Atorvastatin 40mg at bedtime for high
    cholesterol after his last lipid panel showed elevated LDL levels. To reduce
    his risk of cardiovascular events, he was additionally prescribed Aspirin
    81mg daily for heart disease prevention, which he takes alongside his
    breakfast each morning.

    Following a routine thyroid screening, he was found to have an underactive
    thyroid and was started on Levothyroxine 75mcg every morning for
    hypothyroidism, to be taken on an empty stomach before any other medications.
    More recently, after reporting persistent low mood and difficulty sleeping
    during a wellness visit, his primary care physician added Sertraline 50mg
    daily for depression, with plans to reassess the dosage after eight weeks.

    Despite the number of prescriptions, the patient has had difficulty
    maintaining consistency with his Metformin and occasionally forgets his
    evening Atorvastatin dose, which his care team is now addressing through a
    simplified pill organizer and reminder system.
    """).strip()

    # Sample Questions
    #1. "What is the dosage and frequency for Lisinopril?"
    #2. "What is the dosage and frequency for Metformin?"
    #3. "Which medications does the patient take once daily versus twice daily?"
    #4. "What medication is prescribed for hypothyroidism, and at what dose?"
    #5. "List all medications related to cardiovascular conditions and their dosages."
    #6. "How often does the patient take Aspirin?"
    #7. "What condition is Levothyroxine prescribed for?"
    #8. "What time of day should Levothyroxine be taken, and why?"
    #9. "Which medications does the patient have trouble taking consistently?"
    #10. "What is the dosage and frequency for Sertraline?"

    query = "List all medications related to cardiovascular conditions and their dosages."

    answer = graph_rag.run_pipeline(raw_data, query, collection_name="medicationGraphRAGstore")

    graph_rag.close()

Der vollständige Script

Sämtliche Bestandteile in einer Datei zusammengefasst:

import os
import uuid
import textwrap

import ollama
from dotenv import load_dotenv, find_dotenv
from ollama import chat
from neo4j import GraphDatabase
from qdrant_client import QdrantClient, models
from neo4j_graphrag.retrievers import QdrantNeo4jRetriever

import langextract as lx
from langextract.providers import ollama as lx_ollama

load_dotenv(find_dotenv())


class MedicationGraphRAG:

    def __init__(self,env_path: str = ".env",ollama_model_extract: str = "gemma3:latest",
            ollama_model_answer: str = "gemma3:latest",ollama_embedding_model: str = "embeddinggemma:latest",
            ollama_host: str | None = None,vector_dimension: int = 768,
    ):

        load_dotenv(env_path)

        self.qdrant_key = os.getenv("QDRANT_KEY")
        self.qdrant_url = os.getenv("QDRANT_URL")
        self.neo4j_uri = os.getenv("NEO4J_URI")
        self.neo4j_username = os.getenv("NEO4J_USERNAME")
        self.neo4j_password = os.getenv("NEO4J_PASSWORD")

        self.neo4j_driver = GraphDatabase.driver(
            self.neo4j_uri, auth=(self.neo4j_username, self.neo4j_password)
        )

        self.qdrant_client = QdrantClient(
            url=self.qdrant_url,
            api_key=self.qdrant_key,
        )

        # Ollama client for local embeddings (embeddinggemma:latest)
        self.ollama_client = ollama.Client(host=ollama_host) if ollama_host else ollama.Client()

        # langextract needs a plain URL string, not a client object
        self.ollama_url = ollama_host or os.environ.get("OLLAMA_HOST", "http://localhost:11434")

        # Model / config knobs
        self.ollama_model_extract = ollama_model_extract
        self.ollama_model_answer = ollama_model_answer
        self.ollama_embedding_model = ollama_embedding_model
        self.vector_dimension = vector_dimension

    def extract_graph_components(self, raw_data: str):
        """Extract medication entities and relationships using langextract + Ollama."""

        prompt_description = textwrap.dedent("""
            Extract medications with their details, using attributes to group related information:
            1. Extract entities in the order they appear in the text
            2. Each entity must have a 'medication_group' attribute linking it to its medication
            3. All details about a medication should share the same medication_group value
            """).strip()

        examples = [
            lx.data.ExampleData(
                text=(
                    "Patient takes Aspirin 100mg daily for heart health and"
                    " Simvastatin 20mg at bedtime."
                ),
                extractions=[
                    lx.data.Extraction(
                        extraction_class="medication",
                        extraction_text="Aspirin",
                        attributes={"medication_group": "Aspirin"},
                    ),
                    lx.data.Extraction(
                        extraction_class="dosage",
                        extraction_text="100mg",
                        attributes={"medication_group": "Aspirin"},
                    ),
                    lx.data.Extraction(
                        extraction_class="frequency",
                        extraction_text="daily",
                        attributes={"medication_group": "Aspirin"},
                    ),
                    lx.data.Extraction(
                        extraction_class="condition",
                        extraction_text="heart health",
                        attributes={"medication_group": "Aspirin"},
                    ),
                    lx.data.Extraction(
                        extraction_class="medication",
                        extraction_text="Simvastatin",
                        attributes={"medication_group": "Simvastatin"},
                    ),
                    lx.data.Extraction(
                        extraction_class="dosage",
                        extraction_text="20mg",
                        attributes={"medication_group": "Simvastatin"},
                    ),
                    lx.data.Extraction(
                        extraction_class="frequency",
                        extraction_text="at bedtime",
                        attributes={"medication_group": "Simvastatin"},
                    ),
                ],
            )
        ]

        result = lx.extract(
            text_or_documents=raw_data,
            prompt_description=prompt_description,
            examples=examples,
            model_id=self.ollama_model_extract,
            model_url=self.ollama_url,
            resolver_params={"format_handler": lx_ollama.OLLAMA_FORMAT_HANDLER},
            max_char_buffer=4000,
            show_progress=True,
        )

        return self._convert_extractions_to_graph(result.extractions)

    def _convert_extractions_to_graph(self, extractions: list):
        """Convert langextract's flat, grouped extractions into (nodes, relationships)."""

        groups: dict[str, list] = {}
        for ext in extractions:
            if not ext.attributes or "medication_group" not in ext.attributes:
                continue
            group_name = ext.attributes["medication_group"]
            groups.setdefault(group_name, []).append(ext)

        nodes: dict[str, str] = {}
        relationships: list[dict] = []

        for group_name, group_extractions in groups.items():
            anchor_ext = next(
                (e for e in group_extractions if e.extraction_class == "medication"),
                None,
            )

            # Fall back to the group name itself if no explicit "medication"
            # extraction was found in this group, so we still get an anchor.
            anchor_text = anchor_ext.extraction_text if anchor_ext else group_name

            if anchor_text not in nodes:
                nodes[anchor_text] = str(uuid.uuid4())

            for ext in group_extractions:
                if ext is anchor_ext:
                    continue

                target_text = ext.extraction_text
                if target_text not in nodes:
                    nodes[target_text] = str(uuid.uuid4())

                relationships.append(
                    {
                        "source": nodes[anchor_text],
                        "target": nodes[target_text],
                        "type": ext.extraction_class,
                    }
                )

        return nodes, relationships

    def ingest_to_neo4j(self, nodes: dict, relationships: list):
        """
        Ingest nodes and relationships into Neo4j.
        """
        with self.neo4j_driver.session() as session:
            # Create nodes in Neo4j
            for name, node_id in nodes.items():
                session.run(
                    "CREATE (n:Entity {id: $id, name: $name})",
                    id=node_id,
                    name=name,
                )

            # Create relationships in Neo4j, using the semantic type
            # (dosage/frequency/condition/etc.) as the actual relationship
            # label instead of a generic "RELATIONSHIP" type.
            for relationship in relationships:
                rel_type = self._sanitize_relationship_type(relationship["type"])
                session.run(
                    "MATCH (a:Entity {id: $source_id}), (b:Entity {id: $target_id}) "
                    f"CREATE (a)-[:{rel_type} {{type: $type}}]->(b)",
                    source_id=relationship["source"],
                    target_id=relationship["target"],
                    type=relationship["type"],
                )

        return nodes

    @staticmethod
    def _sanitize_relationship_type(raw_type: str) -> str:
        """
        Cypher relationship types can't be passed as query parameters, so
        they have to be interpolated into the query string directly. Since
        raw_type comes from LLM-extracted text, sanitize it to a safe
        UPPER_SNAKE_CASE identifier before interpolation, to avoid Cypher
        injection or syntax errors from unexpected characters.
        """
        safe = "".join(ch if ch.isalnum() else "_" for ch in raw_type.strip())
        safe = safe.upper().strip("_") or "RELATIONSHIP"
        if safe[0].isdigit():
            safe = f"REL_{safe}"
        return safe

    def create_collection(self, collection_name: str, vector_dimension: int = None):
        vector_dimension = vector_dimension or self.vector_dimension

        try:
            # Try to fetch the collection status
            self.qdrant_client.get_collection(collection_name)
            print(f"Skipping creating collection; '{collection_name}' already exists.")
        except Exception as e:
            # If collection does not exist, an error will be thrown, so we create the collection
            if "Not found: Collection" in str(e) or "doesn't exist" in str(e) or "404" in str(e):
                print(f"Collection '{collection_name}' not found. Creating it now...")

                self.qdrant_client.create_collection(
                    collection_name=collection_name,
                    vectors_config=models.VectorParams(
                        size=vector_dimension, distance=models.Distance.COSINE
                    ),
                )

                print(f"Collection '{collection_name}' created successfully.")
            else:
                print(f"Error while checking collection: {e}")

    def ollama_embeddings(self, text: str) -> list[float]:
        response = self.ollama_client.embeddings(
            model=self.ollama_embedding_model,
            prompt=text,
        )
        return response["embedding"]

    def ingest_to_qdrant(self, collection_name: str, raw_data: str, node_id_mapping: dict):
        names = list(node_id_mapping.keys())
        embeddings = [self.ollama_embeddings(name) for name in names]

        self.qdrant_client.upsert(
            collection_name=collection_name,
            points=[
                {
                    "id": str(uuid.uuid4()),
                    "vector": embedding,
                    "payload": {"id": node_id_mapping[name], "name": name},
                }
                for name, embedding in zip(names, embeddings)
            ],
        )

    def retriever_search(self, collection_name: str, query: str, top_k: int = 5):
        retriever = QdrantNeo4jRetriever(
            driver=self.neo4j_driver,
            client=self.qdrant_client,
            collection_name=collection_name,
            id_property_external="id",
            id_property_neo4j="id",
        )

        results = retriever.search(
            query_vector=self.ollama_embeddings(query), top_k=top_k
        )

        return results

    def fetch_related_graph(self, entity_ids: list):
        query = """
        MATCH (e:Entity)-[r1]-(n1)-[r2]-(n2)
        WHERE e.id IN $entity_ids
        RETURN e, r1 as r, n1 as related, r2, n2
        UNION
        MATCH (e:Entity)-[r]-(related)
        WHERE e.id IN $entity_ids
        RETURN e, r, related, null as r2, null as n2
        """
        with self.neo4j_driver.session() as session:
            result = session.run(query, entity_ids=entity_ids)
            subgraph = []
            for record in result:
                subgraph.append(
                    {
                        "entity": record["e"],
                        "relationship": record["r"],
                        "related_node": record["related"],
                    }
                )
                if record["r2"] and record["n2"]:
                    subgraph.append(
                        {
                            "entity": record["related"],
                            "relationship": record["r2"],
                            "related_node": record["n2"],
                        }
                    )
        return subgraph

    def format_graph_context(self, subgraph: list):
        nodes = set()
        edges = []

        for entry in subgraph:
            entity = entry["entity"]
            related = entry["related_node"]
            relationship = entry["relationship"]

            nodes.add(entity["name"])
            nodes.add(related["name"])

            edges.append(f"{entity['name']} {relationship['type']} {related['name']}")

        return {"nodes": list(nodes), "edges": edges}

    def graphRAG_run(self, graph_context: dict, user_query: str):
        nodes_str = ", ".join(graph_context["nodes"])
        edges_str = "; ".join(graph_context["edges"])
        prompt = f"""
        You are an intelligent assistant with access to the following knowledge graph:

        Nodes: {nodes_str}

        Edges: {edges_str}

        Using this graph, Answer the following question:

        User Query: "{user_query}"
        """

        try:
            response = chat(
                model=self.ollama_model_answer,
                messages=[
                    {
                        "role": "system",
                        "content": "Provide the answer for the following question:",
                    },
                    {"role": "user", "content": prompt},
                ],
            )
            return response.message.content

        except Exception as e:
            return f"Error querying LLM: {str(e)}"

    def create_and_ingest(self, raw_data: str, query: str, collection_name: str = "medicationGraphRAGstore"):
        print("Creating collection...")
        self.create_collection(collection_name, self.vector_dimension)
        print("Collection created/verified")

        print("Extracting graph components...")
        nodes, relationships = self.extract_graph_components(raw_data)
        print("Nodes:", nodes)
        print("Relationships:", relationships)

        print("Ingesting to Neo4j...")
        node_id_mapping = self.ingest_to_neo4j(nodes, relationships)
        print("Neo4j ingestion complete")

        print("Ingesting to Qdrant...")
        self.ingest_to_qdrant(collection_name, raw_data, node_id_mapping)
        print("Qdrant ingestion complete")

    def run_pipeline(self, raw_data: str, query: str, collection_name: str = "medicationGraphRAGstore"):

        # run only the first time, comment this for subsequent runs
        # self.create_and_ingest(raw_data, query, collection_name)

        print("Starting retriever search...")
        retriever_result = self.retriever_search(collection_name, query)
        print("Retriever results:", retriever_result)

        print("Extracting entity IDs...")
        entity_ids = [
            item.content.split("'id': '")[1].split("'")[0]
            for item in retriever_result.items
        ]
        print("Entity IDs:", entity_ids)

        print("Fetching related graph...")
        subgraph = self.fetch_related_graph(entity_ids)
        print("Subgraph:", subgraph)

        print("Formatting graph context...")
        graph_context = self.format_graph_context(subgraph)
        print("Graph context:", graph_context)

        print("Running GraphRAG...")
        answer = self.graphRAG_run(graph_context, query)
        print("Final Answer:", answer)

        return answer

    def close(self):
        self.neo4j_driver.close()

if __name__ == "__main__":
    print("Script started")

    graph_rag = MedicationGraphRAG(env_path="../.env")

    # Example-1
    # raw_data = textwrap.dedent("""
    #     The patient was prescribed Lisinopril and Metformin last month.
    #     He takes the Lisinopril 10mg daily for hypertension, but often misses
    #     his Metformin 500mg dose which should be taken twice daily for diabetes.
    #     """).strip()

    # Example-2
    raw_data = textwrap.dedent("""
    The patient is a 62-year-old man with a history of multiple chronic conditions
    being managed through an extensive medication regimen. He was prescribed
    Lisinopril, Metformin, Atorvastatin, Aspirin, Levothyroxine, and Sertraline
    over the course of the past year, with his treatment plan adjusted several
    times based on follow-up visits.

    He takes Lisinopril 10mg daily for hypertension, but often misses his
    Metformin 500mg dose which should be taken twice daily for diabetes. His
    cardiologist also started him on Atorvastatin 40mg at bedtime for high
    cholesterol after his last lipid panel showed elevated LDL levels. To reduce
    his risk of cardiovascular events, he was additionally prescribed Aspirin
    81mg daily for heart disease prevention, which he takes alongside his
    breakfast each morning.

    Following a routine thyroid screening, he was found to have an underactive
    thyroid and was started on Levothyroxine 75mcg every morning for
    hypothyroidism, to be taken on an empty stomach before any other medications.
    More recently, after reporting persistent low mood and difficulty sleeping
    during a wellness visit, his primary care physician added Sertraline 50mg
    daily for depression, with plans to reassess the dosage after eight weeks.

    Despite the number of prescriptions, the patient has had difficulty
    maintaining consistency with his Metformin and occasionally forgets his
    evening Atorvastatin dose, which his care team is now addressing through a
    simplified pill organizer and reminder system.
    """).strip()

    # Sample Questions
    #1. "What is the dosage and frequency for Lisinopril?"
    #2. "What is the dosage and frequency for Metformin?"
    #3. "Which medications does the patient take once daily versus twice daily?"
    #4. "What medication is prescribed for hypothyroidism, and at what dose?"
    #5. "List all medications related to cardiovascular conditions and their dosages."
    #6. "How often does the patient take Aspirin?"
    #7. "What condition is Levothyroxine prescribed for?"
    #8. "What time of day should Levothyroxine be taken, and why?"
    #9. "Which medications does the patient have trouble taking consistently?"
    #10. "What is the dosage and frequency for Sertraline?"

    query = "List all medications related to cardiovascular conditions and their dosages."

    answer = graph_rag.run_pipeline(raw_data, query, collection_name="medicationGraphRAGstore")

    graph_rag.close()

Ausführung

Drei Beispielfragen zeigen das System in Aktion. Jede gibt zunächst die Ergebnisse des Retrievers aus und anschließend die graphbasierte Antwort.

query = "List all medications related to cardiovascular conditions and their dosages."

Console:
Starting retriever search...
Retriever results: items=[RetrieverResultItem(content="<Record node=<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}> score=0.5062605>", metadata=None), RetrieverResultItem(content="<Record node=<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:0' labels=frozenset({'Entity'}) properties={'name': 'Atorvastatin', 'id': '1db81626-c3de-4cab-b5dd-091327785182'}> score=0.47961158>", metadata=None), RetrieverResultItem(content="<Record node=<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:6' labels=frozenset({'Entity'}) properties={'name': 'heart disease prevention', 'id': '44573186-869f-4d5d-ba04-fe254ec4ed21'}> score=0.45777896>", metadata=None), RetrieverResultItem(content="<Record node=<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}> score=0.45199984>", metadata=None), RetrieverResultItem(content="<Record node=<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}> score=0.4511963>", metadata=None)] metadata={'__retriever': 'QdrantNeo4jRetriever'}
Extracting entity IDs...
Entity IDs: ['1c9fb28e-c3e1-4515-afa0-01939beac419', '1db81626-c3de-4cab-b5dd-091327785182', '44573186-869f-4d5d-ba04-fe254ec4ed21', '04f27c55-38a3-46a9-a411-4faf07836a56', '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb']
Fetching related graph...
Subgraph: [{'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:6' labels=frozenset({'Entity'}) properties={'name': 'heart disease prevention', 'id': '44573186-869f-4d5d-ba04-fe254ec4ed21'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:5' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:6' labels=frozenset({'Entity'}) properties={'name': 'heart disease prevention', 'id': '44573186-869f-4d5d-ba04-fe254ec4ed21'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:4' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:6' labels=frozenset({'Entity'}) properties={'name': 'heart disease prevention', 'id': '44573186-869f-4d5d-ba04-fe254ec4ed21'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:5' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:6' labels=frozenset({'Entity'}) properties={'name': 'heart disease prevention', 'id': '44573186-869f-4d5d-ba04-fe254ec4ed21'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:3' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:5' labels=frozenset({'Entity'}) properties={'name': '81mg', 'id': '9d1d3859-cf6f-4a22-81b8-7d80e3cc8e89'}>) type='DOSAGE' properties={'type': 'dosage'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:5' labels=frozenset({'Entity'}) properties={'name': '81mg', 'id': '9d1d3859-cf6f-4a22-81b8-7d80e3cc8e89'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:7' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:17' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:20' labels=frozenset({'Entity'}) properties={'name': 'Sertraline', 'id': '42844c4c-ce96-4bd9-8d37-d8adad5a75fe'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:20' labels=frozenset({'Entity'}) properties={'name': 'Sertraline', 'id': '42844c4c-ce96-4bd9-8d37-d8adad5a75fe'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:7' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:4' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:15' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>) type='ROUTE' properties={'type': 'route'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:14' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:18' labels=frozenset({'Entity'}) properties={'name': 'hypothyroidism', 'id': '95b91440-5ff1-41eb-a036-b57880094b05'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:18' labels=frozenset({'Entity'}) properties={'name': 'hypothyroidism', 'id': '95b91440-5ff1-41eb-a036-b57880094b05'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:15' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>) type='ROUTE' properties={'type': 'route'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:13' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:17' labels=frozenset({'Entity'}) properties={'name': 'every morning', 'id': '7fb1c7e5-e414-43ec-8606-474b08dc9173'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:17' labels=frozenset({'Entity'}) properties={'name': 'every morning', 'id': '7fb1c7e5-e414-43ec-8606-474b08dc9173'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:15' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>) type='ROUTE' properties={'type': 'route'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:12' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:16' labels=frozenset({'Entity'}) properties={'name': '75mcg', 'id': '75b6f7a1-2f53-419c-9365-5f026dcb1e25'}>) type='DOSAGE' properties={'type': 'dosage'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:16' labels=frozenset({'Entity'}) properties={'name': '75mcg', 'id': '75b6f7a1-2f53-419c-9365-5f026dcb1e25'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:0' labels=frozenset({'Entity'}) properties={'name': 'Atorvastatin', 'id': '1db81626-c3de-4cab-b5dd-091327785182'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:2' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:0' labels=frozenset({'Entity'}) properties={'name': 'Atorvastatin', 'id': '1db81626-c3de-4cab-b5dd-091327785182'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:3' labels=frozenset({'Entity'}) properties={'name': 'high cholesterol', 'id': 'dc85b413-3eca-4f26-a1dd-95de9d61e46c'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:3' labels=frozenset({'Entity'}) properties={'name': 'high cholesterol', 'id': 'dc85b413-3eca-4f26-a1dd-95de9d61e46c'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:0' labels=frozenset({'Entity'}) properties={'name': 'Atorvastatin', 'id': '1db81626-c3de-4cab-b5dd-091327785182'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:1' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:0' labels=frozenset({'Entity'}) properties={'name': 'Atorvastatin', 'id': '1db81626-c3de-4cab-b5dd-091327785182'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:2' labels=frozenset({'Entity'}) properties={'name': 'at bedtime', 'id': 'f9a049d4-bdb9-443d-a70f-3aa0ad290f5d'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:2' labels=frozenset({'Entity'}) properties={'name': 'at bedtime', 'id': 'f9a049d4-bdb9-443d-a70f-3aa0ad290f5d'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:0' labels=frozenset({'Entity'}) properties={'name': 'Atorvastatin', 'id': '1db81626-c3de-4cab-b5dd-091327785182'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:0' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:0' labels=frozenset({'Entity'}) properties={'name': 'Atorvastatin', 'id': '1db81626-c3de-4cab-b5dd-091327785182'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:1' labels=frozenset({'Entity'}) properties={'name': '40mg', 'id': '960fd15d-ad36-4b90-aede-3473dd53f70c'}>) type='DOSAGE' properties={'type': 'dosage'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:1' labels=frozenset({'Entity'}) properties={'name': '40mg', 'id': '960fd15d-ad36-4b90-aede-3473dd53f70c'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:6' labels=frozenset({'Entity'}) properties={'name': 'heart disease prevention', 'id': '44573186-869f-4d5d-ba04-fe254ec4ed21'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:5' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:6' labels=frozenset({'Entity'}) properties={'name': 'heart disease prevention', 'id': '44573186-869f-4d5d-ba04-fe254ec4ed21'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:15' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>) type='ROUTE' properties={'type': 'route'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:14' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:18' labels=frozenset({'Entity'}) properties={'name': 'hypothyroidism', 'id': '95b91440-5ff1-41eb-a036-b57880094b05'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:18' labels=frozenset({'Entity'}) properties={'name': 'hypothyroidism', 'id': '95b91440-5ff1-41eb-a036-b57880094b05'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:13' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:17' labels=frozenset({'Entity'}) properties={'name': 'every morning', 'id': '7fb1c7e5-e414-43ec-8606-474b08dc9173'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:17' labels=frozenset({'Entity'}) properties={'name': 'every morning', 'id': '7fb1c7e5-e414-43ec-8606-474b08dc9173'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:12' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:16' labels=frozenset({'Entity'}) properties={'name': '75mcg', 'id': '75b6f7a1-2f53-419c-9365-5f026dcb1e25'}>) type='DOSAGE' properties={'type': 'dosage'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:16' labels=frozenset({'Entity'}) properties={'name': '75mcg', 'id': '75b6f7a1-2f53-419c-9365-5f026dcb1e25'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:8' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:11' labels=frozenset({'Entity'}) properties={'name': 'hypertension', 'id': '1bc0479e-5e00-4ede-8a9d-704e56f58814'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:11' labels=frozenset({'Entity'}) properties={'name': 'hypertension', 'id': '1bc0479e-5e00-4ede-8a9d-704e56f58814'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:7' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:6' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:9' labels=frozenset({'Entity'}) properties={'name': '10mg', 'id': 'cddff401-0958-4093-b196-ad270b7aa797'}>) type='DOSAGE' properties={'type': 'dosage'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:9' labels=frozenset({'Entity'}) properties={'name': '10mg', 'id': 'cddff401-0958-4093-b196-ad270b7aa797'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:15' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>) type='ROUTE' properties={'type': 'route'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>}]
Formatting graph context...
Graph context: {'nodes': ['on an empty stomach before any other medications', 'hypertension', 'Atorvastatin', 'Lisinopril', 'Levothyroxine', 'at bedtime', 'high cholesterol', 'Aspirin', '75mcg', '81mg', 'daily', '10mg', 'heart disease prevention', 'every morning', 'Sertraline', 'hypothyroidism', '40mg'], 'edges': ['heart disease prevention condition Aspirin', 'Aspirin frequency daily', 'heart disease prevention condition Aspirin', 'Aspirin dosage 81mg', 'Lisinopril frequency daily', 'daily frequency Sertraline', 'Lisinopril frequency daily', 'daily frequency Aspirin', 'on an empty stomach before any other medications route Levothyroxine', 'Levothyroxine condition hypothyroidism', 'on an empty stomach before any other medications route Levothyroxine', 'Levothyroxine frequency every morning', 'on an empty stomach before any other medications route Levothyroxine', 'Levothyroxine dosage 75mcg', 'Atorvastatin condition high cholesterol', 'Atorvastatin frequency at bedtime', 'Atorvastatin dosage 40mg', 'heart disease prevention condition Aspirin', 'Levothyroxine route on an empty stomach before any other medications', 'Levothyroxine condition hypothyroidism', 'Levothyroxine frequency every morning', 'Levothyroxine dosage 75mcg', 'Lisinopril condition hypertension', 'Lisinopril frequency daily', 'Lisinopril dosage 10mg', 'on an empty stomach before any other medications route Levothyroxine']}
Running GraphRAG...
Final Answer: Here’s a list of medications related to cardiovascular conditions and their dosages based on the knowledge graph:

*   **Aspirin:** 81mg (frequency: daily) - for heart disease prevention.
*   **Atorvastatin:** 40mg (frequency: at bedtime) - for high cholesterol.
*   **Lisinopril:** 10mg (frequency: daily) - for hypertension.
query = "What medication is prescribed for hypothyroidism, and at what dose?"

Console:
Starting retriever search...
Retriever results: items=[RetrieverResultItem(content="<Record node=<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:18' labels=frozenset({'Entity'}) properties={'name': 'hypothyroidism', 'id': '95b91440-5ff1-41eb-a036-b57880094b05'}> score=0.6616618>", metadata=None), RetrieverResultItem(content="<Record node=<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}> score=0.5983002>", metadata=None), RetrieverResultItem(content="<Record node=<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}> score=0.4675771>", metadata=None), RetrieverResultItem(content="<Record node=<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}> score=0.4620626>", metadata=None), RetrieverResultItem(content="<Record node=<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:9' labels=frozenset({'Entity'}) properties={'name': '10mg', 'id': 'cddff401-0958-4093-b196-ad270b7aa797'}> score=0.4382253>", metadata=None)] metadata={'__retriever': 'QdrantNeo4jRetriever'}
Extracting entity IDs...
Entity IDs: ['95b91440-5ff1-41eb-a036-b57880094b05', '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb', 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847', '1c9fb28e-c3e1-4515-afa0-01939beac419', 'cddff401-0958-4093-b196-ad270b7aa797']
Fetching related graph...
Subgraph: [{'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:9' labels=frozenset({'Entity'}) properties={'name': '10mg', 'id': 'cddff401-0958-4093-b196-ad270b7aa797'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:6' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:9' labels=frozenset({'Entity'}) properties={'name': '10mg', 'id': 'cddff401-0958-4093-b196-ad270b7aa797'}>) type='DOSAGE' properties={'type': 'dosage'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:8' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:11' labels=frozenset({'Entity'}) properties={'name': 'hypertension', 'id': '1bc0479e-5e00-4ede-8a9d-704e56f58814'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:11' labels=frozenset({'Entity'}) properties={'name': 'hypertension', 'id': '1bc0479e-5e00-4ede-8a9d-704e56f58814'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:9' labels=frozenset({'Entity'}) properties={'name': '10mg', 'id': 'cddff401-0958-4093-b196-ad270b7aa797'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:6' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:9' labels=frozenset({'Entity'}) properties={'name': '10mg', 'id': 'cddff401-0958-4093-b196-ad270b7aa797'}>) type='DOSAGE' properties={'type': 'dosage'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:7' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:18' labels=frozenset({'Entity'}) properties={'name': 'hypothyroidism', 'id': '95b91440-5ff1-41eb-a036-b57880094b05'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:14' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:18' labels=frozenset({'Entity'}) properties={'name': 'hypothyroidism', 'id': '95b91440-5ff1-41eb-a036-b57880094b05'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:15' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>) type='ROUTE' properties={'type': 'route'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:18' labels=frozenset({'Entity'}) properties={'name': 'hypothyroidism', 'id': '95b91440-5ff1-41eb-a036-b57880094b05'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:14' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:18' labels=frozenset({'Entity'}) properties={'name': 'hypothyroidism', 'id': '95b91440-5ff1-41eb-a036-b57880094b05'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:13' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:17' labels=frozenset({'Entity'}) properties={'name': 'every morning', 'id': '7fb1c7e5-e414-43ec-8606-474b08dc9173'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:17' labels=frozenset({'Entity'}) properties={'name': 'every morning', 'id': '7fb1c7e5-e414-43ec-8606-474b08dc9173'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:18' labels=frozenset({'Entity'}) properties={'name': 'hypothyroidism', 'id': '95b91440-5ff1-41eb-a036-b57880094b05'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:14' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:18' labels=frozenset({'Entity'}) properties={'name': 'hypothyroidism', 'id': '95b91440-5ff1-41eb-a036-b57880094b05'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:12' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:16' labels=frozenset({'Entity'}) properties={'name': '75mcg', 'id': '75b6f7a1-2f53-419c-9365-5f026dcb1e25'}>) type='DOSAGE' properties={'type': 'dosage'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:16' labels=frozenset({'Entity'}) properties={'name': '75mcg', 'id': '75b6f7a1-2f53-419c-9365-5f026dcb1e25'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:15' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>) type='ROUTE' properties={'type': 'route'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:14' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:18' labels=frozenset({'Entity'}) properties={'name': 'hypothyroidism', 'id': '95b91440-5ff1-41eb-a036-b57880094b05'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:18' labels=frozenset({'Entity'}) properties={'name': 'hypothyroidism', 'id': '95b91440-5ff1-41eb-a036-b57880094b05'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:15' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>) type='ROUTE' properties={'type': 'route'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:13' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:17' labels=frozenset({'Entity'}) properties={'name': 'every morning', 'id': '7fb1c7e5-e414-43ec-8606-474b08dc9173'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:17' labels=frozenset({'Entity'}) properties={'name': 'every morning', 'id': '7fb1c7e5-e414-43ec-8606-474b08dc9173'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:15' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>) type='ROUTE' properties={'type': 'route'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:12' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:16' labels=frozenset({'Entity'}) properties={'name': '75mcg', 'id': '75b6f7a1-2f53-419c-9365-5f026dcb1e25'}>) type='DOSAGE' properties={'type': 'dosage'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:16' labels=frozenset({'Entity'}) properties={'name': '75mcg', 'id': '75b6f7a1-2f53-419c-9365-5f026dcb1e25'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:15' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>) type='ROUTE' properties={'type': 'route'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:14' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:18' labels=frozenset({'Entity'}) properties={'name': 'hypothyroidism', 'id': '95b91440-5ff1-41eb-a036-b57880094b05'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:18' labels=frozenset({'Entity'}) properties={'name': 'hypothyroidism', 'id': '95b91440-5ff1-41eb-a036-b57880094b05'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:13' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:17' labels=frozenset({'Entity'}) properties={'name': 'every morning', 'id': '7fb1c7e5-e414-43ec-8606-474b08dc9173'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:17' labels=frozenset({'Entity'}) properties={'name': 'every morning', 'id': '7fb1c7e5-e414-43ec-8606-474b08dc9173'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:12' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:16' labels=frozenset({'Entity'}) properties={'name': '75mcg', 'id': '75b6f7a1-2f53-419c-9365-5f026dcb1e25'}>) type='DOSAGE' properties={'type': 'dosage'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:16' labels=frozenset({'Entity'}) properties={'name': '75mcg', 'id': '75b6f7a1-2f53-419c-9365-5f026dcb1e25'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:9' labels=frozenset({'Entity'}) properties={'name': '10mg', 'id': 'cddff401-0958-4093-b196-ad270b7aa797'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:6' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:9' labels=frozenset({'Entity'}) properties={'name': '10mg', 'id': 'cddff401-0958-4093-b196-ad270b7aa797'}>) type='DOSAGE' properties={'type': 'dosage'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:11' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:15' labels=frozenset({'Entity'}) properties={'name': 'diabetes', 'id': '9cbb512f-ca6b-47de-bb12-378ac35826bd'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:15' labels=frozenset({'Entity'}) properties={'name': 'diabetes', 'id': '9cbb512f-ca6b-47de-bb12-378ac35826bd'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:10' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:14' labels=frozenset({'Entity'}) properties={'name': 'twice daily', 'id': '73d5a502-05be-4bb7-916a-10b8ff5130fa'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:14' labels=frozenset({'Entity'}) properties={'name': 'twice daily', 'id': '73d5a502-05be-4bb7-916a-10b8ff5130fa'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:9' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:13' labels=frozenset({'Entity'}) properties={'name': '500mg', 'id': '6c38fe32-0ca3-4bcc-a072-05e302aaa8e7'}>) type='DOSAGE' properties={'type': 'dosage'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:13' labels=frozenset({'Entity'}) properties={'name': '500mg', 'id': '6c38fe32-0ca3-4bcc-a072-05e302aaa8e7'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:18' labels=frozenset({'Entity'}) properties={'name': 'hypothyroidism', 'id': '95b91440-5ff1-41eb-a036-b57880094b05'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:14' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:18' labels=frozenset({'Entity'}) properties={'name': 'hypothyroidism', 'id': '95b91440-5ff1-41eb-a036-b57880094b05'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:15' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>) type='ROUTE' properties={'type': 'route'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>}]
Formatting graph context...
Graph context: {'nodes': ['Lisinopril', '75mcg', 'twice daily', 'diabetes', 'on an empty stomach before any other medications', 'hypertension', 'daily', 'Metformin', '500mg', '10mg', 'hypothyroidism', 'Levothyroxine', 'every morning'], 'edges': ['10mg dosage Lisinopril', 'Lisinopril condition hypertension', '10mg dosage Lisinopril', 'Lisinopril frequency daily', 'hypothyroidism condition Levothyroxine', 'Levothyroxine route on an empty stomach before any other medications', 'hypothyroidism condition Levothyroxine', 'Levothyroxine frequency every morning', 'hypothyroidism condition Levothyroxine', 'Levothyroxine dosage 75mcg', 'on an empty stomach before any other medications route Levothyroxine', 'Levothyroxine condition hypothyroidism', 'on an empty stomach before any other medications route Levothyroxine', 'Levothyroxine frequency every morning', 'on an empty stomach before any other medications route Levothyroxine', 'Levothyroxine dosage 75mcg', 'Levothyroxine route on an empty stomach before any other medications', 'Levothyroxine condition hypothyroidism', 'Levothyroxine frequency every morning', 'Levothyroxine dosage 75mcg', '10mg dosage Lisinopril', 'Metformin condition diabetes', 'Metformin frequency twice daily', 'Metformin dosage 500mg', 'hypothyroidism condition Levothyroxine', 'on an empty stomach before any other medications route Levothyroxine']}
Running GraphRAG...
Final Answer: Levothyroxine 75mcg is prescribed for hypothyroidism, taken every morning.
query = "Which medications does the patient take once daily versus twice daily?"

Console:
Starting retriever search...
Retriever results: items=[RetrieverResultItem(content="<Record node=<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:14' labels=frozenset({'Entity'}) properties={'name': 'twice daily', 'id': '73d5a502-05be-4bb7-916a-10b8ff5130fa'}> score=0.6052238>", metadata=None), RetrieverResultItem(content="<Record node=<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}> score=0.50138044>", metadata=None), RetrieverResultItem(content="<Record node=<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}> score=0.424541>", metadata=None), RetrieverResultItem(content="<Record node=<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:15' labels=frozenset({'Entity'}) properties={'name': 'diabetes', 'id': '9cbb512f-ca6b-47de-bb12-378ac35826bd'}> score=0.42364278>", metadata=None), RetrieverResultItem(content="<Record node=<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}> score=0.4210245>", metadata=None)] metadata={'__retriever': 'QdrantNeo4jRetriever'}
Extracting entity IDs...
Entity IDs: ['73d5a502-05be-4bb7-916a-10b8ff5130fa', '1c9fb28e-c3e1-4515-afa0-01939beac419', '06da6faa-baa5-4657-a961-5091f58e3058', '9cbb512f-ca6b-47de-bb12-378ac35826bd', 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847']
Fetching related graph...
Subgraph: [{'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:17' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:20' labels=frozenset({'Entity'}) properties={'name': 'Sertraline', 'id': '42844c4c-ce96-4bd9-8d37-d8adad5a75fe'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:20' labels=frozenset({'Entity'}) properties={'name': 'Sertraline', 'id': '42844c4c-ce96-4bd9-8d37-d8adad5a75fe'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:20' labels=frozenset({'Entity'}) properties={'name': 'Sertraline', 'id': '42844c4c-ce96-4bd9-8d37-d8adad5a75fe'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:18' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:20' labels=frozenset({'Entity'}) properties={'name': 'Sertraline', 'id': '42844c4c-ce96-4bd9-8d37-d8adad5a75fe'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:22' labels=frozenset({'Entity'}) properties={'name': 'depression', 'id': '3aca7091-a4fa-4b12-ba5a-a8dbbbac5df4'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:22' labels=frozenset({'Entity'}) properties={'name': 'depression', 'id': '3aca7091-a4fa-4b12-ba5a-a8dbbbac5df4'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:17' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:20' labels=frozenset({'Entity'}) properties={'name': 'Sertraline', 'id': '42844c4c-ce96-4bd9-8d37-d8adad5a75fe'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:20' labels=frozenset({'Entity'}) properties={'name': 'Sertraline', 'id': '42844c4c-ce96-4bd9-8d37-d8adad5a75fe'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:20' labels=frozenset({'Entity'}) properties={'name': 'Sertraline', 'id': '42844c4c-ce96-4bd9-8d37-d8adad5a75fe'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:16' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:20' labels=frozenset({'Entity'}) properties={'name': 'Sertraline', 'id': '42844c4c-ce96-4bd9-8d37-d8adad5a75fe'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:21' labels=frozenset({'Entity'}) properties={'name': '50mg', 'id': '5fe00dee-bd0f-4476-b5a6-b19974033f78'}>) type='DOSAGE' properties={'type': 'dosage'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:21' labels=frozenset({'Entity'}) properties={'name': '50mg', 'id': '5fe00dee-bd0f-4476-b5a6-b19974033f78'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:4' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:5' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:6' labels=frozenset({'Entity'}) properties={'name': 'heart disease prevention', 'id': '44573186-869f-4d5d-ba04-fe254ec4ed21'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:6' labels=frozenset({'Entity'}) properties={'name': 'heart disease prevention', 'id': '44573186-869f-4d5d-ba04-fe254ec4ed21'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:4' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:3' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:5' labels=frozenset({'Entity'}) properties={'name': '81mg', 'id': '9d1d3859-cf6f-4a22-81b8-7d80e3cc8e89'}>) type='DOSAGE' properties={'type': 'dosage'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:5' labels=frozenset({'Entity'}) properties={'name': '81mg', 'id': '9d1d3859-cf6f-4a22-81b8-7d80e3cc8e89'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:7' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:8' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:11' labels=frozenset({'Entity'}) properties={'name': 'hypertension', 'id': '1bc0479e-5e00-4ede-8a9d-704e56f58814'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:11' labels=frozenset({'Entity'}) properties={'name': 'hypertension', 'id': '1bc0479e-5e00-4ede-8a9d-704e56f58814'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:7' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:6' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:9' labels=frozenset({'Entity'}) properties={'name': '10mg', 'id': 'cddff401-0958-4093-b196-ad270b7aa797'}>) type='DOSAGE' properties={'type': 'dosage'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:9' labels=frozenset({'Entity'}) properties={'name': '10mg', 'id': 'cddff401-0958-4093-b196-ad270b7aa797'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:14' labels=frozenset({'Entity'}) properties={'name': 'twice daily', 'id': '73d5a502-05be-4bb7-916a-10b8ff5130fa'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:10' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:14' labels=frozenset({'Entity'}) properties={'name': 'twice daily', 'id': '73d5a502-05be-4bb7-916a-10b8ff5130fa'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:11' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:15' labels=frozenset({'Entity'}) properties={'name': 'diabetes', 'id': '9cbb512f-ca6b-47de-bb12-378ac35826bd'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:15' labels=frozenset({'Entity'}) properties={'name': 'diabetes', 'id': '9cbb512f-ca6b-47de-bb12-378ac35826bd'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:14' labels=frozenset({'Entity'}) properties={'name': 'twice daily', 'id': '73d5a502-05be-4bb7-916a-10b8ff5130fa'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:10' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:14' labels=frozenset({'Entity'}) properties={'name': 'twice daily', 'id': '73d5a502-05be-4bb7-916a-10b8ff5130fa'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:9' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:13' labels=frozenset({'Entity'}) properties={'name': '500mg', 'id': '6c38fe32-0ca3-4bcc-a072-05e302aaa8e7'}>) type='DOSAGE' properties={'type': 'dosage'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:13' labels=frozenset({'Entity'}) properties={'name': '500mg', 'id': '6c38fe32-0ca3-4bcc-a072-05e302aaa8e7'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:15' labels=frozenset({'Entity'}) properties={'name': 'diabetes', 'id': '9cbb512f-ca6b-47de-bb12-378ac35826bd'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:11' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:15' labels=frozenset({'Entity'}) properties={'name': 'diabetes', 'id': '9cbb512f-ca6b-47de-bb12-378ac35826bd'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:10' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:14' labels=frozenset({'Entity'}) properties={'name': 'twice daily', 'id': '73d5a502-05be-4bb7-916a-10b8ff5130fa'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:14' labels=frozenset({'Entity'}) properties={'name': 'twice daily', 'id': '73d5a502-05be-4bb7-916a-10b8ff5130fa'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:15' labels=frozenset({'Entity'}) properties={'name': 'diabetes', 'id': '9cbb512f-ca6b-47de-bb12-378ac35826bd'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:11' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:15' labels=frozenset({'Entity'}) properties={'name': 'diabetes', 'id': '9cbb512f-ca6b-47de-bb12-378ac35826bd'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:9' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:13' labels=frozenset({'Entity'}) properties={'name': '500mg', 'id': '6c38fe32-0ca3-4bcc-a072-05e302aaa8e7'}>) type='DOSAGE' properties={'type': 'dosage'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:13' labels=frozenset({'Entity'}) properties={'name': '500mg', 'id': '6c38fe32-0ca3-4bcc-a072-05e302aaa8e7'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:15' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>) type='ROUTE' properties={'type': 'route'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:14' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:18' labels=frozenset({'Entity'}) properties={'name': 'hypothyroidism', 'id': '95b91440-5ff1-41eb-a036-b57880094b05'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:18' labels=frozenset({'Entity'}) properties={'name': 'hypothyroidism', 'id': '95b91440-5ff1-41eb-a036-b57880094b05'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:15' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>) type='ROUTE' properties={'type': 'route'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:13' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:17' labels=frozenset({'Entity'}) properties={'name': 'every morning', 'id': '7fb1c7e5-e414-43ec-8606-474b08dc9173'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:17' labels=frozenset({'Entity'}) properties={'name': 'every morning', 'id': '7fb1c7e5-e414-43ec-8606-474b08dc9173'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:15' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>) type='ROUTE' properties={'type': 'route'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:12' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:16' labels=frozenset({'Entity'}) properties={'name': '75mcg', 'id': '75b6f7a1-2f53-419c-9365-5f026dcb1e25'}>) type='DOSAGE' properties={'type': 'dosage'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:16' labels=frozenset({'Entity'}) properties={'name': '75mcg', 'id': '75b6f7a1-2f53-419c-9365-5f026dcb1e25'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:17' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:20' labels=frozenset({'Entity'}) properties={'name': 'Sertraline', 'id': '42844c4c-ce96-4bd9-8d37-d8adad5a75fe'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:20' labels=frozenset({'Entity'}) properties={'name': 'Sertraline', 'id': '42844c4c-ce96-4bd9-8d37-d8adad5a75fe'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:4' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:4' labels=frozenset({'Entity'}) properties={'name': 'Aspirin', 'id': '10939c85-6fc1-41b4-9b80-abe1662eda11'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:7' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:10' labels=frozenset({'Entity'}) properties={'name': 'daily', 'id': '06da6faa-baa5-4657-a961-5091f58e3058'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:8' labels=frozenset({'Entity'}) properties={'name': 'Lisinopril', 'id': '04f27c55-38a3-46a9-a411-4faf07836a56'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:11' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:15' labels=frozenset({'Entity'}) properties={'name': 'diabetes', 'id': '9cbb512f-ca6b-47de-bb12-378ac35826bd'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:15' labels=frozenset({'Entity'}) properties={'name': 'diabetes', 'id': '9cbb512f-ca6b-47de-bb12-378ac35826bd'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:10' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:14' labels=frozenset({'Entity'}) properties={'name': 'twice daily', 'id': '73d5a502-05be-4bb7-916a-10b8ff5130fa'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:14' labels=frozenset({'Entity'}) properties={'name': 'twice daily', 'id': '73d5a502-05be-4bb7-916a-10b8ff5130fa'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:9' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:13' labels=frozenset({'Entity'}) properties={'name': '500mg', 'id': '6c38fe32-0ca3-4bcc-a072-05e302aaa8e7'}>) type='DOSAGE' properties={'type': 'dosage'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:13' labels=frozenset({'Entity'}) properties={'name': '500mg', 'id': '6c38fe32-0ca3-4bcc-a072-05e302aaa8e7'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:14' labels=frozenset({'Entity'}) properties={'name': 'twice daily', 'id': '73d5a502-05be-4bb7-916a-10b8ff5130fa'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:10' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:14' labels=frozenset({'Entity'}) properties={'name': 'twice daily', 'id': '73d5a502-05be-4bb7-916a-10b8ff5130fa'}>) type='FREQUENCY' properties={'type': 'frequency'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:15' labels=frozenset({'Entity'}) properties={'name': 'diabetes', 'id': '9cbb512f-ca6b-47de-bb12-378ac35826bd'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:11' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:15' labels=frozenset({'Entity'}) properties={'name': 'diabetes', 'id': '9cbb512f-ca6b-47de-bb12-378ac35826bd'}>) type='CONDITION' properties={'type': 'condition'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:12' labels=frozenset({'Entity'}) properties={'name': 'Metformin', 'id': 'd14d70ef-3780-4ebe-b803-1ab8bd8ec847'}>}, {'entity': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>, 'relationship': <Relationship element_id='5:a53f7783-1308-4f3d-9a27-45cede6b6376:15' nodes=(<Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>, <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:19' labels=frozenset({'Entity'}) properties={'name': 'on an empty stomach before any other medications', 'id': '1c9fb28e-c3e1-4515-afa0-01939beac419'}>) type='ROUTE' properties={'type': 'route'}>, 'related_node': <Node element_id='4:a53f7783-1308-4f3d-9a27-45cede6b6376:7' labels=frozenset({'Entity'}) properties={'name': 'Levothyroxine', 'id': '60654f2d-2ec8-4f4e-be02-cd57b7c5abfb'}>}]
Formatting graph context...
Graph context: {'nodes': ['twice daily', 'daily', '75mcg', '50mg', '81mg', 'Aspirin', 'on an empty stomach before any other medications', 'hypothyroidism', 'hypertension', 'depression', 'Lisinopril', 'Levothyroxine', 'heart disease prevention', 'every morning', 'Sertraline', 'diabetes', '500mg', '10mg', 'Metformin'], 'edges': ['daily frequency Sertraline', 'Sertraline condition depression', 'daily frequency Sertraline', 'Sertraline dosage 50mg', 'daily frequency Aspirin', 'Aspirin condition heart disease prevention', 'daily frequency Aspirin', 'Aspirin dosage 81mg', 'daily frequency Lisinopril', 'Lisinopril condition hypertension', 'daily frequency Lisinopril', 'Lisinopril dosage 10mg', 'twice daily frequency Metformin', 'Metformin condition diabetes', 'twice daily frequency Metformin', 'Metformin dosage 500mg', 'diabetes condition Metformin', 'Metformin frequency twice daily', 'diabetes condition Metformin', 'Metformin dosage 500mg', 'on an empty stomach before any other medications route Levothyroxine', 'Levothyroxine condition hypothyroidism', 'on an empty stomach before any other medications route Levothyroxine', 'Levothyroxine frequency every morning', 'on an empty stomach before any other medications route Levothyroxine', 'Levothyroxine dosage 75mcg', 'daily frequency Sertraline', 'daily frequency Aspirin', 'daily frequency Lisinopril', 'Metformin condition diabetes', 'Metformin frequency twice daily', 'Metformin dosage 500mg', 'twice daily frequency Metformin', 'diabetes condition Metformin', 'on an empty stomach before any other medications route Levothyroxine']}
Running GraphRAG...
Final Answer: Here’s the breakdown of medications taken once daily versus twice daily based on the knowledge graph:

**Once Daily:**

*   Aspirin: daily frequency
*   Sertraline: daily frequency
*   Levothyroxine: every morning frequency

**Twice Daily:**

*   Metformin: twice daily frequency

Was die Kompilierung zeigt

Das Ergebnis ist ein vollständiger GraphRAG-Pipeline mit allen Komponenten, die lokal auf Ollama, Neo4j, Qdrant und LangExtract laufen. Unstrukturierter Text wird durch die Extraktion von Entitäten und Beziehungen zu strukturiertem Wissen, das als Graph in Neo4j gespeichert wird. Qdrant ermöglicht eine semantische Suche in den Graphen und verbindet die Vektorsuche mit der Graphenuntersuchung. Gemeinsam ersetzen sie die auf Blöcken basierende Suche durch eine kontextbewusste Suche, die auf vernetztem Wissen beruht, sodass ein LLM über Beziehungen statt über isolierte Textteile nachdenken kann – was zu besser begründeten und leichter erklärbaren Antworten führt. Da die gesamte Infrastruktur lokal ist, behalten Entwickler die volle Kontrolle über ihre Daten, Modelle und Infrastruktur. Mit zunehmender Adoption von GraphRAG bietet ein solches Design einen praktischen Leitfaden für eine auf offenen Quellcode-Tools basierende, beziehungsorientierte Suche.