patch 20i

This commit is contained in:
team 1
2026-05-03 10:27:46 +02:00
parent e54d7ecbe7
commit e9070ac96b
5 changed files with 280 additions and 7 deletions

View File

@@ -59,6 +59,7 @@ final readonly class AgentRunner
$optimizedShopQuery = '';
$shopSearchQuery = '';
$commerceHistoryContext = '';
$shopQueryHistoryContext = '';
$attemptedShopRepair = false;
$usedShopRepair = false;
$shopRepairQueries = [];
@@ -212,21 +213,34 @@ final readonly class AgentRunner
yield $this->systemMsg($this->agentRunnerConfig->getOptimizeSearchMessage(), 'think');
$commerceHistoryContext = $this->buildCommerceHistoryContext($userId, $requestContextHint);
$shopQueryHistoryContext = $this->resolveShopQueryHistoryContext(
prompt: $routingPrompt,
commerceHistoryContext: $commerceHistoryContext
);
if ($commerceHistoryContext !== '') {
if ($shopQueryHistoryContext !== '') {
$this->addSource($sources, $this->agentRunnerConfig->getConversationHistorySourceLabel());
}
if ($commerceHistoryContext !== '' && $shopQueryHistoryContext === '') {
$this->agentLogger->info('Ignored commerce history for standalone shop query', [
'userId' => $userId,
'prompt' => $prompt,
'routingPrompt' => $routingPrompt,
'commerceHistoryContextLength' => mb_strlen($commerceHistoryContext),
]);
}
$optimizedShopQuery = yield from $this->buildOptimizedShopQuery(
$routingPrompt,
$userId,
$commerceHistoryContext
$shopQueryHistoryContext
);
$shopSearchQuery = $this->resolveShopSearchQuery(
prompt: $routingPrompt,
optimizedShopQuery: $optimizedShopQuery,
commerceHistoryContext: $commerceHistoryContext,
commerceHistoryContext: $shopQueryHistoryContext,
userId: $userId
);
@@ -279,7 +293,7 @@ final readonly class AgentRunner
$shopQueryPreview = $this->shopSearchService->buildSearchQueryPreview(
$shopSearchQuery,
$commerceIntent,
$commerceHistoryContext
$shopQueryHistoryContext
);
$shopSearchDisplayQuery = $shopQueryPreview->searchText !== ''
@@ -329,7 +343,7 @@ final readonly class AgentRunner
$shopSearchQuery,
$commerceIntent,
$userId,
$commerceHistoryContext
$shopQueryHistoryContext
);
$primaryShopSearchHadSystemFailure = $this->shopSearchService->hadLastSearchSystemFailure();
$primaryShopSearchFailureReason = $this->shopSearchService->getLastSearchFailureReason();
@@ -376,7 +390,7 @@ final readonly class AgentRunner
prompt: $prompt,
userId: $userId,
commerceIntent: $commerceIntent,
commerceHistoryContext: $commerceHistoryContext,
commerceHistoryContext: $shopQueryHistoryContext,
primaryQuery: $shopSearchQuery,
primaryShopResults: $primaryShopResults,
knowledgeChunks: $knowledgeChunks
@@ -1379,6 +1393,102 @@ final readonly class AgentRunner
}
}
private function resolveShopQueryHistoryContext(string $prompt, string $commerceHistoryContext): string
{
$commerceHistoryContext = trim($commerceHistoryContext);
if ($commerceHistoryContext === '') {
return '';
}
if ($this->shouldUseCommerceHistoryForShopQuery($prompt)) {
return $commerceHistoryContext;
}
return '';
}
private function shouldUseCommerceHistoryForShopQuery(string $prompt): bool
{
$prompt = trim($prompt);
if ($prompt === '') {
return false;
}
if ($this->isCommercialTableFollowUpPrompt($prompt)) {
return true;
}
if ($this->isMetaOnlyShopQuery($prompt)) {
return true;
}
if ($this->extractFirstTestomatModelAnchor($prompt) !== '') {
return false;
}
$normalizedPrompt = $this->normalizeFollowUpText($prompt);
if ($this->containsConfiguredShopQueryAnchorTrigger($normalizedPrompt)) {
return !$this->containsNumericShopQueryToken($normalizedPrompt);
}
return $this->containsReferentialShopQueryMarker($normalizedPrompt);
}
private function containsNumericShopQueryToken(string $text): bool
{
return preg_match('/\d/u', $text) === 1;
}
private function containsReferentialShopQueryMarker(string $text): bool
{
$tokens = $this->tokenizeShopQueryCandidate($text);
if ($tokens === []) {
return false;
}
$tokenSet = array_fill_keys($tokens, true);
foreach ($this->agentRunnerConfig->getShopQueryContextUsageReferentialTerms() as $term) {
foreach ($this->tokenizeShopQueryCandidate($term) as $termToken) {
if (isset($tokenSet[$termToken])) {
return true;
}
}
}
return false;
}
private function guardStandaloneOptimizedShopQuery(string $prompt, string $optimizedShopQuery): string
{
if ($this->shouldUseCommerceHistoryForShopQuery($prompt)) {
return $optimizedShopQuery;
}
if ($this->extractFirstTestomatModelAnchor($prompt) === '') {
return $optimizedShopQuery;
}
if (!$this->containsConfiguredShopQueryAnchorTrigger($optimizedShopQuery)) {
return $optimizedShopQuery;
}
if ($this->containsConfiguredShopQueryAnchorTrigger($prompt)) {
return $optimizedShopQuery;
}
$this->agentLogger->info('Ignored optimized shop query because it added an unsupported context anchor', [
'prompt' => $prompt,
'optimizedShopQuery' => $optimizedShopQuery,
]);
return $prompt;
}
private function resolveShopSearchQuery(
string $prompt,
string $optimizedShopQuery,
@@ -1396,7 +1506,7 @@ final readonly class AgentRunner
}
if ($optimizedShopQuery !== '' && !$this->isMetaOnlyShopQuery($optimizedShopQuery)) {
return $optimizedShopQuery;
return $this->guardStandaloneOptimizedShopQuery($prompt, $optimizedShopQuery);
}
if (!$this->isMetaOnlyShopQuery($prompt)) {

View File

@@ -721,6 +721,14 @@ final class AgentRunnerConfig
return $this->getRequiredStringList('shop_prompt.conversation_context_rules');
}
/**
* @return string[]
*/
public function getShopQueryContextUsageReferentialTerms(): array
{
return $this->getRequiredStringList('shop_prompt.context_usage.referential_terms');
}
public function getShopPromptIntro(): string
{
return $this->getRequiredString('shop_prompt.intro');

View File

@@ -529,6 +529,9 @@ final readonly class RetriexEffectiveConfigProvider
'language_markers' => $this->agentRunnerConfig->getShopQueryLanguageMarkers(),
'translation_replacements_de' => $this->agentRunnerConfig->getShopQueryTranslationReplacements('de'),
],
'context_usage' => [
'referential_terms' => $this->agentRunnerConfig->getShopQueryContextUsageReferentialTerms(),
],
'context_anchor_enrichment' => [
'enabled' => $this->agentRunnerConfig->isShopQueryContextAnchorEnrichmentEnabled(),
'max_query_terms' => $this->agentRunnerConfig->getShopQueryContextAnchorEnrichmentMaxQueryTerms(),
@@ -1132,6 +1135,11 @@ final readonly class RetriexEffectiveConfigProvider
$errors[] = 'agent.input_normalization.prompt.current_user_input_label must not be empty.';
}
$contextUsage = $agent['shop_query_optimizer']['context_usage'] ?? [];
if (is_array($contextUsage)) {
$this->validateStringList($this->toList($contextUsage['referential_terms'] ?? []), 'agent.shop_query_optimizer.context_usage.referential_terms', $errors, $warnings);
}
$anchorEnrichment = $agent['shop_query_optimizer']['context_anchor_enrichment'] ?? [];
if (is_array($anchorEnrichment)) {
$this->validateStringList($this->toList($anchorEnrichment['trigger_terms'] ?? []), 'agent.shop_query_optimizer.context_anchor_enrichment.trigger_terms', $errors, $warnings);