|
@@ -1,367 +0,0 @@
|
|
|
-blueprint:
|
|
|
|
|
- name: AI Event Summary (v1.4.1)
|
|
|
|
|
- author: valentinfrlch
|
|
|
|
|
- description: 'AI-powered summaries for security camera events. Sends a notification
|
|
|
|
|
- with a preview to your phone that is updated dynamically when the AI summary is
|
|
|
|
|
- available.
|
|
|
|
|
-
|
|
|
|
|
- '
|
|
|
|
|
- domain: automation
|
|
|
|
|
- source_url: https://raw.githubusercontent.com/valentinfrlch/ha-llmvision/refs/heads/main/blueprints/event_summary.yaml
|
|
|
|
|
- input:
|
|
|
|
|
- important:
|
|
|
|
|
- name: Important (Experimental)
|
|
|
|
|
- description: 'Use AI to classify events as Critical, Normal or Low. Notifications
|
|
|
|
|
- are sent only for events classified as Normal or higher. Critical events override
|
|
|
|
|
- ''Do Not Disturb'' settings. Use with caution: AI can make mistakes.
|
|
|
|
|
-
|
|
|
|
|
- '
|
|
|
|
|
- default: false
|
|
|
|
|
- selector:
|
|
|
|
|
- boolean: {}
|
|
|
|
|
- remember:
|
|
|
|
|
- name: Remember
|
|
|
|
|
- description: Stores this event in the Timeline so you can ask about it. If important
|
|
|
|
|
- is enabled, only events classified as Normal or Critical will be saved.
|
|
|
|
|
- default: false
|
|
|
|
|
- selector:
|
|
|
|
|
- boolean: {}
|
|
|
|
|
- use_memory:
|
|
|
|
|
- name: Use Memory
|
|
|
|
|
- description: Use information stored in memory to provide additional context.
|
|
|
|
|
- Memory must be set up.
|
|
|
|
|
- default: false
|
|
|
|
|
- selector:
|
|
|
|
|
- boolean: {}
|
|
|
|
|
- message:
|
|
|
|
|
- name: Prompt
|
|
|
|
|
- description: Model prompt for the video_analyzer action
|
|
|
|
|
- default: 'Summarize the events based on a series of images captured at short
|
|
|
|
|
- intervals. Focus only on moving subjects such as people, vehicles, and other
|
|
|
|
|
- active elements. Ignore static objects and scenery. Provide a clear and concise
|
|
|
|
|
- account of movements and interactions. Do not mention or imply the existence
|
|
|
|
|
- of images—present the information as if directly observing the events. If
|
|
|
|
|
- no movement is detected, respond with: ''No activity observed.'''
|
|
|
|
|
- selector:
|
|
|
|
|
- text:
|
|
|
|
|
- multiline: true
|
|
|
|
|
- multiple: false
|
|
|
|
|
- run_conditions:
|
|
|
|
|
- name: Run Conditions
|
|
|
|
|
- description: All conditions must be true in order for the blueprint to run.
|
|
|
|
|
- default: []
|
|
|
|
|
- selector:
|
|
|
|
|
- condition: {}
|
|
|
|
|
- notify_device:
|
|
|
|
|
- name: Notify Device
|
|
|
|
|
- description: The devices to send the notification to. Multiple devices may be
|
|
|
|
|
- used. Only works with Home Assistant mobile app.
|
|
|
|
|
- default: []
|
|
|
|
|
- selector:
|
|
|
|
|
- device:
|
|
|
|
|
- multiple: true
|
|
|
|
|
- filter:
|
|
|
|
|
- - integration: mobile_app
|
|
|
|
|
- notification_delivery:
|
|
|
|
|
- name: Notification Delivery
|
|
|
|
|
- description: "Controls how notifications are delivered. \n \n **Dynamic** immediately
|
|
|
|
|
- notifies with a live preview and updates the notification silently with a
|
|
|
|
|
- summary once it is available. \n **Consolidated** Delays the notification
|
|
|
|
|
- until the event summary is generated. Use this if you're receiving multiple
|
|
|
|
|
- notifications for the same event."
|
|
|
|
|
- default: Dynamic
|
|
|
|
|
- selector:
|
|
|
|
|
- select:
|
|
|
|
|
- options:
|
|
|
|
|
- - Dynamic
|
|
|
|
|
- - Consolidated
|
|
|
|
|
- custom_value: false
|
|
|
|
|
- multiple: false
|
|
|
|
|
- sort: false
|
|
|
|
|
- camera_entities:
|
|
|
|
|
- name: Camera Entities
|
|
|
|
|
- description: List of camera entities to monitor
|
|
|
|
|
- default: []
|
|
|
|
|
- selector:
|
|
|
|
|
- entity:
|
|
|
|
|
- multiple: true
|
|
|
|
|
- filter:
|
|
|
|
|
- - domain:
|
|
|
|
|
- - camera
|
|
|
|
|
- trigger_state:
|
|
|
|
|
- name: Trigger State
|
|
|
|
|
- description: Automation starts when one of your camera changes to this state.
|
|
|
|
|
- default: recording
|
|
|
|
|
- selector:
|
|
|
|
|
- text:
|
|
|
|
|
- multiline: false
|
|
|
|
|
- multiple: false
|
|
|
|
|
- motion_sensors:
|
|
|
|
|
- name: Motion Sensor
|
|
|
|
|
- description: Set if your cameras don't change state (Frigate). Use the same
|
|
|
|
|
- order used for camera entities.
|
|
|
|
|
- default: []
|
|
|
|
|
- selector:
|
|
|
|
|
- entity:
|
|
|
|
|
- multiple: true
|
|
|
|
|
- filter:
|
|
|
|
|
- - domain:
|
|
|
|
|
- - binary_sensor
|
|
|
|
|
- preview_mode:
|
|
|
|
|
- name: Preview Mode
|
|
|
|
|
- description: "Choose between a live preview or a snapshot of the event. \n\n
|
|
|
|
|
- **Important:** Live Preview is only supported on iOS."
|
|
|
|
|
- default: Snapshot
|
|
|
|
|
- selector:
|
|
|
|
|
- select:
|
|
|
|
|
- options:
|
|
|
|
|
- - Snapshot
|
|
|
|
|
- - Live Preview
|
|
|
|
|
- custom_value: false
|
|
|
|
|
- multiple: false
|
|
|
|
|
- sort: false
|
|
|
|
|
- cooldown:
|
|
|
|
|
- name: Cooldown
|
|
|
|
|
- description: Time in minutes to wait before running again. Strongly recommended
|
|
|
|
|
- for busy areas.
|
|
|
|
|
- default: 10
|
|
|
|
|
- selector:
|
|
|
|
|
- number:
|
|
|
|
|
- min: 0.0
|
|
|
|
|
- max: 60.0
|
|
|
|
|
- mode: slider
|
|
|
|
|
- step: 1.0
|
|
|
|
|
- tap_navigate:
|
|
|
|
|
- name: Tap Navigate
|
|
|
|
|
- description: Home Assistant dashboard to navigate to when notification is opened
|
|
|
|
|
- (e.g. /lovelace/cameras).
|
|
|
|
|
- default: /lovelace/0
|
|
|
|
|
- selector:
|
|
|
|
|
- text:
|
|
|
|
|
- multiline: false
|
|
|
|
|
- multiple: false
|
|
|
|
|
- duration:
|
|
|
|
|
- name: Duration
|
|
|
|
|
- description: Duration to record for analysis (in seconds).
|
|
|
|
|
- default: 5
|
|
|
|
|
- selector:
|
|
|
|
|
- number:
|
|
|
|
|
- min: 1.0
|
|
|
|
|
- max: 60.0
|
|
|
|
|
- mode: slider
|
|
|
|
|
- step: 1.0
|
|
|
|
|
- max_frames:
|
|
|
|
|
- name: Max Frames
|
|
|
|
|
- description: How many frames to analyze. Picks frames with the most movement.
|
|
|
|
|
- default: 3
|
|
|
|
|
- selector:
|
|
|
|
|
- number:
|
|
|
|
|
- min: 1.0
|
|
|
|
|
- max: 60.0
|
|
|
|
|
- mode: slider
|
|
|
|
|
- step: 1.0
|
|
|
|
|
- provider:
|
|
|
|
|
- name: Provider
|
|
|
|
|
- description: Provider to use for analysis. See docs for additional information.
|
|
|
|
|
- selector:
|
|
|
|
|
- config_entry:
|
|
|
|
|
- integration: llmvision
|
|
|
|
|
- model:
|
|
|
|
|
- name: Model
|
|
|
|
|
- description: Which model to use. Depends on chosen provider.
|
|
|
|
|
- default: gpt-4o-mini
|
|
|
|
|
- selector:
|
|
|
|
|
- text:
|
|
|
|
|
- multiline: false
|
|
|
|
|
- multiple: false
|
|
|
|
|
- target_width:
|
|
|
|
|
- name: Target Width
|
|
|
|
|
- description: Downscale images (uses less tokens and speeds up processing)
|
|
|
|
|
- default: 1280
|
|
|
|
|
- selector:
|
|
|
|
|
- number:
|
|
|
|
|
- min: 512.0
|
|
|
|
|
- max: 3840.0
|
|
|
|
|
- mode: slider
|
|
|
|
|
- step: 1.0
|
|
|
|
|
- max_tokens:
|
|
|
|
|
- name: Maximum Tokens
|
|
|
|
|
- description: Maximum number of tokens to generate. Use this to control the length
|
|
|
|
|
- of the summaries.
|
|
|
|
|
- default: 20
|
|
|
|
|
- selector:
|
|
|
|
|
- number:
|
|
|
|
|
- min: 1.0
|
|
|
|
|
- max: 100.0
|
|
|
|
|
- mode: slider
|
|
|
|
|
- step: 1.0
|
|
|
|
|
- temperature:
|
|
|
|
|
- name: Temperature
|
|
|
|
|
- description: Randomness. Lower is more accurate, higher is more creative.
|
|
|
|
|
- default: 0.1
|
|
|
|
|
- selector:
|
|
|
|
|
- number:
|
|
|
|
|
- min: 0.1
|
|
|
|
|
- max: 1.0
|
|
|
|
|
- step: 0.1
|
|
|
|
|
- mode: slider
|
|
|
|
|
-variables:
|
|
|
|
|
- important: !input important
|
|
|
|
|
- remember: !input remember
|
|
|
|
|
- cooldown: !input cooldown
|
|
|
|
|
- preview_mode: !input preview_mode
|
|
|
|
|
- notify_devices: !input notify_device
|
|
|
|
|
- notification_delivery: !input notification_delivery
|
|
|
|
|
- device_name_map: "{% set ns = namespace(device_names=[]) %} {% for device_id in
|
|
|
|
|
- notify_devices %}\n {% set device_name = device_attr(device_id, \"name\") %}\n
|
|
|
|
|
- \ {% set sanitized_name = \"mobile_app_\" + device_name | slugify %}\n {% set
|
|
|
|
|
- ns.device_names = ns.device_names + [sanitized_name] %}\n{% endfor %} {{ ns.device_names
|
|
|
|
|
- }}\n"
|
|
|
|
|
- camera_entities_list: !input camera_entities
|
|
|
|
|
- motion_sensors_list: !input motion_sensors
|
|
|
|
|
- camera_entity: "{% if motion_sensors_list and not trigger.entity_id.startswith(\"camera\")
|
|
|
|
|
- %}\n {% set index = motion_sensors_list.index(trigger.entity_id) %}\n {{ camera_entities_list[index]
|
|
|
|
|
- }}\n{% else %}\n {{ trigger.entity_id }}\n{% endif %}\n"
|
|
|
|
|
- tag: '{{ camera_entity + int(as_timestamp(now()))|string }}
|
|
|
|
|
-
|
|
|
|
|
- '
|
|
|
|
|
- group: '{{ camera_entity }}
|
|
|
|
|
-
|
|
|
|
|
- '
|
|
|
|
|
- label: Motion detected
|
|
|
|
|
- camera: '{{ camera_entity.replace("camera.", "").replace("_", " ")|capitalize }}
|
|
|
|
|
-
|
|
|
|
|
- '
|
|
|
|
|
- importance_prompt: 'Classify the security event based on this image. Choose from
|
|
|
|
|
- the following options: "passive" for unimportant events, "time-sensitive" for
|
|
|
|
|
- notable but non-critical events such as a person at the front door, and "critical"
|
|
|
|
|
- only for potential burglaries or highly suspicious activity. Respond with one
|
|
|
|
|
- of these options exactly, without additional explanation.
|
|
|
|
|
-
|
|
|
|
|
- '
|
|
|
|
|
-max_exceeded: silent
|
|
|
|
|
-mode: single
|
|
|
|
|
-triggers:
|
|
|
|
|
-- trigger: state
|
|
|
|
|
- entity_id: !input camera_entities
|
|
|
|
|
- to: !input trigger_state
|
|
|
|
|
- id: camera_trigger
|
|
|
|
|
-- trigger: state
|
|
|
|
|
- entity_id: !input motion_sensors
|
|
|
|
|
- to: 'on'
|
|
|
|
|
- id: motion_sensor_trigger
|
|
|
|
|
-condition:
|
|
|
|
|
-- condition: and
|
|
|
|
|
- conditions: !input run_conditions
|
|
|
|
|
-action:
|
|
|
|
|
-- choose:
|
|
|
|
|
- - conditions:
|
|
|
|
|
- - condition: template
|
|
|
|
|
- value_template: '{{ important }}'
|
|
|
|
|
- sequence:
|
|
|
|
|
- - action: llmvision.image_analyzer
|
|
|
|
|
- data:
|
|
|
|
|
- image_entity: '{{[camera_entity]}}'
|
|
|
|
|
- provider: !input provider
|
|
|
|
|
- model: !input model
|
|
|
|
|
- message: '{{importance_prompt}}'
|
|
|
|
|
- include_filename: true
|
|
|
|
|
- target_width: 1280
|
|
|
|
|
- max_tokens: 3
|
|
|
|
|
- temperature: 0.1
|
|
|
|
|
- response_variable: importance
|
|
|
|
|
-- choose:
|
|
|
|
|
- - conditions:
|
|
|
|
|
- - condition: template
|
|
|
|
|
- value_template: '{{ important and importance.response_text|lower == ''passive''
|
|
|
|
|
- }}'
|
|
|
|
|
- sequence:
|
|
|
|
|
- - stop: Event is not important
|
|
|
|
|
-- choose:
|
|
|
|
|
- - conditions:
|
|
|
|
|
- - condition: template
|
|
|
|
|
- value_template: '{{ notification_delivery == ''Dynamic'' }}'
|
|
|
|
|
- sequence:
|
|
|
|
|
- - alias: Send instant notification to notify devices
|
|
|
|
|
- repeat:
|
|
|
|
|
- for_each: '{{device_name_map}}'
|
|
|
|
|
- sequence:
|
|
|
|
|
- - action: notify.{{ repeat.item }}
|
|
|
|
|
- data:
|
|
|
|
|
- title: '{{ label }}'
|
|
|
|
|
- message: '{{camera}} has detected activity.'
|
|
|
|
|
- data:
|
|
|
|
|
- entity_id: '{{camera_entity}}'
|
|
|
|
|
- url: !input tap_navigate
|
|
|
|
|
- clickAction: !input tap_navigate
|
|
|
|
|
- tag: '{{tag}}'
|
|
|
|
|
- group: '{{group}}'
|
|
|
|
|
- alert_once: true
|
|
|
|
|
- push:
|
|
|
|
|
- interruption-level: '{{importance.response_text|lower if importance
|
|
|
|
|
- is defined else ''active''}}'
|
|
|
|
|
-- alias: Analyze event
|
|
|
|
|
- action: llmvision.stream_analyzer
|
|
|
|
|
- data:
|
|
|
|
|
- image_entity: '{{[camera_entity]}}'
|
|
|
|
|
- duration: !input duration
|
|
|
|
|
- provider: !input provider
|
|
|
|
|
- model: !input model
|
|
|
|
|
- message: !input message
|
|
|
|
|
- use_memory: !input use_memory
|
|
|
|
|
- remember: !input remember
|
|
|
|
|
- expose_images: '{{preview_mode == ''Snapshot'' or remember}}'
|
|
|
|
|
- generate_title: !input remember
|
|
|
|
|
- include_filename: true
|
|
|
|
|
- max_frames: !input max_frames
|
|
|
|
|
- target_width: !input target_width
|
|
|
|
|
- max_tokens: !input max_tokens
|
|
|
|
|
- temperature: !input temperature
|
|
|
|
|
- response_variable: response
|
|
|
|
|
-- alias: Update label with title
|
|
|
|
|
- variables:
|
|
|
|
|
- label: '{{response.title}}'
|
|
|
|
|
-- choose:
|
|
|
|
|
- - conditions:
|
|
|
|
|
- - condition: template
|
|
|
|
|
- value_template: '{{ preview_mode==''Snapshot'' }}'
|
|
|
|
|
- sequence:
|
|
|
|
|
- - alias: (Snapshot) Update notification on notify devices
|
|
|
|
|
- repeat:
|
|
|
|
|
- for_each: '{{device_name_map}}'
|
|
|
|
|
- sequence:
|
|
|
|
|
- - action: notify.{{ repeat.item }}
|
|
|
|
|
- data:
|
|
|
|
|
- title: '{{ label }}'
|
|
|
|
|
- message: '{{response.response_text}}'
|
|
|
|
|
- data:
|
|
|
|
|
- image: '{{response.key_frame.replace(''/config/www/'',''/local/'') }}'
|
|
|
|
|
- url: !input tap_navigate
|
|
|
|
|
- clickAction: !input tap_navigate
|
|
|
|
|
- tag: '{{tag}}'
|
|
|
|
|
- group: '{{group}}'
|
|
|
|
|
- push:
|
|
|
|
|
- interruption-level: '{{''passive'' if notification_delivery==''Dynamic''
|
|
|
|
|
- else ''active''}}'
|
|
|
|
|
- - conditions:
|
|
|
|
|
- - condition: template
|
|
|
|
|
- value_template: '{{ preview_mode==''Live Preview'' }}'
|
|
|
|
|
- sequence:
|
|
|
|
|
- - alias: (Live Preview) Update notification on notify devices
|
|
|
|
|
- repeat:
|
|
|
|
|
- for_each: '{{device_name_map}}'
|
|
|
|
|
- sequence:
|
|
|
|
|
- - action: notify.{{ repeat.item }}
|
|
|
|
|
- data:
|
|
|
|
|
- title: '{{ label }}'
|
|
|
|
|
- message: '{{response.response_text}}'
|
|
|
|
|
- data:
|
|
|
|
|
- entity_id: '{{camera_entity}}'
|
|
|
|
|
- url: !input tap_navigate
|
|
|
|
|
- clickAction: !input tap_navigate
|
|
|
|
|
- tag: '{{tag}}'
|
|
|
|
|
- group: '{{group}}'
|
|
|
|
|
- push:
|
|
|
|
|
- interruption-level: '{{''passive'' if notification_delivery==''Dynamic''
|
|
|
|
|
- else ''active''}}'
|
|
|
|
|
-- delay: 00:{{cooldown|int}}:00
|
|
|