This is very nice. If you’re ambitious, you could try adding @fastjack’s suggestion to add multiple topics. I think this is doable by changing the decorator’s signature to:
def on_topic(self, *topic_names: str):
And then put almost all the code inside the wrapper function in a loop for topic_name in topic_names: and then probably some minor changes elsewhere.
I’ll have a closer look tomorrow and test it before merging the PR.
The examples are purely fictional, of course. The goal is to have specific decorators for Hermes messages that work on Rhasspy Hermes classes, but in the mean time, you can use this on_topic decorator for Hermes messages that don’t have their own decorator yet. This also makes it easy to react to both Hermes messages and non-Hermes MQTT messages.
I just created a first rough API documentation. You can generate it with:
make docs
Afterwards you can find the generated HTML pages in docs/build/html. The plan is to extend this documentation and publish it for easier discovery of the library’s functionality.
With the new “on_topic” decorator I am trying to handle the “intent not recognized” event like this:
@app.on_topic("hermes/dialogueManager/intentNotRecognized")
def intent_not_recognized(data: TopicData, payload: bytes):
_LOGGER.debug("not recognized: " + str(data) + str(payload))
payload_json = json.loads(payload.decode("utf-8"))
session_id = payload_json.get("sessionId")
site_id = payload_json.get("siteId")
if session_id in akinator_sessions:
text = 'Das habe ich nicht verstanden'
app.publish(
DialogueContinueSession(
session_id=session_id,
site_id=site_id,
text=text,
intent_filter=intent_filter,
custom_data=None,
send_intent_not_recognized=True,
slot=None
)
)
The problem is: It only kind of works. Rhasspy seems to push some or most of the TTS message into the STT system. Causing an infinite loop of intent_not_recognized events. It should wait until the TTS output is finished before recording. It does that normally, why not when the ContinueSession is published from the intent not recognized event. Is that a Rhasspy bug?
Regarding the api:
It would be great if there were a parameter in the decorator to say the system “payload is json” and it doing the json-load and decode for you. Even better in my case a on_intent_not_recognized decorator´
I think hermes/dialogueManager/intentNotRecognized is the correct one to use. It’s behavior is depending on the send_intent_not_recognized parameter of the DialogueContinueSession message. (True will issue the intentNotRecognized event False will end the session. I looked at the Rhasspy source).
Sadly with both it will capture part of the TTS response as input.
Thank you. I would need the other one. But there are probably use case to have both. The nlu one will react to every not recognized intent the dialogueManager only in an active dialog session (at least that’s my understanding)
I will do it later. I want to have a second look at the Rhasspy source before that. Yesterday it confused me, as it seems to handle the dialogue continue session message always in the same way.
It seems I got confused while testing. The issue with intentNotRecognized triggering a loop because it started to listen to it’s output is triggered by a 10 second TTS timeout in DialogueHermesMqtt.
My help text is pretty long (13 seconds). I thought I could also reproduce it with a shorter text but I can’t anymore. I have opened an issue: https://github.com/rhasspy/rhasspy/issues/62
Yes, it makes sense to add a method to start a session.
Built-in slot types are indeed a feature that could help a lot of use cases. But that should be embedded in Rhasspy itself indeed. There have been some discussions about it already.
I’m now working on tests (current code coverage: 44%) and there’s autogenerated API documentation. I want to expand both before I create the first release on PyPI.
If the API of this library changes, your app possibly stops working when it updates to the newest release of Rhasspy Hermes App. Therefore, it’s best to define a specific version in your requirements.txt file:
rhasspy-hermes-app==0.1.0
This way your app keeps working when the Rhasspy Hermes App library adds incompatible changes in a new version.
I have expanded the documentation, including some information for people who want to contribute.
All contributions are welcome! New features, bug fixes, documentation, tests, …
@H3adcra5h I have added a lot of documentation, mypy annotations and tests to the code, but for now I have left your raw topic additions more or less alone because you know that part of the code better. If you could take a look at it, that would be awesome.
If the Intent has slot values for minutes or seconds handle_start_timer will get called with that otherwise it will provide “None”. One variant of this would be to also put the expected type into the decorator and let the decorator do the validation.
Another option: Just provide a helper function like mine in your module to get the slot values out of an intent. As you can see in my source (maybe I am doing it wrong) it is not that simple.