PHPackages                             solution-forest/ai-kit-core - 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. solution-forest/ai-kit-core

ActiveLibrary

solution-forest/ai-kit-core
===========================

Core of ai-kit: document ingestion, chunking, extraction, vector retrieval (sqlite-vec + pgvector), and RAG agents built on the official Laravel AI SDK.

v0.2.1(yesterday)022↑2900%2MITPHP ^8.3

Since Jul 22Compare

[ Source](https://github.com/solutionforest/ai-kit-core)[ Packagist](https://packagist.org/packages/solution-forest/ai-kit-core)[ RSS](/packages/solution-forest-ai-kit-core/feed)WikiDiscussions Synced today

READMEChangelog (1)Dependencies (11)Versions (3)Used By (2)

ai-kit-core
===========

[](#ai-kit-core)

[![PHP](https://camo.githubusercontent.com/9b10bfbe61ed78776363b7b6ed761bcd0111f4fa4e005df8d830fcd94951469a/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e332b2d3737374242343f6c6f676f3d706870266c6f676f436f6c6f723d7768697465)](https://camo.githubusercontent.com/9b10bfbe61ed78776363b7b6ed761bcd0111f4fa4e005df8d830fcd94951469a/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e332b2d3737374242343f6c6f676f3d706870266c6f676f436f6c6f723d7768697465)[![Laravel](https://camo.githubusercontent.com/ef749269b4e188533479a48e8d4c00604c54f02116015dee66908c8d8e80cf43/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d313225323025374325323031332d4646324432303f6c6f676f3d6c61726176656c266c6f676f436f6c6f723d7768697465)](https://camo.githubusercontent.com/ef749269b4e188533479a48e8d4c00604c54f02116015dee66908c8d8e80cf43/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d313225323025374325323031332d4646324432303f6c6f676f3d6c61726176656c266c6f676f436f6c6f723d7768697465)[![Laravel AI SDK](https://camo.githubusercontent.com/4e08b482fba3ca47e3256760500c9b318b12df94556c0d1e6c6e9b3a1e6122c1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c61726176656c25324661692d253545302e392d464632443230)](https://camo.githubusercontent.com/4e08b482fba3ca47e3256760500c9b318b12df94556c0d1e6c6e9b3a1e6122c1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c61726176656c25324661692d253545302e392d464632443230)[![License](https://camo.githubusercontent.com/f8df3091bbe1149f398a5369b2c39e896766f9f6efba3477c63e9b4aa940ef14/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e)](https://camo.githubusercontent.com/f8df3091bbe1149f398a5369b2c39e896766f9f6efba3477c63e9b4aa940ef14/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e)

**The engine of the ai-kit suite** — document ingestion, chunking, extraction, vector retrieval, and RAG agents for Laravel, built on the official [Laravel AI SDK](https://laravel.com/docs/ai).

`composer require` → `php artisan ai-kit:install` → a grounded, cited RAG assistant over your own documents — with **no external vector database required**.

- **Two vector drivers** behind one contract: **SQLite** (zero-infra, default) and **pgvector** (production).
- **Two RAG modes** via one config flag: **tool** (agentic) and **inject** (classic).
- **Ingest** PDF, Word (.docx), Excel (.xlsx), HTML, Markdown, plain text, **and URLs**.
- **Provider-agnostic** — OpenAI, Anthropic, OpenRouter, Gemini, Groq, Mistral, … (anything the AI SDK supports).
- **Fully testable offline** — no API keys needed in CI.

Why ai-kit?
-----------

[](#why-ai-kit)

Building a grounded, cited RAG chatbot over your own documents in Laravel means wiring together a dozen moving parts: parsing PDFs/Word/Excel, chunking text, generating embeddings, running a vector store, similarity search, prompt orchestration, streaming, citations, conversation history, and cost tracking.

**ai-kit does all of that for you** — on the official Laravel AI SDK, with no external vector database. `composer require` → `php artisan ai-kit:install` → a working, source-cited assistant in under 30 minutes. Then expose it however you like: a Livewire chat widget, an admin panel, a JSON API, a CLI, or an MCP server for AI agents.

Architecture
------------

[](#architecture)

 ```
flowchart TB
    UI["Livewire UI(ai-kit-ui-livewire)"]
    CLI["Artisan CLI"]
    API["HTTP API"]
    MCP["MCP Server"]

    subgraph services["Service layer"]
        SVC["ChatService · CollectionService · DocumentService"]
    end

    UI --> SVC
    CLI --> SVC
    API --> SVC
    MCP --> SVC

    SVC --> ING["Ingestionextract → chunk → embed"]
    SVC --> RET["Retriever"]
    SVC --> AGENT["RagAgenttool / inject mode"]

    ING --> VS[("Vector storesqlite-vec / pgvector")]
    RET --> VS
    ING --> LLM["Laravel AI SDK(any provider)"]
    AGENT --> RET
    AGENT --> LLM
```

      Loading **One core, four faces.** Every surface calls the same service layer, so RAG behaviour is identical whether a user chats in the browser, you script the CLI, another service hits the API, or an AI agent connects over MCP.

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

[](#requirements)

- PHP **8.3+**
- Laravel **12 or 13**
- `laravel/ai` **^0.9**

Install
-------

[](#install)

```
composer require solution-forest/ai-kit-core
php artisan ai-kit:install
```

The installer:

1. Publishes `config/ai-kit.php` + migrations (including the AI SDK's conversation tables).
2. Interactively asks for your **AI provider config** (chat + embeddings provider/model/key) and writes it to `.env`.
3. Scaffolds `App\Ai\SupportAgent` (extends `RagAgent`).
4. Runs migrations.
5. Optionally seeds a demo knowledge base.

Then set your keys (the installer adds the scaffold; fill in the value):

```
AI_KIT_CHAT_PROVIDER=openai
AI_KIT_CHAT_MODEL=gpt-5
AI_KIT_EMBED_PROVIDER=openai
AI_KIT_EMBED_MODEL=text-embedding-3-small
OPENAI_API_KEY=sk-...
```

Quick start
-----------

[](#quick-start)

```
use SolutionForest\AiKit\Models\Collection;
use SolutionForest\AiKit\Ingestion\IngestionService;
use SolutionForest\AiKit\Agents\RagAgent;

// 1. Create a knowledge base and ingest documents.
$kb = Collection::create(['name' => 'Handbook']);
app(IngestionService::class)->createFromPath($kb, storage_path('handbook.pdf'), sync: true);
app(IngestionService::class)->createFromUrl($kb, 'https://example.com/faq', sync: true);

// 2. Ask a question — grounded, cited, provider from config.
$response = (new RagAgent('handbook'))->prompt('What is the refund window?');
echo $response->text;
```

Or from the CLI:

```
php artisan ai-kit:ingest path/to/docs --collection=handbook   # file or directory
php artisan ai-kit:ingest-url https://example.com/faq --collection=handbook
php artisan ai-kit:demo                                         # seed 3 sample docs
```

How ingestion works
-------------------

[](#how-ingestion-works)

```
createFromPath / createFromUrl
        │
        ▼
  ExtractText ──▶ ChunkDocument ──▶ EmbedChunks ──▶ vector index
 (pdf/docx/xlsx/    (recursive,      (AI SDK          (sqlite-vec
  html/md/txt)      sentence-aware)   embeddings)      or pgvector)

```

- **Synchronous** (`sync: true`) — runs inline; used by `ai-kit:demo` and CLI. No queue worker needed.
- **Queued** (default) — dispatches a chained `ExtractText → ChunkDocument → EmbedChunks` batch; document status moves `pending → processing → indexed` (or `failed`).

Every chunk stores its raw embedding **and** the embedding model name, so re-indexing with a different model is detectable and you can switch drivers without re-embedding blindly.

### Supported document types

[](#supported-document-types)

TypeExtractorNotes`.txt` `.md` `.csv``PlainTextExtractor``.html``HtmlExtractor`strips script/style/boilerplate`.pdf``PdfExtractor`via `smalot/pdfparser``.docx``WordExtractor`zero-dependency (zipped XML)`.xlsx``ExcelExtractor`zero-dependency; extracts text cellsURLfetch + `HtmlExtractor``createFromUrl` / `ai-kit:ingest-url`Legacy binary `.doc` / `.xls` are **not** supported.

Two RAG modes
-------------

[](#two-rag-modes)

`config('ai-kit.mode')`:

- **`tool`** (default) — the agent gets a `SearchKnowledgeBase` tool and decides when/what to search (agentic RAG; supports multi-hop). Requires a model with reliable tool-calling.
- **`inject`** — no tool; `ContextInjector` retrieves and prepends context to the prompt before the model runs (classic RAG). Grounding never depends on the model choosing to search — safer with small models.

Both consume the same `Retriever` contract.

Two vector drivers
------------------

[](#two-vector-drivers)

`config('ai-kit.retrieval.driver')`:

- **`sqlite`** (default) — uses the sqlite-vec (`vec1`) extension when present, otherwise an **exact pure-PHP cosine scan** (correct everywhere, zero setup — ideal for demos and small/medium corpora). Optional extension path: `AI_KIT_SQLITE_VEC_PATH`.
- **`pgvector`** — a `vector` column indexed with HNSW/IVFFlat, searched with the `` cosine operator. Scales to millions of chunks.

Building agents
---------------

[](#building-agents)

`RagAgent` reads config and wires the configured chat provider/model into every `prompt()` / `stream()`:

```
use SolutionForest\AiKit\Agents\RagAgent;

(new RagAgent(collection: 'handbook'))
    ->forTenant('acme')            // optional tenant scope
    ->prompt('...');               // uses ai-kit.chat.provider + model
```

Customise instructions by extending it (the installer scaffolds this):

```
namespace App\Ai;

use SolutionForest\AiKit\Agents\RagAgent;

final class SupportAgent extends RagAgent
{
    public function instructions(): \Stringable|string
    {
        return 'You are our support assistant. Always search first; answer only from the knowledge base; cite sources.';
    }
}
```

Point `AI_KIT_AGENT=App\Ai\SupportAgent` at it. The default instructions are strict-grounded (search-first, refuse-if-unsupported, cite by document title).

Conversation persistence &amp; token usage
------------------------------------------

[](#conversation-persistence--token-usage)

When a prompt runs **for an authenticated participant** (`->forUser($user)` / `->continue($id, $user)`), the AI SDK persists the exchange to `agent_conversations` / `agent_conversation_messages`, **including per-message token usage**. Aggregate it with `UsageStats`:

```
use SolutionForest\AiKit\Support\UsageStats;

app(UsageStats::class)->totals(30);            // ['prompt'=>, 'completion'=>, 'total'=>, 'cost'=>, 'messages'=>]
app(UsageStats::class)->daily(14);             // per-day token series
app(UsageStats::class)->conversationTokens($id);
```

Cost is estimated from `config('ai-kit.pricing')` ($ per 1M tokens, per model) using the active chat model's rate.

Multi-tenancy
-------------

[](#multi-tenancy)

Every table has a nullable `tenant_id`. Scope models + retrieval:

```
use SolutionForest\AiKit\Facades\AiKit;

AiKit::withTenant('acme', fn () => (new RagAgent('handbook'))->prompt('...'));
```

Enable with `AI_KIT_TENANCY=true`.

Contracts (swap any layer)
--------------------------

[](#contracts-swap-any-layer)

ContractDefaultBind your own via the container`Retriever` / `VectorIndex``SqliteVecRetriever` / `PgVectorRetriever`custom store`Embedder``AiSdkEmbedder`e.g. a local embedder`Chunker``RecursiveTextChunker`custom splitting`TextExtractor``ExtractorManager`add extractorsConfiguration reference
-----------------------

[](#configuration-reference)

`config/ai-kit.php`: `mode`, `default_collection`, `agent` (class + instructions), `chat` (provider/model/fallback/streaming), `embeddings` (provider/model/dimensions/cache/timeout), `chunking` (size/overlap), `retrieval` (driver/top\_k/min\_score/sqlite/pgvector), `ingestion` (queue/embed\_batch), `tenancy`, `database` (connection/prefix), `features` (dashboard/token\_usage), `pricing`. Every value has an `env()` override.

Commands
--------

[](#commands)

CommandPurpose`ai-kit:install`Publish config/migrations, configure AI providers, scaffold agent`ai-kit:demo`Seed a demo collection + 3 sample docs (sync)`ai-kit:ingest {path} --collection=`Ingest a file or directory`ai-kit:ingest-url {url} --collection=`Fetch + ingest a web pageHeadless surfaces (CLI · HTTP API · MCP)
----------------------------------------

[](#headless-surfaces-cli--http-api--mcp)

Everything the Filament panel does is reachable without Filament. All four surfaces call the same service layer (`ChatService`, `CollectionService`, `DocumentService`), so behaviour is identical everywhere.

### CLI

[](#cli)

CommandPurpose`ai-kit:collection {list|new|show|delete}`Manage knowledge bases (`--json`)`ai-kit:document {list|chunks|reindex|delete}`Manage documents (`--collection`, `--json`)`ai-kit:search {query} --collection=`Raw retrieval, no LLM (`--json`)`ai-kit:chat {collection}`Interactive grounded chat REPL`ai-kit:conversation {list|show}`Conversation log + token usage (`--json`)`ai-kit:stats`Documents/chunks/tokens/cost (`--json`)### HTTP API (optional)

[](#http-api-optional)

Enable with `AI_KIT_API=true`. Locked behind auth by default (`config('ai-kit.api.middleware') = ['api','auth:sanctum']`); set your own guard, or `['api']` for public. Prefix: `AI_KIT_API_PREFIX` (default `api/ai-kit`).

```
POST  /chat                          { message, collection?, conversation_id? } → answer + citations + usage
POST  /chat/stream                   SSE (token-by-token)
POST  /search                        { query, collection?, top? } → chunks
GET   /collections                   list
POST  /collections                   { name, slug?, description? }
GET   /collections/{slug}            + stats
GET   /collections/{slug}/documents  list
POST  /collections/{slug}/documents  { url | text | file, title?, sync? } → ingest
GET   /conversations                 list (+ token totals)
GET   /conversations/{id}            thread + per-message tokens
GET   /usage?days=30                 totals + daily series

```

### MCP server (optional)

[](#mcp-server-optional)

Expose ai-kit to MCP clients (Claude Desktop, IDE agents). Requires `composer require laravel/mcp`, then `AI_KIT_MCP=true`. Tools: `search_knowledge_base`, `ask_knowledge_base`, `list_collections`, `ingest_url`. Serve over stdio:

```
php artisan mcp:start ai-kit
```

Set `AI_KIT_MCP_WEB=true` to also register an HTTP transport route (`config('ai-kit.mcp.web_route')`, guarded by `mcp.web_middleware`).

### Examples

[](#examples)

**HTTP API** (Bearer auth by default):

```
# Ask a question
curl -X POST https://your-app.test/api/ai-kit/chat \
  -H "Authorization: Bearer " -H "Content-Type: application/json" \
  -d '{"message":"What is the refund window?","collection":"handbook"}'

# Raw search
curl -X POST https://your-app.test/api/ai-kit/search \
  -H "Authorization: Bearer " -H "Content-Type: application/json" \
  -d '{"query":"refunds","collection":"handbook","top":5}'

# Ingest a URL
curl -X POST https://your-app.test/api/ai-kit/collections/handbook/documents \
  -H "Authorization: Bearer " -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/faq"}'
```

**MCP** — point a client (e.g. Claude Desktop) at the stdio server:

```
{
  "mcpServers": {
    "ai-kit": {
      "command": "php",
      "args": ["artisan", "mcp:start", "ai-kit"],
      "cwd": "/path/to/your/laravel/app"
    }
  }
}
```

**Programmatic** (any surface, same result):

```
use SolutionForest\AiKit\Services\ChatService;

$result = app(ChatService::class)->ask('What is the refund window?', 'handbook');
$result->answer;      // string
$result->citations;   // [{document_title, chunk_index, score, content}, ...]
$result->usage;       // {in, out, total}
```

Testing
-------

[](#testing)

The suite runs **offline with no API keys** — LLM calls use the AI SDK's fakes, embeddings use a deterministic in-memory double.

```
composer install && vendor/bin/pest
```

The ai-kit suite
----------------

[](#the-ai-kit-suite)

**One core, four faces** — the Livewire UI, CLI, HTTP API, and MCP server all call the same service layer (`ChatService`, `CollectionService`, `DocumentService`), so behaviour is identical everywhere.

PackagePurpose**solution-forest/ai-kit-core** (this)Ingestion, retrieval, agents + CLI, HTTP API, MCP[solution-forest/ai-kit-ui-livewire](https://github.com/solutionforest/ai-kit-ui-livewire)Livewire 4 chat component[solution-forest/ai-kit-filament](https://github.com/solutionforest/ai-kit-filament)Filament v5 admin panel`ai-kit-ui-livewire` and `ai-kit-filament` are optional; core is fully usable headless.

License
-------

[](#license)

MIT © [SolutionForest](https://www.solutionforest.com)

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance100

Actively maintained with recent releases

Popularity9

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity39

Early-stage or recently created project

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

Every ~0 days

Total

2

Last Release

1d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/68211796?v=4)[Solution Forest](/maintainers/solutionforest)[@solutionforest](https://github.com/solutionforest)

---

Tags

laravelaichatbotembeddingsragpgvectorsqlite-vec

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/solution-forest-ai-kit-core/health.svg)

```
[![Health](https://phpackages.com/badges/solution-forest-ai-kit-core/health.svg)](https://phpackages.com/packages/solution-forest-ai-kit-core)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.3M347](/packages/psalm-plugin-laravel)[laravel/ai

The official AI SDK for Laravel.

1.0k3.2M244](/packages/laravel-ai)[laravel/scout

Laravel Scout provides a driver based solution to searching your Eloquent models.

1.7k55.0M631](/packages/laravel-scout)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9762.4M133](/packages/roots-acorn)[api-platform/laravel

API Platform support for Laravel

58174.6k17](/packages/api-platform-laravel)[pressbooks/pressbooks

Pressbooks is an open source book publishing tool built on a WordPress multisite platform. Pressbooks outputs books in multiple formats, including PDF, EPUB, web, and a variety of XML flavours, using a theming/templating system, driven by CSS.

45444.2k1](/packages/pressbooks-pressbooks)

PHPackages © 2026

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