bluefission/synthetiq

Adaptive conversational AI system

Maintainers

Package info

github.com/BlueFissionTech/synthetiq

pkg:composer/bluefission/synthetiq

Transparency log

Statistics

Installs: 22

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 2


README

SynthetIQ is a lightweight conversational library for building simple, low-cost chat experiences. It sits between rigid, scripted workflows and heavy generative systems by combining intent routing, template responses, and small-scale text prediction. The goal is flexible, consistent conversation for help systems, sales assistance, and low-risk dialogue where reliability matters more than creativity.

Design Intent

  • Keep responses predictable and low-cost by using templates and intent routing.
  • Allow lightweight variation and continuity with a small Markov predictor.
  • Favor consistent, repeatable behavior over unconstrained generation.
  • Lean on BlueFission Develation and Automata objects for language, decision, and context utilities.

How It Works

  1. Input is interpreted by an Automata language interpreter.
  2. Intents are classified via Automata analyzers and keyword matching.
  3. Responses are generated from templates attached to those intents.
  4. A decision tree and trigram Markov predictor score and select a response.
  5. Conversation history and context update for follow-up turns.
  6. Optional memory and fallback hooks can bias intent selection or route to a low-confidence fallback.
  7. Optional spell correction can normalize near-miss tokens before routing.

Install

SynthetIQ targets PHP 8.2 or newer.

composer require bluefission/synthetiq:^0.1.0-alpha

Quick Start

use BlueFission\SynthetIQ\SynthetIQ;
use BlueFission\SynthetIQ\Training\RouteTrainer;
use BlueFission\Automata\Language\{Interpreter, Grammar, StemmerLemmatizer, Documenter, Walker};
use BlueFission\Automata\Analysis\KeywordTopicAnalyzer;
use BlueFission\Automata\Strategy\NaiveBayesTextClassification;

$dialogue = require 'sample_configs/dialogue.php';
$intentBoosts = require 'sample_configs/intent_boosts.php';
$grammar = require 'sample_configs/grammar.php';
$tokens = require 'sample_configs/tokens.php';
$documenter = require 'sample_configs/documenter.php';

$interpreter = new Interpreter(
    new Grammar(new StemmerLemmatizer(), $grammar['rules'], $grammar['commands'], $tokens),
    $documenter,
    new Walker()
);

$analyzer = new KeywordTopicAnalyzer(new NaiveBayesTextClassification, 'models/ml/');

$ai = new SynthetIQ($interpreter, $analyzer);

RouteTrainer::train($ai, $dialogue, $intentBoosts);

$result = $ai->processInputEnvelope('hello');
echo $result['response'];

See example.php for a CLI and browser demo.

Examples

  • examples/support.php provides the shared sample bootstrap used by the examples.
  • example.php runs a small browser and CLI demo that returns response envelopes.
  • examples/cli.php runs a CLI-only loop with the sample configs and current route trainer.
  • examples/minimal.php shows a small custom routing setup for quick experiments.
  • examples/batch.php runs a fixed number of inputs from sample_configs/statements.php.
  • examples/sequence.php runs curated multi-turn batches and reports selected intents.
  • examples/envelope.php prints the structured response envelope, fallback state, correction metadata, and predictor diagnostics.
  • examples/evaluator.php runs an intent accuracy report through the current envelope API.
  • examples/route_state.php compiles, saves, loads, verifies, and applies cached route state.
  • examples/jenss/ contains optional JenSS stress fixtures for declarative route catalogs and feedback gates.
  • sample_configs/conversation_scenes.php contains deterministic scene contract examples.

Useful smoke commands:

php example.php hello
php examples/minimal.php hello
php examples/envelope.php hello
php examples/evaluator.php --no-progress
php examples/route_state.php --write --state=models/routes/synthetiq_routes.json --apply --probe=hello
php benchmarks/selection.php 1000 50 5

Client Configuration

Third-party clients for news/weather/location are configured in sample_configs/clients.php. These rely on the Composer package bluefission/simpleclients. External weather and news clients are disabled by default in the sample config so clean installs do not require credentials or app globals.

Use BlueFission\SynthetIQ\Clients\ClientResolver to wire optional clients explicitly:

use BlueFission\SynthetIQ\Clients\ClientResolver;
use BlueFission\SynthetIQ\Clients\WeatherClientInterface;

