This commit is contained in:
team 1
2026-05-06 08:53:49 +02:00
parent 931af8b098
commit 130738e63b
8 changed files with 504 additions and 145 deletions

View File

@@ -106,13 +106,8 @@ parameters:
history_anchor_patterns: history_anchor_patterns:
- '/\bTestomat(?:®)?\s+\d{3,4}\b/iu' - '/\bTestomat(?:®)?\s+\d{3,4}\b/iu'
- '/\b(?:Indikatortyp|Indikator|Indikatoren|Reagenz|Reagenzien|Zubehör|Zubehoer)\b/iu' - '/\b(?:Indikatortyp|Indikator|Indikatoren|Reagenz|Reagenzien|Zubehör|Zubehoer)\b/iu'
table_terms: vocabulary_views:
- tabelle table_terms: agent.follow_up_context.commercial_table_follow_up.table_terms
- tabellarisch
- übersicht
- uebersicht
- liste
- auflistung
commercial_terms: commercial_terms:
- preis - preis
- preise - preise
@@ -228,52 +223,9 @@ parameters:
unavailable_reason_template: '{message} Ursache: {reason}' unavailable_reason_template: '{message} Ursache: {reason}'
product_roles: product_roles:
main_device_request_keywords: vocabulary_views:
- anlage main_device_request_keywords: agent.no_llm_fallback.product_roles.main_device_request_keywords
- messanlage accessory_product_keywords: agent.no_llm_fallback.product_roles.accessory_product_keywords
- gerät
- geraet
- messgerät
- messgeraet
- analysegerät
- analysegeraet
- analysator
- analyzer
- system
- testomat
- testomaten
- testoamt
- testomate
- pockettester
accessory_product_keywords:
- indikator
- indicator
- indikatortyp
- reagenz
- reagent
- reagenzsatz
- kalibrierlösung
- kalibrierloesung
- pufferlösung
- pufferloesung
- reinigungslösung
- reinigungsloesung
- kalibrier
- puffer
- zubehör
- zubehor
- accessory
- ersatzteil
- verbrauch
- consumable
- kit
- set
- flasche
- bottle
- 100 ml
- 500 ml
- 100ml
- 500ml
production_ui: production_ui:
@@ -448,16 +400,10 @@ parameters:
enabled: true enabled: true
# Terms that must be preserved from the current user input in the final # Terms that must be preserved from the current user input in the final
# Shopware search query. This prevents short domain terms from being # Shopware search query. This prevents short domain terms from being
# dropped by query optimization or generic cleanup. Adapt this list for # dropped by query optimization or generic cleanup. Adapt vocabulary view
# other domains/projects instead of changing PHP code. # defaults or add a local `terms` override instead of changing PHP code.
terms: vocabulary_views:
- ph terms: agent.shop_prompt.current_input_preservation_terms
- rx
- th
- tc
- redox
- orp
- '0,02'
product_attribute_query_cleanup: product_attribute_query_cleanup:
enabled: true enabled: true
@@ -503,16 +449,8 @@ parameters:
enabled: true enabled: true
max_query_terms: 2 max_query_terms: 2
template: '{anchor} {query}' template: '{anchor} {query}'
trigger_terms: vocabulary_views:
- indikator trigger_terms: agent.shop_prompt.context_anchor_enrichment.trigger_terms
- indikatortyp
- indicator
- reagenz
- reagenzsatz
- reagent
- zubehör
- zubehor
- accessory
anchor_patterns: anchor_patterns:
- '/\b(?:indikator(?:typ)?|indicator(?:\s+type)?|reagenz(?:satz|typ)?|reagent(?:\s+set|\s+type)?|typ|type)\s+[A-Za-zÄÖÜäöüß]{0,8}\s*\d{1,5}(?:\s*[A-ZÄÖÜ]{1,4})?(?:\s*%)?\b/iu' - '/\b(?:indikator(?:typ)?|indicator(?:\s+type)?|reagenz(?:satz|typ)?|reagent(?:\s+set|\s+type)?|typ|type)\s+[A-Za-zÄÖÜäöüß]{0,8}\s*\d{1,5}(?:\s*[A-ZÄÖÜ]{1,4})?(?:\s*%)?\b/iu'
meta_query_guard: meta_query_guard:

