patch 20n
This commit is contained in:
3242
AgentRunner.php
Normal file
3242
AgentRunner.php
Normal file
File diff suppressed because it is too large
Load Diff
3199
AgentRunner.php.before_p20n
Normal file
3199
AgentRunner.php.before_p20n
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,70 @@
|
||||
# RetrieX Patch p20k - Final Standalone Shop Query Guard
|
||||
|
||||
## Ziel
|
||||
Behebt den Fall, dass eine neue eigenständige Shop-Anfrage wie:
|
||||
|
||||
```text
|
||||
zeige mir Anschlusskabel für pH/Redox
|
||||
```
|
||||
|
||||
nach der Shop-Query-Optimierung fälschlich als alte Kontext-Query wie:
|
||||
|
||||
```text
|
||||
testomat 808 indikator
|
||||
```
|
||||
|
||||
an Shop-Suche und UI-Meta weitergegeben wird.
|
||||
|
||||
## Ursache
|
||||
Der bisherige Guard prüfte den Optimizer-Ausgang zwar im Optimizer-/Resolve-Pfad, aber nicht final direkt vor Preview und Shop-Suche. Wenn später dennoch eine kontextfremde Query in `$shopSearchQuery` landete, wurde sie ungeprüft an `buildSearchQueryPreview()` und `searchShop()` weitergereicht.
|
||||
|
||||
## Änderung
|
||||
Nur `src/Agent/AgentRunner.php` wurde geändert.
|
||||
|
||||
Neu:
|
||||
|
||||
- finale Validierung direkt nach `resolveShopSearchQuery()`
|
||||
- vor `buildSearchQueryPreview()` und `searchShop()`
|
||||
- Wiederverwendung der bestehenden Standalone-Guardlogik
|
||||
- bei erkannter Kontextverschmutzung wird die Query auf den aktuellen Routing-Prompt zurückgesetzt
|
||||
- `$optimizedShopQuery` wird geleert, damit UI/Meta nicht weiter „optimiert“ für eine verworfene Query anzeigen
|
||||
|
||||
## Erwartung
|
||||
|
||||
```text
|
||||
zeige mir Anschlusskabel für pH/Redox
|
||||
```
|
||||
|
||||
soll nicht mehr als `testomat 808 indikator` gesucht werden, sondern auf Basis des aktuellen Prompts, also sinngemäß:
|
||||
|
||||
```text
|
||||
anschlusskabel ph redox
|
||||
```
|
||||
|
||||
Referenzielle Follow-ups wie:
|
||||
|
||||
```text
|
||||
die tabelle mit preisen
|
||||
was kostet der indikator
|
||||
```
|
||||
|
||||
dürfen weiterhin Kontext verwenden.
|
||||
|
||||
## Checks
|
||||
Lokal möglich:
|
||||
|
||||
```bash
|
||||
php -l src/Agent/AgentRunner.php
|
||||
```
|
||||
|
||||
Pflichtchecks nach Einspielen:
|
||||
|
||||
```bash
|
||||
bin/console cache:clear
|
||||
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
|
||||
```
|
||||
|
||||
Falls OPcache/PHP-FPM aktiv ist: PHP-FPM bzw. Container neu laden.
|
||||
@@ -0,0 +1,61 @@
|
||||
# RetrieX Patch p20l - Original Prompt Shop History Guard
|
||||
|
||||
## Ziel
|
||||
Fix fuer die Regression, bei der eine neue Standalone-Shopfrage wie:
|
||||
|
||||
```text
|
||||
zeige mir Anschlusskabel fuer pH/Redox
|
||||
```
|
||||
|
||||
faelschlich mit altem Verlaufskontext optimiert wurde und dadurch als Shop-Suchquery z. B. `testomat 808 indikator` erzeugte.
|
||||
|
||||
## Ursache
|
||||
Der bisherige Guard pruefte die finale Shop-Suchquery gegen den `routingPrompt`. Dieser kann durch LLM-/Fuzzy-Normalisierung leicht vom Original abweichen. Dadurch konnte eine eigentlich neue Standalone-Anfrage intern wie eine referenzielle Anfrage behandelt werden, und alter Commerce-Verlauf durfte in Optimizer/Query einfliessen.
|
||||
|
||||
Besonders kritisch: Die Entscheidung, ob Verlauf fuer die Shop-Query benutzt werden darf, darf nicht von einer normalisierten Variante abhaengen, sondern vom originalen Nutzereingabetext.
|
||||
|
||||
## Aenderung
|
||||
Nur `src/Agent/AgentRunner.php` wurde geaendert.
|
||||
|
||||
1. `resolveShopQueryHistoryContext()` verwendet jetzt den `originalPrompt` als Autoritaet fuer die Entscheidung, ob Commerce-History genutzt werden darf.
|
||||
2. `guardFinalStandaloneShopSearchQuery()` prueft finale Shop-Suchqueries ebenfalls gegen den `originalPrompt`.
|
||||
3. Wenn eine Standalone-Query fremden Kontext einfuehrt, faellt RetrieX auf den aktuellen `routingPrompt` zurueck, nicht auf alten Verlaufskontext.
|
||||
|
||||
## Erwartetes Verhalten
|
||||
|
||||
```text
|
||||
zeige mir Anschlusskabel fuer pH/Redox
|
||||
```
|
||||
|
||||
Erwartete Suchquery sinngemaess:
|
||||
|
||||
```text
|
||||
anschlusskabel ph redox
|
||||
```
|
||||
|
||||
Nicht mehr:
|
||||
|
||||
```text
|
||||
testomat 808 indikator
|
||||
```
|
||||
|
||||
Weiterhin erlaubt:
|
||||
|
||||
```text
|
||||
welche grenzwerte kann der testomat 808 messen
|
||||
die tabelle mit preisen
|
||||
```
|
||||
|
||||
Dieser Follow-up bleibt referenziell und darf den Verlauf fuer `testomat 808 indikator` nutzen.
|
||||
|
||||
## Pflichtchecks nach Einspielen
|
||||
|
||||
```bash
|
||||
bin/console cache:clear
|
||||
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
|
||||
```
|
||||
|
||||
Bei aktivem OPcache/PHP-FPM bitte PHP-FPM bzw. Container neu laden.
|
||||
@@ -0,0 +1,75 @@
|
||||
# RetrieX Patch p20m – Standalone Shop History Authority Fix
|
||||
|
||||
## Ziel
|
||||
Dieser Patch behebt den Fall, dass eine neue eigenständige Shop-Anfrage wie:
|
||||
|
||||
```text
|
||||
zeige mir Anschlusskabel für pH/Redox
|
||||
```
|
||||
|
||||
trotz fehlender Ähnlichkeit zum aktuellen Prompt mit altem Verlaufskontext zu einer falschen Shop-Suchquery wie:
|
||||
|
||||
```text
|
||||
testomat 808 indikator
|
||||
```
|
||||
|
||||
optimiert wurde.
|
||||
|
||||
## Ursache
|
||||
Die Entscheidung, ob Chatverlauf für die Shop-Query-Optimierung verwendet werden darf, wurde im aktiven Codepfad weiterhin anhand des normalisierten/routing-orientierten Prompts getroffen. Dieser Prompt ist für Intent-Erkennung hilfreich, darf aber nicht die Autorität für History-Carry-over sein.
|
||||
|
||||
Zusätzlich konnte der fallback-basierte Query-Resolver nach einer Optimierung nicht konsequent zwischen aktueller Standalone-Anfrage und referenzieller Folgefrage unterscheiden.
|
||||
|
||||
## Änderung
|
||||
Geändert wurde nur:
|
||||
|
||||
- `src/Agent/AgentRunner.php`
|
||||
|
||||
Konkret:
|
||||
|
||||
1. `resolveShopQueryHistoryContext()` entscheidet jetzt anhand des unveränderten `originalPrompt`, ob Shop-History benutzt werden darf.
|
||||
2. `resolveShopSearchQuery()` nutzt den `originalPrompt` als Autorität für referenzielle History-Fallbacks.
|
||||
3. Der normalisierte `routingPrompt` bleibt als Current-Prompt-Fallback erhalten, damit Tippfehlerkorrektur/Normalisierung weiterhin für die aktuelle Suchanfrage genutzt werden kann.
|
||||
4. Der finale Standalone-Guard prüft gegen den `originalPrompt`, nicht gegen den normalisierten Routing-Prompt.
|
||||
|
||||
## Erwartetes Verhalten
|
||||
|
||||
```text
|
||||
zeige mir Anschlusskabel für pH/Redox
|
||||
```
|
||||
|
||||
muss eine Query wie:
|
||||
|
||||
```text
|
||||
anschlusskabel ph redox
|
||||
```
|
||||
|
||||
erzeugen, nicht mehr:
|
||||
|
||||
```text
|
||||
testomat 808 indikator
|
||||
```
|
||||
|
||||
Referenzielle Follow-ups wie:
|
||||
|
||||
```text
|
||||
die tabelle mit preisen
|
||||
```
|
||||
|
||||
behalten weiterhin History-Nutzung.
|
||||
|
||||
## Prüfungen lokal
|
||||
|
||||
- `php -l src/Agent/AgentRunner.php` OK
|
||||
|
||||
Symfony-Console-Checks müssen in der Zielumgebung ausgeführt werden:
|
||||
|
||||
```bash
|
||||
bin/console cache:clear
|
||||
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
|
||||
```
|
||||
|
||||
Bei OPcache/PHP-FPM bitte PHP-FPM bzw. Container neu laden.
|
||||
@@ -0,0 +1,70 @@
|
||||
# RetrieX Patch 20n - Deterministic Standalone Shop Query Fix
|
||||
|
||||
## Purpose
|
||||
Fixes the persistent context leak where a new standalone shop query such as:
|
||||
|
||||
`zeige mir Anschlusskabel für pH/Redox`
|
||||
|
||||
was incorrectly sent to the shop as:
|
||||
|
||||
`testomat 808 indikator`
|
||||
|
||||
## Root cause
|
||||
The issue was not the shop router itself. The route was already commerce/shop. The unsafe part was that standalone shop queries could still pass through the LLM shop-query optimizer. If the optimizer or later query handling revived previous conversation context, an old Testomat/Indikator topic could become the sent Shopware query even though the current prompt had no overlap with it.
|
||||
|
||||
## Fix
|
||||
For non-referential standalone shop queries with no allowed shop-query history context:
|
||||
|
||||
- Skip the LLM shop-query optimizer.
|
||||
- Use the normalized/current prompt deterministically as the shop search source.
|
||||
- Let `ShopSearchService` / `CommerceQueryParser` build the final Store API search text from the current prompt only.
|
||||
- Keep LLM/history optimization enabled for referential follow-ups such as `die tabelle mit preisen` or `was kostet der indikator`.
|
||||
|
||||
## Changed file
|
||||
|
||||
- `src/Agent/AgentRunner.php`
|
||||
|
||||
## Expected behavior
|
||||
|
||||
### Standalone shop query
|
||||
Input:
|
||||
|
||||
`zeige mir Anschlusskabel für pH/Redox`
|
||||
|
||||
Expected sent query:
|
||||
|
||||
`anschlusskabel ph redox` or equivalent current-prompt-only query.
|
||||
|
||||
Must not become:
|
||||
|
||||
`testomat 808 indikator`
|
||||
|
||||
### Explicit product query
|
||||
Input:
|
||||
|
||||
`shop testomat 808`
|
||||
|
||||
Expected sent query:
|
||||
|
||||
`testomat 808`
|
||||
|
||||
### Referential follow-up
|
||||
Input after a Testomat 808 indicator table:
|
||||
|
||||
`die tabelle mit preisen`
|
||||
|
||||
Expected behavior:
|
||||
|
||||
History is still allowed and may resolve to `testomat 808 indikator`.
|
||||
|
||||
## Checks to run after applying
|
||||
|
||||
```bash
|
||||
bin/console cache:clear
|
||||
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
|
||||
```
|
||||
|
||||
If OPcache/PHP-FPM is active, reload PHP-FPM or the container after applying.
|
||||
@@ -214,7 +214,7 @@ final readonly class AgentRunner
|
||||
|
||||
$commerceHistoryContext = $this->buildCommerceHistoryContext($userId, $requestContextHint);
|
||||
$shopQueryHistoryContext = $this->resolveShopQueryHistoryContext(
|
||||
prompt: $routingPrompt,
|
||||
prompt: $originalPrompt,
|
||||
commerceHistoryContext: $commerceHistoryContext
|
||||
);
|
||||
|
||||
@@ -227,6 +227,7 @@ final readonly class AgentRunner
|
||||
'userId' => $userId,
|
||||
'prompt' => $prompt,
|
||||
'routingPrompt' => $routingPrompt,
|
||||
'originalPrompt' => $originalPrompt,
|
||||
'commerceHistoryContextLength' => mb_strlen($commerceHistoryContext),
|
||||
]);
|
||||
}
|
||||
@@ -238,12 +239,32 @@ final readonly class AgentRunner
|
||||
);
|
||||
|
||||
$shopSearchQuery = $this->resolveShopSearchQuery(
|
||||
prompt: $routingPrompt,
|
||||
prompt: $originalPrompt,
|
||||
optimizedShopQuery: $optimizedShopQuery,
|
||||
commerceHistoryContext: $shopQueryHistoryContext,
|
||||
userId: $userId
|
||||
userId: $userId,
|
||||
currentPromptFallback: $routingPrompt
|
||||
);
|
||||
|
||||
$guardedShopSearchQuery = $this->guardFinalStandaloneShopSearchQuery(
|
||||
prompt: $originalPrompt,
|
||||
shopSearchQuery: $shopSearchQuery
|
||||
);
|
||||
|
||||
if ($guardedShopSearchQuery !== $shopSearchQuery) {
|
||||
$this->agentLogger->info('Replaced standalone shop search query after final guard', [
|
||||
'userId' => $userId,
|
||||
'prompt' => $prompt,
|
||||
'routingPrompt' => $routingPrompt,
|
||||
'optimizedShopQuery' => $optimizedShopQuery,
|
||||
'unsafeShopSearchQuery' => $shopSearchQuery,
|
||||
'guardedShopSearchQuery' => $guardedShopSearchQuery,
|
||||
]);
|
||||
|
||||
$shopSearchQuery = $guardedShopSearchQuery;
|
||||
$optimizedShopQuery = '';
|
||||
}
|
||||
|
||||
if ($shopSearchQuery === '') {
|
||||
$this->agentLogger->info('Commerce search skipped because no concrete shop query could be resolved', [
|
||||
'userId' => $userId,
|
||||
@@ -1498,6 +1519,23 @@ final readonly class AgentRunner
|
||||
return $prompt;
|
||||
}
|
||||
|
||||
private function guardFinalStandaloneShopSearchQuery(string $prompt, string $shopSearchQuery): string
|
||||
{
|
||||
$shopSearchQuery = trim($shopSearchQuery);
|
||||
|
||||
if ($shopSearchQuery === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
$guardedQuery = $this->guardStandaloneOptimizedShopQuery($prompt, $shopSearchQuery);
|
||||
|
||||
if ($guardedQuery !== $shopSearchQuery) {
|
||||
return $guardedQuery;
|
||||
}
|
||||
|
||||
return $shopSearchQuery;
|
||||
}
|
||||
|
||||
private function standaloneOptimizedShopQueryIntroducesUnsupportedContext(
|
||||
string $prompt,
|
||||
string $optimizedShopQuery
|
||||
@@ -1535,7 +1573,8 @@ final readonly class AgentRunner
|
||||
string $prompt,
|
||||
string $optimizedShopQuery,
|
||||
string $commerceHistoryContext,
|
||||
string $userId
|
||||
string $userId,
|
||||
string $currentPromptFallback = ''
|
||||
): string {
|
||||
if ($this->isCommercialTableFollowUpPrompt($prompt)) {
|
||||
foreach ($this->buildCommercialTableFollowUpContextCandidates($commerceHistoryContext, $userId) as $contextCandidate) {
|
||||
@@ -1551,6 +1590,11 @@ final readonly class AgentRunner
|
||||
return $this->guardStandaloneOptimizedShopQuery($prompt, $optimizedShopQuery);
|
||||
}
|
||||
|
||||
$currentPromptFallback = trim($currentPromptFallback);
|
||||
if ($currentPromptFallback !== '' && !$this->isMetaOnlyShopQuery($currentPromptFallback)) {
|
||||
return $currentPromptFallback;
|
||||
}
|
||||
|
||||
if (!$this->isMetaOnlyShopQuery($prompt)) {
|
||||
return $prompt;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user