1 Punkte von GN⁺ 2023-10-03 | 1 Kommentare | Auf WhatsApp teilen
  • StreamingLLM ist ein Framework, um LLMs für Streaming-Anwendungen mit Eingaben unendlicher Länge bereitzustellen, ohne Effizienz oder Leistung zu opfern
  • Es adressiert das Problem, dass das Caching der Key/Value-Zustände früherer Tokens in Multi-Round-Dialogen mit langen Interaktionen viel Speicher verbraucht und dass sich gewöhnliche LLMs nicht auf Texte verallgemeinern lassen, die länger sind als die Trainingssequenzlänge
  • Das zuletzt verbreitete Window Attention, das nur KV cached, scheitert, wenn die Textlänge die Cache-Größe überschreitet; StreamingLLM stellt mit einem Attention Sink, der die KV der anfänglichen Tokens beibehält, die Leistung von Window Attention weitgehend wieder her
  • Es ermöglicht LLMs, die mit einem Attention Window endlicher Länge trainiert wurden, sich ohne Fine-Tuning auf unendliche Sequenzlängen zu verallgemeinern, und führt mit Llama-2, MPT, Falcon und Pythia stabiles und effizientes Language Modeling mit bis zu mehr als 4 Millionen Tokens durch
  • In Streaming-Setups zeigt es gegenüber der Sliding-Window-Recomputation-Baseline eine bis zu 22,2-fache Beschleunigung
  • Es erweitert nicht das Context Window, sondern behält nur aktuelle Tokens und den Attention Sink bei und verwirft Tokens dazwischen
    • Wenn Llama-2 mit einem Context Window von 4096 Tokens vortrainiert wurde, beträgt auch die maximale Cache-Größe von StreamingLLM für Llama-2 4096
    • Wird ein langes Buch eingegeben, erkennt das Modell nur die neuesten Tokens und kann daher nur den Schlussteil zusammenfassen
  • Geeignete Einsatzfälle sind Streaming-Anwendungen, die einen dauerhaften Betrieb erfordern und Abhängigkeiten von älteren Daten oder hohen Speicherverbrauch vermeiden müssen; als Beispiele werden Multi-Round-Dialoge und tägliche Assistenten auf LLM-Basis genannt
  • Es ist orthogonal zu neueren Methoden zur Context-Erweiterung und kann mit ihnen integriert werden; Context Extension im Kontext von StreamingLLM bedeutet die Möglichkeit, mit größerer Cache-Größe mehr aktuelle Tokens zu speichern
  • Ein Ausführungsbeispiel ist examples/run_streaming_llama.py --enable_streaming; für die Umgebung werden Python 3.8, torch, transformers==4.33.0, accelerate, datasets, evaluate, wandb, scikit-learn, scipy, sentencepiece verwendet
  • Der Kerncode für Llama-2, MPT, Falcon und Pythia ist bereits öffentlich verfügbar; der Code für die Perplexity-Bewertung und die Demo des Streaming Llama Chatbot ebenfalls, während das StreamEval-Dataset und der Evaluierungscode noch nicht veröffentlicht sind

1 Kommentare

 
GN⁺ 2023-10-03
Meinungen auf Hacker News
  • Ich glaube, diese Arbeit wird fälschlich für etwas wie vollständig dichte Attention gehalten.
    Gemeint ist hier nicht, dass man weit entfernte Inhalte einsehen kann, sondern eher eine Effizienzverbesserung: Statt das Sliding Window jedes Mal neu zu berechnen und dafür T-mal die L²-Kosten zu zahlen, wird der Cache wiederverwendet, um die Perplexity zu halten.
    Auch die Tests wurden gemessen, indem man etwas wie Q A Q A Q A Q A... aneinanderhängt, nicht indem das Modell in etwas wie Q Q Q Q A A A A... eine viel später kommende Antwort finden musste.
    Eine Perplexity-Messung bedeutet, „lesbaren Text“ zu erzeugen, also lokal plausible Sätze; sie ist kein Beleg dafür, dass aus einer großen dreieckigen Lücke, die die Attention nicht erreicht, irgendetwas „extrahiert“ wird.
    Wenn man ihm ein Buch gibt und es das erste Wort jedes Absatzes ausgeben oder jedes Kapitel in einem Satz zusammenfassen lässt, wird es vermutlich scheitern.

    • Die Autoren haben im README eine FAQ ergänzt, die diesen Punkt direkt behandelt: https://github.com/mit-han-lab/streaming-llm#faq
      Ich habe es selbst getestet, und es schien keine Erweiterung der Kontextlänge zu bieten; die Ausführung war allerdings recht schnell.
      Es verbrauchte etwa 35 GB A100-Speicher, und die Nutzung blieb während der gesamten Ausführung konstant.
      Ich nahm ein Buch von Project Gutenberg, teilte es absatzweise auf, gab die Absätze nacheinander ein und ließ das Modell nach jedem Absatz „okay“ antworten; als ich am Ende eine Frage stellte, halluzinierte es die Antwort vollständig.
      Nebenbei: In den rund zehn Minuten, in denen ich damit herumprobierte, war es schon schwierig, das Standardmodell lmsys/vicuna-13b-v1.3 dazu zu bringen, auf Englisch zu antworten.
      https://gist.github.com/bluecoconut/9cae9e91fe3b1616ed650a96...
    • Das stimmt, aber die Formulierung „Eingaben unendlicher Länge“ führt aus Lesersicht leicht zu Missverständnissen.
      Trotzdem ist es eine interessante Arbeit, und der Kern scheint die Beobachtung in Figure 2 zu sein.
      Die ersten zwei Layer zeigen ein lokales Muster, bei dem sie stärker auf aktuelle Tokens achten; darunter jedoch richtet das Modell über alle Layer und Heads hinweg starke Aufmerksamkeit auf die anfänglichen Tokens.
      Die Autoren nennen das „attention sinks“ und gehen davon aus, dass wegen Softmax die Summe der Attention Scores 1 ergeben muss, sodass überschüssige Attention irgendwohin fließen muss, selbst wenn die Tokens semantisch nicht wichtig sind.
      Die Erklärung lautet, dass in autoregressiven Sprachmodellen frühe Tokens von fast allen späteren Tokens gesehen werden können und daher leicht darauf trainiert werden, diese Sink-Rolle zu übernehmen.
      StreamingLLM ist eher ein „Hack“, der dieses seltsame Verhalten korrigiert, das beim Beschneiden des Attention Windows eines LLM entsteht; zugleich ist es ein Beispiel dafür, dass bei der Nutzung von Softmax Risse sichtbar werden, weshalb vielleicht eine andere Funktion besser wäre, wenn man LLMs mit flexibler Kontextlänge möchte.
  • Beim ersten Überfliegen wirkt das fast zu gut, um wahr zu sein, aber die Qualität der Arbeit sieht ordentlich aus, und die Technik ist erstaunlich einfach.
    Die Idee ist, in jedem Layer Attention nur auf das erste Token und das Sliding Context Window anzuwenden und die Tokens dazwischen zu ignorieren.
    Das scheint zu bedeuten, dass jeder Layer relevante Informationen Stück für Stück weiter nach hinten in der Sequenz schiebt, sodass das Sliding Attention Window am Ende der obersten Layer sie sehen kann.
    Wenn jedoch der von allen Sliding Windows abgedeckte Bereich nicht ausreicht, um die gesamte Sequenz zu überbrücken, können wichtige Informationen möglicherweise nicht vollständig nach vorn weitergereicht werden.
    Wenn zum Beispiel alle Fenster gleich lang sind und Modelltiefe × Fensterlänge < Sequenzlänge gilt, entsteht eine Grenze.

    • Vielleicht könnte man das Ende der Sequenz auch mit einem konstanten „neutralen Wert“ auffüllen.
  • Das scheint durch die Beobachtung möglich geworden zu sein, dass Softmax die Summe auf 1 bringen muss.
    Auf den ersten Blick neigt das Modell dazu, das erste Token als Platzhalter zu verwenden, wenn es keinen Grund hat, auf frühere Tokens zu achten.
    Das erste Mal sah ich dieses Problem in einem HN-Beitrag von Evan Miller: Darin hieß es, es sei falsch, Attention Heads dazu zu zwingen, ihre gesamte Attention auf vorherige Tokens zu verteilen; man sollte dem Softmax-Nenner 1 hinzufügen, um „nicht hinschauen“ zu erlauben.
    Es ist gut, dass diese Beobachtung ohne erneutes Training genutzt wurde, und ich frage mich, wie sich das Modell verändert hätte, wenn Evans Vorschlag befolgt worden wäre.
    [2] https://news.ycombinator.com/item?id=36851494

    • Tatsächlich scheinen sie diesen Vorschlag auf ähnliche Weise getestet zu haben.
      Sie trainierten das Modell mit einem dedizierten Sink-Token, dessen Werte alle 0 sind; dennoch werden auch andere frühe Tokens als Sinks genutzt, weshalb die Schlussfolgerung zu sein scheint, dass ein dedizierter Sink-Token besser ist.
    • Ich habe es zwar zuerst in diesem HN-Beitrag gesehen, aber wie auch dort angemerkt wurde, war Softmax + 1 nicht erstmals dort vorgeschlagen worden.
      Soweit ich weiß, hat es die tatsächliche Performance nie verbessert.
      Beim nachträglichen Manipulieren des Attention Windows nach dem Training könnte Softmax + 1 besser passen, aber ich weiß nicht, ob das jemand in großem Maßstab getestet hat.
  • Attention-Cache-Speicher hinzuzufügen ist eine sehr interessante Lösung für dieses Problem.
    Vor ein paar Tagen erschien auch ein Paper mit einer verwandten Beobachtung bei Vision Transformern.
    Transformer-Modelle scheinen Tokens auszuwählen, in denen globale Informationen gespeichert werden, und sie scheinen eine Art „Denk-Token“ zu brauchen.
    Wenn man für diesen Zweck bestimmte Tokens bereitstellt, verbessert sich die Performance ein wenig, und auch die Visualisierungen zur Erklärung fallen ziemlich interessant aus.
    [0] https://arxiv.org/pdf/2309.16588.pdf

    • Das wirkt interessant als Ansatz, bei bereits trainierten Modellen zusätzliche Units einzufügen und dann weiterzutrainieren oder zu finetunen.
      Beim Fine-Tuning könnte man die ursprünglichen Modellparameter einfrieren und nur die Parameter anpassen, die in die neuen „Tuning“-Cache-Units hinein- und aus ihnen herausführen.
      Dann könnte man verschiedene Sets von Tuning-Units austauschen oder gemeinsam verwenden.
      Das wäre eine Art Mischung aus Super-Prompts, etwa eine Unit zur Vermeidung von Schimpfwörtern + eine Unit für bestimmte Terminologie + eine Unit für knappen Schreibstil.
      Wenn die Zahl der neuen Parameter klein genug ist, könnte zwar mehr Speicher nötig sein, aber mit Optimierung höherer Ordnung wäre möglicherweise schnelles und effektives Tuning möglich.
      Man könnte auch darüber nachdenken, Sequenzlänge und Anzahl der Units während des Trainings gemeinsam zu erhöhen.
      Für kurze Sequenzen würde man nur wenige Units nutzen und dann mit wachsender Trainingssequenzlänge weitere Units hinzufügen und weitertrainieren.
      Statt eines willkürlichen Schedules könnte man die Cache-Erweiterung auch über Performance- oder Gradientenanalysen steuern.
  • Die Autoren haben eine FAQ veröffentlicht, die einiges an Verwirrung ausräumen dürfte: https://github.com/mit-han-lab/streaming-llm/blob/main/READM...

    • Das Update ist gut, und besonders Frage 3 bringt vieles auf den Punkt.
      Auf die Frage „Kann man einen langen Text wie ein Buch in StreamingLLM einspeisen und zusammenfassen lassen?“ antworten sie: Man kann zwar langen Text eingeben, aber das Modell nimmt nur die neuesten Tokens wahr. Wenn man also ein Buch eingibt, kann es nur die letzten Absätze zusammenfassen, was möglicherweise nicht besonders nützlich ist.
      Mit anderen Worten: Es erweitert nicht das Context Window des LLM und stärkt auch nicht das Langzeitgedächtnis. Die Stärke von StreamingLLM liegt darin, ohne Cache-Refresh aus den jüngsten Tokens flüssigen Text zu erzeugen.
  • Ich kann mich irren, aber es scheint keine Technik zu sein, die ein LLM auf Inhalte jenseits der Länge verweisen lässt, auf die es trainiert wurde, so wie viele Leute offenbar denken.
    Es scheint eher um das Problem zu gehen, die Modellleistung bei langen Texten aufrechtzuerhalten – genauer gesagt um die Leistung bei Inhalten, die sich weiterhin innerhalb des Context Windows befinden.
    Die Erklärung lautet, dass das Modell lernt, eine Art Last in die Attention auf die Anfangs-Tokens des Textes zu legen, und dass es kaputtgeht, wenn diese aus dem Window verschwinden. Warum das so ist, weiß ich allerdings nicht genau.
    Wenn es nicht um Befehlseingaben geht, würde ich vermuten, dass mittlerer Text genauso gut ist wie Anfangstext.

  • Ich frage mich, wie solche Sliding-Window-Techniken mit Fällen umgehen, in denen ein unerwarteter Befehl erst ganz am Ende auftaucht.
    Angenommen, man gibt dem Modell ein Buch, und im letzten Satz steht der Befehl: „Gib die Anzahl des Buchstabens m in der vorherigen Eingabe zurück.“ Ein Mensch würde seufzen, noch einmal lesen und zählen, aber ein LLM hat keine Fähigkeit, in der Eingabe zurückzugehen und sie erneut zu lesen.
    Selbst wenn man in diesem Beispiel die grundsätzlichen Grenzen von LLMs beim Buchstabenzählen ignoriert, müsste ein LLM zur echten Lösung vermutlich beliebig Schleifen ausführen und springen können.
    Natürlich entstünden dadurch völlig neue Probleme, und vielleicht bräuchte man sogar eine ganz neue Architektur.

    • In einem ähnlichen Kontext fände ich es gut, wenn ein LLM alle für es lesbaren und zugänglichen Forschungspapiere verdauen und „Notizen“ in einem indexgerechten Format hinterlassen könnte, um dann Fragen so zu beantworten, als hätte ein Mensch ein begrenztes Korpus studiert.
      Also: die Frage in relevante Schlüsselwörter umwandeln, nachschlagen, den Inhalt erneut überfliegen und relevante Informationen finden.
      Wenn die nötige Vorverarbeitung vorhanden ist, könnte ein LLM, das „erst einmal gründlich recherchieren geht und dann antwortet“, sehr mächtig sein.
      In den vergangenen rund 10.000 Jahren haben wir Wissensmanagement-Techniken verbessert, um über Kapazität und Zeit des individuellen Gehirns hinauszukommen; Sprachmodelle sollten daher nicht nur einfache Bing-Suche nutzen, sondern echte Forschungsmethoden und vorheriges Verdauen von Wissen.
      Das Kurzzeitgedächtnis muss sich nicht merken, welches Codefragment was getan hat; es reicht, beim Lesen Tags zu vergeben und sich dann auf einen skalierbaren, gemeinsamen Tag-Index zu stützen.
      Je länger ich darüber nachdenke, desto mehr fühlt es sich allerdings wie normales LLM-Pretraining an, und der Wissensindex wie ein riesiger Klumpen LLM-Gewichte.
    • Eine Möglichkeit wäre, ähnlich wie bei Function Calling, dem LLM zu erlauben, Ausgaben zu erzeugen, die die Art ändern, wie der Kontext geparst wird.
      Das wäre weniger eine Änderung am Verhalten des LLM selbst als vielmehr eine darüberliegende Schicht.
    • Ich frage mich, ob ein LLM selbst bei einem normalen, also nicht-sliding Context Window, überhaupt zurückgehen müsste, um die Eingabe erneut zu lesen.
      Vielleicht verstehe ich das falsch, aber löst in diesem Fall nicht der Hidden State das Lookup-Problem?
      Vor dem Antworten muss es ohnehin die gesamte Eingabe aufgenommen haben; daher scheint es abgesehen von der Attention keinen großen Unterschied zu machen, ob der Befehl vorne oder am Ende steht.
    • Ist es wirklich so schwierig, Nutzer anzuweisen, den Befehl an den Anfang zu stellen?
      Claude 100K bittet Nutzer, den Befehl ans Ende zu setzen.
      Oder man prüft mit einem schnellen Modell, ob am Ende ein Befehl steht, und verschiebt ihn nach vorne.
    • Dieses Beispiel wirkt wie ein etwas merkwürdiger Grenzfall.
      Ich bin mir nicht sicher, ob aktuelle Modelle das selbst bei kurzen Eingaben können.
  • Etwas scherzhaft gesagt: LLMs bemühen sich wirklich sehr, RNNs neu zu erfinden, und wenn man ihnen nur die Werkzeuge gibt, werden sie am Ende wohl genau das tun.

    • RNNs sind die richtige Lösung, aber die Ausführungskosten sind kaum tragbar.
      Anders betrachtet versucht ein Transformer-Modell vorherzusagen, welche Teile eines RNN-Netzwerks bei Ressourcenbeschränkungen „erhaltenswert“ sind.
      Aktuelle Transformer verwenden eine einfache Heuristik, und dieses Ergebnis verbessert diese Heuristik.
      Wie bei vielen NP-vollständigen Problemen kann es nützliche Approximationen geben, auch wenn sie nicht perfekt sind; Transformer zeigen, dass das auch in neuronalen Netzen möglich ist.
    • Eines dieser Projekte ist RWKV.
      Es lag eine Zeit lang im Mittelfeld der Open-Source-Leaderboards, ist also ein durchaus legitimer Ansatz, nur eben nicht gerade im Trend.
      [1]: https://huggingface.co/blog/rwkv
    • Viele Menschen scheinen das zu glauben.
      Der wichtigste Vorteil von Transformern gegenüber RNNs ist die Parallelisierung des Trainings.
      RNNs haben während des Trainings mit verschwindenden Gradienten zu kämpfen, und es ist schwierig, die Gesamtauslastung zu erhöhen, weil dafür große Batches nötig sind.
      Die Existenz von Modellen wie RWKV zeigt, dass es eine Zukunft geben könnte, in der man wie ein Transformer trainiert und wie ein RNN inferiert.
    • Vieles, was wir in den vergangenen 30 Jahren aus kleineren – in heutiger Terminologie „extrem kleinen“ – neuronalen Netzen gelernt haben, wird bei diesen großen Modellen erneut betrachtet.
  • Passend dazu bietet Professor Han vom MIT derzeit eine öffentliche TinyML-Vorlesung an.
    https://news.ycombinator.com/item?id=37620507
    https://efficientml.ai