Fallback Image

RAG für Statamic

Semantische Suche und ein KI-Assistent für eure Inhalte

Wir haben zwei Statamic-Addons entwickelt, die Retrieval-Augmented Generation (RAG) auf CMS-Inhalte legen:

 

In diesem Beitrag zeigen wir, wie beide Addons funktionieren, wie ihr sie konfiguriert und welchen Mehrwert sie für Redaktion und Besucher schaffen.

Warum Embeddings

Klassische Keyword-Suche vergleicht Strings, keine Bedeutung. Ein Beispiel: Eine Besucherin sucht nach „Vertrag kündigen“, eure Seite spricht aber von „Abonnement beenden“, und die Keyword-Suche liefert nichts.

 

Ein Embedding ist eine numerische Vektor-Repräsentation eines Textstücks, platziert in einem Vektorraum, sodass semantisch ähnliche Texte nah beieinander liegen. Statt Wörter zu vergleichen, misst man den Abstand zwischen Vektoren, und damit werden die beiden Formulierungen zu Nachbarn.

Addon 1: ai-entry-embeddings

Das Problem, das es löst

Statamic-Entries sind kein flacher Text. Eine Seite kann ein Bard-Field sein, ein verschachtelter Replicator, ein Grid, Markdown oder ein einfaches Textfeld. Dazu kommt Präsentations-Rauschen wie HTML-Tags, CSS-Klassen, Alignment-Flags und IDs. Gibt man diese Rohdaten direkt in ein Embedding-Modell, sind die Ergebnisse entsprechend schlecht.

So funktioniert die Extraktion

1. Ein Entry wird gespeichert. Statamic feuert das EntrySaved-Event.

 

2. Ein Listener prüft, ob die Collection des Entries konfiguriert ist, und dispatcht einen Queue-Job.

 

3. Eine Extraction-Pipeline durchläuft die konfigurierten Felder und wählt pro Field-Type einen passenden Extractor.

 

4. Jeder Extractor liefert ein oder mehrere ContentChunk-Objekte.

 

5. Die Chunks ersetzen die bisherigen Chunks des Entries in PostgreSQL.

 

6. Ein zweiter Queue-Job erzeugt die Embeddings.

Field-Extractors

Für jeden Field-Type gibt es einen eigenen Extractor, der weiß, wie er sinnvollen Text aus dem Feld herausholt:

  • text / textarea übernehmen den rohen String-Wert.

  • markdown wird zu HTML gerendert und anschließend auf Plain-Text reduziert.

  • bard teilt Fließtext und Sets in separate Chunks auf.

  • replicator erzeugt einen Chunk pro Set, inklusive verschachtelter Felder.

  • grid erzeugt einen Chunk pro Zeile, inklusive verschachtelter Spalten.

  • select übernimmt das oder die menschenlesbaren Options-Label(s).

Was ist ein Chunk?

Ein ContentChunk führt mit sich:

 

  • den Text selbst,
  • den Field-Handle, aus dem er stammt,
  • einen Pfad in Dot-Notation, z. B. page_builder.pricing_block.0,
  • strukturierte Metadaten (Set-Type, Index usw.).

 

Weil jeder Chunk festhält, aus welchem Abschnitt welcher Entries er stammt, kann der Assistent genau den Block benennen, der eine Frage beantwortet hat, nicht nur die Seite.

KI-gestützte Extraktion

Für Felder, die für regelbasiertes Parsing zu unregelmäßig sind, lässt sich ExtractFieldWithAi einsetzen. Die rohen Field-Daten gehen dabei an einen kleinen, günstigen LLM-Agenten. Dieser ist angewiesen, nur menschenlesbaren Text zu extrahieren und Tags, Klassen, Flags und technische Identifier zu ignorieren und niemals zu übersetzen oder zusammenzufassen. Über Structured Output (ein JSON-Schema) ist das Ergebnis immer ein sauberes Array von Chunks.


Die Funktion ist pro Feld oder pro Field-Type opt-in und kostet einen API-Call pro Entry.

Speicherung und Suche

Chunks werden in PostgreSQL mit der pgvector-Extension gespeichert. Die Vektoren liegen in derselben Datenbank. Ihr müsst also keinen separaten Vector-Store betreiben. Zwei Tabellen kommen zum Einsatz:

  • ai_entry_embeddings: eine Zeile pro Entry, mit Status (extracting, generating, generated, failed) und Chunk-Zählern.
  • ai_entry_embedding_chunks: eine Zeile pro Chunk, mit Text, Pfad, Metadaten und einer indexierten vector-Spalte.


Nach der Extraktion verarbeitet GenerateEntryEmbeddingsJob die Chunk-Texte gebündelt über die Embeddings-API des Laravel AI SDK, schreibt die Vektoren zurück und setzt den Entry auf generated. Ist der Provider nicht erreichbar, versucht der Job es mit Backoff erneut und markiert den Entry andernfalls als failed.


Der gesamte Flow ist asynchron und event-getrieben: Eure Redaktion speichert wie gewohnt, das Embedding passiert im Hintergrund auf der Queue. Das Löschen eines Entries räumt seine Embeddings automatisch auf (konfigurierbar).

Konfiguration

Standardmäßig wird nichts eingebettet. Ihr listet Collections und Felder explizit:


Das ist eine bewusste Sicherheitsentscheidung: Sie hält interne Notizen, admin-only Felder und sensible Daten vom AI-Provider fern. Weitere Optionen lassen sich konfigurieren, etwa die Embedding-Dimensionen (Standard 1536, muss zum Modell passen), ob Drafts übersprungen werden sowie Queue-Connection und -Name.


Das Control Panel ergänzt einen Bereich „AI Tools" mit Entry- und Chunk-Zählern plus Status pro Collection, abgesichert über eine Permission.

ℹ️ Mehr zu AI bei byte5

Diese Addons sind ein konkretes Beispiel dafür, wie wir AI in bestehende Projekte bringen. Wenn euch das Thema grundsätzlich interessiert – von RAG über Agenten bis zu produktiven AI-Workflows – findet ihr auf byte5.ai unsere Arbeit rund um AI.

Addon 2: ai-entries-assistant

Ein Chat im Control Panel, der Fragen zu euren Inhalten beantwortet.

So wird eine Frage beantwortet

1. Ein Nutzer sendet eine Nachricht. Sie wird gespeichert und UserMessageAddedToConversation dispatcht.

2. Ein Queue-Listener ruft den EntriesAssistantAgent auf.

 

3. Der Agent ruft immer zuerst ein Similarity-Search-Tool auf: eine pgvector-Nearest-Neighbour-Query, die die Top 25 Chunks zurückgibt.

4. Der Agent formuliert eine Markdown-Antwort, ausschließlich aus diesen Ergebnissen, ohne Zusätzliches zu erfinden. Wird nichts Relevantes gefunden, sagt er das.

5. Die Antwort wird als Assistant-Message gespeichert und ans Frontend gepusht.

 

Das ist der Kern von RAG: Das Modell antwortet nicht aus seinen Trainingsdaten, sondern ruft eure Inhalte ab und argumentiert darauf. Das hält Antworten fundiert, aktuell und spezifisch für eure Website und reduziert Halluzinationen.

Eckdaten

  • Provider-agnostisch: Anthropic, OpenAI, Gemini, Mistral, Ollama und weitere, per Config umschaltbar.

  • Conversational: Vorherige Nachrichten werden dem Modell in jeder Runde erneut mitgegeben, sodass Follow-up-Fragen ihren Kontext behalten.

  • Antworten laufen auf einer Queue und blockieren den Request nicht (die Generierung dauert einige Sekunden).

Echtzeit-Auslieferung

  • Broadcasting über Laravel Echo: Die Antwort wird in dem Moment, in dem sie fertig ist, auf einen privaten Channel conversation.{id} gepusht. Jeder Nutzer kann nur seine eigenen Conversations abonnieren.

  • Polling-Fallback: Wer keinen Websocket-Server betreibt, lässt das Frontend stattdessen pollen, ganz ohne zusätzliche Infrastruktur.

  • Broadcasting ist standardmäßig aus und über ein Env-Flag aktivierbar.

  • Der Assistent liegt unter „AI Tools" im Control Panel, hinter einer eigenen Permission.

Der Business Case

  • Semantische On-Site-Suche: Die Embedding-Schicht kann eine Frontend-Suche antreiben, bei der Besucher finden, was sie meinen, nicht nur, was sie tippen. Relevant für Knowledge-Bases, Dokumentationen, Produktkataloge und große redaktionelle Archive, und das bedeutet weniger „nicht gefunden“-Support-Tickets.

  • Vertrauenswürdiger Self-Service-Support: Der Assistent antwortet nur aus euren Inhalten und verweigert sich, wenn er etwas nicht weiß. So gibt es keine erfundenen Richtlinien oder Preise. Das CMS bleibt die Single Source of Truth, ohne separate Knowledge-Base zum Synchronisieren.

  • Schnellere redaktionelle Arbeit: Fragen wie „Was haben wir zu X veröffentlicht?" oder „Wo erwähnen wir die alten Preise?" liefern die genauen Entries und Abschnitte statt manueller Suche.

  • Geringer Betriebsaufwand: Läuft im bestehenden Stack (Statamic, Laravel, PostgreSQL). pgvector bedeutet keine separate Vektordatenbank zum Lizenzieren, Hosten und Monitoren, und das Embedding läuft auf bestehenden Queue-Workern. Der Provider ist austauschbar, sodass ihr auf Kosten oder Qualität optimieren könnt.

  • Sicher by default: Explizites Allow-Listing von Feldern, Ausschluss von Drafts, Permission-Gating und „antworte nur aus den abgerufenen Inhalten“ sind eingebaut.

 

Beide Addons sind Open Source und auf GitHub verfügbar: ai-entry-embeddings und ai-entries-assistant. Schaut rein, probiert sie aus, und wir freuen uns über Issues, Pull Requests und Feedback.


Hilfe vom Laravel Premier Partner

Unsere Expert:innen für Laravel unterstützen dich.

Kontakt