p85
This commit is contained in:
@@ -355,6 +355,21 @@ final readonly class AgentRunner
|
||||
$optimizedShopQuery = '';
|
||||
}
|
||||
|
||||
$deviceAnchoredShopSearchQuery = $this->enrichGenericDeviceShopQueryWithConfiguredAnchor($shopSearchQuery);
|
||||
if ($deviceAnchoredShopSearchQuery !== $shopSearchQuery) {
|
||||
$this->agentLogger->info('Enriched generic device shop query with configured product-family anchor', [
|
||||
'userId' => $userId,
|
||||
'prompt' => $prompt,
|
||||
'routingPrompt' => $routingPrompt,
|
||||
'optimizedShopQuery' => $optimizedShopQuery,
|
||||
'shopSearchQuery' => $shopSearchQuery,
|
||||
'deviceAnchoredShopSearchQuery' => $deviceAnchoredShopSearchQuery,
|
||||
]);
|
||||
|
||||
$shopSearchQuery = $deviceAnchoredShopSearchQuery;
|
||||
$optimizedShopQuery = '';
|
||||
}
|
||||
|
||||
$positiveFilteredShopSearchQuery = $this->filterShopQueryToPositiveTokens($shopSearchQuery);
|
||||
if ($positiveFilteredShopSearchQuery !== $shopSearchQuery) {
|
||||
$this->agentLogger->info('Filtered final shop search query to positive product tokens', [
|
||||
@@ -1718,6 +1733,99 @@ final readonly class AgentRunner
|
||||
return $cleaned !== '' ? $cleaned : $shopSearchQuery;
|
||||
}
|
||||
|
||||
private function enrichGenericDeviceShopQueryWithConfiguredAnchor(string $shopSearchQuery): string
|
||||
{
|
||||
$shopSearchQuery = trim($shopSearchQuery);
|
||||
|
||||
if (
|
||||
$shopSearchQuery === ''
|
||||
|| !$this->agentRunnerConfig->isGenericDeviceQueryAnchorEnabled()
|
||||
) {
|
||||
return $shopSearchQuery;
|
||||
}
|
||||
|
||||
$tokens = $this->tokenizeShopQueryCandidate($shopSearchQuery);
|
||||
if ($tokens === []) {
|
||||
return $shopSearchQuery;
|
||||
}
|
||||
|
||||
$tokenSet = array_fill_keys($tokens, true);
|
||||
$genericDeviceTokens = $this->buildShopQueryTokenSet(
|
||||
$this->agentRunnerConfig->getGenericDeviceQueryAnchorTriggerTerms()
|
||||
);
|
||||
|
||||
if (!$this->tokenSetIntersects($tokenSet, $genericDeviceTokens)) {
|
||||
return $shopSearchQuery;
|
||||
}
|
||||
|
||||
$suppressTokens = $this->buildShopQueryTokenSet(
|
||||
$this->agentRunnerConfig->getGenericDeviceQueryAnchorSuppressTerms()
|
||||
);
|
||||
|
||||
if ($this->tokenSetIntersects($tokenSet, $suppressTokens)) {
|
||||
return $shopSearchQuery;
|
||||
}
|
||||
|
||||
foreach ($this->agentRunnerConfig->getGenericDeviceQueryAnchorRules() as $rule) {
|
||||
$anchor = $rule['anchor'];
|
||||
if ($anchor === '' || !$this->containsAnyShopQueryTerm($shopSearchQuery, $rule['match_terms'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->queryAlreadyContainsAllAnchorTokens($shopSearchQuery, $anchor)) {
|
||||
return $shopSearchQuery;
|
||||
}
|
||||
|
||||
$query = $this->agentRunnerConfig->shouldGenericDeviceQueryAnchorRemoveGenericDeviceTerms()
|
||||
? $this->removeConfiguredGenericDeviceShopQueryTerms(
|
||||
$shopSearchQuery,
|
||||
$this->agentRunnerConfig->getGenericDeviceQueryAnchorTriggerTerms()
|
||||
)
|
||||
: $shopSearchQuery;
|
||||
|
||||
$template = $this->agentRunnerConfig->getGenericDeviceQueryAnchorTemplate();
|
||||
if ($template === '') {
|
||||
return $shopSearchQuery;
|
||||
}
|
||||
|
||||
$enriched = $this->renderAgentTemplate($template, [
|
||||
'anchor' => $anchor,
|
||||
'query' => $query,
|
||||
]);
|
||||
$enriched = preg_replace('/\s+/u', ' ', $enriched) ?? $enriched;
|
||||
$enriched = trim($enriched);
|
||||
|
||||
return $enriched !== '' ? $enriched : $shopSearchQuery;
|
||||
}
|
||||
|
||||
return $shopSearchQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $genericDeviceTerms
|
||||
*/
|
||||
private function removeConfiguredGenericDeviceShopQueryTerms(string $shopSearchQuery, array $genericDeviceTerms): string
|
||||
{
|
||||
$removeTokens = $this->buildShopQueryTokenSet($genericDeviceTerms);
|
||||
|
||||
if ($removeTokens === []) {
|
||||
return $shopSearchQuery;
|
||||
}
|
||||
|
||||
$kept = [];
|
||||
foreach ($this->tokenizeShopQueryCandidate($shopSearchQuery) as $token) {
|
||||
if (isset($removeTokens[$token]) || isset($kept[$token])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$kept[$token] = $token;
|
||||
}
|
||||
|
||||
$cleaned = implode(' ', array_values($kept));
|
||||
|
||||
return $cleaned !== '' ? $cleaned : $shopSearchQuery;
|
||||
}
|
||||
|
||||
private function filterShopQueryToPositiveTokens(string $shopSearchQuery): string
|
||||
{
|
||||
$shopSearchQuery = trim($shopSearchQuery);
|
||||
@@ -1797,11 +1905,15 @@ final readonly class AgentRunner
|
||||
array $variantPatterns,
|
||||
array $variantTokens
|
||||
): bool {
|
||||
if (!isset($variantTokens[$token]) && !$this->matchesAnyConfiguredShopQueryCodePattern($token, $variantPatterns)) {
|
||||
$isExplicitVariantToken = isset($variantTokens[$token]);
|
||||
$isPatternVariantToken = $this->matchesAnyConfiguredShopQueryCodePattern($token, $variantPatterns);
|
||||
|
||||
if (!$isExplicitVariantToken && !$isPatternVariantToken) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$hasAdjacentNumericContext = false;
|
||||
$hasAdjacentExplicitVariantContext = false;
|
||||
$nearbyKeptContextCount = 0;
|
||||
|
||||
for ($offset = -2; $offset <= 2; ++$offset) {
|
||||
@@ -1822,9 +1934,23 @@ final readonly class AgentRunner
|
||||
if (abs($offset) === 1 && preg_match('/\d/u', $nearbyToken) === 1) {
|
||||
$hasAdjacentNumericContext = true;
|
||||
}
|
||||
|
||||
if (abs($offset) === 1 && isset($variantTokens[$nearbyToken])) {
|
||||
$hasAdjacentExplicitVariantContext = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $hasAdjacentNumericContext && $nearbyKeptContextCount >= 2;
|
||||
if ($hasAdjacentNumericContext && $nearbyKeptContextCount >= 2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Preserve compact all-alpha model/acronym chains such as
|
||||
// "Testomat LAB CL" without allowing arbitrary descriptive words to
|
||||
// pass the positive token filter. The non-numeric path therefore uses
|
||||
// only explicitly configured neighbouring variant terms from YAML.
|
||||
return $isExplicitVariantToken
|
||||
&& $hasAdjacentExplicitVariantContext
|
||||
&& $nearbyKeptContextCount >= 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1855,6 +1981,11 @@ final readonly class AgentRunner
|
||||
);
|
||||
}
|
||||
|
||||
$terms = $this->mergeUniqueStrings(
|
||||
$terms,
|
||||
$this->agentRunnerConfig->getGenericDeviceQueryAnchorPositiveFilterTerms()
|
||||
);
|
||||
|
||||
$tokens = [];
|
||||
foreach ($terms as $term) {
|
||||
foreach ($this->tokenizeShopQueryCandidate($term) as $token) {
|
||||
|
||||
Reference in New Issue
Block a user