File size: 12,880 Bytes
c101beb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
import torchaudio
import gradio as gr
import soundfile as sf
import tempfile
import os
import io
import librosa
import numpy as np
import pandas as pd
from transformers import ASTFeatureExtractor, AutoModelForAudioClassification, Trainer, Wav2Vec2FeatureExtractor, HubertForSequenceClassification, pipeline
from datasets import Dataset, DatasetDict
import torch.nn.functional as F
import torch
from collections import Counter
from scipy.stats import kurtosis
from huggingface_hub import InferenceClient
import os

access_token_mod_1 = os.getenv('HF_Access_Personal')

# Cargar el procesador y modelo
processor = ASTFeatureExtractor.from_pretrained("MIT/ast-finetuned-audioset-10-10-0.4593")
model = AutoModelForAudioClassification.from_pretrained("Robertomarting/tmp_trainer",token=access_token_mod_1)

def is_white_noise(audio, threshold=0.75):
    kurt = kurtosis(audio)
    return np.abs(kurt) < 0.1 and np.mean(np.abs(audio)) < threshold

def create_audio_dataframe(audio_tuple, target_sr=16000, target_duration=1.0):
    data = []
    target_length = int(target_sr * target_duration)

    wav_buffer = io.BytesIO()
    sf.write(wav_buffer, audio_tuple[1], audio_tuple[0], format='wav')
    
    wav_buffer.seek(0)
    audio_data, sample_rate = sf.read(wav_buffer)

    audio_data = audio_data.astype(np.float32)
    
    if len(audio_data.shape) > 1:
        audio_data = np.mean(audio_data, axis=1) 

    if sample_rate != target_sr:
        audio_data = librosa.resample(audio_data, orig_sr=sample_rate, target_sr=target_sr)

    audio_data, _ = librosa.effects.trim(audio_data)

    if len(audio_data) > target_length:
        for i in range(0, len(audio_data), target_length):
            segment = audio_data[i:i + target_length]
            if len(segment) == target_length:
                if not is_white_noise(segment):
                    data.append({"audio": segment})
    else:
        if not is_white_noise(audio_data):
            data.append({"audio": audio_data})

    df = pd.DataFrame(data)
    return df

def convert_bytes_to_float64(byte_list):
    return [float(i) for i in byte_list]

def preprocess_function(examples):
    audio_arrays = examples["audio"]
    inputs = processor(
        audio_arrays,
        padding=True,
        sampling_rate=processor.sampling_rate,
        max_length=int(processor.sampling_rate * 1),
        truncation=True,
    )
    return inputs

def predict_audio(audio):
    df = create_audio_dataframe(audio)
    df['audio'] = df['audio'].apply(convert_bytes_to_float64)
    
    # Convertir el dataframe a Dataset
    predict_dataset = Dataset.from_pandas(df)
    dataset = DatasetDict({
        'train': predict_dataset
    })

    if '__index_level_0__' in dataset['train'].column_names:
        dataset['train'] = dataset['train'].remove_columns(['__index_level_0__'])

    encoded_dataset = dataset.map(preprocess_function, remove_columns=["audio"], batched=True)

    # Crear el Trainer para la predicción
    trainer = Trainer(
        model=model,  
        eval_dataset=encoded_dataset["train"]
    )

    # Realizar las predicciones
    predictions_output = trainer.predict(encoded_dataset["train"].with_format("torch"))

    # Obtener las predicciones y etiquetas verdaderas
    predictions = predictions_output.predictions
    labels = predictions_output.label_ids

    # Convertir logits a probabilidades
    probabilities = F.softmax(torch.tensor(predictions), dim=-1).numpy()
    predicted_classes = probabilities.argmax(axis=1)

    # Obtener la etiqueta más común
    most_common_predicted_label = Counter(predicted_classes).most_common(1)[0][0]
    
    # Mapear etiquetas numéricas a etiquetas de texto
    replace_dict = {0: 'Hambre', 1: 'Problemas para respirar', 2: 'Dolor', 3: 'Cansancio/Incomodidad'}
    most_common_predicted_label = replace_dict[most_common_predicted_label]

    return most_common_predicted_label

def clear_audio_input(audio):
    return ""

access_token = os.getenv('HF_ACCESS_TOKEN')

client = InferenceClient("mistralai/Mistral-Nemo-Instruct-2407", token=access_token)

