diff --git a/src/Agent/AgentRunner.php b/src/Agent/AgentRunner.php index 8960481..31e323b 100644 --- a/src/Agent/AgentRunner.php +++ b/src/Agent/AgentRunner.php @@ -36,10 +36,9 @@ final readonly class AgentRunner $this->systemMsgOn = true; } - public function run(string $prompt, string $userId, ?bool $includeFullContext = true): Generator + public function run(string $prompt, string $userId, ?bool $includeFullContext = false): Generator { $prompt = trim($prompt); - $shopResults = []; $swagFullOutPut = ''; if ($prompt === '') { @@ -55,19 +54,22 @@ final readonly class AgentRunner // --------------------------------------------------------- // 1) Context strategy // --------------------------------------------------------- - //$includeFullContext = false; + if ($includeFullContext) { + //Coming soon + } - yield $this->systemMsg("Ich analysiere deine Anfrage...", "think"); + yield $this->systemMsg("Ich analysiere deine Anfrage...", "think"); - $promptSwagSearch = ' + $promptSwagSearch = ' Erzeuge aus dem folgenden Nutzereingabetext einen kurzen Suchtext für die Shopware-6-Suche. Regeln: - Gib nur den finalen Suchtext aus. + - erstelle immer die singular form von den relevanten Suchbegriffen - Keine Einleitung, keine Erklärung, keine Anführungszeichen. - - Verwende nur die wichtigsten Suchbegriffe aus dem Text. - - Maximal 6 Keywords, besser weniger. + - Verwende nur die shop relevanten Suchbegriffe für eine Shopsuche aus dem Nutzereingabetext. + - Maximal 6 Suchbegriffe, besser weniger. - Entferne Füllwörter, Höflichkeitsformen und irrelevante Wörter. - Erhalte Produktnamen, Marken, Modellnummern und zusammengesetzte Begriffe exakt, wenn sie relevant sind. - Zahlen, die zu einem Produktnamen oder Modell gehören (zb Indikator 300 oder Testomat 808), müssen erhalten bleiben. @@ -79,27 +81,24 @@ final readonly class AgentRunner Text: ' . $prompt . ' '; - $this->thinkSuppressor->reset(); + $this->thinkSuppressor->reset(); - foreach ($this->ollamaClient->stream($promptSwagSearch) as $swagToken) { + foreach ($this->ollamaClient->stream($promptSwagSearch) as $swagToken) { - if (!is_string($swagToken)) { - continue; - } - - $swagCleanToken = $this->thinkSuppressor->filter($swagToken); - - if ($swagCleanToken === '') { - continue; - } - - $swagFullOutPut .= $swagCleanToken; + if (!is_string($swagToken)) { + continue; } - yield $this->systemMsg("Ich habe folgende Keywords an die Shopsuche geschickt: " . $swagFullOutPut, "think"); + $swagCleanToken = $this->thinkSuppressor->filter($swagToken); + if ($swagCleanToken === '') { + continue; + } + + $swagFullOutPut .= $swagCleanToken; } + yield $this->systemMsg("Ich habe folgende Keywords an die Shopsuche geschickt: " . $swagFullOutPut, "think"); // --------------------------------------------------------- // 2) Extract URL content (if present) @@ -120,11 +119,7 @@ final readonly class AgentRunner $commerceMeta = $this->commerceIntentLite->detect($prompt); $commerceIntent = (string)($commerceMeta['intent'] ?? CommerceIntentLite::NONE); - if ($commerceIntent === CommerceIntentLite::ADVISORY_PRODUCT_SEARCH || $commerceIntent === CommerceIntentLite::PRODUCT_SEARCH) { - //older - } - - yield $this->systemMsg("Rufe Shop auf (type: " . $commerceIntent . ")", "think"); + yield $this->systemMsg("Ich rufe Shopdaten ab (type: " . $commerceIntent . ")", "think"); $shopResults = $swagFullOutPut ? $this->shopSearchService->search($swagFullOutPut, $commerceIntent) : ''; if ($commerceIntent === CommerceIntentLite::PRODUCT_SEARCH) { @@ -134,12 +129,12 @@ final readonly class AgentRunner } if ($shopResults) { - yield $this->systemMsg("Verarbeite Shopdaten...", "think"); + yield $this->systemMsg("Ich verarbeite Shopdaten...", "think"); } else { - yield $this->systemMsg("Keine releveanten Shopdaten gefunden...", "think"); + yield $this->systemMsg("Ich habe keine releveanten Shopdaten gefunden...", "think"); } - yield $this->systemMsg("Denke nach...", "think"); + yield $this->systemMsg("Ich analysiere gefundene Informationen...", "think"); // --------------------------------------------------------- // 5) Build final prompt @@ -150,7 +145,8 @@ final readonly class AgentRunner urlContent: $urlContent, knowledgeChunks: $knowledgeChunks, shopResults: $shopResults, - fullContext: $includeFullContext + fullContext: $includeFullContext, + swagFullOutPut: $swagFullOutPut ); if ($this->debug && $this->logPrompt) { @@ -183,6 +179,8 @@ final readonly class AgentRunner $cleanToken = $this->thinkSuppressor->filter((string)$token); if ($cleanToken === '') { + yield $this->systemMsg("Denke nach...", "think"); + usleep(500); continue; } @@ -201,7 +199,7 @@ final readonly class AgentRunner if ($finalChunk !== null) { yield $this->systemMsg($finalChunk, 'answer'); } else { - yield $this->systemMsg('... no data received from llm', 'err'); + yield $this->systemMsg('... no more data received from llm', 'err'); } // --------------------------------------------------------- diff --git a/src/Agent/PromptBuilder.php b/src/Agent/PromptBuilder.php index 8bf6442..48720ae 100644 --- a/src/Agent/PromptBuilder.php +++ b/src/Agent/PromptBuilder.php @@ -30,12 +30,14 @@ final readonly class PromptBuilder * @return string */ public function build( - string $prompt, - string $userId, - string $urlContent, - array $knowledgeChunks, - array $shopResults = [], - ?bool $fullContext = false, + string $prompt, + string $userId, + string $urlContent, + array $knowledgeChunks, + array $shopResults = [], + ?bool $fullContext = false, + ?string $swagFullOutPut = '' + ): string { $now = (new DateTimeImmutable())->format('Y-m-d H:i:s'); @@ -77,6 +79,10 @@ final readonly class PromptBuilder $shopBlock = ''; $isDetailed = !(count($shopResults) > 5); + if($swagFullOutPut){ + $shopBlock = "SHOP SEARCH QUERY: " . trim($swagFullOutPut)."\n"; + } + if ($shopResults !== []) { $lines = []; @@ -130,7 +136,7 @@ final readonly class PromptBuilder } if ($lines !== []) { - $shopBlock = + $shopBlock .= "LIVE SHOP RESULTS (authoritative for products):\n" . implode("\n\n", $lines); } @@ -141,6 +147,7 @@ final readonly class PromptBuilder // ------------------------------------------------------------ $knowledgeParts = []; + if ($knowledgeChunks !== []) { $lines = []; diff --git a/src/Context/ContextService.php b/src/Context/ContextService.php index 3fa3e82..e6b609f 100644 --- a/src/Context/ContextService.php +++ b/src/Context/ContextService.php @@ -68,7 +68,7 @@ final class ContextService * @param string $userId Stable client identifier * @param bool $full Whether to load extended history */ - public function buildUserContext(string $userId, bool $full = false): string + public function buildUserContext(string $userId, bool $full = true): string { $path = $this->getHistoryPath($userId); diff --git a/src/Controller/AskSseController.php b/src/Controller/AskSseController.php index 351374f..4a70a74 100644 --- a/src/Controller/AskSseController.php +++ b/src/Controller/AskSseController.php @@ -58,7 +58,7 @@ final readonly class AskSseController // --------------------------------------------------------- // 🔥 FIXED: Sende Chunks direkt (behält \n!) // --------------------------------------------------------- - foreach ($this->agentRunner->run($prompt, $clientId) as $chunk) { + foreach ($this->agentRunner->run($prompt, $clientId,true) as $chunk) { // Normalize line endings $chunk = str_replace(["\r\n", "\r"], "\n", $chunk); diff --git a/src/Intent/CommerceIntentLite.php b/src/Intent/CommerceIntentLite.php index 923bd22..fd19010 100644 --- a/src/Intent/CommerceIntentLite.php +++ b/src/Intent/CommerceIntentLite.php @@ -43,7 +43,10 @@ final class CommerceIntentLite 'Gerät', 'testomat', 'indikator', - 'Titromat' + 'Titromat', + 'Seminar', + 'Schulung', + 'Sensor' ]; foreach ($strongSignals as $signal) { diff --git a/src/Knowledge/Retrieval/QueryEnricher.php b/src/Knowledge/Retrieval/QueryEnricher.php index ca0cdb1..1bac354 100644 --- a/src/Knowledge/Retrieval/QueryEnricher.php +++ b/src/Knowledge/Retrieval/QueryEnricher.php @@ -121,6 +121,8 @@ final class QueryEnricher 'Wasserhärte' => "Resthärte", 'Gerät' => 'Modell', 'Indikator' => 'Chemie', + 'Seminar' => 'Webinar', + 'Schulung' => 'Seminar', 'Indikatoren' => 'Indikator', 'Wasserhärte-Grenzwert'=>'Resthärte', 'Resthärte-Grenzwert'=>'Wasserhärte'