excelle-insights / ai-assistant
Standalone AI assistant package — trainable, reusable across apps and LLM providers, one AI for messaging, guidance, diagnosis and analysis
Requires
- php: >=8.1
- ext-json: *
- ext-pdo: *
- guzzlehttp/guzzle: ^7.0
- vlucas/phpdotenv: ^5.7
Requires (Dev)
- robmorgan/phinx: ^0.16
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-main
- v1.0.1
- v1.0.0
- dev-feat/platform-neutral-core
- dev-feat/package-bookings
- dev-chore/retire-rename-migration
- dev-feat/booking-intent-hook
- dev-docs/llm-env-guide
- dev-fix/migration-class-name
- dev-feature/ai-training
- dev-feature/ai-reply-status
- dev-docs/ai-whatsapp-env
- dev-hotfix/deployment-fixes
- dev-feature/initial-package
This package is auto-updated.
Last update: 2026-10-24 22:22:15 UTC
README
One PHP package that gives any application a trainable AI layer: chat that answers from your own data, your documents and your knowledge base — on the web, in WhatsApp, or in whatever channel you already run. Plain PHP + PDO, no framework, no required service except an OpenAI-compatible LLM endpoint.
The package never knows what your app does. It learns your tables, your wording
and your permissions from your configuration and from the interfaces you
implement, and it writes only to its own ai_assistant_* tables in your
database. Nothing in vendor/ is ever edited, and nothing about your domain is
hardcoded here.
composer require excelle-insights/ai-assistant
php vendor/excelle-insights/ai-assistant/migrate.php # creates its tables in your DB
use ExcelleInsights\AiAssistant\Http\AssistantApi; $api = new AssistantApi($pdo); // your existing PDO connection $api->handle('schema.train', ['options' => []]); // learn your tables + columns $answer = $api->handle('chat', [ 'question' => 'How many orders did we ship last month?', 'user' => ['user_id' => '7', 'tenant_id' => 3, 'roles' => ['manager']], ]); // $answer['answer']['text'], ['sql'], ['rows'], ['chart'], ['citations'], ['meta']['intent']
Configuration is mostly data
.env holds only what is needed before a database connection exists — the DB
credentials, the LLM endpoint/key, the table prefix and the assistant's name.
Behaviour (which tables may be read, features, limits, charts, exports, WhatsApp,
audit) lives in the package's {prefix}_config table and is edited from your own
settings screen or SQL:
$api->handle('config.describe', ['company_id' => 0]); // every settable path + type $api->handle('config.save', ['company_id' => 0, 'settings' => [ 'schema_policy.mode' => 'allowlist', 'schema_policy.allowed_tables' => 'orders,customers', 'features' => 'data_qa,documents,charts,exports', ]]);
A NULL value clears an override; booleans accept yes/no/on/off/1/0
and lists accept CSV or arrays. Env keys still exist as a break-glass override
and deliberately win over the table. Full reference:
docs/03-configuration.md.
What it does
| Capability | Entry point | Needs from you |
|---|---|---|
| Answer a question from your database | chat, query.run |
PDO, LLM key |
| Learn your schema, keep your own column meanings | schema.* |
nothing (optional: descriptions) |
| Train from an uploaded SQL dump or a second DB | schema.import-dump, trainFromConnection |
the dump / connection |
| Knowledge base (FAQ, policies, prices) + CSV import | knowledge.* |
nothing |
| Document upload → extract → chunk → cite (PDF, DOCX, XLSX, images, audio) | document.* |
extractors for binary formats |
| Charts from any result set (14 types, ECharts-ready specs) | chart.suggest, chart.build |
nothing |
| Exports (CSV/TSV/JSON built in; XLSX/PDF via your exporter) with approval gates | export.* |
a writable directory |
| Saved reports, cron schedules, shared links | report.*, schedule.* |
a runner + delivery |
| Data-changing actions with confirm tokens + idempotency | action.* |
ActionHandlerInterface |
| Outbox for queued notifications with retries | outbox.* |
NotificationInterface |
| WhatsApp / any channel auto-reply | whatsapp.*, ChannelInterface |
a sender |
| Package-owned bookings (booking number, per-contact recall) | booking detection in the WhatsApp pipeline, bookings() |
BookingHandlerInterface for display/actions |
| Audit trail, usage counters, rate limits, per-tenant settings, feedback queue | audit.*, usage.*, limit.*, settings.*, feedback.* |
nothing |
| Conversation history, transcripts, share links, summaries | conversation.* |
its own tables |
Each row is documented in its own guide — see docs/; bookings specifically in docs/15-bookings.md.
What it does not do (yet)
Honesty over marketing: these are not implemented in this package.
- Lead scoring, forecasting, churn detection — no such service exists here.
- No built-in XLSX / PDF / DOCX writer, no built-in OCR or audio transcription.
The package ships interfaces (
ExporterInterface,TextExtractorInterface) and your app — which already owns PhpSpreadsheet, html2pdf, Tesseract — plugs them in.csv,tsv,jsonare written by the package itself. - Runtime SQL is written for MySQL and SQLite. Migrations use the adapter-agnostic Phinx API, so they will build tables for Postgres or SQL Server, but the package's own queries assume MySQL/SQLite quoting.
- No HTTP layer, no auth, no UI. It returns arrays; your router, session and frontend decide status codes and pixels.
Requirements
- PHP >= 8.1 with
pdoandjson.ext-pdo_mysql(orext-pdo_sqlite) for the DB. - Any OpenAI-compatible chat endpoint (
/chat/completions). Embeddings, vision and audio endpoints are optional and each feature degrades without them. - Composer
require-devrobmorgan/phinxonly to run migrations. No required runtime dependency is added to your autoloader beyond the package itself.
Guides
Start with docs/README.md for the reading order.
- Installation & migrations — what tables appear, how to re-run safely,
composer updateautomation - Connecting your application —
AssistantApi, every host interface, hooks, user context - Configuration & environment — the whole config tree, precedence, every env key
- Schema training & column descriptions — teach the assistant what your columns mean
- Knowledge & documents — FAQ training, CSV import, uploads, retrieval
- Data questions, analysis & charts — semantic layer, query plans, visualisation
- Exports — formats, approval gates, download tokens, host exporters
- Reports & schedules — saved reports, cron delivery, feedback loop
- Actions & outbox — safe writes into your app, queued notifications
- Channels & WhatsApp — inbound handling, auto-reply, legacy service
- Governance — audit, usage, rate limits, settings, conversations, retention
- API reference — every method, every
handle()action, theok/errorcontract - LLM providers — OpenAI, OpenRouter, Ollama, vLLM, DeepSeek, local
- Troubleshooting — failures you will actually see, and what they mean
- Bookings — package-owned bookings, booking numbers, recall, host actions
Development
cd /path/to/ai-assistant composer install # dev: phinx php tests/run.php # every suite, no DB or network needed
The suites are plain PHP scripts with their own assertions (no PHPUnit):
assistant, api, schema, knowledge, semantic, exports, actions,
channels, governance, config, conversation. They run against SQLite in a
temp file, so composer install && php tests/run.php is green on a clean machine.
To try the migrations locally:
DB_ADAPTER=sqlite DB_NAME=/tmp/ai_mig.sqlite php migrate.php
BLACKBOX_DECOUPLING_PROPOSAL.md is a historical design note from the
pre-rename days. The guides in docs/ are the current contract; where the two
disagree, docs/ wins.