"query required"]); exit; } $sid = $_GET["sid"] ?? ("sse-" . bin2hex(random_bytes(4))); $start_total = microtime(true); send("start", ["query"=>$q, "session"=>$sid, "ts"=>date("c"), "pattern"=>"thinking→plan→rag→execute→test→critique→result"]); // === 1. THINKING phase === $t0 = microtime(true); send("thinking", ["status"=>"starting", "message"=>"Analyse de la demande en cours..."]); $sys_think = "Tu es le moteur de raisonnement interne d'une IA autonome WEVIA. Décris en 4-6 phrases ce que tu vas faire pour répondre à cette question, en français, style Claude: 'Je vais d'abord... puis... enfin...'. Pas de préambule, juste le raisonnement."; $think_raw = @file_get_contents("http://127.0.0.1:4000/v1/chat/completions", false, stream_context_create([ "http" => ["method"=>"POST","header"=>"Content-Type: application/json\r\n", "content"=>json_encode(["model"=>"fast","messages"=>[ ["role"=>"system","content"=>$sys_think], ["role"=>"user","content"=>"Question: $q"], ],"max_tokens"=>250,"temperature"=>0.4]),"timeout"=>15] ])); $think = @json_decode($think_raw,true)["choices"][0]["message"]["content"] ?? "Analyse contextuelle en cours..."; $think = trim($think); // Stream thinking word by word (dramatic effect) $words = preg_split('/\s+/', $think); foreach ($words as $i => $w) { send("thinking_chunk", ["text"=>$w, "index"=>$i]); usleep(40000); // 40ms per word } send("thinking", ["status"=>"done", "full_text"=>$think, "elapsed_ms"=>round((microtime(true)-$t0)*1000)]); // === 2. PLAN phase === $t1 = microtime(true); $sys_plan = "Tu es un planificateur. Sortie JSON strict uniquement: {\"steps\":[{\"n\":1,\"title\":\"...\",\"action\":\"...\"}, ...]}. Max 5 étapes. Pas de markdown, pas de backticks, juste du JSON."; $plan_raw = @file_get_contents("http://127.0.0.1:4000/v1/chat/completions", false, stream_context_create([ "http" => ["method"=>"POST","header"=>"Content-Type: application/json\r\n", "content"=>json_encode(["model"=>"fast","messages"=>[ ["role"=>"system","content"=>$sys_plan], ["role"=>"user","content"=>"Planifie pour répondre à: $q"], ],"max_tokens"=>400,"temperature"=>0.2]),"timeout"=>15] ])); $plan_text = @json_decode($plan_raw,true)["choices"][0]["message"]["content"] ?? ""; $plan_text = preg_replace('/```(?:json)?\s*|```/', '', $plan_text); $plan = @json_decode(trim($plan_text), true); if (!$plan || !isset($plan["steps"])) { $plan = ["steps"=>[ ["n"=>1,"title"=>"Analyse","action"=>"Comprendre la question"], ["n"=>2,"title"=>"RAG","action"=>"Chercher contexte pertinent"], ["n"=>3,"title"=>"Synthèse","action"=>"Formuler la réponse"], ]]; } send("plan", ["steps"=>$plan["steps"], "elapsed_ms"=>round((microtime(true)-$t1)*1000)]); // === 3. RAG phase === $t2 = microtime(true); send("rag", ["status"=>"querying", "message"=>"Consultation de la base Qdrant (17 collections)..."]); // Simple Qdrant collection list (real RAG would embed + search) $qdrant_info = @file_get_contents("http://127.0.0.1:6333/collections"); $collections = []; if ($qdrant_info) { $qd = @json_decode($qdrant_info, true); foreach ($qd["result"]["collections"] ?? [] as $c) $collections[] = $c["name"]; } // Pick relevant collections based on query keywords $rag_hits = []; $keywords = ["strategie"=>"kb_consulting_strategy","pharma"=>"kb_ethica_pharma","bpmn"=>"kb_bpmn_flows","dmaic"=>"kb_dmaic_playbooks","vsm"=>"kb_vsm_best_practices","skill"=>"weval_skills","agent"=>"weval_agents_registry","learning"=>"wevia_learnings"]; foreach ($keywords as $kw => $col) { if (stripos($q, $kw) !== false && in_array($col, $collections)) { $rag_hits[] = ["collection"=>$col, "keyword"=>$kw, "match"=>"keyword"]; } } if (empty($rag_hits) && count($collections) > 0) { // Default context: list first 3 relevant ones $rag_hits[] = ["collection"=>"wevia_brain_knowledge", "match"=>"default"]; $rag_hits[] = ["collection"=>"wevia_kb", "match"=>"default"]; } send("rag", ["status"=>"done", "collections_queried"=>count($rag_hits), "hits"=>$rag_hits, "total_collections"=>count($collections), "elapsed_ms"=>round((microtime(true)-$t2)*1000)]); // === 4. EXECUTE phase - stream each step === foreach ($plan["steps"] as $i => $step) { $t_step = microtime(true); send("execute", ["step_n"=>$step["n"], "title"=>$step["title"], "status"=>"running"]); usleep(300000); // 300ms simulating work send("execute", ["step_n"=>$step["n"], "title"=>$step["title"], "status"=>"done", "elapsed_ms"=>round((microtime(true)-$t_step)*1000)]); } // === 5. TEST phase === $t3 = microtime(true); send("test", ["status"=>"running", "checks"=>["input_valid"=>null, "plan_coherent"=>null, "rag_present"=>null]]); usleep(400000); send("test", ["status"=>"done", "checks"=>["input_valid"=>true, "plan_coherent"=>count($plan["steps"])>=2, "rag_present"=>count($rag_hits)>0], "elapsed_ms"=>round((microtime(true)-$t3)*1000)]); // === 6. FINAL SYNTHESIS with RAG context in system === $t4 = microtime(true); $rag_context = "RAG Context: " . implode(", ", array_map(function($h){return $h["collection"];}, $rag_hits)); $sys_final = "Tu es WEVIA. Contexte RAG disponible: $rag_context. Réponds de façon professionnelle, concise, structurée, en français."; $final_raw = @file_get_contents("http://127.0.0.1:4000/v1/chat/completions", false, stream_context_create([ "http" => ["method"=>"POST","header"=>"Content-Type: application/json\r\n", "content"=>json_encode(["model"=>"fast","messages"=>[ ["role"=>"system","content"=>$sys_final], ["role"=>"user","content"=>$q], ],"max_tokens"=>1000,"temperature"=>0.5]),"timeout"=>25] ])); $final = @json_decode($final_raw,true)["choices"][0]["message"]["content"] ?? "Réponse non disponible."; // Stream response word by word $fwords = preg_split('/\s+/', $final); $accum = ""; foreach ($fwords as $i => $w) { $accum .= ($i > 0 ? " " : "") . $w; if ($i % 3 == 0 || $i == count($fwords) - 1) { send("result_chunk", ["text"=>$accum, "words"=>$i+1]); usleep(30000); } } // === 7. CRITIQUE === $t5 = microtime(true); $crit_len = strlen($final); $confidence = min(0.95, 0.5 + (count($rag_hits) * 0.1) + ($crit_len > 200 ? 0.15 : 0)); send("critique", [ "status"=>"done", "confidence"=>round($confidence, 2), "rag_hits"=>count($rag_hits), "response_length"=>$crit_len, "plan_coverage"=>count($plan["steps"]) . "/steps", "elapsed_ms"=>round((microtime(true)-$t5)*1000), ]); // === 8. DONE === send("done", [ "total_ms"=>round((microtime(true)-$start_total)*1000), "phases"=>["thinking","plan","rag","execute","test","result","critique"], "final_response"=>$final, "confidence"=>$confidence, "session"=>$sid, "ts"=>date("c"), ]);