Modulentwicklung für Rhasspy Sprachassistent

Begonnen von drhirn, 11 März 2021, 15:59:50

Vorheriges Thema - Nächstes Thema

Cordula

Mit der Codeänderung funktioniert die Sprachausgabe. Danke.

drhirn

Zitat von: Beta-User am 09 April 2021, 14:44:28
Wie schaut's damit aus?

Jetzt auch.



Ich versuche gerade, alle Lichter im Wohnzimmer auszuschalten. Bekomme aber immer nur die Antwort, dass kein Gerät gefunden wurde. Das Log meint, die sorted devices list sei leer. Liegt wahrscheinlich daran, dass sich in RHASSPY_getDevicesByGroup ab next if $allgroups =~ m{\b$group\b}x; nichts mehr tut. Da bleiben alle folgenden Variablen leer.


2021.04.09 14:46:19.652 5: RHASSPY: [Rhasspy] Parse (IO: rhasspyMQTT2): Msg: hermes/intent/de.fhem_SetOnOffGroup => {"input": "schalte alle lichter wohnzimmer aus", "intent": {"intentName": "de.fhem:SetOnOffGroup", "confidenceScore": 1.0}, "siteId": "default", "id": "c089e860-cfd7-4b41-8cd7-309653c11e3d", "slots": [{"entity": "de.fhem.Group", "value": {"kind": "Unknown", "value": "lichter"}, "slotName": "Group", "rawValue": "lichter", "confidence": 1.0, "range": {"start": 13, "end": 20, "rawStart": 13, "rawEnd": 20}}, {"entity": "de.fhem.Room", "value": {"kind": "Unknown", "value": "wohnzimmer"}, "slotName": "Room", "rawValue": "wohnzimmer", "confidence": 1.0, "range": {"start": 21, "end": 31, "rawStart": 21, "rawEnd": 31}}, {"entity": "OnOffValue", "value": {"kind": "Unknown", "value": "aus"}, "slotName": "Value", "rawValue": "aus", "confidence": 1.0, "range": {"start": 32, "end": 35, "rawStart": 32, "rawEnd": 35}}], "sessionId": "c089e860-cfd7-4b41-8cd7-309653c11e3d", "customData": null, "asrTokens": [[{"value": "schalte", "confidence": 1.0, "rangeStart": 0, "rangeEnd": 7, "time": null}, {"value": "alle", "confidence": 1.0, "rangeStart": 8, "rangeEnd": 12, "time": null}, {"value": "lichter", "confidence": 1.0, "rangeStart": 13, "rangeEnd": 20, "time": null}, {"value": "wohnzimmer", "confidence": 1.0, "rangeStart": 21, "rangeEnd": 31, "time": null}, {"value": "aus", "confidence": 1.0, "rangeStart": 32, "rangeEnd": 35, "time": null}]], "asrConfidence": null, "rawInput": "schalte alle lichter wohnzimmer aus", "wakewordId": null, "lang": null}
2021.04.09 14:46:19.652 5: Parsed value: schalte alle lichter wohnzimmer aus for key: input
2021.04.09 14:46:19.653 5: Parsed value: wohnzimmer for key: Room
2021.04.09 14:46:19.653 5: Parsed value: c089e860-cfd7-4b41-8cd7-309653c11e3d for key: sessionId
2021.04.09 14:46:19.653 5: Parsed value: aus for key: Value
2021.04.09 14:46:19.653 5: Parsed value: SetOnOffGroup for key: intent
2021.04.09 14:46:19.653 5: Parsed value: 1 for key: probability
2021.04.09 14:46:19.653 5: Parsed value: lichter for key: Group
2021.04.09 14:46:19.654 5: Parsed value: schalte alle lichter wohnzimmer aus for key: rawInput
2021.04.09 14:46:19.654 5: Parsed value: default for key: siteId
2021.04.09 14:46:19.654 5: handleIntentSetOnOffGroup called
2021.04.09 14:46:19.654 5: sorted devices list is:


Mache ich da etwas falsch?

Beta-User

Zitat von: drhirn am 09 April 2021, 14:54:25
Mache ich da etwas falsch?
Nö, mein Fehler (im Zusammenhang mit dem Umbau von Array auf Komma-Liste). Bin froh, wenn es nur das ist ::) ...

Logik sollte m.E. invertiert sein:
next if $allgroups !~ m{\b$group\b}x;

Die InternalTimer-Geschichte mit 10 Sekunden sähe so aus (#523):
    if ($command eq 'update') {
        if ($values[0] eq 'language') {
            return initialize_Language($hash, $hash->{LANGUAGE});
        }
        if ($values[0] eq 'devicemap') {
            initialize_devicemap($hash);
            RHASSPY_updateSlots($hash);
            return InternalTimer(time + 10,\&RHASSPY_trainRhasspy,$hash,0);
        }
        if ($values[0] eq 'devicemap_only') {
            return initialize_devicemap($hash);
        }
        if ($values[0] eq 'slots') {
            RHASSPY_updateSlots($hash);
            return InternalTimer(time + 10,\&RHASSPY_trainRhasspy,$hash,0);
        }
        if ($values[0] eq 'slots_no_training') {
            initialize_devicemap($hash);
            return RHASSPY_updateSlots($hash);
        }
        if ($values[0] eq 'all') {
            initialize_Language($hash, $hash->{LANGUAGE});
            initialize_devicemap($hash);
            RHASSPY_updateSlots($hash);
            return InternalTimer(time + 10,\&RHASSPY_trainRhasspy,$hash,0);
        }
    }
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

drhirn

Zitat von: Beta-User am 09 April 2021, 15:02:41
Logik sollte m.E. invertiert sein:

Perfekt, danke!


Bzgl. Timer: Das war, wie's scheint, ein Problem mit der demo.cfg. Rhasspy kann aus irgendeinem Grund mit dem Wort "AV" nichts anfangen. Zumindest meines nicht. Hat immer ein Fehler beim Training gegeben.
Ich hab das Delay daher wieder raus genommen und überlege mir gerade, ob es nicht trotzdem sinnvoll wäre. Notiere das als einen Punkt für später. Die fixen 10s sind nämlich auch irgendwie unschön.

drhirn

Muss ich bei SetOnOffGroup wirklich einen Raum angeben? Laut Code ja, aber warum? Was ist, wenn ich einfach alle Lampen im Haus ausschalten möchte?

Beta-User

#260
Zitat von: drhirn am 09 April 2021, 15:30:33
Muss ich bei SetOnOffGroup wirklich einen Raum angeben? Laut Code ja, aber warum? Was ist, wenn ich einfach alle Lampen im Haus ausschalten möchte?
Warum? Na ja, weil ich das so wollte... Unspezifisch "Immer alles" war mir ehrlich gesagt nach den ersten live-Tests mit Rhasspy noch zu "heiß" - Meine Musik war beim Testen zu oft weg ;D .

Daher habe ich diesen Raum "global" erfunden, der für "überall" versendet wird:
Zitat von: Beta-User am 31 März 2021, 12:19:05
Auf die Schnelle habe ich folgende sentences dazu zusammengeklöppelt:
[de.fhem:SetNumericGroup]
\[(schalt|mach|fahr)] (alle | sämtliche ) $de.fhem.Group{Group} [im] [( überall:global | $de.fhem.Room){Room}] [um] [(0..10){Value!int}] [dezibel{Unit}] (lauter|höher){Change:volUp}
\[(schalt|mach)] (alle | sämtliche ) $de.fhem.Group{Group} [im] [( überall:global | $de.fhem.Room){Room}] [um] [(0..10){Value!int}] [dezibel{Unit}] (leiser|niedriger){Change:volDown}
( mach | stelle ) (alle | sämtliche ) $de.fhem.Group{Group} [im] [( überall:global | $de.fhem.Room){Room}] [um] [(0..10){Value!int}] [grad{Unit}] (höher|wärmer){Change:tempUp}
( mach | stelle ) (alle | sämtliche ) $de.fhem.Group{Group} [im] [( überall:global | $de.fhem.Room){Room}] [um] [(0..10){Value!int}] [grad{Unit}] (niedriger|kälter){Change:tempDown}
( mach |schalt|schalte|stelle) (alle | sämtliche ) $de.fhem.Group{Group} [im] [( überall:global | $de.fhem.Room){Room}] [um] [(0..100){Value}] [prozent{Unit:percent}] (heller){Change:lightUp}
( mach |schalt|schalte|stelle) (alle | sämtliche ) $de.fhem.Group{Group} [im] [( überall:global | $de.fhem.Room){Room}] [um] [(0..100){Value}] [prozent{Unit:percent}] (dunkler){Change:lightDown}
(schalt | schalte | stelle ) (alle | sämtliche ) $de.fhem.Group{Group} [im] [( überall:global | $de.fhem.Room){Room}] auf (0..100){Value!float}
( mehr{Change:lightUp} | weniger{Change:lightDown} ) (alle | sämtliche ) $de.fhem.Group{Group} [im] [( überall:global | $de.fhem.Room){Room}]


Wir können aber gerne diskutieren, ob das sinnvoll ist.
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

drhirn

Achso, haha, das ist natürlich blöd ;D

Es stimmt schon, das ist riskant. Aber "schalte alle lichter überall aus" wird halt auch keiner sagen. Zumindest nicht freiwillig ;)

