patch 8
This commit is contained in:
23
RETRIEX_PATCH_8_COMMERCE_INTENT_YAML_ONLY_README.md
Normal file
23
RETRIEX_PATCH_8_COMMERCE_INTENT_YAML_ONLY_README.md
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# RetrieX Patch 8 - CommerceIntentConfig YAML-only
|
||||||
|
|
||||||
|
Scope:
|
||||||
|
- Move `CommerceIntentConfig` lists, regex patterns, labels, and score thresholds to YAML-only access.
|
||||||
|
- Keep `CommerceQueryParser`, `ShopService`, `PromptBuilder`, Retrieval, SSE, and frontend unchanged.
|
||||||
|
|
||||||
|
Changed files:
|
||||||
|
- `config/retriex/intent.yaml`
|
||||||
|
- `src/Config/CommerceIntentConfig.php`
|
||||||
|
- `src/Config/RetriexEffectiveConfigProvider.php`
|
||||||
|
|
||||||
|
After applying, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
php bin/console cache:clear
|
||||||
|
php bin/console mto:agent:config:validate
|
||||||
|
php bin/console mto:agent:config:audit-source --details
|
||||||
|
php bin/console mto:agent:regression:test
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected:
|
||||||
|
- `CommerceIntentConfig` fallback accessors disappear from the source audit.
|
||||||
|
- Regression baseline remains green.
|
||||||
@@ -132,6 +132,36 @@ parameters:
|
|||||||
- '/\bzubehör\b/u'
|
- '/\bzubehör\b/u'
|
||||||
- '/\bzubehoer\b/u'
|
- '/\bzubehoer\b/u'
|
||||||
- '/\bersatzteil(?:e)?\b/u'
|
- '/\bersatzteil(?:e)?\b/u'
|
||||||
|
patterns:
|
||||||
|
sku_like: '/\b\d{4,10}\b/u'
|
||||||
|
price_value_template: '/\b\d+(?:[.,]\d+)?\s*(?:{price_pattern})\b/u'
|
||||||
|
size_extraction_template: '/\b(?:{size_pattern})\s*([a-z0-9.-]+)\b/u'
|
||||||
|
size_value_template: '/\b(?:{size_pattern})\s*[a-z0-9.-]+\b/u'
|
||||||
|
size_token_value_template: '/\b(?:{size_token_pattern})\b/u'
|
||||||
|
color_value_template: '/\b(?:{color_pattern})\b/u'
|
||||||
|
model_like_product: '/\b[a-zäöüß][a-zäöüß®\-]*(?:\s+[a-zäöüß][a-zäöüß®\-]*){0,2}\s+\d{2,5}[a-z0-9\-]*\b/u'
|
||||||
|
labels:
|
||||||
|
support_or_diagnostic_signal: support_or_diagnostic
|
||||||
|
sku_signal: sku
|
||||||
|
price_signal: price
|
||||||
|
size_signal: size
|
||||||
|
size_token_signal: size_token
|
||||||
|
color_signal: color
|
||||||
|
advisory_signal_prefix: 'advisory:'
|
||||||
|
advisory_product_selection_signal: advisory_product_selection
|
||||||
|
model_like_product_signal: model_like_product
|
||||||
|
scores:
|
||||||
|
product_search_min_score: 3
|
||||||
|
advisory_product_search_min_score: 2
|
||||||
|
strong_signal_score: 3
|
||||||
|
sku_signal_score: 2
|
||||||
|
price_signal_score: 2
|
||||||
|
size_signal_score: 2
|
||||||
|
size_token_signal_score: 1
|
||||||
|
color_signal_score: 1
|
||||||
|
advisory_signal_score: 1
|
||||||
|
advisory_product_selection_signal_score: 3
|
||||||
|
model_like_product_signal_score: 3
|
||||||
|
|
||||||
retriex.intent.catalog.config:
|
retriex.intent.catalog.config:
|
||||||
min_score: 0.72
|
min_score: 0.72
|
||||||
|
|||||||
@@ -6,153 +6,6 @@ namespace App\Config;
|
|||||||
|
|
||||||
final class CommerceIntentConfig
|
final class CommerceIntentConfig
|
||||||
{
|
{
|
||||||
private const STRONG_SIGNALS = [
|
|
||||||
'shop',
|
|
||||||
'alle',
|
|
||||||
'preis',
|
|
||||||
'kunde',
|
|
||||||
'online',
|
|
||||||
'produkt',
|
|
||||||
'artikel',
|
|
||||||
'sku',
|
|
||||||
'kaufen',
|
|
||||||
'kostet',
|
|
||||||
'suche',
|
|
||||||
'such',
|
|
||||||
'finde',
|
|
||||||
'finden',
|
|
||||||
'analysegerät',
|
|
||||||
'analysegeraet',
|
|
||||||
'messgerät',
|
|
||||||
'messgeraet',
|
|
||||||
'pockettester',
|
|
||||||
'pocket tester',
|
|
||||||
'handmessgerät',
|
|
||||||
'handmessgeraet',
|
|
||||||
'analysator',
|
|
||||||
'analyzer',
|
|
||||||
'puffer',
|
|
||||||
'kalibrierpuffer',
|
|
||||||
'kalibrierlösung',
|
|
||||||
'kalibrierloesung',
|
|
||||||
'kalibrierung',
|
|
||||||
'chemie',
|
|
||||||
'reagenz',
|
|
||||||
'reagenzien',
|
|
||||||
'verbrauchsmaterial',
|
|
||||||
'zubehör',
|
|
||||||
'zubehoer',
|
|
||||||
'ersatzteil',
|
|
||||||
];
|
|
||||||
|
|
||||||
private const ADVISORY_SIGNALS = [
|
|
||||||
'passt',
|
|
||||||
'eignet',
|
|
||||||
'besser',
|
|
||||||
'besten',
|
|
||||||
'gut',
|
|
||||||
'gut für',
|
|
||||||
'gut fuer',
|
|
||||||
'passend für',
|
|
||||||
'passend fuer',
|
|
||||||
'geeignet',
|
|
||||||
'geeigent',
|
|
||||||
'empfiehl',
|
|
||||||
'empfehl',
|
|
||||||
];
|
|
||||||
|
|
||||||
private const ADVISORY_PRODUCT_SELECTION_PATTERNS = [
|
|
||||||
'/\bmit\s+welche(?:m|n|r|s)?\s+(?:testomat(?:en)?|pockettester|pocket\s+tester|analysegerät|analysegeraet|messgerät|messgeraet|analysator|analyzer)\b.*\b(?:messen|messung|überwach(?:en|ung)?|ueberwach(?:en|ung)?)\b/u',
|
|
||||||
'/\bwelche(?:r|s|n|m)?\s+(?:testomat(?:en)?|pockettester|pocket\s+tester|analysegerät|analysegeraet|messgerät|messgeraet|analysator|analyzer)\b.*\b(?:kann|können|koennen|misst|messen|überwacht|ueberwacht|eignet|geeignet|passt|gut|empfehl)\b.*\b(?:messen|messung|überwach(?:en|ung)?|ueberwach(?:en|ung)?)\b/u',
|
|
||||||
'/\b(?:testomat(?:en)?|pockettester|pocket\s+tester|analysegerät|analysegeraet|messgerät|messgeraet|analysator|analyzer)\b.*\b(?:für|fuer)\b.*\b(?:messung|messen|überwachung|ueberwachung)\b/u',
|
|
||||||
];
|
|
||||||
|
|
||||||
private const PRICE_TERMS = [
|
|
||||||
'euro',
|
|
||||||
'€',
|
|
||||||
'eur',
|
|
||||||
'teuer',
|
|
||||||
'preis',
|
|
||||||
'kosten',
|
|
||||||
'kostet',
|
|
||||||
];
|
|
||||||
|
|
||||||
private const COLOR_TERMS = [
|
|
||||||
'schwarz',
|
|
||||||
'weiß',
|
|
||||||
'weis',
|
|
||||||
'blau',
|
|
||||||
'grau',
|
|
||||||
'beige',
|
|
||||||
'rosa',
|
|
||||||
'pink',
|
|
||||||
'gruen',
|
|
||||||
'orange',
|
|
||||||
'braun',
|
|
||||||
];
|
|
||||||
|
|
||||||
private const SIZE_TOKEN_TERMS = [
|
|
||||||
'xs',
|
|
||||||
's',
|
|
||||||
'm',
|
|
||||||
'l',
|
|
||||||
'xl',
|
|
||||||
'xxl',
|
|
||||||
'xxxxl',
|
|
||||||
];
|
|
||||||
|
|
||||||
private const SIZE_TERMS = [
|
|
||||||
'größe',
|
|
||||||
'groesse',
|
|
||||||
'grösse',
|
|
||||||
];
|
|
||||||
|
|
||||||
private const SUPPORT_DIAGNOSTIC_PATTERNS = [
|
|
||||||
'/\bfehler\b/u',
|
|
||||||
'/\bfehlercode\b/u',
|
|
||||||
'/\berror\b/u',
|
|
||||||
'/\bstörung\b/u',
|
|
||||||
'/\bstoerung\b/u',
|
|
||||||
'/\balarm\b/u',
|
|
||||||
'/\bstörungsmeldung\b/u',
|
|
||||||
'/\bstoerungsmeldung\b/u',
|
|
||||||
'/\bmeldung\b/u',
|
|
||||||
'/\bwarnung\b/u',
|
|
||||||
'/\bwarncode\b/u',
|
|
||||||
'/\bcode\b/u',
|
|
||||||
'/\bwas bedeutet\b/u',
|
|
||||||
'/\bwarum\b/u',
|
|
||||||
'/\bblinkt\b/u',
|
|
||||||
'/\bzeigt\b/u',
|
|
||||||
'/\bzeigt an\b/u',
|
|
||||||
'/\bursache\b/u',
|
|
||||||
'/\bdiagnose\b/u',
|
|
||||||
'/\bservicefall\b/u',
|
|
||||||
'/\bproblem\b/u',
|
|
||||||
'/\bstörung beheben\b/u',
|
|
||||||
'/\bstoerung beheben\b/u',
|
|
||||||
'/\be\d{1,3}\b/u',
|
|
||||||
];
|
|
||||||
|
|
||||||
private const EXPLICIT_COMMERCE_INTENT_PATTERNS = [
|
|
||||||
'/\bshop\b/u',
|
|
||||||
'/\bpreis\b/u',
|
|
||||||
'/\bkosten\b/u',
|
|
||||||
'/\bkostet\b/u',
|
|
||||||
'/\bkaufen\b/u',
|
|
||||||
'/\bbestellen\b/u',
|
|
||||||
'/\bprodukt\b/u',
|
|
||||||
'/\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',
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<string, mixed> $config
|
* @param array<string, mixed> $config
|
||||||
*/
|
*/
|
||||||
@@ -163,25 +16,25 @@ final class CommerceIntentConfig
|
|||||||
/** @return string[] */
|
/** @return string[] */
|
||||||
public function getStrongSignalsList(): array
|
public function getStrongSignalsList(): array
|
||||||
{
|
{
|
||||||
return $this->stringList('strong_signals', self::STRONG_SIGNALS);
|
return $this->requiredStringList('strong_signals');
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return string[] */
|
/** @return string[] */
|
||||||
public function getAdvisorySignals(): array
|
public function getAdvisorySignals(): array
|
||||||
{
|
{
|
||||||
return $this->stringList('advisory_signals', self::ADVISORY_SIGNALS);
|
return $this->requiredStringList('advisory_signals');
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return string[] */
|
/** @return string[] */
|
||||||
public function getAdvisoryProductSelectionPatterns(): array
|
public function getAdvisoryProductSelectionPatterns(): array
|
||||||
{
|
{
|
||||||
return $this->stringList('advisory_product_selection_patterns', self::ADVISORY_PRODUCT_SELECTION_PATTERNS);
|
return $this->requiredStringList('advisory_product_selection_patterns');
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return string[] */
|
/** @return string[] */
|
||||||
public function getPriceTerms(): array
|
public function getPriceTerms(): array
|
||||||
{
|
{
|
||||||
return $this->stringList('price_terms', self::PRICE_TERMS);
|
return $this->requiredStringList('price_terms');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPricePattern(): string
|
public function getPricePattern(): string
|
||||||
@@ -192,7 +45,7 @@ final class CommerceIntentConfig
|
|||||||
/** @return string[] */
|
/** @return string[] */
|
||||||
public function getColorTerms(): array
|
public function getColorTerms(): array
|
||||||
{
|
{
|
||||||
return $this->stringList('color_terms', self::COLOR_TERMS);
|
return $this->requiredStringList('color_terms');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getColorPattern(): string
|
public function getColorPattern(): string
|
||||||
@@ -203,7 +56,7 @@ final class CommerceIntentConfig
|
|||||||
/** @return string[] */
|
/** @return string[] */
|
||||||
public function getSizeTokenTerms(): array
|
public function getSizeTokenTerms(): array
|
||||||
{
|
{
|
||||||
return $this->stringList('size_token_terms', self::SIZE_TOKEN_TERMS);
|
return $this->requiredStringList('size_token_terms');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSizeTokenPattern(): string
|
public function getSizeTokenPattern(): string
|
||||||
@@ -214,7 +67,7 @@ final class CommerceIntentConfig
|
|||||||
/** @return string[] */
|
/** @return string[] */
|
||||||
public function getSizeTerms(): array
|
public function getSizeTerms(): array
|
||||||
{
|
{
|
||||||
return $this->stringList('size_terms', self::SIZE_TERMS);
|
return $this->requiredStringList('size_terms');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSizePattern(): string
|
public function getSizePattern(): string
|
||||||
@@ -224,157 +77,192 @@ final class CommerceIntentConfig
|
|||||||
|
|
||||||
public function getSizeExtractionPattern(): string
|
public function getSizeExtractionPattern(): string
|
||||||
{
|
{
|
||||||
return '/\b(?:' . $this->getSizePattern() . ')\s*([a-z0-9.-]+)\b/u';
|
return $this->renderPatternTemplate('patterns.size_extraction_template', [
|
||||||
|
'size_pattern' => $this->getSizePattern(),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return string[] */
|
/** @return string[] */
|
||||||
public function getSupportDiagnosticPatterns(): array
|
public function getSupportDiagnosticPatterns(): array
|
||||||
{
|
{
|
||||||
return $this->stringList('support_diagnostic_patterns', self::SUPPORT_DIAGNOSTIC_PATTERNS);
|
return $this->requiredStringList('support_diagnostic_patterns');
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return string[] */
|
/** @return string[] */
|
||||||
public function getExplicitCommerceIntentPatterns(): array
|
public function getExplicitCommerceIntentPatterns(): array
|
||||||
{
|
{
|
||||||
return $this->stringList('explicit_commerce_intent_patterns', self::EXPLICIT_COMMERCE_INTENT_PATTERNS);
|
return $this->requiredStringList('explicit_commerce_intent_patterns');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSkuLikePattern(): string
|
public function getSkuLikePattern(): string
|
||||||
{
|
{
|
||||||
return '/\b\d{4,10}\b/u';
|
return $this->requiredString('patterns.sku_like');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPriceValuePattern(): string
|
public function getPriceValuePattern(): string
|
||||||
{
|
{
|
||||||
return '/\b\d+(?:[.,]\d+)?\s*(?:' . $this->getPricePattern() . ')\b/u';
|
return $this->renderPatternTemplate('patterns.price_value_template', [
|
||||||
|
'price_pattern' => $this->getPricePattern(),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSizeValuePattern(): string
|
public function getSizeValuePattern(): string
|
||||||
{
|
{
|
||||||
return '/\b(?:' . $this->getSizePattern() . ')\s*[a-z0-9.-]+\b/u';
|
return $this->renderPatternTemplate('patterns.size_value_template', [
|
||||||
|
'size_pattern' => $this->getSizePattern(),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSizeTokenValuePattern(): string
|
public function getSizeTokenValuePattern(): string
|
||||||
{
|
{
|
||||||
return '/\b(?:' . $this->getSizeTokenPattern() . ')\b/u';
|
return $this->renderPatternTemplate('patterns.size_token_value_template', [
|
||||||
|
'size_token_pattern' => $this->getSizeTokenPattern(),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getColorValuePattern(): string
|
public function getColorValuePattern(): string
|
||||||
{
|
{
|
||||||
return '/\b(?:' . $this->getColorPattern() . ')\b/u';
|
return $this->renderPatternTemplate('patterns.color_value_template', [
|
||||||
|
'color_pattern' => $this->getColorPattern(),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSupportOrDiagnosticSignalLabel(): string
|
public function getSupportOrDiagnosticSignalLabel(): string
|
||||||
{
|
{
|
||||||
return 'support_or_diagnostic';
|
return $this->requiredString('labels.support_or_diagnostic_signal');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSkuSignalLabel(): string
|
public function getSkuSignalLabel(): string
|
||||||
{
|
{
|
||||||
return 'sku';
|
return $this->requiredString('labels.sku_signal');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPriceSignalLabel(): string
|
public function getPriceSignalLabel(): string
|
||||||
{
|
{
|
||||||
return 'price';
|
return $this->requiredString('labels.price_signal');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSizeSignalLabel(): string
|
public function getSizeSignalLabel(): string
|
||||||
{
|
{
|
||||||
return 'size';
|
return $this->requiredString('labels.size_signal');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSizeTokenSignalLabel(): string
|
public function getSizeTokenSignalLabel(): string
|
||||||
{
|
{
|
||||||
return 'size_token';
|
return $this->requiredString('labels.size_token_signal');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getColorSignalLabel(): string
|
public function getColorSignalLabel(): string
|
||||||
{
|
{
|
||||||
return 'color';
|
return $this->requiredString('labels.color_signal');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAdvisorySignalPrefix(): string
|
public function getAdvisorySignalPrefix(): string
|
||||||
{
|
{
|
||||||
return 'advisory:';
|
return $this->requiredString('labels.advisory_signal_prefix');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAdvisoryProductSelectionSignalLabel(): string
|
public function getAdvisoryProductSelectionSignalLabel(): string
|
||||||
{
|
{
|
||||||
return 'advisory_product_selection';
|
return $this->requiredString('labels.advisory_product_selection_signal');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getProductSearchMinScore(): int
|
public function getProductSearchMinScore(): int
|
||||||
{
|
{
|
||||||
return 3;
|
return $this->requiredInt('scores.product_search_min_score');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAdvisoryProductSearchMinScore(): int
|
public function getAdvisoryProductSearchMinScore(): int
|
||||||
{
|
{
|
||||||
return 2;
|
return $this->requiredInt('scores.advisory_product_search_min_score');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStrongSignalScore(): int
|
public function getStrongSignalScore(): int
|
||||||
{
|
{
|
||||||
return 3;
|
return $this->requiredInt('scores.strong_signal_score');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSkuSignalScore(): int
|
public function getSkuSignalScore(): int
|
||||||
{
|
{
|
||||||
return 2;
|
return $this->requiredInt('scores.sku_signal_score');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPriceSignalScore(): int
|
public function getPriceSignalScore(): int
|
||||||
{
|
{
|
||||||
return 2;
|
return $this->requiredInt('scores.price_signal_score');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSizeSignalScore(): int
|
public function getSizeSignalScore(): int
|
||||||
{
|
{
|
||||||
return 2;
|
return $this->requiredInt('scores.size_signal_score');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSizeTokenSignalScore(): int
|
public function getSizeTokenSignalScore(): int
|
||||||
{
|
{
|
||||||
return 1;
|
return $this->requiredInt('scores.size_token_signal_score');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getColorSignalScore(): int
|
public function getColorSignalScore(): int
|
||||||
{
|
{
|
||||||
return 1;
|
return $this->requiredInt('scores.color_signal_score');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAdvisorySignalScore(): int
|
public function getAdvisorySignalScore(): int
|
||||||
{
|
{
|
||||||
return 1;
|
return $this->requiredInt('scores.advisory_signal_score');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAdvisoryProductSelectionSignalScore(): int
|
public function getAdvisoryProductSelectionSignalScore(): int
|
||||||
{
|
{
|
||||||
return 3;
|
return $this->requiredInt('scores.advisory_product_selection_signal_score');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getModelLikeProductPattern(): string
|
public function getModelLikeProductPattern(): string
|
||||||
{
|
{
|
||||||
return '/\b[a-zäöüß][a-zäöüß®\-]*(?:\s+[a-zäöüß][a-zäöüß®\-]*){0,2}\s+\d{2,5}[a-z0-9\-]*\b/u';
|
return $this->requiredString('patterns.model_like_product');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getModelLikeProductSignalLabel(): string
|
public function getModelLikeProductSignalLabel(): string
|
||||||
{
|
{
|
||||||
return 'model_like_product';
|
return $this->requiredString('labels.model_like_product_signal');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getModelLikeProductSignalScore(): int
|
public function getModelLikeProductSignalScore(): int
|
||||||
{
|
{
|
||||||
return 3;
|
return $this->requiredInt('scores.model_like_product_signal_score');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function requiredInt(string $key): int
|
||||||
|
{
|
||||||
|
$value = $this->getRequiredValue($key);
|
||||||
|
if (!is_int($value)) {
|
||||||
|
throw new \InvalidArgumentException(sprintf('RetrieX commerce intent config key "%s" must be an integer.', $key));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function requiredString(string $key): string
|
||||||
|
{
|
||||||
|
$value = $this->getRequiredValue($key);
|
||||||
|
if (!is_scalar($value)) {
|
||||||
|
throw new \InvalidArgumentException(sprintf('RetrieX commerce intent config key "%s" must be a string.', $key));
|
||||||
|
}
|
||||||
|
|
||||||
|
$value = trim((string) $value);
|
||||||
|
if ($value === '') {
|
||||||
|
throw new \InvalidArgumentException(sprintf('RetrieX commerce intent config key "%s" must not be empty.', $key));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return string[] */
|
/** @return string[] */
|
||||||
private function stringList(string $key, array $default): array
|
private function requiredStringList(string $key): array
|
||||||
{
|
{
|
||||||
$value = $this->config[$key] ?? $default;
|
$value = $this->getRequiredValue($key);
|
||||||
if (!is_array($value)) {
|
if (!is_array($value)) {
|
||||||
return $default;
|
throw new \InvalidArgumentException(sprintf('RetrieX commerce intent config key "%s" must be a list.', $key));
|
||||||
}
|
}
|
||||||
|
|
||||||
$out = [];
|
$out = [];
|
||||||
@@ -391,6 +279,43 @@ final class CommerceIntentConfig
|
|||||||
$out[] = $item;
|
$out[] = $item;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $out !== [] ? $out : $default;
|
if ($out === []) {
|
||||||
|
throw new \InvalidArgumentException(sprintf('RetrieX commerce intent config key "%s" must contain at least one value.', $key));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, string> $replacements
|
||||||
|
*/
|
||||||
|
private function renderPatternTemplate(string $key, array $replacements): string
|
||||||
|
{
|
||||||
|
$template = $this->requiredString($key);
|
||||||
|
$replace = [];
|
||||||
|
foreach ($replacements as $placeholder => $value) {
|
||||||
|
$replace['{' . $placeholder . '}'] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pattern = strtr($template, $replace);
|
||||||
|
if (preg_match('/\{[A-Za-z_][A-Za-z0-9_]*\}/', $pattern) === 1) {
|
||||||
|
throw new \InvalidArgumentException(sprintf('RetrieX commerce intent pattern template "%s" contains unresolved placeholders.', $key));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getRequiredValue(string $key): mixed
|
||||||
|
{
|
||||||
|
$parts = explode('.', $key);
|
||||||
|
$value = $this->config;
|
||||||
|
foreach ($parts as $part) {
|
||||||
|
if (!is_array($value) || !array_key_exists($part, $value)) {
|
||||||
|
throw new \InvalidArgumentException(sprintf('Missing required RetrieX commerce intent config key "%s".', $key));
|
||||||
|
}
|
||||||
|
$value = $value[$part];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -645,12 +645,33 @@ final readonly class RetriexEffectiveConfigProvider
|
|||||||
'commerce' => [
|
'commerce' => [
|
||||||
'strong_signals' => $this->commerceIntentConfig->getStrongSignalsList(),
|
'strong_signals' => $this->commerceIntentConfig->getStrongSignalsList(),
|
||||||
'advisory_signals' => $this->commerceIntentConfig->getAdvisorySignals(),
|
'advisory_signals' => $this->commerceIntentConfig->getAdvisorySignals(),
|
||||||
|
'advisory_product_selection_patterns' => $this->commerceIntentConfig->getAdvisoryProductSelectionPatterns(),
|
||||||
'price_terms' => $this->commerceIntentConfig->getPriceTerms(),
|
'price_terms' => $this->commerceIntentConfig->getPriceTerms(),
|
||||||
'color_terms' => $this->commerceIntentConfig->getColorTerms(),
|
'color_terms' => $this->commerceIntentConfig->getColorTerms(),
|
||||||
'size_token_terms' => $this->commerceIntentConfig->getSizeTokenTerms(),
|
'size_token_terms' => $this->commerceIntentConfig->getSizeTokenTerms(),
|
||||||
'size_terms' => $this->commerceIntentConfig->getSizeTerms(),
|
'size_terms' => $this->commerceIntentConfig->getSizeTerms(),
|
||||||
'support_diagnostic_patterns' => $this->commerceIntentConfig->getSupportDiagnosticPatterns(),
|
'support_diagnostic_patterns' => $this->commerceIntentConfig->getSupportDiagnosticPatterns(),
|
||||||
'explicit_commerce_intent_patterns' => $this->commerceIntentConfig->getExplicitCommerceIntentPatterns(),
|
'explicit_commerce_intent_patterns' => $this->commerceIntentConfig->getExplicitCommerceIntentPatterns(),
|
||||||
|
'patterns' => [
|
||||||
|
'sku_like' => $this->commerceIntentConfig->getSkuLikePattern(),
|
||||||
|
'price_value' => $this->commerceIntentConfig->getPriceValuePattern(),
|
||||||
|
'size_extraction' => $this->commerceIntentConfig->getSizeExtractionPattern(),
|
||||||
|
'size_value' => $this->commerceIntentConfig->getSizeValuePattern(),
|
||||||
|
'size_token_value' => $this->commerceIntentConfig->getSizeTokenValuePattern(),
|
||||||
|
'color_value' => $this->commerceIntentConfig->getColorValuePattern(),
|
||||||
|
'model_like_product' => $this->commerceIntentConfig->getModelLikeProductPattern(),
|
||||||
|
],
|
||||||
|
'labels' => [
|
||||||
|
'support_or_diagnostic_signal' => $this->commerceIntentConfig->getSupportOrDiagnosticSignalLabel(),
|
||||||
|
'sku_signal' => $this->commerceIntentConfig->getSkuSignalLabel(),
|
||||||
|
'price_signal' => $this->commerceIntentConfig->getPriceSignalLabel(),
|
||||||
|
'size_signal' => $this->commerceIntentConfig->getSizeSignalLabel(),
|
||||||
|
'size_token_signal' => $this->commerceIntentConfig->getSizeTokenSignalLabel(),
|
||||||
|
'color_signal' => $this->commerceIntentConfig->getColorSignalLabel(),
|
||||||
|
'advisory_signal_prefix' => $this->commerceIntentConfig->getAdvisorySignalPrefix(),
|
||||||
|
'advisory_product_selection_signal' => $this->commerceIntentConfig->getAdvisoryProductSelectionSignalLabel(),
|
||||||
|
'model_like_product_signal' => $this->commerceIntentConfig->getModelLikeProductSignalLabel(),
|
||||||
|
],
|
||||||
'thresholds' => [
|
'thresholds' => [
|
||||||
'product_search_min_score' => $this->commerceIntentConfig->getProductSearchMinScore(),
|
'product_search_min_score' => $this->commerceIntentConfig->getProductSearchMinScore(),
|
||||||
'advisory_product_search_min_score' => $this->commerceIntentConfig->getAdvisoryProductSearchMinScore(),
|
'advisory_product_search_min_score' => $this->commerceIntentConfig->getAdvisoryProductSearchMinScore(),
|
||||||
@@ -661,6 +682,7 @@ final readonly class RetriexEffectiveConfigProvider
|
|||||||
'size_token_signal_score' => $this->commerceIntentConfig->getSizeTokenSignalScore(),
|
'size_token_signal_score' => $this->commerceIntentConfig->getSizeTokenSignalScore(),
|
||||||
'color_signal_score' => $this->commerceIntentConfig->getColorSignalScore(),
|
'color_signal_score' => $this->commerceIntentConfig->getColorSignalScore(),
|
||||||
'advisory_signal_score' => $this->commerceIntentConfig->getAdvisorySignalScore(),
|
'advisory_signal_score' => $this->commerceIntentConfig->getAdvisorySignalScore(),
|
||||||
|
'advisory_product_selection_signal_score' => $this->commerceIntentConfig->getAdvisoryProductSelectionSignalScore(),
|
||||||
'model_like_product_signal_score' => $this->commerceIntentConfig->getModelLikeProductSignalScore(),
|
'model_like_product_signal_score' => $this->commerceIntentConfig->getModelLikeProductSignalScore(),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@@ -681,7 +703,6 @@ final readonly class RetriexEffectiveConfigProvider
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return array<string, mixed> */
|
|
||||||
private function languageConfig(): array
|
private function languageConfig(): array
|
||||||
{
|
{
|
||||||
return ['stopwords' => $this->stopWordsConfig->getStopWords()];
|
return ['stopwords' => $this->stopWordsConfig->getStopWords()];
|
||||||
|
|||||||
Reference in New Issue
Block a user