p91
This commit is contained in:
@@ -1924,6 +1924,7 @@ parameters:
|
|||||||
- pronouns
|
- pronouns
|
||||||
- user_instruction_terms
|
- user_instruction_terms
|
||||||
- response_style
|
- response_style
|
||||||
|
- shop_relation_noise
|
||||||
phrase_group_sets:
|
phrase_group_sets:
|
||||||
- user_instruction
|
- user_instruction
|
||||||
rag_evidence:
|
rag_evidence:
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ parameters:
|
|||||||
intent.sales.objection_signals: 'dea7269eaa22d3e3a5ef2cc8d2d012b3c089e0c69d141df2c1e1e118fec6a491'
|
intent.sales.objection_signals: 'dea7269eaa22d3e3a5ef2cc8d2d012b3c089e0c69d141df2c1e1e118fec6a491'
|
||||||
intent.sales.roi_signals: '88101a34b5e63a938055ab89bde1f73ce3bf8698f6d2793018145cdd7ae814da'
|
intent.sales.roi_signals: '88101a34b5e63a938055ab89bde1f73ce3bf8698f6d2793018145cdd7ae814da'
|
||||||
intent.sales.sales_signals: '7269ee14955e4a7c1f0360f3e0c71eaf346a3b12d10c52f5ee78314d0636de69'
|
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.rag_evidence: 'f5917e594cec7923029354157ccdc926a09637efff0041ea6df1d8002c2bf838'
|
||||||
language.cleanup_profiles.shop_context_fallback: 'fec1fbd755fd88fe685ea1ef88ba4a18c1290ccbfd1347d2ebf059e830175e6c'
|
language.cleanup_profiles.shop_context_fallback: 'fec1fbd755fd88fe685ea1ef88ba4a18c1290ccbfd1347d2ebf059e830175e6c'
|
||||||
search_repair.patterns.accessory_candidate_template: '7f5e3429d0bdca47515c107dbce0da1d5b50720e8a678aedd3e40876444e4403'
|
search_repair.patterns.accessory_candidate_template: '7f5e3429d0bdca47515c107dbce0da1d5b50720e8a678aedd3e40876444e4403'
|
||||||
|
|||||||
@@ -200,6 +200,22 @@ parameters:
|
|||||||
- verwende
|
- verwende
|
||||||
- nehmen
|
- nehmen
|
||||||
|
|
||||||
|
shop_relation_noise:
|
||||||
|
- erreicht
|
||||||
|
- erreichen
|
||||||
|
- erreiche
|
||||||
|
- erreichst
|
||||||
|
- erreichte
|
||||||
|
- erreichten
|
||||||
|
- gemessen
|
||||||
|
- messen
|
||||||
|
- messe
|
||||||
|
- misst
|
||||||
|
- konzipiert
|
||||||
|
- speziell
|
||||||
|
- wert
|
||||||
|
- werte
|
||||||
|
|
||||||
reference_fillers:
|
reference_fillers:
|
||||||
- danach
|
- danach
|
||||||
- damit
|
- damit
|
||||||
@@ -263,6 +279,7 @@ parameters:
|
|||||||
- pronouns
|
- pronouns
|
||||||
- user_instruction_terms
|
- user_instruction_terms
|
||||||
- response_style
|
- response_style
|
||||||
|
- shop_relation_noise
|
||||||
phrase_group_sets:
|
phrase_group_sets:
|
||||||
- user_instruction
|
- user_instruction
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -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
|
||||||
|
```
|
||||||
@@ -2426,12 +2426,7 @@ final readonly class AgentRunner
|
|||||||
return $shopSearchQuery;
|
return $shopSearchQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
$removeTokens = [];
|
$removeTokens = $this->buildShopQueryCleanupStopwordTokenSet();
|
||||||
foreach ($this->agentRunnerConfig->getShopQueryStopwordCleanupTerms() as $term) {
|
|
||||||
foreach ($this->tokenizeShopQueryCandidate($term) as $token) {
|
|
||||||
$removeTokens[$token] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($removeTokens === []) {
|
if ($removeTokens === []) {
|
||||||
return $shopSearchQuery;
|
return $shopSearchQuery;
|
||||||
@@ -2727,15 +2722,38 @@ final readonly class AgentRunner
|
|||||||
*/
|
*/
|
||||||
private function buildPositiveShopQueryBlockedTokenSet(): array
|
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) {
|
* @return array<string, true>
|
||||||
$tokens[$token] = 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
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -197,7 +197,7 @@
|
|||||||
<div class="card bg-black border-secondary">
|
<div class="card bg-black border-secondary">
|
||||||
<div class="card-body p-0">
|
<div class="card-body p-0">
|
||||||
<iframe
|
<iframe
|
||||||
src="/index.html?admin_test=1"
|
src="/?admin_test=1"
|
||||||
class="w-100 border-0"
|
class="w-100 border-0"
|
||||||
style="height:75vh;"
|
style="height:75vh;"
|
||||||
></iframe>
|
></iframe>
|
||||||
|
|||||||
@@ -29,20 +29,22 @@
|
|||||||
<img src="{{ asset('assets/img/logo.svg') }}" style="max-height: 20px;" alt="">
|
<img src="{{ asset('assets/img/logo.svg') }}" style="max-height: 20px;" alt="">
|
||||||
<div class="spacer"></div>
|
<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"
|
<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"/>
|
<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>
|
</svg>
|
||||||
|
<span data-chat-message-text="ui.buttons.clear">Diesen Chat löschen</span>
|
||||||
</button>
|
</button>
|
||||||
<a id="chat-logout" href="{{ path('chat_logout') }}" class="btn btn-trans"
|
<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"
|
<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="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"/>
|
<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>
|
</svg>
|
||||||
Abmelden</a>
|
<span data-chat-message-text="ui.buttons.logout">Abmelden</span>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div id="ai-cloud" class="ai-cloud d-none"></div>
|
<div id="ai-cloud" class="ai-cloud d-none"></div>
|
||||||
<div id="chat" class="chat"></div>
|
<div id="chat" class="chat"></div>
|
||||||
|
|||||||
Reference in New Issue
Block a user