How to create multiple phrases to send at random to TTS?

I tried this in my early HA days years ago. The below is what was created with help from this forum. We’ve since updated to new phones and I never bothered updating this automation, it’s just been turned off. I should really try to resurrect it. Hopefully this code helps you.

alias: 'Welcome Home'
trigger:
  - platform: state
    entity_id:
      - person.dave
      - person.rowe
    to: 'home'
condition:
  - condition: template
    value_template: '{{as_timestamp(now()) - as_timestamp(states.group.all_tracked_devices.last_changed) < 60 }}'   
action:
  - wait_template: "{{ is_state('binary_sensor.passage_multi_sensor_sensor', 'on') }}"
    timeout: 00:05:00
  - service: tts.google_translate_say
    entity_id: media_player.lounge_mini
    data_template:
      message: >
        Welcome home,
        {%- set name1 = state_attr('device_tracker.davess7lan','friendly_name') %}
        {%- set name2 = state_attr('device_tracker.rowess7lan','friendly_name') %}
        {%- if is_state('device_tracker.davess7lan','home') and
               is_state('device_tracker.rowess7lan','home') -%}
          {{ ' ' + name1 + ' and ' + name2 }}
        {%- else -%}
          {{ ' ' + trigger.to_state.attributes.friendly_name }}
        {%- endif %}!

As I say, it’s very old code (~4 yrs or more) so it may not be completely correct with today’s HA rules.

I know the original post is from 2017, but people are still commenting, and so I figure I’ll join in and do a little but of show and tell.

When I play something on Plex in the master bedroom, the nightstand speaker announces what’s playing.

In that TTS call I had 40+ phrases that I tried to have the random command handle, like this:

{{[
  'phrase 1',
  'phrase 2',
  'phrase 3,
  'phrase 4',
...
  'phrase 40-something'
]|random }}

It struggled a bit to give me truly random results. For over a week it would just repeat the same few phrases.

So I asked ChatGPT for some advice.

Hi everybody from 2017! We made it to 2023. We have ChatGPT now, but not flying cars

ChatGPT said I had too many phrases in the command, and suggested that I break them apart into groups.

So I created a temp variable, assigned a random number to it, grouped the phrases into buckets, then used basic if else logic to match the value of the temp variable. Each bucket contained a list of 5 phrases that were then chosen randomly.

It’s worth noting that I’m using macros for my TTS scripts. I find it’s easier to keep them all contained in the same place, and the developer tools plays nice with testing them. I followed SlackerLabs lead on using Macros: https://www.youtube.com/watch?v=XiLD9kgfXNI

