PHPackages                             moneo/laravel-rag - 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. moneo/laravel-rag

ActiveLibrary

moneo/laravel-rag
=================

A complete, driver-based RAG pipeline for Laravel

v1.0.0(1mo ago)10MITPHPPHP ^8.2CI passing

Since Mar 29Pushed 1mo agoCompare

[ Source](https://github.com/moneo/laravel-rag)[ Packagist](https://packagist.org/packages/moneo/laravel-rag)[ RSS](/packages/moneo-laravel-rag/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (13)Versions (7)Used By (0)

Laravel RAG
===========

[](#laravel-rag)

[![CI](https://github.com/moneo/laravel-rag/actions/workflows/ci.yml/badge.svg)](https://github.com/moneo/laravel-rag/actions/workflows/ci.yml)[![codecov](https://camo.githubusercontent.com/38f0279f246354ca7366021207720ba365f3bc6f05c252ccb7b0ccff381b1f6f/68747470733a2f2f636f6465636f762e696f2f67682f6d6f6e656f2f6c61726176656c2d7261672f6272616e63682f6d61696e2f67726170682f62616467652e737667)](https://codecov.io/gh/moneo/laravel-rag)[![PHPStan Level 9](https://camo.githubusercontent.com/1bc07920f0d36e55c17e1d38b1caa132cc605f51a82b388c962870b9a747b898/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c253230392d627269676874677265656e2e737667)](https://phpstan.org/)[![Infection MSI](https://camo.githubusercontent.com/b07a164c27dc0587492b4b3682859fee14bf870e318b8833f2e498c9cf69464d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f496e66656374696f6e2532304d53492d25453225383925413538352532352d627269676874677265656e2e737667)](https://infection.github.io/)[![PHP 8.2+](https://camo.githubusercontent.com/0f16581d1180dbfd4c0e13166ec1267d4ad2f2fab8281ea6d6b284cf5c65d921/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e322532422d626c75652e737667)](https://www.php.net/)[![Laravel 11+](https://camo.githubusercontent.com/5c5576721d3a9233c218b8d6db0f2ea626aee0ab821ffd60b59a9e1d0e942daa/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31312532422d7265642e737667)](https://laravel.com/)[![License: MIT](https://camo.githubusercontent.com/fdf2982b9f5d7489dcf44570e714e3a15fce6253e0cc6b5aa61a075aac2ff71b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f772e737667)](LICENSE)

A complete, driver-based RAG (Retrieval-Augmented Generation) pipeline for Laravel. Built on [Prism PHP](https://github.com/prism-php/prism) for provider-agnostic LLM and embedding support.

Features
--------

[](#features)

- **Driver-based vector stores** — pgvector (production) and sqlite-vec (local dev), swappable via `.env`
- **Blueprint macros** — `$table->vector()`, `$table->vectorIndex()` feel native to Laravel
- **Model traits** — `HasVectorSearch` and `AutoEmbeds` for zero-boilerplate integration
- **Embedding cache** — SHA-256 deduplication reduces API costs by 60-80%
- **Chunking strategies** — Character, Sentence, Markdown, and Semantic chunkers
- **Fluent RAG pipeline** — `Rag::from(Document::class)->ask('question')`
- **Streaming SSE** — Real-time response streaming via Server-Sent Events
- **Agentic RAG** — Iterative retrieval with sufficiency evaluation
- **Hybrid search** — Reciprocal Rank Fusion (RRF) combining semantic + full-text
- **LLM re-ranking** — Score and re-order chunks by relevance
- **Conversation memory** — Threaded conversations with automatic context summarization
- **RAG Evals** — First Laravel-native evaluation framework (Faithfulness, Relevancy, Context Recall)
- **MCP Server** — Expose your RAG as MCP tools for Claude Desktop, Cursor, etc.
- **Artisan commands** — `rag:index`, `rag:test`, `rag:estimate`, `rag:eval`, `rag:mcp-serve`
- **DevTools** — Debugbar collector and Telescope watcher
- **Livewire component** — Drop-in `` with streaming and sources
- **Filament plugin** — Admin panel for documents, embeddings, and interactive testing

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

[](#requirements)

- PHP 8.2+
- Laravel 11+
- [Prism PHP](https://github.com/prism-php/prism) ^0.100

**Vector store (choose one):**

- **pgvector** (recommended for production) — PostgreSQL + [pgvector extension](https://github.com/pgvector/pgvector)
- **sqlite-vec** (local dev, Docker/Linux only) — [sqlite-vec](https://github.com/asg017/sqlite-vec)

> **Note:** sqlite-vec requires PHP compiled with SQLite extension loading support. macOS PHP (Herd, Homebrew) does **not** support this. Use Docker, Laravel Sail, or switch to pgvector on macOS.

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

[](#installation)

```
composer require moneo/laravel-rag
```

Publish the config:

```
php artisan vendor:publish --tag=rag-config
```

Run migrations:

```
php artisan vendor:publish --tag=rag-migrations
php artisan migrate
```

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

[](#configuration)

```
# Vector store: pgvector (production) or sqlite-vec (local dev)
RAG_VECTOR_STORE=pgvector

# Embedding provider (via Prism)
RAG_EMBEDDING_DRIVER=openai
RAG_EMBEDDING_MODEL=text-embedding-3-small
RAG_EMBEDDING_DIMENSIONS=1536

# LLM provider (via Prism)
RAG_LLM_PROVIDER=openai
RAG_LLM_MODEL=gpt-4o

# Embedding cache (reduces API costs)
RAG_EMBEDDING_CACHE=true
```

Vector Store Setup
------------------

[](#vector-store-setup)

### Option A: pgvector (recommended)

[](#option-a-pgvector-recommended)

Works everywhere. Requires PostgreSQL with pgvector extension.

```
RAG_VECTOR_STORE=pgvector
```

```
CREATE EXTENSION IF NOT EXISTS vector;
```

### Option B: sqlite-vec (Docker/Linux only)

[](#option-b-sqlite-vec-dockerlinux-only)

Zero-infrastructure local dev. **Does NOT work on macOS Herd/Homebrew PHP.**

```
RAG_VECTOR_STORE=sqlite-vec
RAG_SQLITE_DATABASE=/path/to/your/vectors.sqlite
```

**Linux (Ubuntu/Debian):**

```
# 1. Download sqlite-vec
wget https://github.com/asg017/sqlite-vec/releases/download/v0.1.7/sqlite-vec-0.1.7-loadable-linux-x86_64.tar.gz
tar xzf sqlite-vec-*.tar.gz
sudo mkdir -p /usr/lib/sqlite-vec && sudo cp vec0.so /usr/lib/sqlite-vec/

# 2. Add to php.ini
echo "sqlite3.extension_dir=/usr/lib/sqlite-vec" | sudo tee /etc/php/8.3/cli/conf.d/99-sqlite-vec.ini

# 3. Verify
php -r '$db = new SQLite3(":memory:"); $db->loadExtension("vec0.so"); echo "OK\n";'
```

**Docker / Laravel Sail:**

```
# Add to your Dockerfile
RUN wget -q https://github.com/asg017/sqlite-vec/releases/download/v0.1.7/sqlite-vec-0.1.7-loadable-linux-x86_64.tar.gz \
    && tar xzf sqlite-vec-*.tar.gz && mkdir -p /usr/lib/sqlite-vec && cp vec0.so /usr/lib/sqlite-vec/ \
    && echo "sqlite3.extension_dir=/usr/lib/sqlite-vec" >> /usr/local/etc/php/conf.d/sqlite-vec.ini
```

**macOS:** sqlite-vec is not supported with Herd or Homebrew PHP. Use pgvector instead:

```
RAG_VECTOR_STORE=pgvector
```

Quick Start
-----------

[](#quick-start)

### 1. Prepare Your Model

[](#1-prepare-your-model)

```
use Moneo\LaravelRag\Concerns\HasVectorSearch;
use Moneo\LaravelRag\Concerns\AutoEmbeds;

class Document extends Model
{
    use HasVectorSearch, AutoEmbeds;

    protected string $embedSource = 'content';
    protected string $vectorColumn = 'embedding';
}
```

### 2. Create a Migration

[](#2-create-a-migration)

```
Schema::create('documents', function (Blueprint $table) {
    $table->uuid('id')->primary();
    $table->text('content');
    $table->vector('embedding', dimensions: 1536);
    $table->json('metadata')->nullable();
    $table->timestamps();

    $table->vectorIndex('embedding', method: 'hnsw', distance: 'cosine');
    $table->fulltextIndex('content');
});
```

### 3. Ingest Content

[](#3-ingest-content)

```
use Moneo\LaravelRag\Facades\Ingest;

// From file
Ingest::file('docs/guide.pdf')
    ->chunk(strategy: 'markdown', size: 500)
    ->storeIn(Document::class)
    ->run();

// From text
Ingest::text($content)
    ->chunk(strategy: 'sentence')
    ->withMetadata(['category' => 'tech'])
    ->storeIn(Document::class)
    ->dispatch(); // async via queue
```

### 4. Query

[](#4-query)

```
use Moneo\LaravelRag\Facades\Rag;

// Simple RAG
$result = Rag::from(Document::class)
    ->limit(5)
    ->threshold(0.8)
    ->ask('What is pgvector?');

echo $result->answer;
echo $result->totalTimeMs(); // timing

// With sources
$result = Rag::from(Document::class)
    ->askWithSources('How does indexing work?');

foreach ($result->sources() as $source) {
    echo "{$source['source']} (score: {$source['score']})";
}

// Dry run — retrieve only
$chunks = Rag::from(Document::class)
    ->dryRun('What is pgvector?');
```

Streaming
---------

[](#streaming)

```
// In a controller
return Rag::from(Document::class)
    ->stream($request->question)
    ->toStreamedResponse();
```

Hybrid Search
-------------

[](#hybrid-search)

```
$result = Rag::from(Document::class)
    ->hybrid(semanticWeight: 0.7, fulltextWeight: 0.3)
    ->limit(10)
    ->ask('pgvector performance');
```

Re-ranking
----------

[](#re-ranking)

```
$result = Rag::from(Document::class)
    ->limit(20)       // retrieve 20 candidates
    ->rerank(topK: 5) // LLM scores and keeps top 5
    ->ask('question');
```

Agentic RAG
-----------

[](#agentic-rag)

```
$result = Rag::from(Document::class)
    ->agentic(maxSteps: 3)
    ->ask('Complex multi-part question?');

echo $result->answer;
echo $result->stepCount();           // retrieval iterations
echo $result->totalChunksRetrieved;  // total chunks gathered
```

Conversation Memory
-------------------

[](#conversation-memory)

```
use Moneo\LaravelRag\Memory\RagThread;

$thread = RagThread::create(['model' => Document::class]);

$result1 = $thread->ask('What is Laravel?');
$result2 = $thread->ask('Compare it with Symfony.'); // context-aware
```

Chunking Strategies
-------------------

[](#chunking-strategies)

```
Ingest::text($content)
    ->chunk(strategy: 'character', size: 500, overlap: 50)
    ->chunk(strategy: 'sentence')
    ->chunk(strategy: 'markdown')
    ->chunk(strategy: 'semantic', threshold: 0.85)
    ->storeIn(Document::class)
    ->run();
```

RAG Evals
---------

[](#rag-evals)

```
use Moneo\LaravelRag\Facades\RagEval;

$report = RagEval::suite()
    ->using(Rag::from(Document::class))
    ->add(question: 'What is pgvector?', expected: 'A PostgreSQL extension for vector similarity search')
    ->add(question: 'How to install?', expected: 'Run composer require...')
    ->run();

$report->passes(0.8); // bool
$report->toJson();     // export for CI
```

CLI:

```
php artisan rag:eval --suite=tests/rag/evals.json --fail-below=0.8
```

MCP Server
----------

[](#mcp-server)

```
// In AppServiceProvider::boot()
use Moneo\LaravelRag\Mcp\RagMcpServer;

app(RagMcpServer::class)
    ->register(Document::class)
    ->as('company-docs')
    ->description('Search internal company documentation')
    ->expose();
```

```
php artisan rag:mcp-serve --port=3000
```

Artisan Commands
----------------

[](#artisan-commands)

```
# Index all records
php artisan rag:index "App\Models\Document" --chunk=100

# Test a query
php artisan rag:test "What is pgvector?" --model="App\Models\Document" --rerank

# Estimate costs
php artisan rag:estimate --model="App\Models\Document"

# Run evals
php artisan rag:eval --suite=tests/rag/evals.json --fail-below=0.8

# Start MCP server
php artisan rag:mcp-serve --port=3000
```

Livewire Component
------------------

[](#livewire-component)

```

```

Filament Plugin
---------------

[](#filament-plugin)

```
// In your PanelProvider
->plugins([
    \Moneo\LaravelRag\Filament\RagPlugin::make(),
])
```

DevTools
--------

[](#devtools)

### Debugbar

[](#debugbar)

Auto-registers when `barryvdh/laravel-debugbar` is installed. Shows:

- RAG call count, chunks retrieved
- Cache hit/miss rate
- Retrieval vs generation timing

### Telescope

[](#telescope)

Auto-registers when `laravel/telescope` is installed. Records:

- Embedding generation events
- Cache hit events

Error Handling &amp; Retry
--------------------------

[](#error-handling--retry)

All Prism API calls are wrapped in `PrismRetryHandler` with exponential backoff:

- **Rate limits (429)**: retried with backoff + jitter, throws `EmbeddingRateLimitException` after 3 attempts
- **Server errors (5xx)**: retried once, throws `EmbeddingServiceException`
- **Timeouts**: throws `EmbeddingTimeoutException`
- **Malformed responses**: throws `EmbeddingResponseException`
- **Dimension mismatch**: throws `DimensionMismatchException` before storage

Exception hierarchy:

```
RagException (abstract)
├── EmbeddingException
│   ├── EmbeddingRateLimitException
│   ├── EmbeddingServiceException
│   ├── EmbeddingTimeoutException
│   ├── EmbeddingResponseException
│   └── DimensionMismatchException
├── VectorStoreException
│   ├── DeadlockException
│   └── VectorStoreLockException
├── GenerationException
└── CacheTableMissingException

```

Structured Logging
------------------

[](#structured-logging)

All operations emit structured logs via `RagLogger` (channel: `rag.*`):

- `rag.embedding.*` — API calls, cache hits/misses
- `rag.retrieval.*` — search operations
- `rag.generation.*` — LLM generation
- `rag.cache.*` — cache operations
- `rag.error.*` — all caught exceptions with context

Text fields are SHA-256 hashed for privacy — raw user input never appears in logs.

Custom Vector Store Driver
--------------------------

[](#custom-vector-store-driver)

Implement `VectorStoreContract`:

```
use Moneo\LaravelRag\VectorStores\Contracts\VectorStoreContract;

class QdrantStore implements VectorStoreContract
{
    public function upsert(string $id, array $vector, array $metadata): void { /* ... */ }
    public function similaritySearch(array $vector, int $limit, float $threshold = 0.0): Collection { /* ... */ }
    public function hybridSearch(string $query, array $vector, float $semanticWeight, float $fulltextWeight, int $limit): Collection { /* ... */ }
    public function delete(string $id): void { /* ... */ }
    public function flush(string $collection): void { /* ... */ }
    public function table(string $table): static { /* ... */ }
    public function supportsFullTextSearch(): bool { return false; }
}
```

Register in a service provider:

```
$this->app->singleton(VectorStoreContract::class, QdrantStore::class);
```

Benchmarks
----------

[](#benchmarks)

Operation1K docs10K docs100K docsCharacter chunking (500 chars)0.3ms2.8ms28msSentence chunking0.5ms4.5ms45msMarkdown chunking0.4ms3.8ms38msRRF merge (100+100 results)0.1ms0.1ms0.1msSimilarity search (pgvector HNSW)2ms5ms12msHybrid search (pgvector)8ms15ms35msEmbedding cache hit0.5ms0.5ms0.5ms*Benchmarks run on Apple M2 Pro, PostgreSQL 16 with pgvector 0.7. Results may vary.*

Security
--------

[](#security)

This package ships with built-in security hardening:

- **Input Sanitisation** — `InputSanitiser::clean()` strips 40+ known prompt injection patterns before text reaches the LLM
- **Vector Validation** — `VectorValidator::validate()` checks dimensions, NaN, and infinity before every upsert
- **Cache Integrity** — HMAC-signed cache keys prevent tampered cache entries; corrupted entries are auto-evicted
- **SQL Injection Protection** — Table names are validated against a strict regex before SQL interpolation
- **MCP Input Validation** — Malformed JSON-RPC requests return errors without executing retrieval

Testing
-------

[](#testing)

```
# Unit tests
vendor/bin/pest --testsuite=Unit

# Feature tests
vendor/bin/pest --testsuite=Feature

# Property-based tests (10K random inputs per property)
RAG_ERIS_ITERATIONS=10000 vendor/bin/pest tests/Property

# Chaos tests (fault injection)
vendor/bin/pest tests/Chaos

# Fuzz tests (adversarial inputs)
vendor/bin/pest tests/Fuzz

# Memory leak tests
vendor/bin/pest tests/Memory

# Architecture tests
vendor/bin/pest --testsuite=Architecture

# Contract tests (both vector store drivers)
vendor/bin/pest --testsuite=Contract

# All tests with coverage
vendor/bin/pest --coverage --min=99

# Mutation testing
vendor/bin/infection --threads=4 --min-msi=85

# Static analysis
vendor/bin/phpstan analyse
vendor/bin/rector --dry-run

# Benchmarks
vendor/bin/phpbench run --report=default
```

Quality Gates
-------------

[](#quality-gates)

All of these must pass before merge:

GateRequirementPHPStanLevel 9, zero errorsTest Coverage&gt;= 99% line, &gt;= 95% branchMutation Score (MSI)&gt;= 85%RectorZero suggestionsArchitecture TestsAll Pest `arch()` rules greenSecurity Audit`composer audit` — zero vulnerabilitiesCI MatrixPHP 8.2/8.3/8.4 x Laravel 11/12Contributing
------------

[](#contributing)

1. Fork the repo and create a feature branch
2. Write tests first — every new feature needs unit + feature tests
3. Run the full quality gate suite locally: ```
    vendor/bin/phpstan analyse
    vendor/bin/pest --coverage --min=99
    vendor/bin/infection --threads=4 --min-msi=85
    vendor/bin/rector --dry-run
    ```
4. Ensure all architecture tests pass: `vendor/bin/pest --testsuite=Architecture`
5. Submit a PR — CI will run the full matrix automatically

### Adding a Custom Vector Store Driver

[](#adding-a-custom-vector-store-driver)

Community drivers should:

- Follow naming: `moneo/laravel-rag-{driver}` (e.g., `moneo/laravel-rag-qdrant`)
- Implement `VectorStoreContract`
- Extend `VectorStoreContractTest` from this package to prove compliance
- Target MSI &gt;= 90% for the driver code

Security
--------

[](#security-1)

See [SECURITY.md](docs/SECURITY.md) for vulnerability disclosure policy and security measures.

License
-------

[](#license)

MIT License. See [LICENSE](LICENSE) for details.

###  Health Score

39

—

LowBetter than 86% of packages

Maintenance90

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 85.7% 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.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

45d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/8c1579caf779030cfa5b0e740ae68a7085d5e3d4ba0de2df3388c7cb0e73f6cc?d=identicon)[emir](/maintainers/emir)

---

Top Contributors

[![emir](https://avatars.githubusercontent.com/u/1097170?v=4)](https://github.com/emir "emir (30 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (5 commits)")

---

Tags

ailaravelpg-vectorphpragsqlite-vecvectorlaravelaivectorllmembeddingsragpgvectorsqlite-vec

###  Code Quality

TestsPest

Static AnalysisPsalm

Type Coverage Yes

### Embed Badge

![Health badge](/badges/moneo-laravel-rag/health.svg)

```
[![Health](https://phpackages.com/badges/moneo-laravel-rag/health.svg)](https://phpackages.com/packages/moneo-laravel-rag)
```

###  Alternatives

[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k12.1M99](/packages/laravel-pulse)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9682.1M97](/packages/roots-acorn)[laravel/ai

The official AI SDK for Laravel.

732506.3k60](/packages/laravel-ai)[vizra/vizra-adk

Vizra Agent Development Kit - A comprehensive Laravel package for building intelligent AI agents.

29026.1k](/packages/vizra-vizra-adk)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

245.2k](/packages/aedart-athenaeum)[neuron-core/neuron-laravel

Official Neuron AI Laravel SDK.

10710.0k](/packages/neuron-core-neuron-laravel)

PHPackages © 2026

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