Available data in `response` templates

Hi there,

I am struggling to find documentation on the available data to response templates defined in the custom_sentences folder.

Specifically, I would like to use the out value of a list I have matched. Some sources seem to suggest, it’s just {{slot_name}}, but that doesn’t seem to be defined. There is a slots.slot_name, but it contains the matched in value. Finally, the data available to the sentence trigger contains the details variable, which according to the developers tools has the info I need. However, it also doesn’t seem to be defined in the response template.

Is there some definitive source for the available variables in a response template?

Thanks!

I found the source, where the data is set:

Apparently, we have

  • slots with the matched text only
  • state with the first matched state
  • query.matched with entities having the correct state
  • query.unmatched with entities having a wrong state (but are in the area etc.)

And that’s it. I’ll have to find another way to access the out version of my slot, as it seems. :frowning:

Do you want to replace the response for the built-in intent? Please describe your task in detail.

I want to add another reponse template to a built-in intent.

I am developing some more natural language German sentence triggers. One example is, I have temperature and humidity sensors all over the house. And I want to query their state using the area they are in.

Now, I am a nerd, when it comes to re-using code. So, I didn’t want to repeat the same sentence for each sensor device_class. That’s why I created a list for it using natural language in and HA out values. This list gets fed to the device_class slot, which works well.

Like this (note the beauty of the sentence :wink:):

language: de
intents:
  HassGetState:
    data:

      # Query sensor by device_class
      - sentences:
          - "<was_ist>( <the_sensor_class>;[ <area_floor>])"
        response: sensor_class
        slots:
          domain: sensor

expansion_rules:
  was_ist: "((wie|was) ist|(nenn|sag|gib)[e][ mir])"
  the_sensor_class: "[<artikel_bestimmt> ]{sensor_class:device_class}"

lists:
  sensor_class:
    values:
      - in: "(AQI|air quality [index]|Luftqualität[sindex])"
        out: aqi
      - in: "[(verbleibende|übrige|restliche) ](Batterie|Lade|Ladung)[[zu]stand]"
        out: battery
      - in:  "[relative ][Luft](Feuchte|Feuchtigkeit)"
        out: humidity
      - in: "[elektrische ]Leistung"
        out: power
      - in: "[Luft]Temperatur"
        out: temperature
      - in: "[elektrische ]Spannung[sabfall]"
        out: voltage

However, when I then want to use the device_class slot to form the reponse sentence, I cannot rely on it being, e.g., humidity. Instead it will be “Feuchte” or “relative Luftfeuchtigkeit”.

Unfortunately, I cannot use this text to form a response, because in German we have different genera of words: it would be “die Feuchte”, but “der Ladezustand”. That’s why I wanted to use the normalized device_class to pick a standard response from a dict keyed by the device_class.

Not sure, if that makes sense. It might very opinionated.

Anyways, I have found a way to do this. I will just use state.attributes.device_class. It’s not as straight-forward, but so far it seems to work.

Like this (note the match_class definition):

language: de 

responses:
  intents:
    HassGetState:

      sensor_class: |
        {% set match_states = query.matched
                            | map(attribute = 'state')
                            | map('float', none)
                            | select('number')
                            | map('round', 1)
                            | list %}
        {% set min_state    = match_states
                            | min
                            | replace(".", ",") %}
        {% set max_state    = match_states
                            | max
                            | replace(".", ",") %}
        {% set match_class  = {'humidity':    'Die relative Luftfeuchte',
                               'aqi':         'Der Luftqualitätsindex',
                               'battery':     'Der Batteriezustand',
                               'power':       'Die elektrische Leistung',
                               'temperature': 'Die Temperatur',
                               'voltage':     'Die Spannung',
                              }[state.attributes.device_class] %}
        {% set uom          = state.attributes.unit_of_measurement
                            | replace(state.state, localized_rounded) | replace("°C","Grad") | replace("°F","Grad") %}
        {% if match_states | length > 1 %}
          {{ match_class }} liegt im Bereich von {{ min_state }} bis {{ max_state }} {{ uom }}
        {% else %}
          {% if state.state|float(state.state) is number %}
            {% set localized_rounded = state.state | float | round(1) | replace(".",",") | replace(",0","") %}
            {{ state.name }} ist {{ state.state_with_unit | replace(state.state, localized_rounded) | replace("°C","Grad") | replace("°F","Grad") }}
          {% else %}
            {{ state.name }} ist {{ state.state_with_unit | replace(".", ",") | replace(",0","") }}
          {% endif %}
        {% endif %}

Use your own YAML custom sentence instead of interacting with the system intent. out values ​​are passed to intent_scripts.
All logic can be implemented in the text block.

Thanks, that is interesting to see: the intent_script passes different variables to the response templates than the default conversation agent. :thinking:

I quite like the matching engine in the system intents. But I’ll consider switching to intent_script for this instance.

Is this a general recommendation? That is: Prefer intent_script over interfacing with system intents? If so: why is the one preferrable over the other? I am just setting up my voice assistant, so it is not too late to adopt some architectural advice…

This is the legacy way to create voice automation (custom sentences) and it supports lists. GUI editor still doesn’t have this feature. I believe this is a more optimal way to solve your task.

Moreover, I have been using something similar myself for several years now.