Startseite / Artikel

Domänenbewusster RAG mit MLflow-Registern und LLM-Routing

Domain-konformes RAG: Absicht klassifizieren, den richtigen Embedder aus einem MLflow-Registry laden, die entsprechende Qdrant-Sammlung durchsuchen und anschließend die Generierung an ein LLM weiterleiten.

Verlag: REACTAPP.TOP12 Min. Lesezeit2688 Wörter

Quellen: RAG Beyond Retrieval: Model Registry, Vector Search and Intelligent LLM Routing

Die meisten RAG-Demos verbinden einen Embedder, eine Sammlung und ein LLM miteinander. Das funktioniert gut, solange Hypotheken- und medizinische Fragen denselben Prozess teilen oder bis ein kleines lokales Modell zur Erstbewertung ausreicht, während ein größeres entferntes Modell die klinischen Details beantworten soll. Ein robusterer Ansatz klassifiziert zunächst die Absicht, wählt anschließend die passende Wissensbasis sowie das Embedding-Modell aus, holt den Kontext ab und leitet die Generierung anschließend an das geeignete LLM weiter.

Diese Implementierung setzt diese Idee auf bescheidenen Hardware-Ressourcen um: MLflow Model Registry auf einem Raspberry Pi für die Embedding-Funktionen, Qdrant-Sammlungen pro Domain, Ollama für die lokale Klassifizierung sowie gezielte Aufrufe an Cloud-LLMs in den Bereichen, in denen dies erforderlich ist. Die Netzwerkprobleme bei der Verbindung des Raspberry Pi mit Postgres gehören ebenfalls dazu, denn Model-Registrierungen sind nur dann nützlich, wenn der Backend-Speicher erreichbar ist.

Verbindung zu Postgres vom Raspberry Pi aus

Falls Postgres über Homebrew auf einem Mac im selben LAN installiert wurde, bestätigen Sie vor der Bearbeitung, welche Konfiguration die laufende Instanz verwendet:

psql -U <your_user> -d postgres -c "SHOW config_file;"

Die Abhör-Adressen sowie die damit verbundenen Einstellungen befinden sich in postgresql.conf:

cd /opt/homebrew/var/postgresql@15
sed -i '' "s/#listen_addresses = 'localhost'/listen_addresses = '*'/" postgresql.conf

Überprüfen Sie die tatsächlich angewendete Konfiguration:

grep -v "^#" postgresql.conf | grep listen_addresses
# listen_addresses = '*'

Fügen Sie die IP des Pi in pg_hba.conf zur Whitelist hinzu, damit eine Authentifizierung per Passwort von diesem Host erlaubt wird:

echo "host  all  all  192.168.1.9/32  md5" >> pg_hba.conf

Stellen Sie sicher, dass die Regeln wie erwartet geladen werden:

grep "192.168.1.9" pg_hba.conf

Starten Sie Postgres erneut und überprüfen Sie, ob es auf den gewünschten Schnittstellen abhört:

brew services restart postgresql@15
lsof -i -P | grep LISTEN | grep postgres

Bestätigen Sie, dass die Rolle mit Anmeldeberechtigungen existiert:

psql -U <admin_user> -d postgres -c "\du"

Setzen oder zurücksetzen Sie das Passwort, das MLflow verwenden wird:

psql -U <admin_user> -d postgres -c "ALTER USER root WITH PASSWORD 'root';"

Stellen Sie sicher, dass die Ziel-Datenbank existiert:

psql -U <admin_user> -d postgres -c "\l" | grep mlflow
psql -U <admin_user> -d postgres -c "CREATE DATABASE mlflow OWNER root;"

Prüfen Sie die Rohverbindbarkeit vom Pi, bevor MLflow eingesetzt wird:

nc -zv 192.168.1.8 5432

Sobald der Netzwerkpfad und die Anmeldeinformationen funktionieren, startet man MLflow gegen diesen entfernten Backend-Speicher:

mlflow server \
  --backend-store-uri postgresql://root:root@192.168.1.8:5432/mlflow \
  --host 0.0.0.0 \
  --port 5000 \
  --allowed-hosts "192.168.1.9:5000" \
  --cors-allowed-origins "http://192.168.1.9:5000"

Architektur in zwei Phasen

Phase 1 – Wissensschicht. Domain-spezifische PDFs werden in Blöcke aufgeteilt und mit domain-spezifischen Sentence-Transformer-Modellen verarbeitet, anschließend in separaten Qdrant-Kollektionen gespeichert. MLflow überwacht, welche Embedder-Version für jede Domain als beste gilt, damit die Dienste keine lokalen Pfade fest codieren müssen.

Phase 2 – intelligente Routierung. Ein Klassifikator kennzeichnet jede Benutzerfrage (für diese Demo: Leukämie, Hypothek oder andere). Die Abfrage nutzt die entsprechende Kollektion sowie den Embedder. Die Generierung erfolgt mit dem für diese Absicht ausgewählten LLM – lokal für einige Pfade, entfernt für andere – sodass Kosten und Leistungsfähigkeit der Frage angepasst werden können.

Implementierungsmodule

model_registry.py registriert Arctic-embed für Hypotheken und MiniLM für Leukämie (oder Ihr gewähltes Paar), protokolliert sie in MLflow auf dem Pi und erstellt Alias-Einträge für die jeweiligen Champion-Modelle:

import mlflow
import mlflow.sentence_transformers
from mlflow import MlflowClient
from mlflow.models import infer_signature
from sentence_transformers import SentenceTransformer

mlflow.set_tracking_uri("http://192.168.1.9:5000")
mlflow.set_experiment("embedding-models")

EMBEDDERS = {
    "mortgage-embedder": {"source": "Snowflake/snowflake-arctic-embed-m-v1.5"},
    "leukemia-embedder": {"source": "all-MiniLM-L6-v2"},
}

sample_texts = ["MLflow tracks embedding models", "Qdrant stores vectors"]
client = MlflowClient()

for name, cfg in EMBEDDERS.items():
    model = SentenceTransformer(
        cfg["source"],
        trust_remote_code=cfg.get("trust_remote_code", False),
        config_kwargs=cfg.get("config_kwargs"),
        device=cfg.get("device"),
    )
    with mlflow.start_run(run_name=name):
        info = mlflow.sentence_transformers.log_model(
            model=model,
            name="embedder",
            signature=infer_signature(sample_texts, model.encode(sample_texts)),
            input_example=sample_texts,
            registered_model_name=name,
        )
    client.set_registered_model_alias(name, "champion", info.registered_model_version)
    print(f"{name}: v{info.registered_model_version}, dim={model.get_embedding_dimension()}")

ingest_data.py erstellt erneut die Domänenkollektionen, teilt PDFs mit einem konsistenten Token-Fenster und Überschneidung auf, embeddet sie mit dem Champion-Modell für diese Domäne und fügt die Ergebnisse in Qdrant ein:

import os
from chonkie import Pipeline
from qdrant_client import QdrantClient
from dotenv import load_dotenv, find_dotenv

load_dotenv(find_dotenv())

client = QdrantClient(url="http://localhost:6333", api_key=os.environ["QDRANT_API_KEY"])
client.delete_collection("leukemia_details") # this will delete and recreate the collection.

(Pipeline()
 .fetch_from("file", dir="../", ext=[".pdf"])
 .process_with("liteparse")
 .chunk_with("recursive", chunk_size=512)
 .refine_with("overlap", context_size=100)
 .store_in("qdrant", collection_name="leukemia_details", client=client,
           embedding_model="sentence-transformers/all-MiniLM-L6-v2")
 .run())

count = client.count("leukemia_details", exact=True).count
print(f"Ingested {count} chunks into leukemia_details")

ai_gateway.py klassifiziert die Absicht mithilfe eines strengen lokalen Prompts über Ollama und wählt anschließend die entsprechenden LLM-Backend-Modelle je nach Label aus:

from openai import OpenAI
import mlflow