Anyways, here’s my code:

  {% set rand = range(1,9)|random %}
  {% if rand == 1 %}
  {{[ 
  'Ohh, yay, its',
  'Yaaas queen, its',
  'Yoooo, check it, its',
  'Hurray, lets watch',
  'Such wow, so amaze, its'
  ] |random }} 

  {% elif rand == 2 %}
  {{[ 
  'Sweet, its',
  'Oh my goodness, its',
  'Golly gee its',
  'Jeepers, its',
  'Geewillikers, its'
  ] |random }} 

  {% elif rand == 3 %}
  {{[ 
  'Gee whiz, its',
  'Hot dog, its',
  'Holy cow, its',
  'Groovy, its',
  'Hot diggidy, its'
  ] |random }} 
  
  {% elif rand == 4 %}
  {{[
  'Awesome sauce, its',
  'Whoa, dude, its',
  'Right on, its',
  'Oh my gosh, its',
  'Oh m gee, its'
  ]|random }} 
  
  {% elif rand == 5 %}
  {{[
  'Ermahgard, its',
  'Wowzers, its',
  'Oh youre going to love this, its',
  'Yippee kai yay, its',
  'Okay, see, now Im excited, its'
  ]|random }} 
  
  {% elif rand == 6 %}
  {{[
  'Holy moly, its',
  'Oh my word, its',
  'Oh my goodness gracious, its',
  'Whoa there, its',
  'Whoa nelly, its'
  ]|random }} 
  
  {% elif rand == 7 %}
  {{[
  'Holy mackerel, its',
  'Oh my stars, its',
  'Holy smokes, its',
  'Oh goodness gracious me, its',
  'Woop woop, turn up, its'
  ]|random }} 
  
  {% elif rand == 8 %}
  {{[
  'Boss move, brah. Its',
  'Got damn fam, nice choice. Its',
  'Like, I like, literally like cant, its',
  'Wait, wait. What? its',
  'Oh man, its'
  ]|random }} 
  
  {% elif rand == 9 %}
  {{[
  'Listen up, its',
  'Yo yo yo, its',
  'Mamma mia, its'
  ]|random }} 
  {% else %}
  {% endif %}


  {# Name of Show #}
    {{((state_attr('media_player.plex_master_bedroom', 'media_series_title'))) }}
  
  season 
    {{((state_attr('media_player.plex_master_bedroom', 'media_season'))) }}
  
  episode
    {{((state_attr('media_player.plex_master_bedroom', 'media_episode'))) }}.
  
  This one is called
    {{((state_attr('media_player.plex_master_bedroom', 'media_title'))) }}.

That code runs pretty quickly and outputs something like:

Ermahgard, its Game of Thrones Season 1 episode one. This one is called Winter is Coming.

Wife approves.

2 Likes

I created alexa_confirm.yaml file in config folder and added this line text: !include alexa_confirm.yaml under /config/configuration.yaml, but that make configuration invalid!

Configuration invalid!

Invalid config for [text]: expected a dictionary. Got {'python_script': {}, 'default_config': {}, 'frontend': {'themes': {'ios-dark-mode': {'background-image': "center / cover no-repeat fixed url('data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QBMRXhpZgAATU0AKgAAAAgAAgESAAMAAAABAAEAAIdpAAQAAAABAAAAJgAAAAAAAqACAAQAAAABAAAMiKADAAQAAAABAAAMiAAAAAD/7QA4UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAA4QklNBCUAAAAAABDUHYzZjwCyBOmACZjs+EJ+/+IH6ElDQ19QUk9GSUxFAAEBAAAH2GFwcGwCIAAAbW50clJHQiBYWVogB9kAAgAZAAsAGgALYWNzcEFQUEwAAAAAYXBwbAAAAAAAAAAAAAAAAAAAAAAAAPbWAAE.... (See /config/configuration.yaml, line 988).

I think this is wrong, text: !include alexa_confirm.yaml

text: !include alexa_confirm.yaml only works within the HA intent_script integration where there is

speech:
  text: ...

It does not work for message: within an automation or script when calling the related service.

The intent_script integration works with Google, Home Assist (I think) or an Alexa custom skill you’ve created which has intents and where you have to say “Alexa, ask Home Assistant to…”.

That is just totally wrong! You can’t put text: in configuraton.yaml!

Hi! Can anyone please post a working solution for random text pick for TTS, working with last HA release? It’s looks like it should be possible to use helpers for this purpose, but I was unable to create a working YAML.
Can anyone share a working solution? Thanks!

have this type of code in your TTS message section:

      message: >
        '{{ ["Kingsleys flea treatment is due", "Its that time again, Kingsley
        wants his flea treatment chew", "Kingsley loves a good flea treatment. 
        The time has come"] | random }}'
1 Like

Thank you for for your sample! However, it will be a mess to handle say 50 text entries. I believe it’s possible to utilize input-select helper to work with easy manageable list of entries.

You can split the text out so each one is on it’s own line which would neaten it up. Using an input text helper should be doable but I haven’t tried so don’t have an example. I’ll see if I can figure it out though.

Something along these lines:

message: "{{states('input_text.tts_announcement_text') | random}}"

…but that is untested and likely not quite correct.

EDIT: that is definietly wrong… you would still need all 50 text items in that single input_text so it is no better than my previous example.

I’ve had some success using Macros to achieve this. Check out this thread:

yeah cool, but it’s not really much easier than my option, I mean you still can’t edit the list via the UI so a restart is likely required for any changes. I liked your idea of a text helper because it would mean editing from the frontend without any restart/reload required.

How can make it not saying the same option if it said it that before for example if it say “Halloween 1” the for the next 10 minutes not say it again. Thanks!!!:pray:

So I took slightly different approach to ‘random’, instead of building the list of predefined sentences, I ask OpenAI to generate message for me. This way I have one automation, but endless selection of random text. Here is sample code for entering/leaving specific zone.

  - alias: zone ChatGPT TTS notifications
    id: zone_chatgpt_tts_notifications
    mode: queued
    initial_state: true
    trigger:
      - platform: zone
        entity_id: person.mirek_malinowski, person.dorota_malinowska
        zone: zone.home
        event: enter
      - platform: zone
        entity_id: person.mirek_malinowski, person.dorota_malinowska
        zone: zone.home
        event: leave

        # More zones goes  here

    action:
      - service: conversation.process
        data:
          agent_id: id_redacted
          text: |
            {% if (trigger.event) == "leave" %}
              Prepare humorous notification about {{ trigger.to_state.attributes.friendly_name }} being now outside of {{ trigger.zone.attributes.friendly_name }}, using no more than 15 words and not using emoji.
            {% else %}
              Prepare humorous notification about {{ trigger.to_state.attributes.friendly_name }} being now close to {{ trigger.zone.attributes.friendly_name }}, using no more than 15 words and not using emoji.
            {% endif %}
        response_variable: chatgpt
      - service: tts.cloud_say
        data_template:
          entity_id: media_player.google_home_mini
          language: pl-PL
          message: |
            {{chatgpt.response.speech.plain.speech | trim | replace('\"','')}}
2 Likes

That is great and far more flexible and scalable.

What integration are using for openAI that enables the conversation.process service?

I’m using HA native OpenAI Conversation integration.

1 Like

Would you consider pulling this chatgpt random script together into a ‘Community Guideline’ and adding it to the Cookbook we are creating here on the forums?
The Home Assistant Cookbook - Index.
I think it would be a fantastic addition, and since it is your code and idea, I ddn’t want to just copy you to get it there.

(It might also make a really nice script blueprint to share as you already have the code debugged…)

@Stiltjack FYI…

1 Like

Using @mirekmal’s example, I created a script called Get ChatGPT response with field values for parts of the chatgpt prompt so I can seamlessly reuse the script within my automations.

I couldn’t figure out how to pass the script response directly into another action, so I created an Input Text helper first to house the ChatGPT response each time.

alias: Get ChatGPT response
sequence:
  - service: conversation.process
    data:
      agent_id: id_redacted
      text: >-
        Prepare a {{tone}} notification about "{{subject}}" using no more than
        {{length}} words and not using any emoji.
    response_variable: chatgpt
    alias: ChatGPT Prompt
    enabled: true
  - service: input_text.set_value
    metadata: {}
    data:
      value: "{{chatgpt.response.speech.plain.speech | trim | replace('\\\"','')}}"
    target:
      entity_id: input_text.chatgpt_response
fields:
  subject:
    selector:
      text: null
    name: subject
    description: What do you want to do?
    required: true
  tone:
    selector:
      text: null
    name: tone
    description: Describes the tone you want to add to the ChatGPT request.
    required: true
  length:
    selector:
      text: null
    name: length
    description: How many words do you want to limit the response to?
    default: "15"
    required: true
icon: mdi:robot-excited
mode: single

In my automations, I first call the script above, then add the following template wherever I want to include the response:
"{{ states('input_text.chatgpt_response') }}"

Seems to work pretty well so far.

3 Likes

‘tone’ … Thanks for that, I have a new input select

  • cheeky
  • sarcastic
  • informational
  • bombastic
  • disinterested
  • scathing
  • amorous
  • angry