Beta-User

Na ja, man kann entweder die sentences ergänzen um
Zitatschalte überall das licht aus
- dann ist es natürlicher sprechbar - oder sich eben sonst was überlegen, wie man das haben will.

Im Moment fehlt mir einfach noch die praktische Erfahrung, wie man "praktikable" und gute Sätze baut, die dann eben auch im praktischen Leben nicht für unliebsame Ergebnisse sorgen. Daher eben auch das mit der "confirmation" usw.. Steckt alles noch etwas in den Kinderschuhen, aber sowas wie ein erster Pfad ist erkennbar.
Was sentences an sich angeht: Nach meinem bisherigen Eindruck ist länger = besser/trennschärfer, und das ganze wird wohl auch besser, wenn man mehr "keywords" im Einsatz hat. Deckt sich das mit euren Erfahrungen?

Da du grade mit beidem rumspielst: Wie sind die Eindrücke zu gDT und "Set...Group"?
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

drhirn

Zitat von: Beta-User am 09 April 2021, 15:52:47
Na ja, man kann entweder die sentences ergänzen um - dann ist es natürlicher sprechbar - oder sich eben sonst was überlegen, wie man das haben will.

Ich überlege...

ZitatWas sentences an sich angeht: Nach meinem bisherigen Eindruck ist länger = besser/trennschärfer, und das ganze wird wohl auch besser, wenn man mehr "keywords" im Einsatz hat. Deckt sich das mit euren Erfahrungen?

Ist eindeutig so. Rhasspy nimmt halt einen Intent, der ungefähr zum Satz passt. Je genauer die Sentences mit dem Gesprochenen übereinstimmen, desto korrektere Ergebnisse werden geliefert.
Deswegen muss man auch höllisch aufpassen, dass man nicht zu viel im Sentence optional macht. Sonst spricht man plötzlich einen Satz, der auf mehrere Intents passen könnte. Schon oft genug passiert.
Oder Rhasspy entscheidet sich für einen Intent, obwohl überhaupt nichts gesprochen wurde.

ZitatDa du grade mit beidem rumspielst: Wie sind die Eindrücke zu gDT und "Set...Group"?

Ich hab bisher bzgl. gDT nur mit "switch" und "light" gespielt. Und da nur ein/aus. Ist schon eine große Erleichterung, wenn man bei einem Device nur gDT und FHEM-Room braucht. Ich habe aber ein bisschen Angst vor Inkonsistenzen. Nicht so sehr, was das Modul betrifft, sondern eher den Saustall, den ich eh schon habe ;).

Meine Erkenntnisse zu Set..Group stehen schon hier. Hab bisher nur SetOnOffGroup getestet. Und das funktioniert ja jetzt soweit. Ich persönlich habe aber nicht viel Verwendung dafür.

drhirn

Wo passiert denn die ganze gDT-Magie im Code? Ich mein, wo wird entschieden, welche Fähigkeiten welcher gDT hat?

JensS

@Beta-User
Licht aus - funktioniert mit lc.

