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);
|
$commerceHistoryContext = $this->buildCommerceHistoryContext($userId, $requestContextHint);
|
||||||
$shopQueryHistoryContext = $this->resolveShopQueryHistoryContext(
|
$shopQueryHistoryContext = $this->resolveShopQueryHistoryContext(
|
||||||
prompt: $routingPrompt,
|
prompt: $originalPrompt,
|
||||||
commerceHistoryContext: $commerceHistoryContext
|
commerceHistoryContext: $commerceHistoryContext
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -227,6 +227,7 @@ final readonly class AgentRunner
|
|||||||
'userId' => $userId,
|
'userId' => $userId,
|
||||||
'prompt' => $prompt,
|
'prompt' => $prompt,
|
||||||
'routingPrompt' => $routingPrompt,
|
'routingPrompt' => $routingPrompt,
|
||||||
|
'originalPrompt' => $originalPrompt,
|
||||||
'commerceHistoryContextLength' => mb_strlen($commerceHistoryContext),
|
'commerceHistoryContextLength' => mb_strlen($commerceHistoryContext),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -238,12 +239,32 @@ final readonly class AgentRunner
|
|||||||
);
|
);
|
||||||
|
|
||||||
$shopSearchQuery = $this->resolveShopSearchQuery(
|
$shopSearchQuery = $this->resolveShopSearchQuery(
|
||||||
prompt: $routingPrompt,
|
prompt: $originalPrompt,
|
||||||
optimizedShopQuery: $optimizedShopQuery,
|
optimizedShopQuery: $optimizedShopQuery,
|
||||||
commerceHistoryContext: $shopQueryHistoryContext,
|
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 === '') {
|
if ($shopSearchQuery === '') {
|
||||||
$this->agentLogger->info('Commerce search skipped because no concrete shop query could be resolved', [
|
$this->agentLogger->info('Commerce search skipped because no concrete shop query could be resolved', [
|
||||||
'userId' => $userId,
|
'userId' => $userId,
|
||||||
@@ -1498,6 +1519,23 @@ final readonly class AgentRunner
|
|||||||
return $prompt;
|
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(
|
private function standaloneOptimizedShopQueryIntroducesUnsupportedContext(
|
||||||
string $prompt,
|
string $prompt,
|
||||||
string $optimizedShopQuery
|
string $optimizedShopQuery
|
||||||
@@ -1535,7 +1573,8 @@ final readonly class AgentRunner
|
|||||||
string $prompt,
|
string $prompt,
|
||||||
string $optimizedShopQuery,
|
string $optimizedShopQuery,
|
||||||
string $commerceHistoryContext,
|
string $commerceHistoryContext,
|
||||||
string $userId
|
string $userId,
|
||||||
|
string $currentPromptFallback = ''
|
||||||
): string {
|
): string {
|
||||||
if ($this->isCommercialTableFollowUpPrompt($prompt)) {
|
if ($this->isCommercialTableFollowUpPrompt($prompt)) {
|
||||||
foreach ($this->buildCommercialTableFollowUpContextCandidates($commerceHistoryContext, $userId) as $contextCandidate) {
|
foreach ($this->buildCommercialTableFollowUpContextCandidates($commerceHistoryContext, $userId) as $contextCandidate) {
|
||||||
@@ -1551,6 +1590,11 @@ final readonly class AgentRunner
|
|||||||
return $this->guardStandaloneOptimizedShopQuery($prompt, $optimizedShopQuery);
|
return $this->guardStandaloneOptimizedShopQuery($prompt, $optimizedShopQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$currentPromptFallback = trim($currentPromptFallback);
|
||||||
|
if ($currentPromptFallback !== '' && !$this->isMetaOnlyShopQuery($currentPromptFallback)) {
|
||||||
|
return $currentPromptFallback;
|
||||||
|
}
|
||||||
|
|
||||||
if (!$this->isMetaOnlyShopQuery($prompt)) {
|
if (!$this->isMetaOnlyShopQuery($prompt)) {
|
||||||
return $prompt;
|
return $prompt;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user