View File

@@ -90,6 +90,13 @@ parameters:
- '/\b(testomat|messgerät|messgeraet|analysegerät|analysegeraet|gerät|geraet|analysator)\s+[^?.!,;]{0,40}(messen|misst|überwachen|ueberwachen|kann|für|fuer)\b/u' - '/\b(testomat|messgerät|messgeraet|analysegerät|analysegeraet|gerät|geraet|analysator)\s+[^?.!,;]{0,40}(messen|misst|überwachen|ueberwachen|kann|für|fuer)\b/u'
measurement_evidence_guard: measurement_evidence_guard:
vocabulary_views:
accessory_lookup_guard_terms: prompt.measurement_evidence_guard.accessory_lookup_guard_terms
accessory_lookup_passthrough_terms: prompt.measurement_evidence_guard.accessory_lookup_passthrough_terms
vocabulary_maps:
request_terms: prompt.measurement_evidence_guard.request_terms
positive_terms: prompt.measurement_evidence_guard.positive_terms
non_equivalent_terms: prompt.measurement_evidence_guard.non_equivalent_terms
intro_rules: intro_rules:
- '- This block is generated from the current user question and is stricter than broad product-selection wording.' - '- This block is generated from the current user question and is stricter than broad product-selection wording.'
- '- For measurement-parameter questions, technical suitability requires explicit positive evidence for the requested parameter in the same source record.' - '- For measurement-parameter questions, technical suitability requires explicit positive evidence for the requested parameter in the same source record.'
@@ -134,24 +141,6 @@ parameters:
- stoerungsfrei - stoerungsfrei
generic_safe_no_evidence_answer_template_de: Ich finde in den bereitgestellten Quellen keinen sicher belegten Treffer für die Messung von {label}. generic_safe_no_evidence_answer_template_de: Ich finde in den bereitgestellten Quellen keinen sicher belegten Treffer für die Messung von {label}.
generic_safe_no_accessory_evidence_answer_template_de: Ich finde in den bereitgestellten Quellen keinen sicher belegten Indikator oder ein Reagenz für die Messung von {label}. generic_safe_no_accessory_evidence_answer_template_de: Ich finde in den bereitgestellten Quellen keinen sicher belegten Indikator oder ein Reagenz für die Messung von {label}.
accessory_lookup_guard_terms:
- indikator
- indikatoren
- indicator
- reagenz
- reagenzien
- reagent
- teststreifen
accessory_lookup_passthrough_terms:
- anschlusskabel
- kabel
- sensorkabel
- elektrodenkabel
- elektrode
- puffer
- kalibrierpuffer
- kalibrierlösung
- kalibrierloesung
rule_templates: rule_templates:
shop_positive_evidence: '- Shop record {index} ({product}): explicit positive evidence for {label} is present in this same record.' shop_positive_evidence: '- Shop record {index} ({product}): explicit positive evidence for {label} is present in this same record.'
shop_no_evidence: '- No shop product record shown to the model contains explicit positive evidence for {label} in the same record.' shop_no_evidence: '- No shop product record shown to the model contains explicit positive evidence for {label} in the same record.'
@@ -178,17 +167,6 @@ parameters:
parameters: parameters:
- id: ph - id: ph
label: pH / pH-Wert label: pH / pH-Wert
request_terms:
- ph
- pH
- pH-Wert
- ph-wert
- ph wert
positive_terms:
- pH
- pH-Wert
- ph-wert
- ph wert
negative_context_terms: negative_context_terms:
- Betriebsbereich - Betriebsbereich
- Betriebsumgebung - Betriebsumgebung
@@ -205,47 +183,14 @@ parameters:
- Reagenzlösung hat - Reagenzlösung hat
- Loesung hat - Loesung hat
- Lösung hat - Lösung hat
non_equivalent_terms:
- p-Wert
- p Wert
- m-Wert
- minus m-Wert
- Alkalität
- Säurekapazität
- mmol/l
safe_no_evidence_answer_de: Ich finde in den bereitgestellten Quellen keinen sicher belegten Geräte für pH-Messung. safe_no_evidence_answer_de: Ich finde in den bereitgestellten Quellen keinen sicher belegten Geräte für pH-Messung.
safe_no_accessory_evidence_answer_de: Ich finde in den bereitgestellten Quellen keinen sicher belegten pH-Indikator oder ein pH-Reagenz für Messgeräte. safe_no_accessory_evidence_answer_de: Ich finde in den bereitgestellten Quellen keinen sicher belegten pH-Indikator oder ein pH-Reagenz für Messgeräte.
- id: redox - id: redox
label: Redox / ORP label: Redox / ORP
request_terms:
- redox
- orp
- oxidations-reduktionspotential
- oxidations reduktionspotential
positive_terms:
- Redox
- ORP
- Oxidations-Reduktionspotential
- Oxidations Reduktionspotential
non_equivalent_terms: []
safe_no_evidence_answer_de: Ich finde in den bereitgestellten Quellen keinen sicher belegten Treffer für Redox-/ORP-Messung. safe_no_evidence_answer_de: Ich finde in den bereitgestellten Quellen keinen sicher belegten Treffer für Redox-/ORP-Messung.
safe_no_accessory_evidence_answer_de: Ich finde in den bereitgestellten Quellen keinen sicher belegten Redox-/ORP-Indikator oder ein Redox-/ORP-Reagenz für Messgeräte. safe_no_accessory_evidence_answer_de: Ich finde in den bereitgestellten Quellen keinen sicher belegten Redox-/ORP-Indikator oder ein Redox-/ORP-Reagenz für Messgeräte.
- id: free_chlorine - id: free_chlorine
label: freies Chlor label: freies Chlor
request_terms:
- freies chlor
- freiem chlor
- freien chlor
- free chlorine
positive_terms:
- freies Chlor
- freiem Chlor
- freien Chlor
- free chlorine
non_equivalent_terms:
- Chlor gesamt
- Gesamtchlor
- total chlorine
safe_no_evidence_answer_de: Ich finde in den bereitgestellten Quellen keinen sicher belegten Treffer für die Messung von freiem Chlor. safe_no_evidence_answer_de: Ich finde in den bereitgestellten Quellen keinen sicher belegten Treffer für die Messung von freiem Chlor.
safe_no_accessory_evidence_answer_de: Ich finde in den bereitgestellten Quellen keinen sicher belegten Indikator oder ein Reagenz für die Messung von freiem Chlor. safe_no_accessory_evidence_answer_de: Ich finde in den bereitgestellten Quellen keinen sicher belegten Indikator oder ein Reagenz für die Messung von freiem Chlor.

