Tutor.AI Technologie
Bei Tutor.AI werden aktuelle Entwicklungen von LLM nach derzeitigem Standard gemeinsam genutzt. Diese Dokumentation soll daher einerseits dazu beitragen, Tutor.AI zu verstehen und damit auch für die Nutzer*innen transparent machen, wie gute als auch schlechte Antworten generiert werden, als auch wie Tutor.AI und auch andere Chatbots wie ChatGPT als Black-Box funktionieren.
Der Tutor basiert auf drei Kern-Komponenten:
- Chat-Interface
- Embeddings
- Sprachmodell
Im folgenden werden diese Komponenten und deren Zusammenspiel erklärt.
Inhaltsverzeichnis
Chat Interface
Das Chat-Interface ist das, was die Nutzer*innen sehen und mit dem sie interagieren können. Es bildet die Oberfläche für die Kommunikation mit Tutor.AI und ermöglicht einen nahtlosen Dialog. Für Chatbots wie auch für ChatGPT werden die Texteingaben der Nutzer*innen gespeichert, um ein zusammenhängendes Gespräch zu ermöglichen. Jede Anfrage an ein großes Sprachmodell (Large Language Model, kurz LLM) wird individuell bearbeitet, ohne dass das Modell die Historie des Gesprächs kennt. Stattdessen wird der Kontext der Unterhaltung dem LLM als zusätzliche Information übergeben, jedoch bleibt dieser für die Nutzer*innen unsichtbar.
Eine solche Anfrage nennt man Prompt, wobei hier zwischen
- User-Promt (also die Eingabe der Nutzer*innen),
- System-Prompt,
- und dem Kontext und der Historie
zu differenzieren ist.
User-Prompt
Der User-Prompt bezieht sich auf die direkte Eingabe oder Fragestellung der Nutzer*innen. Beim sogenannten Prompting ist es entscheidend, dem LLM klare Anweisungen oder präzise Fragen zu stellen. Halluzinationen, also falsche oder irrelevante Antworten, können auftreten, wenn das Sprachmodell nicht über ausreichende Informationen verfügt oder die Anfrage zu allgemein formuliert ist.
System-Prompt
Der System-Prompt ist eine oft intransparente Ebene zwischen der Nutzeranfrage und dem Sprachmodell. Er enthält Anweisungen für das Sprachmodell, wie zum Beispiel freundliche und hilfreiche Antworten zu generieren und Sicherheitsrisiken zu vermeiden. Die genauen System-Prompts sind oft nicht offengelegt, können jedoch durch intelligente Anfragen extrahiert werden, siehe z.B. die extrahierte System-Prompt von ChatGPT4 . Diese können auch weitere Anweisungen enthalten, wie das Einhalten von Urheberrechten und das Vermeiden potenziell gefährlicher Inhalte.
Beim Design einer System-Prompt für Tutor.AI sind mehrere Aspekte zu berücksichtigen, darunter die Nutzung von Quellen im Kontext, das Wissen über das Gesprächsthema und die Ehrlichkeit bei fehlenden Informationen.
Kontext
Der Kontext liefert dem Sprachmodell zusätzliche Informationen, die für die Generierung von Antworten relevant sind. Dies kann die bisherige Chat-Historie umfassen, um das Gespräch fortzusetzen, sowie andere Quellen und Informationen. Im Fall von Tutor.AI werden Quellen zur Lehrveranstaltung bereitgestellt, jedoch aufgrund der begrenzten Kapazität des Sprachmodells nicht alle direkt im Kontext. Stattdessen werden von der Anfrage der Nutzer*innen zunächst Abschnitte in den Quellen gesucht, die zur Anfrage passen und dann die besten Treffer bereitgestellt.
Embeddings
Embeddings sind eine Methode, um Wörter oder Sätze in einem numerischen Vektorraum zu repräsentieren. Diese Darstellung ermöglicht es, semantische Ähnlichkeiten zwischen Wörtern oder Sätzen zu erfassen. Diese Informationen sind entscheidend für die Generierung von Antworten durch Tutor.AI und für die Bestimmung der Relevanz einer Antwort auf eine Nutzeranfrage.
Bei der Einbettung der Wörter handelt es sich also um eine abstrakte Darstellung der sogenannten Tokens. Tokens können prinzipiell Wörter sein, jedoch auch einzelne Wortstämme. Bei der Einbettung werden Tokens in Vektoren übersetzt, wobei auf ein Vokabular zurückgegriffen wird.
Textextraktion
Um die Embeddings zu generieren, müssen zunächst die zumeist als PDF Dokumente vorliegenden Quellen extrahiert und in Textdateien umgewandelt werden. Während traditionelle Verfahren oft aufwendige Textbereinigung erfordern, können moderne LLM-Embeddings auch mit schlecht gereinigtem Text umgehen, da sie mit einer Vielzahl von Textdaten trainiert wurden.
Tokenizer
Der Tokenizer wandelt Texte in einzelne Tokens um, z.B. Wörter oder Wortstämme. Er überführt die Tokens in Zahlen anhand eines Vokabulars und markiert unbekannte Wörter sowie den Anfang und das Ende einer Sequenz. Darüber hinaus werden während des Trainings sogenannte MASK-Tokens verwendet, um das Modell zu trainieren, fehlende Wörter vorherzusagen. Da ein LLM nur eine bestimmte Anzahl von Tokens verarbeiten kann, werden Sequenzen durch Padding aufgefüllt, um die gewünschte Länge zu erreichen.
Embeddings
Embeddings kodieren Tokens in numerische Vektoren, die den Text repräsentieren. Diese Vektoren haben eine feste Länge und werden aus den Textdaten von den Embedding-Layern des LLMs berechnet. Zusätzlich zu den Token-Embeddings werden auch Positional Embeddings genutzt, um die Position jedes Tokens im Text einzubetten. Embeddings ermöglichen es, kategoriale Daten in eine kontinuierliche Repräsentation zu überführen und dabei Ähnlichkeiten und Beziehungen zwischen den Tokens zu berücksichtigen.
Um ganze Abschnitte einzubetten werden die Embeddings der Tokens des Abschnitts dann gemittelt. Hierbei gehen natürlich Informationen verloren, jedoch können so ganze Abschnitte eingebettet werden. Zur Einbettung von Abschnitten wurde für Tutor.AI das Paket Sentence Transformers genutzt.
Das folgende Schaubild zeigt wie die Embeddings erzeugt werden.
Ähnlichkeit / Similarity
Die abstrakte Darstellung durch Embeddings ermöglicht es, ähnliche Beiträge in der Datenbank zu finden. Die Ähnlichkeit zwischen zwei Vektoren wird oft mit Metriken wie der Cosinus-Ähnlichkeit (also dem Winkel zwischen den Punkten im (d)-dimensionalen Vektorraum der Embeddings) berechnet. Die ähnlichsten Treffer werden dann mit den entsprechenden Abschnitten aus der Datenbank zurückgegeben und dem LLM im Kontext für die Antwortgenerierung zur Verfügung gestellt.
Sprachmodell
Das Sprachmodell (eng. Large Language Model, kurz LLM) kann mithilfe der im Kontext bereitgestellten Informationen Antworten generieren. Da Sprachmodelle jedoch einen erhöhten Ressourcenbedarf haben, wird auf eine Schnittstelle zurückgegriffen. Tutor.AI nutzt dafür Mistral , welches in Frankreich nach europäischem Datenschutz gehostet wird und prinzipiell auch als Open-Source-Modell zur Verfügung steht. Die Universität Münster arbeitet derzeit daran, ein Sprachmodell, beispielsweise Mistral, auf eigenen Ressourcen zu hosten, sodass Tutor.AI langfristig unabhängig von externen Anbietern bereitgestellt werden kann.
Das Sprachmodell formuliert die Antwort auf Basis der bereitgestellten Informationen im Kontext und gibt diese dann den Nutzer*innen im Chat zurück.
Deployment
Tutor.AI befindet sich bis auf das Sprachmodell komplett in der Cloud der Universität Münster . Die folgenden Komponenten werden als einzelne Container im Kubernetes-Cluster der Universität gehostet und können intern miteinander kommunizieren:
- Chat-Interface
- Embedding
- Embedding-Datenbank
Als Embedding-Datenbank wird QDrant genutzt, während für das Embedding fastembed ebenfalls von QDrant verwendet wird, das speziell für den Betrieb auf kleiner Hardware optimiert ist. Die Embeddings aus den Quellen und Dokumenten wurden zuvor mit Sentence Transformers auf der Hardware der Universität erzeugt, wobei beispielsweise im JupyterHub der Universität Grafikkarten zur Verfügung stehen, um die Berechnung der Embeddings zu beschleunigen.
Das Chat-Interface (1.) leitet die Anfragen der Nutzer*innen an das Embedding (2.) weiter, das diese dann an das Interface zurückgibt. Das Interface gleicht die Anfragen mit der Embedding-Datenbank (3.) ab und sendet die Antworten im Kontext an Mistral.
Das folgende Schaubild zeigt wie eine Anfrage von Tutor.AI verarbeitet wird.
Da das Embedding manchmal auf normaler Hardware ohne Grafikkartenunterstützung zu langsam ist, ist es als Ausweichlösung über die Schnittstelle zu Mistral integriert.
Die Container werden unterschiedlich stark belastet, wobei die Datenbank und das Embedding mehr Ressourcen benötigen als das Chat-Interface. Kubernetes sorgt dafür, dass mehrere Instanzen der Container (sogenannte Pods) gleichzeitig laufen können und die Anfragen unabhängig voneinander verarbeiten können. Im Falle eines Ausfalls eines Pods wird dieser automatisch neu gestartet und die restlichen übernehmen solange die Anfragen.