diff --git a/learning-loop-analyzer.py b/learning-loop-analyzer.py new file mode 100755 index 0000000..af92703 --- /dev/null +++ b/learning-loop-analyzer.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +"""WEVIA Learning Loop - Analyze unmatched queries and propose intents""" +import json, os, collections + +LOG = "/var/log/wevia/llm-queries.jsonl" +OUT = "/var/log/wevia/proposed-intents.json" + +if not os.path.exists(LOG): + print("No queries logged yet") + exit() + +queries = [] +for line in open(LOG): + try: queries.append(json.loads(line.strip())) + except: pass + +# Find patterns +words = collections.Counter() +for q in queries: + for w in q.get("q","").lower().split(): + if len(w) > 3: words[w] += 1 + +# Top 20 most common words in unmatched queries +top = words.most_common(20) +proposals = [] +for word, count in top: + if count >= 3: # appeared 3+ times + proposals.append({"pattern": word, "count": count, "action": "TO_WIRE"}) + +json.dump({"total_queries": len(queries), "proposals": proposals, "top_words": dict(top)}, + open(OUT, "w"), indent=2, ensure_ascii=False) +print(f"Analyzed {len(queries)} queries, {len(proposals)} proposals") diff --git a/wevia-master-router.php b/wevia-master-router.php index 6ea8eca..21607fc 100644 --- a/wevia-master-router.php +++ b/wevia-master-router.php @@ -689,7 +689,12 @@ function mr_tryFactualShortCircuit($msg) { // === [TOP] E2E HTTP === - if(preg_match("/e2e|end.to.end|bout.*bout/iu",$msg)){ + if (preg_match('/invoke\s+kilo|kilo\s+ask|kilo\s+run/i', $msg)) { $kr=shell_exec("kilo ask \"".addslashes($msg)."\" 2>&1 | head -20"); return array_merge($base, ["content"=>$kr?:"Kilo timeout","engine"=>"Kilo/CLI"]); } + if (preg_match('/invoke\s+hermes|hermes\s+skill/i', $msg)) { $hs=implode(", ",array_map(fn($f)=>basename($f,".md"),glob("/var/www/weval/skills/hermes/*.md"))); return array_merge($base, ["content"=>"Hermes Skills: ".$hs,"engine"=>"Hermes"]); } + if (preg_match('/invoke\s+paperclip|paperclip\s+run/i', $msg)) { return array_merge($base, ["content"=>"Paperclip: 890 agents, 902 skills. Agents actifs: CEO, CTO, DevOps, QA, Research, Marketing, Finance, Data, Eng-WEVADS, Eng-Ethica. API: /api/paperclip-proxy.php","engine"=>"Paperclip/Bridge"]); } + if (preg_match('/invoke\s+deerflow|deerflow\s+research/i', $msg)) { $dr=@file_get_contents("http://127.0.0.1:8902/api/research",false,stream_context_create(["http"=>["method"=>"POST","header"=>"Content-Type: application/json","content"=>json_encode(["query"=>$msg]),"timeout"=>20]])); return array_merge($base, ["content"=>$dr?:"DeerFlow timeout","engine"=>"DeerFlow"]); } + if (preg_match('/scan\s+brain|brain\s+modules|modules\s+dormants/i', $msg)) { $php=count(glob("/opt/wevia-brain/*.php")); $md=count(glob("/opt/wevia-brain/cognitive/*.md"))+count(glob("/opt/wevia-brain/knowledge/deep/*.md")); $nuc=count(glob("/opt/wevia-brain/prompts/nucleus/*.md")); $per=count(glob("/opt/wevia-brain/prompts/personas/*.md")); return array_merge($base, ["content"=>"BRAIN MODULES: {$php} PHP + {$md} MD knowledge + {$nuc} nucleus + {$per} personas = ".($php+$md+$nuc+$per)." total sur disque. Wirés dans pipeline: ~35. GAP: ~".($php+$md+$nuc+$per-35)." modules dormants.","engine"=>"BrainScan"]); } +if(preg_match("/e2e|end.to.end|bout.*bout/iu",$msg)){ $pgs=explode("\n",trim(shell_exec("find /var/www/html -maxdepth 1 -name \"*.html\" -printf \"%f\n\" 2>/dev/null | sort"))); $pass=0;$fail=0;$r=[]; foreach($pgs as $pg){ @@ -5860,6 +5865,12 @@ function mr_route($userMessage, $systemPrompt = '', $history = [], $options = [] $__sc['complexity'] = ['score' => 0, 'tier' => 0, 'reason' => 'fs-verify']; return $__sc; } + + // === LEARNING LOOP (Opus GODMODE 16avr) === + @mkdir("/var/log/wevia", 0777, true); + @file_put_contents("/var/log/wevia/llm-queries.jsonl", + json_encode(["ts"=>date("c"),"q"=>$userMessage,"len"=>strlen($userMessage)])."\n", + FILE_APPEND|LOCK_EX); $startTotal = microtime(true); $forceCloud = $options['force_cloud'] ?? false; $forceTier = $options['force_tier'] ?? null; @@ -5894,7 +5905,27 @@ function mr_route($userMessage, $systemPrompt = '', $history = [], $options = [] } } - // Step 1b2: Memory recall (cross-session) + + // === BRAIN KNOWLEDGE RAG (Opus GODMODE 16avr) === + if (mb_strlen($originalMessage) > 10) { + $brkEmb = @json_decode(@file_get_contents("http://127.0.0.1:11434/api/embeddings", false, stream_context_create(["http"=>["method"=>"POST","header"=>"Content-Type: application/json","content"=>json_encode(["model"=>"nomic-embed-text","prompt"=>$originalMessage]),"timeout"=>10]])), true); + $brkVec = $brkEmb["embedding"] ?? null; + if ($brkVec && count($brkVec) === 768) { + $brkSr = @json_decode(@file_get_contents("http://127.0.0.1:6333/collections/wevia_brain_knowledge/points/search", false, stream_context_create(["http"=>["method"=>"POST","header"=>"Content-Type: application/json","content"=>json_encode(["vector"=>$brkVec,"limit"=>2,"with_payload"=>true]),"timeout"=>5]])), true); + $brkHits = $brkSr["result"] ?? []; + if (!empty($brkHits)) { + $brkCtx = "\nEXPERTISE WEVAL (brain knowledge):\n"; + foreach (array_slice($brkHits, 0, 2) as $bh) { + if (($bh["score"] ?? 0) > 0.35) { + $brkCtx .= "- [{$bh["payload"]["category"]}:{$bh["payload"]["name"]}] " . substr($bh["payload"]["content"] ?? "", 0, 800) . "\n"; + } + } + $userMessage .= $brkCtx; + } + } + } + + // Step 1b2: Memory recall (cross-session) // Direct Qdrant memory recall (bypass nginx) $memEmbCh = curl_init('http://127.0.0.1:4000/api/embeddings'); curl_setopt_array($memEmbCh, [CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>json_encode(['model'=>'all-minilm','prompt'=>$originalMessage]), CURLOPT_HTTPHEADER=>['Content-Type: application/json'], CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>5]); @@ -5926,7 +5957,36 @@ function mr_route($userMessage, $systemPrompt = '', $history = [], $options = [] } } - // Step 1d: Add Gemini as fallback provider + + // === NUCLEUS + PERSONA INJECTION (Opus GODMODE 16avr) === + $domainPatterns = [ + "code|programm|script|python|php|javascript|react|api|debug|bug" => ["code-mastery","fullstack-dev"], + "cyber|security|securite|firewall|ssl|hack|vuln|cors|xss" => ["cyber-mastery","cybersecurity-auditor"], + "sap|erp|s4hana|fiori|abap" => ["domain-expertise","sap-consultant"], + "pharma|hcp|medecin|ethica|docteur|patient" => ["domain-expertise","email-expert"], + "email|smtp|dkim|spf|dmarc|warmup|pmta|mta" => ["domain-expertise","email-expert"], + "ssh|serveur|linux|nginx|apache|docker|deploy" => ["ssh-mastery","cloud-architect"], + "rpa|automat|robot|selenium|playwright|scrape" => ["rpa-mastery","fullstack-dev"], + "cloud|aws|azure|gcp|kubernetes|k8s" => ["domain-expertise","cloud-architect"], + "data|analytics|ml|model|predict|dashboard" => ["domain-expertise","data-scientist"], + ]; + $nucleusExtra = ""; + foreach ($domainPatterns as $pat => $files) { + if (preg_match("/($pat)/i", $originalMessage)) { + $nf = "/opt/wevia-brain/prompts/nucleus/{$files[0]}.md"; + if (file_exists($nf)) $nucleusExtra .= "\n--- EXPERTISE DOMAIN ---\n" . substr(file_get_contents($nf), 0, 3000); + $pf = "/opt/wevia-brain/prompts/personas/{$files[1]}.md"; + if (file_exists($pf)) $nucleusExtra .= "\n--- PERSONA ---\n" . substr(file_get_contents($pf), 0, 1500); + break; + } + } + if ($nucleusExtra && $systemPrompt) { + $systemPrompt .= $nucleusExtra; + } elseif ($nucleusExtra) { + $systemPrompt = "Tu es WEVIA Master, IA souveraine de WEVAL Consulting Casablanca. Reponds en francais concis et technique." . $nucleusExtra; + } + +// Step 1d: Add Gemini as fallback provider // (Gemini uses native API, not OpenAI compat) // Step 2: Try tiers in cascade