def respond(
    message,
    history: list[tuple[str, str]],
    system_message,
    max_tokens,
    temperature,
    top_p,
):
    messages = [{"role": "system", "content": system_message}]

    for val in history:
        if val[0]:
            messages.append({"role": "user", "content": val[0]})
        if val[1]:
            messages.append({"role": "assistant", "content": val[1]})

    messages.append({"role": "user", "content": message})

    response = ""

    for message in client.chat_completion(
        messages,
        max_tokens=max_tokens,
        stream=True,
        temperature=temperature,
        top_p=top_p,
    ):
        token = message.choices[0].delta.content
        response += token
        yield response

my_theme = gr.themes.Soft(
    primary_hue="emerald",
    secondary_hue="green",
    neutral_hue="slate",
    text_size="sm",
    spacing_size="sm",
    font=[gr.themes.GoogleFont('Nunito'), 'ui-sans-serif', 'system-ui', 'sans-serif'],
    font_mono=[gr.themes.GoogleFont('Nunito'), 'ui-monospace', 'Consolas', 'monospace'],
).set(
    body_background_fill='*neutral_50',
    body_text_color='*neutral_600',
    body_text_size='*text_sm',
    embed_radius='*radius_md',
    shadow_drop='*shadow_spread',
    shadow_spread='*button_shadow_active'
)

# Función para mostrar la página 1
def mostrar_pagina_1():
    return gr.update(visible=False), gr.update(visible=True)

# Función para mostrar la página 2
def mostrar_pagina_2():
    return gr.update(visible=False), gr.update(visible=True)

# Función para regresar a la pantalla inicial
def redirigir_a_pantalla_inicial():
    return gr.update(visible=True), gr.update(visible=False)

### Monitor

processor = Wav2Vec2FeatureExtractor.from_pretrained("ntu-spml/distilhubert")

monitor_model = HubertForSequenceClassification.from_pretrained("A-POR-LOS-8000/distilhubert-finetuned-cry-detector",token=access_token_mod_1)

pipeline_monitor = pipeline(model=monitor_model,feature_extractor=processor)

def predict_monitor(stream, new_chunk):
    sr, y = new_chunk
    y = y.astype(np.float32)
    y /= np.max(np.abs(y))

    if stream is not None:
        stream = np.concatenate([stream, y])
    else:
        stream = y
    return stream, pipeline_monitor(stream) 
    
my_theme = gr.themes.Soft(
    primary_hue="emerald",
    secondary_hue="green",
    neutral_hue="slate",
    text_size="sm",
    spacing_size="sm",
    font=[gr.themes.GoogleFont('Nunito'), 'ui-sans-serif', 'system-ui', 'sans-serif'],
    font_mono=[gr.themes.GoogleFont('Nunito'), 'ui-monospace', 'Consolas', 'monospace'],
).set(
    body_background_fill='*neutral_50',
    body_text_color='*neutral_600',
    body_text_size='*text_sm',
    embed_radius='*radius_md',
    shadow_drop='*shadow_spread',
    shadow_spread='*button_shadow_active'
)