mlflow.set_tracking_uri("http://192.168.1.9:5000")

client = OpenAI(
    base_url="http://192.168.1.9:5000/gateway/mlflow/v1",
    api_key="no-api-key",
)

CLASSIFIER_PROMPT = (
    "Classify the user query into exactly one label: LEUKEMIA, MORTGAGE, or OTHER.\n"
    "LEUKEMIA = questions about leukemia (AML, CML, ALL, CLL), its symptoms, diagnosis, "
    "treatment, prognosis, or related blood cancers.\n"
    "MORTGAGE = questions about home loans, mortgage rates, refinancing, EMI, "
    "eligibility, lenders, or mortgage documents.\n"
    "OTHER = everything else, including general medical questions not about leukemia.\n"
    "Reply with only the label."
)

ROUTES = {
    "LEUKEMIA": "openai",
    "MORTGAGE": "gemma",
}

REJECT_MESSAGE = (
    "Sorry, this setup can only answer Leukemia-specific medical questions "
    "and mortgage-related questions."
)


def classify(query: str) -> str:
    resp = client.chat.completions.create(
        model="ollama",  # local Ollama endpoint does the classification
        messages=[
            {"role": "system", "content": CLASSIFIER_PROMPT},
            {"role": "user", "content": query},
        ],
        temperature=0,
    )
    label = resp.choices[0].message.content.strip().upper()
    for intent in ROUTES:
        if intent in label:
            return intent
    return "OTHER"


def route(query: str) -> str:
    intent = classify(query)
    target = ROUTES.get(intent)
    if target is None:
        print(f"[intent={intent} -> rejected]")
        return REJECT_MESSAGE
    resp = client.chat.completions.create(
        model=target,
        messages=[{"role": "user", "content": query}],
    )
    print(f"[intent={intent} -> model={target}]")
    return resp.choices[0].message.content

#
# if __name__ == "__main__":
#     print(route("What are the first-line treatments for acute myeloid leukemia?"))
#     print(route("How does refinancing affect my monthly mortgage EMI?"))
#     print(route("What are the side effects of metformin?"))   # medical but not leukemia -> rejected
#     print(route("Write a haiku about monsoon in Hyderabad."))  # rejected

smart_rag.py verbindet Klassifizierung, Auswahl der Datensammlungen, Top-k-Auswahl sowie fundierte Antwortgenerierung miteinander:

from qdrant_client import QdrantClient
import os

from ai_gateway import client, classify, ROUTES, REJECT_MESSAGE
from embedding_model_inference import EMBEDDERS
from dotenv import load_dotenv, find_dotenv

load_dotenv(find_dotenv())

COLLECTIONS = {
    "LEUKEMIA": {"collection": "leukemia_details", "embedder": "leukemia-embedder"},
    "MORTGAGE": {"collection": "mortgage", "embedder": "mortgage-embedder"},
}
TEXT_FIELD = "text"
EXIT_WORDS = {"bye", "exit", "quit"}


class SmartRAG:
    def __init__(self, qdrant_url="http://localhost:6333", top_k=5):
        self.qdrant = QdrantClient(url=qdrant_url, api_key=os.environ.get("QDRANT_API_KEY"))
        self.top_k = top_k

    def retrieve(self, query, intent):
        cfg = COLLECTIONS[intent]
        embedder = EMBEDDERS[cfg["embedder"]]
        prompt = "query" if "query" in embedder.prompts else None  # arctic needs its query prefix
        vec = embedder.encode(query, prompt_name=prompt, normalize_embeddings=True).tolist()
        hits = self.qdrant.query_points(cfg["collection"], query=vec, limit=self.top_k, with_payload=True).points
        return "\n\n".join(str(h.payload.get(TEXT_FIELD, h.payload)) for h in hits)

    def answer(self, query):
        intent = classify(query)
        if intent not in ROUTES:
            return REJECT_MESSAGE
        context = self.retrieve(query, intent)
        resp = client.chat.completions.create(
            model=ROUTES[intent],
            messages=[
                {"role": "system", "content": f"Answer using only this context:\n{context}"},
                {"role": "user", "content": query},
            ],
        )
        print(f"[intent={intent} -> {COLLECTIONS[intent]['collection']} -> {ROUTES[intent]}]")
        return resp.choices[0].message.content

    def run(self):
        while True:
            query = input("\nyou> ").strip()
            if query.lower() in EXIT_WORDS:
                break
            if query:
                print("\nassistant>", self.answer(query))