"Licht im ganzen Haus aus" habe ich so gelöst:[de.fhem:SetAllOff]
(schließe|lösche) alle ((Lichter|Lampen){rType:light}|(Rollos){rType:blind}) ([im (Haus | $de.fhem.Room){rRoom}] | :Haus{rRoom})

"Lösche alle Lichter im Wohnzimmer" schaltet alle Lampen im WZ aus.
"Lösche alle Lichter" ohne Angabe vom Raumnamen, wird durch " :Haus{rRoom}" ergänzt. Hatte ich so erweitert, weil in der neuen Version keine undef-Parameter übergeben wurden.
Debian auf APU2C4, HM-CFG-USB2, SIGNALduino, HM-ES-PMSw1-Pl, TFA 30.3121, TFA 30.3125, ITS-150, PIR-5000, configurable Firmata USB & LAN, 1-wire: DS-18B20, DS-18S20, DS-2408, DS-2413, diverse I2C-Komponenten, zigbee2mqtt, ESPEasy etc.

drhirn

So geht's auch:
schalte alle $de.fhem.Group{Group} (:){Room:global}([$de.fhem.Room{Room}]) $OnOffValue{Value}

Beta-User

Zitat von: JensS am 09 April 2021, 16:59:20
@Beta-User
Licht aus - funktioniert mit lc.
Danke für die Rückmeldung! Dann haken wir diesen Teil also ab :) .

Zitat"Licht im ganzen Haus aus" habe ich so gelöst:[de.fhem:SetAllOff]
Das war eine wertvolle Anregung, auch für die Entwicklung dieses Gruppen-Dingens. Mir war es an zwei Stellen zu eng: Zum einen, weil ich (eventuell fälschlicherweise) davon ausgegangen war, dass Room eine eher größere Gruppe darstellen sollte und daher eine Zwischenstufe analog dem allgemeinen group für sinnvoll empfand und zum anderen, weil ich - wenn schon denn schon - dann auch gleich SetNumeric entsprechend umgesetzt haben wollte (triggernd und mit der Möglichkeit, ein async_delay einzubauen).

Und den Hinweis, dass man "leer" mit "global" übersetzen könnte, behalte (nicht nur) ich hoffentlich im Hinterkopf :) . (EDIT: das hat "jemand" aber schnell aufgegriffen...!)

Zitat von: drhirn am 09 April 2021, 16:36:36
Ist eindeutig so. Rhasspy nimmt halt einen Intent, der ungefähr zum Satz passt. Je genauer die Sentences mit dem Gesprochenen übereinstimmen, desto korrektere Ergebnisse werden geliefert.Deswegen muss man auch höllisch aufpassen, dass man nicht zu viel im Sentence optional macht. Sonst spricht man plötzlich einen Satz, der auf mehrere Intents passen könnte. Schon oft genug passiert.
Nachvollziehbar; bin auch am Überlegen, wie man da was verbessern kann.
Neben einer eventuell verbesserten Erkennung der Kombinationen in FHEM (da ist das aber uU. schon in den Brunnen gefallen...) kommt auf der Rhasspy-Seite in Frage:
- Reihenfolge der sentences bzw. intents (?)
- Verzicht auf Optionen
- Verwendung von speziellen Keywords (Bsp. "überall")
- Verwendung von mehr slots (eben nur alle Lichter für heller/dunkler, nicht pauschal alle FHEM-Devices)
- Einen möglichen Ansatzpunkt könnte auch "kind" liefern:{"entity": "de.fhem.Device", "value": {"kind": "Unknown", "value": "ct light"}, ...
Hat zufällig jemand einen Link, wo man sich dazu schlau machen kann?
Meine Hoffnung ist die, dass Rhasspy sehr viel mehr zu bieten hat als wir derzeit nutzen ;) ..
ZitatOder Rhasspy entscheidet sich für einen Intent, obwohl überhaupt nichts gesprochen wurde.
Bei mir meistens "nein", was dann nur zur Folge hat, dass keiner sich für eine Bestätigung zuständig fühlt...

