fix shop research intent

This commit is contained in:
team 1
2026-04-27 16:11:25 +02:00
parent 75c376c7a8
commit 8c40153745
7 changed files with 157 additions and 4 deletions

View File

@@ -25,6 +25,10 @@ final class CommerceIntentConfig
'analysegeraet',
'messgerät',
'messgeraet',
'pockettester',
'pocket tester',
'handmessgerät',
'handmessgeraet',
'analysator',
'analyzer',
'puffer',
@@ -46,6 +50,7 @@ final class CommerceIntentConfig
'eignet',
'besser',
'besten',
'gut',
'gut für',
'gut fuer',
'passend für',

View File

@@ -40,7 +40,11 @@ final class CommerceIntentLite
);
}
if ($this->isTechnicalFactualKnowledgeQuery($prompt) && !$this->hasExplicitCommerceIntent($prompt)) {
if (
$this->isTechnicalFactualKnowledgeQuery($prompt)
&& !$this->hasExplicitCommerceIntent($prompt)
&& !$this->hasAdvisoryProductSelectionIntent($prompt)
) {
return $this->buildDetectionResult(
intent: self::NONE,
score: 0,
@@ -95,6 +99,81 @@ final class CommerceIntentLite
return $this->matchesAnyPattern($prompt, $this->config->getExplicitCommerceIntentPatterns());
}
/**
* Product advisory prompts can contain technical words such as "Messung".
*
* They must not be swallowed by the factual RAG guard when the user is
* clearly asking for a suitable shop product or device class.
*/
private function hasAdvisoryProductSelectionIntent(string $prompt): bool
{
if (!$this->containsConfiguredAdvisorySignal($prompt)) {
return false;
}
if (preg_match($this->config->getModelLikeProductPattern(), $prompt) === 1) {
return true;
}
foreach ($this->config->getStrongSignalsList() as $signal) {
$signal = mb_strtolower(trim($signal));
if ($signal === '' || $this->isNonProductCommerceSignal($signal)) {
continue;
}
if (str_contains($prompt, $signal)) {
return true;
}
}
return false;
}
private function containsConfiguredAdvisorySignal(string $prompt): bool
{
foreach ($this->config->getAdvisorySignals() as $signal) {
if ($this->containsConfiguredPhraseOrToken($prompt, $signal)) {
return true;
}
}
return false;
}
private function containsConfiguredPhraseOrToken(string $prompt, string $signal): bool
{
$signal = mb_strtolower(trim($signal));
if ($signal === '') {
return false;
}
if (preg_match('/\s/u', $signal) === 1) {
return str_contains($prompt, $signal);
}
$pattern = '/(?<![\p{L}\p{N}])' . preg_quote($signal, '/') . '(?![\p{L}\p{N}])/u';
return preg_match($pattern, $prompt) === 1;
}
private function isNonProductCommerceSignal(string $signal): bool
{
return in_array($signal, [
'shop',
'alle',
'kunde',
'online',
'kaufen',
'kostet',
'suche',
'such',
'finde',
'finden',
], true);
}
/**
* Detects factual technical knowledge questions that must stay in RAG retrieval.
*
@@ -255,7 +334,7 @@ final class CommerceIntentLite
private function applyAdvisorySignals(string $prompt, int $score, array $signals): array
{
foreach ($this->config->getAdvisorySignals() as $signal) {
if (str_contains($prompt, mb_strtolower($signal))) {
if ($this->containsConfiguredPhraseOrToken($prompt, $signal)) {
$score += $this->config->getAdvisorySignalScore();
$signals[] = $this->config->getAdvisorySignalPrefix() . $signal;
}