Initial public push: docs cosmos v4 + AI module + framework groundwork
This is the snapshot the production landing site (nibiru-framework.com) is deployed from. Brings together the recent splash + docs migration to the v4 "Cosmos" design system, the new in-framework AI module, and the framework groundwork that backs the framework-reference extraction. What lands: - docs/: Astro + Starlight site with the v4 dark cosmic palette, GalaxyHero canvas constellation, Mission Control chat (wired to /api/oracle → api.neuronetz.ai via providers.mjs Ollama), 5-panel MMVC stage (Model · AI · Module · Controller · View), translated EN/DE/JA/ES/FR content, PWA + sitemap + llms.txt + Umami analytics. - docs/design-system/: canonical mockup bundle (source/index-v2.html for splash, source/docs-system.html + preview/ for docs, SPEC.md, tokens). - docs/scripts/extraction/framework-reference-v2.md: deep framework reference (~1.6k lines, file:line citations, every public factory and idiom — basis for the LoRA training corpus. - application/module/ai/: AI module with chat / embed / RAG / agent plugins, plus pdoQuery / httpGet / fileRead tools and Modelfile + smoke-test in training/. - application/module/users/: user / ACL / form-factory traits used as the reference plugin pattern for the framework docs. - application/settings/config/database/: schema + seed migrations including the AI module tables (200–203). - Form factory + autogenerator changes the framework-reference-v2 covers. Production secrets stay out: docs/.env, settings.production.ini and ai.production.ini are all gitignored (.example files are in tree). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
114
application/module/ai/plugins/chat.php
Normal file
114
application/module/ai/plugins/chat.php
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
namespace Nibiru\Module\Ai\Plugins;
|
||||
|
||||
/**
|
||||
* Chat completions. Talks to Ollama (default) or Anthropic (when configured).
|
||||
*
|
||||
* $ai = new \Nibiru\Module\Ai\Ai();
|
||||
* $reply = $ai->chat()->ask('How do I scaffold a module?');
|
||||
*
|
||||
* // Multi-turn:
|
||||
* $chat = $ai->chat();
|
||||
* $chat->user('How do I scaffold a module?');
|
||||
* $chat->user('And add Graylog hooks?');
|
||||
* echo $chat->complete();
|
||||
*
|
||||
* // Custom system + model:
|
||||
* echo $ai->chat()
|
||||
* ->system('Answer in German.')
|
||||
* ->user('Explain MMVC.')
|
||||
* ->model('qwen2.5-coder:14b')
|
||||
* ->complete();
|
||||
*/
|
||||
class Chat
|
||||
{
|
||||
protected \stdClass $cfg;
|
||||
protected Ollama $ollama;
|
||||
|
||||
/** @var array<int, array{role:string,content:string}> */
|
||||
protected array $messages = [];
|
||||
|
||||
protected ?string $modelOverride = null;
|
||||
protected ?float $temperature = null;
|
||||
protected ?int $maxTokens = null;
|
||||
protected ?string $systemPrompt = null;
|
||||
|
||||
public function __construct(\stdClass $cfg)
|
||||
{
|
||||
$this->cfg = $cfg;
|
||||
$this->ollama = new Ollama($cfg);
|
||||
$this->systemPrompt = $cfg->chat_system_prompt ?? null;
|
||||
}
|
||||
|
||||
public function system(string $prompt): self { $this->systemPrompt = $prompt; return $this; }
|
||||
public function model(string $name): self { $this->modelOverride = $name; return $this; }
|
||||
public function temperature(float $t): self { $this->temperature = $t; return $this; }
|
||||
public function maxTokens(int $n): self { $this->maxTokens = $n; return $this; }
|
||||
|
||||
public function user(string $content): self { $this->messages[] = ['role' => 'user', 'content' => $content]; return $this; }
|
||||
public function assistant(string $content): self { $this->messages[] = ['role' => 'assistant', 'content' => $content]; return $this; }
|
||||
|
||||
/**
|
||||
* Execute the chat call and return the assistant's reply text.
|
||||
* Appends the reply to the message history.
|
||||
*/
|
||||
public function complete(): string
|
||||
{
|
||||
$apiMessages = [];
|
||||
if ($this->systemPrompt) {
|
||||
$apiMessages[] = ['role' => 'system', 'content' => $this->systemPrompt];
|
||||
}
|
||||
foreach ($this->messages as $m) {
|
||||
$apiMessages[] = $m;
|
||||
}
|
||||
|
||||
$model = $this->modelOverride
|
||||
?? ($this->cfg->chat_model ?? 'qwen2.5-coder:14b');
|
||||
$fallback = $this->cfg->chat_fallback_model ?? null;
|
||||
|
||||
$opts = [
|
||||
'temperature' => $this->temperature ?? (float) ($this->cfg->chat_temperature ?? 0.4),
|
||||
'num_predict' => $this->maxTokens ?? (int) ($this->cfg->chat_max_tokens ?? 1024),
|
||||
];
|
||||
|
||||
try {
|
||||
$res = $this->ollama->chat($model, $apiMessages, $opts);
|
||||
} catch (\RuntimeException $e) {
|
||||
if ($fallback && $fallback !== $model) {
|
||||
$res = $this->ollama->chat($fallback, $apiMessages, $opts);
|
||||
} else {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
$text = $res['message']['content'] ?? '';
|
||||
$this->assistant($text);
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* One-shot helper — append a user message, complete, return reply.
|
||||
*/
|
||||
public function ask(string $question): string
|
||||
{
|
||||
$this->user($question);
|
||||
return $this->complete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the conversation (keeps system prompt + model override).
|
||||
*/
|
||||
public function reset(): self
|
||||
{
|
||||
$this->messages = [];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, array{role:string,content:string}> the conversation
|
||||
*/
|
||||
public function history(): array
|
||||
{
|
||||
return $this->messages;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user