Ein KI-Chat für Ihre Website, der Kundenfragen schnell und zuverlässig beantwortet
Besucher fragen in eigenen Worten und erhalten in Sekunden eine Antwort aus Ihrer eigenen Doku, mit Links auf die genauen Seiten. So funktioniert es.

TL;DR
- Ein Besucher tippt eine Frage in eigenen Worten ein und erhält in wenigen Sekunden eine kurze Antwort, mit Links auf genau die Seiten, aus denen sie stammt.
- Der Chat antwortet nur aus Ihrer eigenen Dokumentation, Ihrem Blog und einem von Hand geprüften FAQ. Steht die Antwort dort nicht, sagt er das, statt zu raten.
- So funktioniert es: Ihre Inhalte werden in kleine Abschnitte (Chunks) zerlegt, jeder Chunk wird in ein Embedding umgewandelt, damit er sich nach Bedeutung finden lässt, und für jede Frage gehen die besten Chunks an ein KI-Modell, das die Antwort allein aus diesen Chunks schreibt.
- Es ist günstig, und die Rechnung bleibt begrenzt: rund $0.0004 pro Frage, ein Tagesbudget und eine harte Obergrenze von $20 pro Monat.
- Die zweite Hälfte des Beitrags ist die Technik: ein kleiner Service, ein Modellaufruf pro Frage, eine Suche, die bei 92 % der Testfragen die richtige Quelle unter die ersten fünf Treffer brachte, und Quellenlinks, die das Modell nicht erfinden kann.
Inhalt
- Was der Besucher davon hat
- So funktioniert es, einfach erklärt
- Unter der Haube: so wird es gebaut
- Wofür ein Doku-Chat da ist, und was er nie tun darf
- Die Architektur: ein Service, ein Aufruf, keine Datenbank
- Retrieval: hybride Suche, und warum Stichwörter weniger Gewicht bekommen
- Ein Aufruf, und ein Prompt, den die Frage nicht übernehmen kann
- Quellen, die das Modell nicht erfinden kann
- Was es kostet, und wie die Rechnung begrenzt bleibt
- Wenn etwas ausfällt, verschwindet der Chat
- Die Wissensbasis wird mit jedem Release ausgeliefert
- Das Wichtigste in Kürze
Was der Besucher davon hat
Jemand liest Ihre Produktseite und hat eine konkrete Frage. Funktioniert es ohne Internetzugang? Läuft es auf unserem Betriebssystem? Was kostet es für zehn Server? Die Antwort steht irgendwo in Ihrer Dokumentation, aber um sie zu finden, muss man die Seite verlassen, den richtigen Suchbegriff erraten und drei Seiten lesen, die fast davon handeln. Viele Besucher tun sich das nicht an. Sie gehen.
Ein KI-Chat auf der Website verändert diesen Moment. Der Besucher stellt die Frage so, wie er eine Kollegin fragen würde, und wenige Sekunden später steht da eine kurze Antwort, in seiner Sprache, mit Links auf die Seiten, aus denen sie stammt (Abbildung 1). Decken Ihre Inhalte die Frage nicht ab, sagt der Chat das offen. Er erfindet keine Antwort, und er greift nicht auf das zurück, was das Modell zufällig allgemein über das Thema weiss.

Schnell und zuverlässig sind die zwei Versprechen, und der Rest dieses Beitrags handelt davon, beide zu halten. Schnell ist das leichtere: Eine Antwort kommt nach einer bis fünf Sekunden. Zuverlässig ist der Teil, der Nachdenken braucht. Jede Antwort stammt aus Ihren eigenen, geprüften Inhalten, jeder Link zeigt auf eine Seite, aus der die Antwort wirklich stammt, und ein öffentliches Textfeld kann nie zu einer offenen Rechnung werden.
So funktioniert es, einfach erklärt
Die Technik hat einen Namen: Retrieval-Augmented Generation, kurz RAG. Die Idee dahinter ist einfach: Bevor die KI etwas schreibt, werden die wenigen Passagen Ihrer eigenen Inhalte nachgeschlagen, die die Frage beantworten, und die KI schreibt nur aus diesen. Abbildung 2 zeigt den ganzen Ablauf auf einer Seite.