if __name__ == "__main__":
    SmartRAG().run()

embedding_model_inference.py lädt Embedder aus MLflow über Alias-Einträge (models:/...@champion) herunter, sodass die Online-Pfade niemals von den Pfaden auf dem Entwickler-Laptop abhängen:

import mlflow
import mlflow.sentence_transformers

mlflow.set_tracking_uri("http://192.168.1.9:5000")

EMBEDDERS = {
    name: mlflow.sentence_transformers.load_model(f"models:/{name}@champion")
    for name in ("leukemia-embedder", "mortgage-embedder")
}

QUERIES = {
    "leukemia-embedder": "What are the first-line treatments for acute myeloid leukemia?",
    "mortgage-embedder": "How does refinancing affect my monthly mortgage EMI?",
}

for name, embedder in EMBEDDERS.items():
    vecs = embedder.encode([QUERIES[name]], normalize_embeddings=True)
    print(f"{name}: shape={vecs.shape}, prompts={list(embedder.prompts) or None}")

Ergebnisse

Bei Fragen zu Hypotheken sollte die Antwort aus der Hypothekensammlung mithilfe des Embedders sowie gemäß der Richtlinie für LLMs zu Hypotheken abgerufen werden. Bei Fragen zur Leukämie sollte der klinische Ablauf befolgt werden. Fragen aus anderen Bereichen sollten entweder ignoriert oder ohne vorzugaukeln, dass eine Abfrage aus dem entsprechenden Bereich erfolgreich war, beantwortet werden.

/Users/pavanmantha/.local/bin/uv run /Users/pavanmantha/Pavans/PracticeExamples/DataScience_Practice/mlflow-tutorials/mlflow_on_edge/.venv/bin/python /Users/pavanmantha/Pavans/PracticeExamples/DataScience_Practice/mlflow-tutorials/mlflow_on_edge/src/smart_rag.py
Downloading artifacts: 100%|██████████| 16/16 [00:19<00:00,  1.19s/it]
2026/09/06 12:48:35 INFO mlflow.sentence_transformers: 'models:/leukemia-embedder@champion' resolved as 'mlflow-artifacts:/3/models/m-f568ee233dd748f997ba66763e41653b/artifacts'
Downloading artifacts: 100%|██████████| 1/1 [00:00<00:00, 76.69it/s]
Loading weights: 100%|██████████| 103/103 [00:00<00:00, 15587.15it/s]
Downloading artifacts: 100%|██████████| 16/16 [01:29<00:00,  5.60s/it]
2026/09/06 12:50:06 INFO mlflow.sentence_transformers: 'models:/mortgage-embedder@champion' resolved as 'mlflow-artifacts:/3/models/m-c4221c844dfb45bfa15c6a4ecde56920/artifacts'
Downloading artifacts: 100%|██████████| 1/1 [00:00<00:00, 27.17it/s]
Loading weights: 100%|██████████| 197/197 [00:00<00:00, 8855.57it/s]
[transformers] BertModel LOAD REPORT from: /var/folders/1x/36nz44_569501n4xs0px2_8m0000gn/T/tmpef4y6tj5/model.sentence_transformer
Key                 | Status  |
--------------------+---------+-
pooler.dense.weight | MISSING |
pooler.dense.bias   | MISSING |

Notes:
- MISSING: those params were newly initialized because missing from the checkpoint. Consider training on your downstream task.
leukemia-embedder: shape=(1, 384), prompts=['query', 'document']
mortgage-embedder: shape=(1, 768), prompts=['query', 'document']
/Users/pavanmantha/Pavans/PracticeExamples/DataScience_Practice/mlflow-tutorials/mlflow_on_edge/src/smart_rag.py:20: UserWarning: Api key is used with an insecure connection.
  self.qdrant = QdrantClient(url=qdrant_url, api_key=os.environ.get("QDRANT_API_KEY"))

