Surveillance du modele local : le brouillon avait un angle mort
Le paquet propose par la session Airtria portait trois entites — interrupteur d alertes, RAM disponible, libelle d etat. Il lui manquait celle sans laquelle les trois autres mentent : un horodatage ecrit a chaque passage. Sans lui, un moniteur mort est indiscernable d un systeme sain. Les trois entites gardent leur derniere valeur, qui dit « tout va bien », indefiniment. C est exactement l incident du 08/09 sur la prevision solaire, ou 4 h 45 de panne n ont laisse aucune trace. Et on ne peut PAS deduire la fraicheur du last_updated des autres entites : Home Assistant ne rafraichit pas l horodatage d un helper reecrit a l identique — une RAM stable une heure produirait la meme illusion. Ajoutes : l horodatage, le modele charge, un capteur d age, et deux alarmes — moniteur muet, RAM sous le seuil ou earlyoom tue le plus gourmand. Defaut trouve et corrige apres creation : l alarme RAM se declenchait avant que le moniteur ait tourne une seule fois, une valeur jamais ecrite valant zero. Une mesure qu on n a pas recue n est pas une mesure basse. Elle est desormais conditionnee a la fraicheur. Tableau separe des tableaux energie : ce qu il montre n a aucun rapport avec le photovoltaique. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
This commit is contained in:
90
dashboards/llm_monitor.yaml
Executable file
90
dashboards/llm_monitor.yaml
Executable file
@@ -0,0 +1,90 @@
|
|||||||
|
# Surveillance du modele local sur la Spark.
|
||||||
|
#
|
||||||
|
# Tableau volontairement SEPARE des tableaux energie : ce qu'il montre n'a aucun
|
||||||
|
# rapport avec le photovoltaique, et les melanger rendrait les deux moins
|
||||||
|
# lisibles.
|
||||||
|
#
|
||||||
|
# Rempli par un moniteur externe (cron toutes les 2 min sur 10.10.10.17). Tant
|
||||||
|
# qu'il n'a pas tourne, la carte le DIT au lieu d'afficher des zeros rassurants.
|
||||||
|
|
||||||
|
title: Modèle local
|
||||||
|
views:
|
||||||
|
- title: Spark
|
||||||
|
path: spark
|
||||||
|
icon: mdi:robot-outline
|
||||||
|
cards:
|
||||||
|
|
||||||
|
- type: conditional
|
||||||
|
conditions:
|
||||||
|
- entity: binary_sensor.llm_monitor_muet
|
||||||
|
state: "on"
|
||||||
|
card:
|
||||||
|
type: markdown
|
||||||
|
content: >
|
||||||
|
## ⚠️ Le moniteur ne parle plus
|
||||||
|
|
||||||
|
|
||||||
|
Aucune nouvelle depuis
|
||||||
|
{{ states('sensor.llm_monitor_age_du_dernier_passage') }} minutes,
|
||||||
|
alors qu'il devrait passer toutes les 2 minutes.
|
||||||
|
|
||||||
|
|
||||||
|
**Les valeurs ci-dessous sont donc périmées** — elles montrent le
|
||||||
|
dernier état connu, pas l'état actuel. Un moniteur mort affiche les
|
||||||
|
mêmes chiffres rassurants qu'un système sain : c'est cette carte,
|
||||||
|
et elle seule, qui fait la différence.
|
||||||
|
|
||||||
|
- type: entities
|
||||||
|
title: Le modèle
|
||||||
|
state_color: true
|
||||||
|
entities:
|
||||||
|
- entity: input_text.llm_monitor_status
|
||||||
|
name: État
|
||||||
|
- entity: input_text.llm_monitor_model
|
||||||
|
name: Modèle chargé
|
||||||
|
- entity: input_datetime.llm_monitor_last_seen
|
||||||
|
name: Dernière vérification
|
||||||
|
- entity: sensor.llm_monitor_age_du_dernier_passage
|
||||||
|
name: Âge de cette vérification
|
||||||
|
- type: divider
|
||||||
|
- entity: binary_sensor.llm_monitor_muet
|
||||||
|
name: Moniteur muet
|
||||||
|
|
||||||
|
- type: entities
|
||||||
|
title: Mémoire de la Spark
|
||||||
|
state_color: true
|
||||||
|
entities:
|
||||||
|
- entity: input_number.llm_mem_avail_pct
|
||||||
|
name: RAM disponible
|
||||||
|
- entity: binary_sensor.spark_ram_critique
|
||||||
|
name: RAM critique
|
||||||
|
footer:
|
||||||
|
type: graph
|
||||||
|
entity: input_number.llm_mem_avail_pct
|
||||||
|
hours_to_show: 24
|
||||||
|
detail: 2
|
||||||
|
|
||||||
|
- type: entities
|
||||||
|
title: Alertes
|
||||||
|
entities:
|
||||||
|
- entity: input_boolean.llm_monitor_enabled
|
||||||
|
name: Alertes WhatsApp
|
||||||
|
|
||||||
|
- type: markdown
|
||||||
|
content: >
|
||||||
|
**Comment lire cette carte**
|
||||||
|
|
||||||
|
|
||||||
|
`RAM critique` ne se déclenche que si le moniteur a donné de ses
|
||||||
|
nouvelles récemment. Une valeur jamais reçue vaut zéro, et zéro n'est
|
||||||
|
pas une mesure basse — c'est une absence de mesure. C'est
|
||||||
|
`Moniteur muet` qui le dit, et lui seul.
|
||||||
|
|
||||||
|
|
||||||
|
Le seuil de RAM est à 8 %. En dessous, `earlyoom` tue le processus le
|
||||||
|
plus gourmand de la machine, et sur la Spark le plus gourmand est le
|
||||||
|
modèle lui-même.
|
||||||
|
|
||||||
|
|
||||||
|
L'interrupteur ne coupe que les **alertes WhatsApp**. Le moniteur
|
||||||
|
continue de mesurer et cette carte reste à jour.
|
||||||
@@ -288,6 +288,13 @@ sensor:
|
|||||||
|
|
||||||
lovelace:
|
lovelace:
|
||||||
dashboards:
|
dashboards:
|
||||||
|
modele-local:
|
||||||
|
mode: yaml
|
||||||
|
title: Modèle local
|
||||||
|
icon: mdi:robot-outline
|
||||||
|
show_in_sidebar: true
|
||||||
|
filename: dashboards/llm_monitor.yaml
|
||||||
|
|
||||||
bilan-energetique:
|
bilan-energetique:
|
||||||
mode: yaml
|
mode: yaml
|
||||||
title: Bilan énergétique
|
title: Bilan énergétique
|
||||||
|
|||||||
108
packages/llm_monitor.yaml
Executable file
108
packages/llm_monitor.yaml
Executable file
@@ -0,0 +1,108 @@
|
|||||||
|
# Surveillance du modele local sur la Spark (10.10.10.8)
|
||||||
|
#
|
||||||
|
# Ce paquet N'A RIEN A VOIR avec le systeme photovoltaique. Il vit ici parce que
|
||||||
|
# c'est le seul endroit ou des entites Home Assistant peuvent exister, pas parce
|
||||||
|
# qu'il appartient au domaine energie. Ne pas melanger ses entites a celles de
|
||||||
|
# `evcs_*` / `victron_*`, et ne rien cabler de l'energie dessus.
|
||||||
|
#
|
||||||
|
# Ce que surveille le moniteur (script externe, cron sur 10.10.10.17) :
|
||||||
|
# - le point d'acces du modele repond-il
|
||||||
|
# - la RAM disponible de la Spark, qu'earlyoom peut faire tomber en tuant
|
||||||
|
# le modele autour de 6 %
|
||||||
|
#
|
||||||
|
# ⚠️ AUCUN `initial:` DANS CE FICHIER. Declarer `initial:` DESACTIVE la
|
||||||
|
# restauration d'etat : le helper est force a cette valeur a CHAQUE demarrage de
|
||||||
|
# Home Assistant. Le 06/09/2026 cinq reglages manuels du projet se
|
||||||
|
# reinitialisaient ainsi en silence, dont deux toggles de cablage. Le
|
||||||
|
# kill-switch ci-dessous doit garder la position choisie par le proprietaire.
|
||||||
|
|
||||||
|
input_boolean:
|
||||||
|
llm_monitor_enabled:
|
||||||
|
name: "LLM monitor — alertes WhatsApp"
|
||||||
|
icon: mdi:bell-ring
|
||||||
|
|
||||||
|
input_number:
|
||||||
|
llm_mem_avail_pct:
|
||||||
|
name: "Spark — RAM disponible"
|
||||||
|
min: 0
|
||||||
|
max: 100
|
||||||
|
step: 0.1
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
mode: box
|
||||||
|
icon: mdi:memory
|
||||||
|
|
||||||
|
input_text:
|
||||||
|
# ⚠️ `max` DOIT couvrir le plus long MESSAGE D'ERREUR, pas la valeur nominale.
|
||||||
|
# Le 08/09/2026, `evcs_balance_forecast_updated` etait declare `max: 32` : ses
|
||||||
|
# messages d'echec faisaient 43 caracteres, Home Assistant les REJETAIT EN
|
||||||
|
# SILENCE, et une panne de 4 h 45 n'a laisse aucune trace. 255 est la valeur
|
||||||
|
# sure pour un champ d'etat.
|
||||||
|
llm_monitor_status:
|
||||||
|
name: "LLM monitor — état"
|
||||||
|
max: 255
|
||||||
|
icon: mdi:robot-outline
|
||||||
|
|
||||||
|
llm_monitor_model:
|
||||||
|
name: "LLM monitor — modèle chargé"
|
||||||
|
max: 100
|
||||||
|
icon: mdi:chip
|
||||||
|
|
||||||
|
input_datetime:
|
||||||
|
# ⚠️ LE CAPTEUR LE PLUS IMPORTANT DU PAQUET, et celui qui manquait au
|
||||||
|
# brouillon. Sans horodatage ecrit A CHAQUE PASSAGE, un moniteur mort est
|
||||||
|
# indiscernable d'un systeme sain : les trois autres entites gardent leur
|
||||||
|
# derniere valeur, qui dit « tout va bien », indefiniment.
|
||||||
|
#
|
||||||
|
# Et il ne faut PAS deduire la fraicheur du `last_updated` des autres
|
||||||
|
# entites : Home Assistant NE RAFRAICHIT PAS l'horodatage d'un helper reecrit
|
||||||
|
# a l'identique. Constate le 01/09/2026 — un etat paraissait fige depuis
|
||||||
|
# 2 440 s alors que le controleur tournait normalement. Une RAM stable a
|
||||||
|
# 12,3 % pendant une heure produirait exactement la meme illusion.
|
||||||
|
llm_monitor_last_seen:
|
||||||
|
name: "LLM monitor — dernière vérification"
|
||||||
|
has_date: true
|
||||||
|
has_time: true
|
||||||
|
|
||||||
|
template:
|
||||||
|
- sensor:
|
||||||
|
- name: "LLM monitor — âge du dernier passage"
|
||||||
|
unique_id: llm_monitor_age_min
|
||||||
|
unit_of_measurement: "min"
|
||||||
|
state: >
|
||||||
|
{% set t = states('input_datetime.llm_monitor_last_seen') %}
|
||||||
|
{% if t not in ['unknown','unavailable',''] %}
|
||||||
|
{{ ((as_timestamp(now()) - as_timestamp(t, 0)) / 60) | round(0) }}
|
||||||
|
{% else %}unknown{% endif %}
|
||||||
|
|
||||||
|
- binary_sensor:
|
||||||
|
# Le moniteur tourne toutes les 2 minutes. Au-dela de 10, il ne tourne
|
||||||
|
# plus — et c'est une information a part entiere, pas une absence.
|
||||||
|
- name: "LLM monitor — muet"
|
||||||
|
unique_id: llm_monitor_muet
|
||||||
|
device_class: problem
|
||||||
|
state: >
|
||||||
|
{% set t = states('input_datetime.llm_monitor_last_seen') %}
|
||||||
|
{% if t in ['unknown','unavailable',''] %}on
|
||||||
|
{% else %}
|
||||||
|
{{ (as_timestamp(now()) - as_timestamp(t, 0)) > 600 }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
# earlyoom tue le processus le plus gourmand quand la memoire s'effondre,
|
||||||
|
# et sur cette machine le plus gourmand est le modele. Le seuil est celui
|
||||||
|
# que le proprietaire a nomme.
|
||||||
|
#
|
||||||
|
# ⚠️ CONDITIONNE A LA FRAICHEUR DU MONITEUR. Une valeur jamais ecrite vaut
|
||||||
|
# 0 — le minimum du helper — et serait lue comme « 0 % de RAM libre »,
|
||||||
|
# donc comme une alarme permanente avant meme que le moniteur ait tourne
|
||||||
|
# une fois. Une mesure qu'on n'a pas recue n'est pas une mesure basse :
|
||||||
|
# c'est `llm_monitor_muet` qui doit le dire, et lui seul.
|
||||||
|
- name: "Spark — RAM critique"
|
||||||
|
unique_id: spark_ram_critique
|
||||||
|
device_class: problem
|
||||||
|
state: >
|
||||||
|
{% set t = states('input_datetime.llm_monitor_last_seen') %}
|
||||||
|
{% if t in ['unknown','unavailable',''] %}off
|
||||||
|
{% elif (as_timestamp(now()) - as_timestamp(t, 0)) > 600 %}off
|
||||||
|
{% else %}
|
||||||
|
{{ states('input_number.llm_mem_avail_pct') | float(100) < 8 }}
|
||||||
|
{% endif %}
|
||||||
Reference in New Issue
Block a user