Spaces:
Runtime error
Runtime error
File size: 9,163 Bytes
7204409 8a9498e 8795508 8a9498e 7204409 4b8f61c 7204409 4b8f61c 7204409 4b8f61c 7204409 275558c 4b8f61c 7204409 8a9498e 275558c 8a9498e 7204409 8a9498e 7204409 8a9498e 275558c 8a9498e 7204409 8a9498e 7204409 8a9498e 275558c 8a9498e 7204409 8a9498e 7204409 275558c 8a9498e 7204409 8a9498e 7204409 8a9498e 7204409 8a9498e 7204409 8a9498e 7204409 8a9498e 275558c 8a9498e 7204409 8a9498e 7204409 2dbb80d 8795508 2dbb80d 650e951 2dbb80d 8a9498e 7204409 8a9498e 7204409 8a9498e 7204409 8a9498e 650e951 8a9498e 7204409 650e951 275558c 8a9498e 7204409 8a9498e 7204409 8a9498e 275558c 7204409 8a9498e 7204409 68cc99d 7204409 68cc99d 7204409 68cc99d 7204409 8a9498e 275558c 8a9498e 7204409 8a9498e 7204409 8a9498e 7204409 8a9498e 7204409 1ade1bc 7204409 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
"""
callbacks.py
-------------
Ce module définit les callbacks de l'application Dash en utilisant les abstractions
définies dans le sous-package helpers."""
from dash import Input, Output, State, no_update
import datetime
import os
from pathlib import Path
from loguru import logger
from dotenv import load_dotenv
load_dotenv()
from helpers.processor import Processor
from helpers.s3 import S3Client
from helpers.models import S3Config
from app import app
from global_vars import data, BUCKET_NAME
PERSIST_FILE = "results.json"
# Instanciation du Processor
processor = Processor()
# Instanciation du client S3 à partir de la configuration
s3_config = S3Config(
bucket_name=BUCKET_NAME,
endpoint_url=os.getenv("AWS_ENDPOINT_URL_S3"),
access_key=os.getenv("AWS_ACCESS_KEY_ID"),
secret_key=os.getenv("AWS_SECRET_ACCESS_KEY")
)
s3_client = S3Client(s3_config)
# -----------------------------------------------------------------------------
# CALLBACKS D'AFFICHAGE DES SECTIONS
# -----------------------------------------------------------------------------
@app.callback(
Output("chapter-section", "style"),
Output("pseudo-continue-button", "style"),
Input("pseudo-continue-button", "n_clicks"),
State("user-info", "value")
)
def show_chapter_section(n_clicks, user_info):
"""Affiche la section chapitre après saisie d'une information utilisateur."""
if n_clicks and user_info:
return {"display": "block"}, {"display": "none"}
return {"display": "none"}, {"display": "block"}
@app.callback(
Output("page-section", "style"),
Output("chapter-continue-button", "style"),
Input("chapter-continue-button", "n_clicks"),
State("chapter-dropdown", "value")
)
def show_page_section(n_clicks, chapter_value):
"""Affiche la section page après sélection d'un chapitre."""
if n_clicks and chapter_value:
return {"display": "block"}, {"display": "none"}
return {"display": "none"}, {"display": "block"}
@app.callback(
Output("transcription-section", "style"),
Output("start-button", "style"),
Input("start-button", "n_clicks"),
State("page-dropdown", "value")
)
def show_transcription_section(n_clicks, page_value):
"""Affiche la section transcription après sélection d'une page."""
if n_clicks and page_value:
return {"display": "block"}, {"display": "none"}
return {"display": "none"}, {"display": "block"}
# -----------------------------------------------------------------------------
# CALLBACK DE MISE À JOUR DU DROPDOWN DES PAGES
# -----------------------------------------------------------------------------
@app.callback(
Output("page-dropdown", "options"),
Input("chapter-dropdown", "value")
)
def update_pages(chapter_value):
"""Met à jour les options du dropdown de pages selon le chapitre sélectionné."""
if chapter_value:
chapter_path = Path(chapter_value)
pages = [d for d in chapter_path.iterdir() if d.is_dir()] if chapter_path.exists() else []
return [{"label": d.name, "value": str(d)} for d in pages]
return []
# -----------------------------------------------------------------------------
# CALLBACK DE MISE À JOUR AUDIO ET DES SUGGESTIONS (via dcc.Store)
# -----------------------------------------------------------------------------
@app.callback(
Output("audio-store", "data"),
Output("values-store", "data"),
Output("audio-player", "src"),
Output("suggestion-checklist", "options"),
Output("hidden-message", "style"),
Input("page-dropdown", "value"),
State("chapter-dropdown", "value")
)
def update_audio_and_suggestions(page_value, chapter_value):
"""
Met à jour les stores pour les chemins audio et les suggestions.
Affiche le premier segment audio et les 6 premières suggestions.
"""
hidden_style = {"display": "none"}
if page_value and chapter_value:
# Utilise la méthode abstraite pour charger les transcriptions et extraire l'état
possible_values, audio_paths = processor.load_page_verses_and_audios(s3_client, page_value, data)
options = [{"label": t, "value": t} for t in possible_values[:6]]
if len(audio_paths)>0: #control end of page
audio_src = audio_paths[0]
return audio_paths, possible_values, audio_src, options, hidden_style
hidden_style = {"display": "block"} # Show the hidden message
try:
os.remove(PERSIST_FILE)
except:
pass
return no_update, no_update, no_update, no_update, hidden_style
return no_update, no_update, no_update, no_update, hidden_style
# CALLBACK POUR LE TRAITEMENT DE LA TRANSCIPTION
# -----------------------------------------------------------------------------
@app.callback(
Output("audio-store", "data", allow_duplicate=True),
Output("values-store", "data", allow_duplicate=True),
Output("audio-player", "src", allow_duplicate=True),
Output("suggestion-checklist", "options", allow_duplicate=True),
Output("suggestion-checklist", "value", allow_duplicate=True),
Output("confirmation-message", "children"),
Output("transcription-store", "data"),
Input("submit-button", "n_clicks"),
State("suggestion-checklist", "value"),
State("user-info", "value"),
State("page-dropdown", "value"),
State("audio-player", "src"),
State("audio-store", "data"),
State("values-store", "data"),
State("transcription-store", "data"),
prevent_initial_call=True
)
def update_transcription(n_clicks, selected_transcriptions, user_info, page_value,
current_audio, audio_store, values_store, stored_transcriptions):
"""
Traite la soumission d'une transcription :
- Ajoute l'entrée avec timestamp dans le store de transcription.
- Retire le segment audio traité et les suggestions utilisées.
- Met à jour l'audio et les options de la checklist.
"""
if n_clicks > 0 and page_value and current_audio:
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
stored_transcriptions = stored_transcriptions if stored_transcriptions is not None else []
stored_transcriptions.append({
"segment_path": current_audio,
"transcriptions": selected_transcriptions,
"timestamp": timestamp,
"user_id": user_info
})
# Mise à jour du store audio
if audio_store and isinstance(audio_store, list):
audio_store.pop(0)
next_audio = audio_store[0] if audio_store else ""
else:
next_audio = ""
# Mise à jour du store de suggestions
if values_store and isinstance(values_store, list):
for val in selected_transcriptions:
if val in values_store:
values_store.remove(val)
next_options = [{"label": t, "value": t} for t in (values_store[:6] + ["autre transcription"])] if values_store else ["autre transcription"]
confirmation_message = (f"Transcriptions sélectionnées : {', '.join(selected_transcriptions)}"
if selected_transcriptions else "Aucune transcription sélectionnée.")
# Réinitialisation de la checklist
print(next_options)
print("************")
if (len(next_options)>1):
return audio_store, values_store, next_audio, next_options, [], confirmation_message, stored_transcriptions
return no_update, no_update, no_update, no_update, no_update, "fin de la page, veuillez sauvegarder", stored_transcriptions
# -----------------------------------------------------------------------------
# CALLBACK POUR LA SAUVEGARDE DES RÉSULTATS
# -----------------------------------------------------------------------------
@app.callback(
Output("confirmation-message", "children", allow_duplicate=True),
Input("save-results-button", "n_clicks"),
State("page-dropdown", "value"),
State("transcription-store", "data"),
prevent_initial_call=True
)
def save_results(n_clicks, page_value, stored_transcriptions):
"""
Sauvegarde les transcriptions en combinant les données persistantes existantes
avec les nouvelles et en les uploadant sur S3.
"""
if n_clicks > 0 and page_value:
try:
initial_transcriptions = processor.load_persistent_data(PERSIST_FILE)
except Exception as e:
logger.error(f"Erreur lors du chargement des données persistantes : {e}")
initial_transcriptions = []
combined_transcriptions = initial_transcriptions + (stored_transcriptions if stored_transcriptions else [])
if len(combined_transcriptions)>0:
processor.save_persistent_data(combined_transcriptions, PERSIST_FILE)
cleaned_page = page_value.replace("\\", "/").replace("assets/", "")
s3_key = f"labelling/{cleaned_page}/{PERSIST_FILE}"
s3_client.upload_file(PERSIST_FILE, s3_key)
return "Les résultats ont été sauvegardés avec succès."
return no_update
|