optimize retrieve logic

This commit is contained in:
team 1
2026-04-14 12:43:43 +02:00
parent 406e59b0fd
commit 7caf6b5354
6 changed files with 51 additions and 41 deletions

View File

@@ -36,10 +36,9 @@ final readonly class AgentRunner
$this->systemMsgOn = true; $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); $prompt = trim($prompt);
$shopResults = [];
$swagFullOutPut = ''; $swagFullOutPut = '';
if ($prompt === '') { if ($prompt === '') {
@@ -55,19 +54,22 @@ final readonly class AgentRunner
// --------------------------------------------------------- // ---------------------------------------------------------
// 1) Context strategy // 1) Context strategy
// --------------------------------------------------------- // ---------------------------------------------------------
//$includeFullContext = false;
if ($includeFullContext) { 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. Erzeuge aus dem folgenden Nutzereingabetext einen kurzen Suchtext für die Shopware-6-Suche.
Regeln: Regeln:
- Gib nur den finalen Suchtext aus. - Gib nur den finalen Suchtext aus.
- erstelle immer die singular form von den relevanten Suchbegriffen
- Keine Einleitung, keine Erklärung, keine Anführungszeichen. - Keine Einleitung, keine Erklärung, keine Anführungszeichen.
- Verwende nur die wichtigsten Suchbegriffe aus dem Text. - Verwende nur die shop relevanten Suchbegriffe für eine Shopsuche aus dem Nutzereingabetext.
- Maximal 6 Keywords, besser weniger. - Maximal 6 Suchbegriffe, besser weniger.
- Entferne Füllwörter, Höflichkeitsformen und irrelevante Wörter. - Entferne Füllwörter, Höflichkeitsformen und irrelevante Wörter.
- Erhalte Produktnamen, Marken, Modellnummern und zusammengesetzte Begriffe exakt, wenn sie relevant sind. - 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. - 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 . ' 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)) { if (!is_string($swagToken)) {
continue; continue;
}
$swagCleanToken = $this->thinkSuppressor->filter($swagToken);
if ($swagCleanToken === '') {
continue;
}
$swagFullOutPut .= $swagCleanToken;
} }
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) // 2) Extract URL content (if present)
@@ -120,11 +119,7 @@ final readonly class AgentRunner
$commerceMeta = $this->commerceIntentLite->detect($prompt); $commerceMeta = $this->commerceIntentLite->detect($prompt);
$commerceIntent = (string)($commerceMeta['intent'] ?? CommerceIntentLite::NONE); $commerceIntent = (string)($commerceMeta['intent'] ?? CommerceIntentLite::NONE);
if ($commerceIntent === CommerceIntentLite::ADVISORY_PRODUCT_SEARCH || $commerceIntent === CommerceIntentLite::PRODUCT_SEARCH) { yield $this->systemMsg("Ich rufe Shopdaten ab (type: " . $commerceIntent . ")", "think");
//older
}
yield $this->systemMsg("Rufe Shop auf (type: " . $commerceIntent . ")", "think");
$shopResults = $swagFullOutPut ? $this->shopSearchService->search($swagFullOutPut, $commerceIntent) : ''; $shopResults = $swagFullOutPut ? $this->shopSearchService->search($swagFullOutPut, $commerceIntent) : '';
if ($commerceIntent === CommerceIntentLite::PRODUCT_SEARCH) { if ($commerceIntent === CommerceIntentLite::PRODUCT_SEARCH) {
@@ -134,12 +129,12 @@ final readonly class AgentRunner
} }
if ($shopResults) { if ($shopResults) {
yield $this->systemMsg("Verarbeite Shopdaten...", "think"); yield $this->systemMsg("Ich verarbeite Shopdaten...", "think");
} else { } 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 // 5) Build final prompt
@@ -150,7 +145,8 @@ final readonly class AgentRunner
urlContent: $urlContent, urlContent: $urlContent,
knowledgeChunks: $knowledgeChunks, knowledgeChunks: $knowledgeChunks,
shopResults: $shopResults, shopResults: $shopResults,
fullContext: $includeFullContext fullContext: $includeFullContext,
swagFullOutPut: $swagFullOutPut
); );
if ($this->debug && $this->logPrompt) { if ($this->debug && $this->logPrompt) {
@@ -183,6 +179,8 @@ final readonly class AgentRunner
$cleanToken = $this->thinkSuppressor->filter((string)$token); $cleanToken = $this->thinkSuppressor->filter((string)$token);
if ($cleanToken === '') { if ($cleanToken === '') {
yield $this->systemMsg("Denke nach...", "think");
usleep(500);
continue; continue;
} }
@@ -201,7 +199,7 @@ final readonly class AgentRunner
if ($finalChunk !== null) { if ($finalChunk !== null) {
yield $this->systemMsg($finalChunk, 'answer'); yield $this->systemMsg($finalChunk, 'answer');
} else { } else {
yield $this->systemMsg('... no data received from llm', 'err'); yield $this->systemMsg('... no more data received from llm', 'err');
} }
// --------------------------------------------------------- // ---------------------------------------------------------

View File

@@ -30,12 +30,14 @@ final readonly class PromptBuilder
* @return string * @return string
*/ */
public function build( public function build(
string $prompt, string $prompt,
string $userId, string $userId,
string $urlContent, string $urlContent,
array $knowledgeChunks, array $knowledgeChunks,
array $shopResults = [], array $shopResults = [],
?bool $fullContext = false, ?bool $fullContext = false,
?string $swagFullOutPut = ''
): string ): string
{ {
$now = (new DateTimeImmutable())->format('Y-m-d H:i:s'); $now = (new DateTimeImmutable())->format('Y-m-d H:i:s');
@@ -77,6 +79,10 @@ final readonly class PromptBuilder
$shopBlock = ''; $shopBlock = '';
$isDetailed = !(count($shopResults) > 5); $isDetailed = !(count($shopResults) > 5);
if($swagFullOutPut){
$shopBlock = "SHOP SEARCH QUERY: " . trim($swagFullOutPut)."\n";
}
if ($shopResults !== []) { if ($shopResults !== []) {
$lines = []; $lines = [];
@@ -130,7 +136,7 @@ final readonly class PromptBuilder
} }
if ($lines !== []) { if ($lines !== []) {
$shopBlock = $shopBlock .=
"LIVE SHOP RESULTS (authoritative for products):\n" . "LIVE SHOP RESULTS (authoritative for products):\n" .
implode("\n\n", $lines); implode("\n\n", $lines);
} }
@@ -141,6 +147,7 @@ final readonly class PromptBuilder
// ------------------------------------------------------------ // ------------------------------------------------------------
$knowledgeParts = []; $knowledgeParts = [];
if ($knowledgeChunks !== []) { if ($knowledgeChunks !== []) {
$lines = []; $lines = [];

View File

@@ -68,7 +68,7 @@ final class ContextService
* @param string $userId Stable client identifier * @param string $userId Stable client identifier
* @param bool $full Whether to load extended history * @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); $path = $this->getHistoryPath($userId);

View File

@@ -58,7 +58,7 @@ final readonly class AskSseController
// --------------------------------------------------------- // ---------------------------------------------------------
// 🔥 FIXED: Sende Chunks direkt (behält \n!) // 🔥 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 // Normalize line endings
$chunk = str_replace(["\r\n", "\r"], "\n", $chunk); $chunk = str_replace(["\r\n", "\r"], "\n", $chunk);

View File

@@ -43,7 +43,10 @@ final class CommerceIntentLite
'Gerät', 'Gerät',
'testomat', 'testomat',
'indikator', 'indikator',
'Titromat' 'Titromat',
'Seminar',
'Schulung',
'Sensor'
]; ];
foreach ($strongSignals as $signal) { foreach ($strongSignals as $signal) {

View File

@@ -121,6 +121,8 @@ final class QueryEnricher
'Wasserhärte' => "Resthärte", 'Wasserhärte' => "Resthärte",
'Gerät' => 'Modell', 'Gerät' => 'Modell',
'Indikator' => 'Chemie', 'Indikator' => 'Chemie',
'Seminar' => 'Webinar',
'Schulung' => 'Seminar',
'Indikatoren' => 'Indikator', 'Indikatoren' => 'Indikator',
'Wasserhärte-Grenzwert'=>'Resthärte', 'Wasserhärte-Grenzwert'=>'Resthärte',
'Resthärte-Grenzwert'=>'Wasserhärte' 'Resthärte-Grenzwert'=>'Wasserhärte'