Revue : pistes ecartees et source (local/OpenRouter) gardees, historisation pour rejeu, carte verbeuse du conseiller
This commit is contained in:
@@ -198,36 +198,84 @@ views:
|
||||
- type: vertical-stack
|
||||
cards:
|
||||
- type: custom:mushroom-title-card
|
||||
title: 🤖 Conseiller IA (observateur)
|
||||
subtitle: Il regarde et signale — il ne décide rien
|
||||
title: 🤖 Conseiller IA — relecteur de la journée
|
||||
subtitle: Les constats sont mesurés par le code ; le conseiller propose des pistes, il ne décide rien
|
||||
|
||||
- type: markdown
|
||||
title: Revue de ce matin
|
||||
content: |
|
||||
{% set r = states.sensor.evcs_revue_jour %}
|
||||
{% set a = states.sensor.evcs_advisor_revue %}
|
||||
{% set auj = now().strftime('%Y-%m-%d') %}
|
||||
{% if r is none %}
|
||||
**Revue indisponible** (capteur absent : publiée à 07:30 par le service d'historisation).
|
||||
{% else %}
|
||||
**Revue du {{ r.state }}**{% if r.state != auj %} — ⚠️ pas celle d'aujourd'hui (publiée à 07:30){% endif %}
|
||||
· 24 h jusqu'à la fin des heures creuses de nuit · **{{ r.attributes.a_examiner | default(0) }} point(s) à examiner**
|
||||
|
||||
{% for c in r.attributes.constats | default([]) %}
|
||||
---
|
||||
{% if c.gravite == 'a_examiner' %}🔶{% else %}ℹ️{% endif %} **{{ c.code }}**
|
||||
{{ c.texte }}
|
||||
{% if c.contexte %}<br><small>Raison publiée par le contrôleur à ce moment-là : <i>{{ c.contexte }}</i></small>{% endif %}
|
||||
{% set ps = (a.attributes.pistes | default([]) | selectattr('code','eq',c.code) | list) if a is not none and a.state == r.state else [] %}
|
||||
{% for p in ps %}
|
||||
<br>💡 **Piste du conseiller** (avis, à vérifier) : {{ p.piste }}
|
||||
{% endfor %}
|
||||
{% set es = (a.attributes.ecartees | default([]) | selectattr('code','eq',c.code) | list) if a is not none and a.state == r.state else [] %}
|
||||
{% for e in es %}
|
||||
<br><small>🚫 Piste écartée ({{ e.motif }}) : <i>{{ e.piste }}</i></small>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% if (r.attributes.constats | default([])) | length == 0 %}✅ {{ r.attributes.texte }}{% endif %}
|
||||
{% endif %}
|
||||
|
||||
- type: markdown
|
||||
title: Qui a répondu, et comment
|
||||
content: |
|
||||
{% set a = states.sensor.evcs_advisor_revue %}
|
||||
{% if a is none %}
|
||||
Le conseiller n'a encore publié aucune revue.
|
||||
{% else %}
|
||||
| | |
|
||||
|---|---|
|
||||
| Revue relue | {{ a.state }} ({{ a.attributes.constats_relus | default('?') }} constat(s)) |
|
||||
| Modèle | {{ a.attributes.modele | default('?') }} |
|
||||
| **Où** | {% if a.attributes.source == 'openrouter' %}☁️ **OpenRouter (cloud)**{% else %}🏠 **Spark (local)**{% endif %} |
|
||||
| Pistes retenues | {{ a.attributes.pistes | default([]) | length }} |
|
||||
| Pistes écartées | {{ a.attributes.rejetees | default(0) }} (chiffre inventé, code inconnu, doublon) |
|
||||
|
||||
{{ a.attributes.source_texte | default('') }}
|
||||
{% endif %}
|
||||
|
||||
**Rôle d'OpenRouter** : solution de **secours seulement**. Le conseiller interroge d'abord le modèle local de la Spark ; si la Spark ne répond pas, les constats (textes ci-dessus, sans identifiants) sont envoyés à OpenRouter. Il n'a aucun autre rôle.
|
||||
|
||||
Statut du dernier passage : `{{ states('input_text.evcs_advisor_status') }}` · {{ states('input_text.evcs_advisor_last_run') }} · {{ states('input_text.evcs_advisor_model') }}
|
||||
|
||||
- type: markdown
|
||||
title: Les 7 derniers jours
|
||||
content: |
|
||||
{% set h = states.sensor.evcs_revue_historique %}
|
||||
{% if h is none or (h.attributes.jours | default([])) | length == 0 %}
|
||||
Pas encore d'historique (la première revue est publiée le 08/10 à 07:30).
|
||||
{% else %}
|
||||
{% for j in h.attributes.jours %}
|
||||
**{{ j.jour }}** — {{ j.constats | selectattr('gravite','eq','a_examiner') | list | length }} point(s), {{ j.pistes | selectattr('retenue') | list | length }} piste(s) retenue(s), {{ j.pistes | rejectattr('retenue') | list | length }} écartée(s){% if j.pistes | selectattr('source','eq','openrouter') | list | length > 0 %} · ☁️ OpenRouter{% endif %}
|
||||
{% for c in j.constats %}
|
||||
<br><small>• {{ c.texte }}</small>
|
||||
{% endfor %}
|
||||
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<small>Tout est gardé en base (`revue_constat`, `revue_piste`, avec les pistes écartées et leur motif) pour rejouer le conseiller plus tard et mesurer s'il progresse.</small>
|
||||
|
||||
- type: markdown
|
||||
title: Dialoguer avec le conseiller
|
||||
content: |
|
||||
Pour l'instant, le dialogue passe par **OpenClaw** (WhatsApp ou vocal) : « qu'est-ce qui a cloché hier ? » — il lit la revue et les pistes ci-dessus, et présente les pistes comme des avis.
|
||||
|
||||
- type: entities
|
||||
title: Dernière observation
|
||||
entities:
|
||||
- entity: input_text.evcs_advisor_gravite
|
||||
name: Gravité
|
||||
icon: mdi:alert-circle-outline
|
||||
- entity: input_text.evcs_advisor_constat
|
||||
name: Ce qu'il voit
|
||||
icon: mdi:eye-outline
|
||||
- entity: input_text.evcs_advisor_ce_qui_cloche
|
||||
name: Ce qui cloche
|
||||
icon: mdi:help-rhombus-outline
|
||||
- entity: input_text.evcs_advisor_reason
|
||||
name: Piste (et sa confiance)
|
||||
icon: mdi:magnify
|
||||
- type: divider
|
||||
- entity: input_text.evcs_advisor_status
|
||||
name: Statut
|
||||
- entity: input_text.evcs_advisor_model
|
||||
name: Modèle LLM
|
||||
- entity: input_text.evcs_advisor_last_run
|
||||
name: Dernière analyse
|
||||
- entity: input_number.evcs_advisor_agree_count
|
||||
name: Cycles calmes
|
||||
- entity: input_number.evcs_advisor_diverge_count
|
||||
name: Signalements
|
||||
- type: divider
|
||||
- entity: input_boolean.evcs_advisor_enabled
|
||||
name: Conseiller actif (kill-switch)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user