En este tutorial, utilizará el modelo de IBM Granite 3.3 de código abierto para generar la transcripción del podcast IBM Mixture of Experts de YouTube. Luego, usando el LLM de código abierto IBM Granite-3.3-8B-Instruct, se creará un resumen de la transcripción generada. Ejecutará este código en un notebook de watsonx.ai.
El reconocimiento automático de voz (ASR), también conocido como reconocimiento de voz o voz a texto, es la tecnología que convierte el lenguaje hablado en texto escrito. Se utilizan diversos algoritmos de machine learning y técnicas de computación de inteligencia artificial para convertir la voz en texto. La tecnología de reconocimiento de voz ha evolucionado significativamente desde sus inicios a mediados del siglo XX hasta la actualidad.
En la década de 1960, los espectrogramas se utilizaron inicialmente para analizar la voz. En las décadas siguientes, se produjo un cambio hacia los modelos estadísticos. Aparecieron los modelos ocultos de Markov (HMM) y se convirtieron en dominantes para modelar secuencias de pequeñas unidades de sonido conocidas como fonemas en lingüística. La arquitectura de los sistemas ASR estaba compuesta por tres componentes separados: un modelo acústico, un modelo de lenguaje y un decodificador.
En la década de 2010, los avances en el aprendizaje profundo comenzaron a afectar la arquitectura tradicional de los sistemas de reconocimiento de voz. Los modelos codificado-decodificador pueden usar una red neuronal recurrente o una arquitectura de red neuronal convolucional donde un codificador procesa los datos de entrada y un decodificador genera resultados basados en la representación del codificador. Se entrenan con grandes conjuntos de datos sin etiquetar de pares de audio y texto para aprender a corresponder señales de audio con transcripciones. Los modelos populares de ASR incluyen DeepSpeech y Wav2Vec.
Hoy en día, los asistentes virtuales como Siri de Apple, Alexa de Amazon o Cortana de Microsoft utilizan la tecnología ASR para procesar la voz humana en tiempo real. También pueden integrar voz a texto con modelos de lenguaje grandes (LLM) y procesamiento de lenguaje natural (PLN). Los LLM se pueden utilizar para agregar contexto, lo que puede ayudar cuando las opciones de palabras son más ambiguas o si hay variabilidad en los patrones de voz humana.
Necesita una cuenta de IBM Cloud para crear un proyecto en watsonx.ai .
Si bien puede elegir entre varias herramientas, este tutorial lo guiará a través de cómo configurar una cuenta de IBM para usar un Jupyter Notebook.
Inicie sesión en watsonx.ai con su cuenta de IBM Cloud.
2. Cree un proyecto de watsonx.ai.
3. Cree un Jupyter Notebook.
Asegúrese de elegir
También puede descargar este Notebook en su sistema local y cargarlo en su proyecto watsonx.ai como activo. Este tutorial también está disponible en GitHub. Para ver más tutoriales de Granite, consulte la comunidad de IBM Granite.
Si recibe un error "pip dependency resolver" relacionado con el paquete caikit-nlp, puede ignorarlo por ahora, ya que el resto del notebook aún debería poder ejecutarse normalmente.
# Install required packages
! pip install -q peft torchaudio soundfile pytubefix pytube moviepy tqdm https://github.com/huggingface/transformers/archive/main.zip
# Required imports
import json
import os
from pytubefix import YouTube
from tqdm import tqdm
from moviepy.audio.io.AudioFileClip import AudioFileClip
import torch
import torchaudio
from transformers import AutoProcessor, AutoModelForSpeechSeq2Seq
from huggingface_hub import hf_hub_download
En este tutorial, utilizaremos el último episodio del podcast IBM "Mixture of Experts", "IA en IBM z17, Llama 4 de Meta y Google Cloud Next 2025". El podcast está alojado en YouTube. Primero crearemos un
url = "https://www.youtube.com/watch?v=90fUR1PQgt4" #latest episode 37 minutes
# Create a YouTube object
yt = YouTube(url)
# Download only the audio stream from the video
video = yt.streams.filter(only_audio=True).first()
# Save the audio to a file
out_file = video.download()
# Get the base name and extension of the downloaded audio
base = os.path.splitext(out_file)[0]
Tendremos que hacer un par de modificaciones en el archivo de audio del podcast antes de poder usarlo para la inferencia de modelos.
Primero, necesitamos convertir el archivo M4A en un archivo WAV para usarlo con el modelo Granite Speech. Usaremos la biblioteca moviepy para hacer esta conversión. Podemos usar la variable base que definimos anteriormente para crear el nuevo nombre de archivo con la extensión .wav
# Load the M4A file
audio_clip = AudioFileClip(out_file)
# Write the audio to a WAV file
audio_clip.write_audiofile(base+".wav")
# Close the audio clip
audio_clip.close()
audio_path = base+".wav"
A continuación, usaremos torchaudiodio.load() para cargar el archivo de audio como tensor y extraer la frecuencia de muestra.
También necesitaremos convertir la forma de onda devuelta del sonido estéreo al sonido mono. Podemos hacer esto tomando el promedio de los canales de sonido estéreo usando torch.mean().
#Resulting waveform and sample rate
waveform, sample_rate = torchaudio.load(audio_path, normalize=True)
# convert from stereo to mono
mono_waveform = torch.mean(waveform, dim=0, keepdim=True)
# confirm the waveform is mono
assert mono_waveform.shape[0] == 1 # mono
A continuación, necesitamos volver a muestrear la forma de onda mono a la frecuencia de muestra del modelo: 16 khz. Podemos usar la API de remuestreo de torchaudio para lograr esto.
# Resample the mono waveform to the model's sample rate
resample_transform = torchaudio.transforms.Resample(orig_freq=sample_rate, new_freq=16000)
resampled_waveform = resample_transform(mono_waveform)
Finalmente, podemos dividir la forma de onda remuestreada en fragmentos de igual tamaño para alimentar el modelo y facilitar la inferencia.
Usaremos torch.split() para dividir la forma de onda remuestreada completa en fragmentos de 30 segundos y una muestra de tamaño de fragmento igual a 30 segundos * 16 khz. Este paso nos dará una lista de formas de onda, chunks, cada uno con 30 segundos de datos de audio. Vamos a alimentar cada fragmento en el modelo para la inferencia.
# Define the desired chunk size
chunk_size_seconds = 30
chunk_size_samples = chunk_size_seconds * 16000
# Split the waveform into chunks of equal size
chunks = torch.split(resampled_waveform, chunk_size_samples, dim=1)
Ahora podemos comenzar a crear instancias de nuestro modelo de voz.
Primero configuraremos nuestro dispositivo torch en CPU. Si el dispositivo está configurado en GPU, es posible que encuentre errores de falta de memoria al ejecutar este portátil, pero la CPU debería funcionar bien en su notebook watsonx.ai. A continuación, podemos configurar nuestro procesador y tokenizador para el modelo.
device = 'cpu'
model_name = "ibm-granite/granite-speech-3.3-8b"
speech_granite_processor = AutoProcessor.from_pretrained(
model_name, trust_remote_code=True)
tokenizer = speech_granite_processor.tokenizer
Si está ejecutando su notebook en la plataforma watsonx.ai, es posible que también deba ejecutar el siguiente código para editar manualmente el archivo adapter_config.json. Esto evitará un error al cargar el modelo.
adapter_config_file = hf_hub_download(model_name, 'adapter_config.json')
#load the existing config file and print it
with open(adapter_config_file, 'r') as file:
data = json.load(file)
#remove key, value pairs in config file throwing error
keys_to_delete = ['layer_replication', 'loftq_config', 'megatron_config', 'megatron_core', 'use_dora', 'use_rslora']
for key in keys_to_delete:
if key in data:
del data[key]
# write the updated config file back to disk
with open(adapter_config_file, 'w') as file:
json.dump(data, file, indent=4)
with open(adapter_config_file, 'r') as file:
data = json.load(file)
Excelente, Ahora podemos cargar el modelo. Usaremos AutoModelForSpeechSeq2Seq de la biblioteca transformers y el método from_pretrained para cargar el modelo.
speech_granite = AutoModelForSpeechSeq2Seq.from_pretrained(model_name, trust_remote_code=True).to(device)
Ahora que tenemos el modelo cargado y los datos de audio preparados, podemos usarlo para generar texto a partir de la voz.
Comenzaremos creando una instrucción para que el modelo transcriba los datos de audio. Usaremos tokenizer.apply_chat_template() para convertir la instrucción a un formato que pueda introducirse en el modelo.
chat = [
{
"role": "system",
"content": "Knowledge Cutoff Date: April 2025.\nToday's Date: April 16, 2025.\nYou are Granite, developed by IBM. You are a helpful AI assistant",
},
{
"role": "user",
"content": "<|audio|>can you transcribe the speech into a written format?",
}
]
text = tokenizer.apply_chat_template(
chat, tokenize=False, add_generation_prompt=True
)
Luego, podemos configurar una lista vacía generated_texts para recopilar el texto generado de cada fragmento de entrada de audio.
Configuramos un bucle for para iterar a través de cada fragmento de audio y pasarlo al modelo para su generación. Aquí, también realizaremos un seguimiento del progreso del bucle mediante una barra de progreso tqdm.
Las entradas del modelo se crean a través del speech_granite_processor que establecimos anteriormente. El procesador toma el text y el chunk como entrada y devuelve una versión procesada de los datos de audio para que el modelo los utilice.
Los resultados del modelo se producen mediante el método generate del modelo de voz. A partir de ahí, usamos el tokenizer para convertir las salidas del modelo en texto legible por humanos y almacenar la transcripción de cada fragmento en nuestra lista generated_texts.
generated_texts = []
for chunk in tqdm(chunks, desc="Generating transcript..."):
model_inputs = speech_granite_processor(
text,
chunk,
device=device, # Computation device; returned tensors are put on CPU
return_tensors="pt",
).to(device)
# Generate
model_outputs = speech_granite.generate(
**model_inputs,
max_new_tokens=1000,
num_beams=1,
do_sample=False,
min_length=1,
top_p=1.0,
repetition_penalty=1.0,
length_penalty=1.0,
temperature=1.0,
bos_token_id=tokenizer.bos_token_id,
eos_token_id=tokenizer.eos_token_id,
pad_token_id=tokenizer.pad_token_id,)
num_input_tokens = model_inputs["input_ids"].shape[-1]
new_tokens = torch.unsqueeze(model_outputs[0, num_input_tokens:], dim=0)
output_text = tokenizer.batch_decode(
new_tokens, add_special_tokens=False, skip_special_tokens=True)[0]
generated_texts.append(output_text)
Dado que las transcripciones en fragmentos son actualmente cadenas individuales en una lista, uniremos las cadenas con un espacio intermedio para hacer una transcripción completa cohesiva.
full_transcript = " ".join(generated_texts)
Ahora que tenemos una transcripción completa, usaremos el mismo modelo para resumirla. Podemos acceder a Granite-3.3-8B-Instruct directamente desde Granite-speech-3.3-8b llamándolo con una instrucción de texto que no contenga el token <|audio|>.
Configuraremos una nueva instrucción para indicar a este modelo que genere un resumen de la transcripción completa. Podemos usar tokenizer.apply_chat_template() de nuevo para convertir la instrucción para la inferencia del modelo.
conv = [{"role": "user",
"content": f"Compose a single, unified summary of the following transcript. Your response should only include the unified summary. Do not provide any further explanation. Transcript:{full_transcript}"}]
text = tokenizer.apply_chat_template(conv, tokenize=False, add_generation_prompt=True)
Usaremos speech_granite_processor nuevamente para crear entradas de modelo, pero esta vez no pasaremos ningún archivo de audio.
model_inputs = speech_granite_processor(
text,
device=device, # Computation device; returned tensors are put on CPU
return_tensors="pt",
).to(device)
Recibiremos la salida de speech_granite.generate() como un tensor. Podemos convertir esta salida en texto usando tokenizer.decode(). ¡E imprima nuestro resumen final!
output = speech_granite.generate(
**model_inputs,
max_new_tokens= 2000, # concise summary
)
summary = tokenizer.decode(output[0, model_inputs["input_ids"].shape[1]:], skip_special_tokens=True)
print(summary)
Resultado:
In the 50th episode of Mixture of Experts, the panel discusses various AI-related topics.
Kate Soule, Director of Technical Product Management at Granite, estimates that 90% of enterprise data is unstructured.
Hilary Hunter, IBM Fellow and CTO of IBM Infrastructure, introduces IBM's new mainframe launch, IBM z, emphasizing its zero downtime and eight nines of reliability, crucial for global financial transactions.
The conversation also touches on Meta's Llama 4 release, featuring three models: Scout (100 billion parameters), Maverick (200 billion parameters), and Behemoth (two trillion parameters). The panelists discuss the implications of these models, particularly the mixture of experts architecture, and its potential to become more community-driven.
Shobhit Varshney Head of Data and AI for the Americas, shares insights on handling unstructured data in enterprises, advocating for bringing AI close to transaction data for low-latency, mission-critical applications.
The episode concludes with a brief overview of Google Cloud Next, highlighting advancements in AI models, on-premises AI capabilities, and Google's focus on AI for media creation and agent-to-agent communication.
The panel also references a Pew Research report on American perceptions of AI, noting discrepancies between experts' optimism and the general public's concerns about job impacts from AI.
En este tutorial, descargó un archivo de audio en inglés de YouTube. Transformó el archivo de audio para que lo consumiera el modelo de voz de Granite, generó una transcripción completa del audio y utilizó un modelo de instrucciones de Granite para generar un resumen de la transcripción.
Diseñe asistentes y agentes de IA escalables con facilidad, automatice tareas repetitivas y simplifique procesos complejos con IBM watsonx Orchestrate.
Acelere el valor de negocio de la inteligencia artificial con una cartera potente y flexible de bibliotecas, servicios y aplicaciones.
Reinvente los flujos de trabajo y las operaciones críticas añadiendo IA para maximizar las experiencias, la toma de decisiones en tiempo real y el valor empresarial.