Log to a file everything "discussed" with ChatGPT on all Voice Assist devices

I would like to introduce ChatGPT (through Voice Assistant PE) also to my kids.
Additionally I’m sure there will be situations to debug in controlling the house.
Question:
How to make a log (real file in Home Assistant) where to log everything it’s “discussed” ?
I would like to have 1 file (csv, xml, xls, whatever) with the following information:

  • date/time
  • device
  • owner (e.g.: ChatGpt or user)
  • message

How could I do this so that I see everything is asked and answered on all my Voice Assistant PE devices ?

Thanks

Later Edit: The implementation below has some negative (side) effects ! Read (also) the next post.

======================================

I think I did it :slight_smile:
With the big help from @renee1 in this answer How to save voice assistant responses? - #8 by renee1 , plus some adjustments, it seems to work.

Disclaimer: this is for the OpenAI (ChatGPT) option of Vocie Assist. I’m currently using fully ChatGPT without ‘Prefer handling commands locally’ option.

Shortly the steps:

  1. One “File” integration associated to my “log” file
  2. One Script which formats the message before being written in the log file
  3. One automation which is triggered when a sentence is spoken/written

Additionally I did also:

  1. [OPTIONAL] One “File Size” integration to monitor the log file size
  2. [OPTIONAL] One shell_command integration based on a custom bash script which renames a log file into something like thefile_004.log
  3. [OPTIONAL] One automation which renames the log file when bigger than 1MB

(1) The File Integration:

Following this : File - Home Assistant , I created a file notification integration based on a logfile I defined myself. (e.g.: /config/log/myLogFiles/myVoiceAssistLog.log). When you “notify” mesages “into” this file, they are written in the log file.

Then … just to have a friendlier name, I renamed the entity created from “notify.file” to “notify.myvoiceassistantlog”

PS. I have in my configuration.yaml :

# Used by File integrations (check my custom logfiles)
homeassistant:
  allowlist_external_dirs:
    - /config/log

(2) The Script for writing in the log file

I created this only to be able to add details in all messages … like the Date/Time. When you run this script with a string / a message, that line will appear in the log file

sequence:
  - metadata: {}
    data:
      message: "{{ now().strftime('%Y-%m-%d %H:%M:%S,%f')}} ; {{message}}"
    target:
      entity_id: notify.myvoiceassistantlog
    action: notify.send_message
alias: write to my VoiceAssist log
mode: single
fields:
  message:
    selector:
      text: null
    name: message
    description: The given message will be added in the log file and it will have date and time as prefix
    required: true
description: ""

(3) The automation:

That’s the core of the solution :slight_smile:

alias: Log Voice Assist Conversations (ChatGPT)
description: ""
triggers:
  - trigger: conversation
    command: "{question}"
conditions: []
actions:
  - action: conversation.process
    metadata: {}
    data:
      agent_id: conversation.chatgpt
      text: "{{ trigger.slots.question }}"
    response_variable: chatgpt
  - set_conversation_response: "{{ chatgpt.response.speech.plain.speech }}"
  - if:
      - condition: template
        value_template: "{{trigger.device_id is not none}}"
        alias: If we have a 'device_id'
    then:
      - action: script.write_to_my_voiceassist_log
        metadata: {}
        data:
          message: >-
            name='{{ device_attr(trigger.device_id, "name") }}' ;
            area='{{area_name(trigger.device_id)}}' ;
            question='{{trigger.slots.question }}' ;
            answer='{{chatgpt.response.speech.plain.speech }}'
    else:
      - action: script.write_to_my_voiceassist_log
        metadata: {}
        data:
          message: >-
            name='Assist Popup' ; area='PC Browser' ;
            question='{{trigger.slots.question }}' ;
            answer='{{chatgpt.response.speech.plain.speech }}'
mode: single

(4,5,6) Optional points

(4) File Size Integration
Based on File size - Home Assistant I created an integration for the given log file path.

(5) shell_command
In configuration.yaml I’ve added this:

shell_command:
  rename_log_file: bash /config/myBashScripts/rename_log_file.sh