$resolver = ClientResolver::make(require 'sample_configs/clients.php');
$weatherClient = $resolver->client(WeatherClientInterface::class);

The sample config includes null clients for clean installs and lists the SimpleClients bindings that can be enabled by changing the enabled and bindings entries. A local fake-client example is available:

php examples/optional_clients.php

Core Components

  • BlueFission\SynthetIQ\SynthetIQ: orchestrates interpretation, intent classification, response generation, and selection.
  • BlueFission\SynthetIQ\Intents\IntelligenceRouter: combines matcher, keyword overlap, and optional Naive Bayes strategies.
  • BlueFission\SynthetIQ\Intents\Classifier: provides baseline intent matching and fallback keyword checks.
  • BlueFission\SynthetIQ\Responses\Generator: renders template-based responses.
  • BlueFission\SynthetIQ\Responses\Selector: selects responses using a decision tree and prediction heuristics.
  • BlueFission\SynthetIQ\ConversationHistory: stores input/response pairs.
  • BlueFission\SynthetIQ\Skills\*: optional Automata skills for common responses.
  • BlueFission\SynthetIQ\Memory\*: pluggable short-term memory adapters.
  • BlueFission\SynthetIQ\Fallback\*: low-confidence fallback responders.

Memory Recall

Memory adapters can bias intent routing and provide response-selection context. processInputEnvelope() includes recalled entries and a memory.selection summary showing which recalled episodes matched the selected response or response intent. Scope, permission checks, retrieval limits, and similarity thresholds remain adapter-owned.

See docs/memory-response-selection.md for the envelope fields and adapter responsibilities.

Routing and Templates

Routes are built by registering statements for an intent label. Each statement becomes:

  • an intent keyword hint,
  • a response template, and
  • training data for the trigram predictor.

This keeps behavior simple, repeatable, and easy to customize.

RouteTrainer centralizes route catalog registration, boost keyword handling, progress events, stable cache-key generation, and compiled route-state serialization:

use BlueFission\SynthetIQ\Training\RouteTrainer;

$state = RouteTrainer::compile($dialogue, $intentBoosts, [
    'grammar' => $grammar,
    'tokens' => $tokens,
]);

RouteTrainer::saveState($state, __DIR__ . '/models/routes.json');

if (RouteTrainer::stateMatches($state, $dialogue, $intentBoosts, ['grammar' => $grammar, 'tokens' => $tokens])) {
    RouteTrainer::apply($ai, $state);
}

The route-state example can be used as a non-interactive rollout smoke command:

php examples/route_state.php --write --state=models/routes/synthetiq_routes.json
php examples/route_state.php --state=models/routes/synthetiq_routes.json
php examples/route_state.php --state=models/routes/synthetiq_routes.json --apply --probe=hello

Intent Routing Strategies

SynthetIQ uses IntelligenceRouter by default. The router trains lightweight strategies from registered route keywords, combines their scores, and exposes diagnostics for review:

$ai = new SynthetIQ($interpreter, $analyzer, null, null, null, null, [
    'strategy_weights' => [
        'matcher' => 1.0,
        'keyword_overlap' => 0.75,
        'naive_bayes' => 0.5,
    ],
    'strategy_thresholds' => [
        'matcher' => 0.2,
        'keyword_overlap' => 0.1,
    ],
]);

For direct router use:

use BlueFission\SynthetIQ\Intents\IntelligenceRouter;

$router = new IntelligenceRouter($analyzer, null, [
    'enable_naive_bayes' => false,
]);

$scores = $router->score('hello there', $context);
$diagnostics = $router->lastDiagnostics();

Response Predictor Diagnostics

Response selection uses a bounded trigram predictor when available. The public diagnostic contract reports whether that predictor is available, disabled, unavailable, or failed, and whether response selection had to fall back to a candidate response:

$diagnostics = $ai->responsePredictorDiagnostics();

Use setResponsePredictor(null) to disable predictor-assisted selection while keeping template selection compatible. Custom predictors can expose predictNextWords, predictNextWord, or predictBeginning.

Local Model Fallback

LocalModelFallbackResponder provides an opt-in adapter contract for unknown or low-confidence turns. Hosts provide a FallbackProviderInterface; SynthetIQ captures prompts, responses, fallback reasons, confidence, selected intent metadata, and candidate review status through TrainingCandidateStore.

