event_summary.yaml 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. blueprint:
  2. name: AI Event Summary (v1.4.1)
  3. author: valentinfrlch
  4. description: 'AI-powered summaries for security camera events. Sends a notification
  5. with a preview to your phone that is updated dynamically when the AI summary is
  6. available.
  7. '
  8. domain: automation
  9. source_url: https://raw.githubusercontent.com/valentinfrlch/ha-llmvision/refs/heads/main/blueprints/event_summary.yaml
  10. input:
  11. important:
  12. name: Important (Experimental)
  13. description: 'Use AI to classify events as Critical, Normal or Low. Notifications
  14. are sent only for events classified as Normal or higher. Critical events override
  15. ''Do Not Disturb'' settings. Use with caution: AI can make mistakes.
  16. '
  17. default: false
  18. selector:
  19. boolean: {}
  20. remember:
  21. name: Remember
  22. description: Stores this event in the Timeline so you can ask about it. If important
  23. is enabled, only events classified as Normal or Critical will be saved.
  24. default: false
  25. selector:
  26. boolean: {}
  27. use_memory:
  28. name: Use Memory
  29. description: Use information stored in memory to provide additional context.
  30. Memory must be set up.
  31. default: false
  32. selector:
  33. boolean: {}
  34. message:
  35. name: Prompt
  36. description: Model prompt for the video_analyzer action
  37. default: 'Summarize the events based on a series of images captured at short
  38. intervals. Focus only on moving subjects such as people, vehicles, and other
  39. active elements. Ignore static objects and scenery. Provide a clear and concise
  40. account of movements and interactions. Do not mention or imply the existence
  41. of images—present the information as if directly observing the events. If
  42. no movement is detected, respond with: ''No activity observed.'''
  43. selector:
  44. text:
  45. multiline: true
  46. multiple: false
  47. run_conditions:
  48. name: Run Conditions
  49. description: All conditions must be true in order for the blueprint to run.
  50. default: []
  51. selector:
  52. condition: {}
  53. notify_device:
  54. name: Notify Device
  55. description: The devices to send the notification to. Multiple devices may be
  56. used. Only works with Home Assistant mobile app.
  57. default: []
  58. selector:
  59. device:
  60. multiple: true
  61. filter:
  62. - integration: mobile_app
  63. notification_delivery:
  64. name: Notification Delivery
  65. description: "Controls how notifications are delivered. \n \n **Dynamic** immediately
  66. notifies with a live preview and updates the notification silently with a
  67. summary once it is available. \n **Consolidated** Delays the notification
  68. until the event summary is generated. Use this if you're receiving multiple
  69. notifications for the same event."
  70. default: Dynamic
  71. selector:
  72. select:
  73. options:
  74. - Dynamic
  75. - Consolidated
  76. custom_value: false
  77. multiple: false
  78. sort: false
  79. camera_entities:
  80. name: Camera Entities
  81. description: List of camera entities to monitor
  82. default: []
  83. selector:
  84. entity:
  85. multiple: true
  86. filter:
  87. - domain:
  88. - camera
  89. trigger_state:
  90. name: Trigger State
  91. description: Automation starts when one of your camera changes to this state.
  92. default: recording
  93. selector:
  94. text:
  95. multiline: false
  96. multiple: false
  97. motion_sensors:
  98. name: Motion Sensor
  99. description: Set if your cameras don't change state (Frigate). Use the same
  100. order used for camera entities.
  101. default: []
  102. selector:
  103. entity:
  104. multiple: true
  105. filter:
  106. - domain:
  107. - binary_sensor
  108. preview_mode:
  109. name: Preview Mode
  110. description: "Choose between a live preview or a snapshot of the event. \n\n
  111. **Important:** Live Preview is only supported on iOS."
  112. default: Snapshot
  113. selector:
  114. select:
  115. options:
  116. - Snapshot
  117. - Live Preview
  118. custom_value: false
  119. multiple: false
  120. sort: false
  121. cooldown:
  122. name: Cooldown
  123. description: Time in minutes to wait before running again. Strongly recommended
  124. for busy areas.
  125. default: 10
  126. selector:
  127. number:
  128. min: 0.0
  129. max: 60.0
  130. mode: slider
  131. step: 1.0
  132. tap_navigate:
  133. name: Tap Navigate
  134. description: Home Assistant dashboard to navigate to when notification is opened
  135. (e.g. /lovelace/cameras).
  136. default: /lovelace/0
  137. selector:
  138. text:
  139. multiline: false
  140. multiple: false
  141. duration:
  142. name: Duration
  143. description: Duration to record for analysis (in seconds).
  144. default: 5
  145. selector:
  146. number:
  147. min: 1.0
  148. max: 60.0
  149. mode: slider
  150. step: 1.0
  151. max_frames:
  152. name: Max Frames
  153. description: How many frames to analyze. Picks frames with the most movement.
  154. default: 3
  155. selector:
  156. number:
  157. min: 1.0
  158. max: 60.0
  159. mode: slider
  160. step: 1.0
  161. provider:
  162. name: Provider
  163. description: Provider to use for analysis. See docs for additional information.
  164. selector:
  165. config_entry:
  166. integration: llmvision
  167. model:
  168. name: Model
  169. description: Which model to use. Depends on chosen provider.
  170. default: gpt-4o-mini
  171. selector:
  172. text:
  173. multiline: false
  174. multiple: false
  175. target_width:
  176. name: Target Width
  177. description: Downscale images (uses less tokens and speeds up processing)
  178. default: 1280
  179. selector:
  180. number:
  181. min: 512.0
  182. max: 3840.0
  183. mode: slider
  184. step: 1.0
  185. max_tokens:
  186. name: Maximum Tokens
  187. description: Maximum number of tokens to generate. Use this to control the length
  188. of the summaries.
  189. default: 20
  190. selector:
  191. number:
  192. min: 1.0
  193. max: 100.0
  194. mode: slider
  195. step: 1.0
  196. temperature:
  197. name: Temperature
  198. description: Randomness. Lower is more accurate, higher is more creative.
  199. default: 0.1
  200. selector:
  201. number:
  202. min: 0.1
  203. max: 1.0
  204. step: 0.1
  205. mode: slider
  206. variables:
  207. important: !input important
  208. remember: !input remember
  209. cooldown: !input cooldown
  210. preview_mode: !input preview_mode
  211. notify_devices: !input notify_device
  212. notification_delivery: !input notification_delivery
  213. device_name_map: "{% set ns = namespace(device_names=[]) %} {% for device_id in
  214. notify_devices %}\n {% set device_name = device_attr(device_id, \"name\") %}\n
  215. \ {% set sanitized_name = \"mobile_app_\" + device_name | slugify %}\n {% set
  216. ns.device_names = ns.device_names + [sanitized_name] %}\n{% endfor %} {{ ns.device_names
  217. }}\n"
  218. camera_entities_list: !input camera_entities
  219. motion_sensors_list: !input motion_sensors
  220. camera_entity: "{% if motion_sensors_list and not trigger.entity_id.startswith(\"camera\")
  221. %}\n {% set index = motion_sensors_list.index(trigger.entity_id) %}\n {{ camera_entities_list[index]
  222. }}\n{% else %}\n {{ trigger.entity_id }}\n{% endif %}\n"
  223. tag: '{{ camera_entity + int(as_timestamp(now()))|string }}
  224. '
  225. group: '{{ camera_entity }}
  226. '
  227. label: Motion detected
  228. camera: '{{ camera_entity.replace("camera.", "").replace("_", " ")|capitalize }}
  229. '
  230. importance_prompt: 'Classify the security event based on this image. Choose from
  231. the following options: "passive" for unimportant events, "time-sensitive" for
  232. notable but non-critical events such as a person at the front door, and "critical"
  233. only for potential burglaries or highly suspicious activity. Respond with one
  234. of these options exactly, without additional explanation.
  235. '
  236. max_exceeded: silent
  237. mode: single
  238. triggers:
  239. - trigger: state
  240. entity_id: !input camera_entities
  241. to: !input trigger_state
  242. id: camera_trigger
  243. - trigger: state
  244. entity_id: !input motion_sensors
  245. to: 'on'
  246. id: motion_sensor_trigger
  247. condition:
  248. - condition: and
  249. conditions: !input run_conditions
  250. action:
  251. - choose:
  252. - conditions:
  253. - condition: template
  254. value_template: '{{ important }}'
  255. sequence:
  256. - action: llmvision.image_analyzer
  257. data:
  258. image_entity: '{{[camera_entity]}}'
  259. provider: !input provider
  260. model: !input model
  261. message: '{{importance_prompt}}'
  262. include_filename: true
  263. target_width: 1280
  264. max_tokens: 3
  265. temperature: 0.1
  266. response_variable: importance
  267. - choose:
  268. - conditions:
  269. - condition: template
  270. value_template: '{{ important and importance.response_text|lower == ''passive''
  271. }}'
  272. sequence:
  273. - stop: Event is not important
  274. - choose:
  275. - conditions:
  276. - condition: template
  277. value_template: '{{ notification_delivery == ''Dynamic'' }}'
  278. sequence:
  279. - alias: Send instant notification to notify devices
  280. repeat:
  281. for_each: '{{device_name_map}}'
  282. sequence:
  283. - action: notify.{{ repeat.item }}
  284. data:
  285. title: '{{ label }}'
  286. message: '{{camera}} has detected activity.'
  287. data:
  288. entity_id: '{{camera_entity}}'
  289. url: !input tap_navigate
  290. clickAction: !input tap_navigate
  291. tag: '{{tag}}'
  292. group: '{{group}}'
  293. alert_once: true
  294. push:
  295. interruption-level: '{{importance.response_text|lower if importance
  296. is defined else ''active''}}'
  297. - alias: Analyze event
  298. action: llmvision.stream_analyzer
  299. data:
  300. image_entity: '{{[camera_entity]}}'
  301. duration: !input duration
  302. provider: !input provider
  303. model: !input model
  304. message: !input message
  305. use_memory: !input use_memory
  306. remember: !input remember
  307. expose_images: '{{preview_mode == ''Snapshot'' or remember}}'
  308. generate_title: !input remember
  309. include_filename: true
  310. max_frames: !input max_frames
  311. target_width: !input target_width
  312. max_tokens: !input max_tokens
  313. temperature: !input temperature
  314. response_variable: response
  315. - alias: Update label with title
  316. variables:
  317. label: '{{response.title}}'
  318. - choose:
  319. - conditions:
  320. - condition: template
  321. value_template: '{{ preview_mode==''Snapshot'' }}'
  322. sequence:
  323. - alias: (Snapshot) Update notification on notify devices
  324. repeat:
  325. for_each: '{{device_name_map}}'
  326. sequence:
  327. - action: notify.{{ repeat.item }}
  328. data:
  329. title: '{{ label }}'
  330. message: '{{response.response_text}}'
  331. data:
  332. image: '{{response.key_frame.replace(''/config/www/'',''/local/'') }}'
  333. url: !input tap_navigate
  334. clickAction: !input tap_navigate
  335. tag: '{{tag}}'
  336. group: '{{group}}'
  337. push:
  338. interruption-level: '{{''passive'' if notification_delivery==''Dynamic''
  339. else ''active''}}'
  340. - conditions:
  341. - condition: template
  342. value_template: '{{ preview_mode==''Live Preview'' }}'
  343. sequence:
  344. - alias: (Live Preview) Update notification on notify devices
  345. repeat:
  346. for_each: '{{device_name_map}}'
  347. sequence:
  348. - action: notify.{{ repeat.item }}
  349. data:
  350. title: '{{ label }}'
  351. message: '{{response.response_text}}'
  352. data:
  353. entity_id: '{{camera_entity}}'
  354. url: !input tap_navigate
  355. clickAction: !input tap_navigate
  356. tag: '{{tag}}'
  357. group: '{{group}}'
  358. push:
  359. interruption-level: '{{''passive'' if notification_delivery==''Dynamic''
  360. else ''active''}}'
  361. - delay: 00:{{cooldown|int}}:00