fix p45
This commit is contained in:
@@ -212,6 +212,13 @@ parameters:
|
|||||||
vocabulary_maps:
|
vocabulary_maps:
|
||||||
synonyms: agent.rag_evidence_guard.synonyms
|
synonyms: agent.rag_evidence_guard.synonyms
|
||||||
|
|
||||||
|
direct_shop_result_answer:
|
||||||
|
enabled: true
|
||||||
|
max_results: 10
|
||||||
|
intro: 'Aus den Shopdaten ergeben sich folgende passende Treffer:'
|
||||||
|
no_results: 'Ich finde in den Shopdaten keine passenden Treffer für die angefragte Produktsuche. Ich liste deshalb keine fachfremden Ersatzprodukte auf.'
|
||||||
|
sorted_by_length_note: 'Sortierung: aufsteigend nach erkannter Kabellänge.'
|
||||||
|
|
||||||
no_llm_fallback:
|
no_llm_fallback:
|
||||||
max_shop_results: 5
|
max_shop_results: 5
|
||||||
messages:
|
messages:
|
||||||
@@ -440,6 +447,66 @@ parameters:
|
|||||||
comparative_constraint_patterns:
|
comparative_constraint_patterns:
|
||||||
- '/\b(?:länger|laenger|kürzer|kuerzer|größer|groesser|kleiner|über|ueber|unter|mindestens|maximal|maximum|minimum|ab|bis|mehr\s+als|weniger\s+als)\s+(?P<value>\d+(?:[,.]\d+)?\s*[\p{L}µ°%]*)\b/iu'
|
- '/\b(?:länger|laenger|kürzer|kuerzer|größer|groesser|kleiner|über|ueber|unter|mindestens|maximal|maximum|minimum|ab|bis|mehr\s+als|weniger\s+als)\s+(?P<value>\d+(?:[,.]\d+)?\s*[\p{L}µ°%]*)\b/iu'
|
||||||
|
|
||||||
|
query_stopword_cleanup:
|
||||||
|
enabled: true
|
||||||
|
min_query_tokens_after_cleanup: 2
|
||||||
|
# Plain Shopware text search should contain product-relevant terms only.
|
||||||
|
# These terms are UI, instruction, presentation or sorting words and are
|
||||||
|
# removed after LLM query optimization. Keep this list simple and local.
|
||||||
|
terms:
|
||||||
|
- zeige
|
||||||
|
- zeig
|
||||||
|
- suche
|
||||||
|
- such
|
||||||
|
- finde
|
||||||
|
- find
|
||||||
|
- gib
|
||||||
|
- gebe
|
||||||
|
- nenne
|
||||||
|
- mir
|
||||||
|
- bitte
|
||||||
|
- ich
|
||||||
|
- wir
|
||||||
|
- im
|
||||||
|
- in
|
||||||
|
- shop
|
||||||
|
- für
|
||||||
|
- fuer
|
||||||
|
- nach
|
||||||
|
- mit
|
||||||
|
- ohne
|
||||||
|
- von
|
||||||
|
- zum
|
||||||
|
- zur
|
||||||
|
- der
|
||||||
|
- die
|
||||||
|
- das
|
||||||
|
- ein
|
||||||
|
- eine
|
||||||
|
- einen
|
||||||
|
- ordne
|
||||||
|
- sortiere
|
||||||
|
- sortiert
|
||||||
|
- sortierung
|
||||||
|
- liste
|
||||||
|
- tabelle
|
||||||
|
- übersicht
|
||||||
|
- uebersicht
|
||||||
|
- auflistung
|
||||||
|
- meter
|
||||||
|
- metern
|
||||||
|
|
||||||
|
direct_result_guard:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
length_sort:
|
||||||
|
enabled: true
|
||||||
|
trigger_patterns:
|
||||||
|
- '/\b(?:ordne|sortiere|sortiert|sortierung)\b.{0,80}\b(?:meter|metern|m)\b/iu'
|
||||||
|
- '/\bnach\s+(?:meter|metern|m)\b/iu'
|
||||||
|
value_patterns:
|
||||||
|
- '/(?P<value>\d+(?:[,.]\d+)?)\s*(?:m|meter|metern)\b/iu'
|
||||||
|
|
||||||
context_usage:
|
context_usage:
|
||||||
referential_terms:
|
referential_terms:
|
||||||
- der
|
- der
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ a {
|
|||||||
color: #7a9ed1;
|
color: #7a9ed1;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
li {
|
||||||
|
margin-bottom: .5rem;
|
||||||
|
}
|
||||||
a:hover {
|
a:hover {
|
||||||
color: #FFF;
|
color: #FFF;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -467,6 +467,8 @@ final readonly class AgentRunner
|
|||||||
}
|
}
|
||||||
|
|
||||||
$shopResults = $repairPayload['results'];
|
$shopResults = $repairPayload['results'];
|
||||||
|
$shopResults = $this->guardDirectProductShopResults($prompt, $shopSearchQuery, $shopResults);
|
||||||
|
$shopResults = $this->sortShopResultsForLengthRequest($prompt, $shopSearchQuery, $shopResults);
|
||||||
$attemptedShopRepair = $repairPayload['attemptedRepair'];
|
$attemptedShopRepair = $repairPayload['attemptedRepair'];
|
||||||
$usedShopRepair = $repairPayload['usedRepair'];
|
$usedShopRepair = $repairPayload['usedRepair'];
|
||||||
$shopRepairQueries = $repairPayload['repairQueries'];
|
$shopRepairQueries = $repairPayload['repairQueries'];
|
||||||
@@ -604,7 +606,21 @@ final readonly class AgentRunner
|
|||||||
knowledgeEvidenceState: $knowledgeEvidenceState
|
knowledgeEvidenceState: $knowledgeEvidenceState
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$deterministicDirectShopAnswer = $this->buildDeterministicDirectShopResultAnswer(
|
||||||
|
prompt: $prompt,
|
||||||
|
shopResults: $shopResults,
|
||||||
|
commerceIntent: $commerceIntent,
|
||||||
|
shopSearchAttempted: $shopSearchAttempted,
|
||||||
|
shopSearchHadSystemFailure: $primaryShopSearchHadSystemFailure,
|
||||||
|
shopSearchQuery: $shopSearchQuery
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($deterministicDirectShopAnswer !== '') {
|
||||||
|
$fullOutput = $deterministicDirectShopAnswer;
|
||||||
|
yield $this->systemMsg($deterministicDirectShopAnswer, 'answer');
|
||||||
|
} else {
|
||||||
$fullOutput = yield from $this->streamFinalAnswer($finalPrompt, $noLlmFallbackAnswer);
|
$fullOutput = yield from $this->streamFinalAnswer($finalPrompt, $noLlmFallbackAnswer);
|
||||||
|
}
|
||||||
|
|
||||||
yield $this->systemMsg(
|
yield $this->systemMsg(
|
||||||
$this->buildProductionUiMetaMessage(
|
$this->buildProductionUiMetaMessage(
|
||||||
@@ -1565,7 +1581,49 @@ final readonly class AgentRunner
|
|||||||
? $this->preserveCurrentInputShopQueryTerms($prompt, $guardedQuery)
|
? $this->preserveCurrentInputShopQueryTerms($prompt, $guardedQuery)
|
||||||
: $this->preserveCurrentInputShopQueryTerms($prompt, $shopSearchQuery);
|
: $this->preserveCurrentInputShopQueryTerms($prompt, $shopSearchQuery);
|
||||||
|
|
||||||
return $this->cleanupDirectProductAttributeShopQuery($prompt, $query);
|
$query = $this->cleanupDirectProductAttributeShopQuery($prompt, $query);
|
||||||
|
|
||||||
|
return $this->cleanupShopQueryStopwords($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function cleanupShopQueryStopwords(string $shopSearchQuery): string
|
||||||
|
{
|
||||||
|
$shopSearchQuery = trim($shopSearchQuery);
|
||||||
|
|
||||||
|
if (
|
||||||
|
$shopSearchQuery === ''
|
||||||
|
|| !$this->agentRunnerConfig->isShopQueryStopwordCleanupEnabled()
|
||||||
|
) {
|
||||||
|
return $shopSearchQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
$removeTokens = [];
|
||||||
|
foreach ($this->agentRunnerConfig->getShopQueryStopwordCleanupTerms() as $term) {
|
||||||
|
foreach ($this->tokenizeShopQueryCandidate($term) as $token) {
|
||||||
|
$removeTokens[$token] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($removeTokens === []) {
|
||||||
|
return $shopSearchQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
$kept = [];
|
||||||
|
foreach ($this->tokenizeShopQueryCandidate($shopSearchQuery) as $token) {
|
||||||
|
if (isset($removeTokens[$token]) || isset($kept[$token])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$kept[$token] = $token;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($kept) < max(1, $this->agentRunnerConfig->getShopQueryStopwordCleanupMinTokens())) {
|
||||||
|
return $shopSearchQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cleaned = implode(' ', array_values($kept));
|
||||||
|
|
||||||
|
return $cleaned !== '' ? $cleaned : $shopSearchQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function cleanupDirectProductAttributeShopQuery(string $prompt, string $shopSearchQuery): string
|
private function cleanupDirectProductAttributeShopQuery(string $prompt, string $shopSearchQuery): string
|
||||||
@@ -2883,6 +2941,269 @@ final readonly class AgentRunner
|
|||||||
return mb_strtolower($line, 'UTF-8');
|
return mb_strtolower($line, 'UTF-8');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ShopProductResult[] $shopResults
|
||||||
|
* @return ShopProductResult[]
|
||||||
|
*/
|
||||||
|
private function guardDirectProductShopResults(string $prompt, string $shopSearchQuery, array $shopResults): array
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
$shopResults === []
|
||||||
|
|| !$this->agentRunnerConfig->isDirectShopResultGuardEnabled()
|
||||||
|
) {
|
||||||
|
return $shopResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
$requestedTerms = $this->extractRequestedDirectProductTerms($prompt, $shopSearchQuery);
|
||||||
|
if ($requestedTerms === []) {
|
||||||
|
return $shopResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
$filtered = [];
|
||||||
|
foreach ($shopResults as $product) {
|
||||||
|
if (!$product instanceof ShopProductResult) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->shopProductMatchesAnyDirectProductTerm($product, $requestedTerms)) {
|
||||||
|
$filtered[] = $product;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ShopProductResult[] $shopResults
|
||||||
|
* @return ShopProductResult[]
|
||||||
|
*/
|
||||||
|
private function sortShopResultsForLengthRequest(string $prompt, string $shopSearchQuery, array $shopResults): array
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
count($shopResults) < 2
|
||||||
|
|| !$this->agentRunnerConfig->isShopResultLengthSortEnabled()
|
||||||
|
|| !$this->isShopResultLengthSortRequested($prompt . ' ' . $shopSearchQuery)
|
||||||
|
) {
|
||||||
|
return $shopResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
$hasLength = false;
|
||||||
|
$decorated = [];
|
||||||
|
|
||||||
|
foreach (array_values($shopResults) as $index => $product) {
|
||||||
|
$length = $product instanceof ShopProductResult
|
||||||
|
? $this->extractShopProductLengthMeters($product)
|
||||||
|
: null;
|
||||||
|
$hasLength = $hasLength || $length !== null;
|
||||||
|
$decorated[] = [
|
||||||
|
'index' => $index,
|
||||||
|
'length' => $length,
|
||||||
|
'product' => $product,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$hasLength) {
|
||||||
|
return $shopResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
usort($decorated, static function (array $a, array $b): int {
|
||||||
|
if ($a['length'] === null && $b['length'] === null) {
|
||||||
|
return $a['index'] <=> $b['index'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($a['length'] === null) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($b['length'] === null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$lengthCompare = $a['length'] <=> $b['length'];
|
||||||
|
|
||||||
|
return $lengthCompare !== 0 ? $lengthCompare : ($a['index'] <=> $b['index']);
|
||||||
|
});
|
||||||
|
|
||||||
|
return array_values(array_map(
|
||||||
|
static fn(array $row): mixed => $row['product'],
|
||||||
|
$decorated
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function isShopResultLengthSortRequested(string $text): bool
|
||||||
|
{
|
||||||
|
foreach ($this->agentRunnerConfig->getShopResultLengthSortTriggerPatterns() as $pattern) {
|
||||||
|
if (@preg_match($pattern, $text) === 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function extractShopProductLengthMeters(ShopProductResult $product): ?float
|
||||||
|
{
|
||||||
|
$text = trim(implode(' ', array_filter([
|
||||||
|
$product->name,
|
||||||
|
$product->description,
|
||||||
|
implode(' ', $product->highlights),
|
||||||
|
$product->customFields,
|
||||||
|
])));
|
||||||
|
|
||||||
|
if ($text === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->agentRunnerConfig->getShopResultLengthSortValuePatterns() as $pattern) {
|
||||||
|
if (@preg_match($pattern, $text, $matches) !== 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$value = $matches['value'] ?? ($matches[1] ?? null);
|
||||||
|
if (!is_scalar($value)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$normalized = str_replace(',', '.', (string) $value);
|
||||||
|
if (is_numeric($normalized)) {
|
||||||
|
return (float) $normalized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
private function extractRequestedDirectProductTerms(string $prompt, string $shopSearchQuery = ''): array
|
||||||
|
{
|
||||||
|
$combined = trim($prompt . ' ' . $shopSearchQuery);
|
||||||
|
if ($combined === '') {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$terms = [];
|
||||||
|
foreach ($this->agentRunnerConfig->getShopQueryProductAttributeCleanupProductTypeTerms() as $term) {
|
||||||
|
if ($this->containsAllShopQueryTokens($combined, $term)) {
|
||||||
|
$terms[] = $term;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_values(array_unique($terms));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function containsAllShopQueryTokens(string $text, string $term): bool
|
||||||
|
{
|
||||||
|
$tokens = array_fill_keys($this->tokenizeShopQueryCandidate($text), true);
|
||||||
|
$termTokens = $this->tokenizeShopQueryCandidate($term);
|
||||||
|
|
||||||
|
if ($tokens === [] || $termTokens === []) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($termTokens as $termToken) {
|
||||||
|
if (!isset($tokens[$termToken])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string[] $requestedTerms
|
||||||
|
*/
|
||||||
|
private function shopProductMatchesAnyDirectProductTerm(ShopProductResult $product, array $requestedTerms): bool
|
||||||
|
{
|
||||||
|
$productText = trim(implode(' ', array_filter([
|
||||||
|
$product->name,
|
||||||
|
$product->description,
|
||||||
|
implode(' ', $product->highlights),
|
||||||
|
$product->customFields,
|
||||||
|
])));
|
||||||
|
|
||||||
|
foreach ($requestedTerms as $term) {
|
||||||
|
if ($this->containsAllShopQueryTokens($productText, $term)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ShopProductResult[] $shopResults
|
||||||
|
*/
|
||||||
|
private function buildDeterministicDirectShopResultAnswer(
|
||||||
|
string $prompt,
|
||||||
|
array $shopResults,
|
||||||
|
string $commerceIntent,
|
||||||
|
bool $shopSearchAttempted,
|
||||||
|
bool $shopSearchHadSystemFailure,
|
||||||
|
string $shopSearchQuery
|
||||||
|
): string {
|
||||||
|
if (
|
||||||
|
!$this->agentRunnerConfig->isDirectShopResultAnswerEnabled()
|
||||||
|
|| !$this->isCommerceIntent($commerceIntent)
|
||||||
|
|| !$shopSearchAttempted
|
||||||
|
|| $shopSearchHadSystemFailure
|
||||||
|
|| $this->extractRequestedDirectProductTerms($prompt, $shopSearchQuery) === []
|
||||||
|
) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($shopResults === []) {
|
||||||
|
return $this->agentRunnerConfig->getDirectShopResultAnswerNoResultsMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
$lines = [$this->agentRunnerConfig->getDirectShopResultAnswerIntro()];
|
||||||
|
|
||||||
|
if ($this->isShopResultLengthSortRequested($prompt . ' ' . $shopSearchQuery)) {
|
||||||
|
$note = trim($this->agentRunnerConfig->getDirectShopResultAnswerSortedByLengthNote());
|
||||||
|
if ($note !== '') {
|
||||||
|
$lines[] = $note;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$lines[] = '';
|
||||||
|
foreach ($this->buildDirectShopProductLines($shopResults, 'accessory_or_consumable') as $line) {
|
||||||
|
$lines[] = $line;
|
||||||
|
}
|
||||||
|
|
||||||
|
return trim(implode("\n", $lines));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ShopProductResult[] $shopResults
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
private function buildDirectShopProductLines(array $shopResults, string $requestedProductRole): array
|
||||||
|
{
|
||||||
|
$maxResults = max(1, $this->agentRunnerConfig->getDirectShopResultAnswerMaxResults());
|
||||||
|
$lines = [];
|
||||||
|
$index = 1;
|
||||||
|
|
||||||
|
foreach ($shopResults as $product) {
|
||||||
|
if (!$product instanceof ShopProductResult) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$lines[] = $this->formatNoLlmShopProductLine($product, $index, $requestedProductRole);
|
||||||
|
$index++;
|
||||||
|
|
||||||
|
if (count($lines) >= $maxResults) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($lines === []) {
|
||||||
|
return [$this->agentRunnerConfig->getNoLlmProductField('unreadable_results_message')];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $lines;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a deterministic safety answer for environments where the LLM returns no tokens.
|
* Build a deterministic safety answer for environments where the LLM returns no tokens.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -732,6 +732,31 @@ final class AgentRunnerConfig
|
|||||||
return $this->getRequiredStringList('final_answer_guard.repeated_line.ignore_patterns');
|
return $this->getRequiredStringList('final_answer_guard.repeated_line.ignore_patterns');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isDirectShopResultAnswerEnabled(): bool
|
||||||
|
{
|
||||||
|
return $this->getRequiredBool('direct_shop_result_answer.enabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDirectShopResultAnswerMaxResults(): int
|
||||||
|
{
|
||||||
|
return $this->getRequiredInt('direct_shop_result_answer.max_results');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDirectShopResultAnswerIntro(): string
|
||||||
|
{
|
||||||
|
return $this->getRequiredString('direct_shop_result_answer.intro');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDirectShopResultAnswerNoResultsMessage(): string
|
||||||
|
{
|
||||||
|
return $this->getRequiredString('direct_shop_result_answer.no_results');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDirectShopResultAnswerSortedByLengthNote(): string
|
||||||
|
{
|
||||||
|
return $this->getRequiredString('direct_shop_result_answer.sorted_by_length_note');
|
||||||
|
}
|
||||||
|
|
||||||
public function getNoLlmFallbackMaxShopResults(): int
|
public function getNoLlmFallbackMaxShopResults(): int
|
||||||
{
|
{
|
||||||
return $this->getRequiredInt('no_llm_fallback.max_shop_results');
|
return $this->getRequiredInt('no_llm_fallback.max_shop_results');
|
||||||
@@ -1082,6 +1107,50 @@ final class AgentRunnerConfig
|
|||||||
return $this->getRequiredStringList('shop_prompt.product_attribute_query_cleanup.comparative_constraint_patterns');
|
return $this->getRequiredStringList('shop_prompt.product_attribute_query_cleanup.comparative_constraint_patterns');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isShopQueryStopwordCleanupEnabled(): bool
|
||||||
|
{
|
||||||
|
return $this->getRequiredBool('shop_prompt.query_stopword_cleanup.enabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getShopQueryStopwordCleanupMinTokens(): int
|
||||||
|
{
|
||||||
|
return $this->getRequiredInt('shop_prompt.query_stopword_cleanup.min_query_tokens_after_cleanup');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getShopQueryStopwordCleanupTerms(): array
|
||||||
|
{
|
||||||
|
return $this->getRequiredStringList('shop_prompt.query_stopword_cleanup.terms');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isDirectShopResultGuardEnabled(): bool
|
||||||
|
{
|
||||||
|
return $this->getRequiredBool('shop_prompt.direct_result_guard.enabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isShopResultLengthSortEnabled(): bool
|
||||||
|
{
|
||||||
|
return $this->getRequiredBool('shop_prompt.length_sort.enabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getShopResultLengthSortTriggerPatterns(): array
|
||||||
|
{
|
||||||
|
return $this->getRequiredStringList('shop_prompt.length_sort.trigger_patterns');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getShopResultLengthSortValuePatterns(): array
|
||||||
|
{
|
||||||
|
return $this->getRequiredStringList('shop_prompt.length_sort.value_patterns');
|
||||||
|
}
|
||||||
|
|
||||||
public function getShopPromptIntro(): string
|
public function getShopPromptIntro(): string
|
||||||
{
|
{
|
||||||
return $this->getRequiredString('shop_prompt.intro');
|
return $this->getRequiredString('shop_prompt.intro');
|
||||||
|
|||||||
Reference in New Issue
Block a user