Files
MtoRagSystem/RETRIEX_PATCH_20_LLM_INPUT_NORMALIZATION_README.md
2026-05-02 19:17:59 +02:00

174 lines
5.2 KiB
Markdown

# RetrieX Patch 20 - LLM-assisted Input Normalization before Routing
## Ziel
Patch 20 ersetzt den p19-Symptom-Fix fuer einzelne Preis-Tippfehler (`kpstet`, `ksotet`) durch eine generische, LLM-gestuetzte Eingabe-Normalisierung vor der Intent-/Commerce-/Retrieval-Erkennung.
Der Ausloeser war der Flow:
1. `Was ist der niedrigste Grenzwert fuer die Wasserhaerte, welcher mit einem Testomaten ueberwacht werden kann?`
2. `mit welchem indikator wird der wert gemessen`
3. `was kpstet der indikator`
p19 konnte diesen konkreten Tippfehler per YAML-Liste auffangen, skaliert aber nicht. p20 normalisiert die Nutzereingabe vorher, z. B. `was kpstet der indikator` -> `was kostet der indikator`, ohne Produktkontext fachlich aufzufuellen.
## Architektur
Der Normalisierungsschritt sitzt in `AgentRunner::run()` direkt nach `analyze_request` und vor:
- URL-/Quellenpruefung
- CommerceIntentLite-Erkennung
- Knowledge-Retrieval-Prompt-Bau
- Shop-Query-Optimierung
- finalem PromptBuilder-Aufruf
Das LLM ist ueber den bereits vorhandenen `final class OllamaClient` angebunden und nutzt analog zur Shop-Query-Optimierung:
```php
foreach ($this->ollamaClient->stream($normalizationPrompt) as $token) {
...
}
```
Die Originalfrage bleibt erhalten und wird weiterhin in die Conversation History geschrieben. Die normalisierte Frage wird nur als effektive Eingabe fuer Routing, Intent, Retrieval, Shop-Optimierung und Antwortgenerierung genutzt.
## Guardrails
Die Normalisierung darf nur offensichtliche Tippfehler korrigieren. Sie darf nicht fachlich interpretieren.
Konkrete Schutzmechanismen:
- YAML-konfigurierbarer Normalizer-Prompt in `config/retriex/agent.yaml`
- keine fachliche Kontextauflösung im Normalizer
- keine Produktnamen, Modellnummern, Messwerte, Artikelnummern oder Einsatzbereiche hinzufuegen
- vage Referenzen wie `der indikator` bleiben vage und werden erst spaeter ueber bestehende Kontextlogik aufgeloest
- URL-/Code-aehnliche Eingaben werden uebersprungen
- maximale Eingabe-/Ausgabelaenge
- maximale Laengenvergroesserung
- maximale Token-Zunahme
- neue Zahlen in der normalisierten Eingabe werden verworfen
- bei Fehlern, leerer Ausgabe oder unsicherem Ergebnis faellt RetrieX auf die Originalfrage zurueck
## Geaenderte Dateien
- `src/Agent/AgentRunner.php`
- `src/Config/AgentRunnerConfig.php`
- `src/Config/RetriexEffectiveConfigProvider.php`
- `config/retriex/agent.yaml`
- `config/retriex/intent.yaml`
- `config/retriex/commerce.yaml`
## Entfernt aus p19-Symptomlisten
Die expliziten Tippfehler `kpstet` und `ksotet` wurden entfernt aus:
- `intent.yaml` strong/non-product/price/explicit-commerce Listen
- `commerce.yaml` stopword- und correction-Listen
Damit ist p20 nicht mehr auf diese konkreten Fehlerlisten angewiesen.
## Erwartetes Verhalten
Eingabe:
```text
was kpstet der indikator
```
Interne Normalisierung:
```text
was kostet der indikator
```
Danach sollte der bestehende Commerce-/Shop-Follow-up-Flow greifen:
- Commerce Intent wird erkannt
- Shop-Suche wird angefragt
- referenzieller Kontext `Indikatortyp 300` kann durch bestehende Shop-Query-Context-Anchor-Logik ergaenzt werden
## Lokal ausgefuehrte Pruefungen
Im Container ausgefuehrt:
```bash
php -l src/Agent/AgentRunner.php
php -l src/Config/AgentRunnerConfig.php
php -l src/Config/RetriexEffectiveConfigProvider.php
python3 - <<'PY'
import yaml
from pathlib import Path
for rel in ['config/retriex/agent.yaml','config/retriex/intent.yaml','config/retriex/commerce.yaml']:
with (Path('.') / rel).open() as f:
yaml.safe_load(f)
PY
php -r '$patterns=["/^(?:normalisiert|korrigiert|corrected|normalized)\\s*:\\s*/iu","/https?:\\/\\//iu","/\\bwww\\./iu","/```/u"]; foreach($patterns as $p){ if(@preg_match($p, "was kpstet der indikator")===false){ exit(1); } } echo "OK\n";'
grep -R "kpstet\|ksotet" -n config src || true
```
Ergebnis:
- PHP-Syntax: OK
- YAML-Parse: OK
- Regex-Smoke-Test: OK
- `kpstet` / `ksotet`: nicht mehr in `config` oder `src`
## Nicht lokal ausfuehrbar
Die Symfony-/Composer-basierten Pflichtchecks konnten im Container nicht ausgefuehrt werden, weil im ZIP keine installierten Vendor-Dependencies enthalten sind.
Bitte nach dem Einspielen ausfuehren:
```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
```
## Empfohlene Regressionstests
1. Stabiler v1.5.1-Flow:
```text
Was ist der niedrigste Grenzwert fuer die Wasserhaerte, welcher mit einem Testomaten ueberwacht werden kann?
mit welchem indikator wird der wert gemessen
was kostet der indikator
```
2. Tippfehler-Flow:
```text
Was ist der niedrigste Grenzwert fuer die Wasserhaerte, welcher mit einem Testomaten ueberwacht werden kann?
mit welchem indikator wird der wert gemessen
was kpstet der indikator
```
Erwartung fuer beide Preisfragen:
- Shop-Suche wird angefragt
- Shop-Treffer werden genutzt
- keine Rueckkehr in RAG-only mit Testomat-2000-Indikatoren
3. Guardrail-Test:
```text
was kpstet der indikator 300
```
Erwartung:
- Normalisierung darf `300` erhalten
- keine neue Modellnummer / Artikelnummer hinzufuegen
4. URL-Skip-Test:
```text
pruefe https://example.com/test?x=kpstet
```
Erwartung:
- Normalisierung wird uebersprungen
- URL bleibt unveraendert