From 130738e63b02c3a3eb5067c55e3f1886b60722c9 Mon Sep 17 00:00:00 2001 From: team 1 Date: Wed, 6 May 2026 08:53:49 +0200 Subject: [PATCH] p43Q --- config/retriex/agent.yaml | 84 ++-------- config/retriex/prompt.yaml | 69 +------- config/retriex/vocabulary.yaml | 158 ++++++++++++++++++ ...UREMENT_EVIDENCE_VOCABULARY_MAPS_README.md | 86 ++++++++++ ...IDENCE_DUPLICATE_WARNING_CLEANUP_README.md | 65 +++++++ ...RM_VOCABULARY_VIEW_CONSOLIDATION_README.md | 100 +++++++++++ src/Config/AgentRunnerConfig.php | 25 ++- src/Config/PromptBuilderConfig.php | 62 ++++++- 8 files changed, 504 insertions(+), 145 deletions(-) create mode 100644 patch_history/RETRIEX_PATCH_43O_PROMPT_MEASUREMENT_EVIDENCE_VOCABULARY_MAPS_README.md create mode 100644 patch_history/RETRIEX_PATCH_43P_PROMPT_MEASUREMENT_EVIDENCE_DUPLICATE_WARNING_CLEANUP_README.md create mode 100644 patch_history/RETRIEX_PATCH_43Q_AGENT_TERM_VOCABULARY_VIEW_CONSOLIDATION_README.md diff --git a/config/retriex/agent.yaml b/config/retriex/agent.yaml index 0ca7b3a..2daca60 100644 --- a/config/retriex/agent.yaml +++ b/config/retriex/agent.yaml @@ -106,13 +106,8 @@ parameters: history_anchor_patterns: - '/\bTestomat(?:®)?\s+\d{3,4}\b/iu' - '/\b(?:Indikatortyp|Indikator|Indikatoren|Reagenz|Reagenzien|Zubehör|Zubehoer)\b/iu' - table_terms: - - tabelle - - tabellarisch - - übersicht - - uebersicht - - liste - - auflistung + vocabulary_views: + table_terms: agent.follow_up_context.commercial_table_follow_up.table_terms commercial_terms: - preis - preise @@ -228,52 +223,9 @@ parameters: unavailable_reason_template: '{message} Ursache: {reason}' product_roles: - main_device_request_keywords: - - anlage - - messanlage - - 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 + vocabulary_views: + main_device_request_keywords: agent.no_llm_fallback.product_roles.main_device_request_keywords + accessory_product_keywords: agent.no_llm_fallback.product_roles.accessory_product_keywords production_ui: @@ -448,16 +400,10 @@ parameters: enabled: true # Terms that must be preserved from the current user input in the final # Shopware search query. This prevents short domain terms from being - # dropped by query optimization or generic cleanup. Adapt this list for - # other domains/projects instead of changing PHP code. - terms: - - ph - - rx - - th - - tc - - redox - - orp - - '0,02' + # dropped by query optimization or generic cleanup. Adapt vocabulary view + # defaults or add a local `terms` override instead of changing PHP code. + vocabulary_views: + terms: agent.shop_prompt.current_input_preservation_terms product_attribute_query_cleanup: enabled: true @@ -503,16 +449,8 @@ parameters: enabled: true max_query_terms: 2 template: '{anchor} {query}' - trigger_terms: - - indikator - - indikatortyp - - indicator - - reagenz - - reagenzsatz - - reagent - - zubehör - - zubehor - - accessory + vocabulary_views: + trigger_terms: agent.shop_prompt.context_anchor_enrichment.trigger_terms 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' meta_query_guard: diff --git a/config/retriex/prompt.yaml b/config/retriex/prompt.yaml index 3cde695..2b883c3 100644 --- a/config/retriex/prompt.yaml +++ b/config/retriex/prompt.yaml @@ -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' 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: - '- 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.' @@ -134,24 +141,6 @@ parameters: - 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_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: 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.' @@ -178,17 +167,6 @@ parameters: parameters: - id: ph 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: - Betriebsbereich - Betriebsumgebung @@ -205,47 +183,14 @@ parameters: - Reagenzlösung hat - Loesung 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_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 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_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 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_accessory_evidence_answer_de: Ich finde in den bereitgestellten Quellen keinen sicher belegten Indikator oder ein Reagenz für die Messung von freiem Chlor. diff --git a/config/retriex/vocabulary.yaml b/config/retriex/vocabulary.yaml index de89a4b..e63f2d3 100644 --- a/config/retriex/vocabulary.yaml +++ b/config/retriex/vocabulary.yaml @@ -167,6 +167,77 @@ parameters: - empfehlung - empfehlen - 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: shop: device_query: @@ -578,6 +649,27 @@ parameters: - reagenz - reagent 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: add: - technisch @@ -737,7 +829,73 @@ parameters: input_normalization_fuzzy_routing_terms: include: - 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: + 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: rag_evidence_guard: synonyms: diff --git a/patch_history/RETRIEX_PATCH_43O_PROMPT_MEASUREMENT_EVIDENCE_VOCABULARY_MAPS_README.md b/patch_history/RETRIEX_PATCH_43O_PROMPT_MEASUREMENT_EVIDENCE_VOCABULARY_MAPS_README.md new file mode 100644 index 0000000..be7ea94 --- /dev/null +++ b/patch_history/RETRIEX_PATCH_43O_PROMPT_MEASUREMENT_EVIDENCE_VOCABULARY_MAPS_README.md @@ -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 +``` diff --git a/patch_history/RETRIEX_PATCH_43P_PROMPT_MEASUREMENT_EVIDENCE_DUPLICATE_WARNING_CLEANUP_README.md b/patch_history/RETRIEX_PATCH_43P_PROMPT_MEASUREMENT_EVIDENCE_DUPLICATE_WARNING_CLEANUP_README.md new file mode 100644 index 0000000..4dc7366 --- /dev/null +++ b/patch_history/RETRIEX_PATCH_43P_PROMPT_MEASUREMENT_EVIDENCE_DUPLICATE_WARNING_CLEANUP_README.md @@ -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 +``` diff --git a/patch_history/RETRIEX_PATCH_43Q_AGENT_TERM_VOCABULARY_VIEW_CONSOLIDATION_README.md b/patch_history/RETRIEX_PATCH_43Q_AGENT_TERM_VOCABULARY_VIEW_CONSOLIDATION_README.md new file mode 100644 index 0000000..d3591b4 --- /dev/null +++ b/patch_history/RETRIEX_PATCH_43Q_AGENT_TERM_VOCABULARY_VIEW_CONSOLIDATION_README.md @@ -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 +``` diff --git a/src/Config/AgentRunnerConfig.php b/src/Config/AgentRunnerConfig.php index 0ac9032..bcb9f34 100644 --- a/src/Config/AgentRunnerConfig.php +++ b/src/Config/AgentRunnerConfig.php @@ -82,7 +82,10 @@ final class AgentRunnerConfig */ 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 { - 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 { - 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 @@ -979,7 +988,10 @@ final class AgentRunnerConfig */ 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 @@ -1163,7 +1175,10 @@ final class AgentRunnerConfig */ 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' + ); } /** diff --git a/src/Config/PromptBuilderConfig.php b/src/Config/PromptBuilderConfig.php index 8a6afb9..66014c8 100644 --- a/src/Config/PromptBuilderConfig.php +++ b/src/Config/PromptBuilderConfig.php @@ -189,6 +189,49 @@ final class PromptBuilderConfig return $terms; } + /** + * @return array + */ + 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 $item + * @param array $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[] */ @@ -735,7 +778,10 @@ final class PromptBuilderConfig */ 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 { - 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 @@ -783,6 +832,9 @@ final class PromptBuilderConfig $out = []; $genericPositiveContextTerms = $this->getMeasurementEvidenceGenericPositiveContextTerms(); $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) { if (!is_array($item)) { @@ -799,15 +851,15 @@ final class PromptBuilderConfig $out[] = [ 'id' => $id, 'label' => $label, - 'request_terms' => $this->normalizeMixedStringList($item['request_terms'] ?? []), - 'positive_terms' => $this->normalizeMixedStringList($item['positive_terms'] ?? []), + 'request_terms' => $this->getParameterStringList($item, $id, 'request_terms', $requestTermsByParameter), + 'positive_terms' => $this->getParameterStringList($item, $id, 'positive_terms', $positiveTermsByParameter), 'positive_context_terms' => array_key_exists('positive_context_terms', $item) ? $this->normalizeMixedStringList($item['positive_context_terms']) : $genericPositiveContextTerms, 'negative_context_terms' => array_key_exists('negative_context_terms', $item) ? $this->normalizeMixedStringList($item['negative_context_terms']) : $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']) ? trim((string) $item['safe_no_evidence_answer_de']) : '',