v4
This commit is contained in:
+103
-5
@@ -106,6 +106,21 @@ def conversation(score=1.0, injected_text=None): # ALFRED_DUPLEX_CONVERSATION_V
|
||||
emit_state("idle", partial="")
|
||||
return
|
||||
|
||||
# DONA_LEARNING_V93 : évaluation vocale explicite, puis correction Vosk approuvée.
|
||||
_dona_v93_original_vosk = r.text
|
||||
_dona_v93_ack = _dona_learning_v93.voice_feedback(r.text)
|
||||
if _dona_v93_ack is not None:
|
||||
socketio.emit('alfred_render', {'type':'text','text':_dona_v93_ack})
|
||||
if not audio_settings.speaker_muted():
|
||||
_dona_v93_done = threading.Event()
|
||||
if speak_async(_dona_v93_ack,on_end=_dona_v93_done.set):
|
||||
_dona_v93_done.wait(timeout=120)
|
||||
emit_state('idle',partial='')
|
||||
return
|
||||
r.text = _dona_learning_v93.correct_transcript(r.text)
|
||||
if r.text != _dona_v93_original_vosk:
|
||||
socketio.emit('dona_learning_stt', {'raw':_dona_v93_original_vosk,'used':r.text})
|
||||
|
||||
emit_state(
|
||||
"thinking",
|
||||
partial="",
|
||||
@@ -113,9 +128,41 @@ def conversation(score=1.0, injected_text=None): # ALFRED_DUPLEX_CONVERSATION_V
|
||||
content={"type": "text", "text": r.text}
|
||||
)
|
||||
|
||||
# DONA_VISION_V95 : photo locale et compréhension par Hermes sur demande.
|
||||
if _dona_vision_v95.is_camera_question(r.text):
|
||||
try:
|
||||
_vision_answer = _dona_vision_monitor.analyze(r.text)
|
||||
except RuntimeError as _vision_exc:
|
||||
_vision_answer = str(_vision_exc)
|
||||
except Exception as _vision_exc:
|
||||
print('[DONA VISION] Analyse vocale :',type(_vision_exc).__name__,flush=True)
|
||||
_vision_answer = 'Analyse visuelle indisponible. Vérifie le modèle vision Hermes.'
|
||||
with STATE_LOCK:
|
||||
STATE['content']={'type':'text','text':_vision_answer}
|
||||
socketio.emit('alfred_render',STATE['content'])
|
||||
socketio.emit('dona_learning_turn',_dona_learning_v93.track('voice',_dona_v93_original_vosk,_vision_answer))
|
||||
if _vision_answer and not audio_settings.speaker_muted():
|
||||
emit_state('speaking')
|
||||
_vision_done=threading.Event()
|
||||
if speak_async(_vision_answer[:850],on_end=_vision_done.set):_vision_done.wait(timeout=120)
|
||||
emit_state('idle',partial='')
|
||||
return
|
||||
|
||||
# DONA_FILES_V91 : questions explicites sur la pièce jointe active.
|
||||
if _dona_files_v91.is_file_question(r.text):
|
||||
_file_speech = _dona_files_v91.handle_voice(r.text, socketio, STATE, STATE_LOCK)
|
||||
socketio.emit('dona_learning_turn', _dona_learning_v93.track('voice',_dona_v93_original_vosk,_file_speech))
|
||||
if _file_speech and not audio_settings.speaker_muted():
|
||||
emit_state('speaking')
|
||||
_file_done = threading.Event()
|
||||
if speak_async(_file_speech, on_end=_file_done.set): _file_done.wait(timeout=120)
|
||||
emit_state('idle', partial='')
|
||||
return
|
||||
|
||||
# DONA_SUITE_V9: intents locaux explicites, sinon continuer vers Hermes.
|
||||
if _dona_suite_v9.is_request(r.text):
|
||||
_v9_speech=_dona_suite_v9.handle_and_emit(r.text,socketio)
|
||||
socketio.emit('dona_learning_turn', _dona_learning_v93.track('voice',_dona_v93_original_vosk,_v9_speech))
|
||||
if _v9_speech and not audio_settings.speaker_muted():
|
||||
emit_state('speaking')
|
||||
_v9_done=threading.Event()
|
||||
@@ -127,6 +174,7 @@ def conversation(score=1.0, injected_text=None): # ALFRED_DUPLEX_CONVERSATION_V
|
||||
# DONA_NAV_V83: cartes et itinéraires à la demande, sans LLM.
|
||||
if _dona_nav.is_request(r.text):
|
||||
_nav_reply=_dona_nav.handle_and_emit(r.text,socketio,STATE,STATE_LOCK)
|
||||
socketio.emit('dona_learning_turn', _dona_learning_v93.track('voice',_dona_v93_original_vosk,_nav_reply))
|
||||
if _nav_reply and not audio_settings.speaker_muted():
|
||||
emit_state('speaking')
|
||||
_nav_done=threading.Event()
|
||||
@@ -138,6 +186,7 @@ def conversation(score=1.0, injected_text=None): # ALFRED_DUPLEX_CONVERSATION_V
|
||||
# DONA_YOUTUBE_V82 : recherche publique et contrôle du lecteur à la voix.
|
||||
if _dona_youtube.is_search(r.text):
|
||||
_speech=_dona_youtube.search_and_emit(r.text, socketio, STATE, STATE_LOCK)
|
||||
socketio.emit('dona_learning_turn', _dona_learning_v93.track('voice',_dona_v93_original_vosk,_speech))
|
||||
if _speech and not audio_settings.speaker_muted():
|
||||
emit_state('speaking')
|
||||
_evt=threading.Event()
|
||||
@@ -153,6 +202,7 @@ def conversation(score=1.0, injected_text=None): # ALFRED_DUPLEX_CONVERSATION_V
|
||||
# DONA_V8_DYNAMIC — creation visuelle explicite, source Hermes/MCP ou API directe.
|
||||
if _dona_dynamic.is_dynamic_request(r.text):
|
||||
_board = _dona_dynamic.build_dashboard(r.text, _dona_dashboard_agent.ask_dashboard)
|
||||
socketio.emit('dona_learning_turn',_dona_learning_v93.track('voice',_dona_v93_original_vosk,_board.get('title','Tableau de bord')))
|
||||
_payload = {'type':'dona_dynamic', 'dashboard':_board}
|
||||
with STATE_LOCK:
|
||||
STATE['content'] = _payload
|
||||
@@ -176,6 +226,7 @@ def conversation(score=1.0, injected_text=None): # ALFRED_DUPLEX_CONVERSATION_V
|
||||
|
||||
if visual is not None:
|
||||
content, speech = visual
|
||||
socketio.emit('dona_learning_turn', _dona_learning_v93.track('voice',_dona_v93_original_vosk,speech))
|
||||
with STATE_LOCK:
|
||||
STATE["content"] = content
|
||||
socketio.emit("alfred_render", content)
|
||||
@@ -196,6 +247,7 @@ def conversation(score=1.0, injected_text=None): # ALFRED_DUPLEX_CONVERSATION_V
|
||||
print('[ALFRED LISTES] Erreur :', _lists_error, flush=True)
|
||||
_lists_reply = 'Je n’ai pas pu modifier la liste. Vérifie le stockage d’Alfred.'
|
||||
if _lists_reply is not None:
|
||||
socketio.emit('dona_learning_turn', _dona_learning_v93.track('voice',_dona_v93_original_vosk,_lists_reply))
|
||||
_lists_display = {'type':'text', 'text':_lists_reply}
|
||||
with STATE_LOCK:
|
||||
STATE['content'] = _lists_display
|
||||
@@ -225,7 +277,7 @@ def conversation(score=1.0, injected_text=None): # ALFRED_DUPLEX_CONVERSATION_V
|
||||
emit_state('error', content={'type': 'text', 'text': str(exc)})
|
||||
return
|
||||
# DONA_V7_RELEASE: reconnaissance sur ordre vocal explicite, sinon Hermes normal.
|
||||
answer = _dona_face_recognize(ask_hermes) if _dona_face_request(r.text) else ask_hermes(r.text)
|
||||
answer = _dona_face_recognize(ask_hermes) if _dona_face_request(r.text) else ask_hermes(_dona_learning_v93.enhance_prompt(r.text))
|
||||
print(f"[ALFRED] Réponse Hermes : {answer!r}", flush=True)
|
||||
if isinstance(answer, dict):
|
||||
speech = str(answer.get("speech") or answer.get("text") or "")
|
||||
@@ -237,6 +289,10 @@ def conversation(score=1.0, injected_text=None): # ALFRED_DUPLEX_CONVERSATION_V
|
||||
speech = str(answer or "")
|
||||
display = {"type": "text", "text": speech}
|
||||
|
||||
# DONA_LEARNING_V93 : évaluation du tour Hermes, RAM seulement avant 👍 / 👎.
|
||||
socketio.emit('dona_learning_turn',
|
||||
_dona_learning_v93.track('voice',_dona_v93_original_vosk,speech))
|
||||
|
||||
# Une illustration contextuelle (Wikipédia) peut compléter la réponse Hermes.
|
||||
# Elle n'interrompt pas la lecture TTS et ne remplace pas la scène centrale.
|
||||
alfred_context_images.schedule_context_image(
|
||||
@@ -666,21 +722,43 @@ def _dona_submit_typed(prompt):
|
||||
_before_image = IMAGE_REVISION
|
||||
emit_state('thinking', partial='', transcript=prompt,
|
||||
content={'type': 'text', 'text': prompt})
|
||||
# DONA_VISION_V95 : demande écrite de vision depuis la caméra réelle.
|
||||
if _dona_vision_v95.is_camera_question(prompt):
|
||||
try:
|
||||
_vision_answer=_dona_vision_monitor.analyze(prompt)
|
||||
except Exception as _vision_exc:
|
||||
_vision_answer=str(_vision_exc)[:190] if isinstance(_vision_exc,RuntimeError) else 'Analyse visuelle indisponible.'
|
||||
with STATE_LOCK:
|
||||
STATE['content']={'type':'text','text':_vision_answer}
|
||||
socketio.emit('alfred_render',STATE['content'])
|
||||
socketio.emit('dona_learning_turn',_dona_learning_v93.track('typed',prompt,_vision_answer))
|
||||
emit_state('idle',partial='')
|
||||
return
|
||||
|
||||
# DONA_FILES_V91 : question écrite à propos de la dernière pièce jointe.
|
||||
if _dona_files_v91.is_file_question(prompt):
|
||||
_dona_files_v91.handle_voice(prompt, socketio, STATE, STATE_LOCK)
|
||||
emit_state('idle',partial='')
|
||||
return
|
||||
|
||||
# DONA_SUITE_V9: commandes quotidiennes écrites, sans perturber Hermes.
|
||||
if _dona_suite_v9.is_request(prompt):
|
||||
_dona_suite_v9.handle_and_emit(prompt,socketio)
|
||||
_v93_local=_dona_suite_v9.handle_and_emit(prompt,socketio)
|
||||
socketio.emit('dona_learning_turn',_dona_learning_v93.track('typed',prompt,_v93_local))
|
||||
emit_state('idle',partial='')
|
||||
return
|
||||
|
||||
# DONA_NAV_V83: commande écrite navigation, sans polluer la session Hermes.
|
||||
if _dona_nav.is_request(prompt):
|
||||
_dona_nav.handle_and_emit(prompt,socketio,STATE,STATE_LOCK)
|
||||
_v93_local=_dona_nav.handle_and_emit(prompt,socketio,STATE,STATE_LOCK)
|
||||
socketio.emit('dona_learning_turn',_dona_learning_v93.track('typed',prompt,_v93_local))
|
||||
emit_state('idle',partial='')
|
||||
return
|
||||
|
||||
# DONA_YOUTUBE_V82 : vidéos et commandes écrites hors conversation Hermes.
|
||||
if _dona_youtube.is_search(prompt):
|
||||
_dona_youtube.search_and_emit(prompt,socketio,STATE,STATE_LOCK)
|
||||
_v93_local=_dona_youtube.search_and_emit(prompt,socketio,STATE,STATE_LOCK)
|
||||
socketio.emit('dona_learning_turn',_dona_learning_v93.track('typed',prompt,_v93_local))
|
||||
emit_state('idle',partial='')
|
||||
return
|
||||
if _dona_youtube.is_control(prompt,_dona_youtube.player_active()):
|
||||
@@ -691,13 +769,14 @@ def _dona_submit_typed(prompt):
|
||||
# DONA_V8_DYNAMIC — commandes visuelles saisies via le formulaire habituel.
|
||||
if _dona_dynamic.is_dynamic_request(prompt):
|
||||
_board = _dona_dynamic.build_dashboard(prompt, _dona_dashboard_agent.ask_dashboard)
|
||||
socketio.emit('dona_learning_turn',_dona_learning_v93.track('typed',prompt,_board.get('title','Tableau de bord')))
|
||||
_payload = {'type':'dona_dynamic','dashboard':_board}
|
||||
with STATE_LOCK:
|
||||
STATE['content'] = _payload
|
||||
socketio.emit('alfred_render',_payload)
|
||||
emit_state('idle', partial='')
|
||||
return
|
||||
_answer = ask_hermes(prompt)
|
||||
_answer = ask_hermes(_dona_learning_v93.enhance_prompt(prompt))
|
||||
if isinstance(_answer, dict):
|
||||
_speech = str(_answer.get('speech') or _answer.get('text') or '')
|
||||
_display = _answer.get('display') or {'type':'text','text':_speech}
|
||||
@@ -708,6 +787,9 @@ def _dona_submit_typed(prompt):
|
||||
if IMAGE_REVISION == _before_image:
|
||||
STATE['content'] = _display
|
||||
socketio.emit('alfred_render', _display)
|
||||
# DONA_LEARNING_V93 : évaluation de l’échange écrit.
|
||||
socketio.emit('dona_learning_turn',
|
||||
_dona_learning_v93.track('typed',prompt,_speech))
|
||||
# Deliberately no speak_async(): typed interaction is silent.
|
||||
emit_state('idle', partial='')
|
||||
except Exception as exc:
|
||||
@@ -756,6 +838,22 @@ def _dona_dynamic_submit(prompt):
|
||||
|
||||
_dona_dynamic.register_dynamic(app,_dona_dynamic_submit)
|
||||
|
||||
# DONA_VISION_V95 : API vision/YOLOv8, surveillance opt-in.
|
||||
from services import dona_vision_v95 as _dona_vision_v95
|
||||
_dona_vision_monitor = _dona_vision_v95.register(app, socketio)
|
||||
|
||||
# DONA_LEARNING_V93 : retours explicites et corrections approuvées.
|
||||
from services import dona_learning_v93 as _dona_learning_v93
|
||||
_dona_learning_v93.register(app)
|
||||
|
||||
# DONA_UI_V92 : préférences de raccourcis persistantes, menus gérés côté navigateur.
|
||||
from services import dona_shortcuts_v92 as _dona_shortcuts_v92
|
||||
_dona_shortcuts_v92.register(app)
|
||||
|
||||
# DONA_FILES_V91 : fichiers temporaires et analyse Hermes isolée.
|
||||
from services import dona_files_v91 as _dona_files_v91
|
||||
_dona_files_v91.register_files(app)
|
||||
|
||||
# DONA_SUITE_V9 : routeur local, cockpit, mémoire, cuisine, documents, routines.
|
||||
from services import dona_suite_v9 as _dona_suite_v9
|
||||
_dona_suite_v9.register_suite(app,socketio)
|
||||
|
||||
Reference in New Issue
Block a user