Skip to main content

Open source · MIT licensed · PHP 8.2+

php-chatbot-assistant
A self-hosted AI chatbot platform

Train it on your own documents and drop one script tag on your site. Answers come out of your content, the conversations stay in your PostgreSQL database, and nobody bills you per seat, per bot or per message.

  • MIT license
  • No framework
  • PostgreSQL 16 + pgvector
  • 282 unit tests
https://your-server.com/dashboard
Chatbot assistant dashboard showing chatbot, document, conversation and message counts alongside unique visitors, tokens used, average response time and a response-source chart
  • 2 retrieval strategies — vector RAG or PageIndex
  • 30+ industry prompt presets, several per industry
  • 1 script tag to put a bot on any website
  • $0 per seat, per bot, per conversation

What you get

A complete chatbot product, not a demo script

Clone it, run the installer, add your API keys. Everything a client-facing chatbot needs — tenancy, training pipeline, widget, lead capture, permissions and audit trail — is already in the box.

Chatbots per tenant

Create, clone and manage as many bots as you like. Each one carries its own model settings, system prompt, widget styling and allowed domains.

Document Q&A

Upload PDF, DOCX, TXT or Markdown. The pipeline parses, chunks, embeds and indexes it automatically, and shows you the status of every step.

Two retrieval strategies

Classic vector search in pgvector, or PageIndex — an LLM navigating a document outline with no embeddings at all. Choose per chatbot.

AI lead capture

The bot asks for a name, email and phone inside the conversation — no modal, no form. Leads are extracted, stored and summarised per conversation.

Quick answers

Trigger-based canned replies that fire before the model is ever called. Common questions cost nothing and come back instantly.

Authentication, finished

Argon2id passwords, magic links, TOTP with recovery codes, account lockout, per-IP rate limiting, CSRF tokens and rotating sessions.

Retrieval

Two ways to answer from your documents

Most chatbots force one retrieval model on you. Here it is a per-chatbot setting, so you can use embeddings where they are strongest and skip them where they get in the way.

Traditional RAG

Vector search

Documents are chunked, embedded with text-embedding-3-small (1536 dimensions) and stored in pgvector with an IVFFlat index. At query time the question is embedded and the nearest chunks are returned by cosine distance.

  • Fast, proven and predictable on cost
  • Ideal when answers live inside individual paragraphs
  • Index is ready as soon as ingestion finishes
PageIndex

Vectorless navigation

Documents are parsed into a hierarchy of headings and sections. The model skims the outline, picks the sections that matter and reads only those — the way a person uses a table of contents.

  • No chunk boundaries to split an answer in half
  • Strong on long, well-structured documents
  • Fewer embedding calls; outline skimming stays cheap

The widget

One script tag, and it is on your site

The embed snippet is generated from your chatbot's own settings — colours, header text, placeholder and position all update live as you edit them, and the code panel rewrites itself as you go.

Embed code
<script src="https://your-server.com/widget.js"
        data-widget-token="YOUR_WIDGET_TOKEN"
        data-api-base="https://your-server.com"
        data-bot-name="Support"
        data-primary-color="#2563eb"
        data-position="bottom-right"
        data-widget-theme="light"></script>

  • Shadow DOM — your site's CSS cannot break the widget, and the widget cannot break your site.
  • Light and dark panels, custom primary, gradient, accent and header colours.
  • Quick answer chips loaded when the panel opens, plus typing indicators.
  • Expandable — drag either edge to resize the panel width.
  • Ratings — an inactivity-triggered 1–5 star bar per conversation.
  • Locked down — allowed-domain CORS restriction so a copied snippet is useless on someone else's site.
https://your-server.com/chatbots/1/edit
Widget styling form with theme preset, panel theme, bot name, colour pickers, header icon, position and placeholder text, beside a live preview of the chatbot panel

Widget styling with the live preview — every field on the left is reflected in the panel on the right, and in the embed code underneath.

Inside the product

Seventeen screens, from first login to audit trail

Click any screen to open it full size. Use the arrow keys to move through the set, Escape to close.

Dashboard and analytics

2 screens

Chatbots, training and results

4 screens

The chatbot builder, top to bottom

6 screens

Accounts, roles and the audit trail

5 screens

Installation

