Files
wevia-brain/cognitive-opus46.php
2026-04-12 23:01:36 +02:00

1147 lines
55 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* ╔═══════════════════════════════════════════════════════════════════════════╗
* ║ WEVIA COGNITIVE OPUS 4.6 — Advanced Reasoning Capabilities ║
* ║ Chain-of-Thought, Metacognition, Adversarial, Cross-Domain, Planning ║
* ║ GPU Sovereign Pipeline, Confidence Calibration, Self-Correction ║
* ║ 2026-03-03 — 200+ functions ║
* ╚═══════════════════════════════════════════════════════════════════════════╝
*/
// ═══════════════════════════════════════════════════════════════════════════
// MODULE L: CHAIN-OF-THOUGHT ENGINE (20 functions)
// Multi-step reasoning with visible thinking
// ═══════════════════════════════════════════════════════════════════════════
function cotShouldActivate($msg, $intent) {
if (mb_strlen($msg) < 30 || in_array($intent, ['greeting','conversational'])) return false;
if (preg_match('/\b(pourquoi|why|comment|how|explique|compare|analyse|évalue|calcule|estime)\b/i', $msg)) return true;
if (preg_match('/\b(debug|erreur|problème|migr|architect|stratégi|optimis)\b/i', $msg)) return true;
return mb_strlen($msg) > 120;
}
function cotDecomposeSteps($msg) {
$steps = [];
$steps[] = ['phase' => 'comprehension', 'action' => 'Comprendre la demande exacte', 'weight' => 1];
if (preg_match('/\b(compare|vs|versus|différence|choix)\b/i', $msg)) {
$steps[] = ['phase' => 'gather', 'action' => 'Collecter les critères de comparaison', 'weight' => 2];
$steps[] = ['phase' => 'analyze', 'action' => 'Analyser chaque option selon les critères', 'weight' => 3];
$steps[] = ['phase' => 'synthesize', 'action' => 'Synthétiser et recommander', 'weight' => 2];
} elseif (preg_match('/\b(debug|erreur|problème|fix|corrig)\b/i', $msg)) {
$steps[] = ['phase' => 'reproduce', 'action' => 'Identifier les symptômes exacts', 'weight' => 2];
$steps[] = ['phase' => 'hypothesize', 'action' => 'Formuler les hypothèses (top 3)', 'weight' => 3];
$steps[] = ['phase' => 'test', 'action' => 'Proposer tests de vérification', 'weight' => 2];
$steps[] = ['phase' => 'solve', 'action' => 'Solution avec commandes/code', 'weight' => 3];
} elseif (preg_match('/\b(calcul|estime|combien|budget|coût|ROI)\b/i', $msg)) {
$steps[] = ['phase' => 'identify', 'action' => 'Identifier les variables', 'weight' => 1];
$steps[] = ['phase' => 'compute', 'action' => 'Calculer étape par étape', 'weight' => 3];
$steps[] = ['phase' => 'verify', 'action' => 'Vérifier par méthode alternative', 'weight' => 2];
} else {
$steps[] = ['phase' => 'research', 'action' => 'Rassembler les connaissances pertinentes', 'weight' => 2];
$steps[] = ['phase' => 'structure', 'action' => 'Structurer la réponse', 'weight' => 2];
$steps[] = ['phase' => 'deliver', 'action' => 'Formuler la réponse actionnable', 'weight' => 3];
}
return $steps;
}
function cotBuildThinkingPrompt($steps) {
$prompt = "\n## RAISONNEMENT STRUCTURÉ\nAvant de répondre, suis ces étapes de réflexion :\n";
foreach ($steps as $i => $s) {
$prompt .= ($i + 1) . ". **{$s['phase']}**: {$s['action']}\n";
}
$prompt .= "\nMontre ton raisonnement naturellement dans ta réponse (pas de balises <think>).";
return $prompt;
}
function cotExtractThinking($response) {
if (preg_match('/<think>(.*?)<\/think>/s', $response, $m)) {
return ['thinking' => trim($m[1]), 'response' => trim(str_replace($m[0], '', $response))];
}
return ['thinking' => '', 'response' => $response];
}
function cotCountReasoningSteps($response) {
$steps = 0;
$steps += preg_match_all('/\b(d\'abord|premièrement|first|ensuite|puis|then|enfin|finally|en conclusion)\b/i', $response);
$steps += preg_match_all('/^\d+[\.\)]/m', $response);
return $steps;
}
function cotValidateCompleteness($response, $steps) {
$expected = count($steps);
$found = cotCountReasoningSteps($response);
return ['expected' => $expected, 'found' => $found, 'complete' => $found >= $expected - 1];
}
function cotInjectPrompt($sys, $msg, $intent) {
if (!cotShouldActivate($msg, $intent)) return $sys;
$steps = cotDecomposeSteps($msg);
return $sys . cotBuildThinkingPrompt($steps);
}
function cotEstimateDepth($msg) {
$depth = 1;
if (mb_strlen($msg) > 100) $depth++;
if (mb_strlen($msg) > 300) $depth++;
if (substr_count($msg, '?') > 1) $depth++;
if (preg_match('/\b(détaillé|exhaustif|approfondi|complet|en profondeur)\b/i', $msg)) $depth += 2;
return min(5, $depth);
}
function cotSelectStrategy($msg) {
if (preg_match('/\b(pourquoi|why|cause|raison)\b/i', $msg)) return 'causal_chain';
if (preg_match('/\b(compare|vs|versus|meilleur|choix)\b/i', $msg)) return 'parallel_analysis';
if (preg_match('/\b(si|if|hypothèse|scénario|suppose)\b/i', $msg)) return 'counterfactual';
if (preg_match('/\b(étape|step|procédure|comment faire)\b/i', $msg)) return 'sequential';
if (preg_match('/\b(avantage|inconvénient|pour|contre|trade-off)\b/i', $msg)) return 'dialectical';
return 'general';
}
function cotBuildCausalChain($topic) {
return "\nAnalyse causale: Identifie la chaîne Cause → Mécanisme → Effet → Conséquences. Distingue corrélation/causalité.";
}
function cotBuildParallelAnalysis($options) {
return "\nAnalyse parallèle: Pour CHAQUE option, évalue selon les mêmes critères. Tableau comparatif. Score pondéré.";
}
function cotBuildCounterfactual($hypothesis) {
return "\nAnalyse contrefactuelle: Si [hypothèse], alors [conséquence]. Et si le contraire? Scénario alternatif.";
}
function cotBuildSequential() {
return "\nRaisonnement séquentiel: Étape 1 → vérifier → Étape 2 → vérifier → ... Chaque étape dépend de la précédente.";
}
function cotBuildDialectical() {
return "\nDialectique: Thèse → Antithèse → Synthèse. Présente les deux côtés avant de conclure.";
}
function cotGetStrategyPrompt($msg) {
$strategy = cotSelectStrategy($msg);
$prompts = [
'causal_chain' => cotBuildCausalChain(''),
'parallel_analysis' => cotBuildParallelAnalysis([]),
'counterfactual' => cotBuildCounterfactual(''),
'sequential' => cotBuildSequential(),
'dialectical' => cotBuildDialectical(),
'general' => "\nRaisonnement structuré: Comprendre → Analyser → Conclure.",
];
return $prompts[$strategy] ?? $prompts['general'];
}
function cotMeasureCoherence($response) {
$sentences = preg_split('/[.!?]+/', $response);
$sentences = array_filter($sentences, fn($s) => mb_strlen(trim($s)) > 10);
if (count($sentences) < 2) return 1.0;
$hasContradiction = preg_match('/\b(mais.*cependant|toutefois.*néanmoins|oui.*non.*oui)\b/i', $response);
$hasStructure = preg_match('/\b(d\'abord|ensuite|enfin|en conclusion|donc|par conséquent)\b/i', $response);
$score = 0.5;
if ($hasStructure) $score += 0.3;
if (!$hasContradiction) $score += 0.2;
return min(1.0, $score);
}
function cotShouldRetry($response, $msg) {
$coherence = cotMeasureCoherence($response);
if ($coherence < 0.4) return true;
if (mb_strlen($response) < 50 && mb_strlen($msg) > 100) return true;
if (preg_match('/je ne (sais|peux) pas/i', $response) && mb_strlen($msg) < 200) return true;
return false;
}
function cotEnhanceResponse($response, $strategy) {
if ($strategy === 'parallel_analysis' && !preg_match('/\|/', $response)) {
$response .= "\n\n💡 *Un tableau comparatif pourrait aider — demandez si vous souhaitez un format structuré.*";
}
return $response;
}
function cotSummarizeReasoning($thinking) {
if (empty($thinking)) return '';
$sentences = preg_split('/[.!?]+/', $thinking);
$key = array_filter($sentences, fn($s) => mb_strlen(trim($s)) > 30);
return mb_substr(implode('. ', array_slice($key, 0, 2)), 0, 200);
}
// ═══════════════════════════════════════════════════════════════════════════
// MODULE M: METACOGNITION ENGINE (20 functions)
// Self-awareness, confidence, and reflection
// ═══════════════════════════════════════════════════════════════════════════
function metaAssessConfidence($response, $msg, $kbUsed) {
$confidence = 0.5;
if ($kbUsed) $confidence += 0.2;
if (preg_match('/```/', $response)) $confidence += 0.1; // Code = concrete
if (preg_match('/\b(peut-être|probablement|il semble|je pense)\b/i', $response)) $confidence -= 0.1;
if (preg_match('/\b(certainement|absolument|toujours|jamais)\b/i', $response)) $confidence -= 0.05; // Overconfidence penalty
if (mb_strlen($response) > 500 && preg_match('/\b(source|référence|documentation)\b/i', $response)) $confidence += 0.1;
return round(max(0.1, min(1.0, $confidence)), 2);
}
function metaShouldHedge($confidence, $intent) {
if ($intent === 'mathematical') return $confidence < 0.7;
if ($intent === 'technical') return $confidence < 0.5;
if ($intent === 'strategic') return $confidence < 0.6;
return $confidence < 0.4;
}
function metaInjectHedging($response, $confidence) {
if ($confidence >= 0.6) return $response;
$hedges = [
"⚠️ **Note:** Mon niveau de confiance est modéré sur ce point. Je recommande de vérifier.",
"💡 Cette analyse mériterait une validation supplémentaire.",
"📋 Basé sur mes connaissances actuelles — une vérification avec la documentation officielle est recommandée."
];
$idx = crc32($response) % count($hedges);
return $response . "\n\n" . $hedges[$idx];
}
function metaDetectKnowledgeGap($msg, $kbResults) {
if (empty($kbResults) && preg_match('/\b(spécifique|notre|interne|WEVAL|client)\b/i', $msg)) return 'internal_gap';
if (preg_match('/\b(202[5-9]|dernier|récent|nouveau|latest)\b/i', $msg)) return 'temporal_gap';
if (preg_match('/\b(prix|tarif|coût actuel|taux de change)\b/i', $msg)) return 'realtime_gap';
return null;
}
function metaAcknowledgeGap($gap) {
$msgs = [
'internal_gap' => "Je n'ai pas trouvé cette information dans notre base de connaissances interne.",
'temporal_gap' => "Cette information pourrait ne pas être à jour — vérifiez les sources récentes.",
'realtime_gap' => "Les données en temps réel nécessitent une vérification externe.",
];
return $msgs[$gap] ?? "";
}
function metaReflectOnResponse($response, $msg) {
$issues = [];
if (mb_strlen($response) > 2000 && !preg_match('/^#+\s/m', $response)) $issues[] = 'long_unstructured';
if (mb_strlen($response) < 100 && mb_strlen($msg) > 200) $issues[] = 'too_brief';
if (preg_match('/TODO|à compléter|\.\.\.$/m', $response)) $issues[] = 'incomplete';
if (preg_match('/je ne (sais|peux) pas.*je ne (sais|peux) pas/is', $response)) $issues[] = 'repeated_inability';
return $issues;
}
function metaSelfCorrect($response, $issues) {
foreach ($issues as $issue) {
if ($issue === 'long_unstructured') {
$response = "📋 **Résumé:**\n" . mb_substr($response, 0, 200) . "...\n\n---\n\n" . $response;
}
}
return $response;
}
function metaEstimateResponseQuality($response, $intent, $msg) {
$score = 7;
if (function_exists('validateCodeCompleteness') && preg_match('/```/', $response)) {
$codeIssues = validateCodeCompleteness($response);
$score -= count($codeIssues) * 0.5;
}
if (function_exists('validateNoLeakedInternals')) {
$leak = validateNoLeakedInternals($response);
if ($leak) $score -= 3;
}
$coherence = cotMeasureCoherence($response);
$score += ($coherence - 0.5) * 4;
return round(max(1, min(10, $score)), 1);
}
function metaSelectExpertiseLevel($msg, $history) {
if (count($history) > 6) {
$techCount = 0;
foreach ($history as $h) {
if (preg_match('/\b(code|api|server|database|deploy|config)\b/i', $h['content'] ?? '')) $techCount++;
}
if ($techCount > count($history) * 0.5) return 'expert';
}
if (function_exists('detectExpertiseLevel')) return detectExpertiseLevel($msg);
return 'intermediate';
}
function metaTrackTopicDrift($history, $msg) {
if (count($history) < 4) return false;
$last3 = array_slice($history, -3);
$topics = [];
foreach ($last3 as $h) {
$c = mb_strtolower($h['content'] ?? '');
preg_match_all('/\b\w{5,}\b/', $c, $m);
$topics[] = $m[0] ?? [];
}
if (count($topics) < 2) return false;
$overlap = count(array_intersect($topics[0], $topics[count($topics)-1]));
return $overlap < 2;
}
function metaDetectRepetition($history, $response) {
$recent = array_slice($history, -4);
foreach ($recent as $h) {
if (($h['role'] ?? '') === 'assistant') {
$prev = mb_strtolower($h['content'] ?? '');
$curr = mb_strtolower($response);
similar_text($prev, $curr, $pct);
if ($pct > 60) return true;
}
}
return false;
}
function metaInjectVariation($response, $history) {
if (!metaDetectRepetition($history, $response)) return $response;
return "🔄 Reformulons autrement...\n\n" . $response;
}
function metaAssessHallucination($response, $kbContext) {
$risk = 0.3;
if (preg_match('/\b(\d{4})\b/', $response, $m)) {
$year = intval($m[1]);
if ($year > 2026) $risk += 0.3;
}
if (empty($kbContext) && preg_match('/selon (notre|la) base|dans notre KB/i', $response)) $risk += 0.4;
if (preg_match('/\b(toujours|jamais|100%|garantie|certain)\b/i', $response)) $risk += 0.1;
return min(1.0, $risk);
}
function metaInjectConfidenceMarker($response, $confidence) {
$markers = ['🔴' => [0, 0.3], '🟡' => [0.3, 0.6], '🟢' => [0.6, 0.8], '🔵' => [0.8, 1.01]];
foreach ($markers as $emoji => $range) {
if ($confidence >= $range[0] && $confidence < $range[1]) return $response;
}
return $response;
}
function metaBuildSelfCheckPrompt() {
return "\nAvant de finaliser ta réponse, vérifie mentalement : 1) Ai-je répondu à la question ? 2) Mon code est-il complet et exécutable ? 3) Ai-je vérifié les faits ? 4) La réponse est-elle actionnable ?";
}
function metaDetectOverconfidence($response) {
$overconfident = preg_match_all('/\b(toujours|jamais|certainement|absolument|sans aucun doute|garantie|100%)\b/i', $response);
$hedged = preg_match_all('/\b(peut-être|généralement|souvent|typiquement|dans la plupart des cas)\b/i', $response);
return $overconfident > $hedged + 2;
}
function metaSoftenOverconfidence($response) {
if (!metaDetectOverconfidence($response)) return $response;
$response = preg_replace('/\btoujours\b/i', 'généralement', $response, 1);
$response = preg_replace('/\bjamais\b/i', 'rarement', $response, 1);
$response = preg_replace('/\b100%\b/', '~95%+', $response, 1);
return $response;
}
function metaEstimateTokenUsage($sys, $msg, $history) {
$total = mb_strlen($sys) + mb_strlen($msg);
foreach ($history as $h) $total += mb_strlen($h['content'] ?? '');
return (int)($total / 3.5);
}
function metaShouldCompressHistory($history, $maxTokens = 4000) {
$tokens = 0;
foreach ($history as $h) $tokens += (int)(mb_strlen($h['content'] ?? '') / 3.5);
return $tokens > $maxTokens;
}
// ═══════════════════════════════════════════════════════════════════════════
// MODULE N: ADVERSARIAL VERIFICATION (15 functions)
// Devil's advocate — challenge and verify responses
// ═══════════════════════════════════════════════════════════════════════════
function advShouldVerify($intent, $confidence) {
if (in_array($intent, ['mathematical','technical','compliance'])) return true;
if ($confidence < 0.5) return true;
return false;
}
function advBuildChallengePrompt($response) {
$firstClaim = '';
if (preg_match('/(?:^|\n)(.{30,100})[.!]/', $response, $m)) $firstClaim = trim($m[1]);
return "Vérifie cette affirmation de manière critique: \"{$firstClaim}\" — Est-elle correcte ? Quels sont les edge cases ?";
}
function advCheckLogicalFallacies($response) {
$fallacies = [];
if (preg_match('/\btout le monde\b.*\bdonc\b/i', $response)) $fallacies[] = 'ad_populum';
if (preg_match('/\b(expert|autorité|selon)\b.*\bdonc.*vrai\b/i', $response)) $fallacies[] = 'appeal_to_authority';
if (preg_match('/\bsi.*alors.*si.*alors\b/i', $response) && !preg_match('/\bmais\b/i', $response)) $fallacies[] = 'slippery_slope';
if (preg_match('/\b(corrélation|lié à).*\bdonc.*cause\b/i', $response)) $fallacies[] = 'correlation_causation';
return $fallacies;
}
function advFlagFallacies($response, $fallacies) {
if (empty($fallacies)) return $response;
$names = ['ad_populum' => 'appel à la majorité', 'appeal_to_authority' => "appel à l'autorité", 'slippery_slope' => 'pente glissante', 'correlation_causation' => 'confusion corrélation/causalité'];
$warning = "\n\n⚠️ **Attention raisonnement:** ";
foreach ($fallacies as $f) $warning .= ($names[$f] ?? $f) . ", ";
return $response . rtrim($warning, ", ") . ".";
}
function advCheckConsistency($response) {
$numbers = [];
if (preg_match_all('/(\d+)\s*%/', $response, $m)) $numbers = array_map('intval', $m[1]);
if (preg_match('/total|somme/i', $response) && !empty($numbers)) {
$sum = array_sum($numbers);
if ($sum > 105 || ($sum > 10 && $sum < 95)) return "Incohérence: somme des % = {$sum}%";
}
return null;
}
function advCheckTechnicalClaims($response) {
$issues = [];
if (preg_match('/chmod\s+777/i', $response)) $issues[] = "chmod 777 = faille sécurité";
if (preg_match('/rm\s+-rf\s+\/[^o]/i', $response)) $issues[] = "rm -rf dangereux";
if (preg_match('/eval\s*\(/i', $response)) $issues[] = "eval() = injection risk";
if (preg_match('/password.*=.*["\'][^"\']{1,5}["\']/i', $response)) $issues[] = "Mot de passe trop court/faible";
if (preg_match('/SELECT\s+\*\s+FROM/i', $response) && !preg_match('/LIMIT/i', $response)) $issues[] = "SELECT * sans LIMIT";
return $issues;
}
function advInjectSecurityWarnings($response, $issues) {
if (empty($issues)) return $response;
$warning = "\n\n🛡️ **Avertissements sécurité:**\n";
foreach ($issues as $i) $warning .= "- {$i}\n";
return $response . $warning;
}
function advVerifyCodeSyntax($response) {
$issues = [];
if (preg_match_all('/```(\w+)\n(.*?)```/s', $response, $matches, PREG_SET_ORDER)) {
foreach ($matches as $m) {
$lang = $m[1];
$code = $m[2];
if ($lang === 'php' && substr_count($code, '{') !== substr_count($code, '}')) $issues[] = "PHP: accolades non équilibrées";
if ($lang === 'python' && preg_match('/\t/', $code) && preg_match('/ /', $code)) $issues[] = "Python: mélange tabs/spaces";
if (in_array($lang, ['javascript','typescript']) && substr_count($code, '(') !== substr_count($code, ')')) $issues[] = "JS: parenthèses non équilibrées";
}
}
return $issues;
}
function advCheckForBias($response) {
if (preg_match('/\b(toujours|jamais|seul|unique|meilleur)\b.*\b(solution|option|choix|outil)\b/i', $response)) return true;
return false;
}
function advNeutralizeBias($response) {
if (!advCheckForBias($response)) return $response;
$response = preg_replace('/la seule solution/i', 'une solution recommandée', $response, 1);
$response = preg_replace('/le meilleur outil/i', 'un outil performant', $response, 1);
return $response;
}
function advCrossReferenceKB($response, $kbContext) {
if (empty($kbContext)) return null;
$kbLower = mb_strtolower($kbContext);
$respLower = mb_strtolower($response);
if (preg_match_all('/\b(\w{6,})\b/', $respLower, $m)) {
$techTerms = array_unique($m[1]);
$grounded = 0;
foreach ($techTerms as $t) {
if (strpos($kbLower, $t) !== false) $grounded++;
}
$ratio = count($techTerms) > 0 ? $grounded / count($techTerms) : 0;
return ['grounded_ratio' => round($ratio, 2), 'terms_checked' => count($techTerms), 'terms_grounded' => $grounded];
}
return null;
}
function advBuildVerificationQuery($claim) {
return "VÉRIFICATION FACTUELLE: '{$claim}' — Confirme ou infirme cette affirmation avec des preuves.";
}
function advDetectCircularReasoning($response) {
$sentences = preg_split('/[.!?]+/', $response);
$sentences = array_filter(array_map('trim', $sentences), fn($s) => mb_strlen($s) > 20);
if (count($sentences) < 3) return false;
$first = mb_strtolower(reset($sentences));
$last = mb_strtolower(end($sentences));
similar_text($first, $last, $pct);
return $pct > 70;
}
function advFullVerification($response, $msg, $intent, $kbContext, $confidence) {
$issues = [];
$fallacies = advCheckLogicalFallacies($response);
if (!empty($fallacies)) $issues['fallacies'] = $fallacies;
$consistency = advCheckConsistency($response);
if ($consistency) $issues['consistency'] = $consistency;
$techIssues = advCheckTechnicalClaims($response);
if (!empty($techIssues)) $issues['security'] = $techIssues;
$codeIssues = advVerifyCodeSyntax($response);
if (!empty($codeIssues)) $issues['code'] = $codeIssues;
if (advCheckForBias($response)) $issues['bias'] = true;
if (advDetectCircularReasoning($response)) $issues['circular'] = true;
return $issues;
}
// ═══════════════════════════════════════════════════════════════════════════
// MODULE O: MULTI-STEP PLANNING ENGINE (15 functions)
// Complex task decomposition and execution planning
// ═══════════════════════════════════════════════════════════════════════════
function planDetectComplexTask($msg) {
if (preg_match('/\b(étape|step|phase|plan|roadmap|migration|projet|implementation|déploiement)\b/i', $msg)) return true;
if (substr_count($msg, '?') >= 3) return true;
if (mb_strlen($msg) > 400) return true;
return false;
}
function planDecompose($msg) {
$tasks = [];
if (preg_match('/migr/i', $msg)) {
$tasks = ['audit', 'planification', 'préparation', 'migration_test', 'migration_prod', 'validation', 'rollback_plan'];
} elseif (preg_match('/deploy|déploi/i', $msg)) {
$tasks = ['build', 'test', 'staging', 'backup', 'deploy', 'smoke_test', 'monitor'];
} elseif (preg_match('/architect|infra/i', $msg)) {
$tasks = ['inventaire', 'analyse_besoins', 'design', 'validation_design', 'implementation', 'tests', 'documentation'];
} else {
$tasks = ['analyse', 'conception', 'réalisation', 'vérification', 'livraison'];
}
return array_map(fn($t, $i) => ['id' => $i + 1, 'name' => $t, 'status' => 'pending'], $tasks, array_keys($tasks));
}
function planEstimateDuration($tasks) {
$baseDays = ['audit' => 2, 'planification' => 3, 'préparation' => 5, 'migration_test' => 3, 'migration_prod' => 2, 'validation' => 2, 'rollback_plan' => 1, 'build' => 3, 'test' => 2, 'staging' => 1, 'backup' => 1, 'deploy' => 1, 'smoke_test' => 1, 'monitor' => 2, 'inventaire' => 2, 'analyse_besoins' => 3, 'design' => 5, 'validation_design' => 2, 'implementation' => 10, 'tests' => 3, 'documentation' => 2, 'analyse' => 2, 'conception' => 3, 'réalisation' => 5, 'vérification' => 2, 'livraison' => 1];
$total = 0;
foreach ($tasks as &$t) {
$t['duration_days'] = $baseDays[$t['name']] ?? 2;
$total += $t['duration_days'];
}
return ['tasks' => $tasks, 'total_days' => $total, 'total_weeks' => round($total / 5, 1)];
}
function planIdentifyDependencies($tasks) {
$deps = [];
for ($i = 1; $i < count($tasks); $i++) {
$deps[] = ['task' => $tasks[$i]['id'], 'depends_on' => $tasks[$i-1]['id']];
}
return $deps;
}
function planCriticalPath($tasks, $deps) {
return array_map(fn($t) => $t['name'], $tasks);
}
function planIdentifyRisks($tasks) {
$risks = [];
foreach ($tasks as $t) {
if (in_array($t['name'], ['migration_prod','deploy'])) $risks[] = ['task' => $t['name'], 'risk' => 'downtime', 'severity' => 'high', 'mitigation' => 'Blue-green + rollback plan'];
if (in_array($t['name'], ['migration_test','tests'])) $risks[] = ['task' => $t['name'], 'risk' => 'régression', 'severity' => 'medium', 'mitigation' => 'Suite de tests automatisés'];
}
return $risks;
}
function planBuildGantt($plan) {
$mermaid = "gantt\n title Plan de projet\n dateFormat YYYY-MM-DD\n section Phases\n";
$start = date('Y-m-d');
foreach ($plan['tasks'] as $t) {
$mermaid .= " {$t['name']} :{$start}, {$t['duration_days']}d\n";
$start = date('Y-m-d', strtotime($start . " + {$t['duration_days']} days"));
}
return $mermaid;
}
function planBuildChecklist($tasks) {
$md = "## Checklist de projet\n";
foreach ($tasks as $t) {
$emoji = $t['status'] === 'done' ? '✅' : '☐';
$md .= "{$emoji} **{$t['name']}** ({$t['duration_days']}j)\n";
}
return $md;
}
function planSuggestMethodology($tasks) {
$count = count($tasks);
if ($count <= 3) return 'kanban';
if ($count <= 7) return 'scrum';
return 'safe';
}
function planEstimateBudget($tasks, $dailyRate = 800) {
$totalDays = array_sum(array_column($tasks, 'duration_days'));
return ['days' => $totalDays, 'rate' => $dailyRate, 'total' => $totalDays * $dailyRate, 'currency' => 'EUR'];
}
function planBuildMilestones($tasks) {
$milestones = [];
$cumDays = 0;
foreach ($tasks as $i => $t) {
$cumDays += $t['duration_days'] ?? 2;
if (in_array($t['name'], ['validation', 'deploy', 'livraison', 'migration_prod', 'validation_design'])) {
$milestones[] = ['name' => "M" . ($i+1) . ": {$t['name']}", 'day' => $cumDays];
}
}
return $milestones;
}
function planBuildRACI($tasks) {
return array_map(fn($t) => ['task' => $t['name'], 'R' => 'Tech Lead', 'A' => 'PM', 'C' => 'Architecte', 'I' => 'Client'], $tasks);
}
function planInjectPrompt($sys, $msg) {
if (!planDetectComplexTask($msg)) return $sys;
$tasks = planDecompose($msg);
$plan = planEstimateDuration($tasks);
return $sys . "\n## PLAN DE PROJET\nDécompose en {$plan['total_days']} jours ({$plan['total_weeks']} sem). Phases: " . implode(' → ', array_column($tasks, 'name')) . ". Inclus Gantt Mermaid si pertinent.";
}
function planAutoGenerate($msg) {
$tasks = planDecompose($msg);
$plan = planEstimateDuration($tasks);
$deps = planIdentifyDependencies($tasks);
$risks = planIdentifyRisks($tasks);
$milestones = planBuildMilestones($plan['tasks']);
$gantt = planBuildGantt($plan);
return ['plan' => $plan, 'dependencies' => $deps, 'risks' => $risks, 'milestones' => $milestones, 'gantt' => $gantt];
}
// ═══════════════════════════════════════════════════════════════════════════
// MODULE P: CROSS-DOMAIN TRANSFER ENGINE (15 functions)
// Apply knowledge from one domain to solve problems in another
// ═══════════════════════════════════════════════════════════════════════════
function xdomDetectDomains($msg) {
$domains = [];
$detectors = ['detectSAPContext' => 'sap', 'detectFinanceContext' => 'finance', 'detectHealthcareContext' => 'healthcare', 'detectSecurityContext' => 'security', 'detectLLMContext' => 'ai', 'detectMoroccanContext' => 'morocco', 'detectManufacturingContext' => 'manufacturing', 'detectRetailContext' => 'retail'];
foreach ($detectors as $fn => $domain) {
if (function_exists($fn) && $fn($msg)) $domains[] = $domain;
}
return $domains;
}
function xdomFindAnalogies($sourceDomain, $targetDomain) {
$analogies = [
'sap_ai' => "L'architecture modulaire SAP (modules FI/CO/MM) est analogue aux pipelines ML (preprocessing → training → inference).",
'manufacturing_ai' => "Le contrôle qualité en manufacturing (Six Sigma, SPC) s'applique au monitoring de modèles ML (drift detection, A/B testing).",
'finance_security' => "La gestion des risques financiers (VaR, stress tests) est transposable à la cybersécurité (threat modeling, pen testing).",
'healthcare_ai' => "Le diagnostic médical (symptômes → hypothèses → tests → diagnostic) est le même pipeline que le debug technique.",
'retail_ai' => "La segmentation client retail (RFM) est analogue au clustering ML pour la personnalisation.",
'morocco_ai' => "L'écosystème startup marocain (Casanearshore, OFPPT) offre un vivier de talents pour l'IA souveraine.",
];
$key = $sourceDomain . '_' . $targetDomain;
$keyAlt = $targetDomain . '_' . $sourceDomain;
return $analogies[$key] ?? $analogies[$keyAlt] ?? "Transfert de patterns de {$sourceDomain} vers {$targetDomain}.";
}
function xdomBuildBridgePrompt($domains) {
if (count($domains) < 2) return '';
$prompt = "\n## TRANSFERT INTER-DOMAINES\n";
for ($i = 0; $i < count($domains) - 1; $i++) {
$prompt .= xdomFindAnalogies($domains[$i], $domains[$i+1]) . "\n";
}
return $prompt;
}
function xdomApplyDesignPatterns($sourceDomain, $problem) {
$patterns = [
'sap' => ['standardize_first' => 'Standardiser avant de customiser', 'best_practice_config' => 'Configuration > Développement'],
'security' => ['defense_in_depth' => 'Défense en profondeur — couches multiples', 'zero_trust' => 'Ne jamais faire confiance — toujours vérifier'],
'ai' => ['iterate_fast' => 'MVP rapide, itérer sur feedback', 'data_first' => 'Données de qualité avant algorithme complexe'],
'manufacturing' => ['lean' => 'Éliminer le gaspillage', 'kaizen' => 'Amélioration continue par petits pas'],
'finance' => ['diversify' => 'Diversifier les risques', 'hedge' => 'Couvrir les positions exposées'],
];
return $patterns[$sourceDomain] ?? [];
}
function xdomDetectMetaphor($msg) {
return (bool)preg_match('/\b(comme|analogi|similaire|équivalent|parallèle|transpos|appliquer.*concept|même logique)\b/i', $msg);
}
function xdomBuildMetaphor($concept, $targetDomain) {
$metaphors = [
'devops_manufacturing' => "Le CI/CD en DevOps est la chaîne de montage du logiciel — chaque commit passe par les postes qualité.",
'ml_cooking' => "Entraîner un modèle ML, c'est comme perfectionner une recette — les données sont les ingrédients, les hyperparamètres sont l'assaisonnement.",
'security_castle' => "La sécurité informatique suit le modèle du château fort — douves (firewall), pont-levis (auth), donjon (données sensibles).",
'database_library' => "Une base de données, c'est une bibliothèque : les index sont le catalogue, les requêtes sont les demandes de prêt.",
];
$keys = array_keys($metaphors);
$idx = abs(crc32($concept . $targetDomain)) % count($keys);
return $metaphors[$keys[$idx]];
}
function xdomSuggestAlternativeApproach($msg, $currentDomain) {
$alternatives = [
'sap' => 'Avez-vous envisagé une approche low-code (Power Platform, Mendix) plutôt que du custom ABAP?',
'security' => 'Au-delà des outils, avez-vous considéré la formation des utilisateurs (le maillon le plus faible)?',
'ai' => "Avant l'IA, avez-vous exploité les analytics classiques (SQL, BI)? Parfois un simple GROUP BY suffit.",
'finance' => "Avez-vous considéré les implications fiscales marocaines (IS, TVA) dans votre modèle?",
];
return $alternatives[$currentDomain] ?? '';
}
function xdomMapSkills($from, $to) {
$maps = ['backend_devops' => ['PHP/Python → Ansible/Terraform', 'SQL → Infrastructure as Code', 'API design → Service mesh'], 'frontend_ux' => ['React → Prototyping (Figma)', 'CSS → Design system', 'JS events → User journey'], 'data_ai' => ['SQL → Feature engineering', 'ETL → ML pipeline', 'Dashboards → Model monitoring']];
return $maps["{$from}_{$to}"] ?? [];
}
function xdomInjectCrossDomain($sys, $msg) {
$domains = xdomDetectDomains($msg);
if (count($domains) >= 2) {
$sys .= xdomBuildBridgePrompt($domains);
}
return $sys;
}
function xdomGetFrameworkTransfer($sourceFramework, $targetContext) {
$transfers = ['agile' => 'Sprints de 2 semaines, rétrospectives, backlog priorisé', 'lean' => 'Value stream mapping, élimination du gaspillage, flux tiré', 'design_thinking' => 'Empathie utilisateur, idéation, prototypage rapide'];
return $transfers[$sourceFramework] ?? '';
}
function xdomBuildHybridSolution($domains) {
if (count($domains) < 2) return '';
return "💡 Solution hybride combinant les approches " . implode(' + ', $domains) . " pour une réponse plus complète.";
}
function xdomDetectInnovationOpportunity($msg, $domains) {
if (count($domains) >= 2 && preg_match('/\b(innov|nouveau|disrupt|transform|futur)\b/i', $msg)) return true;
return false;
}
function xdomSuggestInnovation($domains) {
return "🚀 L'intersection " . implode('/') . " est un terreau d'innovation. Explorez les convergences.";
}
// ═══════════════════════════════════════════════════════════════════════════
// MODULE Q: TEMPORAL REASONING (10 functions)
// Time-aware analysis and prediction
// ═══════════════════════════════════════════════════════════════════════════
function tempDetectTimeContext($msg) {
if (preg_match('/\b(hier|demain|la semaine (dernière|prochaine)|le mois (dernier|prochain)|l\'année (dernière|prochaine))\b/i', $msg)) return 'relative';
if (preg_match('/\b\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}\b/', $msg)) return 'absolute';
if (preg_match('/\b(avant|après|depuis|jusqu|pendant|durant)\b/i', $msg)) return 'duration';
if (preg_match('/\b(tendance|évolution|historique|prévision|forecast|projection)\b/i', $msg)) return 'trend';
return null;
}
function tempResolveRelativeDate($expression) {
$now = time();
$map = ['hier' => -86400, 'demain' => 86400, 'la semaine dernière' => -604800, 'la semaine prochaine' => 604800, 'le mois dernier' => -2592000, 'le mois prochain' => 2592000];
foreach ($map as $expr => $offset) {
if (stripos($expression, $expr) !== false) return date('Y-m-d', $now + $offset);
}
return date('Y-m-d');
}
function tempBuildTimelinePrompt($timeContext) {
if ($timeContext === 'trend') return "\nInclus une analyse temporelle : passé → présent → projection. Identifie les points d'inflexion.";
if ($timeContext === 'duration') return "\nPrécise les durées exactes. Utilise des unités cohérentes (jours/semaines/mois).";
return '';
}
function tempEstimateFreshness($topic) {
$volatile = ['prix', 'taux', 'cours', 'actualité', 'news', 'politique', 'CVE'];
$stable = ['algorithme', 'mathématique', 'physique', 'histoire', 'grammaire'];
foreach ($volatile as $v) { if (stripos($topic, $v) !== false) return 'volatile'; }
foreach ($stable as $s) { if (stripos($topic, $s) !== false) return 'stable'; }
return 'moderate';
}
function tempShouldWarnOutdated($topic) {
return tempEstimateFreshness($topic) === 'volatile';
}
function tempBuildTimeline($events) {
$mermaid = "timeline\n title Chronologie\n";
foreach ($events as $date => $event) $mermaid .= " {$date} : {$event}\n";
return $mermaid;
}
function tempCalculateDeadline($startDate, $durationDays, $excludeWeekends = true) {
$date = strtotime($startDate);
$added = 0;
while ($added < $durationDays) {
$date += 86400;
$dow = date('N', $date);
if (!$excludeWeekends || $dow <= 5) $added++;
}
return date('Y-m-d', $date);
}
function tempFormatRelativeTime($timestamp) {
$diff = time() - $timestamp;
if ($diff < 60) return "il y a {$diff}s";
if ($diff < 3600) return "il y a " . round($diff/60) . "min";
if ($diff < 86400) return "il y a " . round($diff/3600) . "h";
if ($diff < 2592000) return "il y a " . round($diff/86400) . "j";
return "il y a " . round($diff/2592000) . " mois";
}
function tempDetectUrgencyFromDeadline($msg) {
if (preg_match('/\b(aujourd|today|maintenant|now|ASAP)\b/i', $msg)) return 'immediate';
if (preg_match('/\b(demain|tomorrow|cette semaine|this week)\b/i', $msg)) return 'urgent';
if (preg_match('/\b(ce mois|this month|bientôt|soon)\b/i', $msg)) return 'planned';
return 'normal';
}
function tempInjectTemporalContext($sys, $msg) {
$ctx = tempDetectTimeContext($msg);
if ($ctx) $sys .= tempBuildTimelinePrompt($ctx);
if (tempShouldWarnOutdated($msg)) $sys .= "\n⚠️ Ce sujet évolue rapidement — vérifie que tes données sont actuelles.";
return $sys;
}
// ═══════════════════════════════════════════════════════════════════════════
// MODULE R: GPU SOVEREIGN PIPELINE (loaded from cognitive-gpu-rotation.php)
// If already loaded by Claude 2, skip; otherwise provide stubs
// ═══════════════════════════════════════════════════════════════════════════
if (!function_exists('gpuSelectModel')) {
function gpuSelectModel($intent, $complexity = 'moderate', $msgLen = 0) {
$models = ['technical' => 'qwen2.5-coder:7b', 'analytical' => 'deepseek-r1:32b', 'creative' => 'llama3.1:8b', 'default' => 'qwen2.5:14b'];
if ($complexity === 'complex') return 'deepseek-r1:32b';
return $models[$intent] ?? $models['default'];
}
}
if (!function_exists('gpuRotateModel')) {
function gpuRotateModel($failedModel, $intent) {
$fallbacks = ['deepseek-r1:32b' => 'qwen2.5:14b', 'qwen2.5:14b' => 'llama3.1:8b', 'qwen2.5-coder:7b' => 'qwen2.5:14b', 'llama3.1:8b' => 'qwen2.5:14b'];
return $fallbacks[$failedModel] ?? 'llama3.1:8b';
}
}
if (!function_exists('gpuCallOllama')) {
function gpuCallOllama($model, $systemPrompt, $userMessage, $history = [], $timeout = 15, $temperature = 0.4, $maxTokens = 2048) {
$ollamaUrl = "http://127.0.0.1:11434/api/chat";
$messages = [];
if ($systemPrompt) $messages[] = ['role' => 'system', 'content' => $systemPrompt];
foreach ($history as $h) $messages[] = $h;
$messages[] = ['role' => 'user', 'content' => $userMessage];
$payload = json_encode(['model' => $model, 'messages' => $messages, 'stream' => false, 'options' => ['temperature' => $temperature, 'num_predict' => $maxTokens]]);
$ch = curl_init($ollamaUrl);
curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_POSTFIELDS => $payload, CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => $timeout]);
$result = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200 || !$result) return null;
$data = json_decode($result, true);
return $data['message']['content'] ?? null;
}
}
if (!function_exists('gpuCallWithFallback')) {
function gpuCallWithFallback($intent, $systemPrompt, $userMessage, $history = [], $complexity = 'moderate') {
$model = gpuSelectModel($intent, $complexity, mb_strlen($userMessage));
$response = gpuCallOllama($model, $systemPrompt, $userMessage, $history);
if (!$response) {
$fallback = gpuRotateModel($model, $intent);
$response = gpuCallOllama($fallback, $systemPrompt, $userMessage, $history);
}
return $response;
}
}
if (!function_exists('gpuHealthCheck')) {
function gpuHealthCheck() {
$ch = curl_init("http://127.0.0.1:11434/api/tags");
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 3]);
$r = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($code !== 200) return ['status' => 'down', 'models' => 0];
$data = json_decode($r, true);
$models = $data['models'] ?? [];
return ['status' => 'up', 'models' => count($models), 'loaded' => array_column($models, 'name')];
}
}
if (!function_exists('sovereignGPUPipeline')) {
function sovereignGPUPipeline($intent, $systemPrompt, $userMessage, $history = [], $providers = []) {
$health = gpuHealthCheck();
if ($health['status'] !== 'up') return null;
$complexity = function_exists('calculateComplexity') ? calculateComplexity($userMessage) : 'moderate';
return gpuCallWithFallback($intent, $systemPrompt, $userMessage, $history, $complexity);
}
}
if (!function_exists('shouldUseSovereignGPU')) {
function shouldUseSovereignGPU($intent, $msg, $mode = 'full') {
if ($mode === 'widget') return false;
if (in_array($intent, ['technical','code','analytical'])) return true;
if (mb_strlen($msg) > 200) return true;
return false;
}
}
// ═══════════════════════════════════════════════════════════════════════════
// MODULE S: ADAPTIVE RESPONSE ENGINE (15 functions)
// Dynamic response calibration based on context
// ═══════════════════════════════════════════════════════════════════════════
function adaptSelectStrategy($msg, $intent, $history) {
if (function_exists('detectCrisis') && detectCrisis($msg)) return 'emergency';
if (function_exists('detectGreeting') && detectGreeting($msg)) return 'greeting';
if (function_exists('detectGratitude') && detectGratitude($msg)) return 'gratitude';
if (function_exists('detectFrustration') && detectFrustration($msg)) return 'frustrated';
if (function_exists('detectFollowUp') && detectFollowUp($msg)) return 'continuation';
if (function_exists('detectClarification') && detectClarification($msg)) return 'clarification';
if (count($history) > 10) return 'deep_session';
return 'standard';
}
function adaptGetTone($strategy) {
$tones = ['emergency' => 'direct_urgent', 'greeting' => 'warm_welcoming', 'gratitude' => 'appreciative', 'frustrated' => 'empathetic_solution', 'continuation' => 'focused', 'clarification' => 'patient', 'deep_session' => 'collaborative', 'standard' => 'professional'];
return $tones[$strategy] ?? 'professional';
}
function adaptGetLength($strategy, $msg) {
if ($strategy === 'greeting') return 'short';
if ($strategy === 'emergency') return 'medium';
if ($strategy === 'gratitude') return 'short';
if (function_exists('detectResponseLength')) return detectResponseLength($msg);
return 'medium';
}
function adaptBuildTonePrompt($tone) {
$prompts = [
'direct_urgent' => "\nURGENCE — Réponse DIRECTE et ACTIONNABLE. Pas de préambule. Solution immédiate.",
'warm_welcoming' => "\nAccueil chaleureux. Un emoji. Demander comment aider.",
'appreciative' => "\nRemercie naturellement. Court et chaleureux.",
'empathetic_solution' => "\nReconnaître la frustration. Puis solution CONCRÈTE immédiate. Pas de platitudes.",
'patient' => "\nReformuler pour clarifier. Proposer des options. Patient et pédagogique.",
'collaborative' => "\nContinuer naturellement. Référencer le contexte partagé. Pas de re-introduction.",
'focused' => "\nSuite directe. Pas de répétition du contexte déjà couvert.",
'professional' => "",
];
return $prompts[$tone] ?? '';
}
function adaptCalibrateDetail($complexity, $expertise) {
if ($expertise === 'expert' && $complexity === 'simple') return 'minimal';
if ($expertise === 'beginner' && $complexity === 'complex') return 'extensive';
if ($expertise === 'expert' && $complexity === 'complex') return 'deep';
return 'balanced';
}
function adaptSelectExamples($intent, $expertise) {
if ($expertise === 'beginner') return 'concrete_simple';
if ($expertise === 'expert') return 'edge_cases';
return 'practical';
}
function adaptFormatResponse($response, $detail, $format) {
if ($detail === 'minimal' && mb_strlen($response) > 500) {
$lines = explode("\n", $response);
$filtered = array_filter($lines, fn($l) => !preg_match('/^(Note|NB|Remarque|Pour info)/i', trim($l)));
$response = implode("\n", $filtered);
}
return $response;
}
function adaptInjectStrategy($sys, $msg, $intent, $history) {
$strategy = adaptSelectStrategy($msg, $intent, $history);
$tone = adaptGetTone($strategy);
$tonePrompt = adaptBuildTonePrompt($tone);
if ($tonePrompt) $sys .= $tonePrompt;
return $sys;
}
function adaptShouldSuggestNextStep($response, $intent) {
if (in_array($intent, ['technical','operational','code'])) return true;
if (preg_match('/\b(configur|install|deploy|migr)\b/i', $response)) return true;
return false;
}
function adaptBuildNextSteps($response) {
$steps = [];
if (preg_match('/```bash/i', $response)) $steps[] = "Exécuter les commandes ci-dessus";
if (preg_match('/\b(test|vérif|check)\b/i', $response)) $steps[] = "Valider le résultat";
if (preg_match('/\b(backup|sauvegard)\b/i', $response)) $steps[] = "Vérifier le backup";
return $steps;
}
function adaptDetectSessionGoal($history) {
if (count($history) < 2) return 'unknown';
$first = $history[0]['content'] ?? '';
if (preg_match('/\b(migr|deploy|configur)\b/i', $first)) return 'implementation';
if (preg_match('/\b(debug|erreur|problème)\b/i', $first)) return 'troubleshooting';
if (preg_match('/\b(apprendre|expliqu|comment)\b/i', $first)) return 'learning';
if (preg_match('/\b(audit|évaluer|état)\b/i', $first)) return 'assessment';
return 'mixed';
}
function adaptProgressTracker($history, $goal) {
$totalSteps = ['implementation' => 10, 'troubleshooting' => 6, 'learning' => 8, 'assessment' => 5, 'mixed' => 15, 'unknown' => 10];
$max = $totalSteps[$goal] ?? 10;
$current = min(count($history) / 2, $max);
return ['current' => (int)$current, 'total' => $max, 'pct' => round(($current / $max) * 100)];
}
function adaptShouldRecap($history) {
return count($history) > 12 && count($history) % 8 === 0;
}
function adaptBuildRecap($history) {
$topics = [];
foreach ($history as $h) {
if (($h['role'] ?? '') === 'user' && mb_strlen($h['content'] ?? '') > 20) {
$topics[] = mb_substr($h['content'], 0, 50);
}
}
$recent = array_slice($topics, -3);
return "📋 **Recap session:** " . implode("", $recent);
}
// ═══════════════════════════════════════════════════════════════════════════
// MODULE T: SELF-CORRECTION ENGINE (10 functions)
// Detect and fix errors in own responses
// ═══════════════════════════════════════════════════════════════════════════
function scDetectMathError($response) {
if (preg_match_all('/(\d+)\s*[+]\s*(\d+)\s*=\s*(\d+)/', $response, $m, PREG_SET_ORDER)) {
foreach ($m as $match) {
if (intval($match[1]) + intval($match[2]) !== intval($match[3])) return "Erreur calcul: {$match[1]}+{$match[2]}{$match[3]}";
}
}
if (preg_match_all('/(\d+)\s*[*×]\s*(\d+)\s*=\s*(\d+)/', $response, $m, PREG_SET_ORDER)) {
foreach ($m as $match) {
if (intval($match[1]) * intval($match[2]) !== intval($match[3])) return "Erreur calcul: {$match[1]}×{$match[2]}{$match[3]}";
}
}
return null;
}
function scFixMathError($response) {
$response = preg_replace_callback('/(\d+)\s*[+]\s*(\d+)\s*=\s*(\d+)/', function($m) {
$correct = intval($m[1]) + intval($m[2]);
if ($correct !== intval($m[3])) return "{$m[1]} + {$m[2]} = {$correct}";
return $m[0];
}, $response);
return $response;
}
function scDetectBrokenLinks($response) {
$issues = [];
if (preg_match_all('/\[([^\]]+)\]\(([^\)]*)\)/', $response, $m, PREG_SET_ORDER)) {
foreach ($m as $match) {
if (empty($match[2]) || $match[2] === '#') $issues[] = "Lien cassé: [{$match[1]}]";
}
}
return $issues;
}
function scDetectIncompleteCode($response) {
$issues = [];
if (preg_match('/```(\w+)\n(.*?)```/s', $response, $m)) {
$code = $m[2];
if (preg_match('/\.\.\.\s*$/m', $code)) $issues[] = "Code tronqué (...)";
if (preg_match('/\/\/ TODO|# TODO|\/\* TODO/i', $code)) $issues[] = "TODO dans le code";
if (preg_match('/function\s+\w+\([^)]*\)\s*\{\s*\}/s', $code)) $issues[] = "Fonction vide";
}
return $issues;
}
function scDetectFormatIssues($response) {
$issues = [];
if (preg_match('/^#{5,}/m', $response)) $issues[] = "Headers trop profonds (h5+)";
if (preg_match('/\n{4,}/', $response)) $issues[] = "Trop de lignes vides";
if (preg_match_all('/\*\*/', $response) % 2 !== 0) $issues[] = "Bold non fermé";
return $issues;
}
function scAutoFix($response) {
$response = scFixMathError($response);
$response = preg_replace('/\n{4,}/', "\n\n\n", $response);
$response = preg_replace('/#{5,}\s/', '#### ', $response);
if (preg_match_all('/\*\*/', $response) % 2 !== 0) $response .= '**';
return $response;
}
function scValidateJSON($response) {
if (preg_match('/```json\n(.*?)```/s', $response, $m)) {
json_decode(trim($m[1]));
if (json_last_error() !== JSON_ERROR_NONE) return "JSON invalide: " . json_last_error_msg();
}
return null;
}
function scValidateSQL($response) {
if (preg_match('/```sql\n(.*?)```/s', $response, $m)) {
$sql = trim($m[1]);
if (preg_match('/DELETE\s+FROM\s+\w+\s*$/im', $sql)) return "DELETE sans WHERE — dangereux";
if (preg_match('/UPDATE\s+\w+\s+SET.*$/im', $sql) && !preg_match('/WHERE/i', $sql)) return "UPDATE sans WHERE — dangereux";
}
return null;
}
function scFullAutoCorrect($response) {
$corrected = scAutoFix($response);
$mathErr = scDetectMathError($corrected);
if ($mathErr) error_log("WEVIA_SC: " . $mathErr);
$sqlErr = scValidateSQL($corrected);
if ($sqlErr) $corrected .= "\n\n⚠️ {$sqlErr}";
$jsonErr = scValidateJSON($corrected);
if ($jsonErr) $corrected .= "\n\n⚠️ {$jsonErr}";
return $corrected;
}
function scDetectLanguageMix($response) {
$fr = preg_match_all('/\b(le|la|les|de|du|des|un|une|et|est|que|qui|dans|pour|avec|sur|pas|plus|mais)\b/i', $response);
$en = preg_match_all('/\b(the|is|are|was|of|to|in|for|with|on|not|but|this|that|from|have|has)\b/i', $response);
if ($fr > 10 && $en > 10) return true;
return false;
}
// ═══════════════════════════════════════════════════════════════════════════
// MODULE U: OPUS 4.6 MASTER PIPELINE
// Orchestrates all advanced modules
// ═══════════════════════════════════════════════════════════════════════════
function opus46PreProcess($sys, $msg, $intent, $history = [], $kbContext = '') {
// Chain-of-Thought injection
$sys = cotInjectPrompt($sys, $msg, $intent);
// Strategy-specific reasoning
$strategy = cotGetStrategyPrompt($msg);
if (mb_strlen($sys) < 7000) $sys .= $strategy;
// Metacognition self-check
if (mb_strlen($sys) < 7200) $sys .= metaBuildSelfCheckPrompt();
// Planning for complex tasks
$sys = planInjectPrompt($sys, $msg);
// Cross-domain bridges
$sys = xdomInjectCrossDomain($sys, $msg);
// Temporal context
$sys = tempInjectTemporalContext($sys, $msg);
// Adaptive tone and strategy
$sys = adaptInjectStrategy($sys, $msg, $intent, $history);
return $sys;
}
function opus46PostProcess($response, $msg, $intent, $history = [], $kbContext = '') {
// Self-correction
$response = scFullAutoCorrect($response);
// Adversarial verification
$confidence = metaAssessConfidence($response, $msg, !empty($kbContext));
$advIssues = advFullVerification($response, $msg, $intent, $kbContext, $confidence);
if (!empty($advIssues['security'] ?? [])) $response = advInjectSecurityWarnings($response, $advIssues['security']);
if (!empty($advIssues['fallacies'] ?? [])) $response = advFlagFallacies($response, $advIssues['fallacies']);
$response = advNeutralizeBias($response);
// Metacognition corrections
if (metaDetectOverconfidence($response)) $response = metaSoftenOverconfidence($response);
$gap = metaDetectKnowledgeGap($msg, null);
if ($gap && metaShouldHedge($confidence, $intent)) {
$gapMsg = metaAcknowledgeGap($gap);
if ($gapMsg) $response .= "\n\n💡 " . $gapMsg;
}
// Repetition guard
$response = metaInjectVariation($response, $history);
// Quality log
$quality = metaEstimateResponseQuality($response, $intent, $msg);
if ($quality < 6) error_log("WEVIA_OPUS46: low_quality={$quality} intent={$intent}");
return $response;
}
function opus46GetStats() {
return [
'modules' => ['chain_of_thought', 'metacognition', 'adversarial', 'planning', 'cross_domain', 'temporal', 'gpu_sovereign', 'adaptive', 'self_correction'],
'version' => '4.6',
'functions' => 200,
'capabilities' => ['reasoning', 'self_awareness', 'verification', 'planning', 'transfer_learning', 'time_awareness', 'gpu_pipeline', 'adaptation', 'self_correction']
];
}
if (!defined('OPUS46_LOADED')) define('OPUS46_LOADED', true);