AIConnector Plugin

The AIConnector plugin extends DGS (Data Grid Store) with LLM integration. AI-capable fields (e.g. aiTextarea, aiFile) can define a prompt and show an "Apply AI" button. On click, the current value (or uploaded file) is sent to an LLM service (OpenAI, Claude, Ollama), and the result is applied back to the form.

Requirements

  • festi-framework-core (DGS, store, actions)
  • festi-framework-ai (LLM clients: OpenAI, Claude, Ollama)

Installation

  1. Place the plugin in the project's plugins directory (e.g. plugins/AIConnector/).
  2. Ensure the project loads the plugin (e.g. via init.php or plugin registry) and that AIConnectorPlugin is instantiated and its init hooks run (store init, response).

Configuration

1. AI services (database-managed, recommended)

Navigate to /manage/ai/services/ (requires the AIConnectorSections::MANAGE permission). Add a service row with provider, model, API key, and optionally org ID, endpoint, and timeout. Click Default on the row you want active — the plugin verifies connectivity and model availability before marking it as the default. The default service is loaded into Core::getConfigValue('ai') automatically on every request via Core::EVENT_ON_AFTER_INIT.

Rules enforced by the UI: - Only one row can be the default at a time. - A disabled service cannot be set as the default. - The Default action button is hidden for rows that are already the default or are disabled.

2. AI connection (manual fallback)

If you are not using the database-managed services, set the config directly before any AI action runs:

$GLOBALS['config']['ai'] = [
    'provider' => 'openai',      // openai, claude, or ollama
    'model'    => 'gpt-4',
    'key'      => 'sk-proj-XXXX',
    'org_id'   => 'org-xxxxxxxx',  // optional
    'endpoint' => null,            // optional
    'timeout'  => 60,              // optional, seconds
];

Runtime lookup is done via Core::getInstance()->getConfigValue('ai') (not by direct $GLOBALS access in action code). The plugin validates and normalizes this section using AIProviderConfig.

For local Ollama, use 'provider' => 'ollama', set 'endpoint' => 'http://localhost:11434/api/', and leave key empty.

For Claude, use 'provider' => 'claude' with your Anthropic API key.

3. Declare the Apply AI action in your store (table) XML

Use the action class name as type (per DGS Actions: pass the class name as the type attribute).

<actions>
    <action type="<?php echo \Plugins\AIConnector\Domain\Store\Action\ApplyAIAction::class; ?>"
            caption="<?php echo __('Apply AI'); ?>" />
</actions>

4. Add an AI-capable field with a prompt (enables the "Apply AI" button):

<field type="Plugins\AIConnector\Domain\Store\Field\AITextareaField"
       name="summary"
       caption="<?php echo __('Summary'); ?>"
       prompt="Summarize in 2 sentences: %summary%"
       aiFormat="text" />

Use %fieldName% in the prompt for current form values. aiFormat may be text (default) or json for structured output.

5. Frontend The plugin includes static/js/ai-connector.js and registers it on response. Ensure the store form view is one where the plugin's script is loaded (typical when using the framework's store views).

Usage

  1. Open a form for a store that has the Apply AI action and at least one field with a prompt.
  2. Fill the field (or upload a file for AIFileField).
  3. Click Apply AI. The prompt is sent to the LLM; the response is applied to the form (and optionally mapped to multiple fields when aiFormat="json").

For file-based extraction (e.g. CV), use AIFileField with prompt and aiFormat="json". For multiple fields from one AI response, use events (BeforeResolvedValuesPrepareEvent for custom mapping, AfterAICompleteEvent for logging) — see Apply AI action and configuration for events, DOCX extractors, and advanced use cases.

Events

The Apply AI flow dispatches these events (in order):

Event Purpose
BeforePromptPrepareEvent Customize the prompt before sending to the LLM
BeforeAIRequestEvent Override model, system instructions, JSON schema; register document extractors
BeforeResolvedValuesPrepareEvent Recover malformed JSON, add warnings, or provide custom field mapping
AfterAICompleteEvent Logging, analytics, access to response data

See Apply AI action and configuration for details and examples.

Registering Custom Document Extractors

The AI framework includes default extractors for plain text and PDF files. To support additional document formats (e.g. DOCX, ODT, RTF), register custom extractors via the BeforeAIRequestEvent or pass them to createConnection().

Option 1: In BeforeAIRequestEvent (Store context)

use AI\Utils\Extractor\IDocumentExtraction;
use Plugins\AIConnector\Domain\Store\Event\BeforeAIRequestEvent;

$store->addEventListener(
    BeforeAIRequestEvent::EVENT_TYPE,
    function (BeforeAIRequestEvent &$event) {
        $client = $event->getClient();

        if (!$client instanceof IDocumentExtraction) {
            return;
        }

        $extractor = new MyCustomExtractor();

        $client->registerDocumentExtractor($extractor);
    }
);

Option 2: Via createConnection() (outside Store context)

use Plugins\AIConnector\Domain\Store\Action\Client\AIProviderConfig;

$plugin = Core::getInstance()->getPluginInstance(AIConnectorPlugin::class);

// Pass extractors as second argument
$extractor = new MyCustomExtractor();
$extractors = [
    $extractor,
];

$connection = $plugin->createConnection(null, $extractors);

// Or with custom config
$customConfig = new AIProviderConfig('claude', 'claude-3-opus', $apiKey);

$connection = $plugin->createConnection($customConfig, $extractors);

Security

  • Authentication: Ensure proper user authentication before AI requests.
  • Rate limiting: Implement rate limiting to prevent abuse.
  • Input validation: All user input is validated before sending to the LLM.
  • Prompt injection: Be aware of prompt injection risks with user-provided content.
  • Cost control: Monitor API usage to control LLM costs.