Una guida per principianti alla creazione di grafici della conoscenza dai video |  di Mohammed Mohammed |  Gennaio 2024

 | Intelligenza-Artificiale

Costruisci una pipeline per analizzare e archiviare i dati all’interno dei video.

Prima di immergerci nell’aspetto tecnico dell’articolo, definiamo il contesto e rispondiamo alla domanda che potresti avere: cos’è un grafico della conoscenza?

E per rispondere a questa domanda, immagina che invece di conservare la conoscenza negli armadi, la conserviamo in una rete di tessuto. Ogni fatto, concetto, informazione su persone, luoghi, eventi o anche idee astratte sono nodi e la linea che li collega tra loro è la relazione che hanno tra loro. Questa intricata rete, amici miei, è l’essenza di un grafico della conoscenza.

fotografato da Shubham Dhage SU Unsplash

Pensala come una vivace mappa della città, che non mostra solo le strade ma rivela le connessioni tra punti di riferimento, parchi e negozi. Allo stesso modo, un grafico della conoscenza non memorizza solo fatti freddi; cattura il ricco arazzo di come le cose sono collegate. Ad esempio, potresti scoprire che Marie Curie ha scoperto il radio, quindi seguire un thread per vedere che il radio viene utilizzato nei trattamenti medici, che a loro volta si collegano agli ospedali e alla ricerca sul cancro. Vedi come un fatto porta facilmente a un altro, dipingendo un quadro più ampio?

Allora perché questo modo di archiviare la conoscenza simile a una mappa è così popolare? Bene, immagina di cercare informazioni online. I metodi tradizionali spesso ti lasciano con frammenti isolati, come trovare solo edifici su una mappa senza conoscere le strade che li collegano. Un grafico della conoscenza, invece, ti accompagna in un viaggio, guidandoti da un fatto all’altro, come se una guida amichevole sussurrasse storie affascinanti dietro ogni angolo del mondo dell’informazione. Interessante vero? Lo so.

Da quando ho scoperto questa magia, ha catturato la mia attenzione e ho esplorato e giocato con molte potenziali applicazioni. In questo articolo ti mostrerò come costruire una pipeline che estrae l’audio dal video, quindi lo trascrive e, dalla trascrizione, crea un grafico della conoscenza che consenta una rappresentazione più sfumata e interconnessa delle informazioni all’interno del video.

Utilizzerò Google Drive per caricare l’esempio video. Utilizzerò anche Google Colab per scrivere il codice e, infine, avrai bisogno dell’accesso all’API GPT Plus per questo progetto. Lo suddividerò in passaggi per renderlo chiaro e facile per i principianti:

  • Configurare tutto.
  • Estrazione dell’audio dal video.
  • Trascrizione dell’audio in testo.
  • Costruire il grafico della conoscenza.

Alla fine di questo articolo costruirai un grafico con il seguente schema.

Immagine dell’autore

Immergiamoci subito!

Come accennato, utilizzeremo Google Drive e Colab. Nella prima cella colleghiamo Google Drive a Colab e creiamo le nostre cartelle di directory (video_files, audio_files, text_files). Il seguente codice può ottenere questo risultato. (Se vuoi seguire il codice, ho caricato tutto il codice per questo progetto su GitHub; puoi accedervi da Qui.)

# installing required libraries
!pip install pydub
!pip install git+https://github.com/openai/whisper.git
!sudo apt update && sudo apt install ffmpeg
!pip install networkx matplotlib
!pip install openai
!pip install requests

# connecting google drive to import video samples

from google.colab import drive
import os
drive.mount('/content/drive')

video_files = '/content/drive/My Drive/video_files'
audio_files = '/content/drive/My Drive/audio_files'
text_files = '/content/drive/My Drive/text_files'

folders = (video_files, audio_files, text_files)
for folder in folders:
# Check if the output folder exists
if not os.path.exists(folder):
# If not, create the folder
os.makedirs(folder)

Oppure puoi creare le cartelle manualmente e caricare il tuo campione video nella cartella “video_files”, a seconda di quale sia più semplice per te.

Ora abbiamo le nostre tre cartelle con un esempio video nella cartella “video_files” per testare il codice.

La prossima cosa che vogliamo fare è importare il nostro video ed estrarne l’audio. Possiamo usare il Pydub libreria, che è una libreria di elaborazione audio di alto livello che può aiutarci a farlo. Vediamo il codice e poi lo spieghiamo di seguito.

from pydub import AudioSegment
# Extract audio from videos
for video_file in os.listdir(video_files):
if video_file.endswith('.mp4'):
video_path = os.path.join(video_files, video_file)
audio = AudioSegment.from_file(video_path, format="mp4")

# Save audio as WAV
audio.export(os.path.join(audio_files, f"{video_file(:-4)}.wav"), format="wav")

Dopo aver installato il nostro pacchetto pydubabbiamo importato il Segmento audio classe da Pydub biblioteca. Quindi, abbiamo creato un ciclo che scorre tutti i file video nella cartella “video_files” che abbiamo creato in precedenza e passa ogni file attraverso AudioSegment.from_file per caricare l’audio dal file video. L’audio caricato viene quindi esportato come file WAV utilizzando audio.esportazione e salvato nella cartella “audio_files” specificata con lo stesso nome del file video ma con estensione .wav.

A questo punto potete andare nella cartella “audio_files” di Google Drive dove vedrete l’audio estratto.

Nel terzo passaggio, trascriveremo il file audio che abbiamo in un file di testo e lo salveremo come file .txt nella cartella “text_files”. Qui ho utilizzato il sistema Whisper ASR (Automatic Speech Recognition) di OpenAI per farlo. L’ho usato perché è facile e abbastanza preciso, inoltre ha diversi modelli per diversa precisione. Ma quanto più accurato è il modello, tanto più grande è, tanto più lento sarà il caricamento, quindi utilizzerò quello medio solo a scopo dimostrativo. Per rendere il codice più pulito, creiamo una funzione che trascrive l’audio e quindi utilizziamo un loop per utilizzare la funzione su tutti i file audio nella nostra directory

import re
import subprocess
# function to transcribe and save the output in txt file
def transcribe_and_save(audio_files, text_files, model='medium.en'):
# Construct the Whisper command
whisper_command = f"whisper '{audio_files}' --model {model}"
# Run the Whisper command
transcription = subprocess.check_output(whisper_command, shell=True, text=True)

# Clean and join the sentences
output_without_time = re.sub(r'\(\d+:\d+\.\d+ --> \d+:\d+\.\d+\) ', '', transcription)
sentences = (line.strip() for line in output_without_time.split('\n') if line.strip())
joined_text = ' '.join(sentences)

# Create the corresponding text file name
audio_file_name = os.path.basename(audio_files)
text_file_name = os.path.splitext(audio_file_name)(0) + '.txt'
file_path = os.path.join(text_files, text_file_name)

# Save the output as a txt file
with open(file_path, 'w') as file:
file.write(joined_text)

print(f'Text for {audio_file_name} has been saved to: {file_path}')

# Transcribing all the audio files in the directory
for audio_file in os.listdir(audio_files):
if audio_file.endswith('.wav'):
audio_files = os.path.join(audio_files, audio_file)
transcribe_and_save(audio_files, text_files)

Librerie utilizzate:

  • os: fornisce un modo di interagire con il sistema operativo, utilizzato per gestire percorsi e nomi di file.
  • Rif: Modulo di espressioni regolari per la corrispondenza e la sostituzione di pattern.
  • sottoprocesso: consente la creazione di processi aggiuntivi, qui utilizzati per eseguire il sistema Whisper ASR dalla riga di comando.

Abbiamo creato un comando Whisper e lo abbiamo salvato come variabile per facilitare il processo. Successivamente, abbiamo utilizzato sottoprocesso.check_output per eseguire il comando Whisper e salvare la trascrizione risultante nella variabile di trascrizione. Ma la trascrizione a questo punto non è pulita (puoi verificarlo stampando la variabile di trascrizione fuori dalla funzione; ha timestamp e un paio di righe che non sono rilevanti per la trascrizione), quindi abbiamo aggiunto un codice di pulizia che rimuove il timestamp utilizzando re.sub e unisce le frasi insieme. Successivamente, abbiamo creato un file di testo all’interno della cartella “text_files” con lo stesso nome dell’audio e abbiamo salvato al suo interno la trascrizione pulita.

Ora se vai nella cartella “text_files”, puoi vedere il file di testo che contiene la trascrizione. Woah, passaggio 3 completato con successo! Congratulazioni!

Questa è la parte cruciale – e forse la più lunga. Seguirò un approccio modulare con 5 funzioni per gestire questa attività, ma prima iniziamo con le librerie e i moduli necessari per effettuare richieste HTTP richiestegestire JSON jsonlavorare con frame di dati pandae creazione e visualizzazione di grafici networkx E matplotlib. E impostando le costanti globali che sono variabili utilizzate in tutto il codice. API_ENDPOINT è l’endpoint per l’API di OpenAI, API_KEY è dove verrà archiviata la chiave API OpenAI e testo_promp memorizzerà il testo utilizzato come input per il prompt OpenAI. Tutto questo è fatto in questo codice

import requests
import json
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt

# Global Constants API endpoint, API key, prompt text
API_ENDPOINT = "https://api.openai.com/v1/chat/completions"
api_key = "your_openai_api_key_goes_here"
prompt_text = """Given a prompt, extrapolate as many relationships as possible from it and provide a list of updates.
If an update is a relationship, provide (ENTITY 1, RELATIONSHIP, ENTITY 2). The relationship is directed, so the order matters.
Example:
prompt: Sun is the source of solar energy. It is also the source of Vitamin D.
updates:
(("Sun", "source of", "solar energy"),("Sun","source of", "Vitamin D"))
prompt: $prompt
updates:"""

Proseguiamo quindi con la scomposizione della struttura delle nostre funzioni:

La prima funzione, crea_grafo()il compito di questa funzione è creare una visualizzazione grafica utilizzando il file networkx biblioteca. Ci vuole un DataFrame df e un dizionario delle etichette dei bordi rel_labels — che verrà creato nella funzione seguente — come input. Quindi, utilizza DataFrame per creare un grafico diretto e visualizzarlo utilizzando matplotlib con qualche personalizzazione e produce il bellissimo grafico di cui abbiamo bisogno

# Graph Creation Function

def create_graph(df, rel_labels):
G = nx.from_pandas_edgelist(df, "source", "target",
edge_attr=True, create_using=nx.MultiDiGraph())
plt.figure(figsize=(12, 12))

pos = nx.spring_layout(G)
nx.draw(G, with_labels=True, node_color='skyblue', edge_cmap=plt.cm.Blues, pos=pos)
nx.draw_networkx_edge_labels(
G,
pos,
edge_labels=rel_labels,
font_color='red'
)
plt.show()

Il DataFrame df e le etichette sui bordi rel_labels sono l’output della funzione successiva, che è: preparazione_dati_per_grafo(). Questa funzione accetta OpenAI api_response — che verrà creato dalla seguente funzione — come input ed estrae le triple entità-relazione (fonte, destinazione, bordo) da. Qui abbiamo usato il json modulo per analizzare la risposta e ottenere i dati rilevanti, quindi filtrare gli elementi che presentano dati mancanti. Successivamente, crea un dataframe della knowledge base kg_df dalle triple e, infine, creare un dizionario (relazioni_etichette) mappando coppie di nodi alle etichette dei bordi corrispondenti e, ovviamente, restituiscono DataFrame e il dizionario.

# Data Preparation Function

def preparing_data_for_graph(api_response):
#extract response text
response_text = api_response.text
entity_relation_lst = json.loads(json.loads(response_text)("choices")(0)("text"))
entity_relation_lst = (x for x in entity_relation_lst if len(x) == 3)
source = (i(0) for i in entity_relation_lst)
target = (i(2) for i in entity_relation_lst)
relations = (i(1) for i in entity_relation_lst)

kg_df = pd.DataFrame({'source': source, 'target': target, 'edge': relations})
relation_labels = dict(zip(zip(kg_df.source, kg_df.target), kg_df.edge))
return kg_df,relation_labels

La terza funzione è call_gpt_api()che è responsabile di effettuare una richiesta POST all’API OpenAI e di generare il file api_response. Qui costruiamo il payload dei dati con informazioni sul modello, prompt e altri parametri come il modello (in questo caso: gpt-3.5-turbo-istruire), max_tokens, stop e temperatura. Quindi inviare la richiesta utilizzando richieste.post e restituire la risposta. Ho incluso anche una semplice gestione degli errori per stampare un messaggio di errore nel caso in cui si verifichi un’eccezione. Il blocco try contiene il codice che potrebbe sollevare un’eccezione dalla richiesta durante l’esecuzione, quindi se si verifica un’eccezione durante questo processo (ad esempio, a causa di problemi di rete, errori API, ecc.), verrà eseguito il codice all’interno del blocco eccetto .

# OpenAI API Call Function
def call_gpt_api(api_key, prompt_text):
global API_ENDPOINT
try:
data = {
"model": "gpt-3.5-turbo",
"prompt": prompt_text,
"max_tokens": 3000,
"stop": "\n",
"temperature": 0
}
headers = {"Content-Type": "application/json", "Authorization": "Bearer " + api_key}
r = requests.post(url=API_ENDPOINT, headers=headers, json=data)
response_data = r.json() # Parse the response as JSON
print("Response content:", response_data)
return response_data
except Exception as e:
print("Error:", e)

Quindi la funzione penultima è the principale() funzione, che orchestra il flusso principale dello script. Per prima cosa legge il contenuto del file di testo dalla cartella “text_files” che avevamo in precedenza e lo salva nella variabile kb_testo. Porta la variabile globale testo_prompche memorizza il nostro prompt, quindi sostituisci un segnaposto nel modello di prompt ($richiesta) con il contenuto del file di testo kb_testo. Allora chiama il call_gpt_api() funzione, dagli il api_key E testo_promp per ottenere la risposta dell’API OpenAI. La risposta viene quindi passata a preparazione_dati_per_grafo() per preparare i dati e ottenere il DataFrame e il dizionario delle etichette dei bordi, infine passare questi due valori al file crea_grafo() funzione per costruire il grafo della conoscenza.

# Main function

def main(text_file_path, api_key):

with open(file_path, 'r') as file:
kb_text = file.read()

global prompt_text
prompt_text = prompt_text.replace("$prompt", kb_text)

api_response = call_gpt_api(api_key, prompt_text)
df, rel_labels = preparing_data_for_graph(api_response)
create_graph(df, rel_labels)code

Infine, abbiamo il inizio() funzione, che scorre tutti i file di testo nella nostra cartella “text_files” – se ne abbiamo più di uno, ottiene il nome e il percorso del file e lo passa insieme al api_key alla funzione principale per svolgere il suo lavoro.

# Start Function

def start():
for filename in os.listdir(text_files):
if filename.endswith(".txt"):
# Construct the full path to the text file
text_file_path = os.path.join(text_files, filename)
main(text_file_path, api_key)

Se hai seguito correttamente i passaggi, dopo aver eseguito il file inizio() funzione, dovresti vedere una visualizzazione simile.

Immagine dell’autore

Ovviamente puoi salvare questo grafico della conoscenza nel database Neo4j e portarlo oltre.

NOTA: questo flusso di lavoro si applica SOLO ai video di tua proprietà o i cui termini consentono questo tipo di download/elaborazione.

I grafici della conoscenza utilizzano relazioni semantiche per rappresentare i dati, consentendo una comprensione più sfumata e consapevole del contesto. Questa ricchezza semantica consente interrogazioni e analisi più sofisticate, poiché le relazioni tra le entità sono definite esplicitamente.

In questo articolo, descrivo i passaggi dettagliati su come costruire una pipeline che coinvolga l’estrazione dell’audio dai video, la trascrizione con Whisper ASR di OpenAI e la creazione di un grafico della conoscenza. Essendo interessato a questo campo, spero che questo articolo sia più facile da comprendere per i principianti, dimostrando il potenziale e la versatilità delle applicazioni del knowledge graph.

E come sempre l’intero codice è disponibile in GitHub.

Fonte: towardsdatascience.com

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *