#
Capire la classe Interface

In questa sezione, daremo un’occhiata più da vicino alla classe `Interface` e scopriremo i parametri principali che si usano per crearne una.

##
Come creare una Interface

Si può notare che la classe `Interface` (interfaccia) ha 3 parametri necessari:

`Interface(fn, inputs, outputs, ...)`

Questi parametri sono:

- `fn`: la funzione per le predizione chi viene utilizzata dall’interfaccia di Gradio. Questa funzione può accettare uno o più parametri e restituire uno o più valori
- `inputs`: il/i tipo/i dei componenti in input. Gradio fornisce molti componenti predefiniti, come `"image"`(immagine) o `"mic"`(microfono).
- `outputs`: il/i tipo/i dei componenti in output. Anche in questo caso, Gradio fornisce molti componenti predefiniti, come `"image"` o `"label"`.

Per un elenco completo dei componenti, consultare la documentazione di Gradio. Ogni componente predefinito può essere personalizzato istanziando la classe corrispondente al componente.

Ad esempio, come abbiamo visto nella sezione precedente, invece di passare `"textbox"` al parametro `inputs`, si può passare un componente `Textbox(lines=7, label="Prompt")` per creare una casella di testo con 7 righe e un’etichetta.

Diamo un’occhiata a un altro esempio, questa volta con un componente `Audio`.

##
Un semplice esempio con l'audio

Come detto in precedenza, Gradio fornisce molti input e output differenti. Costruiamo perciò una `Interface` che funziona con l’audio.

In questo esempio, svilupperemo una funzione da audio ad audio che prende un file audio e semplicemente lo inverte.

Per l’input utilizzeremo il componente `Audio`. Quando si usa il componente `Audio`, si può specificare se si vuole che la `source` (sorgente) dell’audio sia un file caricato dall’utente o un microfono con cui l’utente può registrare la propria voce. In questo caso, impostiamo `"microphone"`. Per divertimento, aggiungeremo un’etichetta al nostro `Audio` che dice “Speak here…” (“Parla qui…”).

Inoltre, vorremmo ricevere l’audio come un numpy array, in modo da poterlo facilmente “invertire”. Impostiamo quindi il `"type"` come `"numpy"`, che passa i dati in input come una tupla di (`sample_rate`, `data`) alla nostra funzione.

Utilizzeremo anche il componente di output `Audio`, il quale può convertire automaticamente una tupla formata da una frequenza di campionamento e un numpy array di dati in un file audio riproducibile. In questo caso, non abbiamo bisogno di fare alcuna personalizzazione, quindi useremo la stringa `"audio"`.

    import numpy as np
    import gradio as gr

    def reverse_audio(audio):
        sr, data = audio
        reversed_audio = (sr, np.flipud(data))
        return reversed_audio

    mic = gr.Audio(source="microphone", type="numpy", label="Speak here...")
    gr.Interface(reverse_audio, mic, "audio").launch()

Il codice precedente produrrà un’interfaccia come quella qui sotto (se il tuo browser non chiede il premesso per usare il microfono, apri il demo in una tab diversa.)

A questo punto potresti registrare la tua voce e di sentirti parlare al contrario - spaventoso 👻!

##
Lavorare con più input e output

Supponiamo di avere una funzione più complicata, con più input e output. Nell’esempio seguente, abbiamo una funzione che richiede un elenco a tendina, il valore di uno slider e un numero, e restituisce il campione audio di una nota musicale.

Osserva come si passa un elenco di componenti di input e di output, e vedi se riesci a seguire quello che succede.

La questione fondamentale è che quando si passa:

- un elenco di componenti di input, ogni componente corrisponde in ordine a un parametro.
- un elenco di componenti di output, ogni componente corrisponde a un valore restituito.

Lo snippet di codice qui sotto mostra come tre componenti di input si abbinano ai tre argomenti della funzione `generate_tone()`:

    import numpy as np
    import gradio as gr

    notes = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]

    def generate_tone(note, octave, duration):
        sr = 48000
        a4_freq, tones_from_a4 = 440, 12 * (octave - 4) + (note - 9)
        frequency = a4_freq * 2 ** (tones_from_a4 / 12)
        duration = int(duration)
        audio = np.linspace(0, duration, duration * sr)
        audio = (20000 * np.sin(audio * (2 * np.pi * frequency))).astype(np.int16)
        return (sr, audio)

    gr.Interface(
        generate_tone,
        [
            gr.Dropdown(notes, type="index"),
            gr.Slider(minimum=4, maximum=6, step=1),
            gr.Textbox(type="number", value=1, label="Duration in seconds"),
        ],
        "audio",
    ).launch()

###
Il metodo `launch()`

Per ora, abbiamo utilizzato il metodo `launch()` per avviare l’interfaccia, ma non abbiamo discusso realmente cosa fa.

Di default, il metodo `launch()` avvia la demo in un web server che che viene eseguito in locale. Se si esegue il codice in un Jupyter o Colab notebook, Gradio incorporerà l’interfaccia grafica della demo nel notebook, così da poterla usare facilmente.

È possibile modificare il comportamento di `launch()` attraverso diversi parametri:

- `inline` - per visualizzare l’interfaccia inline sui notebook di Python.
- `inbrowser` - per avviare automaticamente l’interfaccia in una nuova scheda del browser di default.
- `share` - per create un link pubblico per l’interfaccia da condividere dal proprio computer. Un po’ come un link di Google Drive!

Il parametro `share` sarà trattato in modo molto più dettagliato nella prossima sezione!

##
✏️ Mettiamolo in pratica!

Costruiamo un’interfaccia che permetta di provare un modello di riconoscimento vocale. Per renderlo interessante, accetteremo un input qualisiasi tra un microfono o un file caricato.

Come al solito, caricheremo il nostro modello di riconoscimento vocale usando la funzione `pipeline()` da 🤗 Transformers. Se si ha bisogno di un ripasso veloce, si può tornare a quella sezione nel Capitolo 1. Quindi, implementeremo una funzione `transcribe_audio()` che elabora l’audio e restituisce la sua trascrizione. Infine, avvolgeremo questa funzione in una `Interface` con i componenti `Audio` per gli input e solo testo per l’output. Il codice completo per questa applicazione è il seguente:

    from transformers import pipeline
    import gradio as gr

    model = pipeline("automatic-speech-recognition")

    def transcribe_audio(mic=None, file=None):
        if mic is not None:
            audio = mic
        elif file is not None:
            audio = file
        else:
            return "You must either provide a mic recording or a file"
        transcription = model(audio)["text"]
        return transcription

    gr.Interface(
        fn=transcribe_audio,
        inputs=[
            gr.Audio(source="microphone", type="filepath", optional=True),
            gr.Audio(source="upload", type="filepath", optional=True),
        ],
        outputs="text",
    ).launch()

Se il tuo browser non ti chiede i permessi per il microfono, apri la demo in una scheda separata.

Ecco fatto! Ora è possibile utilizzare questa interfaccia per trascrivere l’audio. Si osservi che passando il parametro `optional` come `True`, si permette all’utente di fornire o un microfono o un file audio (o nessuno dei due, ma questo restituirà un messaggio di errore).

Continua a leggere per scoprire come condividere la tua interfaccia con gli altri!