CustomIntent mit Dialog

Begonnen von gregorv, 03 Oktober 2024, 10:54:24

Vorheriges Thema - Nächstes Thema

Beta-User

ZitatOder spricht etwas dagegen
Ja.

Ich versuche die ganze Zeit schon zu vermitteln, dass wir die nämliche neue Funktion brauchen.

Jetzt funktioniert sie prinzipiell, es ist aber noch Arbeit "drum herum" zu machen.

Ich erkläre es ggf. ein anderes Mal, für heute ist mein Rhasspy-Zeitbudget schon überschritten.
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

Beta-User

Erst mal nur wieder kurz:

M.E. brauchen wir 2 Funktionalitäten:
a) Wenn Rhasspy neu startet oder sich (möglicherweise) irgendwas in RHASSPY geändert hat, brauchen wir den "objektorientierten" JSON für den "configure"-Topic. Dieser Teil steckt in "configure_DialogManager()", und wurde bisher fälschlicherweise auch aufgerufen, wenn einer der internen Dialog-Intents (confirm, cancel, choice) angeschalten werden sollte.
b) Für "normale Dialoge" (oder eben den expliziten Start einer session mit einer bestimmten Auswahl von Intents ist "eigentlich" vorgesehen, die "flache Liste" für das enqueue/start/continue-session-Topic zu verwenden.
Genau das macht neuerdings die neue Funktion _get_sessionIntentFilter(), und die soll künftig immer dann verwendt werden, wenn es eben nicht um dauerhafte Einstellungen gehen soll (die dann aktiv sind, wenn eine Sitzung mit "null" gestartet wird), sondern "nur" um irgendwas, was sitzungsbezogen ist.

Wie man an dem bereits geposteten MQTT-Verkehr sehen kann, stört sich die nlu-Analyse überhaupt nicht daran, dass ein bestimmter Intent per default deaktiviert ist, aber eben sitzungsbezogen (oder besser: bezogen auf den aktuellen Stand in der session) grade aktiv.

Dementsprechend sind jetzt erst mal ein paar Aufräumarbeiten erforderlich, um (mindestens)
- in CancelAction die Unterscheidung reinzuknödeln, ob das "versehentlich" oder absichtlich ist, dass der Intent aktiv ist und
- den/die "falschen" Aufruf/e von configure_DialogManager() umzustellen, und
- die Weitergabe der gewünschten (aktivierten) Intents aus handleCustomIntent() zu vereinfachen (es sollte am Ende ohne "de.fhem:" übergeben werden können und das RHASSPY-intern passend ergänzt).
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

gregorv

OK, jetzt wird das für mich klar, ich schau mir das mal an. Wird aber etwas dauern, weil ich gerade noch auf einer anderen Baustelle bin.

Übrigens hast Du gestern die beiden Änderungen in einer älteren Version gemacht (12.11.) statt in Deiner aktuellen vom 18.11. Die von gestern darf keine Basis für künftige Versionen werden, sonst muss da einiges Andere wieder eingebaut werden.

Beta-User

Zitat von: gregorv am 23 November 2024, 09:17:45Übrigens hast Du gestern die beiden Änderungen in einer älteren Version gemacht (12.11.) statt in Deiner aktuellen vom 18.11.
Ups, dachte, ich hätte die Fassung vom 18.11. auf github gehabt. Sind aber nur ein paar Zeilen anders, von daher sollte sich das relativ schnell übereinander schieben lassen. Aber nicht mehr heute...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

Beta-User

#199
OK, bis auf ein
Zitat2024.11.24 15:00:28 1: PERL WARNING: Use of uninitialized value $intents in split at ./FHEM/10_RHASSPY.pm line 1788.
scheint die Version anbei erst mal wieder zu funktionieren; dabei ist neben der Einarbeitung der Version vom 18. auch schon "configue" weitgehend umgestellt, aber noch nicht intensiv getestet, v.a. mit CustomIntents nicht. Da sollte man jetzt auch einfach z.B. "CancelAction" angeben können.

Gibt bestimmt wieder viele Feinheiten zum Nacharbeiten, und die Doku/commandref fehlt auch noch...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

gregorv

Zitatdie Doku/commandref fehlt auch noch...
Heute habe ich hier Beschreibung der Optionen noch etws weiter gamacht.
Das wird eine Art Vorlage für die CommandRef, ist aber noch nicht komplett.

gregorv

@Beta-User
Eine Frage:
Ich habe die getOptions() mit der man bestimmte Keys aus Specials oder Tweaks auslesen und an $data anhängen kann soweit, dass sie das macht, was wir derzeit brauchen.
Eigentlich müsste die in jedem Intent ausgerufen werden, damit das bei beliebigen Intents funktioniert.

Statt dessen möcht ich sie gerne an zentraler Stelle aufrufen.
In der analyzeMQTTmessage(), unmittelbar unter der Zeile:
return [$hash->{NAME}] if !_check_minimumConfidence($hash, $data);
getOptions($hash, $data); # @@@   
schein es passend. Irgendwelche Einwände ?
Die getOptions() selbst habe ich so erweitert, dass sie sich $room und $device selbst aus $data holen kann:
# this will insert specified keys into $data which are stored in $device hash or tweaks hash # @@@
sub getOptions{
    my $hash   = shift // return;
    my $data   = shift // return;
    my $room   = shift // getRoomName($hash,$data);
    my $device = shift // getDeviceByName($hash, $room, $data->{Device});

Noch eine kleine Erweiterung da drin, da sie ja ohnehin schon in $data schreibt:
Ich habe als möglichen Key noch customData erlaubt. Damit kann man auch in $data->{customData} key-values unterbringen.
Tweaks: customData=MeinKey=MeinValue oder Specials: customData:MeinKey=MeinValue

Beta-User

Zitat von: gregorv am 24 November 2024, 16:37:51Heute habe ich hier Beschreibung der Optionen noch etws weiter gamacht.
Danke! Muss aber mal darüber nachdenken, wie und wo man das sinnvollerweise unterbringen könnte. Tendiere dazu, das in einem eigenen (Unter-Abschnitt) unterzubringen, der dann erst mal unter "Tweaks" anzusiedeln wäre (obwohl es dazu noch nichts gibt).

Zitat von: gregorv am 25 November 2024, 17:39:13Irgendwelche Einwände ?
Für den Moment erst mal keine echten "Einwände", aber vom Bauchgefühl her neige ich dazu, das (zumindest zum Teil) in die Intents zu verteilen.

Muss aber vermutlich etwas ausholen:
Letztlich geht es doch darum, zum einen die Dialogsteuerung zu ergänzen, und zum anderen ggf. fehlende Infos aus den Altdaten zu holen. Für den ersten Teil kann (!) es sinnvoll sein, das zentral zu erledigen, für den Rest _glaube_ ich, dass es sinnvoll wäre, erst mal zu checken, wie "treffsicher" die bereits vorhandenen Infos aus der nlu für sich genommen sind. Wenn wir das da schon vermengen, können wir es hinterher nicht mehr bewerten. Beispiel: Es ist kein Device angegeben, wir holen das aus customData* (so wie wir das auf den Weg gebracht hatten: einfach die Alt-$data verpacken). Plötzlich sieht der gesamte Datensatz eindeutig aus, obwohl er es vorher nicht war...

Ich neige dazu, in solchen Fällen den "confidence"-Level zu ändern und nochmal zu checken, ob das noch ausreichend ist (falls du die Testsuite "durch" hast, verstehst du vielleicht besser, wie sich das eventuell auswirkt).

Konkret müßte ich das ganze aber auch erst mal für ein paar Grenzfälle durchspielen.

Zitat von: gregorv am 25 November 2024, 17:39:13Ich habe als möglichen Key noch customData erlaubt.
*Spontan finde ich das nicht gut. "customData" sind in meiner aktuellen Gedankenwelt Infos zum vorherigen Dialog. Irgendwas in der Konfiguration hat damit (erst mal) nichts zu tun und sollte m.E. auch anders benannt werden, auch, damit man das gg. anderen Usern halbwegs transparent erklären kann.

Habe übrigens noch einen logischen Wackler in der neuen Funktion (bzw. dem Aufruf anstelle von "configure") gefunden, muss das aber auch erst noch testen.
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

gregorv

#203
ZitatBeispiel: Es ist kein Device angegeben, wir holen das aus customData* ...
Der Einbau an dieser Stelle schließt nicht aus, dass er auch aus einem Intent heraus aufgrufen werden kann. Dafür sind die zusätzlichen Parameter $room und $device gedacht. Wenn bei einem erneuten Aufruf ein Key-Value Paar dazukommt, oder ein Wert sich ändert, bleiben alle sonstigen Daten, die vorher geschrieben wurden, erhalten.

Zitat"customData" sind in meiner aktuellen Gedankenwelt Infos zum vorherigen Dialog
Ja dazu haben wir es gemacht. Es ist nach wie vor die - meine ich - einzige Möglichkeit Daten zu Rhasspy zu transportieren - falls man die dort auswerten wollte. JensS hatte hier customData in Rhasspy auswerten dazu mal eine Möglichkeit beschrieben. Einige Posts früher hatte er mal erwähnt, dass er customData nutzt (genutzt hat) und dabei einfach einen String da reinschreibt. Wenn jemand das innerhalb vom Modul macht macht sind unsere Daten weg. Wenn ein String in customData von der NLU kommt (das kann z.B. mit einem CustomIntent gemacht werden), wird er derzeit gelöscht. Besser wäre, den in einen key von customData umzuwandeln, damit er erhalten bleibt. Log3... "$customData succesfully converted into \$customData->{$customData}".

Beta-User

Zitat von: gregorv am 25 November 2024, 22:23:33Der Einbau an dieser Stelle schließt nicht aus, dass er auch aus einem Intent heraus aufgrufen werden kann. Dafür sind die zusätzlichen Parameter $room und $device gedacht. Wenn bei einem erneuten Aufruf ein Key-Value Paar dazukommt, oder ein Wert sich ändert, bleiben alle sonstigen Daten, die vorher geschrieben wurden, erhalten.
Wie gesagt: ich habe da im Moment einfach nur ein Bauchgefühl, über Details wird man sich unterhalten müssen und können. Wann "multifunktionale" Codes sinnvoll sind und wann nicht, ist auch so eine Frage, tendenziell würde ich im Moment eher davon ausgehen, dass es einfacher ist, gleich die Trennung vorzusehen, aber wir werden sehen...

Zitat von: gregorv am 25 November 2024, 22:23:33Es ist nach wie vor die - meine ich - einzige Möglichkeit Daten zu Rhasspy zu transportieren - falls man die dort auswerten wollte.
Das mit dem Beispiel von JensS aus https://forum.fhem.de/index.php?topic=139337.msg1322321#msg1322321 ist ein guter Hinweis.
Muss mal nachschauen, dass wir sowas nicht kaputt machen, im Moment _glaube_ ich, dass wir customData nur anfassen (sollten), wenn wir nach einer abgeschlossenen Sitzung eine neue aufmachen; für den bisherigen Fall der "echten Dialoge" via "continueSession" speichern wir die Altdaten anders und verändern (hoffentlich) customData nicht.
Ob es "Altdaten" sind oder irgendwas anderes, sollte das "eval{-decode}" bereits jetzt (indirekt) aussortieren, und wir bringen eventuell was durcheinander, wenn wir da plötzlich einen Hash generieren?

Ad "zu Rhasspy transportieren": Jedenfalls so, wie wir Rhasspy nutzen, ist das nur ein Weg, uns selbst Infos zu schicken. Rhasspy (also eigentlich: die "üblicherweise genutzten Module innerhalb des Rhasspy-Universums") läßt die nach meiner bisherigen Erfahrung unverändert, wenn man da was reinschiebt (und nicht die Sitzung mit "null" startet). "customData" ist echt "user-sphere".

Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

gregorv

Zitatdass wir sowas nicht kaputt machen
so, wie es jetzt ist, kann etwas Wichtiges in customData nur durch einen CustomIntent gesetzt werden - ansonsten ist da nur die wake-word-Id  drin.
Erst, wenn nach sessionEnded eine neue Session mit sonst noch was aufgemacht wird überschreiben wir einen eventuell im CustomIntent gesetzten String.
Dürfte also soweit keine Beeinträchtigung geben - oder kennst Du eine andere Möglichkeit customData außerhalb vom Modul zu setzen?



Beta-User

Zitat von: gregorv am 26 November 2024, 16:31:16oder kennst Du eine andere Möglichkeit customData außerhalb vom Modul zu setzen
Na ja, im Prinzip kann "jeder", der da per MQTT mit dran hängt, auch beliebige Parameter mit einschleusen... Ergo: In der Theorie ja, in der Praxis dürfte das für unsere Anwendung keine Rolle spielen.

Anbei meine - leider immer noch ungetestete - aktualisierte Fassung, v.a. wegen der commandref. Aus "reopenVoiceInput" ist jetzt "reActivateVoiceInput" geworden, irgendeine Option aus dem "Text-Dialog-Modus" ist auch entfallen.

Achtung: Da der timer-Name geändert ist, sollte FHEM nach dem Austausch der Datei neu gestartet werden, ich hoffe, dass kein bug drin ist und das Modul wenigstens geladen werden kann.
(Sehr) vielleicht komme ich morgen wenigstens zu einem Kurztest und kann ggf. selbst debuggen.
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

Beta-User

So, kleines update mit einigen wenigen Fixes...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

gregorv

@Beta-User

kannst Du Dir das mal bitte anschauen. Ich denke das ist einfacher für den Aufruf.
Args: $hash, $data, [qw(IntentA IntentB)],
  • enable: enabled einen oder mehrere Intents (alle anderen Intents behalten ihren Status).
  • disable: disabled einen oder mehrere Intents (alle anderen Intents behalten ihren Status).
  • default: stellt die default Intents wieder her. (return = undef)
  • prefix: ergänzt nur den Präfix (fhem.de:), bei denen, wo es noch nicht da ist
sub _set_sessionIntentFilter {
    my $hash         = shift // return;
    my $data         = shift // return;
    my $intents        = shift;
    my $action       = shift // 'default' ; # possible values: default: reset to global intents, enable: enable the intent(s) in $intents, disable: disable the intent(s) in $intents, prefix: just add prefix
   
    my @allIntents = split m{,}xm, ReadingsVal( $hash->{NAME}, 'intents', '' );
    my @sessionIntents;
    for (@allIntents) {
        next if $_ =~ m{ConfirmAction|CancelAction|Choice|ChoiceRoom|ChoiceDevice};
        push @sessionIntents, $_ if
        !defined $hash->{helper}->{tweaks} ||
        !defined $hash->{helper}{tweaks}->{intentFilter} ||
        !defined $hash->{helper}{tweaks}->{intentFilter}->{$_} ||
        defined $hash->{helper}{tweaks}->{intentFilter}->{$_} && $hash->{helper}{tweaks}->{intentFilter}->{$_} eq 'true';
    }
    return undef if $action eq 'default';

      my $id = qq($hash->{LANGUAGE}.$hash->{fhemId}:);
    my @tmp;
    my @actionIntents;
    if ( ref $intents eq 'ARRAY' ) {
        @tmp = @$intents;
    } else {
        @tmp = split m{,}xm, $intents;
    }
    for (@tmp) {
        if ( $_ =~ m{\a${id}} ) {
            push @actionIntents, $_;
        } else {
            push @actionIntents, ${id}.$_;
        }
      }
  
    my @intentFilter;
    @tmp = ();
    @tmp = @{ $data->{intentFilter} } if defined $data->{intentFilter};
    @tmp = @sessionIntents if !defined $data->{intentFilter};
    for my $element (@tmp) {
        if ( $element =~ m{$id}x ) {
            push @intentFilter, $element;
        } else {
            push @intentFilter, ${id}.$element;
        }
      }
    @sessionIntents = ();
    if ( $action eq 'enable' ) {
        for my $element (@actionIntents) {
            push @intentFilter, $element unless grep { $_ eq $element } @intentFilter ;
        }
        @sessionIntents = @intentFilter;      
    }elsif ( $action eq 'disable' ) {
        for my $element (@intentFilter) {
             push @sessionIntents, "$element"  if  ! grep( /^$element$/, @actionIntents ) ;
        }
    }elsif ( $action eq 'prefix' ) {
        for my $element (@intentFilter) {
             push @sessionIntents, "$element" ;
        }
    }
   
    return \@sessionIntents;
}

Für unseren Fall wäre das _set_sessionIntentFilter($hash, $data, 'CancelAction', 'enable') )die aktuell enabled Intents holt er sich aus $data - wenn das leer ist - oder nicht existiert basieren die Ergebnisse für enable/disable auf den default Intents.

Beta-User

Hmmm, werde zumindest heute nicht groß Zeit finden, intensiver darüber nachzudenken, aber kurz zu
- "return undef":
a) Logik:
Warum soll man die Funktion überhaupt aufrufen, wenn man ein ganz bestimmtes Ergebnis haben will? Und warum dann vorab überhaupt irgendwelche Operationen durchführen?
b) Formal:
Schau mal in die Perl-Ecke: https://forum.fhem.de/index.php?topic=109592.0. ("unless" ist auch "bäh", und an der Stelle wollte ich bei Gelegenheit "any" einbauen...)

Sonst:
- "all" fehlt. Wäre ggf. hilfreich fürs Testen von Sätzen ;) . (ist imo jetzt in meinem Code vorbereitet, wird aber noch nicht genutzt)
- Die Idee, bei "ergänze CancelAction" auf $data zurückzugreifen finde ich gut!
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors