Una guida completa per creare un assistente IA per riassumere video di YouTube – Parte 1

Una guida completa per creare un assistente IA per riassumere video di YouTube - Parte 1 I fondamenti

Trascrivi un video di YouTube utilizzando il modello Whisper di OpenAI

Immagine generata dall'autore con Playground.ai

Questo articolo è il primo di una serie di tre post sul blog che spiega passo dopo passo come ho costruito un assistente intelligente per riassumere i video di YouTube. Iniziamo questa serie con istruzioni dettagliate per catturare la trascrizione di un video di YouTube utilizzando Whisper di OpenAI, un modello di conversione del parlato in testo open source. Nel prossimo post, copriremo i fondamenti della sintesi del testo utilizzando Langchain e istruzioni dettagliate per implementare una pipeline di sintesi basata su Falcon-7b-instruct, un LLM ottimizzato per istruzioni e open source. Nel post finale, vedremo come dimostrare un prototipo di soluzione utilizzando Gradio e Hugging Face Spaces. In questi post, valutiamo diverse alternative architettoniche per l’implementazione di ogni passaggio.

Introduzione

Immagina questo: Stai cercando un video che contiene informazioni su un argomento specifico che ti appassiona. Una rapida ricerca su YouTube inonda il tuo schermo con anteprime affascinanti e titoli di video intriganti. La maggior parte delle persone si tufferebbe istintivamente nello scroll, cercando gemme che valga la pena cliccare. Eppure, quanto spesso ti ritrovi a scorrere un video, sperando che contenga la risposta elusiva alle tue domande? Se sei come me, questa situazione si verifica troppo spesso e l’esperienza non è solo una perdita di tempo, ma anche incredibilmente fastidiosa!

Motivato da questa frustrazione ricorrente, ho intrapreso un viaggio per creare il mio assistente personale di intelligenza artificiale. Questo compagno intelligente esamina i contenuti video e riassume in modo efficiente le idee principali e gli argomenti, risparmiandomi tempo e sanità mentale!

Nella creazione di questo strumento, ho utilizzato il modello di lingua Falcon. Ed ecco una divertente analogia: proprio come un falco che vola graziosamente ad alte altitudini, possedendo contemporaneamente la capacità di zoomare su qualsiasi oggetto di interesse, il nostro strumento basato su Falcon consente agli utenti di avere una visione d’insieme dei contenuti mentre passano senza sforzo a una esplorazione dettagliata attraverso una completa trascrizione! 🙂

Potresti chiederti, “Ma non esistono già servizi online che fanno questo?” E avresti assolutamente ragione! Tuttavia:

  1. Spesso hanno limiti di utilizzo che potrebbero comportare costi aggiuntivi.
  2. Desideravo avere maggior controllo sulle sintesi generate, senza la possibilità di impostare i parametri in base alle mie esigenze specifiche.
  3. Come dice il proverbio, “La gioia è nel viaggio!”

Quindi, ho preso in mano la situazione e ho sviluppato un’app che prende in input l’URL di un video di YouTube e fornisce un riassunto conciso. Piuttosto figo, vero?

Una schermata dell'interfaccia utente dell'app ospitata su Hugging Face Spaces — Immagine dell'autore

Una soluzione blueprint

I componenti interni della soluzione svolgono le seguenti attività:

  1. Ottieni la trascrizione da YouTube se disponibile. In caso contrario, trascrivi il video utilizzando un modello di conversione del parlato in testo (Whisper) su Hugging Face.
  2. Riassumi la trascrizione utilizzando un approccio map-reduce utilizzando Langchain e un grande modello di lingua ottimizzato per seguire le istruzioni (Falcon-7b-instruct) su Hugging Face.
  3. Fornisci un’interfaccia utente piacevole utilizzando Gradio che consente all’utente di interagire in modo fluido con il modello, generare e rivedere il riassunto affiancato al video stesso.
Una visione ad alto livello dell'architettura della soluzione — Immagine dell'autore

Nel corso dell’implementazione di ogni passaggio, ho provato varie alternative architettoniche. Ad esempio, ho implementato ogni passaggio in due versioni: inference on-prem vs. inference on-cloud. Oppure, per quanto riguarda l’hosting dell’app, ho provato on-prem vs. on-cloud ospitato su Hugging Face Spaces.

Se qualcosa di tutto ciò suscita la tua curiosità, seguimi, parliamo e impariamo gli uni dagli altri.

Prima di procedere alla prossima sezione, suggerirei di dare un’occhiata rapida al prototipo ospitato su Hugging Face Spaces. Sentiti libero di provarlo e fammi sapere nei commenti quale sia stata la tua prima impressione.

Passo 1: Cattura della trascrizione video di YouTube

Prima di poter riassumere un video, abbiamo bisogno della sua trascrizione in formato testo. Sebbene le trascrizioni siano disponibili per molti video di YouTube, potresti trovarne alcuni che non le hanno. Se la trascrizione è disponibile, la scarichiamo semplicemente utilizzando youtube_transcript_api e pytube:

from youtube_transcript_api import YouTubeTranscriptApi
import pytube

# ottieni la trascrizione da YouTube
def get_yt_transcript(url):
    text = ''
    vid_id = pytube.extract.video_id(url)
    temp = YouTubeTranscriptApi.get_transcript(vid_id)
    for t in temp:
        text+=t['text']+' '
    return text

Il codice ottiene semplicemente l’ID del video di YouTube dall’URL e utilizza il YouTubeTranscriptApi per ottenere l’oggetto della trascrizione. L’oggetto della trascrizione è una lista di dizionari, ognuno dei quali contiene il testo della trascrizione, l’ora di inizio e la durata di visualizzazione nel video. La proprietà che ci interessa qui è solo il testo.

Ma cosa succede se YouTube non ha una trascrizione per un video? Ora le cose diventano più interessanti…

Trascrivi utilizzando Whisper

A tal scopo, ho utilizzato il famoso modello Whisper, un modello voice2text open source di OpenAI. Per ora, non dobbiamo preoccuparci troppo del funzionamento interno del modello, purché serva al nostro scopo. Anche se sono disponibili molte risorse online a riguardo, se noto interesse nei commenti, ne parlerò anche in un post separato sul blog.

Prima di utilizzare il modello Whisper, dobbiamo scaricare l’audio del video in una directory locale, cosa che possiamo fare con poche righe di codice:

from pytube import YouTube
yt = YouTube(str(url))
audio = yt.streams.filter(only_audio = True).first()
out_file = audio.download(filename="audio.wav",output_path="./docs/youtube/")

Ora siamo pronti a utilizzare Whisper per elaborare direttamente il file audio come input e trascriverlo. Prima creiamo un oggetto di pipeline per Transformers che scarica il modello da HuggingFace:

import transformers
whisper_asr = transformers.pipeline(
    "automatic-speech-recognition", model="openai/whisper-large", device_map= 'auto',)

Whisper è disponibile in diverse dimensioni, dalle versioni tiny (con 39 milioni di parametri) a quelle large (con 1,55 miliardi di parametri). Ho utilizzato il modello whisper-large per ottenere la massima qualità dei risultati. Una volta caricato e avviato il punteggio, ha raggiunto un picco di utilizzo di 12 GB della mia memoria GPU da 16 GB, il che andava bene. Ma puoi scegliere di utilizzare versioni più piccole se si adattano al tuo caso d’uso.

Quindi, dobbiamo impostare i parametri di configurazione del modello, incluso il linguaggio e il tipo di task:

whisper_asr.model.config.forced_decoder_ids = (
    whisper_asr.tokenizer.get_decoder_prompt_ids(
        language="en",
        task="transcribe"
    ))

In questo scenario, ho limitato la pipeline a trascrivere solo video in inglese. Tuttavia, potresti utilizzare lo stesso modello per trascrivere dozzine di altre lingue. Per fare ciò, dovresti determinare la lingua del video prima di configurare la pipeline di trascrizione. Lascio questa attività agli interessati lettori come esercizio.

Infine, chiamiamo il modello per l’inferring:

temp = whisper_asr(out_file,chunk_length_s=20)text = temp['text']

Ma cos’è l’argomento chunk_length_s? Il modello Whisper è progettato per elaborare file audio con una durata massima di 30 secondi. Pertanto, il file deve essere suddiviso in frammenti prima di essere passato al modello. chunk_length_s controlla semplicemente la lunghezza di questi frammenti.

Mettendo tutto insieme, il codice avrà questo aspetto:

from pytube import YouTubeimport transformersimport torch# trascribe il video di YouTubedef transcribe_yt_vid(url):    # scarica l'audio del video di YouTube    save_dir="./docs/youtube/"    yt = YouTube(str(url))    audio = yt.streams.filter(only_audio = True).first()    out_file = audio.download(filename="audio.wav",                              output_path = save_dir)    # definizione di una pipeline di automatic-speech-recognition usando `openai/whisper-large`    whisper_asr = transformers.pipeline(        "automatic-speech-recognition",        model="openai/whisper-large",        device_map= 'auto',    )    # impostazione dei parametri di configurazione del modello    whisper_asr.model.config.forced_decoder_ids = (        whisper_asr.tokenizer.get_decoder_prompt_ids(            language="en",            task="transcribe"        )    )    # invocazione del modello Whisper    temp = whisper_asr(out_file,chunk_length_s=20)    text = temp['text']       # possiamo farlo alla fine per liberare la memoria GPU    del(whisper_asr)    torch.cuda.empty_cache()       return text

OK, Brillante!!! Ma aspetta! E se non ho abbastanza potenza di calcolo in locale e voglio eseguire l’inferring nel cloud?

Inferring usando le API di HuggingFace Hub

La buona notizia è che HuggingFace permette di eseguire l’inferring nel loro cloud utilizzando le API di HuggingFace Hub.

