date('c'), 'source'=>'opus5-predictive-cache']; $redis = new Redis(); try { $redis->connect('127.0.0.1', 6379, 1.0); if (!$redis->ping()) { http_response_code(503); echo json_encode(['err'=>'redis_down']); exit; } } catch (Throwable $e) { http_response_code(503); echo json_encode(['err'=>'redis_err','msg'=>$e->getMessage()]); exit; } $PREFIX = 'wevia:predcache:'; $STATS_KEY = $PREFIX . 'stats'; $PATTERNS_KEY = $PREFIX . 'patterns'; $action = $_GET['action'] ?? 'stats'; switch ($action) { case 'get': $k = $_GET['key'] ?? ''; if (!$k) { http_response_code(400); echo json_encode(['err'=>'no_key']); exit; } $hash = 'msg:' . md5($k); $v = $redis->get($PREFIX . $hash); $redis->hIncrBy($STATS_KEY, 'gets', 1); if ($v !== false) { $redis->hIncrBy($STATS_KEY, 'hits', 1); $R['cache'] = 'HIT'; $R['value'] = json_decode($v, true); } else { $redis->hIncrBy($STATS_KEY, 'misses', 1); $R['cache'] = 'MISS'; } break; case 'set': $k = $_GET['key'] ?? ''; $raw = file_get_contents('php://input'); $body = json_decode($raw, true); if (!$k || !$body) { http_response_code(400); echo json_encode(['err'=>'missing']); exit; } $ttl = (int)($_GET['ttl'] ?? 300); // default 5 min $hash = 'msg:' . md5($k); $redis->setex($PREFIX . $hash, $ttl, json_encode($body, JSON_UNESCAPED_UNICODE)); // Track pattern (increment count for prediction) $redis->hIncrBy($PATTERNS_KEY, $k, 1); $redis->expire($PATTERNS_KEY, 86400 * 7); // 7 jours rolling $R['cache'] = 'SET'; $R['hash'] = $hash; $R['ttl'] = $ttl; break; case 'warm': // Pré-calcule les N requêtes les plus fréquentes $top = $redis->hGetAll($PATTERNS_KEY) ?: []; arsort($top); $top_n = array_slice($top, 0, 20, true); $warmed = 0; foreach ($top_n as $msg => $count) { if ($count < 3) continue; // skip if rare // Call autonomous-orchestrator pour pré-calculer $ch = curl_init('https://127.0.0.1/api/opus5-autonomous-orchestrator.php'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode(['message'=>$msg, 'session'=>'cache-warm-' . date('YmdHi')]), CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Host: weval-consulting.com'], CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => 0, CURLOPT_TIMEOUT => 10 ]); $resp = curl_exec($ch); curl_close($ch); $parsed = @json_decode($resp, true); if ($parsed && isset($parsed['final_response'])) { $hash = 'msg:' . md5($msg); $redis->setex($PREFIX . $hash, 600, json_encode([ 'response' => $parsed['final_response'], 'provider' => 'predictive-warm', 'warmed_at' => date('c'), 'original_provider' => $parsed['final_provider'] ?? '?' ], JSON_UNESCAPED_UNICODE)); $warmed++; } } $R['warmed'] = $warmed; $R['top_patterns'] = array_slice($top_n, 0, 10, true); break; case 'stats': $stats = $redis->hGetAll($STATS_KEY) ?: []; $stats['gets'] = (int)($stats['gets'] ?? 0); $stats['hits'] = (int)($stats['hits'] ?? 0); $stats['misses'] = (int)($stats['misses'] ?? 0); $stats['hit_rate_pct'] = $stats['gets'] > 0 ? round(($stats['hits'] / $stats['gets']) * 100, 1) : 0; $patterns = $redis->hGetAll($PATTERNS_KEY) ?: []; arsort($patterns); $R['stats'] = $stats; $R['patterns_count'] = count($patterns); $R['top_5_patterns'] = array_slice($patterns, 0, 5, true); // Keys count (scanned) $keys = []; $it = null; while (($scan = $redis->scan($it, $PREFIX . 'msg:*', 100)) !== false) { $keys = array_merge($keys, $scan); if (count($keys) > 500) break; } $R['cached_entries'] = count($keys); break; case 'train': // Analyse les logs pour extraire patterns temporels // TODO: parse /var/log/wevia/requests.log si exists $log = '/var/log/wevia/requests.log'; $detected = 0; if (file_exists($log)) { $lines = @file($log, FILE_IGNORE_NEW_LINES); if ($lines) { foreach (array_slice($lines, -1000) as $l) { if (preg_match('/"message"\s*:\s*"([^"]+)"/', $l, $m)) { $msg = substr($m[1], 0, 200); $redis->hIncrBy($PATTERNS_KEY, $msg, 1); $detected++; } } } } $R['trained_from_log'] = $detected; break; default: $R['err'] = 'unknown_action'; $R['available'] = ['get', 'set', 'warm', 'stats', 'train']; } $redis->close(); $R['doctrine'] = '68 — predictive cache Redis (hit rate tracking + top N warm + pattern learning)'; echo json_encode($R, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE);