This commit is contained in:
team 1
2026-05-11 13:44:32 +02:00
parent 0bce89cd8b
commit c4890183f8
8 changed files with 209 additions and 20 deletions

View File

@@ -1924,6 +1924,7 @@ parameters:
- pronouns
- user_instruction_terms
- response_style
- shop_relation_noise
phrase_group_sets:
- user_instruction
rag_evidence:

View File

@@ -48,7 +48,7 @@ parameters:
intent.sales.objection_signals: 'dea7269eaa22d3e3a5ef2cc8d2d012b3c089e0c69d141df2c1e1e118fec6a491'
intent.sales.roi_signals: '88101a34b5e63a938055ab89bde1f73ce3bf8698f6d2793018145cdd7ae814da'
intent.sales.sales_signals: '7269ee14955e4a7c1f0360f3e0c71eaf346a3b12d10c52f5ee78314d0636de69'
language.cleanup_profiles.commerce_query: 'e45193fa1eb51b444fb1e95fcc9814c57f77f954057f7452a467e6e335b13752'
language.cleanup_profiles.commerce_query: 'bb4984a95beb84c3c6a5d117e44c9f3e91c590ca3c39cd3d018a75fde4c75d21'
language.cleanup_profiles.rag_evidence: 'f5917e594cec7923029354157ccdc926a09637efff0041ea6df1d8002c2bf838'
language.cleanup_profiles.shop_context_fallback: 'fec1fbd755fd88fe685ea1ef88ba4a18c1290ccbfd1347d2ebf059e830175e6c'
search_repair.patterns.accessory_candidate_template: '7f5e3429d0bdca47515c107dbce0da1d5b50720e8a678aedd3e40876444e4403'

View File

@@ -200,6 +200,22 @@ parameters:
- verwende
- nehmen
shop_relation_noise:
- erreicht
- erreichen
- erreiche
- erreichst
- erreichte
- erreichten
- gemessen
- messen
- messe
- misst
- konzipiert
- speziell
- wert
- werte
reference_fillers:
- danach
- damit
@@ -263,6 +279,7 @@ parameters:
- pronouns
- user_instruction_terms
- response_style
- shop_relation_noise
phrase_group_sets:
- user_instruction

View File

@@ -0,0 +1,66 @@
# RetrieX Patch 90 - Chat Header Icon Preservation
## Ziel
Die Icons im Chat-Header bleiben sichtbar, waehrend die Button-Texte weiterhin ueber `config/retriex/chat-messages.yaml` gepflegt werden.
Betroffen sind:
- `Diesen Chat loeschen`
- `Abmelden`
## Ursache
Die Frontend-Konfiguration schreibt Elemente mit `data-chat-message-text` per `textContent`. Wenn dieses Attribut direkt auf einem Button oder Link liegt, wird dessen kompletter Inhalt ersetzt. Dadurch verschwinden vorhandene SVG-Icons.
## Aenderungen
### `templates/chat/index.html.twig`
- `data-chat-message-text` liegt nicht mehr direkt auf dem Clear-Button oder Logout-Link.
- Die konfigurierbaren Texte liegen nun in separaten `<span>`-Elementen innerhalb der Buttons.
- Die SVG-Icons bleiben dadurch Bestandteil des Buttons/Links.
- Fuer die Buttons wird zusaetzlich `data-chat-message-aria-label` gesetzt.
- Die SVGs erhalten `aria-hidden="true"` und `focusable="false"`, damit Screenreader den Button-Text verwenden.
## Bewusst nicht geaendert
- Keine Aenderung an Chat-Security, Admin-Security oder Userverwaltung.
- Keine Aenderung an RAG, Retrieval, Scoring, Ranking, Shop-Matching, SSE oder History-Logik.
- Keine Aenderung an `public/assets/js/base.js`; das bestehende Message-System bleibt unveraendert.
- Keine Aenderung an `config/retriex/chat-messages.yaml`.
## Erwartetes Verhalten
- Der Button `Diesen Chat loeschen` zeigt weiterhin das Papierkorb-Icon plus Text.
- Der Link `Abmelden` zeigt weiterhin das Power-Icon plus Text.
- Beide Texte koennen weiterhin zentral ueber `chat-messages.yaml` angepasst werden.
- Beim Laden der Chat-Messages werden nur die Text-Spans ersetzt, nicht die Icons.
## Lokale Checks
Ausgefuehrt:
```bash
python3 - <<'PY'
from pathlib import Path
s = Path('templates/chat/index.html.twig').read_text()
assert '<button id="clear" class="btn btn-trans" data-chat-message-aria-label="ui.buttons.clear">' in s
assert '<span data-chat-message-text="ui.buttons.clear">Diesen Chat löschen</span>' in s
assert 'id="chat-logout"' in s
assert '<span data-chat-message-text="ui.buttons.logout">Abmelden</span>' in s
assert 'class="bi bi-trash-fill"' in s
assert 'class="bi bi-power"' in s
assert 'id="clear" class="btn btn-trans" data-chat-message-text=' not in s
assert 'id="chat-logout" href="{{ path(\'chat_logout\') }}" class="btn btn-trans"\n data-chat-message-text=' not in s
print('p90 icon preservation checks OK')
PY
```
Ergebnis:
- Template-Strukturcheck OK
- Clear-/Logout-Icons bleiben im DOM
- Konfigurierbare Texte liegen auf separaten Spans
Symfony-Console-Checks muessen in der Zielumgebung mit installiertem `vendor/` ausgefuehrt werden.

View File

@@ -0,0 +1,85 @@
# RetrieX Patch p91 - Shop Query Stopword Profile Fix
## Ziel
Shop-Suchqueries sollen vor dem Store-API-Call konsequenter von reinen Sprach-, Satz- und Relationswoertern bereinigt werden. Der konkrete Regressionsfall war:
- Verlauf: `Testomat 808` / `Indikatortyp 300`
- Preis-Follow-up: `was kostet der indikator`
- Fehlerhafte Shopquery: `testomat 808 erreicht 300 indikator`
- Erwartete Shopquery: `testomat 808 300 indikator`
Das Wort `erreicht` blockierte in der Shop-API Treffer, obwohl die gleiche Query ohne dieses Wort passende Produkte liefert.
## Ursache
Es gab bereits zwei Cleanup-Stufen:
1. `stopword_cleanup`
2. `positive_token_filter`
`erreicht` war jedoch weder in der Shop-Stopword-Liste noch in den blockierten Positive-Filter-Tokens. Danach konnte es ueber das generische `adjacent_variant_patterns`-Pattern als angeblich moegliches Modell-/Variantentoken durchrutschen, weil es zwischen den numerischen Kontexttokens `808` und `300` stand.
## Aenderungen
### `src/Agent/AgentRunner.php`
- Die Shop-Stopword-Bereinigung nutzt jetzt zusaetzlich das zentrale Language-Cleanup-Profil `commerce_query`.
- Der Positive-Token-Filter verwendet dieselben Cleanup-Tokens ebenfalls als Blocklist.
- Dadurch koennen zuvor bereinigte Sprach-/Relationswoerter nicht spaeter durch die Variantenerkennung wieder in die finale Shopquery gelangen.
### `config/retriex/language.yaml`
- Neues Stopword-Group-Set `shop_relation_noise` fuer Shopquery-Sprachrauschen, z. B.:
- `erreicht`
- `gemessen`
- `konzipiert`
- `speziell`
- `wert`
- Das Profil `commerce_query` referenziert diese Gruppe.
### `config/retriex/genre.yaml`
- Die Source-of-Truth-Profilstruktur wurde entsprechend gespiegelt.
### `config/retriex/governance.yaml`
- Der Frozen-Legacy-Hash fuer `language.cleanup_profiles.commerce_query` wurde aktualisiert.
## Erwartetes Verhalten
- `testomat 808 erreicht 300 indikator` wird zu `testomat 808 300 indikator` bereinigt.
- Produkt-/Fachanker bleiben erhalten, z. B.:
- `testomat lab cl`
- `testomat 2000 thcl 100276`
- `chlor select sensor`
## Lokale Checks
Im Patch-Arbeitsbaum ausgefuehrt:
```bash
php -l src/Agent/AgentRunner.php
python3 - <<'PY'
from pathlib import Path
import yaml
for p in ['config/retriex/language.yaml','config/retriex/genre.yaml','config/retriex/governance.yaml']:
yaml.safe_load(Path(p).read_text())
PY
```
Zusatzsimulation:
- `testomat 808 erreicht 300 indikator` => `testomat 808 300 indikator`
- `testomat lab cl` bleibt erhalten
- `testomat 2000 thcl 100276` bleibt erhalten
- `chlor select sensor` bleibt erhalten
## Noch in Nutzerumgebung pruefen
```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

@@ -2426,12 +2426,7 @@ final readonly class AgentRunner
return $shopSearchQuery;
}
$removeTokens = [];
foreach ($this->agentRunnerConfig->getShopQueryStopwordCleanupTerms() as $term) {
foreach ($this->tokenizeShopQueryCandidate($term) as $token) {
$removeTokens[$token] = true;
}
}
$removeTokens = $this->buildShopQueryCleanupStopwordTokenSet();
if ($removeTokens === []) {
return $shopSearchQuery;
@@ -2727,15 +2722,38 @@ final readonly class AgentRunner
*/
private function buildPositiveShopQueryBlockedTokenSet(): array
{
$tokens = [];
return $this->buildShopQueryTokenSet($this->mergeUniqueStrings(
$this->agentRunnerConfig->getShopQueryPositiveTokenFilterBlockedTerms(),
$this->getShopQueryCleanupStopwordTerms()
));
}
foreach ($this->agentRunnerConfig->getShopQueryPositiveTokenFilterBlockedTerms() as $term) {
foreach ($this->tokenizeShopQueryCandidate($term) as $token) {
$tokens[$token] = true;
}
}
/**
* @return array<string, true>
*/
private function buildShopQueryCleanupStopwordTokenSet(): array
{
return $this->buildShopQueryTokenSet($this->getShopQueryCleanupStopwordTerms());
}
return $tokens;
/**
* @return string[]
*/
private function getShopQueryCleanupStopwordTerms(): array
{
$profileTerms = $this->mergeUniqueStrings(
$this->languageCleanupConfig->getStopWordsForProfile('commerce_query'),
$this->languageCleanupConfig->getPhrasesForProfile('commerce_query')
);
$profileTerms = $this->mergeUniqueStrings(
$profileTerms,
$this->languageCleanupConfig->getMetaTermsForProfile('commerce_query')
);
return $this->mergeUniqueStrings(
$this->agentRunnerConfig->getShopQueryStopwordCleanupTerms(),
$profileTerms
);
}
/**

View File

@@ -197,7 +197,7 @@
<div class="card bg-black border-secondary">
<div class="card-body p-0">
<iframe
src="/index.html?admin_test=1"
src="/?admin_test=1"
class="w-100 border-0"
style="height:75vh;"
></iframe>

View File

@@ -29,20 +29,22 @@
<img src="{{ asset('assets/img/logo.svg') }}" style="max-height: 20px;" alt="">
<div class="spacer"></div>
<button id="clear" class="btn btn-trans" data-chat-message-text="ui.buttons.clear">
<button id="clear" class="btn btn-trans" data-chat-message-aria-label="ui.buttons.clear">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-trash-fill"
viewBox="0 0 16 16">
viewBox="0 0 16 16" aria-hidden="true" focusable="false">
<path d="M2.5 1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1H3v9a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V4h.5a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H10a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1zm3 4a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 .5-.5M8 5a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7A.5.5 0 0 1 8 5m3 .5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 1 0"/>
</svg>
<span data-chat-message-text="ui.buttons.clear">Diesen Chat löschen</span>
</button>
<a id="chat-logout" href="{{ path('chat_logout') }}" class="btn btn-trans"
data-chat-message-text="ui.buttons.logout">
data-chat-message-aria-label="ui.buttons.logout">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-power"
viewBox="0 0 16 16">
viewBox="0 0 16 16" aria-hidden="true" focusable="false">
<path d="M7.5 1v7h1V1z"/>
<path d="M3 8.812a5 5 0 0 1 2.578-4.375l-.485-.874A6 6 0 1 0 11 3.616l-.501.865A5 5 0 1 1 3 8.812"/>
</svg>
Abmelden</a>
<span data-chat-message-text="ui.buttons.logout">Abmelden</span>
</a>
</div>
<div id="ai-cloud" class="ai-cloud d-none"></div>
<div id="chat" class="chat"></div>