optimize cleanup search query shop api extends part 2

This commit is contained in:
team2
2026-04-25 22:47:50 +02:00
parent 6cf8aac872
commit 2797834a5f
5 changed files with 119 additions and 12 deletions

View File

@@ -179,6 +179,59 @@ document.addEventListener('DOMContentLoaded', () => {
cleanupEmptyBlocks(container);
}
function hasVisibleContentAfterNode(container, markerNode) {
const walker = document.createTreeWalker(
container,
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT,
null
);
let afterMarker = false;
while (walker.nextNode()) {
const node = walker.currentNode;
if (node === markerNode) {
afterMarker = true;
continue;
}
if (!afterMarker) {
continue;
}
if (node.nodeType === Node.TEXT_NODE) {
if (node.parentElement?.closest('.think')) {
continue;
}
if ((node.textContent || '').trim() !== '') {
return true;
}
continue;
}
if (node.nodeType !== Node.ELEMENT_NODE) {
continue;
}
if (node.classList?.contains('think') || node.closest?.('.think')) {
continue;
}
if (node.tagName === 'BR') {
continue;
}
if ((node.textContent || '').trim() !== '' || hasMeaningfulChildContent(node)) {
return true;
}
}
return false;
}
function cleanupThinkSpans(container) {
if (!container) {
return;
@@ -191,12 +244,14 @@ document.addEventListener('DOMContentLoaded', () => {
return;
}
if (hasNonThinkContent(container)) {
removeThinkSpansOnly(container);
const lastThink = thinkSpans[thinkSpans.length - 1];
if (!hasVisibleContentAfterNode(container, lastThink)) {
keepOnlyLastThink(container);
return;
}
keepOnlyLastThink(container);
removeThinkSpansOnly(container);
}
function renderBubbleContent(bubble, raw) {

View File

@@ -765,11 +765,14 @@ final readonly class AgentRunner
private function streamFinalAnswer(string $finalPrompt): Generator
{
$fullOutput = '';
$firstThinkLoop = true;
$thinkingNoticeShown = false;
$chunker = new StreamChunker();
$this->thinkSuppressor->reset();
yield $this->systemMsg($this->agentRunnerConfig->getThinkingWhileStreamingMessage(), 'think');
$thinkingNoticeShown = true;
foreach ($this->ollamaClient->stream($finalPrompt) as $token) {
if (!is_string($token)) {
continue;
@@ -778,9 +781,9 @@ final readonly class AgentRunner
$cleanToken = $this->thinkSuppressor->filter($token);
if ($cleanToken === '') {
if ($firstThinkLoop) {
if (!$thinkingNoticeShown) {
yield $this->systemMsg($this->agentRunnerConfig->getThinkingWhileStreamingMessage(), 'think');
$firstThinkLoop = false;
$thinkingNoticeShown = true;
}
continue;
@@ -902,7 +905,7 @@ final readonly class AgentRunner
return '<div class="retriex-meta-card retriex-shop-meta">'
. '<div class="retriex-meta-card__eyebrow">Live-Shopdaten</div>'
. '<div class="retriex-meta-card__title">Shopware-Suche wird ausgeführt</div>'
. '<div class="retriex-meta-card__title">Shop-Suche wird ausgeführt</div>'
. '<div class="retriex-meta-card__body">'
. '<span class="retriex-meta-pill">' . htmlspecialchars($badge, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . '</span>'
. '<span class="retriex-meta-pill">Intent: ' . htmlspecialchars($intentLabel, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . '</span>'

View File

@@ -79,7 +79,6 @@ final readonly class CommerceQueryParser
private function normalize(string $prompt): string
{
$value = $this->textNormalizer->normalize($prompt);
$value = $this->queryCleaner->clean($value);
$value = mb_strtolower(trim($value));
$value = str_replace(
$this->config->getNormalizationSearch(),
@@ -274,7 +273,16 @@ final readonly class CommerceQueryParser
for ($offset = 1; $offset <= $this->config->getModelContextTokenWindow(); $offset++) {
$previousIndex = $index - $offset;
if (!isset($tokens[$previousIndex]) || !$this->isLikelyModelContextToken($tokens[$previousIndex])) {
if (!isset($tokens[$previousIndex])) {
break;
}
if ($this->isSemanticShopToken($tokens[$previousIndex])) {
$keep[$previousIndex] = true;
continue;
}
if (!$this->isLikelyModelContextToken($tokens[$previousIndex])) {
break;
}
@@ -287,7 +295,7 @@ final readonly class CommerceQueryParser
}
}
if ($this->isSemanticShopToken($token) || $this->isKnownBrandToken($token)) {
if ($this->isSemanticShopToken($token) || $this->isKnownBrandToken($token) || $this->isMeasurementValueToken($token)) {
$keep[$index] = true;
}
}
@@ -314,6 +322,10 @@ final readonly class CommerceQueryParser
return true;
}
if ($this->isMeasurementValueToken($token)) {
return false;
}
if (preg_match($this->config->getContainsDigitPattern(), $token) === 1) {
return false;
}
@@ -334,6 +346,11 @@ final readonly class CommerceQueryParser
return preg_match($this->config->getModelNumberTokenPattern(), $token) === 1;
}
private function isMeasurementValueToken(string $token): bool
{
return preg_match($this->config->getMeasurementValueTokenPattern(), $token) === 1;
}
private function isLikelyModelContextToken(string $token): bool
{
if ($this->isQueryNoiseToken($token)) {

View File

@@ -37,6 +37,13 @@ final class CommerceIntentConfig
'kalibrierlösung',
'kalibrierloesung',
'kalibrierung',
'chemie',
'reagenz',
'reagenzien',
'verbrauchsmaterial',
'zubehör',
'zubehoer',
'ersatzteil',
];
}
@@ -50,6 +57,10 @@ final class CommerceIntentConfig
'eignet',
'besser',
'besten',
'gut für',
'gut fuer',
'passend für',
'passend fuer',
'geeignet',
'geeigent',
'empfiehl',
@@ -195,6 +206,12 @@ final class CommerceIntentConfig
'/\bartikel\b/u',
'/\bsku\b/u',
'/\bonline\b/u',
'/\bchemie\b/u',
'/\breagenz(?:ien)?\b/u',
'/\bverbrauchsmaterial(?:ien)?\b/u',
'/\bzubehör\b/u',
'/\bzubehoer\b/u',
'/\bersatzteil(?:e)?\b/u',
];
}

View File

@@ -133,6 +133,14 @@ final class CommerceQueryParserConfig
'kostet',
'kosten',
'ua',
'also',
'gut',
'gute',
'guten',
'guter',
'gutes',
'passen',
'passend',
];
}
@@ -297,7 +305,7 @@ final class CommerceQueryParserConfig
public function getModelContextTokenWindow(): int
{
return 2;
return 4;
}
public function getMinMeaningfulAlphaTokenLength(): int
@@ -312,7 +320,11 @@ final class CommerceQueryParserConfig
public function getInstructionOrPresentationTokenPattern(): string
{
return '/^(?:zeig(?:e)?|such(?:e)?|find(?:e)?|gib|gebe|nenn(?:e)?|liefer(?:e)?|erstelle?|mach(?:e)?|brauch(?:e)?|will|möchte|moechte|hätte|haette|kannst|bitte|mal|alle|alles|komplett|vollständig|vollstaendig|gesamt|ganze|ganzen|liste|listung|auflistung|tabelle|tabellarisch|übersicht|uebersicht|anzeigen?|ausgeben?|darstellen?|antwort(?:e)?|erklär(?:e)?|erklaer(?:e)?|info|infos|informationen|dazu|hierzu|damit|davon|an|als|mit|ohne|inkl|inklusive)$/u';
return '/^(?:zeig(?:e)?|such(?:e)?|find(?:e)?|gib|gebe|nenn(?:e)?|liefer(?:e)?|erstelle?|mach(?:e)?|brauch(?:e)?|will|möchte|moechte|hätte|haette|kannst|bitte|mal|alle|alles|komplett|vollständig|vollstaendig|gesamt|ganze|ganzen|liste|listung|auflistung|tabelle|tabellarisch|übersicht|uebersicht|anzeigen?|ausgeben?|darstellen?|antwort(?:e)?|erklär(?:e)?|erklaer(?:e)?|info|infos|informationen|dazu|hierzu|damit|davon|an|als|mit|ohne|inkl|inklusive|also|gut|gute|guten|guter|gutes|passend|passen)$/u';
}
public function getMeasurementValueTokenPattern(): string
{
return '/^\d+[.,]\d+$/u';
}
/**
@@ -332,6 +344,9 @@ final class CommerceQueryParserConfig
'zubehor',
'ersatzteil',
'verbrauchsmaterial',
'chemie',
'indikatorchemie',
'reagenzchemie',
'kit',
'set',
'filter',