ZitatIch hab bisher bzgl. gDT nur mit "switch" und "light" gespielt. Und da nur ein/aus. Ist schon eine große Erleichterung, wenn man bei einem Device nur gDT und FHEM-Room braucht. Ich habe aber ein bisschen Angst vor Inkonsistenzen. Nicht so sehr, was das Modul betrifft, sondern eher den Saustall, den ich eh schon habe ;) .
Nachvollziehbar.
M.E. beherrschbar, wenn man devspec nutzt, um erst mal mit wenigen Devices anzufangen. Bei mir derzeit: Zwei FHEM-Räume und einige wenige Einzeldevices.

ZitatMeine Erkenntnisse zu Set..Group stehen schon hier. Hab bisher nur SetOnOffGroup getestet. Und das funktioniert ja jetzt soweit. Ich persönlich habe aber nicht viel Verwendung dafür.
Auch nachvollziehbar, aber vermutlich eine Geschmacksfrage bzw. eine Frage dessen, was vorher schon da war. Ich habe z.B. praktisch alle structures irgendwann nicht mehr benötigt/genutzt und daher ausgebaut. Meine Beleuchtung in den zwei Räumen besteht aber aus diversen logischen Gruppen, und die lassen sich wunderbar zusammenfassen und mit Rhasspy steuern - das ist bisher die eleganteste Variante, die ich im Einsatz hatte :) .
Eventuell läßt sich das toppen, wenn man lightscene noch als gDT dazunimmt. Das ist aber was für V 0.6.0...

Zitat von: drhirn am 09 April 2021, 16:58:20
Wo passiert denn die ganze gDT-Magie im Code? Ich mein, wo wird entschieden, welche Fähigkeiten welcher gDT hat?
initialize_devicemap() =>     
for (@devices) {
        _analyze_genDevType($hash, $_) if $hash->{useGenericAttrs};
        _analyze_rhassypAttr($hash, $_);
    }

medias res ist also _analyze_rhassypAttr(), und dort ab "my $currentMapping"
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

drhirn

Zitat von: Beta-User am 09 April 2021, 17:20:38
Zum einen, weil ich (eventuell fälschlicherweise) davon ausgegangen war, dass Room eine eher größere Gruppe darstellen sollte

Ist auch meine FHEM-Logik


ZitatNeben einer eventuell verbesserten Erkennung der Kombinationen in FHEM (da ist das aber uU. schon in den Brunnen gefallen...)

Naja, Rhasspy sollte schon mal den richtigen Intent liefern. Sonst können wir im Modul auch nicht viel machen.

Zitat
- Verwendung von mehr slots (eben nur alle Lichter für heller/dunkler, nicht pauschal alle FHEM-Devices)
- Einen möglichen Ansatzpunkt könnte auch "kind" liefern:{"entity": "de.fhem.Device", "value": {"kind": "Unknown", "value": "ct light"}, ...

Mehr Slots wäre eine Option.
Ich weiß jetzt auch nicht, wofür "kind" ist. Aber ich habe mal nachgefragt und werden dann berichten. Die Frage ist allerdings, ob man's überhaupt setzen kann.

ZitatBei mir meistens "nein", was dann nur zur Folge hat, dass keiner sich für eine Bestätigung zuständig fühlt...

Ja, bei mir auch. Das ist der de.fhem:ConfirmAction Intent. Ich weiß aber nicht, warum.

ZitatEventuell läßt sich das toppen, wenn man lightscene noch als gDT dazunimmt. Das ist aber was für V 0.6.0...

Fände ich ganz gut. Ich bilde meinen Lichtszene derzeit ja mit rhasspyChannels ab.
Interessanter wäre - und deswegen habe ich wegen gDT im Code gefragt - ein Typ "colorlight" oder so. Um die Farbe des Lichts setzen zu können.

Zitatmedias res ist also _analyze_rhassypAttr(), und dort ab "my $currentMapping"

Danke!

drhirn

Zitat von: Beta-User am 09 April 2021, 17:20:38
Bei mir meistens "nein", was dann nur zur Folge hat, dass keiner sich für eine Bestätigung zuständig fühlt...

btw. da gibt's schon einen Thread dazu: https://community.rhasspy.org/t/unrecognized-commands-silence-incorrectly-return-intent/2270