Dies ist mein Vortrag zu Retrieval-Augmented Generation auf dem Meetup der JUG.ch in Bern am 28. Januar 2025. Als Talk+ zum Nachlesen.
Ist euch auch aufgefallen, dass man seit zwei Jahren „AI” sagt, statt „KI”? Ich habe manchmal so eine verrückte Theorie: Das liegt daran, dass man früher immer „KI” zu Machine Learning und allem gesagt hat, was man dann nicht gemacht hat - weil es zu kompliziert war, weil man keine Kompetenz im Haus hatte, weil es auch nicht mächtig genug war.
Seit diesem ChatGPT-Moment sagen alle „AI”, weil Menschen immer Begriffe brauchen, um Dinge auseinanderzuhalten und für sich einzusortieren. Vielleicht ist das nur menschlich, dass jetzt alle „AI” sagen, wenn sie die „powerful” AI meinen oder die Generative, nicht wahr? Ist nur so eine Theorie, die ich habe.
An dieser Stelle möchten wir Dir gerne ein YouTube Video anzeigen. Um es zu sehen, musst Du dem Laden von Fremdinhalten von youtube.com zustimmen.
Thomas hat mich ja schon angekündigt. Zu mir gibt’s gar nicht so viel zu sagen: Ich bin bei INNOQ Deutschland, kümmere mich da um das Geschäft zu Data & AI, und Christian, der im Vorstand ist, ist bei der INNOQ Schweiz. Ich hatte auch schon mal die Ehre, zwei Jahre ein Projekt für einen Schweizer Kunden zu machen. Da war ich sehr oft in Zürich und habe die Schweiz kennen und schätzen gelernt. Deswegen erlebe ich hier heute meinen ersten Skandal nach Schweizer Maßstäben: Wir starten mit einer Verspätung von fast 8 Minuten, das sind fast deutsche Zustände. Ich bin nämlich auch sehr viel Bahn gefahren zum Zürich Flughafen hin und zurück, und da ist einmal passiert, dass der Zug zum Flughafen in Zürich Hauptbahnhof 3 Minuten Verspätung angesagt wurde - und am Bahnsteig war so ein Raunen, alle Leute waren richtig ungehalten. Das gibt’s in Deutschland nicht. Ab 60 Minuten fangen die Leute erst an verstimmt zu werden.
Ich habe einen kleinen Podcast „AI und jetzt”, den mache ich mit einer Kollegin zusammen. Der ist gar nicht so technisch. Da geht’s weniger um Softwarearchitektur und Entwicklung, sondern vor allen Dingen darum, was KI oder AI für Auswirkungen hat - nicht nur auf die Gesellschaft. Wir sprechen mit verschiedensten Leuten: Wir hatten mal einen Designer da, eine Verhaltensmathematikerin, die sehr tief in dem Thema ist, auch auf der Entwicklungsebene. Wir haben einen Tech-Journalisten der FAZ da gehabt. Wir sprechen mit ihnen darüber, wie sie das im Alltag für ihre Aufgaben einsetzen, was sie damit machen und wie sie es einschätzen. Wenn ihr Interesse habt, hört mal rein.
Warum ich heute hier bin: Schaut euch mal an, das ist ein Screenshot von ChatGPT mit dem aktuellsten Modell. Als ich die Folie gebaut habe, habe ich ein griffiges Beispiel gesucht, womit sich Softwarearchitekt:innen identifizieren können. Mein Beispiel ist: Ich bin Softwarearchitekt:in, ich komme neu in ein Unternehmen. In diesem Beispiel geht es um einen High-End Wine Online Shop, die Snobby Wine Connoisseurs GmbH, und meine Aufgabe ist es, mich in die Architektur einzuarbeiten. Wie und warum ist die Architektur für diesen E-Commerce Shop so wie sie ist? Wer waren die Entscheidungsträger:innen? Wie kam das eigentlich zustande? Ich will das verstehen, weil meine Aufgabe vielleicht eine Modernisierung ist, vielleicht ist meine Aufgabe was anderes - eine typische Architekturaufgabe.
Diese Frage habe ich bei ChatGPT reingeschmissen, obwohl ich genau wusste, was rauskommen sollte. ChatGPT kann das ja nicht wissen, es sei denn, ich hätte jetzt mit dem Firmennamen Jackpot gelandet und diese Firma wäre bekannt und hätte mal vor zwei Jahren einen Datenleak gehabt, wo diese Entscheidung in ein AI Training hätte laufen können. Was ich da gesehen habe, war ich froh, dass ich es screenshotten konnte, weil ich es nie wieder hingekriegt habe. Das war so ein Riss im Raumzeitkontinuum. Eigentlich sind diese modernsten, größten Foundation Models so gut, dass sie deutlich weniger halluzinieren als zum Beispiel kleine Modelle. Und da wurde auf brutalste Weise halluziniert.
Das wollen wir nicht, das wollen wir nie - zumindest nicht, wenn es nicht der Auftrag ist. Wenn ich sage „erfinde mal eine Geschichte, wie es zur Softwarearchitektur kam”, weil ich vielleicht synthetische Dokumentation brauche, dann ist das super, aber das habe ich nicht bestellt. Am Ende liegt’s vielleicht doch an meinem Prompt. Ich habe es noch mal über Tage reingehämmert, es hat das nie wieder gemacht.
Er hat eigentlich immer das gemacht, was danach kam: „Sorry, ich kann dir nicht helfen, habe keine Infos darüber, aber wir können gerne Softwarearchitektur in der Weinindustrie diskutieren.” Das erwarten wir, das wollen wir ja - zumindest, wenn wir ihm nicht den Job geben, frei zu drehen.
Bei den anderen Modellen, hier Claude 3.5 Sonnet, ist’s genau das gleiche: Die bieten Hilfe an, aber sagen auch, wo sie nicht helfen können. Und so wollen wir das haben. Das ist zuverlässige KI. Das wollen wir auch, wenn wir KI oder AI im Unternehmen einsetzen. Diese Modelle sind gigantisch, man redet oft von „Weltwissen” in Anführungszeichen, aber es ist auch keine Knowledge Base, wo ich Schubladen aufmache und Infos rausholen kann, genaue Daten, wann was passiert ist. Das sind gigantische neuronale Netze, und wenn meine internen Firmendaten nicht ins Training gewandert sind, auch bewusst oder unbewusst, kann ich da keine Antworten zu kriegen.
Was ist also das Problem, wenn wir jetzt Softwarearchitekt:in bei den Snobby Wine Connoisseurs sind? Wir haben hier eine Technologie, wo viele smarte Leute sagen, das werden wir nur einmal in unserer Generation erleben. Es ist eine General Purpose Technology, eine Allzwecktechnologie, auf einer Ebene zu setzen mit der Dampfmaschine, dem Internet, der Elektrizität, sagen manche. Weil ich es für alles einsetzen kann. Die Grenze verläuft zackig: Es gibt Use Cases, die stand heute nicht so gut funktionieren, aber prinzipiell funktionieren. Es gibt andere, wo es hervorragend funktioniert, und wir müssen alle in diesem Meer von Use Cases herausfinden, wie diese Grenze verläuft.
Das erklärt uns niemand. Das erklären vor allen Dingen nicht wir der Gesellschaft als Techniker:innen und IT-Menschen, die immer den Job hatten, Technik der Gesellschaft zu erklären, Digitalisierung zu erklären, anzuwenden. Wir sind jetzt auf einer Ebene mit allen anderen. Es funktioniert nicht mehr, wir können das nicht mehr erklären. Wir müssen uns jeden Use Case angucken, wir müssen uns unsere eigenen Use Cases angucken, auf einmal sind wir auch exponiert.
Jetzt wollen wir aber diese Large Language Models bzw. Foundation Models für unseren Job hier nutzen. Wir wollen das für unsere Architekturarbeit nutzen.
Wie kriege ich denn jetzt die Unternehmensdaten da rein? Wie mache ich die denn dem Modell bekannt?
Es gibt eine Lösung und die ist total einfach: Steck sie einfach ins Prompt.
Das war’s. Das muss ich machen.
Ihr habt alle schon mal ChatGPT benutzt oder vielleicht auch lokale Modelle. Ihr wisst so ein bisschen, wie die funktionieren. Das Prompt macht den Kontext auf für die Aufgabe, die ich dem Modell stelle. Deswegen können wir eigentlich sagen, es war ja einfach, sind wir hier fertig. Ich rate immer dazu, wenn wir eine Architektur bauen wollen, eine Software entwickeln sollen, ein Feature bauen sollen, was eine KI mit internem Wissen, mit verifizierten internen Informationen in Verbindung bringen soll, immer erstmal die einfachste Lösung zu nehmen. Ist generell eigentlich eine gute Idee. Weil ich unterwegs so viel lerne - vielleicht ist die einfachste Lösung nicht die beste, aber ich muss keine Elfenbeintürme mehr einreißen.
Wenn ich jetzt im Internet suche, was ich für RAG brauche, dann kriege ich erstmal natürlich Frameworks und Tools um die Ohren geschmissen. Du musst das und das installieren, die und die LangChain, und dann gibt’s dafür noch das und das Plugin, dann brauchst du noch eine Vektordatenbank, dann brauchst du eine Ingestion Pipeline deiner Daten in die Vektordatenbank. Es ist ein ganz neues Set Technologien für viele von uns, und das führt einfach dazu, dass wir uns mangels Zeit oft damit auch nicht beschäftigen.
Was ich sagen will: Wir brauchen für RAG erstmal eigentlich fast gar nichts. Wir brauchen die Kerntechnologie, das Large Language Model, und wir müssen wissen, wie es funktioniert, unser Wissen da reinzukriegen. Das ist aber der große Hammer, den wir irgendwie architektonisch umschiffen müssen. Wir müssen die Daten ins Prompt kriegen, wenn sie denn reinpassen.
Es wäre alles so einfach gewesen, wenn wir im Alltag aber nicht davor stehen würden. Zum Beispiel unser Confluence, wo unsere ganzen Architekturdokumentationen drin sind, die sollen jetzt bitte ins Modell. Copy-paste ist mühsam. Und selbst wenn ich es mache, merke ich schnell: Oh oh, es wird voll, es passt einfach nicht mehr, es ist zu viel.
Was machen wir dann? Dann stehen die meisten in ihren PoCs im Unternehmen genauso da und geben auf. Das ist eigentlich der Punkt, wo wir ansetzen mit einer Architekturlösung, die RAG sein kann.
Deswegen müssen wir zuerst mal dem Kontext Window „Hallo” sagen und das ein bisschen näher kennenlernen.
Was ist denn das Kontextfenster eigentlich? Das Kontextfenster ist im Prinzip wie - als Analogie - das menschliche Gehirn. Large Language Models funktionieren nicht exakt so, aber es ist eine gute Analogie. Es ist quasi das Kurzzeitgedächtnis: Alles, was wir dem Praktikanten auf den Tisch legen - „erledige diesen Job, hier sind unsere Infos dazu”. Das ist das Kontextfenster, und wenn der Schreibtisch voll ist, ist der Schreibtisch voll.
Die führenden Modelle - diese Folie veraltet 14-tägig, ich komme gar nicht mehr dazu, sie zu aktualisieren. Llama 3.3 gibt’s jetzt, Gemini 2.0 steht uns diese oder nächste Woche final wahrscheinlich ins Haus. Witzigerweise ändert sich viel, aber nicht die Kontextfenster. Die bleiben immer so im Groben gleich. Google hat offenbar noch einen Mode, in dem sie sehr große Kontextfenster hinkriegen können, ohne dass es da „Needle in the Haystack”-Probleme gibt. Da kann ich in 2 Millionen Tokens schon mal ein dickes Buch reinklatschen als Kontext und kann auch gezielte Fragen zu einer Info stellen, die sich in einem Satz in der Mitte befindet. Es gibt Tests, die zeigen, dass es gut funktioniert - das war auch nicht immer so. Aber egal was wir nutzen, und das sind die größten Modelle, die es gibt - Kontextfenster ist erstmal nicht an Modellgröße gekoppelt.
Wir müssen uns mit dem Context Window auseinandersetzen. Dafür müssen wir erstmal verstehen: Was sind denn jetzt Tokens? Die Tokens geben ja die Größe des Kontextfensters vor. Tokens sind im Prinzip nichts anderes als Zahlen. Diese Large Language Models bzw. Foundation Models, sagt man heute eher - kurzer Schwenk dazu, warum man eigentlich nicht mehr Large Language Models sagt, wenn man die ganz großen meint: „Frontier Models” ist so ein anderer Begriff, weil die gar nicht mehr nur mit Sprache sich aufhalten oder beschäftigen. Sprache ist eine Facette. Eigentlich sind das autoregressive Modelle, das ist der Fachterminus.
Alles, was gut in Tokens passt und in die Transformer-Architektur, die zugrunde liegt, können die verarbeiten. Sprache ist eins davon. Videostreams sind was anderes, Audiostreams passen auch gut in Tokens und den Transformer. Deswegen sehen wir ja Suno und solche Sachen, wo ich Musik mitmachen kann. Oder ich kann meinen Baustellen-Livestream in ein Modell klinken und sagen: „Schreib mir mal bitte von dem Stream alle Sicherheitsprobleme auf dieser Baustelle in eine Liste und kategorisiere die nach Schwere.” Das hat nichts mehr mit dem Language Model zu tun.
Wenn ich dann bei Kund:innen sitze und sage: „Haben Sie denn schon ein paar Use Cases sich überlegt?” und dann sagen die: „Ja, Texte zusammenfassen.” Dann denke ich immer: Ja, das ist so einer der ersten Use Cases und natürlich sind die toll darin. Aber sie haben jetzt ein Meer von Use Cases und sie nehmen ganz vorne ein Glas Wasser raus.
Kurzer Schwenk dazu, was Tokens sind und warum die Dinger nicht mehr immer LLMs heißen: Tokens sind im Prinzip Zahlen, die etwas abbilden in diesen gigantischen neuronalen Netzen. Wenn ich jetzt im Beispiel Sprache oder Text verarbeiten will mit so einem neuronalen Netz, muss ich quasi Sätze und Texte zerhacken. Wenn ich ganze Sätze oder Geschichten oder Absätze verarbeiten würde - könnt ihr euch alle vorstellen, so tun wir Menschen ja auch nicht. Das ist irgendwie sehr unhandlich, es ist unflexibel und wahnsinnig ineffizient.
Wir müssen also eine Schnittgröße finden, die ein guter Tradeoff ist zwischen ganzen Worten oder vielleicht ein bisschen darunter. Im Englischen hier in diesem Beispiel - die Fragen, die ich am Anfang gestellt habe, kann man sich mit dem GPT Tokenizer von Simon Willison auch mal angucken. Der stellt das grafisch dar, verwendet auch, glaube ich, ein Standard Embedding Modell, um diese Tokens zu erzeugen. Vieles sind ganze Worte, aber zum Beispiel „GmbH” wird total zerhackt. „Snobby” wird zerhackt. Anführungszeichen ist auch ein eigenes Token.
Ich glaube, da sieht man ganz schön, warum das so ist. Denn so ein Large Language Model muss, um bei Text zu bleiben, Sprache eigentlich abstrahieren. Und das ist auch was Tolles, was wir noch nie hatten: Wir haben jetzt eine Abstraktion von Wissen. Eine sprachunabhängige. Wie viele Jahrhunderte und Jahrtausende packen wir unser Wissen sprachgebunden auf Papyrusrollen, Wiki-Seiten, Confluences? Es ist immer in einer Sprache oder mehreren, aber ich muss es in einer Sprache manifestieren. Wir haben jetzt eine Technologie, in der das sprachunabhängig geht, weil diese Tokens eben sprachunabhängig sind.
Deswegen, nur deswegen funktionieren diese Modelle auch so toll, wenn ich sage: „Beantworte mir die Frage mal auf Chinesisch.” Oder ich frage auf Chinesisch und will Deutsch oder sage: „Erfinde mal einen Dialekt zwischen Chinesisch und Deutsch.” Die müssen also eine modulare, einfach zu handhabende und möglichst effiziente Möglichkeit haben, Dinge zu formen für uns - die Transformer und die Tokens sind eben das, was aktuell am besten dafür ist.
Noch mal zurück zu unserer Bedingung: Unser Prompt mit unserem ganzen Wissen und jede andere Message, wenn wir von einem Chat reden - wir bauen ja nicht immer Chats, vielleicht bauen wir auch AI-gestützte Features, da chatte ich vielleicht gar nicht - müssen ins Kontextfenster passen.
Wenn die das nicht tun, dann muss ich eben den Korpus zerhacken, ich muss ihn chunken.
Die sogenannten Chunks sind ein relativ wichtiger Begriff in der RAG-Architektur. Ihr wisst alle, was ein Chunk ist. Wenn ihr bei Google sucht nach „tolle Restaurants Berlin”, dann kriegt ihr zehn Ergebnisse und das sind Chunks. Das ist eine Überschrift mit ein bisschen Text, und der Text ist meistens so ein Ausriss, wo Google dann auch schon markiert, was mir wahrscheinlich in der Übersicht, wenn ich das nur scanne, möglichst wahrscheinlich Hilfestellung gibt, diesen Link anzuklicken oder einen anderen zu wählen. Chunks sind nichts anderes als Textfetzen, die möglichst relevant sein müssen - und relevant ist hier das große Zauberwort.
Wir müssen also unseren Korpus, wo unsere ganze Architekturdokumentation drin steht, zerhacken. Nehmen wir mal Confluence, ist so ein gängiges Beispiel. Confluence-Seiten, wo irgendwelche Meeting-Protokolle drin sind, ADRs vielleicht, arc42-Dokumentation, vielleicht kommt auch noch mal ein anderer Datentopf dazu, nämlich der Sourcecode oder so. Ich muss also meinen ganzen Korpus, der für mein Feature oder mein Produkt relevant ist, zerschneiden - und wie gehe ich davor?
Ich muss den Elefanten essen, muss mit irgendwas anfangen. Ich empfehle immer, damit anzufangen, mit dem Bauchgefühl. Ich muss mir die Daten angucken, da kommen wir nicht drum rum. Wir müssen unsere Daten kennen. Wir müssen uns nicht alles angucken, aber wir müssen ein Gefühl dafür entwickeln, wie sie so grob aufgebaut sind. Ich rede auch gar nicht davon, dass wir sie alle in eine gleiche Struktur bringen müssen - das muss ich bei Machine Learning machen. Aber bei Generativer KI und Large Language Models ist das ja eigentlich was Schönes, dass ich gar nicht so auf Struktur angewiesen bin.
Ich muss aber diesen Korpus zerhacken, dann muss ich mich eben entscheiden: Nehme ich jetzt Sätze, nehme ich Absätze, nehme ich Kapitel, nehme ich Seiten? Damit muss ich irgendwie anfangen, um dann über das Problem zu iterieren. Wenn ihr diese Chunks schneidet - ihr entscheidet euch vielleicht für Absätze - dann fangt erstmal an und dann müsst ihr gucken: Wie gut funktioniert es denn jetzt, wenn ich diese Chunks dem LLM gebe, wie gut sind die Antworten? Wenn es dann wieder doch nicht in den Kontext passt oder zu viel Quatsch drum rum ausgeschnitten wird oder zu wenig, dann müsst ihr eben die Chunkgröße justieren. Darüber iteriert man eigentlich die meiste Zeit, wenn man ein RAG-System baut.
Wenn ich jetzt entschieden habe, ich nehme zum Beispiel Sätze oder Absätze, dann muss ich die Chunks eben in meinen Prompt kleben.
Copy-paste. Das einfachste RAG - man hat eine RAG-Architektur in 5 Minuten aufgesetzt. Die kann auch manuell sein, die kann ich sein. Ich kann die Textfetzen in meinen Prompt kleben, dann bin ich die RAG-Architektur.
Lasst euch nicht ablenken von irgendwelchem XML-Text. Das könnt ihr strukturieren im Prompt, wie ihr wollt. Ihr könnt es so einfach mit Leerzeile dazwischen schicken. Ihr müsst dem LLM eben nur sagen: „Pass auf, hier beginnen jetzt die Chunks.” Meistens kriegen die das auch so raus, aber die Praktikanten-Analogie ist immer gut: Hier ist der Stapel Dokumente, löse diese Aufgabe und guck da rein. Wenn wir das maschinell machen, dann wird ja nicht jemand von uns sitzen und diese Chunks immer in jeder Abfrage kleben, dann könnte man eben auch XML machen. Es gibt Modelle, die freuen sich darüber - die Anthropic-Modelle besonders. Denen ist es aber im Endeffekt auch total egal.
An der Stelle kommt oft die Frage: „Moment, RAG ist jetzt wirklich nur das?” Ja, es ist genau nur das. Es ist eine Architektur oder eine Technik, die Zeug in meinen Prompt klebt. Deswegen noch mal zu Google: Das habt ihr vielleicht mitbekommen, Google macht auch RAG im sehr, sehr großen Maßstab. Das werden wir wahrscheinlich nicht machen, je nachdem, woran wir dann arbeiten. Aber das ist bisher nur in den USA ausgerollt, diese AI-Overviews.
Das ist halt manchmal problematisch. Da geht’s auch um Chunkgrößen wahrscheinlich. Wenn die ersten zehn Suchergebnisse auf diese Frage Quatsch sind in ihrer Relevanz, oder die Chunkgröße den wichtigen Part wegschneidet - kann man schon machen, ist aber ungesund - dann kann dieses AI-Feature, je nachdem wie es gepromptet ist, Blödsinn erzeugen. Aber auch da: Das ist nicht der letzte Hebel. Wenn ich im Prompt schreibe „nutz bitte auch deinen Common Sense und erzähl den Leuten keinen Quatsch”, dann sollte sowas auch nicht passieren. Niemand weiß, was die da getrieben haben, aber das sind echte Screenshots und das sind Probleme, die passieren.
Deswegen sagen wir dieser Architektur mal „Hallo” und gucken uns die ein bisschen an. RAG ist im Prinzip nichts anderes als eine Technik, um LLM-Antworten auf verifizierten externen Informationen zu grundieren - „Grounding” ist so ein beliebtes Wort, das sich durchgesetzt hat. Ich muss eben meine These, mein Statement belegen.
Die Technik ist eigentlich schon relativ alt. Sie entstand 2005 im Paper von Lewis und anderen: „Retrieval Augmented Generation for Knowledge Intensive NLP Tasks”. Da hat noch niemand von Large Language Models geredet.
Und heute wird’s tatsächlich dafür benutzt: Es holt unser Zeug, was auch immer in unserem Confluence steckt, was irgendwo steckt. Das spickt unser Prompt, und das LLM steht eigentlich erst hinten dran und generiert auf dieser Basis eine Antwort. Das ist RAG.
Wenn wir das uns mal aus einer Architektursicht - so Helikopterflug, 20.000 m hoch (fliegen Helikopter überhaupt so hoch?) - angucken, so eine High Level Bird’s Eye View, dann sieht es im Prinzip so aus: Am Anfang steht mein Prompt, das wandert in ein Retrieval System. Retrieval System ist kein neuer Begriff, das nutzen wir in der Informatik schon ewig. Suchfunktionen sind zum Beispiel Retrieval Systeme. Und hier geht’s ganz oft um Suchfunktionen bei RAG.
Der Retrieval-Schritt gibt unser gesamtes Prompt oder eben einen Teil davon an eine Suche - eine Vektorsuche oder eine Volltextsuche. Die gibt Sachen zurück, dann geht’s in die Augmentation. Die Results, die Ergebnisse des Retrieval Systems, werden ins Prompt gespickt und am Ende ist das schwarze Loch - deswegen das LLM. Da haben wir eigentlich keinerlei Kontrolle mehr, da können wir nichts mehr modifizieren. Da sind wir dem so ein bisschen ausgeliefert. Wenn unser Prompt da drin ist, dann war’s das. Das kommt auch nie wieder raus, da kommt dann eine Antwort raus.
Wenn wir ein bisschen tiefer fliegen, dann sehen wir: Im Retrieval-Schritt scheint die Komplexität dieser Architektur verborgen zu sein. Die anderen Schritte sind relativ trivial, da passiert nicht mehr viel. Deswegen müssen wir eigentlich hier mal genauer reingucken, was da passiert.
In dem Beispiel hätten wir jetzt zum Beispiel zwei Suchfunktionen. Warum zwei? Dazu komme ich später. Wir können uns ja erstmal die erste angucken. Wer hat schon mal von Vektorsuche gehört? Hört man total oft gerade, besonders im Zusammenhang mit RAG. Wenn man im Internet so guckt, wie man RAG macht, sagen 90% der Tutorials und Fachartikel: „Ja, pass auf, installiere dir mal eine Vektordatenbank, dann embedde deinen ganzen Kram und der muss dann in die Vektordatenbank.” Das ist nur die Hälfte der Wahrheit. Ich brauche gar nicht immer eine Vektordatenbank, die brauche ich für einen bestimmten Use Case.
Deswegen gucken wir uns den erstmal an. Dazu müssen wir ein bisschen ausholen. Wer weiß denn, was Vektoren und Embedding bzw. Embeddings sind? Ich muss also meine Chunks, meinen Text embedden. Warum muss ich das? Diese neuronalen Netze, so groß sie auch sind, arbeiten ja quasi mit der semantischen Ähnlichkeit von Konzepten von Dingen. Und die muss ich der Maschine eben irgendwie beibringen.
Jetzt mal als Beispiel: Die führenden AI Labs geben gar keine Daten mehr raus, wie groß die neuronalen Netze denn sind. Bei GPT-3 ist so der letzte Datenpunkt, den man noch von OpenAI bekommen hat - da waren es 12.288 Dimensionen. Auf meiner Folie ist das total vereinfacht als dreidimensionaler Raum dargestellt. Das kann man sich super vorstellen, aber ein Raum mit 13.000 Dimensionen ist ein bisschen schwer im Kopf, wenn wir uns das jetzt vorstellen wollen, um Embeddings zu verstehen.
Bleiben wir mal in diesem - fünfte Klasse, sechste Klasse - dreidimensionalen Geometriemodell. Ich könnte jetzt ja Dinge haben: Die gelbe Zitrone, den gelben Vogel, die Katze da unten und dann ganz unten den Vogel mit dem weißen Körper und dem roten Kopf. Das sind Konzepte in dem neuronalen Netz, das Weltmodell. Da ist ja noch sehr viel mehr drin und vielleicht meine Sachen. Die sind da nicht drin, aber die will ich ja irgendwie in den Kontext bringen.
Ich muss also wissen in der Vektorsuche, wie ähnlich Sachen sind oder wie wenig ähnlich sie sind. Ein sogenanntes Embedding ist im Prinzip so ein Vektor. Die gelbe Zitrone ist ein Konzept. Und dann gibt’s jetzt verschiedene Methodiken, wie ich die Ähnlichkeit zwischen Dingen mathematisch abbilde - und die Kosinus-Ähnlichkeit ist so das bekannteste, deswegen gehe ich nur darauf ein. Es gibt noch zwei, drei andere, aber das ist so das gängigste, was man eigentlich immer sieht, was für die meisten Use Cases absolut passend ist. Andere sind optimierte Varianten für ein bisschen andere Fälle.
Gucken wir uns nur mal das an: Die Kosinus-Ähnlichkeit ist im Prinzip nichts anderes als der gemessene Winkel zwischen zwei Vektoren, zwischen zwei Konzepten, zwei Bedeutungen. Wenn der Winkel kleiner ist, dann sind die ähnlicher als wenn der Winkel groß ist. Also die gelbe Zitrone ist dem gelben Vogel, den grünen Flügeln und den grünen Früchten - also so ein Konglomerat von Konzepten, sind ja nicht einzelne Sachen - relativ ähnlich. Zumindest ähnlicher als die gelbe Zitrone der Katze da unten. Deswegen ist der Winkel zwischen denen dann eben auch größer, oder zwischen der gelben Zitrone und dem Vogel ganz unten, da ist er eben relativ groß.
Man geht jetzt bei der Kosinus-Ähnlichkeit hin und misst quasi die Winkel und sagt: 180° ist quasi das komplette Gegenteil, dann zeigen die in zwei verschiedene Richtungen. Das blaue Auto und die gelbe Zitrone. Im echten Leben ist es nicht so einfach, nichts ist komplett gegensätzlich. Alles ist irgendwie so ein bisschen ähnlich. Und dafür ist das eben perfekt geeignet, weil fast nichts komplett gegensätzlich ist und fast nichts identisch, auch keine Zwillinge. Deswegen sehen wir, wenn wir unsere Chunks, unsere Textfetzen in ein Embedding, also einen Vektor überführen, fast nie irgendwelche identischen oder exakt gegensätzlichen Dinge.
Man geht jetzt für die Winkel hin und sagt dann eben: 180° wäre -1, 90° ist irgendwie neutral zueinander, 90° oder 270° ist eine 0, und identisch wäre eine 1. Was man im echten Leben sieht, sind Fließkommazahlen, die genau auf dieser Skala punktiert sind.
Wie sieht das dann aus, wenn ich unsere Textfetzen da durchjage? Noch mal zum Verständnis: Ein Embedding ist nichts anderes als ein Vektor, der Semantik beschreibt, Bedeutung.
Mir hat das geholfen, das einfach mal zu machen. Den Tipp gebe ich auch immer jedem und jeder: Wenn ihr zum Beispiel eine Postgres habt - haben die meisten von uns - selbst das, ich brauche nicht mehr, irgendeine relationale Datenbank. Ich könnte hingehen und in meiner Tabelle Blogpost oder Versicherungsverträge oder was auch immer eine Spalte einführen, die ich Embedding nenne. Da kann ich so ein Array aus Fließkommazahlen reinspeichern.
Das heißt, ich könnte eine Row aus meiner Tabelle - wenn es sich anbietet, beim Blogpost wären es dann der Titel, der Untertitel, der:die Autor:in, das Datum und der Text - wenn ich die konkateniere und durch so ein Embedding-Modell jage, fliegt sowas raus. Und das Array ist exakt so lang, wie das Embedding-Modell die Größe vorgibt. Die sind immer gleich lang, aber die Werte da drin sind immer unterschiedlich.
Das ist eigentlich ein Embedding. Und wenn ich eine Postgres habe, kann ich mir die pg_vector Extension installieren und dann kann ich das einfach mal ausprobieren. Dann könnte ich meine Blogposts oder was auch immer ich habe, Fruchtsorten in meiner Datenbank, einfach mal embedden mit so einem Embedding-Modell. Das dauert ein bisschen, das ist relativ rechenintensiv. Das macht man nicht einfach zwischendurch mal, das macht man auch nicht im Request-Response-Zyklus - das dauert jetzt nicht ewig, aber ist schon ein Langläufer.
Dann gucke ich mir das mal an, speichere ich das mal da rein und dann kann ich nämlich mit SQL - das zeige ich in diesem Vortrag nicht, aber das findet man relativ schnell - die Query gibt’s auch als Operator, wo ich eben Dinge vergleiche. Ich gebe was rein, zum Beispiel eine Query: „Such mir mal alle Blogposts, die sich mit Java-Architekturen beschäftigen, die vor 10 Jahren en vogue waren und wo es noch nicht Spring Boot gab.” Das könnte so eine wahnsinnig fuzzy Suchquery sein. Wenn ich das da reinschmeiße in meine SQL-Query und sage „guck bitte auf die Spalte Embeddings”, dann kriege ich Ergebnisse zurück. Das sind dann wahrscheinlich relativ relevante Blogposts, die zu dieser enorm aufgepusteten Query passen, und das ist genau das, was Vektordatenbanken uns ermöglichen.
Ich zeige jetzt noch mal vereinfacht, wie das funktioniert: In diesen vielen Dimensionen in diesem Vektorraum gibt’s eben eine Fließkommazahl und die repräsentiert einen Aspekt von der gesamten Bedeutung. Das heißt, unsere Blogposts oder unsere gechunkten, unsere embeddeten Chunks werden eben so abgebildet. Wir können das aber schlecht visualisieren, weil 2D und 3D ist noch machbar, danach wird’s schwierig.
Die Vektorsuche geht eben hin, nimmt diese Beispiel-Query - die wahnsinnig aufgepustete, fuzzy, wo ich mich vielleicht auch gar nicht entscheiden kann, was suche ich denn eigentlich, aber ich gebe es mal so rein, ich habe es vielleicht diktiert beim Spazierengehen. Die Vektorsuche sucht und liefert mir eben Ergebnisse zurück, in unserem RAG-Fall eben die gechunkten Confluence-Inhalte und findet Chunks. Jeder dieser Chunks oder jede Bedeutung hat eben diese Kosinus-Ähnlichkeit als Fließkommazahl. Ist jetzt hier extrem vereinfacht: Der ist weit weg, der hat jetzt eine bestimmte Entfernung zu meiner Query. Dann gibt’s andere Chunks, die gehen näher Richtung 1, näher Richtung identisch. Die sind näher dran an dem, was ich gefragt habe. Dann gibt’s andere, die sind so bei 0,8 und so weiter.
So muss man sich diesen Raum eigentlich vorstellen: In der Mitte steht meine Frage und drum rum sind meine Chunks, und die sind unterschiedlich relevant zu dieser Frage. Das Coole bei der Vektorsuche ist, dass ich eben wahnsinnig komplexe Fragen formulieren kann. Ich kann frei reden, ich kann auf Chinesisch fragen, ich könnte auch Holländisch mal dazwischen mischen oder so. Es ist ja egal, weil es ja embedded wird.
Deswegen ein paar Eigenheiten der Vektorsuche, die man kennen muss: Weil nichts irgendwie entgegengesetzt ist, gibt’s auch eigentlich keine leeren Result-Sets. Man sieht nie leere Abfragen, leere Ergebnismengen bei der Vektorsuche. Die geben immer was zurück. Und es können auch immer relativ viele Ergebnisse sein - also wenn die Suche extrem speziell ist, heißt es nicht, dass ich nur eins zurückkriege, ich kriege vielleicht doch sechs, sieben zurück. Ich muss mir halt dann die Scores angucken.
Die werden eben nach Ähnlichkeit bewertet und nicht nach exaktem Match, wie wir es von der Volltextsuche gewohnt sind. Wie schon gesagt, funktioniert es sprachübergreifend und das Coole ist: Wenn mir ein Begriff nicht einfällt und ich etwas beschreibe, so relativ menschlich - wie war das noch mal meine Query, die habt ihr noch im Kopf: „en vogue Frameworks in Java vor Spring Boot”. Das ist ja alles nicht so wahnsinnig trennscharf, am Ende fehlt mir noch ein Jahr oder so. Das geht. Ich könnte auch sagen „gib mir mal Plätze zum Essen gehen”, wenn mir das Wort „Restaurant” nicht einfällt. Da seht ihr alle, da steigt eine Volltextsuche eigentlich schon aus. Die Fuzziness ist eigentlich die große Macht der Vektorsuche.
Es hängt eben stark von der Embedding-Qualität ab, was wir da zurückkriegen. Jetzt könnte ich ja sagen, in meinem RAG-System gibt jemand diese Frage vom Anfang ein: „Wie kam es zu unserer Softwarearchitektur? Wer waren die Entscheidungsträger:innen?” Jetzt könnte ich ja sagen: Okay, die Ähnlichkeiten, die muss ich hochkriegen, dann werden meine Ergebnisse relevanter. Das ist so ein bekannter Irrglaube. Wenn ich quasi die Kosinus-Ähnlichkeit steigere, dann habe ich relevantere Ergebnisse.
Das kann ich erreichen, indem ich die Query aufpuste, indem ich sie neu schreibe. Da könnte ich zum Beispiel ein LLM vorne hinstellen und sagen: „Pass auf, hier hat gerade jemand die Frage gestellt, reichere die mal an, puste sie mal ein bisschen auf, was meint er wohl? Was könnte er noch wollen?” Dann steigen auf einmal die Wahrscheinlichkeiten. Aber in der echten Welt sind die Ergebnisse nicht relevanter. Die sind nur mathematisch ähnlicher.
Das ist eine beliebte Technik in RAG-Systemen, dass man die Query neu schreibt oder ergänzt. Ich muss aber Kontext haben, der relevant ist. Wenn ich den nicht habe, wird der erfunden und dann kommen wir wieder in die Quatschwolke. Wenn ich zum Beispiel ein Userprofil habe - Google Maps, Google Places API, die wissen sehr genau, was hat der Robert in den letzten 20 Jahren so für Restaurants gesucht. Also es würde mich wundern, wenn die das nicht wissen. Die haben ein Userprofil und zwar ein relativ umfangreiches über mich.
Wenn ich jetzt in ein neues Produkt bei Google Maps - was es aktuell nicht gibt, zumindest nicht für mich - reinhacke: „Du, ich will mal sowas hier haben” - statt „die besten Restaurants in Berlin Mitte” - könnten wir, die wir das System entwickeln, ja eben entscheiden: Okay, der Robert fragt nach den besten Restaurants in Berlin Mitte. Wir wissen aber eigentlich ganz schön viel über den. Wir wissen zum Beispiel, der geht sehr gern klassisch traditionell italienisch essen und freut sich immer über tolle Restaurant-Interieurs, vielleicht mit Century-Architektur-Style, und der ist nicht so ein Fan von stinkigem Naturwein - ist in Berlin ein relativ wichtiges Kriterium, wenn man Restaurants sucht.
Wenn ich das weiß: Do it, puste die Query auf! Die Leute sind schreibfaul. Die sind vor allen Dingen über Jahrzehnte konditioniert worden, sowas in Suchfenster einzugeben: „Best Restaurants Berlin Mitte”. „Best” - man kann kein besseres Beispiel finden als „Best”, weil „Best” total kontextabhängig ist. Für dich ist „Best” was völlig anderes als für mich. Wir sind uns, glaube ich, relativ ähnlich, haben wir im Vorgespräch festgestellt, aber in dem Case: Das muss ich eben, wenn ich die Daten habe, die Query aufpusten. Das ist ein toller Mechanismus, bessere Ergebnisse zu bekommen und sich nicht rein auf die Chunk-Relevanz zu verlassen.
Ein bekannter Irrglaube ist, dass wenn man RAG baut, muss man immer eine Vektorsuche nehmen. Das ist Quatsch. Was die Realität eigentlich zeigt und was wir auch für Kund:innen umsetzen, ist fast immer eine hybride Suche, wo eigentlich zwei Retrieval-Systeme eingesetzt werden: Eine Vektorsuche und eine Volltextsuche, weil die beide unterschiedliche Stärken und Schwächen haben. Deswegen empfehlen wir das eigentlich auch.
Man muss es aber vom Feature abhängig machen. Wenn wir jetzt bei Google Maps bleiben - die Leute werden noch ein paar Jahre „Best Italian Restaurant” da eintippen, die sind da einfach konditioniert drauf. Wenn wir aber da so einen Zauberstab daneben machen und sagen „Das ist eine coole AI-Suche, hier sind ein paar Beispiele, wie du auch suchen könntest”, dann werden die ersten User:innen anfangen, ihre Queries eben ein bisschen spezifischer zu formulieren.
Beide Use Cases kann ich mit einer Hybridsuche bedienen. Habe ich die nicht, die beiden Use Cases, ist es trotzdem manchmal cool, die beiden zu haben. Ich würde sogar sagen, in der Mehrheit der Fälle, weil die Vektorsuche mit diesen fuzzy, „vibe-basierten” Queries extrem gut ist und die Volltextsuche extrem schlecht. Die Volltextsuche ist aber extrem gut mit spezifischen Queries, zum Beispiel „ADR 25.04.2024 Softwarearchitektur” oder so. Die Vektorsuche wird mir da sechs, sieben, zehn Ergebnisse liefern und die Volltextsuche, wenn sie gut konfiguriert ist, eins - und das will ich haben. Das will ich mir nicht erst aus den Results der Vektorsuche rauspicken.
Wenn ich jetzt beide habe, und die funktionieren ja völlig anders, das sind andere Welten, muss ich die Results irgendwie vereinen.
Dann nimmt man die sogenannte Rank Fusion, einen relativ einfachen mathematischen Algorithmus. Ich sortiere eben nach der Rangposition und nicht nach ihren Scores, weil die Scores kann ich nicht vergleichen. Der Score in der Vektorsuche ist die Fließkommazahl und der Score in der Volltextsuche ist vielleicht eine Integerzahl, die aufsteigt. Die kann ich nicht so vergleichen, das ist Quatsch. Deswegen muss ich eigentlich den Rang, also die Reihenfolge, die tatsächliche, die logische nehmen und sie vereinen.
Das sieht eben so aus: Ich habe jetzt die Volltextsuche, die hat mir zwei Chunks geliefert, A und B. Die Vektorsuche vier: A und B sind auch enthalten, aber A ist nicht an erster Stelle wie in der Volltextsuche und B ist ganz unten. Dafür hat die noch C und D. Kann gutes Zeug drin sein, was die Volltextsuche vielleicht nicht gefunden hätte. Die muss ich dann eben durch Rank Fusion vereinen.
Dann nimmt man die Ordnung in jeder Liste einfach. So, und dann habe ich meine vier Ergebnisse. In echt müsste man das halt algorithmisch lösen.
Damit sind wir eigentlich durch mit dem komplexen Retrieval-Loch in der RAG-Architektur. Da müssen wir relativ viel neu lernen, aber wir können auch super unser Wissen von FTS-Systemen, Volltext-Search anwenden. Das ist für uns alle nichts Neues. Da haben wir wahnsinnig viel Kompetenz drin. Und das ist auch gut, weil das die Qualität von so einem RAG-System steigert.
Wo sind denn die Limits, die Grenzen von so einem Retrieval-System? Ich kann nicht erwarten, dass ich in einem RAG-System User:innen sagen lassen kann: „Gib mir mal alle Orders aus der letzten Kalenderwoche.” Das ist eine Aggregation. Das wird mit dem Retrieval, wie wir ihn besprochen haben, nicht funktionieren, nicht verlässlich. Ich kann Glück haben. Ich kann auch nicht sagen „gruppiere mir mal irgendwas” oder so. Das ist für was anderes gedacht.
Wir haben sogar schon mal so etwas gebaut. Da geht man dann hin und setzt quasi ein LLM ganz vorne hin, wo eine RAG-Architektur eigentlich hinten sitzt, und sagt: „Was will der denn jetzt hier? Stell mal den Intent fest.” Fragt er nach einer Aggregation, dann bau bitte eine SQL-Query und frag das einfach ab und gib es ihm zurück. Oder versucht er ein paar coole Restaurants in Berlin zu finden und kann sich nicht richtig ausdrücken? Dann geh bitte an unseren Retrieval. Man hat vorne wie einen Router eine KI, die das quasi entscheidet, was denn da wohl gewollt wird. Für den:die User:in ist es nicht transparent, er:sie kriegt im Chat dann Ergebnis auf seine:ihre Frage. Aber das müssen wir vom Use Case abhängig machen.
Wir verlassen jetzt den Retrieval und gehen in die Augmentation- und Generation-Phase. Jetzt haben wir nämlich unsere Chunks, die drei, die zurückkamen - vorher waren es vier in dem Beispiel, hier haben wir nur noch drei vereinfacht. Die sind sortiert. Wie sieht denn dann das Prompt aus, was in die Maschine wandert?
Das ist tatsächlich - Teile des Prompts sind aus dem Produktivsystem für einen Kunden. Da steht dann einfach drin - da oben ist zum Beispiel das System Prompt, das würde nicht im Feature Prompt stehen, aber jetzt vereinfacht alles zusammengeklatscht: „Du bist ein AI-Assistent und du hilfst Softwarearchitekt:innen, die an einem E-Commerce für einen High-End Wine Shop arbeiten, in ihrer täglichen Arbeit. Deine Rolle ist, du sollst akkurate, relevante und hilfreiche Antworten auf ihre Fragen liefern mit dem Kontext, den du bekommst.”
Sowas muss man wirklich vorkauen - Praktikanten-Analogie. „Du kriegst Kontext in der Form von Ranked Chunks aus einem Retrieval-System. Dieser Kontext enthält relevante Informationen, um die Architektenfrage zu beantworten. Hier folgt der Kontext.” XML ignorieren. Ihr könnt das formatieren, wie ihr wollt. Ihr müsst nur sagen: „Hier kommt jetzt der Kontext”, damit da nichts durcheinander geschmissen wird.
So kann das aussehen, muss es nicht. Wenn ich URLs habe, packe ich URLs da rein. Ist doch schön, dann kann ich in der Antwort direkt die Antworten verlinken. Wenn ich ein System habe, wo es um PDFs geht und um Seiten, die irgendwo auf Filesystemen liegen, kann ich natürlich nicht direkt verlinken, dann muss ich es irgendwie anders machen. Gebe ich dem:der User:in einfach: „Findest du in Buch ABC auf Seite 13 Kapitel 4.” Hier ist das Confluence-Beispiel, da kann ich ja URIs nehmen. Das sind die gerankten Chunks.
„Der:Die Softwarearchitekt:in hat folgende Frage gestellt”, dann die Frage reinkleben. „Um diese Frage zu beantworten, geh schrittweise vor. Analysiere erstmal den Kontext. Dann identifiziere die relevanten Informationen, um diese Frage zu beantworten. Formuliere eine umfangreiche und akkurate Antwort.”
Und jetzt wird’s eigentlich erst richtig interessant: „Stelle sicher, dass jedes Statement in der Antwort, die du formulierst, gedeckt ist von mindestens einer Quelle, und die Quellen müssen die Chunks sein. Und klemme jedes Statement, klemme da hinten dran eine numerische Referenz auf die Quelle, die dein Statement unterstützt.” Du bringst dem quasi journalistische Arbeit bei durch dieses Prompt. „Gib keine Infos, die nicht auf Basis der Quellen belegbar sind.”
„Important!” - dann noch mal schreien. „Bitte beachten” - sieht man alles im Produktivsystem. „Bitte, bitte, bitte denk daran, deine Antwort in Markdown zu formulieren.” Findet man so im Anthropic System Prompt. Da steht wirklich „bitte, bitte, bitte” drin auf Englisch. „Nutze Referenzen für die Quellen durch die Bank in dem Format, setz die Referenzen immer hinter das Statement, wo die Quelle benutzt wird, und jeder Absatz muss mindestens eine Referenz enthalten und jedes Statement muss eine Referenz enthalten.”
So sieht das Prompt aus. Das geben wir dann in die Generierung, dann kriegen wir eine Antwort. Die Beispiele erspare ich euch jetzt, wie sowas aussieht. Ihr kennt das ja auch: Wenn ihr in ChatGPT sagt - die kann man ja jetzt eine Suchfunktion anschmeißen, die Weltkugel anklicken, meistens erkennt er euren Intent und schmeißt die Kugel selbst an - „Gib mir mal coole Restaurants”, dann nutzt er eben so einen Suchindex. Auch das ist RAG und macht uns diese Pöppel hinter seine Antworten, die kann ich dann anklicken. Das sind dann die Quellen.
Was haben wir in Kundenprojekten gelernt?
Chunking ist das harte Problem. Die Chunks müssen relevant sein, die Chunks müssen die Info enthalten, die quasi als Beleg für eine Antwort gilt. Das heißt, ich muss die Chunks richtig schneiden, sonst ist mein Retrieval-System nicht gut, und wenn das Retrieval-System nicht gut ist, ist alles dahinter eigentlich verloren.
Wenn die Chunks zu klein sind, geht Kontext verloren. Ich habe eben ein Beispiel genannt: Dann fehlt die Begründung, ist weggeschnitten worden, klemmt in einem anderen Chunk drei Chunks später. Und wenn das dann von der Suche nicht mehr gefunden werden kann, weil der Vordersatz fehlt, dann wird es nicht auftauchen. Wenn die zu groß sind, fällt der Retrieval auch aus, weil dann suche ich eigentlich eine Nadel und liefere immer eine ganze Scheune, und davon 10 oder 15 oder so.
Informationsverteilung ist schwierig. Wenn die Kernfakten auf zu viele Chunks verteilt sind, sind sie schwer zu kombinieren.
Query-Formulierung: Was will der:die User:in denn versus was geben meine Daten denn überhaupt her? Wenn ich meinen Confluence da reinklemme und sage „beantworte Fragen zu Softwarearchitektur”, da findet sich kein einziger ADR drin und eine arc42-Doku von 1950, dann kann ich die beste Architektur bauen, das funktioniert eben dann nicht, wenn die Daten Schrott sind.
Eine Lösung für diese Probleme ist relativ neu, die haben die Anthropic-Forscher:innen - also die auch die Claude-Modelle entwickeln, die machen richtig relativ coole Grundlagenforschung auch noch und teilen die auch - nämlich die haben Contextual Retrieval entwickelt, das ist vom November, ist gar nicht so alt. Die gehen eben hin und nutzen ein LLM, um die Chunks in sich schlüssig auszuformulieren.
Wenn ich meinen Confluence chunke, dann fehlen vorne und hinten Sachen. Das wird immer so sein. Wenn ich ganze Sätze bilde, dann habe ich einen Satz, der ist erstmal vollständig semantisch, aber wenn der Folgesatz eigentlich dazugehört, um richtig relevant zu sein, und es im nächsten Chunk ist, habe ich ein Problem. Und ich kann mich diesem Problem eben immer nur näherungsweise nähern, das zu lösen. Ich werde nie die perfekte Chunkgröße finden.
Die gehen hin und sagen: Wenn du deine Chunks geschnitten hast, dann lässt du ein LLM laufen über alle Chunks, was auch immer sich den gesamten Korpus iterativ durchackert und alle Chunks quasi in sich schlüssig ausformuliert. Und dadurch habe ich so ein bisschen Informationsdopplung, vielleicht auch nicht, aber jeder Chunk ist im Prinzip schlüssig. Ich blase quasi wie die Query vorhin meine Chunks auf. Da haben sie ein Paper zu veröffentlicht und das sorgt wohl dafür, dass eine deutlich höhere Ergebnisqualität zu erreichen ist, wenn die Voraussetzungen stimmen und wenn es eben schwierig ist, eine einheitliche Chunkgröße für meine Daten zu finden. Ich muss eine finden. Ich muss mich für die beste Näherungsweise entscheiden, aber die wird vielleicht nicht perfekt sein. Wenn sie das nicht ist, ist Contextual Retrieval die Lösung.
Was gibt’s denn für Alternativen zu RAG?
Fine-Tuning habt ihr bestimmt schon mal gehört, oder? Das ist quasi, man nimmt die fertigen Modelle und verpasst denen noch mal einen Trainingsschritt ganz hinten dran. Ich könnte jetzt denken: Okay, warum trainiere ich denn nicht meinen Confluence in mein Llama 3.3 70B rein? Dann ist das doch da drin, wieso muss ich diesen ganzen Retrieval-Kram denn dahinstellen, den muss wieder jemand warten, die beiden suchen, die loggen wieder, da muss dafür eine Kiste hingestellt werden. Ich könnte doch einfach fine-tunen. Das mache ich einmal und dann ist das Zeug da drin.
Und das ist genau das Problem. Das mache ich nicht mal eben. Das ist auch nicht ewig, aber das ist relativ teuer, weil ich natürlich GPUs brauche, um so einen Trainingsschritt hinten an ein Modell zu klemmen. Ich werde wahrscheinlich nicht die allerkleinsten Modelle verwenden, wenn ich denn überhaupt Open Weights Modelle verwende. OpenAI und Anthropic bieten beide auch ein Fine-Tuning an für ihre Closed Modelle. Also es kann man schon alles mit denen auch machen, aber es ist eben langläufig, es kostet ein bisschen was.
Und dann habe ich eigentlich wieder Knowledge Cutoff. Das heißt, wenn ein neuer ADR im Confluence landet, muss jemand wieder das Fine-Tuning anschmeißen. Im Retrieval-System ist das in Echtzeit drin, also wenn es eben im Index landet. Nicht in Echtzeit, aber mit sehr viel kürzeren Fristen. Das muss man eben abwägen. Wenn sich das Confluence nur alle Jubeljahre ändert und wir über eine Architektur von dem Mainframe reden, wo keiner mehr ran kann oder so, könnte das eine Option sein.
Aber was ich mit dem Fine-Tuning auch mache: Ich beeinflusse natürlich auch die Modellgewichte, und was man oft sieht ist, wenn man einfach irgendwelchen Quatsch da rein fine-tunet, dann verlernt das Modell auch Hochsprache, dann fängt es irgendwie komisch an zu plappern und so Sachen. Da muss ich also schon ein bisschen wissen, was ich da tue. Und ich muss gucken, dass die Daten wirklich gut sind.
Ja, und es kostet ein bisschen was, wobei der Faktor - gerade OpenAI scheint enorm überzeugt davon zu sein, dass das gut ist für viele Kund:innen, deswegen geben die gigantische Rabatte aufs Fine-Tuning, was es echt kostengünstig macht. Die wollen, dass die Leute das probieren, weil es zu wenig Leute einfach machen. Weil genauso Aussagen den Leuten immer um die Ohren gehauen werden: „Ach, ist zu teuer, dann ist der Knowledge Cutoff wieder da, das dauert zu lang und das Ding plappert hinterher Mist.” Das kann eintreten, muss aber nicht, und das ist auch relativ gut gelöst von OpenAI. Ihr müsst euch entscheiden, es ist ein Tradeoff.
Ein Beispiel, wo Fine-Tuning genial ist, ist zum Beispiel Image Fine-Tuning. Wenn ich ein Foundation Model einsetze, was mir vielleicht irgendwelche Marketing-Flyer in der Markensprache im Corporate Design meines Unternehmens erstellen soll und die variieren soll und soll immer on Brand sein - Whitespace muss stimmen, Farbwahl, Fonts und alles - dann ist Image Fine-Tuning genial, das kriege ich über Prompt Engineering nicht hin. Dafür ist Fine-Tuning toll.
Große Law Companies machen auch Fine-Tuning ihrer Modelle mit Gesetzestexten und Anwaltssprech. Da sagt man immer, das wäre so ein Fine-Tuning-Case - bin ich mir nicht so ganz sicher, ob das so einfach ist, weil ich rein über Prompt Engineering einem Modell eigentlich schon beibringen kann, wie ein Gesetzestext auszusehen hat.
Bei RAG sind es eben einfach Storage Costs. Ich muss irgendwo diese Indizes vorhalten, den Vektor-Index und den Volltext-Index. Ist relativ einfach zu updaten. Beim Embedden natürlich bedenken: Wenn jemand eine neue Confluence-Seite anlegt, kann man nicht einfach instantan Embedding erzeugen, das läuft ein bisschen - wahrscheinlich ein paar Minuten bis halbe Stunde macht man dann irgendwie später oder so, aber es ist alles nicht so wie bei Fine-Tuning.
Wir haben alle gelernt, dieses Jahr kommen die Agenten. Deswegen reden viele über agentisches RAG. Ich habe das immer mit drin, dass man noch mal grob weiß, was sich da verändert. Denn ich könnte ja sagen: „Hier, lieber Agent, mach mal eine Recherche und gib mir heute Abend dein Ergebnis” - so ein Langläufer-Task - „und entscheide selbst, wie lange du suchst, und gib eben zurück, wenn du denkst, dass es gut ist.” Das sind so agentische Facetten.
Niemand weiß genau, wie man Agenten definiert. Gerade fangen alle an, Agenten zu definieren, was das denn nun ist. Nehmen wir mal an, es wäre sowas. Es könnte ein guter Use Case sein. Wie verändert sich denn die RAG-Architektur durch einen Agenten? Verändert sich eigentlich nur dadurch, dass so ein Outer Loop eingeführt wird, nämlich vom Generierungsschritt wieder zurück zum Retrieval.
Der Agent guckt eben, indem er die Query reingibt, was gebe ich denn zurück? Oder das LLM - das ist eigentlich ein anderes LLM: Was gibt’s denn zurück und bewertet das?
Da muss ich noch mal an die Query ran. Dann geht’s noch mal rein. Da fehlt vielleicht Kontext, ich müsste Tools benutzen. Was sind denn Tools? Tools ist einfach, wenn ein LLM eine Websuche anschmeißt oder eine API aufruft oder ein Hotel bucht - sowas ist Tool Usage. Der Agent entscheidet eben autonom, ein Tool zu benutzen. Wenn ich ihm sage: „Guck mal, wir haben außer dem Retrieval-System könntest du noch unsere API mit ADRs anzapfen. Guck doch da mal drin”, dann ist es eben Tool Use. Und der Agent macht das eben so lange, bis er denkt, mein Ergebnis ist gut. Ich klopfe beim:bei der Chef:in wieder an: „Hier ist mein Ergebnis.” Das ist agentisches RAG, es wird eben ein Outer Loop eingeführt. Im besten Fall kaufen die nicht zwischendurch irgendwas ein.
Wie baue ich jetzt eine gute RAG-Suche? Fragen auch viele. Und ihr habt das, glaube ich, schon gesehen im Vortrag: Man muss eigentlich eine gute Suche bauen. Wenn die Suche Mist ist, dann löst die RAG-Architektur das Problem nicht. Deswegen muss man eine gute Suche bauen, und wie weiß man, was eine gute Suche ist?
Das kennt ihr alle, ihr leidet alle wie ich unter der Confluence-Suche von Atlassian. Das ist ganz offenbar keine gute Suche. Ich lehne mich jetzt sehr weit aus dem Fenster, weil ich stehe auch so ein bisschen dahinter. Das Ding findet nie, was ich suche, und ich gebe schon exakte, wirklich exakte Keywords ein. Das ist so schlimm, ich muss immer den exakten Seitentitel eingeben, dann kriege ich das Ergebnis, sonst ist es an Stelle 20 oder so.
Eine gute Suche ist dann gut, wenn sie für die User:innen des Features oder des Produkts funktioniert. Und wenn sie das ist, funktioniert sie witzigerweise für die Silizium-User:innen genauso gut. Das ist eigentlich das Schöne. Weil diese Menschen-Analogie hier besonders schön ist: Wenn meine Usertests zeigen „Boah, die Leute finden das, was sie suchen”, dann brauche ich mir um die RAG-Architektur und das LLM hinten gar nicht mehr so viel Kopf machen.
So, das war’s. Wir haben noch ein kleines Goodie: Wir haben so ein kleines Booklet rausgebracht, das kann man sich als EPUB und PDF runterladen, ist so ein Schnelleinstieg in die Architektur, ein bisschen mehr als dieser Vortrag. Wer das haben möchte, kann den QR-Code scannen. Wir tracken nichts, wir beschaffen uns keine Daten. Könnt ihr einfach downloaden. Müsst auch nichts eingeben. Wenn die Folien geteilt werden, werdet ihr es da wahrscheinlich noch mal finden.
Ich lasse die Folie deswegen noch ein bisschen stehen, denn eigentlich habe ich sonst nichts mehr, außer noch auf eine Case Study hinzuweisen, die wir - also wir machen diverse RAG-Architekturen für Kund:innen - die haben uns erlaubt, drüber zu reden, die Firma Sprengnetter, die machen Immobilienbewertung.
Wer sich da mal für so einen echten Real-World-Case interessiert, kann da mal nachlesen. Kurzfassung ist: Da ging es um Immobilien, deren Domäne ist Immobilienbewertung. Und ich nehme immer diesen wahnsinnig griffigen Case: Wenn jetzt ein:e Immobilienbewerter:in, ein:e Makler:in bei denen hingeht und der:die soll jetzt eine neue Gewerbeimmobilie vor Ort bewerten, die in direkter Nähe - 500 m zum Nuklearreaktor - gebaut werden soll. Was ist das Grundstück wert? Was kann ich dafür an Mieten abrufen? Was hat diese Immobilie für einen Wert?
Dann können die das diesen Assistenten fragen. Die könnten auch die interne Knowledge, die sie produzieren - die haben ihr gesamtes Makler-Immobilienbewertungswissen in PDF-Büchern und die kann ich gegen Geld auch lizenzieren und meinen Makler:innen bereitstellen. Aber da stehen die Antworten drin, da stehen auch mathematische Formeln drin, aber wenn ich eben on the run was wissen will, wälze ich keine Bücher, dann frage ich eine:n Kolleg:in, der:die es besser weiß als ich. Mit dem Assistenten sind die ziemlich happy, weil die genau sowas fragen können. Die können auch völlig andere Sachen fragen - ich stecke nicht so drin in der Domäne - aber der liefert eben dann die Antworten zurück. Weil das PDFs sind, steht dann auch immer da: „Findest du auf Seite 13 Kapitel 4 in dem Satz und hier ist der Excerpt.” Das ist ein schöner echter Case, wo denen das einen echten Mehrwert im Alltag bringt.
Ansonsten freue ich mich auf eure Fragen. Danke.