Using Chat GPT json response in an automation

After trying to use chat gpt to help me build an automation, I’ve come to the end of my rope and back to the real experts.

I have a well running automation which announces events from my calendar 45 min ahead of their start time. It has random phrases and uses amazon polly. But, its become a little repetitive, even with the randomness, and I wanted to see if chat gpt could help.
Turns out I can send a request to the OpenAI API and get a response back, but I’m struggling to parse the json and feed the text into my TTS script.

So far I have this Rest Command:

rest_command:
  generate_calendar_prompt:
    url: "https://api.openai.com/v1/chat/completions"
    method: POST
    headers:
      Authorization: "Bearer !secret openai_api_key"
      Content-Type: "application/json"
    payload: >
      {
        "model": "gpt-3.5-turbo",
        "messages": [
          {
            "role": "system",
            "content": "You are a friendly assistant providing natural responses to calendar events."
          },
          {
            "role": "user",
            "content": "Create a varied, natural announcement for an event called '{{ event_title }}', starting at '{{ event_start }}'. Make it fun and a little snarky but do not include any emojis. Keep it less than 200 characters"
          }
        ],
        "temperature": 0.7
        }
    content_type: "application/json; charset=utf-8"

When I try this in the developer tools I get a good response (also tried it with curl in terminal and works well)

content:
  id: chatcmpl-AeXHZSe5oE8RYXkOiWbcVu5Ppc88g
  object: chat.completion
  created: 1734224421
  model: gpt-3.5-turbo-0125
  choices:
    - index: 0
      message:
        role: assistant
        content: >-
          Alright everyone, it's time for Kids Bedtime! Get your little ones
          ready to wind down and enjoy a cozy evening at 9:52 PM on December 6,
          2024. Let's make bedtime fun!
        refusal: null
      logprobs: null
      finish_reason: stop
  usage:
    prompt_tokens: 85
    completion_tokens: 45
    total_tokens: 130
    prompt_tokens_details:
      cached_tokens: 0
      audio_tokens: 0
    completion_tokens_details:
      reasoning_tokens: 0
      audio_tokens: 0
      accepted_prediction_tokens: 0
      rejected_prediction_tokens: 0
  system_fingerprint: null
status: 200

If I plug the json into the template demo, I am able to extract the text properly with:

{{ value_json["choices"][0].message.content }}

BUT, when I try to bring it all together in the final automation, it’s just not working. I’m stuck.

- id: "1733272058982"
  alias: Family Reminders ChatGPT
  description: remind family of events using Chat GPT
  triggers:
    - trigger: calendar
      event: start
      entity_id: calendar.family
      offset: -0:45:0
  conditions:
    - condition: time
      before: "23:00:00"
      after: 07:30:00
      weekday:
        - sun
        - mon
        - tue
        - wed
        - thu
        - fri
        - sat
    - condition: state
      entity_id: input_boolean.vacation_mode
      state: "off"
  actions:
    - action: rest_command.generate_calendar_prompt
      metadata: {}
      data:
        event_title: "{{ trigger.calendar_event.summary }}"
        event_start: "{{ trigger.calendar_event.start }}"
      response_variable: gpt_response
    - delay:
        hours: 0
        minutes: 0
        seconds: 5
        milliseconds: 0
    - alias: Parse GPT Response
      variables:
        content: " {{ gpt_response['choices'][0].message.content }} "
    - action: script.voice_announcement_gpt
      metadata: {}
      data:
        message: "{{ content }}"
  mode: queued

Thanks all for the help in advance!

What does the trace show for the value of gpt_response in the “Changed Variables” section?

I get an error.
Error: UndefinedError: ‘dict object’ has no attribute ‘choices’

BUT, in the trace for the rest command itself (within the automation), I do get the response as follows:

context:
  id: 01JF5DAPC3884DKJJEKHY7A0X2
  parent_id: null
  user_id: null
gpt_response:
  content:
    id: chatcmpl-AekO8rUPwOnLvXmIeeFdZqCpHbqVU
    object: chat.completion
    created: 1734274800
    model: gpt-3.5-turbo-0125
    choices:
      - index: 0
        message:
          role: assistant
          content: >-
            Get ready to celebrate Toad's Birthday on December 15, 2024, at
            10:45 AM EST! Join us for a fun-filled event to make Toad's special
            day unforgettable.
          refusal: null
        logprobs: null
        finish_reason: stop
    usage:
      prompt_tokens: 86
      completion_tokens: 41
      total_tokens: 127
      prompt_tokens_details:
        cached_tokens: 0
        audio_tokens: 0
      completion_tokens_details:
        reasoning_tokens: 0
        audio_tokens: 0
        accepted_prediction_tokens: 0
        rejected_prediction_tokens: 0
    system_fingerprint: null
  status: 200

Hello Cowboy-Ry,

I’m not good at this JSON stuff, but I’m thinking this maybe?

OK I figured it out with some additional help from ChatGPT. Here is the final automation!

- id: "1733272058982"
  alias: Family Reminders ChatGPT
  description: remind family of events using Chat GPT
  triggers:
    - trigger: calendar
      event: start
      entity_id: calendar.family
      offset: -0:45:0
  conditions:
    - condition: time
      before: "23:00:00"
      after: 07:30:00
      weekday:
        - sun
        - mon
        - tue
        - wed
        - thu
        - fri
        - sat
    - condition: state
      entity_id: input_boolean.vacation_mode
      state: "off"
  actions:
    - action: rest_command.generate_calendar_prompt
      metadata: {}
      data:
        event_title: "{{ trigger.calendar_event.summary }}"
      response_variable: gpt_response
    - delay:
        hours: 0
        minutes: 0
        seconds: 3
        milliseconds: 0
    - alias: Parse GPT Response
      variables:
        announcement: >
          {% if gpt_response and gpt_response['content'] and 'choices' in gpt_response['content'] %}
            {{ gpt_response['content']['choices'][0]['message']['content'] }}
          {% else %}
            "Error: Invalid or empty response from GPT."
          {% endif %}
    - action: script.voice_announcement_gpt
      metadata: {}
      data:
        message: "{{ announcement }}"
  mode: queued