Ein Teil davon geschieht im Voraus, bevor überhaupt jemand fragt:
- Das Wissen sammeln. Zusammentragen, was der Chat wissen darf: Ihre Dokumentation, Ihr Blog und ein kurzes FAQ, das ein Mensch geschrieben und geprüft hat. Sonst kommt nichts hinein, und genau das hält die Antworten bei Ihnen.
- In Chunks teilen. Eine ganze Seite ist für eine Frage zu viel, ein einzelner Satz zu wenig. Also wird jede Seite in Chunks von etwa einem Abschnitt zerlegt, je ein paar Absätze, und jeder Chunk merkt sich, von welcher Seite und unter welcher Überschrift er stammt. Das macht die Quellenlinks später überhaupt erst möglich.
- Jeden Chunk in ein Embedding umwandeln. Mehr dazu gleich unten. Kurz gesagt: Ein Embedding-Modell macht aus jedem Chunk eine Liste von Zahlen, die beschreibt, was der Chunk bedeutet.
- Das Ergebnis als durchsuchbare Bibliothek ablegen. Alle Chunks mit ihren Zahlen, bereit für die Suche. Die Bibliothek wird automatisch neu gebaut, sobald sich die Website ändert, damit der Chat nie weniger, aber auch nie mehr weiss als die Site.
Dann, für jede Frage:
- Der Besucher fragt. Die Frage erhält ihr eigenes Embedding, auf dieselbe Weise erzeugt.
- Die relevanten Chunks finden. Der Chat sucht die Chunks, deren Bedeutung der Frage am nächsten liegt, dazu eine klassische Stichwortsuche für exakte Begriffe wie Produktnamen und Versionsnummern. Die besten acht Chunks bleiben übrig.
- Die KI schreibt die Antwort. Die Frage und diese acht Chunks gehen an ein Sprachmodell, mit einer strikten Anweisung: Antworte nur aus diesen Chunks, und wenn sie die Antwort nicht enthalten, sag es.
- Prüfen, dann antworten. Bevor etwas beim Besucher ankommt, prüft der Chat, dass jede Quelle, die das Modell nennt, einer der Chunks ist, die es tatsächlich bekommen hat, und macht daraus Links. Dann erscheint die Antwort.
Was ist ein Embedding?
Ein Embedding ist eine Art, Text auf eine Landkarte der Bedeutung zu legen. Ein spezielles KI-Modell liest ein Stück Text und gibt eine lange Liste von Zahlen zurück, seine Koordinaten auf dieser Karte. Texte, die Ähnliches bedeuten, landen nah beieinander, auch wenn sie völlig andere Wörter verwenden.
Genau das fehlt einer Website-Suche meistens. Ein Besucher fragt «Funktioniert es ohne Internetzugang?», während Ihre Dokumentation von «Air-gapped-Installation» spricht. Die beiden teilen kein einziges Wort, also verfehlt eine Stichwortsuche die Seite. Auf der Bedeutungskarte liegen sie direkt nebeneinander, also findet der Chat sie (Abbildung 3).

