Lokale KI im Unternehmen
Ein Mitarbeiter sucht eine Information. Er weiß, dass sie irgendwo dokumentiert ist: in einem Protokoll, einem Handbuch, einer Projektunterlage. Er öffnet den Dateiserver, schaut in drei Ordner, findet nichts. Er sucht per Strg+F nach einem Stichwort, aber das Dokument formuliert es anders. Er fragt den Kollegen, der es auch nicht mehr genau weiß. Am Ende rekonstruiert er die Information aus dem Gedächtnis, mit dem Risiko, dass sie veraltet oder unvollständig ist.
Das ist kein Einzelfall. Das ist Alltag in Unternehmen mit gewachsenen Dokumentenbeständen, und es kostet täglich Stunden, die in echte Arbeit fließen könnten.
Die naheliegende Reaktion: eine KI einsetzen, ChatGPT fragen. Das Problem ist bekannt: ChatGPT kennt die internen Dokumente nicht. Wer sie hochlädt, schickt sensible Unternehmensdaten auf externe Server. Wer Kundendaten, Verträge oder interne Prozesse in ein Cloud-Tool eingibt, bewegt sich rechtlich auf dünnem Eis.
Die Frage, die ich mir gestellt habe: Geht das auch lokal? Ein System, das interne Dokumente versteht, präzise Fragen beantwortet und dabei das Firmennetzwerk nie verlässt?
Die Antwort ist ja. Dieser Artikel beschreibt, wie ich ein solches lokales RAG-System aufgebaut habe, welche Architektur dahintersteckt und was es braucht, um daraus ein produktives System zu machen.
RAG steht für Retrieval-Augmented Generation. Der Name klingt technisch, die Idee dahinter ist einfach.
Ein Sprachmodell antwortet aus seinem Trainingswissen. Es kennt die Welt bis zu einem bestimmten Zeitpunkt, es kennt keine internen Dokumente eines Unternehmens, und es erfindet Antworten, wenn es keine belastbaren Informationen hat. Das nennt sich Halluzination.
RAG löst das strukturell. Statt das Modell alleine antworten zu lassen, wird zuerst in einer Wissensdatenbank nach relevanten Informationen gesucht. Diese Informationen werden dem Modell als Kontext mitgegeben. Das Modell antwortet dann nicht aus seinem Trainingswissen, sondern aus den gefundenen Dokumenten.
Das hat eine entscheidende Konsequenz: Das System kann nur auf Basis von Inhalten antworten, die tatsächlich vorhanden sind. Als ich das fertige System nach dem Wetter in Hamburg gefragt habe, kam die Antwort: „Ich kann keine Informationen über das Wetter finden, da die bereitgestellten Dokumente nichts über dieses Thema enthalten.“ Kein Erfinden, kein Raten. Das ist der Unterschied, der im Unternehmenskontext zählt.
Bevor ich den technischen Aufbau erkläre, muss ich erklären, wie das System Dokumente überhaupt „versteht“. Das ist das Herzstück eines lokalen RAG-Systems und das Konzept, das am häufigsten falsch verstanden wird.
Eine klassische Datenbank sucht nach exakten Treffern. Suche nach „Projektplan“ findet nur Einträge, die genau dieses Wort enthalten. Ein Dokument, das von „Meilensteinplanung“ oder „Terminstruktur“ spricht, wird nicht gefunden, obwohl es inhaltlich das gleiche Thema behandelt.
Eine Vektordatenbank sucht nach Bedeutung. Sie wandelt jeden Text in eine Liste von Zahlen um, einen sogenannten Vektor. Dabei erfasst sie nicht die Wörter selbst, sondern ihre inhaltliche Bedeutung im Kontext. Texte mit ähnlichem Inhalt bekommen Vektoren, die mathematisch nah beieinander liegen. Texte mit unterschiedlichem Inhalt liegen weit auseinander.
Eine konkrete Vorstellung: Der Vektorraum lässt sich wie eine riesige Landkarte vorstellen. Alle Texte über Projektmanagement liegen in einer Region. Alle Texte über KI in einer anderen. Alle Texte über DSGVO in einer dritten. Wenn eine Frage gestellt wird, wird sie auf dieselbe Landkarte verortet, und das System findet die Texte, die in der Nähe liegen, unabhängig davon, welche genauen Wörter verwendet wurden.
Wie ein Vektor entsteht
Das Modell, das Texte in Vektoren umwandelt, heißt Embedding-Modell. In diesem System ist das nomic-embed-text, ein neuronales Netz, das auf riesigen Textmengen trainiert wurde. Das Training optimiert dabei eine einzige Sache: Texte mit ähnlicher Bedeutung sollen ähnliche Vektoren bekommen.
Konkret passiert folgendes, wenn ein Text durch nomic-embed-text läuft: Der Text wird in Tokens zerlegt, also in kleine Einheiten, die das Modell versteht. Das neuronale Netz verarbeitet diese Tokens in mehreren Schichten und berücksichtigt dabei die Beziehungen der Wörter zueinander. Am Ende kollabiert die gesamte Verarbeitung in einen einzigen Vektor mit 768 Zahlen.
Das Modell hat aus dem Training gelernt, dass „Projektchaos“, „Zeitverzug“ und „fehlende Planung“ oft im gleichen Kontext vorkommen. Deshalb liegen ihre Vektoren nah beieinander. Was du nicht beeinflussen kannst: Die 768 Zahlen haben keine einzeln interpretierbare Bedeutung. Der Vektor ist ein emergentes Muster aus dem gesamten Training, keine bewusst designte Repräsentation.
Warum der Winkel verglichen wird, nicht die Zahlen
Hier liegt ein Missverständnis, das sich hartnäckig hält: Eine Vektordatenbank vergleicht nicht einfach die Zahlen zweier Vektoren miteinander. Sie vergleicht den Winkel zwischen ihnen.
Der Grund ist praktisch: Derselbe Text, einmal kurz und einmal ausführlich formuliert, erzeugt Vektoren unterschiedlicher „Länge“ im mathematischen Sinn. Würde man die Zahlen direkt vergleichen, wäre der kurze Text immer weiter entfernt vom langen, obwohl beide dasselbe bedeuten. Der Winkel zwischen zwei Vektoren ist dagegen unabhängig von ihrer Länge. Zwei Vektoren, die in die gleiche Richtung zeigen, haben einen Winkel von null Grad, also maximale Ähnlichkeit, egal wie lang sie sind.
Die Methode dahinter heißt Cosine Similarity. Sie berechnet den Kosinus des Winkels zwischen zwei Vektoren. Das Ergebnis liegt immer zwischen null und eins. Je näher an eins, desto ähnlicher der Inhalt. Das ist auch der Grund, warum beim Anlegen der Qdrant Collection „Cosine“ als Distance-Metrik gewählt wurde, nicht „Euclidean“ oder „Dot Product“. Für Textsemantik ist Cosine die richtige Wahl.
Kein Tutorial nachgebaut, kein vorgefertigter Stack übernommen. Jede Komponente wurde bewusst ausgewählt.
Das System besteht aus zwei voneinander getrennten Pipelines: Ingestion und Retrieval.
Ingestion: Wie Dokumente ins lokale RAG-System kommen
Ein neues Dokument wird in den Eingangsordner gelegt. n8n erkennt die Datei, extrahiert den Text und schickt ihn an einen KI-Agenten, der mit Llama 3.1 8B läuft.
Hier war eine der wichtigsten Architekturentscheidungen: Wie sollen Dokumente in Wissenseinheiten zerlegt werden?
Der einfache Ansatz ist blindes Chunking: Text mechanisch in gleich große Stücke schneiden. Das ist schnell, produziert aber Einheiten, die mitten im Gedanken abbrechen und bei der späteren Suche schlechte Ergebnisse liefern.
Der gewählte Ansatz ist intelligentes Chunking: Der KI-Agent liest das Dokument vollständig, versteht den Inhalt und extrahiert semantisch vollständige Wissenseinheiten. Jede Einheit deckt genau ein Thema ab und ist ohne zusätzlichen Kontext verständlich. Das Modell entscheidet selbst, wie viele Einheiten ein Dokument enthält, auf Basis des Inhalts, nicht auf Basis von Zeichenanzahl.
Der Nachteil: Diese Methode ist langsamer als blindes Chunking, weil das Modell jedes Dokument vollständig verarbeiten muss. Für einen Prototypen mit wenigen Dutzend Dokumenten ist das kein Problem. Bei tausenden Dokumenten braucht es eine hybride Strategie.
Jede Wissenseinheit bekommt eine ID, die aus dem Inhalt berechnet wird. Gleicher Inhalt ergibt immer gleiche ID. Das ermöglicht Deduplizierung: Wird ein Dokument ein zweites Mal verarbeitet, überschreibt Qdrant den bestehenden Eintrag statt einen neuen anzulegen.
Dann folgen zwei Schritte: nomic-embed-text wandelt den Inhalt in einen Vektor um, und Qdrant speichert Vektor und Payload gemeinsam.
Retrieval: Wie das DSGVO-konforme KI-System Fragen beantwortet
Eine Frage kommt im Chat-Interface an. Pipelines empfängt sie, wandelt sie mit nomic-embed-text in einen Vektor um und sucht in Qdrant nach den fünf ähnlichsten Einträgen. Diese Zahl ist eine Designentscheidung: Fünf Einträge liefern in den meisten Fällen genug Kontext, ohne den Prompt zu überladen. Sie ist anpassbar.
Aus den gefundenen Einträgen baut Pipelines einen Kontext auf: Quelldatei und Inhalt jeder Wissenseinheit. Dieser Kontext wird zusammen mit der originalen Frage als Prompt an Llama 3.1 8B übergeben. Das Modell antwortet ausschließlich auf Basis dieses Kontexts.
Eine wichtige Einschränkung: Dieser Prozess dauert mehrere Sekunden. Embedding, Datenbanksuche, Kontextaufbau und Modell-Inference laufen sequenziell. Das ist deutlich langsamer als ein direktes Gespräch mit einem Sprachmodell. Für einen Wissensassistenten, der präzise Antworten aus Dokumenten liefert, ist das akzeptabel. Für Echtzeit-Anwendungen braucht es eine andere Architektur.
Diese Punkte gehören in diesen Artikel, weil sie zeigen, wo die echten Hürden beim Aufbau eines lokalen RAG-Systems liegen.
n8n und Dateizugriff. Ab Version 2.0 beschränkt n8n den Dateizugriff standardmäßig auf einen internen Ordner. Der gemountete Docker-Ordner war nicht erreichbar, ohne eine Umgebungsvariable explizit zu setzen. Außerdem blockiert n8n Node.js-Standardmodule wie fs und crypto im Code-Node. Die Hash-Berechnung für die Eintrags-IDs musste als eigene JavaScript-Funktion implementiert werden.
Qdrant Named Vectors und n8n. Der eingebaute Qdrant-Node in n8n unterstützt keine Named Vectors, die bei Hybrid Collections zwingend erforderlich sind. Das ist ein bekanntes offenes Issue. Die Lösung waren direkte HTTP-Requests an die Qdrant REST-API statt des eingebauten Nodes.
Structured Output Parser mit kleineren Modellen. Der Output Parser in n8n soll JSON-Output vom Modell erzwingen. Mit Llama 3.1 8B funktioniert das nicht zuverlässig. Die pragmatische Lösung: JSON über den System-Prompt anfordern und den Output per Code-Block parsen.
Sonderzeichen im HTTP-Body. Wenn der extrahierte Text Zeilenumbrüche oder Anführungszeichen enthält, bricht der HTTP-Request mit einem JSON-Fehler ab. Die Lösung ist JSON.stringify() in den Expressions des HTTP-Request-Nodes.
Dieser Prototyp zeigt das Prinzip und beweist, dass es funktioniert. Für den produktiven Einsatz in einem Unternehmen fehlen noch mehrere Bausteine.
Zugriffskontrolle ist der kritischste fehlende Baustein. Nicht jeder Mitarbeiter darf alle Dokumente sehen. Role-based Access muss von Anfang an in die Architektur eingeplant werden, nicht nachträglich.
OCR für gescannte Dokumente erweitert den Anwendungsbereich erheblich. Viele Unternehmen haben wichtige Informationen in eingescannten PDFs. Tesseract als lokales OCR-Tool kann in die Ingestion-Pipeline integriert werden.
Update-Logik für veränderte Dokumente ist noch nicht vollständig implementiert. Der Hash-basierte ID-Ansatz ist die Grundlage dafür, aber wenn ein Dokument inhaltlich aktualisiert wird, muss die alte Version gezielt aus der Vektordatenbank entfernt werden.
Hybrid Search ist konfiguriert, aber noch nicht vollständig aktiv. Die Kombination aus semantischer Suche und Keyword-Suche in Qdrant würde die Trefferqualität bei spezifischen Fachbegriffen weiter verbessern.
Das System läuft auf einem MacBook Pro. Für den Einsatz im Unternehmen braucht es einen dedizierten Server im Firmennetzwerk, auf dem alle Komponenten laufen. Mitarbeiter greifen dann über den Browser auf das Chat-Interface zu, ohne Installation, ohne Cloud-Account und ohne dass Unternehmensdaten das Netzwerk verlassen.
Die entscheidenden Fragen vor dem Einsatz sind nicht technischer Natur. Sie sind strategisch: Wie sensibel sind die Daten? Welche Dokumente sollen ins System? Wie viele Mitarbeiter nutzen es gleichzeitig? Welche Anforderungen gibt es an Antwortqualität und Geschwindigkeit? Erst wenn diese Fragen beantwortet sind, macht eine Architekturentscheidung Sinn.
Viele Unternehmen kämpfen mit genau diesen Problemen und das oft ohne es bewusst zu erkennen.
Gemeinsam lässt sich schnell herausfinden, wo Automatisierung und KI konkret Mehrwert schaffen können.