you> What are the phases of treatment for acute lymphoblastic leukemia?
[intent=LEUKEMIA -> leukemia_details -> openai]

assistant> The phases of treatment for acute lymphoblastic leukemia (ALL) are:

1. Induction - achieving remission.
2. Consolidation - eradicating residual disease with different agents to circumvent resistance.
3. Maintenance (in ALL) - prolonged low-dose therapy to suppress re-emergence of the clone.

you> What was 30-day Average SOFR referred to in Series issued before July 2023?
[intent=MORTGAGE -> mortgage -> gemma]

assistant> *   Question: "What was 30-day Average SOFR referred to in Series issued before July 2023?"
    *   Constraint: Use *only* the provided context.

    *   Chunk 1: Discusses "Excess inclusion income", Residual Holders, taxable income, Trust REMIC taxable income, etc. No mention of SOFR or July 2023.
    *   Chunk 2: Discusses "Backup withholding", Non-U.S. Persons, Ginnie Mae Guaranty, State/Local/Foreign tax. No mention of SOFR or July 2023.
    *   Chunk 3: Discusses "Residual Holder's share of expenses", REITs, RICs, phantom income. No mention of SOFR or July 2023.
    *   Chunk 4: Discusses "Principal Distribution Amount", Ginnie Mae Project Loan Certificates, Underlying Certificates. No mention of SOFR or July 2023.
    *   Chunk 5: Discusses "OID on a Teaser Security", "Initial Distribution Period", "Excess Interest Payment", "Accrual of Original Issue Discount". No mention of SOFR or July 2023.

    *   I have scanned all five provided text nodes.

you>

Warum diese Struktur interessant ist

Durch Register können Embedder ausgetauscht werden, ohne jeden Client neu bereitstellen zu müssen. Domänenspezifische Sammlungen verhindern eine Kontamination durch Daten aus anderen Domänen. Die Intent-Routeierung sorgt dafür, dass teure Modelle nicht für einfache Anfragen genutzt werden. Für dieses Muster ist es zwar nicht notwendig, MLflow auf einem Pi zu betreiben, doch es zeigt, dass Register auf kontrolliertem Hardware-Equipment in der Nähe des Labornetzes betrieben werden können.

Operative Vorsichtsmaßnahmen

Sichern Sie Postgres, bevor Sie es im LAN freigeben. Behandeln Sie Änderungen an pg_hba als Änderungen in der Produktumgebung. Festlegen Sie konkrete Versionen für MLflow und die Treiber. Überwachen Sie die Fehlerraten der Klassifikatoren: Eine falsche Intent sendet die Anfrage an die falsche Sammlung und kann wie ein „schlechtes LLM“ erscheinen. Bewerten Sie die Datenerfassung und das Routing getrennt voneinander. Wenn sich die „Champions“ im Registry ändern, führen Sie vor dem Einführen des Live-Traffics einen Smoke-Test oder einen Vergleich mit einem Shadow-Embed durch.

Fazit

RAG jenseits eines einzigen Datenerfassungswegs ist größtenteils Produktarchitektur: Man muss das jeweilige Domänenwissen kennen, mit der richtigen Methode Daten abrufen und unter Berücksichtigung des passenden Ressourcenbudgets Ergebnisse erzeugen. MLflow, Qdrant sowie ein kleines Gateway machen diese Architektur konkret genug, um am Schreibtisch getestet zu werden – und diszipliniert genug, um über eine Demo hinauszuwachsen.

Verstärkung des auf dem Registry basierenden Weges

Champion-Alias sollten durch die Staging-Phase gehen. Protokollieren Sie die Modellversion-ID, die jede Antwort liefert, damit Sie Incidents nach einer Änderung im Registry nachvollziehen können. Falls der Pi offline geht, benötigen die Clients einen Fail-Closed-Modus anstelle eines stillen Zurückgreifens auf ein zufälliges lokales Checkpoint.

Die Chunking-Parameter sollten zusammen mit dem Embedder in den Registry-Metadaten aufgeführt werden. Ein neuer Champion mit einer anderen bevorzugten Kontextlänge sollte ohne einen Rebuild-Flag keine alten Chunks wiederverwenden.

Klassifizierungsanfragen benötigen festgelegte Beispiele: zehn Formulierungen für Hypotheken, zehn für klinische Anwendungen sowie zehn feindliche „andere“ Formulierungen. Messen Sie Präzision und Recall, bevor Sie die Wahl des LLM anpassen. Andernfalls konzentrieren Sie sich auf die Qualität des Generators, obwohl das eigentliche Problem in der Routing-Logik liegt.

Für Raspberry Pi-Implementierungen sollte man den Festplattenschaden durch häufige Schreibvorgänge von Artefakten im Auge behalten und für die Speicherung der MLflow-Artefakte externe Festplatten bevorzugen. Halten Sie die Postgres-Backups auf einem anderen Gerät als dem Pi.

Wenn Sie das Design den Stakeholdern erklären, skizzieren Sie die Abfolge: Klassifizierung → Auswahl des Embedders/Sammlungsmoduls → Abruf → Auswahl des LLM → Antwort mit Quellenangaben. Dieses Bild vermittelt bessere Vorstellungen als eine Liste von Tools und macht klar, wo die Richtlinienentscheidungen getroffen werden.

Erweitern Sie Domänen sorgfältig. Jeder neue Label benötigt eine Sammlung, einen Verantwortlichen für das Embedding-Modul, einen Importvorgang, Beispiele für den Klassifikator sowie eine LLM-Richtlinie. Der Gateway sollte unbekannte Labels ablehnen, anstatt automatisch das größte Modell zu verwenden.

Zum Schluss sollte der „ANDERE“-Pfad ehrlich gehandhabt werden. Es ist besser, abzulehnen, anstatt von einer zufälligen Domain zu ziehen, um unangenehmes Schweigen zu vermeiden. Nutzer vertrauen Systemen, die wissen, wann sie außerhalb ihres Anwendungsbereichs sind. Die Genauigkeit der Route sowie die Qualität der Abrufung müssen als separate Freigabekriterien gemessen werden, bevor die Anweisungen für den Generator weiter angepasst werden. Die Genauigkeit der Route sowie die Qualität der Abrufung müssen als separate Freigabekriterien gemessen werden, bevor die Anweisungen für den Generator weiter angepasst werden. Die Genauigkeit der Route sowie die Qualität der Abrufung müssen als separate Freigabekriterien gemessen werden, bevor die Anweisungen für den Generator weiter angepasst werden. Die Genauigkeit der Route sowie die Qualität der Abrufung müssen als separate Freigabekriterien gemessen werden, bevor die Anweisungen für den Generator weiter angepasst werden. Die Genauigkeit der Route sowie die Qualität der Abrufung müssen als separate Freigabekriterien gemessen werden, bevor die Anweisungen für den Generator weiter angepasst werden. Die Genauigkeit der Route sowie die Qualität der Abrufung müssen als separate Freigabekriterien gemessen werden, bevor der Generator-

Die Anfragen werden weiter optimiert. Die Genauigkeit der Route sowie die Qualität der Abrufung müssen als separate Freigabekriterien gemessen werden, bevor die Anfragen an den Generator weiter optimiert werden. Die Genauigkeit der Route sowie die Qualität der Abrufung müssen als separate Freigabekriterien gemessen werden, bevor die Anfragen an den Generator weiter optimiert werden. Die Genauigkeit der Route sowie die Qualität der Abrufung müssen als separate Freigabekriterien gemessen werden, bevor die Anfragen an den Generator weiter optimiert werden. Die Genauigkeit der Route sowie die Qualität der Abrufung müssen als separate Freigabekriterien gemessen werden, bevor die Anfragen an den Generator weiter optimiert werden. Die Genauigkeit der Route sowie die Qualität der Abrufung müssen als separate Freigabekriterien gemessen werden, bevor die Anfragen an den Generator weiter optimiert werden. Die Genauigkeit der Route sowie die Qualität der Abrufung müssen als separate Freigabekriterien gemessen werden, bevor die Anfragen an den Generator weiter optimiert werden. Die Genauigkeit der Route sowie die Qualität der Abrufung müssen als separate Freigabekriterien gemessen werden, bevor die Anfragen an den Generator weiter optimiert werden. RouteDie Genauigkeit sowie die Qualität der Informationsabrufung müssen als separate Freigabekriterien gemessen werden, bevor die Anweisungen für den Generator weiter angepasst werden.Sie müssen als separate Freigabekriterien gemessen werden, bevor die Generatoranweisungen weiter angepasst werden. Die Routenpräzision und die Qualität der Informationsabrufung müssen als separate Freigabekriterien gemessen werden, bevor die Generatoranweisungen weiter angepasst werden. Die Routenpräzision und die Qualität der Informationsabrufung müssen als separate Freigabekriterien gemessen werden, bevor die Generatoranweisungen weiter angepasst werden. Die Routenpräzision und die Qualität der Informationsabrufung müssen als separate Freigabekriterien gemessen werden, bevor die Generatoranweisungen weiter angepasst werden. Die Routenpräzision und die Qualität der Informationsabrufung müssen als separate Freigabekriterien gemessen werden, bevor die Generatoranweisungen weiter angepasst werden. Die Routenpräzision und die Qualität der Informationsabrufung müssen als separate Freigabekriterien gemessen werden, bevor die Generatoranweisungen weiter angepasst werden. Die Routenpräzision und die Qualität der Informationsabrufung müssen als separate Freigabekriterien gemessen werden, bevor die Generatoranweisungen weiter angepasst werden. Die Routenpräzision und die Qualität der Informationsabrufung müssen als separate Freigabekriterien gemessen werden.Die Ase-Gates müssen vor weiterer Anpassung der Generator-Anfragen überprüft werden. Die Genauigkeit der Routen sowie die Qualität der Abrufung müssen als separate Freigabekriterien gemessen werden, bevor die Generator-Anfragen weiter angepasst werden. Die Genauigkeit der Routen sowie die Qualität der Abrufung müssen als separate Freigabekriterien gemessen werden, bevor die Generator-Anfragen weiter angepasst werden. Die Genauigkeit der Routen sowie die Qualität der Abrufung müssen als separate Freigabekriterien gemessen werden, bevor die Generator-Anfragen weiter angepasst werden. Die Genauigkeit der Routen sowie die Qualität der Abrufung müssen als separate Freigabekriterien gemessen werden, bevor die Generator-Anfragen weiter angepasst werden. Die Genauigkeit der Routen sowie die Qualität der Abrufung müssen als separate Freigabekriterien gemessen werden, bevor die Generator-Anfragen weiter angepasst werden. Die Genauigkeit der Routen sowie die Qualität der Abrufung müssen als separate Freigabekriterien gemessen werden, bevor die Generator-Anfragen weiter angepasst werden. Die Genauigkeit der Routen sowie die Qualität der Abrufung müssen als separate Freigabekriterien gemessen werden, bevor die Generator-Anfragen weiter angepasst werden.Die TS werden weiter optimiert. Die Genauigkeit der Routen sowie die Qualität der Abrufvorgänge müssen als separate Freigabekriterien gemessen werden, bevor die Generator-Anweisungen weiter angepasst werden. Die Genauigkeit der Routen sowie die Qualität der Abrufvorgänge müssen als separate Freigabekriterien gemessen werden, bevor die Generator-Anweisungen weiter angepasst werden. Die Genauigkeit der Routen sowie die Qualität der Abrufvorgänge müssen als separate Freigabekriterien gemessen werden, bevor die Generator-Anweisungen weiter angepasst werden.