Die Begrenzung von Kontextfenstern bei großen Sprachmodellen (LLMs) erinnert an die technischen Herausforderungen der 1990er-Jahre. Damals kämpften Entwickler mit der 640-KB-Grenze für konventionellen Speicher unter DOS. Die Lösung? EMM386 nutzte die Adressübersetzungsfunktionen des 80386-Prozessors, um größere Speicherbereiche durch ein kleines Fenster im 640-KB-Rahmen zugänglich zu machen. Programme konnten so effektiv unbegrenzten Speicher adressieren, indem nur die relevanten Daten in den begrenzten Speicher geladen wurden.
Heute steht die KI-Branche vor einem ähnlichen Dilemma: LLMs arbeiten mit festen Kontextfenstern – sei es 32.000, 128.000 oder sogar eine Million Token. Doch die Daten, die ein Agent verarbeiten muss, umfassen oft Konversationsverläufe, abgerufene Dokumente, Testergebnisse und persistente Fakten. Diese übersteigen schnell die Kapazität eines bezahlbaren Kontextfensters. Die gängige Praxis, einfach die letzten Nachrichten oder vektorielle Treffer zu kombinieren, führt zu unübersichtlichen und unvorhersehbaren Ergebnissen. Das Modell liefert Antworten, doch niemand kann nachvollziehen, warum – und zwei aufeinanderfolgende Anfragen können unterschiedliche Reaktionen auslösen, ohne dass die Gründe dokumentiert wären.
Genau hier setzt LLM386 an. Die Open-Source-Software übernimmt die Rolle von EMM386 für LLMs und verwaltet Kontextfenster effizienter. Sie fungiert als Laufzeitumgebung, die den begrenzten Speicherplatz des Modells optimal nutzt.
Die Kernidee: Kontext als Funktion
Ein Sprachmodell ist eine reine Funktion: `f(Kontext) → Ausgabe`. Es besitzt weder Gedächtnis noch Persistenz zwischen verschiedenen Aufrufen. Jede Interaktion muss den vollständigen Kontext neu konstruieren. Daraus ergeben sich zwei zentrale Konsequenzen:
- Stateless-Design: Der persistente Zustand wird in einem Speicher verwaltet, den die Laufzeitumgebung kontrolliert. Das Modell agiert als zustandsloser Verbraucher dieser Daten.
- Dynamische Kontextzusammenstellung: Der Prompt für jeden Modellaufruf wird aus dem persistenten Speicher generiert – unter Berücksichtigung des verfügbaren Eingabevolumens des Modells.
Architektur von LLM386: Was unter der Haube steckt
LLM386 besteht aus mehreren Komponenten, die zusammen eine robuste und nachvollziehbare Kontextverwaltung ermöglichen:
- Persistenter Blockspeicher: Basierend auf LMDB, adressiert über Inhalte und dedupliziert über Hashes. Jede Information wird nur einmal gespeichert, unabhängig davon, wie oft sie referenziert wird.
- Pager: Diese Komponente wählt die relevanten Blöcke aus, die in das Kontextfenster des Modells passen. Sie führt dabei mehrere Retriever parallel aus – etwa für Aktualität, BM25-ähnliche Suchen, Embedding-basierte ANN oder benutzerdefinierte Logik. Die Ergebnisse werden normalisiert, nach Blöcken zusammengefasst und auf canonicalisierte Abschnitte verteilt:
- System: Vorgegebene Anweisungen oder Constraints.
- Task: Aktuelle Aufgabe oder Zielsetzung.
- State: Persistenter Zustand der Anwendung.
- Plan: Geplante Schritte oder Zwischenziele.
- Retrieved: Abgerufene externe Daten.
- Tools: Verfügbare Funktionen oder APIs.
- Recent: Letzte Nachrichten oder Interaktionen.
- Background: Hintergrundinformationen oder Kontext.
- Packer: Wandelt die ausgewählten Blöcke in einen deterministischen Prompt um – entweder als String oder als rolenspezifische Chat-Nachrichtenliste.
- Tracer: Dokumentiert, welche Daten das Modell zu einem bestimmten Zeitpunkt erhalten hat und warum. Jede Prompt-Version wird mit einem Byte-level-Hash versehen, um spätere Replays zu ermöglichen.
- Reducer: Überführt die Modellausgabe zurück in persistente Zustandsänderungen durch geparste Ereignisse.
- Typisierte Graphen: Verbinden abhängige Blöcke miteinander, sodass der Pager Ergebnisse von Tools immer zusammen mit der zugehörigen Nutzeranfrage speichert.
- Diff-Layer: Ermöglicht den Vergleich zweier Trace-Einträge zwischen verschiedenen Modellaufrufen.
Die Implementierung erfolgt in Rust mit einer Python-SDK-Erweiterung (PyO3). Eine CLI ist ebenfalls verfügbar. Die Software steht unter der Apache-2.0-Lizenz und befindet sich aktuell in der Alpha-Phase (Version 1.0.0-alpha).
Was bewusst nicht implementiert wurde
Die Entwickler von LLM386 haben bewusst auf bestimmte Funktionen verzichtet, um die Zuverlässigkeit und Nachvollziehbarkeit zu gewährleisten:
- Keine Chatbot-Oberfläche: LLM386 ist eine Laufzeitbibliothek, keine fertige Anwendung.
- Kein versteckter Zustand in Prompts: Alle Informationen müssen explizit verwaltet werden.
- Keine automatische Annahme von Modellausgaben als Wahrheit: Die Software behandelt Ausgaben als Vorschläge, die weiterverarbeitet werden müssen.
- Keine verteilte Speicherarchitektur in der ersten Version.
- Keine gelernten Komponenten im kritischen Pfad: Retriever, Packer und Reducer sind deterministisch, um die Reproduzierbarkeit von Traces zu gewährleisten. Gelernte Komponenten wie Reranker oder Embedding-Optimierungen würden diese Eigenschaft brechen.
Erste Schritte mit LLM386
Ein einfacher Einstieg ist mit wenigen Befehlen möglich:
git clone
cd llm386
export ANTHROPIC_API_KEY=sk-ant-...
docker compose -f examples/langgraph-agent/docker-compose.yml run --rm agentInnerhalb von fünf Minuten ist ein einfacher Chatbot mit zwei Beispiel-Tools (einem Taschenrechner und einer simulierten Nutzerprofilabfrage) einsatzbereit. Die Konversation bleibt auch nach einem Neustart des Containers erhalten, da der Speicher als Docker-Volume persistiert wird. Das Modell kann sich an vorherige Interaktionen erinnern – allerdings wird diese Erinnerung nicht vom LangGraph-Framework selbst verwaltet, sondern vollständig von LLM386 bereitgestellt.
Für wen lohnt sich der Einsatz?
LLM386 ist besonders interessant für Entwickler und Teams, die folgende Herausforderungen erleben:
- Unübersichtliche Prompts: Wenn die Zusammenstellung des Kontexts immer komplexer wird und niemand mehr nachvollziehen kann, welche Daten tatsächlich an das Modell gesendet werden.
- Fehlende Reproduzierbarkeit: Wenn das Modell in aufeinanderfolgenden Anfragen unterschiedliche Antworten liefert, ohne dass die Gründe dokumentiert sind.
- Modellunabhängigkeit: Wenn der Wechsel zwischen verschiedenen LLMs mit unterschiedlichen Kontextfenstern oder Tokenisierern einfach möglich sein soll. LLM386 abstrahiert diese Details über das
ModelProfile-Interface. - Agenten-Systeme: Für komplexe Agenten, die über mehrere Interaktionen hinweg Zustand verwalten müssen, ohne dass dieser Zustand in den Prompts verloren geht.
Für einfache Chatbot-Demos oder erste Experimente ist LLM386 wahrscheinlich überdimensioniert. Hier reichen oft einfachere Lösungen wie die Kombination von LangChain mit Vektor-Datenbanken.
Die Idee von EMM386 war es, ein komplexes Problem mit einem einfachen, aber genialen Abstraktionsprinzip zu lösen. LLM386 überträgt dieses Prinzip auf eine der zentralen Herausforderungen moderner KI-Systeme – die effiziente Verwaltung von Kontext. Mit deterministischen Komponenten und klarer Zustandsverwaltung bietet die Software einen vielversprechenden Ansatz, um Sprachmodelle zuverlässiger und nachvollziehbarer zu machen. Besonders in Agenten-Systemen, die über längere Zeiträume hinweg konsistente Ergebnisse liefern müssen, könnte LLM386 zum Standardwerkzeug werden.
KI-Zusammenfassung
LLM386, 1990’lardaki EMM386 bellek yönetiminden esinlenen, LLM bağlam pencerelerini optimize eden bir runtime. Nasıl çalışır, kimler kullanmalı ve beş dakikada nasıl denenir?