and the bash script content is:

#!/bin/bash

# The script recevied one filepath as input and it's doing 3 things:
# - Finding the first available number for a flle name in the format: theFile_123.log
# - Moves the given file to the new numbered name
# - Creates a empty initial file in place of the original one
# e.g.: from myLogFile.log it will create myLogFile_001.log, if it exists, then myLogFile_002.log, etc

src_file_path="$1"
if [ -n "$src_file_path" ]; then
    if [ -f $src_file_path ]; then
        #echo "not empty"
        filename="${src_file_path##*/}"                 # Strip longest match of */ from start
        dir="${src_file_path:0:${#src_file_path} - ${#filename}}" # Substring from 0 thru pos of filename
        base="${filename%.[^.]*}"                       # Strip shortest match of . plus at least one non-dot char from end
        ext="${filename:${#base} + 1}"                  # Substring from len of base thru end
        if [[ -z "$base" && -n "$ext" ]]; then          # If we have an extension and no base, it's really the base
            base=".$ext"
            ext=""
        fi
        #echo -e "$src_file_path:\n\tdir  = \"$dir\"\n\tbase = \"$base\"\n\text  = \"$ext\""
        i=1
        while (( i < 999 )); do
            dest_file_path=$(printf "%s%s_%03d.%s" $dir $base $i $ext)
            #echo $dest_file_path
            if [ ! -f $dest_file_path ]; then
                # File name is available
                mv $src_file_path $dest_file_path
                touch $src_file_path #Create dummy empty initial file
                echo "moved file: '$src_file_path' to: '$dest_file_path'"
                i=1001 # force to stop while command
            fi
            i=$((i + 1))
        done
    else
        echo "ERROR: File not existing or no permission to access $src_file_path" 1>&2
        exit 78 
    fi
else
    echo "ERROR: No filepath given as parameter" 1>&2
    exit 194 
fi

(6) The automation for renaming the log file

When the log file size is over 1MB, I move it aside using the above shell_comand.

alias: watchdog log file size
description: ""
mode: single
triggers:
  - trigger: numeric_state
    entity_id:
      - sensor.myvoiceassistlog_log_size
    above: 1
conditions: []
actions:
  - action: shell_command.rename_log_file
    metadata: {}
    data:
      filepath: /config/log/myLogFiles/myVoiceAssistLog.log

I hope I didn’t missed anything (or messed-up things) when copying & pasting here :slight_smile:

1 Like

It seems that with the previous implementation there are some effects I was not aware of :

  • Only one chat agent is used (because of the conversation.process action which redirects directly to a dedicated agent_id
  • The “fallback to local agent” doesn’t work
  • Somehow it looks like it starts a new “session” with chatgpt each time. If I disable the automation, chatgpt remembers what the previous question was, but with this automation it doesn’t remember.

I will dig more for improved/other/better solution.

I’m testing now, and it seems to work:
I replaced point number (3) from above with … adopting Vocie PE in ESPHome Builder and adding this:

voice_assistant:
  on_stt_end:
    - homeassistant.action:
        action: script.write_to_my_voiceassist_log
        data:
          message: !lambda return ("name='${friendly_name}' ; question='" + x +"'");
  on_tts_start:
    - homeassistant.action:
        action: script.write_to_my_voiceassist_log
        data:
          message: !lambda return ("name='${friendly_name}' ; answer='" + x +"'");

It seems to work, for now. But I will confirm later if I find it ok . (If anyone can confirm if this approch can have side effects, please comment :slight_smile: )

LaterEdit
1.: After ~10 days → It works ok for any VoicePE satellite.
2.: Forgot to mention, you need to: “Allow the device to perform Home Assistant actions” from Devices-EspHome-VoicePE_Device-Configure

That doesn’t go across all satellites or for typing conversations though :frowning: seems like for an event we can hook into after any conversation is processed though!

I added the second Voice PE sattelite and (after I applied the same change on adoption as in my previous post) then it works also for it.
Indeed it doesn’t work for the Assist on the browser.