patch 20c
This commit is contained in:
61
RETRIEX_PATCH_20C_COMMERCIAL_TABLE_FOLLOWUP_FIX_README.md
Normal file
61
RETRIEX_PATCH_20C_COMMERCIAL_TABLE_FOLLOWUP_FIX_README.md
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
# RetrieX Patch 20c – Commercial Table Follow-up Fix
|
||||||
|
|
||||||
|
## Ziel
|
||||||
|
|
||||||
|
Patch 20c korrigiert eine Regression aus dem p20/p20b-Normalisierungs- und Routing-Umfeld: kurze referenzielle Nachfragen wie `die tabelle mit preisen` müssen den letzten fachlichen Kontext übernehmen und eine Shop-Suche auslösen.
|
||||||
|
|
||||||
|
## Reproduzierter Problemfall
|
||||||
|
|
||||||
|
1. `welche grenzwerte kann der testomat 808 messen`
|
||||||
|
2. RetrieX antwortet korrekt mit Testomat 808 und einer Grenzwert-/Indikatortyp-Tabelle.
|
||||||
|
3. Folgefrage: `die tabelle mit preisen`
|
||||||
|
|
||||||
|
Vor p20c blieb die Folgefrage RAG-only bzw. ohne Shop-Suche. Das ist fachlich zu schwach, weil `die tabelle` klar auf die vorherige Indikatortyp-Tabelle referenziert und `mit preisen` aktuelle Shopdaten verlangt.
|
||||||
|
|
||||||
|
## Lösung
|
||||||
|
|
||||||
|
- LLM-Input-Normalisierung aus p20/p20b bleibt erhalten.
|
||||||
|
- Es gibt eine zusätzliche, YAML-konfigurierbare Erkennung für kommerzielle Tabellen-Follow-ups.
|
||||||
|
- Wenn der normale Commerce-Intent ausfällt, kann ein kurzer Tabellen-/Preis-Follow-up anhand vorhandener History-Anker gezielt zu `product_search` hochgestuft werden.
|
||||||
|
- Für Preis-Tabellen-Follow-ups wird vor einer generischen optimierten Suchquery ein kontextueller Shop-Suchbegriff aus der letzten Antwort abgeleitet.
|
||||||
|
- Beim Testomat-808-/Indikatortyp-Fall ergibt der Fallback generisch `Testomat 808 indikator` statt nur `die tabelle mit preisen` oder `Testomat 808`.
|
||||||
|
- Es werden keine konkreten Tippfehlerlisten eingeführt.
|
||||||
|
|
||||||
|
## Geänderte Dateien
|
||||||
|
|
||||||
|
- `src/Agent/AgentRunner.php`
|
||||||
|
- `src/Config/AgentRunnerConfig.php`
|
||||||
|
- `src/Config/RetriexEffectiveConfigProvider.php`
|
||||||
|
- `config/retriex/agent.yaml`
|
||||||
|
- `config/retriex/intent.yaml`
|
||||||
|
|
||||||
|
## Pflichtchecks
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bin/console mto:agent:config:validate
|
||||||
|
bin/console mto:agent:regression:test
|
||||||
|
bin/console mto:agent:config:audit-source --details
|
||||||
|
bin/console mto:agent:config:audit-patterns --details
|
||||||
|
```
|
||||||
|
|
||||||
|
## Manuelle Regressionen
|
||||||
|
|
||||||
|
1. `was kpstet der indikator`
|
||||||
|
- Erwartung: LLM-/Fuzzy-Normalisierung bleibt wirksam.
|
||||||
|
- Shop-Suche wird ausgelöst.
|
||||||
|
|
||||||
|
2. `ich suche eine preiswerte Lösung zur messung von pH & Chlor für mein schwimmbad`
|
||||||
|
- Erwartung: beratende Shop-/Produktsuche wird ausgelöst.
|
||||||
|
|
||||||
|
3. `welche grenzwerte kann der testomat 808 messen` → `die tabelle mit preisen`
|
||||||
|
- Erwartung: Folgefrage wird als kommerzieller Tabellen-Follow-up erkannt.
|
||||||
|
- Shop-Suche wird ausgelöst.
|
||||||
|
- Gesendete Suchquery sollte sinngemäß `Testomat 808 indikator` sein.
|
||||||
|
- Antwort soll eine Preistabelle der passenden Indikatoren/Zubehörtreffer bilden, soweit Shopdaten vorhanden sind.
|
||||||
|
|
||||||
|
## Nicht geändert
|
||||||
|
|
||||||
|
- Kein Scoring-Umbau.
|
||||||
|
- Keine harte Tippfehlerliste.
|
||||||
|
- Keine Änderung an Retrieval-/Vectorlogik.
|
||||||
|
- Keine Änderung an Shop-Service-Suche selbst.
|
||||||
@@ -59,6 +59,7 @@ parameters:
|
|||||||
- kosten
|
- kosten
|
||||||
- preis
|
- preis
|
||||||
- preise
|
- preise
|
||||||
|
- preisen
|
||||||
- preiswert
|
- preiswert
|
||||||
- preiswerte
|
- preiswerte
|
||||||
- günstig
|
- günstig
|
||||||
@@ -138,6 +139,7 @@ parameters:
|
|||||||
- shop
|
- shop
|
||||||
- preis
|
- preis
|
||||||
- preise
|
- preise
|
||||||
|
- preisen
|
||||||
- kostet
|
- kostet
|
||||||
- kosten
|
- kosten
|
||||||
- kaufen
|
- kaufen
|
||||||
@@ -152,6 +154,20 @@ parameters:
|
|||||||
- artikelnummer
|
- artikelnummer
|
||||||
- sku
|
- sku
|
||||||
- produktnummer
|
- produktnummer
|
||||||
|
|
||||||
|
commercial_table_follow_up:
|
||||||
|
enabled: true
|
||||||
|
prompt_patterns:
|
||||||
|
- '/\b(?:tabelle|tabellarisch|übersicht|uebersicht|liste|auflistung)\b.{0,80}\b(?:preis|preise|preisen|kosten|kostet|shop)\b/u'
|
||||||
|
- '/\b(?:preis|preise|preisen|kosten|kostet|shop)\b.{0,80}\b(?:tabelle|tabellarisch|übersicht|uebersicht|liste|auflistung)\b/u'
|
||||||
|
- '/\b(?:mit|inkl|inklusive|plus)\s+(?:preis|preise|preisen|kosten|shopdaten)\b/u'
|
||||||
|
history_anchor_patterns:
|
||||||
|
- '/\bTestomat(?:®)?\s+\d{3,4}\b/iu'
|
||||||
|
- '/\b(?:Indikatortyp|Indikator|Indikatoren|Reagenz|Reagenzien|Zubehör|Zubehoer)\b/iu'
|
||||||
|
indicator_marker_patterns:
|
||||||
|
- '/\b(?:Indikatortyp|Indikator(?:en)?|indicator(?:\s+type)?|Reagenz(?:ien)?)\b/iu'
|
||||||
|
query_template_with_model: '{model} indikator'
|
||||||
|
query_template_without_model: 'indikator'
|
||||||
history_question_pattern: '/^Question:\s*(.+)$/mi'
|
history_question_pattern: '/^Question:\s*(.+)$/mi'
|
||||||
history_turn_split_pattern: '/(?=^Question:\s)/m'
|
history_turn_split_pattern: '/(?=^Question:\s)/m'
|
||||||
history_question_strip_pattern: '/^Question:\s*.*(?:\R|$)/u'
|
history_question_strip_pattern: '/^Question:\s*.*(?:\R|$)/u'
|
||||||
@@ -416,6 +432,20 @@ parameters:
|
|||||||
context_fallback_max_terms: 6
|
context_fallback_max_terms: 6
|
||||||
context_fallback_filter_terms:
|
context_fallback_filter_terms:
|
||||||
- mit
|
- mit
|
||||||
|
- tabelle
|
||||||
|
- tabellarisch
|
||||||
|
- übersicht
|
||||||
|
- uebersicht
|
||||||
|
- liste
|
||||||
|
- auflistung
|
||||||
|
- preis
|
||||||
|
- preise
|
||||||
|
- preisen
|
||||||
|
- kosten
|
||||||
|
- kostet
|
||||||
|
- grenzwert
|
||||||
|
- grenzwerte
|
||||||
|
- grenzwerten
|
||||||
- welche
|
- welche
|
||||||
- welcher
|
- welcher
|
||||||
- welches
|
- welches
|
||||||
@@ -450,6 +480,18 @@ parameters:
|
|||||||
- gemessen
|
- gemessen
|
||||||
meta_only_terms:
|
meta_only_terms:
|
||||||
- shop
|
- shop
|
||||||
|
- tabelle
|
||||||
|
- tabellarisch
|
||||||
|
- übersicht
|
||||||
|
- uebersicht
|
||||||
|
- liste
|
||||||
|
- auflistung
|
||||||
|
- preis
|
||||||
|
- preise
|
||||||
|
- preisen
|
||||||
|
- kosten
|
||||||
|
- kostet
|
||||||
|
- mit
|
||||||
- shopsuche
|
- shopsuche
|
||||||
- shop-suche
|
- shop-suche
|
||||||
- suche
|
- suche
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ parameters:
|
|||||||
- shop
|
- shop
|
||||||
- alle
|
- alle
|
||||||
- preis
|
- preis
|
||||||
|
- preise
|
||||||
|
- preisen
|
||||||
- kunde
|
- kunde
|
||||||
- online
|
- online
|
||||||
- produkt
|
- produkt
|
||||||
@@ -83,6 +85,8 @@ parameters:
|
|||||||
- eur
|
- eur
|
||||||
- teuer
|
- teuer
|
||||||
- preis
|
- preis
|
||||||
|
- preise
|
||||||
|
- preisen
|
||||||
- kosten
|
- kosten
|
||||||
- kostet
|
- kostet
|
||||||
- preiswert
|
- preiswert
|
||||||
@@ -140,7 +144,7 @@ parameters:
|
|||||||
- '/\be\d{1,3}\b/u'
|
- '/\be\d{1,3}\b/u'
|
||||||
explicit_commerce_intent_patterns:
|
explicit_commerce_intent_patterns:
|
||||||
- '/\bshop\b/u'
|
- '/\bshop\b/u'
|
||||||
- '/\bpreis\b/u'
|
- '/\bpreis(?:e|en)?\b/u'
|
||||||
- '/\bkosten\b/u'
|
- '/\bkosten\b/u'
|
||||||
- '/\bkostet\b/u'
|
- '/\bkostet\b/u'
|
||||||
- '/\bkaufen\b/u'
|
- '/\bkaufen\b/u'
|
||||||
|
|||||||
@@ -107,7 +107,11 @@ final readonly class AgentRunner
|
|||||||
$this->addSource($sources, $this->agentRunnerConfig->getExternalUrlSourceLabel());
|
$this->addSource($sources, $this->agentRunnerConfig->getExternalUrlSourceLabel());
|
||||||
}
|
}
|
||||||
|
|
||||||
$commerceIntent = $this->detectCommerceIntent($routingPrompt);
|
$commerceIntent = $this->detectCommerceIntentForRouting(
|
||||||
|
$routingPrompt,
|
||||||
|
$userId,
|
||||||
|
$requestContextHint
|
||||||
|
);
|
||||||
|
|
||||||
yield $this->systemMsg($this->agentRunnerConfig->getRetrieveKnowledgeMessage(), 'think');
|
yield $this->systemMsg($this->agentRunnerConfig->getRetrieveKnowledgeMessage(), 'think');
|
||||||
|
|
||||||
@@ -933,6 +937,36 @@ final readonly class AgentRunner
|
|||||||
return (string) ($commerceMeta['intent'] ?? CommerceIntentLite::NONE);
|
return (string) ($commerceMeta['intent'] ?? CommerceIntentLite::NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function detectCommerceIntentForRouting(
|
||||||
|
string $prompt,
|
||||||
|
string $userId,
|
||||||
|
string $requestContextHint
|
||||||
|
): string {
|
||||||
|
$commerceIntent = $this->detectCommerceIntent($prompt);
|
||||||
|
|
||||||
|
if ($this->isCommerceIntent($commerceIntent)) {
|
||||||
|
return $commerceIntent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->isCommercialTableFollowUpPrompt($prompt)) {
|
||||||
|
return $commerceIntent;
|
||||||
|
}
|
||||||
|
|
||||||
|
$commerceHistoryContext = $this->buildCommerceHistoryContext($userId, $requestContextHint);
|
||||||
|
|
||||||
|
if (!$this->commercialTableFollowUpHistoryHasAnchor($commerceHistoryContext)) {
|
||||||
|
return $commerceIntent;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->agentLogger->info('Promoted commercial table follow-up to shop intent', [
|
||||||
|
'userId' => $userId,
|
||||||
|
'prompt' => $prompt,
|
||||||
|
'hasRequestContextHint' => trim($requestContextHint) !== '',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return CommerceIntentLite::PRODUCT_SEARCH;
|
||||||
|
}
|
||||||
|
|
||||||
private function isCommerceIntent(string $commerceIntent): bool
|
private function isCommerceIntent(string $commerceIntent): bool
|
||||||
{
|
{
|
||||||
return $commerceIntent === CommerceIntentLite::PRODUCT_SEARCH
|
return $commerceIntent === CommerceIntentLite::PRODUCT_SEARCH
|
||||||
@@ -1265,6 +1299,14 @@ final readonly class AgentRunner
|
|||||||
string $commerceHistoryContext,
|
string $commerceHistoryContext,
|
||||||
string $userId
|
string $userId
|
||||||
): string {
|
): string {
|
||||||
|
if ($this->isCommercialTableFollowUpPrompt($prompt)) {
|
||||||
|
$commercialTableContextQuery = $this->extractCommercialTableFollowUpShopQuery($commerceHistoryContext);
|
||||||
|
|
||||||
|
if ($commercialTableContextQuery !== '' && !$this->isMetaOnlyShopQuery($commercialTableContextQuery)) {
|
||||||
|
return $commercialTableContextQuery;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($optimizedShopQuery !== '' && !$this->isMetaOnlyShopQuery($optimizedShopQuery)) {
|
if ($optimizedShopQuery !== '' && !$this->isMetaOnlyShopQuery($optimizedShopQuery)) {
|
||||||
return $optimizedShopQuery;
|
return $optimizedShopQuery;
|
||||||
}
|
}
|
||||||
@@ -1302,6 +1344,78 @@ final readonly class AgentRunner
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function extractCommercialTableFollowUpShopQuery(string $commerceHistoryContext): string
|
||||||
|
{
|
||||||
|
if (!$this->agentRunnerConfig->isCommercialTableFollowUpEnabled()) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$turn = $this->extractLatestHistoryTurn($commerceHistoryContext);
|
||||||
|
|
||||||
|
if ($turn === '') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->matchesAnyConfiguredPattern(
|
||||||
|
$turn,
|
||||||
|
$this->agentRunnerConfig->getCommercialTableFollowUpIndicatorMarkerPatterns()
|
||||||
|
)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$model = $this->extractFirstTestomatModelAnchor($turn);
|
||||||
|
|
||||||
|
if ($model !== '') {
|
||||||
|
$query = str_replace(
|
||||||
|
'{model}',
|
||||||
|
$model,
|
||||||
|
$this->agentRunnerConfig->getCommercialTableFollowUpQueryTemplateWithModel()
|
||||||
|
);
|
||||||
|
|
||||||
|
return trim((string) preg_replace('/\s+/u', ' ', $query));
|
||||||
|
}
|
||||||
|
|
||||||
|
return trim($this->agentRunnerConfig->getCommercialTableFollowUpQueryTemplateWithoutModel());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function isCommercialTableFollowUpPrompt(string $prompt): bool
|
||||||
|
{
|
||||||
|
if (!$this->agentRunnerConfig->isCommercialTableFollowUpEnabled()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->matchesAnyConfiguredPattern(
|
||||||
|
$this->normalizeFollowUpText($prompt),
|
||||||
|
$this->agentRunnerConfig->getCommercialTableFollowUpPromptPatterns()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function commercialTableFollowUpHistoryHasAnchor(string $commerceHistoryContext): bool
|
||||||
|
{
|
||||||
|
if (trim($commerceHistoryContext) === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->matchesAnyConfiguredPattern(
|
||||||
|
$commerceHistoryContext,
|
||||||
|
$this->agentRunnerConfig->getCommercialTableFollowUpHistoryAnchorPatterns()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string[] $patterns
|
||||||
|
*/
|
||||||
|
private function matchesAnyConfiguredPattern(string $text, array $patterns): bool
|
||||||
|
{
|
||||||
|
foreach ($patterns as $pattern) {
|
||||||
|
if (preg_match($pattern, $text) === 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private function extractContextualShopSearchQuery(string $commerceHistoryContext): string
|
private function extractContextualShopSearchQuery(string $commerceHistoryContext): string
|
||||||
{
|
{
|
||||||
if (!$this->agentRunnerConfig->isShopQueryContextFallbackEnabled()) {
|
if (!$this->agentRunnerConfig->isShopQueryContextFallbackEnabled()) {
|
||||||
|
|||||||
@@ -55,6 +55,45 @@ final class AgentRunnerConfig
|
|||||||
return $this->getRequiredStringList('follow_up_context.explicit_commercial_signal_terms');
|
return $this->getRequiredStringList('follow_up_context.explicit_commercial_signal_terms');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isCommercialTableFollowUpEnabled(): bool
|
||||||
|
{
|
||||||
|
return $this->getRequiredBool('follow_up_context.commercial_table_follow_up.enabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getCommercialTableFollowUpPromptPatterns(): array
|
||||||
|
{
|
||||||
|
return $this->getRequiredStringList('follow_up_context.commercial_table_follow_up.prompt_patterns');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getCommercialTableFollowUpHistoryAnchorPatterns(): array
|
||||||
|
{
|
||||||
|
return $this->getRequiredStringList('follow_up_context.commercial_table_follow_up.history_anchor_patterns');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getCommercialTableFollowUpIndicatorMarkerPatterns(): array
|
||||||
|
{
|
||||||
|
return $this->getRequiredStringList('follow_up_context.commercial_table_follow_up.indicator_marker_patterns');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCommercialTableFollowUpQueryTemplateWithModel(): string
|
||||||
|
{
|
||||||
|
return $this->getRequiredString('follow_up_context.commercial_table_follow_up.query_template_with_model');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCommercialTableFollowUpQueryTemplateWithoutModel(): string
|
||||||
|
{
|
||||||
|
return $this->getRequiredString('follow_up_context.commercial_table_follow_up.query_template_without_model');
|
||||||
|
}
|
||||||
|
|
||||||
public function getFollowUpHistoryQuestionPattern(): string
|
public function getFollowUpHistoryQuestionPattern(): string
|
||||||
{
|
{
|
||||||
return $this->getRequiredString('follow_up_context.history_question_pattern');
|
return $this->getRequiredString('follow_up_context.history_question_pattern');
|
||||||
|
|||||||
@@ -441,6 +441,16 @@ final readonly class RetriexEffectiveConfigProvider
|
|||||||
'product_search_knowledge_chunk_limit' => $this->agentRunnerConfig->getProductSearchKnowledgeChunkLimit(),
|
'product_search_knowledge_chunk_limit' => $this->agentRunnerConfig->getProductSearchKnowledgeChunkLimit(),
|
||||||
'advisory_product_search_knowledge_chunk_limit' => $this->agentRunnerConfig->getAdvisoryProductSearchKnowledgeChunkLimit(),
|
'advisory_product_search_knowledge_chunk_limit' => $this->agentRunnerConfig->getAdvisoryProductSearchKnowledgeChunkLimit(),
|
||||||
'optimized_shop_query_prefix_pattern' => $this->agentRunnerConfig->getOptimizedShopQueryPrefixPattern(),
|
'optimized_shop_query_prefix_pattern' => $this->agentRunnerConfig->getOptimizedShopQueryPrefixPattern(),
|
||||||
|
'follow_up_context' => [
|
||||||
|
'commercial_table_follow_up' => [
|
||||||
|
'enabled' => $this->agentRunnerConfig->isCommercialTableFollowUpEnabled(),
|
||||||
|
'prompt_patterns' => $this->agentRunnerConfig->getCommercialTableFollowUpPromptPatterns(),
|
||||||
|
'history_anchor_patterns' => $this->agentRunnerConfig->getCommercialTableFollowUpHistoryAnchorPatterns(),
|
||||||
|
'indicator_marker_patterns' => $this->agentRunnerConfig->getCommercialTableFollowUpIndicatorMarkerPatterns(),
|
||||||
|
'query_template_with_model' => $this->agentRunnerConfig->getCommercialTableFollowUpQueryTemplateWithModel(),
|
||||||
|
'query_template_without_model' => $this->agentRunnerConfig->getCommercialTableFollowUpQueryTemplateWithoutModel(),
|
||||||
|
],
|
||||||
|
],
|
||||||
'input_normalization' => [
|
'input_normalization' => [
|
||||||
'enabled' => $this->agentRunnerConfig->isInputNormalizationEnabled(),
|
'enabled' => $this->agentRunnerConfig->isInputNormalizationEnabled(),
|
||||||
'max_input_chars' => $this->agentRunnerConfig->getInputNormalizationMaxInputChars(),
|
'max_input_chars' => $this->agentRunnerConfig->getInputNormalizationMaxInputChars(),
|
||||||
@@ -1044,6 +1054,18 @@ final readonly class RetriexEffectiveConfigProvider
|
|||||||
$this->validateStringListMap($agent['source_labels'] ?? [], 'agent.source_labels', $errors, $warnings);
|
$this->validateStringListMap($agent['source_labels'] ?? [], 'agent.source_labels', $errors, $warnings);
|
||||||
$this->validateStringListMap($agent['html_templates'] ?? [], 'agent.html_templates', $errors, $warnings);
|
$this->validateStringListMap($agent['html_templates'] ?? [], 'agent.html_templates', $errors, $warnings);
|
||||||
|
|
||||||
|
$followUpContext = is_array($agent['follow_up_context'] ?? null) ? $agent['follow_up_context'] : [];
|
||||||
|
$commercialTableFollowUp = is_array($followUpContext['commercial_table_follow_up'] ?? null) ? $followUpContext['commercial_table_follow_up'] : [];
|
||||||
|
$this->validateRegexPatternList($commercialTableFollowUp['prompt_patterns'] ?? [], 'agent.follow_up_context.commercial_table_follow_up.prompt_patterns', $errors);
|
||||||
|
$this->validateRegexPatternList($commercialTableFollowUp['history_anchor_patterns'] ?? [], 'agent.follow_up_context.commercial_table_follow_up.history_anchor_patterns', $errors);
|
||||||
|
$this->validateRegexPatternList($commercialTableFollowUp['indicator_marker_patterns'] ?? [], 'agent.follow_up_context.commercial_table_follow_up.indicator_marker_patterns', $errors);
|
||||||
|
if (trim((string) ($commercialTableFollowUp['query_template_with_model'] ?? '')) === '') {
|
||||||
|
$errors[] = 'agent.follow_up_context.commercial_table_follow_up.query_template_with_model must not be empty.';
|
||||||
|
}
|
||||||
|
if (trim((string) ($commercialTableFollowUp['query_template_without_model'] ?? '')) === '') {
|
||||||
|
$errors[] = 'agent.follow_up_context.commercial_table_follow_up.query_template_without_model must not be empty.';
|
||||||
|
}
|
||||||
|
|
||||||
$ragEvidence = is_array($agent['rag_evidence_guard'] ?? null) ? $agent['rag_evidence_guard'] : [];
|
$ragEvidence = is_array($agent['rag_evidence_guard'] ?? null) ? $agent['rag_evidence_guard'] : [];
|
||||||
$this->validateStringList($this->toList($ragEvidence['stop_terms'] ?? []), 'agent.rag_evidence_guard.stop_terms', $errors, $warnings);
|
$this->validateStringList($this->toList($ragEvidence['stop_terms'] ?? []), 'agent.rag_evidence_guard.stop_terms', $errors, $warnings);
|
||||||
$this->validateStringListMap($ragEvidence['synonyms'] ?? [], 'agent.rag_evidence_guard.synonyms', $errors, $warnings);
|
$this->validateStringListMap($ragEvidence['synonyms'] ?? [], 'agent.rag_evidence_guard.synonyms', $errors, $warnings);
|
||||||
|
|||||||
Reference in New Issue
Block a user