This commit is contained in:
team 1
2026-05-10 08:55:05 +02:00
parent 7e96af5f1d
commit 96375668b2
9 changed files with 379 additions and 29 deletions

View File

@@ -1719,13 +1719,19 @@ final readonly class AgentRunner
return $shopSearchQuery;
}
$modelVariantSuffixTokens = $this->extractPositiveShopQueryModelVariantSuffixTokens($tokens, $blockedTokens, $codePatterns);
$kept = [];
foreach ($tokens as $token) {
if (isset($blockedTokens[$token]) || isset($kept[$token])) {
continue;
}
if (isset($allowedTokens[$token]) || $this->matchesAnyConfiguredShopQueryCodePattern($token, $codePatterns)) {
if (
isset($allowedTokens[$token])
|| isset($modelVariantSuffixTokens[$token])
|| $this->matchesAnyConfiguredShopQueryCodePattern($token, $codePatterns)
) {
$kept[$token] = $token;
}
}
@@ -1807,6 +1813,53 @@ final readonly class AgentRunner
return false;
}
/**
* Preserve model variant suffixes that are attached to an already retained
* model number in the same query, for example family-number-code product
* names. This prevents the positive-token filter from degrading a specific
* model variant to its generic base model.
*
* @param string[] $tokens
* @param array<string, true> $blockedTokens
* @param string[] $codePatterns
* @return array<string, true>
*/
private function extractPositiveShopQueryModelVariantSuffixTokens(
array $tokens,
array $blockedTokens,
array $codePatterns
): array {
$suffixTokens = [];
$count = count($tokens);
for ($index = 0; $index < $count; $index++) {
$token = $tokens[$index] ?? '';
if (!$this->matchesAnyConfiguredShopQueryCodePattern($token, $codePatterns)) {
continue;
}
for ($suffixIndex = $index + 1; $suffixIndex < $count; $suffixIndex++) {
$suffix = $tokens[$suffixIndex] ?? '';
if (isset($blockedTokens[$suffix]) || !$this->isPositiveShopQueryModelVariantSuffixToken($suffix)) {
break;
}
$suffixTokens[$suffix] = true;
}
}
return $suffixTokens;
}
private function isPositiveShopQueryModelVariantSuffixToken(string $token): bool
{
$token = trim($token);
return $token !== ''
&& preg_match('/^[\p{L}]{2,8}\d{0,3}$/u', $token) === 1;
}
private function cleanupDirectProductAttributeShopQuery(string $prompt, string $shopSearchQuery): string
{
$shopSearchQuery = trim($shopSearchQuery);
@@ -3321,10 +3374,6 @@ final readonly class AgentRunner
return $shopResults;
}
if ($this->isMixedDeviceAndAccessoryProductRequest($prompt, $shopSearchQuery)) {
return $shopResults;
}
$primaryMatches = [];
$corpusMatches = [];
@@ -3383,10 +3432,6 @@ final readonly class AgentRunner
return $emptyResult;
}
if ($this->isMixedDeviceAndAccessoryProductRequest($prompt, $shopSearchQuery)) {
return $emptyResult;
}
$repairQuery = $this->buildDirectProductPrimaryIdentityRepairQuery(
shopSearchQuery: $shopSearchQuery,
requestedTerms: $requestedTerms
@@ -4070,7 +4115,7 @@ final readonly class AgentRunner
}
$terms = [];
foreach ($this->agentRunnerConfig->getDirectShopResultProductIdentityTerms() as $term) {
foreach ($this->agentRunnerConfig->getShopQueryProductAttributeCleanupProductTypeTerms() as $term) {
if ($this->containsAllShopQueryTokens($combined, $term)) {
$terms[] = $term;
}
@@ -4079,17 +4124,6 @@ final readonly class AgentRunner
return array_values(array_unique($terms));
}
private function isMixedDeviceAndAccessoryProductRequest(string $prompt, string $shopSearchQuery): bool
{
$combined = mb_strtolower($this->normalizeOneLine($prompt . ' ' . $shopSearchQuery), 'UTF-8');
if ($combined === '') {
return false;
}
return $this->containsAnyConfiguredTerm($combined, $this->agentRunnerConfig->getNoLlmMainDeviceRequestRoleKeywords())
&& $this->containsAnyConfiguredTerm($combined, $this->agentRunnerConfig->getNoLlmAccessoryProductRoleKeywords());
}
private function containsAllShopQueryTokens(string $text, string $term): bool
{
$tokens = array_fill_keys($this->tokenizeShopQueryCandidate($text), true);
@@ -4235,7 +4269,6 @@ final readonly class AgentRunner
|| !$shopSearchAttempted
|| $shopSearchHadSystemFailure
|| $this->extractRequestedDirectProductTerms($prompt, $shopSearchQuery) === []
|| $this->isMixedDeviceAndAccessoryProductRequest($prompt, $shopSearchQuery)
) {
return '';
}
@@ -5457,7 +5490,7 @@ final readonly class AgentRunner
private function followUpActionAnswerAlreadyContainsPrice(string $answerText): bool
{
return preg_match('/(?:\bpreis\b.{0,24}\d+[,.]\d{2}|\d+[,.]\d{2}\s*(?:€|eur)\b|(?:€|eur)\s*\d+[,.]\d{2})/iu', $answerText) === 1;
return preg_match('/(?:\bpreise?\b.{0,80}\d+[,.]\d{2}\s*(?:€|eur\b)|\d+[,.]\d{2}\s*(?:€|eur\b)|(?:€|eur\b)\s*\d+[,.]\d{2})/iu', $answerText) === 1;
}
/**