88 lines
2.8 KiB
PHP
88 lines
2.8 KiB
PHP
<?php
|
|
// DOCTRINE 217 — Brain Training Dashboard Endpoint
|
|
// URL: /api/brain-training.php
|
|
// Shows: training state, runs history, proposals pending approval, quality trend
|
|
|
|
header('Content-Type: application/json');
|
|
error_reporting(E_ERROR);
|
|
|
|
$TRAINING_DIR = '/opt/wevia-brain/training';
|
|
$state_file = "$TRAINING_DIR/training-state.json";
|
|
$runs_log = "$TRAINING_DIR/training-state.json.log";
|
|
$proposals_file = "$TRAINING_DIR/training-proposals.jsonl";
|
|
|
|
$out = [
|
|
'doctrine' => 217,
|
|
'module' => 'brain-permanent-training',
|
|
'status' => 'UP',
|
|
'timestamp' => date('c'),
|
|
];
|
|
|
|
// Current state snapshot
|
|
$out['current_state'] = is_readable($state_file)
|
|
? @json_decode(@file_get_contents($state_file), true)
|
|
: null;
|
|
|
|
// Last 20 runs
|
|
$runs = [];
|
|
if (is_readable($runs_log)) {
|
|
$lines = @file($runs_log, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: [];
|
|
$last_20 = array_slice($lines, -20);
|
|
foreach ($last_20 as $ln) {
|
|
$parsed = @json_decode($ln, true);
|
|
if ($parsed) $runs[] = $parsed;
|
|
}
|
|
}
|
|
$out['recent_runs'] = $runs;
|
|
$out['runs_count_24h'] = count(array_filter($runs, fn($r) => strtotime($r['ts'] ?? 0) > time() - 86400));
|
|
|
|
// Proposals pending approval
|
|
$proposals = [];
|
|
if (is_readable($proposals_file)) {
|
|
$tail = @shell_exec("sudo tail -30 $proposals_file 2>/dev/null") ?? '';
|
|
foreach (explode("\n", $tail) as $ln) {
|
|
if (empty(trim($ln))) continue;
|
|
$p = @json_decode($ln, true);
|
|
if ($p && ($p['status'] ?? '') === 'pending_approval') {
|
|
$proposals[] = $p;
|
|
}
|
|
}
|
|
}
|
|
$out['pending_proposals'] = array_slice($proposals, -10);
|
|
$out['pending_count'] = count($proposals);
|
|
|
|
// Quality trend (last 10 runs)
|
|
if (count($runs) >= 2) {
|
|
$recent = array_slice($runs, -10);
|
|
$scores = array_column($recent, 'avg_score');
|
|
$scores = array_filter($scores, fn($s) => $s > 0);
|
|
if ($scores) {
|
|
$out['quality_trend'] = [
|
|
'avg' => round(array_sum($scores) / count($scores), 2),
|
|
'min' => min($scores),
|
|
'max' => max($scores),
|
|
'direction' => end($scores) > reset($scores) ? 'improving' : 'stable',
|
|
];
|
|
}
|
|
}
|
|
|
|
// Aggregate
|
|
$total_proposals = array_sum(array_column($runs, 'proposals'));
|
|
$total_hallucinations = array_sum(array_column($runs, 'hallucinations'));
|
|
$total_harvests = array_sum(array_column($runs, 'harvest'));
|
|
|
|
$out['aggregate'] = [
|
|
'total_proposals_generated' => $total_proposals,
|
|
'total_hallucinations_detected' => $total_hallucinations,
|
|
'total_queries_harvested' => $total_harvests,
|
|
];
|
|
|
|
// Cron schedule check
|
|
$cron_file = '/etc/cron.d/wevia-brain-training';
|
|
$out['cron'] = [
|
|
'installed' => is_readable($cron_file),
|
|
'schedule' => is_readable($cron_file) ? trim(@file_get_contents($cron_file)) : null,
|
|
];
|
|
|
|
echo json_encode($out, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|