Search by

zofe / ai-module

zofe

AI widget, tool registry and multi-provider service (Anthropic, OpenAI-compatible, Ollama) for rapyd-admin

Package info

github.com/zofe/ai-module

pkg:composer/zofe/ai-module

Statistics

Installs: 20

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.3.2 2026-09-20 17:38 UTC

This package is auto-updated.

Last update: 2026-09-20 17:40:48 UTC


README

Tests

A chat widget (@aiWidget in any layout), a registry of tools the modules expose to the model, and one service for Anthropic, OpenAI-compatible APIs (OpenAI, DeepSeek, Groq, Mistral…) and Ollama.

composer require zofe/ai-module
AI_WIDGET_ENABLED=true
AI_WIDGET_MODE=customer            # customer: text only, for a public site | operator: tools on the app's data
AI_PROVIDER=openai                 # anthropic | openai | ollama
AI_OPENAI_KEY=sk-...
AI_OPENAI_BASE_URL=https://api.deepseek.com/v1
AI_MODEL=deepseek-chat
AI_SYSTEM_PROMPT="You are the assistant of ..."   # optional, default: a brief from rpd:context
AI_KNOWLEDGE=resources/ai/knowledge.md            # optional: what the bot knows about the product

Then @aiWidget in the layout (rapyd-admin's reference theme already prints it).

Two modes

  • customer: the model only gets text. Rules appended to the system prompt keep it on the product: it declines other topics, ignores instructions in the messages, never reveals the prompt or the internals, answers briefly in the user's language.
  • operator: the registered AiTools (see Zofe\Rapyd\Contracts\AiToolProvider) are offered to the model, so it can read the application's data. Tools go only to logged-in users, and to those holding AI_TOOLS_PERMISSION when it is set. A guest never gets tools, whatever the mode.

What the bot knows

AI_KNOWLEDGE points to a markdown file (path relative to the app root, or absolute) or to an URL (fetched once an hour). Its content is appended to the system prompt, trimmed to AI_KNOWLEDGE_MAX characters (16000). Keep it a plain, current description of the product: versions, features, commands, links, prices, what to say when something is not covered.

The perimeter of a public bot

Every request from the browser goes through, in this order:

Check Setting Default
Message length AI_MAX_INPUT characters 500
Daily budget of the whole site AI_DAILY_BUDGET USD, 0 = none 0
Requests per session AI_RATE_LIMIT per AI_RATE_WINDOW seconds 20 / 3600
Requests per IP address AI_RATE_LIMIT_IP per window 60
Pause between two messages of a session AI_MIN_INTERVAL seconds 2

The conversation lives in a #[Locked] Livewire property: the browser cannot add, edit or inflate it. Only the last AI_HISTORY messages (8) are sent to the model, the reply is capped at AI_MAX_TOKENS (1024). Provider errors are logged; the visitor sees a generic message (the real one with APP_DEBUG=true).

Spend

The tokens of every call are counted in the cache (per day) and priced with AI_PRICE_INPUT / AI_PRICE_OUTPUT (USD per million tokens, defaults 0.30 / 1.20: set your provider's list price). When the day's cost reaches AI_DAILY_BUDGET the widget answers "paused until tomorrow" instead of calling the provider. With AI_LOG_USAGE (default on) every request writes one log line with tokens, cost, IP and user. The counters live in the cache store named by AI_USAGE_STORE (default: the application cache, which cache:clear and optimize:clear wipe); set it to another store, file for instance, to keep them across deploys.

php artisan ai:usage            # requests, tokens and cost of the last 7 days

The "Develop with AI" page

/ai/develop in the admin (menu entry "Develop with AI", permission develop with ai, given to admin and operator) shows the developers of the application what Rapyd Admin gives their coding assistant:

  • What your agent can do here: knows Rapyd Admin (guideline), builds modules and designs workflows (skills), knows Laravel and Livewire (Boost), reads the schema, the logs and the routes (MCP). Every capability that is missing names the command that unlocks it. Then the generators the agent calls instead of writing the code, and the estimated context it loads per session.
  • Built in this project: every module in app/Modules, generated by rpd:make (when, how many files, how many tokens the model did not have to write) or by hand, and whether it follows the conventions: authorized pages, permissions, Limits/, tests, workflows.
  • Try it: prompts to copy into the agent, each saying which packages it needs.
  • AI in the app: provider and model, widget mode, the tools the modules registered, the spend of the last 7 days against the daily budget.

This is rapyd-admin's php artisan rpd:ai:develop, as a page. Nothing on it calls a provider.

Tests

composer install && vendor/bin/phpunit