Running on your own server in about fifteen minutes

  • PHP 8.2+ with pdo_pgsql and mbstring
  • PostgreSQL 16+ with the pgvector extension
  • Composer
  • An OpenAI API key
  1. Clone the repository and install its two dependencies

    git clone https://github.com/OnlineTechSupportBiz/php-chatbot-assistant.git
    cd php-chatbot-assistant/pca
    composer install

    Composer and the application live in pca/. Point your web server's document root at its sibling public_html/, which holds the front controller, the installer, the widget and the assets.

  2. Open install.php and work through the installer

    Visit https://your-server.com/install.php. The three-step wizard configures the database connection, runs the migrations and creates the super-admin account — it checks the PHP extensions, the PostgreSQL version and the vector extension before it writes anything.

  3. Register a user account and add its API keys

    Create a user account from the login screen, then sign in as that user and open Settings to save the OpenAI key (used for embeddings and chat) and the LlamaCloud key (used to parse uploaded documents). The keys belong to the account, not the server, so each tenant brings its own. You can also switch registration off in the admin dashboard and create client accounts yourself.

  4. Create a chatbot and train it

    Pick an industry preset or write your own system prompt, choose vector RAG or PageIndex, then upload a document. The pipeline runs parse → chunk → embed → index and reports the status of every step.

  5. Embed the widget and restrict it to your domain

    Copy the snippet from the chatbot page and paste it into your site before </body>. Add the domains allowed to use that widget token, so a copied snippet fails anywhere else.

Delete install.php once the first admin exists. It is the one file in the repository that must not stay on a production server.

Verify the install

Test suite — run from the pca/ directory, no external services needed
php vendor/bin/phpunit tests/Unit/

282 tests cover the models, controllers, routing, auth, rate limiting, prompt-injection detection, retrieval strategies and XSS sanitisation, using mocked databases so nothing outside your machine is contacted.

Under the hood

Clean PHP, PostgreSQL and nothing you have to babysit

PSR-4 classes, no framework, no queue server and no external vector database. If you can run a PHP site you can run this.

Technology stack of php-chatbot-assistant
LayerTechnology
BackendPHP 8.2+, PSR-4, no framework
DatabasePostgreSQL 16 with pgvector (IVFFlat index)
TenancyRow-Level Security on a session-scoped tenant id
EmbeddingsOpenAI text-embedding-3-small, 1536 dimensions
Chat modelConfigurable per chatbot, GPT-4o-mini or GPT-4.1-mini class by default
ParsingLlamaCloud Parse for PDF, DOCX, TXT and Markdown
AuthArgon2id, TOTP via otphp, magic links
WidgetVanilla JavaScript in a Shadow DOM, with Marked for Markdown
EmailPHPMailer over your own SMTP server

Abuse protection before the model is called

Every guardrail is evaluated before any API request goes out, so a blocked request costs you nothing and a hostile one does not reach your invoice.

  • Rate limiting — a configurable number of messages per minute per session.
  • Daily token budget — a hard per-chatbot cap, with the current model's spend estimate beside it.
  • Maximum message length — oversized prompts are rejected outright.
  • Maximum messages per conversation — limits how deep one session can run.
  • Prompt-injection detection — pattern scanning with a polite, silent refusal.
  • Audit trail — every guardrail trigger is logged with its context.
  • Tenant isolation — PostgreSQL Row-Level Security, never a user id trusted from client input.

Questions

Before you clone it

What does it cost to run?
The software is free under the MIT license and there is no per-seat, per-bot or per-conversation fee. Your real costs are the server you already have, your OpenAI usage (embeddings at ingestion plus chat completions) and a LlamaCloud key for document parsing. Quick answers and guardrail rejections never reach the model, and each chatbot can carry a daily token budget as a hard ceiling.
Do I need Docker or a Node toolchain?
No. The application is plain PHP 8.2+ with two Composer dependencies, PHPMailer and otphp. The widget is vanilla JavaScript served straight from the repository. You need a PostgreSQL 16 database with the pgvector extension and a web server pointed at public_html.
Where does my data — and my clients' data — live?
In your PostgreSQL database, on your server. The only outbound calls are the ones you configure: OpenAI for embeddings and chat, LlamaCloud for document parsing, and your own SMTP server for email. Tenants are isolated at the database level with Row-Level Security rather than by application code alone.
Can I host several clients on one installation?
Yes — that is what it is built for. Each tenant gets its own users, chatbots, API keys, branding, timezone and audit log, and the super admin dashboard shows every account with a per-account permissions screen.
Traditional RAG or PageIndex — which should I choose?
Start with vector RAG for FAQ-shaped content where answers sit inside individual paragraphs. Choose PageIndex for long, well-structured documents — manuals, policies, long reports — where chunk boundaries tend to cut an answer in half. It is a per-chatbot setting, so you can upload the same document under both strategies and compare the answers side by side.
How do I put the chatbot on a website?
Paste the generated script tag before </body> on the site, then add that site's domain to the chatbot's allowed-domain list. The widget runs in a Shadow DOM, so it inherits nothing from the host page's CSS and cannot leak styles back into it.

Own your chatbot stack

Clone it, run the installer, and put an AI assistant on your website that answers from your own content — on infrastructure you control.

MIT licensed · PHP 8.2+ · PostgreSQL 16 + pgvector