ahmednour / eloquent-rag
The Eloquent synchronization layer for Laravel AI's RAG stack — model lifecycle sync, dependency tracking, invalidation, chunk management, and rebuild tooling.
Requires
- php: ^8.3
- illuminate/database: ^13.29
- illuminate/queue: ^13.29
- illuminate/support: ^13.29
- laravel/ai: ^0.11.2 || ^1.0
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.17
- orchestra/testbench: ^11.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
- yethee/tiktoken: ^1.1
Suggests
- yethee/tiktoken: Real BPE token counts for chunk sizing via the 'tiktoken' tokenizer driver (^1.1)
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-28 14:24:21 UTC
README
Keep your Eloquent models' RAG index correct, automatically — including when the data a document depends on lives in other models.
Eloquent RAG is the synchronization layer between your Eloquent models and Laravel AI's embeddings and native vector search: model lifecycle sync, dependency tracking, invalidation, chunking, and rebuild tooling. It does not implement vector search itself; it keeps what Laravel's vector search reads up to date.
Example
use Ahmednour\EloquentRag\Concerns\HasRag; use Ahmednour\EloquentRag\Rag; use Ahmednour\EloquentRag\RagDefinition; class Product extends Model { use HasRag; public function toRagDefinition(): RagDefinition { return Rag::make() ->content(['name', 'description', 'price']) // this model's own attributes ->relation('category.name') // data from related models, ->relation('features.name'); // tracked as dependencies } } // Saving a product re-syncs its document on the queue. Renaming a category // re-syncs every product that depends on it, in bounded batches. Product::create([...]); $category->update(['name' => 'Audio']); // Hydrated Product models, most relevant first: $products = Product::searchRag('wireless speaker for the shower', limit: 5); // Or with scores and the matching text, for grounding an LLM answer: foreach (Product::searchRagWithScores('wireless speaker', limit: 5) as $result) { $result->model; // Product $result->score; // cosine similarity, 0.0–1.0 $result->chunk(); // the matching chunk of the rendered document (null if stale) }
Embeddings are generated with php artisan rag:sync, or automatically after
each save with RAG_AUTO_EMBED=true — see
automatic embedding.
Why not just call Laravel AI's vector search directly?
Embedding a row and searching it is the easy part. The hard part is knowing when an embedding has gone stale. A product's document includes its category's name, so renaming that category changes 50,000 products' documents, but none of those product rows changed, so nothing re-embeds them. Eloquent RAG records, per document, which related models it was rendered from. When one of those changes, it finds every affected document through an indexed reverse lookup and re-syncs them in bounded, coalesced queue batches (ten quick edits to one category produce one pass, not ten), skipping documents whose rendered content didn't actually change. See fan-out behavior and the benchmarks (1,000,000 dependent documents resolved and dispatched in under 3 seconds on SQLite).
Requirements
| Target | Supported | Requirement |
|---|---|---|
| MariaDB 11.7+ | ✅ | Laravel 13.29+ (vector query builder API) |
| PostgreSQL + pgvector | ✅ | Laravel 13.x |
| Plain MySQL / SQLite | ⚠️ dev only | No native vector search; opt-in portable fallback for development and small data |
PHP 8.3+, and laravel/ai 0.11.2+ or 1.x. See
docs/backend-support.md and
docs/support-policy.md.
Installation
composer require ahmednour/eloquent-rag php artisan migrate php artisan rag:doctor
rag:doctor checks your Laravel version, database backend, embedding
dimensions, and queue setup before anything gets indexed. See
docs/installation.md for the full setup.
Status
Beta (v0.2.0-beta.1 on
Packagist), and
not yet recommended for production. The correctness-critical paths are
covered by unit and feature tests plus acceptance suites that run in CI
against real MariaDB 11.7 and PostgreSQL+pgvector servers across the
supported PHP/Laravel matrix. What's missing before a stable 1.0:
- Production usage history. No deployment has run it under real
traffic yet. If you try it, start with a non-critical model and run
php artisan rag:verifyon a schedule. - Real-backend performance numbers. Fan-out is benchmarked on SQLite only so far; the MariaDB/PostgreSQL run is wired up but not published (see docs/benchmarks.md).
- API stability. While pre-1.0, a minor release may contain breaking changes (always called out in the changelog).
The portable fallback is never meant for production, whatever the version. Changes are tracked in CHANGELOG.md.
Documentation
- Installation
- Definition API:
HasRag,toRagDefinition(), sync, embed, search, events - Dependency model: how documents declare and track dependencies
- Fan-out behavior: batching, coalescing, and the two gotchas you need to know about
- Backend support: the support matrix, the portable fallback, and
rag:doctor - Tokenization: chunk sizing, the
tiktokendriver, custom tokenizers - Rebuild and migration:
rag:sync,rag:rebuild,rag:verify,rag:prune,rag:forget - Testing your models:
Rag::fake() - Benchmarks: fan-out at 10k/100k/1M documents
- Support policy: supported PHP/Laravel/
laravel/aiversions - Principles: the core principle and explicit non-goals
- Architecture Decision Records
Contributing
See CONTRIBUTING.md. Please report security issues privately, as described in SECURITY.md.
License
MIT. See LICENSE.