patch 20j
This commit is contained in:
@@ -0,0 +1,75 @@
|
|||||||
|
# RetrieX Patch p20j - Standalone Shop Optimizer Context Guard
|
||||||
|
|
||||||
|
## Ziel
|
||||||
|
Verhindert, dass die LLM-gestützte Shop-Query-Optimierung bei eigenständigen neuen Shop-Suchen alten oder nicht im aktuellen Prompt enthaltenen Kontext in die Suchquery übernimmt.
|
||||||
|
|
||||||
|
## Reproduzierter Fehler
|
||||||
|
Nach vorherigen Testomat-808-/Indikator-Kontexten wurde bei der neuen Anfrage:
|
||||||
|
|
||||||
|
```text
|
||||||
|
zeige mir Anschlusskabel für pH/Redox
|
||||||
|
```
|
||||||
|
|
||||||
|
als gesendete Shop-Suchquery fälschlich erzeugt:
|
||||||
|
|
||||||
|
```text
|
||||||
|
testomat 808
|
||||||
|
```
|
||||||
|
|
||||||
|
Dadurch lieferte der Shop Testomat-808- und Indikator-Produkte statt Anschlusskabeln für pH/Redox.
|
||||||
|
|
||||||
|
## Ursache
|
||||||
|
Der Shop-Router selbst war nicht mehr das Problem: Shop wurde korrekt angefragt. Der Fehler entstand im Ausgang der LLM-Shop-Query-Optimierung. Bei einem eigenständigen neuen Prompt ohne zulässigen History-Kontext durfte der Optimizer eine Query erzeugen, die keine Token-Überschneidung mit dem aktuellen Prompt hatte und sogar eine Modellnummer enthielt, die im aktuellen Prompt nicht vorkam.
|
||||||
|
|
||||||
|
## Änderung
|
||||||
|
Geändert wurde nur:
|
||||||
|
|
||||||
|
- `src/Agent/AgentRunner.php`
|
||||||
|
|
||||||
|
Neu abgesichert:
|
||||||
|
|
||||||
|
- Bei eigenständigen Shop-Suchen ohne History-Kontext wird die optimierte Query validiert.
|
||||||
|
- Der Optimizer darf Suchbegriffe entfernen oder verdichten.
|
||||||
|
- Er darf aber keine Modell-/Artikelnummern hinzufügen, die nicht im aktuellen Prompt stehen.
|
||||||
|
- Wenn die optimierte Query keinerlei Token-Überschneidung mit dem aktuellen Prompt hat, wird sie als Kontextsubstitution verworfen.
|
||||||
|
- In diesem Fall fällt RetrieX auf den aktuellen Prompt zurück; der vorhandene CommerceQueryParser bereinigt ihn anschließend regulär.
|
||||||
|
|
||||||
|
## Erwartung
|
||||||
|
|
||||||
|
```text
|
||||||
|
zeige mir Anschlusskabel für pH/Redox
|
||||||
|
```
|
||||||
|
|
||||||
|
soll nicht mehr zu `testomat 808` optimiert werden. Erwartbar ist eine Shop-Suchquery im Bereich:
|
||||||
|
|
||||||
|
```text
|
||||||
|
anschlusskabel ph redox
|
||||||
|
```
|
||||||
|
|
||||||
|
oder ein sauber aus dem aktuellen Prompt abgeleiteter äquivalenter Suchtext.
|
||||||
|
|
||||||
|
Bestehende Follow-ups bleiben erlaubt:
|
||||||
|
|
||||||
|
```text
|
||||||
|
die tabelle mit preisen
|
||||||
|
```
|
||||||
|
|
||||||
|
nutzt weiterhin History-Kontext, weil es explizit referenziell ist.
|
||||||
|
|
||||||
|
## Prüfungen lokal
|
||||||
|
|
||||||
|
- `php -l src/Agent/AgentRunner.php` OK
|
||||||
|
|
||||||
|
Symfony-Console-Checks konnten in der ChatGPT-Umgebung nicht vollständig ausgeführt werden, weil die Laufzeit-/Composer-Dependencies nicht installiert sind.
|
||||||
|
|
||||||
|
## Nach dem Einspielen prüfen
|
||||||
|
|
||||||
|
```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.
|
||||||
@@ -1469,6 +1469,15 @@ final readonly class AgentRunner
|
|||||||
return $optimizedShopQuery;
|
return $optimizedShopQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->standaloneOptimizedShopQueryIntroducesUnsupportedContext($prompt, $optimizedShopQuery)) {
|
||||||
|
$this->agentLogger->info('Ignored optimized shop query because it introduced unsupported standalone context', [
|
||||||
|
'prompt' => $prompt,
|
||||||
|
'optimizedShopQuery' => $optimizedShopQuery,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $prompt;
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->extractFirstTestomatModelAnchor($prompt) === '') {
|
if ($this->extractFirstTestomatModelAnchor($prompt) === '') {
|
||||||
return $optimizedShopQuery;
|
return $optimizedShopQuery;
|
||||||
}
|
}
|
||||||
@@ -1489,6 +1498,39 @@ final readonly class AgentRunner
|
|||||||
return $prompt;
|
return $prompt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function standaloneOptimizedShopQueryIntroducesUnsupportedContext(
|
||||||
|
string $prompt,
|
||||||
|
string $optimizedShopQuery
|
||||||
|
): bool {
|
||||||
|
$promptTokens = array_fill_keys($this->tokenizeShopQueryCandidate($prompt), true);
|
||||||
|
$optimizedTokens = $this->tokenizeShopQueryCandidate($optimizedShopQuery);
|
||||||
|
|
||||||
|
if ($optimizedTokens === [] || $promptTokens === []) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$overlap = 0;
|
||||||
|
|
||||||
|
foreach ($optimizedTokens as $token) {
|
||||||
|
if (isset($promptTokens[$token])) {
|
||||||
|
$overlap++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A standalone query optimizer may remove words, but it must not add
|
||||||
|
// model numbers or article-like numbers that are absent from the
|
||||||
|
// current user input. Otherwise old context can leak into new shop
|
||||||
|
// searches, for example "Anschlusskabel pH/Redox" -> "testomat 808".
|
||||||
|
if (preg_match('/\d/u', $token) === 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the optimized query has no token overlap with the current standalone
|
||||||
|
// input, it is not a safe optimization but a context substitution.
|
||||||
|
return $overlap === 0 && !$this->isMetaOnlyShopQuery($prompt);
|
||||||
|
}
|
||||||
|
|
||||||
private function resolveShopSearchQuery(
|
private function resolveShopSearchQuery(
|
||||||
string $prompt,
|
string $prompt,
|
||||||
string $optimizedShopQuery,
|
string $optimizedShopQuery,
|
||||||
|
|||||||
Reference in New Issue
Block a user