View File

@@ -167,6 +167,77 @@ parameters:
- empfehlung - empfehlung
- empfehlen - empfehlen
- empfiehl - empfiehl
agent_follow_up_commercial_table_terms:
- tabelle
- tabellarisch
- übersicht
- uebersicht
- liste
- auflistung
agent_no_llm_main_device_request_keywords:
- anlage
- messanlage
- gerät
- geraet
- messgerät
- messgeraet
- analysegerät
- analysegeraet
- analysator
- analyzer
- system
- testomat
- testomaten
- testoamt
- testomate
- pockettester
agent_no_llm_accessory_product_keywords:
- indikator
- indicator
- indikatortyp
- reagenz
- reagent
- reagenzsatz
- kalibrierlösung
- kalibrierloesung
- pufferlösung
- pufferloesung
- reinigungslösung
- reinigungsloesung
- kalibrier
- puffer
- zubehör
- zubehor
- accessory
- ersatzteil
- verbrauch
- consumable
- kit
- set
- flasche
- bottle
- 100 ml
- 500 ml
- 100ml
- 500ml
agent_shop_current_input_preservation_terms:
- ph
- rx
- th
- tc
- redox
- orp
- '0,02'
agent_shop_context_anchor_trigger_terms:
- indikator
- indikatortyp
- indicator
- reagenz
- reagenzsatz
- reagent
- zubehör
- zubehor
- accessory
views: views:
shop: shop:
device_query: device_query:
@@ -578,6 +649,27 @@ parameters:
- reagenz - reagenz
- reagent - reagent
prompt: prompt:
measurement_evidence_guard:
accessory_lookup_guard_terms:
add:
- indikator
- indikatoren
- indicator
- reagenz
- reagenzien
- reagent
- teststreifen
accessory_lookup_passthrough_terms:
add:
- anschlusskabel
- kabel
- sensorkabel
- elektrodenkabel
- elektrode
- puffer
- kalibrierpuffer
- kalibrierlösung
- kalibrierloesung
technical_product_keywords: technical_product_keywords:
add: add:
- technisch - technisch
@@ -737,7 +829,73 @@ parameters:
input_normalization_fuzzy_routing_terms: input_normalization_fuzzy_routing_terms:
include: include:
- input_normalization_fuzzy_routing_terms - input_normalization_fuzzy_routing_terms
follow_up_context:
commercial_table_follow_up:
table_terms:
include:
- agent_follow_up_commercial_table_terms
no_llm_fallback:
product_roles:
main_device_request_keywords:
include:
- agent_no_llm_main_device_request_keywords
accessory_product_keywords:
include:
- agent_no_llm_accessory_product_keywords
shop_prompt:
current_input_preservation_terms:
include:
- agent_shop_current_input_preservation_terms
context_anchor_enrichment:
trigger_terms:
include:
- agent_shop_context_anchor_trigger_terms
maps: maps:
prompt:
measurement_evidence_guard:
request_terms:
ph:
- ph
- ph-wert
- ph wert
redox:
- redox
- orp
- oxidations-reduktionspotential
- oxidations reduktionspotential
free_chlorine:
- freies chlor
- freiem chlor
- freien chlor
- free chlorine
positive_terms:
ph:
- pH
- pH-Wert
- ph wert
redox:
- Redox
- ORP
- Oxidations-Reduktionspotential
- Oxidations Reduktionspotential
free_chlorine:
- freies Chlor
- freiem Chlor
- freien Chlor
- free chlorine
non_equivalent_terms:
ph:
- p-Wert
- p Wert
- m-Wert
- minus m-Wert
- Alkalität
- Säurekapazität
- mmol/l
free_chlorine:
- Chlor gesamt
- Gesamtchlor
- total chlorine
agent: agent:
rag_evidence_guard: rag_evidence_guard:
synonyms: synonyms:

View File

@@ -0,0 +1,86 @@
# RetrieX Patch 43O - Prompt Measurement Evidence Vocabulary Maps
## Goal
Continue the p43 YAML/list/map consolidation with a larger but still behavior-preserving config-structure patch.
This patch centralizes prompt measurement-evidence term lists in `vocabulary.yaml` while keeping prompt rules, labels, answer templates and parameter definitions in `prompt.yaml`.
## Scope
Changed files:
- `config/retriex/prompt.yaml`
- `config/retriex/vocabulary.yaml`
- `src/Config/PromptBuilderConfig.php`
- `patch_history/RETRIEX_PATCH_43O_PROMPT_MEASUREMENT_EVIDENCE_VOCABULARY_MAPS_README.md`
## Changes
- Moved `measurement_evidence_guard.accessory_lookup_guard_terms` from `prompt.yaml` into vocabulary view:
- `prompt.measurement_evidence_guard.accessory_lookup_guard_terms`
- Moved `measurement_evidence_guard.accessory_lookup_passthrough_terms` from `prompt.yaml` into vocabulary view:
- `prompt.measurement_evidence_guard.accessory_lookup_passthrough_terms`
- Moved per-parameter `request_terms`, `positive_terms`, and `non_equivalent_terms` from `prompt.yaml` into vocabulary maps:
- `prompt.measurement_evidence_guard.request_terms`
- `prompt.measurement_evidence_guard.positive_terms`
- `prompt.measurement_evidence_guard.non_equivalent_terms`
- Added `measurement_evidence_guard.vocabulary_views` and `measurement_evidence_guard.vocabulary_maps` references in `prompt.yaml`.
- Added `PromptBuilderConfig` vocabulary-map resolving for measurement-evidence parameters.
- Kept local per-parameter list overrides supported: if a parameter defines `request_terms`, `positive_terms`, or `non_equivalent_terms` locally, that local list still wins.
## Non-goals
This patch intentionally does not change:
- Fachlogik / runtime product-selection behavior
- Scoring
- Retrieval
- Prompt rules
- Prompt wording
- Admin UI
- PHP-core hardcoded fachliche Listen
## Effective-value validation
The effective measurement-evidence output was compared against the p43N base and remained identical:
- accessory lookup guard terms: 7 / identical
- accessory lookup passthrough terms: 9 / identical
- measurement evidence parameters: 3 / identical
- `ph`: request 5, positive 4, non-equivalent 7
- `redox`: request 4, positive 4, non-equivalent 0
- `free_chlorine`: request 4, positive 4, non-equivalent 3
## Local checks run
```bash
php -l src/Config/PromptBuilderConfig.php
php -l src/Config/DomainVocabularyConfig.php
php -l src/Config/AgentRunnerConfig.php
php -l src/Config/SearchRepairConfig.php
php -l src/Config/GovernanceConfig.php
php -l src/Config/LanguageCleanupConfig.php
python3 YAML parse check for config/retriex/*.yaml
python3 effective p43N-vs-p43O prompt measurement evidence comparison
php PromptBuilderConfig vocabulary resolver check
```
All checks above passed.
## Console checks
The Symfony console checks could not be executed in this artifact environment because the uploaded ZIP does not contain `vendor/`:
```text
PHP Fatal error: Uncaught LogicException: Dependencies are missing. Try running "composer install".
```
Please run in the project environment:
```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
```

