Teilen

26. March 2024

Optimierung eines RAG-Chat-Bot-Systems

Aktuell spüren wir ein grosses Interesse an sogenannten «RAG-Systemen». «RAG» steht für «Retrieval Augmented Generation». Ein solches System ruft Informationen aus einer - meist nicht öffentlichen - Wissensquelle ab, um mit diesen Informationen als Kontext die Anfragen an ein bestehendes, bereits trainiertes Sprachmodell wie z.B. ChatGPT zu verbessern und so präzisere Antworten zu erhalten, die auf den abgerufenen Daten basieren. Im Rahmen eines aktuellen Kundenprojektes haben wir ein solches System entwickelt und berichten hier von unseren Erfahrungen.

Ausgangslage

Unsere Aufgabe war es, in kürzester Zeit einen «Proof-of-Concept» für einen deutschsprachigen Chat-Bot umzusetzen, der – basierend auf einer vorhandenen «Knowledge-Base» - Fragen interner User beantworten kann.

Die Knowledge-Base bestand zum einen aus öffentlich verfügbaren und sehr gut strukturierten schweizerischen Gesetzestexten auf kantonaler und Bundesebene im PDF-Format; zum anderen beinhaltete sie interne Kundendokumente (Weisungen), ebenfalls im PDF-Format. Diese waren weniger gut strukturiert als die Gesetzestexte und beinhalteten mehr Grafiken. Hinzu kamen im weiteren noch interne Glossare in tabellarischer Form.

Im Rahmen des Projektes stellten sich uns insbesondere die folgenden Fragen:

  • Wie können wir ein Basis-RAG-System ausgehend von den gesetzten Default-Einstellungen und -Parametern mit begrenztem Mitteleinsatz optimieren?

  • An welchen «Stellschrauben» können wir überhaupt drehen und was sind deren Auswirkungen?

  • Wann ist das System "gut genug" für die Anwender?

Den Chat-Bot haben wir als «RAG-System» konzipiert.

Architektur

In einem ersten, vorgelagerten Schritt, der sog. «Ingestion», wird der Inhalt als Text aus den Dokumenten der Knowledge-Base extrahiert. Der Content wird sodann in kleinere «Schnipsel», sog. «Chunks», zerteilt. Diese Text-Chunks werden mittels eines Embedding-Modells in numerische Vektoren (Embeddings) umgewandelt und im Such-Index abgelegt.

Stellt der User dem Bot dann zur Laufzeit eine Frage, wird die Frage ebenfalls vektorisiert; das System sucht aus dem Search Index diejenigen z.B. fünf Schnipsel heraus, die dem Frage-Vektor am ähnlichsten sind.
Frage, Kontext-Schnipsel und ggf. auch die Chat-Historie werden zuletzt an ein Sprachmodell wie z.B. GPT-4 als Prompt weitergereicht, welches dann die Antwort generiert.

Parameter

Die Tabelle links zeigt die gewählten Default-Einstellungen.

Basierend auf diesem Setup haben wir dann «Stellschrauben» identifiziert, mit welchen sich das System optimieren lassen würde, ohne jedoch das Sprachmodell selbst fine-tunen zu müssen.

Letzteres war aufgrund des hohen Aufwands und der damit verbundenen Kosten in diesem Projekt nicht möglich.

Die Tabelle rechts zeigt die identifizierten Stellschrauben.

Stellschrauben

Da die Zeit sehr knapp und das Budget begrenzt waren, konnten wir nur wenige Experimente zu diesen Stellschrauben tatsächlich durchführen. Als Entscheidungskriterien berücksichtigten wir den geschätzten Umsetzungsaufwand und das geschätzte Verbesserungspotential der Stellschrauben. Unsere Wahl fiel so auf ..

  1. .. die Extraktion der PDF-Dokumente in das Markdown-Format anstatt HTML, ..

  2. .. die Berücksichtigung der Text-Struktur, ..

  3. .. die Übersetzung ins Englische, sowie ..

  4. .. die Verwendung einer semantischen Suche.

Jedes durchgeführte Experiment bestand dann aus den nötigen Anpassungen am System mit einer anschliessenden, möglichst objektiven, Evaluation der Ergebnisse.

Evaluation

Für die Evaluation der Experimente verwendeten wir den RAGAS-Score. RAGAS ist ein OpenSource Framework, welches basierend auf der Anfrage, der vom System gelieferten Antwort, sowie der tatsächlich korrekten Antwort, die Qualität der generierten Antworten bewertet. Für Details zu diesem Framework verweisen wir auf die Dokumentation des Projekts. Eine vertiefte Erläuterung würde den Rahmen dieses Blog-Beitrags sprengen.

Die Evaluation von RAG-Systemen ist jedoch ein sich derzeit sehr schnell entwickelndes und interessantes Themengebiet.

Um die Evaluation durchführen zu können, hatten wir zuvor mit Fachexperten unseres Kunden einen Fragenkatalog mit den jeweils «korrekten» bzw. gewünschten Antworten erarbeitet. 