Die Karte in der Abbildung hat zwei Dimensionen, damit sie auf einen Bildschirm passt. Ein echtes Embedding hat rund tausend, aber «nah» bedeutet dasselbe: Der Chat misst den Abstand zwischen der Frage und jedem Chunk und nimmt die nächstgelegenen.
Unter der Haube: so wird es gebaut
Das ist die ganze Idee. Der Rest dieses Beitrags richtet sich an alle, die so etwas bauen: die Designentscheide, die Zahlen, die wir gemessen haben, und die Teile, die den Chat zuverlässig machen statt bloss beeindruckend.
Vor Jahren haben wir in einer fünfteiligen Serie einen Chatbot auf Azure gebaut. Intents, Utterances, ein Dialogbaum: viel Maschinerie, um eine recht kleine Menge an Fragen zu beantworten. Diesen Oktober haben wir wieder einen gebaut, einen Chat für eine Produktdokumentation, und die Form des Problems hatte sich komplett verändert. Der Sprachteil ist heute der günstige Teil. Nachdenken braucht alles drumherum: was das Modell wissen darf, wie man verhindert, dass es eine Quelle erfindet, und wie man sicherstellt, dass ein Chat-Widget auf einer öffentlichen Seite nie zu einer offenen Rechnung wird.
Hier ist das Muster, bei dem wir gelandet sind, mit den Zahlen, die wir unterwegs gemessen haben. Nichts davon ist an eine bestimmte Site gebunden: Es passt zu jeder Dokumentations-, Helpcenter- oder Produkt-Site mit einigen hundert bis einigen tausend Seiten.
Wofür ein Doku-Chat da ist, und was er nie tun darf
Die Vorgabe, die vor der ersten Zeile Code feststehen muss, ist strikt: Der Chat antwortet nur aus Ihrer eigenen Wissensbasis. Das heisst aus dem kuratierten FAQ, der Dokumentation und dem Blog. Steht die Antwort dort nicht, sagt er das. Er greift nicht auf das zurück, was das Modell zufällig allgemein über das Thema weiss, denn auf einer Produkt-Site ist eine selbstbewusste Antwort, die nicht von Ihnen stammt, schlimmer als keine Antwort.
Daraus folgen zwei kleinere Regeln. Der Chat sollte die Sprachen sprechen, die die Site spricht (unserer musste Englisch und Deutsch können). Und wenn irgendetwas dahinter nicht verfügbar ist, sollte der Chat einfach nicht da sein, statt auf einer Marketingseite eine Fehlermeldung zu zeigen.
Die Architektur: ein Service, ein Aufruf, keine Datenbank
Abbildung 4 zeigt das ganze System. Die Site selbst ist statisch und wird von Cloudflare ausgeliefert. Ein kleiner Cloudflare Worker sitzt auf /api/* derselben Domain und leitet genau die Chat-Endpunkte an einen Go-Service weiter, der auf einem kleinen k3s-Cluster läuft und nur über einen Cloudflare-Tunnel erreichbar ist. Weil die API auf demselben Origin liegt wie die Seite, braucht es überhaupt keine CORS-Konfiguration.

Ein paar Entscheide prägen alles andere:
- Ein Modellaufruf pro Frage. Keine Tools, keine Agenten-Schleife. Der Service sucht, ruft Claude Haiku einmal mit einem Structured-Output-Schema auf, prüft das Ergebnis und antwortet. Jede Frage hat dieselben, planbaren Kosten und dieselbe Latenz.
- Kein Gesprächsgedächtnis auf dem Server. Der Browser behält die letzten drei Frage-Antwort-Paare im
sessionStorageund schickt sie mit, sodass «und unter Windows?» weiterhin Sinn ergibt. Der Server bleibt zustandslos und speichert keine Session. - Die Wissensbasis steckt im Image. Mehr dazu weiter unten, aber es bedeutet: keine Datenbank, die man betreiben, sichern oder absichern müsste.
- Triviale Eingaben beantwortet das Widget selbst. Befehle, Aliase, Stichwörter und Tippfehler kurzer Eingaben werden im Browser ohne Kosten erkannt. Nur echte Freitextfragen gehen ans Backend.
Retrieval: hybride Suche, und warum Stichwörter weniger Gewicht bekommen
Der naheliegende erste Entwurf packt die ganze Wissensbasis in den Prompt. Für eine kleine Site ist das eine verlockende Abkürzung, und wir haben sie aus zwei Gründen verworfen: Die Kosten jeder Frage wachsen mit jeder Seite, die Sie veröffentlichen, und das Modell bekommt keinen Hinweis darauf, welche Seiten die Frage wirklich beantworten, was ehrliche Quellenlinks viel schwieriger macht.
Also arbeitet der Chat mit Retrieval-Augmented Generation (RAG). Die Seiten werden an jeder H2-Überschrift in Chunks geteilt, rund 1'600 Zeichen mit etwas Überlappung, ohne Boilerplate. Auf unserem Testkorpus ergab das 2'680 Chunks, jeder mit seiner URL samt Überschriften-Anker, seinem Titel, seiner Sprache und seinem Typ. Jeder Chunk wird mit bge-m3 eingebettet, einem mehrsprachigen Embedding-Modell, das bequem auf einer Consumer-GPU läuft (bei uns eine GTX 1080).
Zur Fragezeit führt der Service zwei Suchen über dieselben Chunks parallel aus: eine Vektorsuche auf der eingebetteten Frage (im Median etwa 45 ms) und eine klassische BM25-Stichwortsuche. Die beiden Rankings werden mit Reciprocal Rank Fusion zusammengeführt. Der interessante Teil ist die Gewichtung. Abbildung 5 zeigt, was wir auf 24 repräsentativen Fragen gemessen haben.

Stichwörter allein fanden die richtige Quelle bei zwei Dritteln der Fragen unter den ersten fünf. Beides gleich gewichtet zu fusionieren half, aber der klare Gewinner gab dem Vektor-Ranking das Gewicht 1.0 und BM25 nur 0.3: 92 % in den Top 5, 96 % in den Top 8. BM25 verdient seinen Platz trotzdem. Es findet exakte Produktbegriffe und Versionsangaben, die Embeddings verwischen, und es ist die Rückfallebene, auf die der Chat zurückgreift, wenn der Embedding-Service langsam oder ausgefallen ist.
Zwei Dinge, die man besser weglässt:
- Eine Vektordatenbank. 2'680 Vektoren mit 1'024 Dimensionen sind etwa 11 MB. Der Service lädt sie in den Speicher und rechnet die Kosinus-Ähnlichkeit per Brute Force, was deutlich unter einer Millisekunde dauert. Eine Indexstruktur oder ein gehosteter Vector Store brächte einen Netzwerk-Hop, eine Rechnung und eine betriebliche Abhängigkeit für einen Korpus, der vielfach in den RAM passt.
- Ein Reranker. Wir haben einen über die Top-30-Kandidaten getestet. Auf unserer GPU kostete er im Median 4 Sekunden und verbesserte die Top-8-Trefferquote überhaupt nicht. Lassen Sie ihn weg, bis schnellere Hardware und ein messbarer Gewinn ihn rechtfertigen.
Ein Aufruf, und ein Prompt, den die Frage nicht übernehmen kann
Die acht besten Chunks, etwa 3'000 Input-Tokens, gehen in einen einzigen Messages-Aufruf. Die Reihenfolge des Prompts ist bewusst gewählt, und Abbildung 6 verfolgt eine Frage hindurch.

Der System-Block enthält die Regeln: nur aus den gelieferten Chunks antworten; wenn sie die Antwort nicht enthalten, das sagen und answered auf false setzen; in der Sprache der Frage antworten; kurz bleiben; Chunk-IDs zitieren. Weil die Regeln bei jeder Anfrage Byte für Byte identisch sind, sind sie der eine Teil des Prompts, der sich für das Caching lohnt. Chunks und Frage ändern sich jedes Mal, sie zu cachen würde nur den Schreibaufschlag kosten.
Danach kommen die Chunks, jeder in einem abgegrenzten Block mit kurzer ID, URL und Überschrift. Dann das bisherige Gespräch. Dann die Frage des Besuchers, zuletzt. Sowohl die Frage als auch das Gespräch sind ausdrücklich als Daten markiert, nicht als Anweisungen, und das Gespräch wird nie als echte Assistant-Turns geschickt. Dem Browser lässt sich alles Mögliche als «Verlauf» unterschieben, auch eine gefälschte frühere Antwort voller Anweisungen. Sie in einen Datenblock zu setzen, statt sie mit der eigenen Stimme des Modells sprechen zu lassen, verhindert, dass ein gefälschter Turn die Kontrolle übernimmt.
Quellen, die das Modell nicht erfinden kann
Diesen Schritt würden wir in jedes RAG-System mitnehmen. Das Modell soll Chunk-IDs zitieren, nie URLs. Wenn die Antwort zurückkommt, behält der Server eine zitierte ID nur, wenn sie zu den Chunks gehört, die für genau diese Anfrage gesucht wurden, ordnet ihr die öffentliche URL aus dem Index zu und verwirft alles andere. Überlebt keine zitierte Quelle, wird die Antwort als nicht beantwortet markiert.
Das ist ein strengerer Test als «die URL existiert auf der Site». Ein plausibel aussehender Link, den sich das Modell ausgedacht hat, oder eine echte Seite, die es gar nicht gesehen hat, kann den Besucher nicht erreichen. Jeder Link in einer Antwort zeigt auf Text, den das Modell vor sich hatte.
Die Ausgabe selbst kommt als strukturiertes JSON zurück (answer, answered, sources), über die Structured-Output-Unterstützung der API statt über eine vorausgefüllte Antwort, und eine Verweigerung oder ein Parse-Fehler wird zu einer kurzen, freundlichen Ersatzantwort statt zu einem kaputten Panel.
Was es kostet, und wie die Rechnung begrenzt bleibt
Wir haben echte Aufrufe mit Claude Haiku 5.5 gemessen, bevor wir uns dafür entschieden haben. Eine Frage mit warmem Prompt-Cache kostet etwa vier Hundertstel eines Cents, und die Antworten kamen nach 1.4 bis 4.6 Sekunden. Abbildung 7 stellt das neben die zwei Grenzen, die die Gesamtkosten deckeln.

Ein öffentliches Textfeld, das einen kostenpflichtigen API-Aufruf auslöst, braucht Grenzen, die nicht davon abhängen, dass jemand an sie denkt. Legen Sie sie in Schichten an:
- Vor jedem Modellaufruf prüft ein Guard die Grösse der Anfrage, die Länge der Frage (500 Zeichen), die Form des Verlaufs und ein Rate-Limit pro Besucher. Nehmen Sie die Besucheradresse von Ihrer Edge (in diesem Aufbau Cloudflare), nicht aus einem Header, den der Client setzen könnte, und verwenden Sie sie nur zum Zählen: hashen, nie loggen, nie speichern.
- Ein Tagesbudget in US-Dollar, berechnet aus dem tatsächlichen Token-Verbrauch jeder Antwort mal den Preisen des Modells, sodass ein Modellwechsel die Obergrenze nicht still verschieben kann. Ist es aufgebraucht, pausiert der Chat bis Mitternacht UTC.
- Eine harte Monatsgrenze, durchgesetzt vom API-Anbieter auf einem Workspace und einem Key, die für nichts anderes verwendet werden. Selbst ein geleakter Key könnte nicht mehr als $20 pro Monat kosten, und er lässt sich widerrufen, ohne etwas anderes anzufassen.
Wenn etwas ausfällt, verschwindet der Chat
Beim Laden der Seite fragt das Widget einen günstigen Status-Endpunkt, ob der Chat bereit ist. Erst dann erscheint der Launcher. Sind der Service oder der Tunnel ausgefallen oder ist das Tagesbudget aufgebraucht, sieht der Besucher gar keinen Chat: keine Fehlermeldung, kein springendes Layout. Die Site selbst wird von der Edge ausgeliefert und bleibt so oder so erreichbar.
Ein eingeschränktes Retrieval ist ein anderer Fall. Ist der Embedding-Service langsam oder nicht verfügbar, antwortet der Chat allein mit der Stichwortsuche weiter. Das Widget auszublenden bleibt dem Fall vorbehalten, in dem es wirklich nicht antworten kann.
Die Wissensbasis wird mit jedem Release ausgeliefert
Halten Sie den Chat im selben Repository wie die Website. Das erwies sich als der nützlichste Entscheid von allen. Bei jedem Website-Release baut eine einzige Pipeline die Site, baut daraus die Wissensbasis aus genau diesem Build, bettet nur neue oder geänderte Chunks ein, backt alles ins Chat-Image und rollt Site und Chat gemeinsam aus.
Daraus ergeben sich drei Eigenschaften:
- Jeder Quellenlink existiert per Konstruktion auf der Live-Site, weil der Index aus genau den Seiten erzeugt wurde, die ausgerollt werden. Eine entfernte Seite verlässt die Wissensbasis im selben Release.
- Das Einbetten ist inkrementell. Vektoren werden über einen Hash aus Chunk-Text und Modell-ID gecacht. Bei einem typischen Release sind nur ein paar Dutzend von rund 2'600 Chunks neu, und ihr Einbetten dauert Sekunden statt der über acht Minuten eines vollen Durchlaufs.
- Was der Chat weiss, ändert sich nur per geprüftem Merge Request. Die handgeschriebenen FAQ-Einträge sind Markdown-Dateien im Repo, jede mit dem Vermerk, wer sie wann geprüft hat. Der Chat gibt sie fast wörtlich wieder, also bekommen sie wie jede andere Änderung einen menschlichen Reviewer. Etwa zehn bis fünfundzwanzig Minuten nach dem Merge weiss es der Chat.
Es ist verlockend, den Chat zur Laufzeit zusätzlich eine interne Wissensbasis abfragen zu lassen, denn dort liegt oft der grösste Teil des Wissens eines Teams. Tun Sie es nicht. Ein interner Speicher enthält vertrauliches Material, und ein öffentlicher Lesezugriff darauf bringt Sie ein einziges falsches Sichtbarkeits-Flag von einem Datenleck entfernt. Öffentliche Antworten sollten aus öffentlichen Seiten kommen, im Repo geprüft, und aus nichts anderem.
Das Wichtigste in Kürze
- Beginnen Sie mit dem, was der Chat nie tun darf. «Nur unsere eigenen Inhalte, nie raten» hat das Retrieval-Design, den Prompt und die Quellenprüfung bestimmt.
- Messen Sie die Fusionsgewichte. Gleich gewichtete hybride Suche liess in unserem Test neun Prozentpunkte Trefferquote liegen.
- Kleine Korpora brauchen keine Vektordatenbank. Laden Sie die Vektoren in den Speicher und halten Sie die Zahl der beweglichen Teile klein.
- Lassen Sie das Modell IDs zitieren und den Code die Links erzeugen. Das ist der günstigste Weg, erfundene Quellen unmöglich statt bloss unwahrscheinlich zu machen.
- Legen Sie die Kostengrenze dorthin, wo Sie sie nicht vergessen können. Ein eigener, gedeckelter API-Key ist die Absicherung, die auch dann hält, wenn Ihre eigenen Zähler zurückgesetzt werden.
- Liefern Sie das Wissen mit der Site aus. Eine Pipeline, ein Release, und der Chat kann nie auf eine Seite zeigen, die es nicht gibt.
Wenn Sie etwas Ähnliches bauen und sich austauschen möchten, schreiben Sie uns an info@opensight.ch.