with gr.Blocks(theme = my_theme) as demo:

    with gr.Column() as pantalla_inicial:
        gr.HTML(
            """
            <style>
            @import url('https://fonts.googleapis.com/css2?family=Lobster&display=swap');
            @import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
            
            h1 {
                font-family: 'Lobster', cursive;
                font-size: 5em !important;
                text-align: center;
                margin: 0;
            }
            h2 {
                font-family: 'Lobster', cursive;
                font-size: 3em !important;
                text-align: center;
                margin: 0;
            }
            p.slogan, h4, p, h3 {
                font-family: 'Roboto', sans-serif;
                text-align: center;
            }
            </style>
            <h1>Iremia</h1>
            <h4 style='text-align: center; font-size: 1.5em'>El mejor aliado para el bienestar de tu bebé</h4>
            """
        )
        gr.Markdown("<h4 style='text-align: left; font-size: 1.5em;'>¿Qué es Iremia?</h4>")
        gr.Markdown("<p style='text-align: left'>Iremia es un proyecto llevado a cabo por un grupo de estudiantes interesados en el desarrollo de modelos de inteligencia artificial, enfocados específicamente en casos de uso relevantes para ayudar a cuidar a los más pequeños de la casa.</p>")
        gr.Markdown("<h4 style='text-align: left; font-size: 1.5em;'>Nuestra misión</h4>")
        gr.Markdown("<p style='text-align: left'>Sabemos que la paternidad puede suponer un gran desafío. Nuestra misión es brindarles a todos los padres unas herramientas de última tecnología que los ayuden a navegar esos primeros meses de vida tan cruciales en el desarrollo de sus pequeños.</p>")
        gr.Markdown("<h4 style='text-align: left; font-size: 1.5em;'>¿Qué ofrece Iremia?</h4>")
        gr.Markdown("<p style='text-align: left'>Iremia ofrece dos funcionalidades muy interesantes:</p>")
        gr.Markdown("<p style='text-align: left'>Predictor: Con nuestro modelo de inteligencia artificial, somos capaces de predecir por qué tu hijo de menos de 2 años está llorando. Además, tendrás acceso a un asistente personal para consultar cualquier duda que tengas sobre el cuidado de tu pequeño.</p>")
        gr.Markdown("<p style='text-align: left'>Monitor: Nuestro monitor no es como otros que hay en el mercado, ya que es capaz de reconocer si un sonido es un llanto del bebé o no, y si está llorando, predice automáticamente la causa, lo cual te brindará la tranquilidad de saber siempre qué pasa con tu pequeño y te ahorrará tiempo y muchas horas de sueño.</p>")

        with gr.Row():
            with gr.Column():
                gr.Markdown("<h2>Predictor</h2>")
                boton_pagina_1 = gr.Button("Prueba el predictor")
                gr.Markdown("<p>Descubre por qué llora tu bebé y resuelve dudas sobre su cuidado con nuestro Iremia assistant</p>")
            with gr.Column():
                gr.Markdown("<h2>Monitor</h2>")
                boton_pagina_2 = gr.Button("Prueba el monitor")
                gr.Markdown("<p>Un monitor inteligente que detecta si tu hijo está llorando y te indica el motivo antes de que puedas levantarte del sofá</p>")

    with gr.Column(visible=False) as pagina_1:
        with gr.Row():
            with gr.Column():
                gr.Markdown("<h2>Predictor</h2>")
                audio_input = gr.Audio(type="numpy", label="Baby recorder")
                classify_btn = gr.Button("¿Por qué llora?")
                classification_output = gr.Textbox(label="Tu bebé llora por:")

                classify_btn.click(predict_audio, inputs=audio_input, outputs=classification_output)
                audio_input.change(fn=clear_audio_input, inputs=audio_input, outputs=classification_output)


            with gr.Column():
                gr.Markdown("<h2>Assistant</h2>")
                system_message = "You are a Chatbot specialized in baby health and care."
                max_tokens = 512
                temperature = 0.7
                top_p = 0.95

                chatbot = gr.ChatInterface(
                    respond,
                    additional_inputs=[
                        gr.State(value=system_message),
                        gr.State(value=max_tokens),
                        gr.State(value=temperature),
                        gr.State(value=top_p)
                    ],
                )

                gr.Markdown("Este chatbot no sustituye a un profesional de la salud. Ante cualquier preocupación o duda, consulta con tu pediatra.")

        boton_volver_inicio_1 = gr.Button("Volver a la pantalla inicial")
        boton_volver_inicio_1.click(redirigir_a_pantalla_inicial, inputs=None, outputs=[pantalla_inicial, pagina_1])

    with gr.Column(visible=False) as pagina_2:
        gr.Markdown("<h2>Monitor</h2>")
        gr.Markdown("# Detección en tiempo real del llanto del bebé con Pipeline")

        # Componente de audio en streaming
        audio_input = gr.Audio(source="microphone", streaming=True, format="wav", label="Habla cerca del micrófono")
        
        # Salida del texto donde se muestra la predicción
        output_text = gr.Textbox(label="Resultado de la predicción")
        
        # Vincular la predicción en streaming con el audio
        audio_input.stream(fn=lambda audio: predict_monitor(audio, audio_classifier),
                           inputs=audio_input,
                           outputs=output_text)

        boton_volver_inicio_2 = gr.Button("Volver a la pantalla inicial")
        boton_volver_inicio_2.click(redirigir_a_pantalla_inicial, inputs=None, outputs=[pantalla_inicial, pagina_2])

    boton_pagina_1.click(mostrar_pagina_1, inputs=None, outputs=[pantalla_inicial, pagina_1])
    boton_pagina_2.click(mostrar_pagina_2, inputs=None, outputs=[pantalla_inicial, pagina_2])

demo.launch()