Das RAGAS-Framework bewertet das Auffinden des Kontextes (sog. Context Retrieval) und die Generierung der Antwort (Answer Generation) mit je zwei Metriken: Für die Context Precision wird mit verschiedenen Modellen bewertet, wie gut der aufgefundene Kontext zur Frage passt (sog. Signal to Noise Ratio). Für den Context-Recall wird ermittelt, wie viele Sätze in der korrekten Antwort sich auf den gefundenen Kontext zurückführen lassen. Die Faithfulness überprüft, wieviele Aussagen in der Antwort aus dem Kontext abgeleitet werden können. Für die Answer Relevancy werden zuletzt mit einem Sprachmodell aus der Antwort weitere Fragen generiert und dann berechnet, wie ähnlich diese der ursprünglichen Frage sind.

Mit unserer Auswahl der Stellschrauben haben wir also vor allem versucht, das Context Retrieval zu verbessern.

Experimente

Markdown-Format

In der Basisversion wurden die PDF-Dokumente mit dem «FormRecognizerService» von Microsoft vor der Weiterverarbeitung in das HTML-Format extrahiert. Wir vermuteten jedoch, dass eine Extraktion in das Markdown-Format zu einer besseren Leistung des RAG-Systems führen würde.

Für das Experiment verwendeten wir den «DocumentIntelligenceClient» von Microsoft in der neusten Version, wobei wir Markdown als Output-Format wählten. Im Ergebnis erbrachte die Verwendung von Markdown allein jedoch keine messbare Verbesserung gegenüber der Basisversion.

Berücksichtigung der Text-Struktur

In der Basisversion wurden die aus den Dokumenten extrahierten Texte anhand gängiger Satzzeichen wie z.B. «.», «!», «?», «;», «:» usw. in Schnipsel mit der vorgegebenen Grösse von 1024 Tokens zerteilt. Dies hat zur Folge, dass der Text unabhängig von der Struktur des jeweiligen Dokumentes gesplitted wird: Der zusammengehörende Inhalt eines Text-Abschnitts, der aus mehreren Sätzen besteht, wird so unter Umständen auf verschiedene Schnipsel aufgeteilt, was suboptimal erscheint.

Wir wählten deshalb ein Vorgehen, bei dem der Text zunächst nach den Überschriften der Abschnitte und erst in einem zweiten Schritt bei den dann noch zu grossen Chunks nach den gängigen Satzzeichen gesplittet wird. Zu kleine Schnipsel setzten wir hierbei wieder bis zur Zielgrösse zusammen.

Dieses Experiment erwies sich als erfolgreich und erzielte einen um sechs Prozentpunkte höheren RAGAS-Score als die Basisversion.

Übersetzung nach Englisch

Im Weiteren vermuteten wir, dass das für die Antwort-Generierung verwendete GPT4-Modell mit englischsprachigen Anfragen und Dokumenten besser umgehen könnte, als mit unseren deutschsprachigen. Insofern erwogen wir eine Übersetzung der Anfragen und Dokumente ins Englische, sowie eine Rückübersetzung der Antworten ins Deutsche. Da dies aufwändige Anpassungen erfordern und die Übersetzungen auch einen Qualitätsverlust bewirken könnten, entschieden wir uns schliesslich gegen die Übersetzung.

Dafür fanden wir heraus, dass Deutsch mittlerweile von der Lucene-Suche im Azure AI Search Index unterstützt wird, wenn man die Felder entsprechend konfiguriert. Folglich wählten wir diesen Weg und kombinierten ihn mit einer Anpassung in der Suchmethodik wie im Folgenden beschrieben.

Semantische Suche

Standardmässig werden bei RAG-Systemen sowohl die Anfrage als auch die in der Datenbank gespeicherten Dokumentschnipsel in numerische Vektoren (sog. Embeddings) umgewandelt. Das RAG-System sucht dann die für die Anfrage relevanten Schnipsel, indem es diejenigen Schnipsel-Vektoren mit der geringsten «Distanz» zum Anfrage-Vektor identifiziert (vgl. die Links unten zur Vertiefung dieser Themen).

Wir haben uns gefragt, ob eine semantische Lucene-Suche in deutscher Sprache besser abschneiden würde als die Standard-Vektorsuche, da das standardisierte Embedding-Modell von OpenAI möglicherweise für unsere Dokumente und Kontext nicht optimal sein könnte.

Diese Vermutung erwies sich als zutreffend und unser Experiment erzielte einen um sechs Prozentpunkte höheren RAGAS-Score als die Basisversion.

Fazit

Unsere Experimente haben gezeigt, dass es sich lohnen kann, in Abhängigkeit von der genauen Aufgabe und dem Kontext, Anpassungen an der Default-Konfiguration der vorhandenen Basis-RAG-Systeme durchzuführen. Mit der Kombination unserer Experimente konnten wir einen Uplift im RAGAS-Score von gut zehn Prozentpunkten erzielen.

Wir bieten umfangreiche Unterstützung im Bereich Artificial Intelligence & Machine Learning.

Weitere Blogposts zum Thema