- Langfristig interaktive Chatbots haben selbst mit großen Kontextfenstern Schwierigkeiten, den Kern früherer Interaktionen zuverlässig in ihre Antworten einzubeziehen; diese Studie behandelt eine Methode, Konsistenzprobleme durch rekursives Zusammenfassungs-Gedächtnis zu verringern
- Der Kernablauf besteht darin, aus einem kurzen Dialog ein anfängliches Gedächtnis zu erstellen und es bei jeder neu hinzukommenden Sitzung zu aktualisieren, indem das bisherige Gedächtnis und der neue Dialog gemeinsam zusammengefasst werden
- Retrieval-basierte Ansätze hängen von einem Retriever ab, der die benötigten früheren Äußerungen präzise findet; bestehende gedächtnisbasierte Ansätze können durch nicht aktualisierte veraltete Informationen die Antwortqualität beeinträchtigen
- In Experimenten mit öffentlichen und proprietären LLMs wie Llama, ChatGLM und OpenAI GPT-3.5-Turbo zeigten sowohl automatische als auch menschliche Bewertungen eine höhere Konsistenz in Langzeitdialogen als bei bisherigen Ansätzen
- Die Methode lässt sich auch mit großen Kontextfenstern oder Retrieval-augmented LLMs kombinieren und kann damit eine praktische Option sein, sehr lange Dialogkontexte zu verarbeiten, ohne die Gesamtlänge der Konversation wahllos zu erhöhen
Langzeitgedächtnis in Dialogen: Lange Kontexte allein reichen nicht
- LLMs wie GPT-4 und ChatGPT können zu vielen Themen dynamische und kontextgerechte Gespräche führen, können bei Langzeitdialogen jedoch frühere Informationen übersehen und dadurch inkonsistente Antworten erzeugen
- Auch wenn ein großes Kontextfenster die gesamte Dialoghistorie als Eingabe verarbeiten kann, bleibt die Fähigkeit, frühere Interaktionen zu verstehen und Kerninformationen in Antworten zu integrieren, weiterhin begrenzt
- Typische Anwendungsfälle, die ein Gedächtnis für frühere Gespräche erfordern, sind persönliche AI Companions und Gesundheitsassistenzdienste
- Persönliche AI Companions müssen sich an frühere Gespräche erinnern, um Beziehungen aufzubauen
- Gesundheitsassistenzdienste müssen die gesamte Anfragehistorie eines Patienten berücksichtigen, um Diagnoseergebnisse bereitzustellen
- In einem Beispiel aus dem Multi-Session Chat Dataset erwähnte ein Nutzer nach etwa 20 Turns erneut das frühere Thema „Komponieren“; die Version ChatGPT gpt-turbo-3.5-0301 antwortete darauf, sie sei „ein KI-Sprachmodell ohne Beruf im traditionellen Sinne“, und erzeugte damit eine Antwort, die nicht mit der früheren Persona übereinstimmte
Grenzen von Retrieval- und Gedächtnis-basierten Ansätzen
- Die wichtigsten Ansätze zur Stärkung von Langzeitdialog-Fähigkeiten lassen sich in Retrieval-basierte Ansätze und Gedächtnis-basierte Ansätze einteilen
- Retrieval-basierte Ansätze speichern frühere Äußerungen in einem Speicher und nutzen einen Retriever, um die für das aktuelle Gespräch relevanteste Historie zu finden und für die Antwortgenerierung zu verwenden
- Eine Einschränkung besteht darin, dass es schwierig ist, einen idealen Retriever zu erhalten, der die für das aktuelle Gespräch erforderliche Bedeutung vollständig erfasst
- Gedächtnis-basierte Ansätze fassen frühere Dialoge mit einem separat trainierten Modell oder einem leistungsfähigen LLM zusammen und speichern die Kerninformationen
- Fehlt ein Mechanismus zur wiederholten Aktualisierung, können die gespeicherten veralteten Informationen die Antwortqualität direkt beeinträchtigen
- MemoChat rekonstruiert die frühere Dialoghistorie nach Themen der Sprecher und promptet das LLM bei der Generierung, aus einem strukturierten Gedächtnis zu suchen
- MemoryBank schlägt einen Gedächtnismechanismus vor, bei dem zunächst Zusammenfassungen einzelner Dialogsitzungen erstellt und anschließend zu einer globalen Zusammenfassung komprimiert werden
- Wenn gespeichertes Gedächtnis vollständig fixiert ist, lässt sich die Konsistenz mit einem laufenden Gespräch nur schwer gewährleisten
Rekursiv aktualisierte Gedächtniserzeugung
- Der vorgeschlagene Ansatz ist ein einfacher Plugin-Ansatz, bei dem das LLM selbst Zusammenfassungen erstellt sowie den früheren Kontext fortlaufend aktualisiert und überprüft, um Echtzeitinformationen der Sprecher zu speichern
- Der Ablauf besteht aus drei Schritten
- Ein generatives LLM erhält einen kurzen Dialogkontext als Eingabe und erzeugt eine anfängliche Zusammenfassung
- Anschließend werden das frühere Gedächtnis und der Folgedialog kombiniert, um fortlaufend eine neue Zusammenfassung bzw. ein neues Gedächtnis zu aktualisieren
- Der Chatbot nutzt das aktuellste Gedächtnis als wichtigste Referenz, um auf das aktuelle Gespräch zu antworten
- Da die erzeugten Zusammenfassungen deutlich kürzer sind als der gesamte Dialog, können sehr lange Kontexte über mehrere Sitzungen hinweg verarbeitet werden, ohne die maximale Eingabelänge kostspielig zu erhöhen
- Ein Langzeitdialog wird als Multi-Session Dialogue definiert, der aus mehreren Sitzungen besteht
- Verwendet werden die Menge vergangener Sitzungen
S = {S1, S2, ..., SN}, der Dialogkontext der aktuellen SitzungCtund die korrekte Antwortrt - Ziel ist es, auf Basis der vergangenen Sitzungen und des aktuellen Kontexts eine relevante und hochgradig konsistente Antwort zu erzeugen
- Verwendet werden die Menge vergangener Sitzungen
- Das Gedächtnis
Miist das Gedächtnis, das nach Abschluss der i-ten Sitzung verfügbar ist; der gesamte Prozess wird als sequenzieller Prozess definiert, bei dem jedes Gedächtnis nur von der aktuellen Sitzung und dem vorherigen Gedächtnis abhängt
Gedächtnis-Iteration und Antwortgenerierung
- Der vorgeschlagene Ansatz überträgt einem beliebigen LLM zwei Aufgaben
- Gedächtnis-Iteration: Kerninformationen entsprechend dem Langzeitdialogverlauf rekursiv zusammenfassen
- Gedächtnisbasierte Antwortgenerierung: Das aktuellste Gedächtnis mit dem aktuellen Dialog kombinieren, um eine passende und konsistente Antwort zu erzeugen
- Gedächtnis-Iteration ist der Prozess, eine konsistente und aktuelle Zusammenfassung zu erhalten, die der Chatbot verwenden kann
- Einige frühere Arbeiten aktualisieren Gedächtnis, indem sie „harte Operationen“ wie replace, append und delete auf Zusammenfassungen anwenden
- Solche Methoden hängen von hochwertigen Dialogen mit Operationslabels ab, stören die semantische Konsistenz von Zusammenfassungen und eignen sich auch nicht für die langfristige Verwaltung
- Der vorgeschlagene Ansatz gibt den Dialogkontext und das vorherige Gedächtnis gemeinsam in das LLM, damit es rekursiv ein Gedächtnis bzw. eine Zusammenfassung erzeugt
- Durch die Nutzung der vorherigen Zusammenfassung kann das Modell den aktuellen Dialogkontext besser verarbeiten und ein hochwertiges Gedächtnis erstellen
- Im Beispiel wird nach der ersten Sitzung ein anfängliches Gedächtnis erstellt; nach der zweiten Sitzung wird die neue Persona-Information, dass „der Bot kürzlich einem neuen Fitnessstudio beigetreten ist, das 24 Stunden am Tag geöffnet ist“, in das frühere Gedächtnis integriert
Experimentelle Ergebnisse und Einsatzmöglichkeiten
- Die Experimente wurden mit aktuellen öffentlichen und proprietären LLMs wie Llama, ChatGLM und OpenAI GPT-3.5-Turbo umgesetzt
- Die Langzeitdialog-Leistung fiel sowohl in automatischen als auch in menschlichen Bewertungen höher aus als bei bestehenden populären Ansätzen
- Validiert wurde, dass explizites Gedächtnis in Langzeitdialogen wirksam ist und dass das mit dem vorgeschlagenen Ansatz erzeugte Gedächtnis für LLMs leichter zu verarbeiten ist
- Die Kombination mit In-Context Learning (ICL) kann die Antwortqualität weiter erhöhen
- Dem LLM werden mehrere Beispiele im Format
(Dialog, Gedächtnis, korrekte Antwort)präsentiert - Dadurch kann das LLM das erzeugte Gedächtnis flexibler nutzen
- Dem LLM werden mehrere Beispiele im Format
- Bei text-davinci-003 verbesserte sich der BLEU-Score um etwa +3 %
- Der vorgeschlagene Ansatz ergänzt LLMs mit großen Kontextfenstern wie GPT-3.5-Turbo-16k und LongLoRA-8k sowie Retrieval-augmented LLMs wie LLM-BM25 und LLM-DPR
- Der öffentliche Code ist unter qingyue2014/Rsum verfügbar
1 Kommentare
Meinungen auf Hacker News
Die Art und Weise, Memory im „Textraum“ aufzubauen, wirkt insgesamt ziemlich hacky.
Um die Bedeutung des Modells vollständig zu bewahren, erscheint es natürlicher, sie in einem dichten Embedding-Raum zu speichern, statt ständig über einen nachträglich aufgesetzten Prozess Zusammenfassungen neu zu erzeugen.
Außerdem sollte das Modell darauf trainiert sein, Memory zu erkennen und zu nutzen; idealerweise würde es von Anfang an in einem solchen Setup trainiert.
Letztlich fordert man es auf, an die gegebene Unterhaltung ein weiteres nächstes Wort anzuhängen, und sobald es irgendwann ein End-Token ausgibt, übergibt die Anwendung die Kontrolle wieder an den Nutzer.
Latent Space und Textraum liegen meiner Ansicht nach näher beieinander, als man denkt. LLMs sind ziemlich stumpf, aber sehr gut im Reden; beim Schreiben von Code ist es ähnlich, weshalb sie darin gut sind, während sie in Bereichen wie Mathematik, die echtes abstraktes Denken erfordern, zusammenbrechen.
Solche Hacks im Textraum funktionieren in der Praxis recht gut, und deshalb sind Prompts wie „Denke Schritt für Schritt“ so verbreitet geworden.
LoRA geht eher in die von dir genannte Richtung und ist hervorragend darin, viel Verständnis in sehr wenige Daten zu komprimieren. Allerdings ist es noch nicht realistisch, die Gewichte für eine einzelne Unterhaltung anzupassen; für diesen Zweck erkundet man daher den Textraum.
Etwas im Kopf zusammenzufassen kann sich „hacky“ anfühlen, aber ich denke, ein großer Teil der tatsächlichen Funktionsweise des Gedächtnisses ist dem ziemlich ähnlich.
https://news.northwestern.edu/stories/2012/09/your-memory-is...
So wie ich Embeddings verstehe, ähneln sie im Kern eher einer verlustbehafteten Kompression. Bei einer Textzusammenfassung kann ein Agent zumindest überprüfen, ob diese Zusammenfassung die ursprünglichen Informationen korrekt repräsentiert.
Bei CodeRabbit verwenden wir diesen Ansatz bereits für inkrementelle PR-Reviews und Gespräche im Kontext von Codeänderungen.
Er lässt den Bot so wirken, als hätte er weit mehr Kontext, als tatsächlich der Fall ist, und ist einer von mehreren Tricks, mit denen wir AI-Code-Reviews auf große PRs (100+ Dateien) skalieren.
Für jeden Commit fassen wir die Diffs pro Datei zusammen, erstellen wiederum eine Zusammenfassung dieser Zusammenfassungen und aktualisieren sie inkrementell, wann immer dem PR ein Commit hinzugefügt wird. Diese Zusammenfassung der Zusammenfassungen wird versteckt in einem PR-Kommentar gespeichert und genutzt, wenn einzelne Dateien reviewt oder Nutzerfragen beantwortet werden.
Ein Teil des Codes ist Open Source, und der relevante Prompt, den wir für rekursive Zusammenfassungen verwenden, ist hier: https://github.com/coderabbitai/ai-pr-reviewer/blob/main/src...
[0]: coderabbit.ai
Falls ja, würde mich auch interessieren, ob ihr statt des Parsens von Freitext-Ausgaben function calling ausprobiert habt.
Wenn man noch in der Phase „Code und Skripte werden später veröffentlicht“ ist, fällt es inzwischen schwer, irgendeiner Behauptung zu glauben.
Es kann stimmen oder auch Unsinn sein, aber wenn es keine kostengünstige Möglichkeit gibt, das Experiment zu reproduzieren, betrachte ich solche Papers als etwas, das die Autoren für ihren Lebenslauf geschrieben haben.
Im LLM-Bereich warte ich seit über sechs Monaten auf Papers mit „Code wird später veröffentlicht“, aber es gibt keinerlei Anzeichen für eine tatsächliche Veröffentlichung. Manche Papers sind sogar so dreist, defekte Links einzubauen, die auf geparkte Domains führen.
Es ist an der Zeit, dass die Community diese Praxis unveröffentlichten Codes ernsthaft wahrnimmt.
Ich habe früher mit einer ähnlichen Idee experimentiert, indem ich in einem API-Dashboard nur die Prompts direkt angepasst habe. Es hatte Potenzial, schien aber die API-Kosten nicht wert zu sein. Wahrscheinlich ist ein Vektor-Embedding-Ansatz deutlich besser.
Als persönliches Beispiel: In unserem Unternehmen gibt es Tausende von „Briefings“, also einstündige, manchmal ganztägige Offline-Panels.
Wir haben jedes Briefing erfolgreich zusammengefasst, und die unordentlichen Transkripte wurden sauber zu Zusammenfassungen aus fünf Absätzen verdichtet.
Relevanter ist, dass wir jedes Briefing in Themen und Unterthemen im Verhältnis 1:N klassifiziert haben. Themen umfassten Dutzende Briefings, Unterthemen etwa ein Dutzend; anschließend haben wir Teilmengen der relevanten Zusammenfassungen erneut zusammengefasst und breit getestet, wobei wir mit LLMs sehr gute Ergebnisse erzielt haben.
Anfangs war ich skeptisch, ob das funktionieren würde, aber es hat sehr gut funktioniert. Mit einem ausreichend großen Kontextfenster hätte ich es nicht so gemacht, aber zum Glück war das kein Problem.
Ich denke, ein Problem wie bei MapReduce zu zerlegen funktioniert deutlich besser, als alles in ein riesiges 32k-Kontextfenster zu stopfen und es auf einmal lösen zu lassen.
Vor ein paar Monaten habe ich mit einem Open-Source-Modell einen rekursiven Zusammenfassungs-Speicher gebaut; naiv implementiert blieb er häufig für immer in einem bestimmten Thema stecken.
Der Grund ist, dass bestimmte Fragmente jede Zusammenfassungsrunde überleben.
Es ist unmöglich, einen beliebigen Textblock auf einen kleineren Textblock zu reduzieren, ohne irgendeine Information zu verlieren.
Wenn das möglich wäre, hieße das, dass unendliche Kompression möglich wäre und jeder Datensatz auf 1 Bit reduziert und anschließend perfekt rekonstruiert werden könnte. Das geht aber nicht.
Wenn man eine Unterhaltung zu einer Zusammenfassung komprimiert, verschwindet zwangsläufig ein Teil der Information. Egal wie viel man tunt, faltet oder welche cleveren Methoden man einsetzt: Grundsätzlich entsteht Informationsverlust.
Außerdem ist dieser Prozess rekursiv, sodass man irgendwann ein Bündel von Zusammenfassungen erneut zusammenfasst, und auch dabei geht ein gewisses Maß an Information verloren.
In trivialen Fällen mag es also helfen, aber rekursive Zusammenfassungen in den Prompt zu stecken, ist ziemlich töricht und wird mit ziemlicher Sicherheit nicht richtig funktionieren, sobald man tatsächlich nützliche Arbeit damit erledigen will. Solange man rekursive Zusammenfassungen nicht viel nutzt, sieht es nur so aus, als würde es funktionieren, weil wenig Information verloren geht; wenn man es wirklich einsetzt, dürften die Grenzen schnell sichtbar werden.
Wenn man bedenkt, wie leicht die menschliche Psyche schon durch Trauma oder Entwicklung aus der Bahn geraten kann, merkt man, wie hoffnungsvoll die Vorstellung einer menschenähnlichen KI ist.
Das Paper ist etwas enttäuschend. Details zur Technik gibt es praktisch kaum, nur Tabellen, die zeigen, dass ihre Methodik gute Ergebnisse liefert.
Ich weiß, dass das in der heutigen Wissenschaft üblich ist, aber aus Sicht eines Entwicklers, der mit LLMs arbeitet, hat das Paper kaum Wert. Natürlich wird der akademische Ruf der Autoren dadurch ein wenig steigen, und das dürfte sehr wahrscheinlich der Zweck gewesen sein.
Ich frage mich, ob ich nicht auch ein paar solcher Papers mitschreiben sollte. Wie viele bräuchte man wohl, um ganz oben im Lebenslauf den Titel „ML researcher“ führen zu können?
Sie hätten viel mehr Zeit auf Beispiele und Prompts verwenden sollen.
Ich habe vor ein paar Wochen schon etwas Ähnliches geschrieben, aber die Leute vereinfachen den Teil mit der Zusammenfassung viel zu stark: https://news.ycombinator.com/item?id=37117515
Der Wert von Langzeitgedächtnis ist je nach Use Case nuanciert unterschiedlich.
Wenn man einen Home Assistant baut, muss man mit NER Namen identifizieren und verstehen, welchen Tonfall diese Person bevorzugt, wenn man ihr eine Nachricht schickt, sowie Orte und Fortbewegungsarten verstehen.
Wenn man einen Kundenservice-Bot baut, muss man Anfragen identifizieren, die zu langen Gesprächen geführt haben, oder Anfragen, die zu plötzlichen Warenkorbabbrüchen geführt haben.
Schon mit einem allgemeinen Zusammenfassungsniveau lassen sich eindrucksvolle Demos bauen, aber wenn man heute wirklich nützliche Produkte bauen will, muss man einen Schritt weiter gehen.
Ich bin mir nicht sicher, was daran neu sein soll.
LLM-basierte Zusammenfassungen von Chatverlaufs-Speichern sind eine bekannte Technik, die bereits in vielen LLM-Frameworks implementiert ist. Wenn man wie im Paper jede Nachricht zusammenfasst, entsteht ein großer Performance-Flaschenhals, und die Chat-Schleife bekommt eine erhebliche Latenz.
Viele Implementierungen verwenden einen Puffer fester Größe und fassen ältere Speicherblöcke, die aus dem Puffer herausfallen, schrittweise zusammen. Idealerweise passiert auch das außerhalb der Chat-Schleife.
Ich bin einer der Autoren von Zep, einem Open-Source-Langzeitspeicher-Store, und wir haben Zusammenfassungen auf diese Weise implementiert.
0: https://github.com/getzep/zep
https://github.com/paul-gauthier/aider/blob/main/aider/histo...
https://www.deeplearning.ai/short-courses/langchain-for-llm-...
Das geht etwas am Artikel oder an der Diskussion vorbei, aber kurzes Gedächtnis ist tatsächlich eine echte Grenze.
Allerdings glaube ich, dass die meisten Kritikpunkte an den Fähigkeiten von GPT-4 genauso oder sogar noch stärker auf Menschen zutreffen.
In einer Situation eines umgekehrten Turing-Tests glaube ich nicht, dass mich irgendeine lebende Person davon überzeugen könnte, sie sei GPT-4. Allein die schnellen und gut strukturierten Antworten von GPT-4 übertreffen menschliche Fähigkeiten.
Selbst wenn ein Team von Menschen 60 Minuten pro Frage Zeit hätte, könnte es schwer werden, bei interessanten Fragen mit den Antworten von GPT-4 mitzuhalten. Das wäre ein interessanter Wettbewerb.
Die Implementierung im Paper hängt den Memory-Text im Grunde als Teil des Prompts an.
Ich frage mich, warum sie kein Speicher- und Suchsystem verwenden, das keine Tokens aus dem Kontextfenster verbraucht. Zum Beispiel könnte man beim Speichern, also wenn ein Nutzer-Prompt eingeht, die Daten automatisch nach Tags klassifizieren und beim Abruf eine Abfrage ausführen, die nach den Tags filtert, die das LLM vor der Antwort geschätzt hat.
Intuitiv glaube ich, dass schon ein paar anfängliche Regeln wie hartcodierte Tag-Namen oder Stile ziemlich gute Ergebnisse liefern könnten.