The default fallback remains disabled unless explicitly configured. See docs/llm-fallback-training.md and sample_configs/fallback_training.php.

Response Envelope

processInput(string) still returns the selected response string. Use processInputEnvelope(string) when callers need structured diagnostics for a turn:

$result = $ai->processInputEnvelope('hello');

echo $result['response'];
$intent = $result['intent']['label'];
$responseRoute = $result['response_route']['label'];
$predictor = $result['predictor']['status'];

The envelope includes the response text, raw and normalized input, classified intent label, confidence, score map, selected response route, fallback state, memory recall summary, correction metadata, and response predictor diagnostics.

Use classifyInput() when evaluating or tooling only needs the classified intent and should not generate a response or append to conversation history.

Scripted Template Blocks

Response templates support opt-in {=...} blocks for bounded dynamic values. The renderer resolves input, intent, and context.* paths plus the safe transforms upper, lower, trim, and capitalize. It does not execute arbitrary PHP or external scripts.

$ai->enableScriptedTemplates(true);

When disabled, scripted blocks remain literal text. See docs/scripted-templates.md and sample_configs/scripted_templates.php.

Policy Filters And Audit

Policy filters can inspect input and output text around the deterministic pipeline. Denied input returns a configured replacement response; denied output can replace the selected response. Response envelopes include policy status and the structured audit trail.

use BlueFission\SynthetIQ\Policy\NullPolicyFilter;

$ai->addPolicyFilter(new NullPolicyFilter());
$envelope = $ai->processInputEnvelope('hello');
$audit = $envelope['audit'];

Use setAuditRedactor() to redact audit payloads before they are recorded. See docs/policy-audit.md for the contract and boundary notes.

Conversation Flow Graphs

BlueFission\SynthetIQ\Flow\ConversationFlow defines explicit multi-turn states, allowed intents, transitions, fallback intents, and completion state. Attach a flow to constrain routing while a task is active:

use BlueFission\SynthetIQ\Flow\ConversationFlow;

$flow = ConversationFlow::fromArray(require 'sample_configs/conversation_flow.php');
$ai->setConversationFlow($flow);

$envelope = $ai->processInputEnvelope('ship');
$current = $envelope['flow']['current_state'];

Flows can be reset, completed, or abandoned through SynthetIQ methods.

Conversation State

BlueFission\SynthetIQ\State\ConversationState stores persona, mood, tone, task slots, session metadata, and turn summaries. SynthetIQ applies this state to the Automata context before each turn so routing, memory metadata, and response templates can read it without app globals:

use BlueFission\SynthetIQ\State\ConversationState;

$state = ConversationState::fromArray(require 'sample_configs/conversation_state.php');
$ai->setConversationState($state);

$envelope = $ai->processInputEnvelope('status');
$tone = $envelope['state']['tone'];

Conversation Scene Contracts

BlueFission\SynthetIQ\Scenes\SceneContract validates deterministic scene definitions for authored conversation paths. Scene definitions include states, dialogue prompts, choices, fallback prompts, voice policy, public-safety constraints, and handoff metadata.

use BlueFission\SynthetIQ\Scenes\SceneContract;

$scenes = require 'sample_configs/conversation_scenes.php';
$errors = SceneContract::validate($scenes['proof_walkthrough']);

See docs/conversation-scenes.md for the full contract shape and package boundaries.

Notes and Constraints

  • This library is not a generative model. It predicts and selects from known statements.
  • Some skills (weather/news/status) depend on external services or app-specific globals and should be wired explicitly or excluded in lightweight deployments.
  • src/Models/LearningModel.php is optional and not yet integrated with SynthetIQ.
  • Generated cache and model artifacts belong under models/ and should not be committed.
  • Spell correction is lightweight and vocabulary-driven. You can disable it with:
$ai->enableSpellCorrection(false);

Testing

See tests.md for the full clean-install checklist, focused suites, optional fixture environment variables, and generated artifact policy.

vendor/bin/phpunit --do-not-cache-result

Optional JenSS fixture smoke tests require a local Jenerator autoload path:

SYNTHETIQ_JENERATOR_AUTOLOAD=/path/to/jenerator/vendor/autoload.php vendor/bin/phpunit --do-not-cache-result tests/Jenss

Benchmarking

php benchmarks/selection.php 1000 50 5

The current benchmark is a local smoke command, not a hard CI budget gate.

License

MIT