Later Edit: The implementation below has some negative (side) effects ! Read (also) the next post.
======================================
I think I did it
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:
- One “File” integration associated to my “log” file
- One Script which formats the message before being written in the log file
- One automation which is triggered when a sentence is spoken/written
Additionally I did also:
- [OPTIONAL] One “File Size” integration to monitor the log file size
- [OPTIONAL] One shell_command integration based on a custom bash script which renames a log file into something like thefile_004.log
- [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
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