PHPackages                             xddesigners/silverstripe-rag-assistant - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. xddesigners/silverstripe-rag-assistant

ActiveSilverstripe-vendormodule[Utility &amp; Helpers](/categories/utility)

xddesigners/silverstripe-rag-assistant
======================================

RAG-based referral assistant for SilverStripe: indexes pages via OpenAI embeddings and directs visitors to the correct page.

06↑2400%PHP

Since Jun 18Pushed yesterdayCompare

[ Source](https://github.com/xddesigners/silverstripe-rag-assistant)[ Packagist](https://packagist.org/packages/xddesigners/silverstripe-rag-assistant)[ RSS](/packages/xddesigners-silverstripe-rag-assistant/feed)WikiDiscussions main Synced today

READMEChangelogDependenciesVersions (1)Used By (0)

silverstripe-rag-assistant
==========================

[](#silverstripe-rag-assistant)

A floating AI referral widget for SilverStripe 4/5. It indexes your pages using OpenAI embeddings and directs visitors to the right page — it never answers from its own knowledge, only from your content.

**RAG** = Retrieval-Augmented Generation: embed your content → find the most relevant chunks via cosine similarity → send those as context to the language model.

Requirements
------------

[](#requirements)

- PHP 8.0+
- SilverStripe CMS 4 or 5 (`silverstripe/cms`)
- OpenAI API key
- MySQL (embeddings stored as comma-separated floats in a TEXT column)

Installation
------------

[](#installation)

```
composer require xddesigners/silverstripe-rag-assistant
```

Run a dev/build after installation:

```
vendor/bin/sake dev/build flush=1
```

Assets are exposed automatically via `vendor-expose` during `composer install` or `composer update` — no extra steps required.

Configuration
-------------

[](#configuration)

Set your OpenAI API key in `.env`:

```
OPENAI_API_KEY="sk-..."
```

Override defaults in your project's `_config/myconfig.yml`:

```
XD\RAGAssistant\Controllers\AssistantController:
  chat_model: 'gpt-4o-mini'
  embedding_model: 'text-embedding-3-small'
  embedding_dimensions: 512
  top_k: 5
  system_prompt: >
    You are a referral assistant for example.com. Your task is to refer
    visitors to the correct page. Only use information from the provided
    context. Always answer in Dutch.

XD\RAGAssistant\Tasks\RAGIndexTask:
  chunk_size: 800
  indexed_classes:
    - class: Page
      exclude_classes:
        - RedirectorPage
        - ErrorPage
    - class: SilverStripe\Blog\Model\BlogPost
      date_field: PublishDate
      date_offset: '-12 months'
```

### `indexed_classes` options

[](#indexed_classes-options)

KeyDescription`class`Fully qualified class name to index`exclude_classes`Subclasses to skip (per entry)`extra_fields`Additional DB fields to include in the chunk text`date_field`Filter by this date field`date_offset`Only index records newer than this offset (e.g. `-12 months`)`upcoming_via`Related class to check for upcoming dates`upcoming_via_relation`Foreign key on the related class`upcoming_date_field`Date field on the related class — only indexes records with a future date`limit`Maximum number of records to index for this entry (no limit by default)By default there is no record limit — all pages matching the configured filters are indexed. Use `limit` to cap the number of indexed records per entry, for example to control token costs or indexing time on large datasets:

```
XD\RAGAssistant\Tasks\RAGIndexTask:
  indexed_classes:
    - class: SilverStripe\Blog\Model\BlogPost
      date_field: PublishDate
      date_offset: '-12 months'
      limit: 100

    - class: App\Pages\EventPage
      upcoming_via: App\Models\EventDateTime
      upcoming_via_relation: EventID
      upcoming_date_field: StartDate
      limit: 50
```

### Excluding page classes globally

[](#excluding-page-classes-globally)

Use `excluded_page_classes` to block entire page types from appearing in results — regardless of which `indexed_classes` entry they come from. Subclasses of listed classes are also excluded.

Set it on **both** the task (prevents indexing) and the controller (filters query results immediately, without needing a re-index):

```
XD\RAGAssistant\Tasks\RAGIndexTask:
  excluded_page_classes:
    - App\Pages\ProfilePage
    - App\Pages\AccountPage

XD\RAGAssistant\Controllers\AssistantController:
  excluded_page_classes:
    - App\Pages\ProfilePage
    - App\Pages\AccountPage
```

After changing `excluded_page_classes` on the task, re-run `RAGIndexTask` to remove the excluded pages from the index. The controller-side filter takes effect immediately for pages already in the index.

### Logging

[](#logging)

Request logging is disabled by default. Enable it per project:

```
XD\RAGAssistant\Controllers\AssistantController:
  enable_logging: true
```

Log entries are written to `assets/logs/silverstripe-rag-assistant.log` by default. The `logs/` directory and a `.htaccess` (denying web access) are created automatically on first use.

Paths starting with `assets/` are resolved via SilverStripe's `ASSETS_PATH`. All other paths are relative to `BASE_PATH`. Override via YAML:

```
XD\RAGAssistant\Controllers\AssistantController:
  enable_logging: true
  log_file: 'assets/logs/rag-assistant.log'   # inside assets/ — auto-protected
  # log_file: 'silverstripe-cache/rag.log'    # outside webroot — always safe
```

A typical conversation produces entries like:

```
[RAG] Question — ip:a3f2b1c8 history:1 "is er opleiding in groningen?"
[RAG] Embedding request — model:text-embedding-3-small
[RAG] Embedding response — HTTP:200 312ms
[RAG] Chat request — model:gpt-4o-mini
[RAG] Chat response — HTTP:200 1048ms
[RAG] Answer — sources:1 "Ja, in Groningen worden er opleidingen georganiseerd..."

```

Rate limit hits are logged at `warning` level, API errors at `error` level, and quota exhaustion at `critical` level. IP addresses are hashed (first 8 hex chars of MD5) for privacy.

### Optional module integrations (Blog, Events, etc.)

[](#optional-module-integrations-blog-events-etc)

This module has **no dependency** on Blog, Events, or any other optional SilverStripe module. Classes listed in `indexed_classes` that are not installed are silently skipped during indexing — no errors, no fatal crashes.

To index Blog posts or Event pages, add them to `indexed_classes` in your project YAML **only when those modules are installed**:

```
XD\RAGAssistant\Tasks\RAGIndexTask:
  indexed_classes:
    - class: Page
      exclude_classes:
        - SilverStripe\CMS\Model\RedirectorPage

    # Only add these if the modules are installed:
    - class: SilverStripe\Blog\Model\BlogPost
      date_field: PublishDate
      date_offset: '-12 months'

    - class: App\Pages\EventPage
      upcoming_via: App\Models\EventDateTime
      upcoming_via_relation: EventID
      upcoming_date_field: StartDate
```

Adding the widget to a template
-------------------------------

[](#adding-the-widget-to-a-template)

Add the include to your layout template, typically just before ``:

```

```

Indexing content
----------------

[](#indexing-content)

Run the index task from the CLI or via `/dev/tasks`:

```
vendor/bin/sake dev/tasks/RAGIndexTask
```

This fetches all configured pages, splits them into chunks, embeds each chunk via OpenAI, and stores the results in the `RAGContentChunk` table. A binary cache is written to `silverstripe-cache/rag_chunks.bin` for fast loading on each request.

Re-run the task whenever content changes significantly, or set up a nightly cron job.

Customising the widget appearance
---------------------------------

[](#customising-the-widget-appearance)

Override CSS custom properties in your project stylesheet:

```
:root {
    --rag-primary:      #your-brand-color;
    --rag-primary-dark: #your-brand-color-dark;
    --rag-panel-width:  360px;
    --rag-z-index:      9000;
}
```

Building assets (development only)
----------------------------------

[](#building-assets-development-only)

The `client/dist/` files are pre-built and committed. You only need to run a build if you modify the source files in `client/src/`.

```
yarn install
yarn build    # one-off build
yarn watch    # rebuild on save
```

Requires Node.js 18+.

API endpoint
------------

[](#api-endpoint)

The widget POSTs to `/api/assistant/ask`:

```
{ "question": "..." }
```

Response:

```
{
  "answer": "...",
  "sources": [
    { "title": "Page title", "url": "https://..." }
  ]
}
```

###  Health Score

22

—

LowBetter than 22% of packages

Maintenance65

Regular maintenance activity

Popularity6

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity11

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/e35b3b006174e7015e9711c27bdee08fb707a816a434276c22dcb6327185c35b?d=identicon)[RVXD](/maintainers/RVXD)

---

Top Contributors

[![RVXD](https://avatars.githubusercontent.com/u/1586761?v=4)](https://github.com/RVXD "RVXD (5 commits)")

### Embed Badge

![Health badge](/badges/xddesigners-silverstripe-rag-assistant/health.svg)

```
[![Health](https://phpackages.com/badges/xddesigners-silverstripe-rag-assistant/health.svg)](https://phpackages.com/packages/xddesigners-silverstripe-rag-assistant)
```

###  Alternatives

[hydrat/filament-table-layout-toggle

Filament plugin adding a toggle button to tables, allowing user to switch between Grid and Table layouts.

63105.4k2](/packages/hydrat-filament-table-layout-toggle)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
