patch 20p

This commit is contained in:
team 1
2026-05-03 17:12:57 +02:00
parent 814510456b
commit 1a24590863
5 changed files with 108 additions and 2 deletions

View File

@@ -0,0 +1,55 @@
# RetrieX Patch p20p - History Product Anchor Follow-up Fix
## Ziel
Behebt den Fall, dass kurze Shop-Follow-ups wie `suche im shop` den Produkt-/Modellanker aus dem vorherigen fachlichen Turn nicht mehr sicher übernehmen.
Beispiel:
1. `welche grenzwerte kann der testomat 2000 thcl messen`
2. `suche im shop`
Vorher konnte die Shop-Suche mit `keine Suchquery` enden, obwohl der vorherige Turn einen klaren Produktanker enthält.
## Ursache
Die bisherige Shop-Follow-up-Auflösung nutzte primär extrahierte `Question:`-Zeilen. Wenn diese Extraktion nicht greift oder der stabile Produktanker nur in der Antwort bzw. im gesamten letzten Turn steht, wurde keine belastbare Shopquery erzeugt.
Außerdem erkannte der Testomat-Modellanker bisher numerische Testomat-Modelle ohne nachgestellten Varianten-/Parameter-Suffix. Dadurch wurde `Testomat 2000 THCL` nicht als kompletter Modellanker erfasst.
## Änderung
- `AgentRunner::extractContextualShopSearchQuery()` wurde gehärtet.
- Wenn aus den letzten Nutzerfragen keine Query entsteht, werden die neuesten History-Turns selbst geprüft.
- Pro Turn wird zuerst die Nutzerfrage ausgewertet.
- Danach wird ein expliziter Testomat-Modellanker aus dem gesamten Turn extrahiert.
- Das Modellanker-Pattern erlaubt nun numerische Testomat-Modelle mit Suffix, z. B. `Testomat 2000 THCL`.
## Dateien
- `src/Agent/AgentRunner.php`
- `config/retriex/agent.yaml`
## Erwartung
`suche im shop` nach einem technischen Turn zu `Testomat 2000 THCL` soll eine Shopquery wie `testomat 2000 thcl` ableiten, statt mit `keine Suchquery` abzubrechen.
Der Fix ist generisch für History-Produktanker und enthält keine harte 808- oder THCL-Sonderquery.
## Prüfungen lokal
- `php -l src/Agent/AgentRunner.php`: OK
- `config/retriex/agent.yaml` mit Python YAML Parser: OK
- Regex-Smoke-Test für `Testomat 2000 THCL`, `Testomat 808`, `Testomat EVO TH`: OK
## 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
```
PHP-FPM/OPcache danach neu laden, falls aktiv.

View File

@@ -189,7 +189,7 @@ parameters:
history_turn_split_pattern: '/(?=^Question:\s)/m'
history_question_strip_pattern: '/^Question:\s*.*(?:\R|$)/u'
reference_anchor:
testomat_model_pattern: '/\bTestomat(?:®)?\s+(?:\d{3,4}|EVO(?:\s+[A-Z]{2,6})?|ECO(?:[-\s]?(?:PLUS|C))?|DUO(?:\s+\d{3,4})?|LAB(?:\s+[A-Z]{2,6})?)\b/iu'
testomat_model_pattern: '/\bTestomat(?:®)?\s+(?:\d{3,4}(?:\s+[A-Z]{2,8})?|EVO(?:\s+[A-Z]{2,6})?|ECO(?:[-\s]?(?:PLUS|C))?|DUO(?:\s+\d{3,4})?|LAB(?:\s+[A-Z]{2,6})?)\b/iu'
hardness_value_pattern: '/\b\d+(?:[,.]\d+)?\s*°\s*dH\b/iu'
messages:

View File

@@ -56,11 +56,14 @@ parameters:
- davon
- stattdessen
- bitte
- preiswerte
- gern
- eine
- größer
- würde
- ich
- gerne
- mein
- größer
- zeige
- zeig
@@ -80,6 +83,7 @@ parameters:
- welches
- welchen
- sind
- zur
- ist
- geeignet
- geeigent

View File

@@ -58,6 +58,10 @@ parameters:
- stattdessen
- bitte
- gern
- preiswerte
- zur
- mein
- eine
- würde
- ich
- gerne

View File

@@ -1847,14 +1847,57 @@ final readonly class AgentRunner
$contextQuery = $this->buildContextFallbackShopQuery($question);
if ($contextQuery !== '' && !$this->isMetaOnlyShopQuery($contextQuery)) {
if ($this->isUsableContextualShopQuery($contextQuery)) {
return $contextQuery;
}
}
return $this->extractContextualShopSearchQueryFromHistoryTurns($commerceHistoryContext);
}
private function extractContextualShopSearchQueryFromHistoryTurns(string $commerceHistoryContext): string
{
foreach ($this->extractHistoryTurnsNewestFirst($commerceHistoryContext) as $turn) {
$question = $this->extractQuestionFromHistoryTurn($turn);
if ($question !== '' && !$this->isMetaOnlyShopQuery($question)) {
$contextQuery = $this->buildContextFallbackShopQuery($question);
if ($this->isUsableContextualShopQuery($contextQuery)) {
return $contextQuery;
}
}
$modelAnchor = $this->extractFirstTestomatModelAnchor($turn);
if ($modelAnchor !== '' && !$this->isMetaOnlyShopQuery($modelAnchor)) {
return mb_strtolower($modelAnchor, 'UTF-8');
}
}
return '';
}
private function extractQuestionFromHistoryTurn(string $turn): string
{
if (preg_match($this->agentRunnerConfig->getFollowUpHistoryQuestionPattern(), $turn, $matches) !== 1) {
return '';
}
return $this->sanitizeHistoryQuestion((string) ($matches[1] ?? ''));
}
private function isUsableContextualShopQuery(string $query): bool
{
$query = trim($query);
if ($query === '' || $this->isMetaOnlyShopQuery($query)) {
return false;
}
return $this->tokenizeShopQueryCandidate($query) !== [];
}
private function buildContextFallbackShopQuery(string $question): string
{
$tokens = $this->tokenizeShopQueryCandidate($question);