Ecco come funzionerebbe:

from HuggingFace_hub import InferenceClient# Inizializza il client per il modello Whisperclient = InferenceClient(model="openai/whisper-large", token="xxxxxxxxxxx")

Basterà passare un argomento token ottenibile da HuggingFace gratuitamente.

Ora, qui ho incontrato un problema! L’API di inferring troncava il risultato per qualche motivo. Non sono riuscito a capire dalle risorse online se questo è un comportamento atteso o forse semplicemente una limitazione dovuta all’uso del servizio gratuito. In ogni caso, un trucco è dividere l’audio in frammenti prima di inviarli all’API di inferring. Ciò può essere fatto utilizzando librosa per caricare il file audio come un array numpy, poi suddividerlo in frammenti con una lunghezza che non venga troncata dall’API (per me, 20 secondi ha funzionato bene), e infine, salvare ogni frammento in un file che viene quindi inviato all’API per l’inferring:

import librosaimport soundfile as sfx, sr = librosa.load(out_file, sr=None)t=20 # durata del frammento audio in secondi# Questo fornisce x come file audio in un array numpy e sr come frequenza di campionamento originale# L'audio deve essere suddiviso in frammenti di 20 secondi poiché la chiamata all'API tronca la rispostatext = ''for i in range(0, (len(x)//(t * sr)) +1):    y = x[t * sr * i: t * sr *(i+1)]    split_path = save_dir+"audio_split.wav"    sf.write(split_path, y, sr)    text += client.automatic_speech_recognition(split_path)

Con questo trucco, sono riuscito a trascrivere anche video più lunghi utilizzando l’API. Tuttavia, ricorda che l’abbonamento gratuito limita il tasso di inferring. Ciò significa che se richiami l’API troppe volte in un breve periodo di tempo, potresti ottenere un errore. La buona notizia è che il limite viene ripristinato ogni ora, quindi non dovrai aspettare troppo a lungo prima di poter testare di nuovo il tuo codice. Ma ciò significa anche che potresti non essere in grado di utilizzare questo trucco per video troppo lunghi!

Il risultato finale potrebbe essere simile a questo:

from pytube import YouTubefrom huggingface_hub import InferenceClient# Trascrive il video utilizzando l'API di Hugging Face Hubdef transcribe_yt_vid_api(url):    # scarica l'audio del video di YouTube    yt = YouTube(str(url))    audio = yt.streams.filter(only_audio = True).first()    out_file = audio.download(filename="audio.wav",                              output_path = save_dir)       # Inizializza il client per il modello Whisper    client = InferenceClient(model="openai/whisper-large",                       token=os.environ["HUGGINGFACEHUB_API_TOKEN"])    import librosa    import soundfile as sf    text = ''    t=20 # durata del frammento audio in secondi    x, sr = librosa.load(out_file, sr=None)    # Questo fornisce x come file audio in un array numpy e sr come frequenza di campionamento originale    # L'audio deve essere suddiviso in frammenti di 20 secondi poiché la chiamata all'API tronca la risposta    for i in range(0, (len(x)//(t * sr)) +1):        y = x[t * sr * i: t * sr *(i+1)]        split_path = save_dir+"audio_split.wav"        sf.write(split_path, y, sr)        text += client.automatic_speech_recognition(split_path)    return text

Mettendo tutto insieme

Adesso per mettere insieme i due approcci in una sola funzione, possiamo fare qualcosa del genere:

def trascrivi_video_youtube(url, forza_trascrizione=False, usa_api=False):       yt = YouTube(str(url))    testo = ''    # ottieni la trascrizione da YouTube se disponibile    try:        testo = get_yt_trascrizione(url)    except:        print('La trascrizione non era disponibile, trascrivendo ora...')        pass       # trascrive il video se YouTube non fornisce una trascrizione    # o se desideri forzare la trascrizione comunque    if testo == '' or forza_trascrizione:        if usa_api:            testo = trascrivi_video_yt_api(url)        else:            testo = trascrivi_video_yt(url)       return yt.title, testo

Conclusione

Ripassiamo ciò che abbiamo trattato in questo post. Abbiamo creato tre diverse funzioni per catturare la trascrizione di un video YouTube: la prima la scarica direttamente da YouTube, la seconda la trascrive utilizzando il modello Whisper di OpenAI in locale e la terza lo fa tramite chiamate API di Hugging Face Hub. È importante notare che la distribuzione in ambienti di produzione richiederebbe un po’ più di impegno. A seconda della velocità di inferenza e della quantità di risorse richiesta, il modello potrebbe essere spinto su un endpoint. Hugging Face fornisce servizi di endpoint di inferenza, dove il modello viene distribuito su infrastrutture dedicate e con autoscaling. Lasciamo questa discussione per un’altra occasione.

Nel prossimo post, ti guiderò attraverso i passaggi per prendere la trascrizione e riassumerla utilizzando Langchain e Falcon-7b-instruct su HuggingFace.