View File

@@ -0,0 +1,65 @@
# RetrieX Patch 43P - Prompt Measurement Evidence Duplicate Warning Cleanup
## Ziel
Beseitigt die drei Config-Validation-Warnings aus p43O, ohne fachliche Runtime-Logik, Scoring, Retrieval oder Prompt-Regeln zu ändern.
## Hintergrund
p43O hat Measurement-Evidence-Terme aus `prompt.yaml` nach `vocabulary.yaml` verschoben. Dabei wurden bestehende, normalisiert doppelte pH-Schreibweisen bewusst 1:1 mitgenommen. Die Config-Validation meldet diese Duplikate nun an den zentralen Vocabulary-Maps:
- `vocabulary.maps.prompt.measurement_evidence_guard.request_terms.ph` enthält doppelt normalisiert `pH`
- `vocabulary.maps.prompt.measurement_evidence_guard.request_terms.ph` enthält doppelt normalisiert `ph-wert`
- `vocabulary.maps.prompt.measurement_evidence_guard.positive_terms.ph` enthält doppelt normalisiert `ph-wert`
## Änderungen
Geändert wurde nur `config/retriex/vocabulary.yaml`:
- `request_terms.ph`
- entfernt: `pH`
- entfernt: `pH-Wert`
- behalten: `ph`, `ph-wert`, `ph wert`
- `positive_terms.ph`
- entfernt: `ph-wert`
- behalten: `pH`, `pH-Wert`, `ph wert`
## Nicht geändert
- keine PHP-Codeänderung
- keine neue Fachlogik
- keine Scoringänderung
- keine Retrievaländerung
- keine Prompt-Regeländerung
- keine Admin-UI
- keine neuen harten Listen im PHP-Core
## Erwartetes Verhalten
Die pH-Erkennung bleibt durch normalisierte, case-insensitive Matching-Logik erhalten. Entfernt wurden nur normalisiert redundante Schreibweisen.
## Lokale Prüfungen
In der Artefakt-Umgebung geprüft:
```bash
php -l src/Config/PromptBuilderConfig.php
php -l src/Config/DomainVocabularyConfig.php
php -l src/Config/AgentRunnerConfig.php
php -l src/Config/SearchRepairConfig.php
php -l src/Config/GovernanceConfig.php
php -l src/Config/LanguageCleanupConfig.php
python3 YAML parse check for config/retriex/*.yaml
python3 duplicate check for prompt.measurement_evidence_guard pH term maps
zip -T retriex_p43p_prompt_measurement_evidence_duplicate_warning_cleanup_patch_only.zip
```
Die Symfony-Console-Checks konnten lokal nicht ausgeführt werden, weil der ZIP-Stand kein `vendor/` enthält und `bin/console` mit fehlenden Dependencies abbricht. Bitte wie üblich im Projekt ausführen:
```bash
bin/console c:cl
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
```

View File

@@ -0,0 +1,100 @@
# RetrieX Patch 43Q - Agent Term Vocabulary View Consolidation
## Ziel
p43Q reduziert weitere lokale Agent-Termlisten und verschiebt sie in zentrale Vocabulary-Views, ohne fachliche Runtime-Logik, Scoring, Retrieval oder Prompt-Regeln zu ändern.
Der Patch setzt auf dem grünen p43P-Stand auf.
## Änderungen
### `config/retriex/agent.yaml`
Folgende lokale Listen wurden entfernt und durch `vocabulary_views` ersetzt:
- `follow_up_context.commercial_table_follow_up.table_terms`
- `no_llm_fallback.product_roles.main_device_request_keywords`
- `no_llm_fallback.product_roles.accessory_product_keywords`
- `shop_prompt.current_input_preservation.terms`
- `shop_prompt.context_anchor_enrichment.trigger_terms`
Lokale Overrides bleiben möglich: Wird die ursprüngliche lokale Liste wieder gesetzt, bevorzugt der Config-Accessor diese Liste vor der Vocabulary-View.
### `config/retriex/vocabulary.yaml`
Neue zentrale Klassen:
- `agent_follow_up_commercial_table_terms`
- `agent_no_llm_main_device_request_keywords`
- `agent_no_llm_accessory_product_keywords`
- `agent_shop_current_input_preservation_terms`
- `agent_shop_context_anchor_trigger_terms`
Neue Views:
- `agent.follow_up_context.commercial_table_follow_up.table_terms`
- `agent.no_llm_fallback.product_roles.main_device_request_keywords`
- `agent.no_llm_fallback.product_roles.accessory_product_keywords`
- `agent.shop_prompt.current_input_preservation_terms`
- `agent.shop_prompt.context_anchor_enrichment.trigger_terms`
### `src/Config/AgentRunnerConfig.php`
Die betroffenen Accessors nutzen nun `getConfiguredStringListOrVocabularyView()`:
- `getCommercialTableFollowUpTableTerms()`
- `getNoLlmMainDeviceRequestRoleKeywords()`
- `getNoLlmAccessoryProductRoleKeywords()`
- `getShopQueryCurrentInputPreservationTerms()`
- `getShopQueryContextAnchorEnrichmentTriggerTerms()`
## Effektive Werte
Die effektiven Listen bleiben gegenüber p43P identisch:
- `commercial_table_terms`: 6 / 6
- `no_llm_main_device_request_keywords`: 16 / 16
- `no_llm_accessory_product_keywords`: 28 / 28
- `current_input_preservation_terms`: 7 / 7
- `context_anchor_trigger_terms`: 9 / 9
## Nicht geändert
- keine neue Fachlogik
- keine Scoringänderung
- keine Retrievaländerung
- keine Prompt-Regeländerung
- keine Admin-UI
- keine neuen harten fachlichen Listen im PHP-Core
## Lokale Prüfungen
Ausgeführt:
```bash
php -l src/Config/AgentRunnerConfig.php
php -l src/Config/DomainVocabularyConfig.php
php -l src/Config/SearchRepairConfig.php
php -l src/Config/PromptBuilderConfig.php
php -l src/Config/GovernanceConfig.php
php -l src/Config/LanguageCleanupConfig.php
python3 YAML parse check for config/retriex/*.yaml
python3 effective p43P-vs-p43Q agent list comparison
zip -T retriex_p43q_agent_term_vocabulary_view_consolidation_patch_only.zip
```
Ergebnis: grün.
## Nicht lokal ausführbar
Die Symfony-Console-Checks konnten in der lokalen Artefaktumgebung nicht ausgeführt werden, weil der ZIP-Stand kein `vendor/` enthält und `bin/console` mit fehlenden Dependencies abbricht.
Bitte nach Einspielen wie gewohnt prüfen:
```bash
bin/console c:cl
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
```

View File

