hotwords.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. from dash import html, dcc, callback_context, dash_table
  2. import dash_bootstrap_components as dbc
  3. from dash.dependencies import Input, Output, State
  4. from utils.file_utils import list_directories_in_directory, list_files_in_directory, get_file_metadata, get_training_time, get_file_size, trainer_classes, get_Size_String
  5. import os
  6. import json
  7. import plotly.graph_objs as go
  8. TRAINING_HOTWORD_DIR = './training/hotword/'
  9. def HotwordsLayout():
  10. hotword_models = list_directories_in_directory(TRAINING_HOTWORD_DIR)
  11. model_table = generate_model_table(hotword_models)
  12. return html.Div([
  13. html.H2("Hotword Models"),
  14. dbc.Button("Add New Hotword", id="add-new-hotword", color="primary", className="mb-3"),
  15. html.Div(id="new-hotword-input"),
  16. model_table,
  17. dcc.Store(id='hidden-model-name'),
  18. html.Div(id="hotword-manage-training-data")
  19. ])
  20. def generate_model_table(models):
  21. header = [
  22. html.Thead(html.Tr([html.Th("Model Name"), html.Th("Actions")]))
  23. ]
  24. rows = []
  25. for model in models:
  26. rows.append(html.Tr([
  27. html.Td(model),
  28. html.Td([
  29. dbc.Button("Details", href=f"/manage_hotword/{model}", color='primary', className='mr-2'),
  30. dbc.Button("Delete", id={'type': 'delete-hotword', 'index': model}, color='danger')
  31. ])
  32. ]))
  33. return dbc.Table(header + [html.Tbody(rows)], bordered=True, hover=True)
  34. def ManageHotwordLayout(model_name):
  35. page_size = 10
  36. training_data = list_files_in_directory(f"{TRAINING_HOTWORD_DIR}/{model_name}/", ".wav")
  37. training_data_table, row_count = generate_training_data_table(model_name, training_data, 1, page_size)
  38. trainer_options = [{'label': name, 'value': name} for name in trainer_classes.keys()]
  39. training_time = get_training_time(model_name)
  40. tab_trainer = []
  41. for trainer_info in trainer_options:
  42. infoFile = f"./model/hotword/{model_name}/info_{trainer_info['value']}.json"
  43. if os.path.exists(infoFile):
  44. with open(infoFile, 'r') as file:
  45. info = json.load(file)
  46. epochs = '-'
  47. batch_size = '-'
  48. dropout_rate = '-'
  49. training_method = '-'
  50. duration = '-'
  51. testAccuracy = '-'
  52. accu = []
  53. loss = []
  54. size = '-'
  55. if 'epochs' in info:
  56. epochs = info['epochs']
  57. if 'batch_size' in info:
  58. batch_size = info['batch_size']
  59. if 'dropout_rate' in info:
  60. dropout_rate = info['dropout_rate']
  61. if 'trainer_script' in info:
  62. training_method = info['trainer_script']
  63. if 'accuracy' in info:
  64. accu = info['accuracy']
  65. if 'loss' in info:
  66. loss = info['loss']
  67. if 'training_time' in info:
  68. duration = info['training_time']
  69. if 'test_accuracy' in info:
  70. testAccuracy = info['test_accuracy']
  71. if 'model_size' in info:
  72. size = info['model_size']
  73. chart_fig1 = go.Figure(data=[go.Scatter(y=accu)])
  74. chart_fig2 = go.Figure(data=[go.Scatter(y=loss)])
  75. entries = [
  76. dcc.Graph(figure=chart_fig1),
  77. dcc.Graph(figure=chart_fig2),
  78. html.P("Epochen: "+str(epochs), className="card-text"),
  79. html.P("Batch Size: "+str(batch_size), className="card-text"),
  80. html.P("Dropout Rate: "+str(dropout_rate), className="card-text"),
  81. html.P("Methode: "+str(training_method), className="card-text"),
  82. html.P("Duration: "+str(duration), className="card-text"),
  83. html.P("Test Accuracy: "+str(testAccuracy), className="card-text"),
  84. html.P("Size: "+get_Size_String(size*1024), className="card-text"),
  85. ]
  86. tab_trainer.append(
  87. dbc.Tab(entries
  88. , label=trainer_info['label'], tab_id=trainer_info['value'])
  89. )
  90. else:
  91. tab_trainer.append(
  92. dbc.Tab("",label=trainer_info['label'], tab_id=trainer_info['value'], disabled=True)
  93. )
  94. # Pagination logic
  95. num_pages = (row_count // page_size) + (1 if row_count % page_size > 0 else 0)
  96. pagination = dbc.Pagination(id='data-table-pagination', max_value=num_pages, active_page=1)
  97. return html.Div([
  98. html.H2(f"Manage Hotword Model: {model_name}"),
  99. dbc.Card([dbc.CardHeader("Model Infos"),dbc.CardBody(dbc.Tabs(tab_trainer))]),
  100. dbc.Card([
  101. dbc.CardHeader("Training Controls"),
  102. dbc.CardBody([
  103. #dbc.Row([
  104. #dbc.Col(dbc.Button("Start Training", id="start-training-hotword", color="success", className="mb-3")),
  105. #dbc.Col(dbc.Button("Optimize Training", id="optimize-training-hotword", color="primary", className="mb-3 ml-3")),
  106. #dbc.Col(dbc.Button("Stop Training", id="stop-training-hotword", color="danger", className="mb-3 ml-3")),
  107. dbc.ButtonGroup([
  108. dbc.DropdownMenu(
  109. label="Start training",
  110. children=[
  111. dbc.DropdownMenuItem("Item 1"),
  112. dbc.DropdownMenuItem("Item 2"),
  113. dbc.DropdownMenuItem("Item 3"),
  114. ],
  115. ),
  116. dbc.Button("Start Training", id="start-training-hotword", color="success", className="mb-3"),
  117. dbc.Button("Optimize Training", id="optimize-training-hotword", color="primary", className="mb-3 ml-3"),
  118. dbc.Button("Stop Training", id="stop-training-hotword", color="danger", className="mb-3 ml-3"),
  119. ]),
  120. #]),
  121. dbc.Row([
  122. dbc.Col(
  123. dcc.Dropdown(
  124. id="training-method-dropdown",
  125. options=trainer_options,
  126. value=trainer_options[0]["value"], # default value
  127. clearable=False,
  128. className="mb-3",
  129. placeholder="Select Training Method",
  130. )
  131. ),
  132. dbc.Col(
  133. dcc.Input(
  134. id="dropout-rate",
  135. type="number",
  136. value=0.5,
  137. step=0.1,
  138. min=0,
  139. max=1,
  140. className="mb-3",
  141. placeholder="Dropout Rate"
  142. )
  143. ),
  144. dbc.Col(
  145. dcc.Slider(0, 10000, value=3000, id="num-epochs",tooltip={"placement": "bottom", "always_visible": False})
  146. #dcc.Input(
  147. # id="num-epochs",
  148. # type="number",
  149. # value=10,
  150. # step=1,
  151. # min=1,
  152. # className="mb-3",
  153. # placeholder="Epochs"
  154. #)
  155. ),
  156. dbc.Col(
  157. dcc.Slider(0, 256, marks={
  158. 8: '8',
  159. 16: '16',
  160. 32: '32',
  161. 64: '64',
  162. 128: '128',
  163. 256: '256',
  164. }, value=32, id="batch-size", step=None)
  165. #dcc.Input(
  166. # id="batch-size",
  167. # type="number",
  168. # value=32,
  169. # step=1,
  170. # min=1,
  171. # className="mb-3",
  172. # placeholder="Batch Size"
  173. #)
  174. )
  175. ]),
  176. html.Div(id="training-status", className='mt-3'),
  177. html.Div(id="training-timer", className='mt-3'),
  178. dbc.Card([
  179. dbc.CardHeader("Training Progress"),
  180. dbc.CardBody([
  181. dcc.Graph(id="training-chart", figure=[]),
  182. dbc.Progress(id="training-progress", striped=True, animated=True, style={"height": "20px"}),
  183. ])
  184. ]),
  185. ])
  186. ]),
  187. dbc.Card([
  188. dbc.CardHeader("Upload Training Data"),
  189. dbc.CardBody([
  190. dcc.Upload(
  191. id="upload-training-data",
  192. children=html.Div([
  193. 'Drag and Drop or ',
  194. html.A('Select Files')
  195. ]),
  196. style={
  197. 'width': '100%',
  198. 'height': '60px',
  199. 'lineHeight': '60px',
  200. 'borderWidth': '1px',
  201. 'borderStyle': 'dashed',
  202. 'borderRadius': '5px',
  203. 'textAlign': 'center',
  204. 'margin': '10px'
  205. },
  206. multiple=True
  207. ),
  208. html.Div(id="file-preview-list"),
  209. dbc.Button("Upload Files", id="confirm-upload", color='success', className='mt-3'),
  210. html.Div(id="upload-status"),
  211. ])
  212. ]),
  213. dbc.Card([
  214. dbc.CardHeader("Training Data"),
  215. dbc.CardBody([
  216. training_data_table, pagination
  217. ])
  218. ])
  219. ])
  220. def generate_training_data_table(model_name, files, page=1, page_size=10):
  221. import os
  222. header = [
  223. html.Thead(html.Tr([html.Th("Audio"), html.Th("File Name"), html.Th("Display"), html.Th("Length (s)"), html.Th("Size (KB)"), html.Th("Actions")]))
  224. ]
  225. rows = []
  226. for file in files:
  227. filex = os.path.basename(file)
  228. if not os.path.isdir(f"{TRAINING_HOTWORD_DIR}/{model_name}/{filex}"):
  229. file_name = filex.lstrip('_')
  230. file_path = f"{TRAINING_HOTWORD_DIR}/{model_name}/{filex}"
  231. fileImg = filex[0:-3] + "png"
  232. try:
  233. length, size = get_file_metadata(file_path)
  234. rows.append(html.Tr([
  235. html.Td(html.Audio(src=f"/audio/hotword/{model_name}/{filex}", controls=True)),
  236. html.Td(file_name),
  237. html.Td(html.Img(src=f"/audio/hotword/{model_name}/{fileImg}")),
  238. html.Td(length),
  239. html.Td(size),
  240. html.Td([
  241. dbc.Button("Delete", id={'type': 'delete-button', 'index': file}, color='danger', className='mr-2'),
  242. dbc.Button("Deactivate" if not filex.startswith('_') else "Activate", id={'type': 'toggle-button', 'index': filex}, color='warning')
  243. ])
  244. ]))
  245. except ValueError as e:
  246. rows.append(html.Tr([
  247. html.Td("-"),
  248. html.Td(file_name),
  249. html.Td("-"),
  250. html.Td("-"),
  251. html.Td("-"),
  252. html.Td([
  253. dbc.Button("Delete", id={'type': 'delete-button', 'index': file}, color='danger', className='mr-2')
  254. ])
  255. ]))
  256. except FileNotFoundError as e:
  257. rows.append(html.Tr([
  258. html.Td("-"),
  259. html.Td(file_name),
  260. html.Td("-"),
  261. html.Td("-"),
  262. html.Td("-"),
  263. html.Td("File not found")
  264. ]))
  265. start = (page - 1) * 10
  266. end = start + 10
  267. row_count = len(rows)
  268. table_body = html.Tbody(id='data-table-body', children=rows[start:end])
  269. return html.Div([
  270. dbc.Table(header + [table_body], bordered=True, hover=True)
  271. ]), row_count