@@ -82,7 +82,10 @@ final class AgentRunnerConfig
*/ */
public function getCommercialTableFollowUpTableTerms(): array public function getCommercialTableFollowUpTableTerms(): array
{ {
return $this->getRequiredStringList('follow_up_context.commercial_table_follow_up.table_terms'); return $this->getConfiguredStringListOrVocabularyView(
'follow_up_context.commercial_table_follow_up.table_terms',
'follow_up_context.commercial_table_follow_up.vocabulary_views.table_terms'
);
} }
/** /**
@@ -828,7 +831,10 @@ final class AgentRunnerConfig
*/ */
public function getNoLlmMainDeviceRequestRoleKeywords(): array public function getNoLlmMainDeviceRequestRoleKeywords(): array
{ {
return $this->getRequiredStringList('no_llm_fallback.product_roles.main_device_request_keywords'); return $this->getConfiguredStringListOrVocabularyView(
'no_llm_fallback.product_roles.main_device_request_keywords',
'no_llm_fallback.product_roles.vocabulary_views.main_device_request_keywords'
);
} }
/** /**
@@ -836,7 +842,10 @@ final class AgentRunnerConfig
*/ */
public function getNoLlmAccessoryProductRoleKeywords(): array public function getNoLlmAccessoryProductRoleKeywords(): array
{ {
return $this->getRequiredStringList('no_llm_fallback.product_roles.accessory_product_keywords'); return $this->getConfiguredStringListOrVocabularyView(
'no_llm_fallback.product_roles.accessory_product_keywords',
'no_llm_fallback.product_roles.vocabulary_views.accessory_product_keywords'
);
} }
public function getNoLlmFallbackShopUnavailableWithKnowledgeMessage(): string public function getNoLlmFallbackShopUnavailableWithKnowledgeMessage(): string
@@ -979,7 +988,10 @@ final class AgentRunnerConfig
*/ */
public function getShopQueryCurrentInputPreservationTerms(): array public function getShopQueryCurrentInputPreservationTerms(): array
{ {
return $this->getOptionalStringList('shop_prompt.current_input_preservation.terms'); return $this->getConfiguredStringListOrVocabularyView(
'shop_prompt.current_input_preservation.terms',
'shop_prompt.current_input_preservation.vocabulary_views.terms'
);
} }
public function isShopQueryProductAttributeCleanupEnabled(): bool public function isShopQueryProductAttributeCleanupEnabled(): bool
@@ -1163,7 +1175,10 @@ final class AgentRunnerConfig
*/ */
public function getShopQueryContextAnchorEnrichmentTriggerTerms(): array public function getShopQueryContextAnchorEnrichmentTriggerTerms(): array
{ {
return $this->getRequiredStringList('shop_prompt.context_anchor_enrichment.trigger_terms'); return $this->getConfiguredStringListOrVocabularyView(
'shop_prompt.context_anchor_enrichment.trigger_terms',
'shop_prompt.context_anchor_enrichment.vocabulary_views.trigger_terms'
);
} }
/** /**

View File

@@ -189,6 +189,49 @@ final class PromptBuilderConfig
return $terms; return $terms;
} }
/**
* @return array<string, string[]>
*/
private function getVocabularyStringListMap(string $mapPathConfigPath): array
{
if (!$this->hasPath($mapPathConfigPath)) {
return [];
}
if ($this->vocabulary === null) {
throw new \InvalidArgumentException(sprintf(
'RetrieX prompt vocabulary map config path "%s" is set but no vocabulary resolver is available.',
$mapPathConfigPath
));
}
$mapPath = $this->getRequiredString($mapPathConfigPath);
$map = $this->vocabulary->map($mapPath, []);
if ($map === []) {
throw new \InvalidArgumentException(sprintf(
'RetrieX prompt vocabulary map "%s" resolved to an empty map.',
$mapPath
));
}
return $map;
}
/**
* @param array<string, mixed> $item
* @param array<string, string[]> $vocabularyMap
* @return string[]
*/
private function getParameterStringList(array $item, string $id, string $localKey, array $vocabularyMap): array
{
if (array_key_exists($localKey, $item)) {
return $this->normalizeMixedStringList($item[$localKey]);
}
return $vocabularyMap[$id] ?? [];
}
/** /**
* @return string[] * @return string[]
*/ */
@@ -735,7 +778,10 @@ final class PromptBuilderConfig
*/ */
public function getMeasurementEvidenceAccessoryLookupGuardTerms(): array public function getMeasurementEvidenceAccessoryLookupGuardTerms(): array
{ {
return $this->getRequiredStringList('measurement_evidence_guard.accessory_lookup_guard_terms'); return $this->getConfiguredStringListOrVocabularyView(
'measurement_evidence_guard.accessory_lookup_guard_terms',
'measurement_evidence_guard.vocabulary_views.accessory_lookup_guard_terms'
);
} }
/** /**
@@ -743,7 +789,10 @@ final class PromptBuilderConfig
*/ */
public function getMeasurementEvidenceAccessoryLookupPassthroughTerms(): array public function getMeasurementEvidenceAccessoryLookupPassthroughTerms(): array
{ {
return $this->getRequiredStringList('measurement_evidence_guard.accessory_lookup_passthrough_terms'); return $this->getConfiguredStringListOrVocabularyView(
'measurement_evidence_guard.accessory_lookup_passthrough_terms',
'measurement_evidence_guard.vocabulary_views.accessory_lookup_passthrough_terms'
);
} }
public function getMeasurementEvidenceRuleTemplate(string $key): string public function getMeasurementEvidenceRuleTemplate(string $key): string
@@ -783,6 +832,9 @@ final class PromptBuilderConfig
$out = []; $out = [];
$genericPositiveContextTerms = $this->getMeasurementEvidenceGenericPositiveContextTerms(); $genericPositiveContextTerms = $this->getMeasurementEvidenceGenericPositiveContextTerms();
$genericNegativeContextTerms = $this->getMeasurementEvidenceGenericNegativeContextTerms(); $genericNegativeContextTerms = $this->getMeasurementEvidenceGenericNegativeContextTerms();
$requestTermsByParameter = $this->getVocabularyStringListMap('measurement_evidence_guard.vocabulary_maps.request_terms');
$positiveTermsByParameter = $this->getVocabularyStringListMap('measurement_evidence_guard.vocabulary_maps.positive_terms');
$nonEquivalentTermsByParameter = $this->getVocabularyStringListMap('measurement_evidence_guard.vocabulary_maps.non_equivalent_terms');
foreach ($value as $item) { foreach ($value as $item) {
if (!is_array($item)) { if (!is_array($item)) {
@@ -799,15 +851,15 @@ final class PromptBuilderConfig
$out[] = [ $out[] = [
'id' => $id, 'id' => $id,
'label' => $label, 'label' => $label,
'request_terms' => $this->normalizeMixedStringList($item['request_terms'] ?? []), 'request_terms' => $this->getParameterStringList($item, $id, 'request_terms', $requestTermsByParameter),
'positive_terms' => $this->normalizeMixedStringList($item['positive_terms'] ?? []), 'positive_terms' => $this->getParameterStringList($item, $id, 'positive_terms', $positiveTermsByParameter),
'positive_context_terms' => array_key_exists('positive_context_terms', $item) 'positive_context_terms' => array_key_exists('positive_context_terms', $item)
? $this->normalizeMixedStringList($item['positive_context_terms']) ? $this->normalizeMixedStringList($item['positive_context_terms'])
: $genericPositiveContextTerms, : $genericPositiveContextTerms,
'negative_context_terms' => array_key_exists('negative_context_terms', $item) 'negative_context_terms' => array_key_exists('negative_context_terms', $item)
? $this->normalizeMixedStringList($item['negative_context_terms']) ? $this->normalizeMixedStringList($item['negative_context_terms'])
: $genericNegativeContextTerms, : $genericNegativeContextTerms,
'non_equivalent_terms' => $this->normalizeMixedStringList($item['non_equivalent_terms'] ?? []), 'non_equivalent_terms' => $this->getParameterStringList($item, $id, 'non_equivalent_terms', $nonEquivalentTermsByParameter),
'safe_no_evidence_answer_de' => isset($item['safe_no_evidence_answer_de']) && is_scalar($item['safe_no_evidence_answer_de']) 'safe_no_evidence_answer_de' => isset($item['safe_no_evidence_answer_de']) && is_scalar($item['safe_no_evidence_answer_de'])
? trim((string) $item['safe_no_evidence_answer_de']) ? trim((string) $item['safe_no_evidence_answer_de'])
: '', : '',