Usar o reconhecimento automático de fala (ASR) para gerar a transcrição de um podcast com o Granite 3.3 e o watsonx.ai

Neste tutorial, você usará o modelo de fala IBM® Granite 3.3 de código aberto para gerar uma transcrição do podcast "Mixture of Experts" da IBM a partir do YouTube. Em seguida, usando o grande modelo de linguagem (LLM) de código aberto IBM Granite-3.3-8B-Instruct, você produzirá um resumo da transcrição gerada. Você executará esse código em um notebook watsonx.ai.

Reconhecimento automático de fala

O reconhecimento automático de fala (ASR), também conhecido como reconhecimento de fala ou speech to text, é a tecnologia que converte a linguagem falada em texto escrito. Vários algoritmos de aprendizado de máquina e técnicas de computação de inteligência artificial são usados para converter a fala em texto. A tecnologia de reconhecimento de fala evoluiu significativamente desde seu início em meados do século XX até hoje.

Na década de 1960, os espectrogramas foram usados inicialmente para analisar a fala. Nas décadas seguintes, ocorreu uma mudança para modelos estatísticos. Modelos de Markov ocultos (HMMs) surgiram e se tornaram dominantes para modelar sequências de pequenas unidades sonoras conhecidas como fonemas em linguística. A arquitetura dos sistemas ASR foi composta por três componentes separados: um modelo acústico, um modelo de linguagem e um decodificador.

Na década de 2010, os avanços no deep learning começaram a impactar a arquitetura tradicional dos sistemas de reconhecimento de fala. Os modelos de codificador-decodificador podem utilizar uma arquitetura de rede neural recorrente (RNN) ou de rede neural convolucional (CNN) em que um codificador processa dados de entrada e um decodificador gera saída com base na representação do codificador. Esses modelos são treinados com grandes conjuntos de dados não rotulados de pares de áudio e texto para aprender a associar sinais de áudio a transcrições. Modelos ASR populares incluem DeepSpeich e Wav2Vec.

Hoje, assistentes virtuais como a Siri da Apple, a Alexa da Amazon ou a Cortana da Microsoft usam a tecnologia ASR para processar a fala humana em tempo real. Elas também são capazes de integrar a Speech to Text com grandes modelos de linguagem (LLMs) e processamento de linguagem natural (NLP). Os LLMs podem ser usados para adicionar contexto, o que pode ajudar quando as escolhas de palavras são mais ambíguas ou se houver variabilidade nos padrões da fala humana.

Pré-requisitos

Você precisa de uma conta do IBM Cloud para criar um projeto do watsonx.ai .

Etapas

Etapa 1. Configure seu ambiente

Embora você possa escolher entre várias ferramentas, este tutorial explica como configurar uma conta da IBM para usar um Jupyter Notebook. 

Faça login no watsonx.ai usando sua conta do IBM Cloud.

2. Crie um projeto do watsonx.ai.

3. Crie um Jupyter Notebook.

É importante que você opteGPU 2xV100 Runtime 24.1 por definir a configuração. Essa etapa abrirá um ambiente do Jupyter Notebook onde você poderá copiar o código deste tutorial.

Ou então, você pode baixar esse Notebook em seu sistema local e carregá-lo como um ativo em seu projeto do watsonx.ai. Este tutorial também está disponível no GitHub. Para ver mais tutoriais do Granite, consulte a Comunidade IBM Granite. 

Etapa 2. Instale e importe bibliotecas relevantes

Temos algumas dependências para este tutorial. Certifique-se de importar os seguintes e, se eles não estiverem instalados, você pode resolver isso com uma instalação rápida cpm pip.

Se você receber um erro "pip dependency resolver" relacionado ao pacote "caikit-nlp", você pode ignorá-lo por enquanto, pois o restante do bloco de notas ainda deve poder ser executado 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

Etapa 3. Baixe o áudio do podcast do YouTube

Neste tutorial, usaremos o último episódio do podcast "Mixture of Experts" da IBM, "IA on IBM z17, Meta's Llama 4 e nuvem do Google Next 2025". O podcast está hospedado no YouTube. Primeiro, criaremos umYouTube  YouTube e usaremos ostreams.filter(only_audio=True) método para capturar somente o áudio bruto. A partir daí, extraímos o áudio do vídeo e o salvamos como um arquivo de áudio M4A,out_file .base é o nome completo do arquivo, incluindo o diretório no qual o arquivo será salvo sem am4a  extensão. Usaremos abase  variável mais tarde, quando convertermos o formato de áudio.

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]

Etapa 4: Prepare o arquivo de áudio do podcast para inferência de modelo Precisaremos fazer algumas modificações no arquivo de áudio do podcast antes de podermos usá-lo para inferência de modelo.

Primeiro, precisamos converter o arquivo M4A em um arquivo WAV para usá-lo com o modelo Granite Speech. Usaremos a biblioteca de filmes para fazer essa conversão. Podemos usar a variável base que definimos anteriormente para criar o novo nome de arquivo com a extensão .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"

Em seguida, usaremos "torchaudio.load()" para carregar o arquivo de áudio como um tensor e extrair a taxa de amostragem.

Também precisaremos converter a forma de onda devolvida de som estereofônico para som mono. Podemos fazer isso calculando a média dos canais de som estufa 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

Em seguida, precisamos reajustar a forma de onda mono para a taxa de amostragem do modelo: 16 kHz. Podemos usar a API de resampling do torchaudio para fazer isso.

# 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 a forma de onda reamostrada em fragmentos de tamanho igual para alimentar o modelo para facilitar a inferência.

Usaremos "torch.split()" para dividir a forma de onda reamostrada completa em fragmentos de 30 segundos e uma amostra de tamanho de fragmento igual a 30 segundos * 16 kHz. Essa etapa nos dará uma lista de formas de onda, "fragmentos", cada um com 30 segundos de dados de áudio. Alimentaremos cada fragmento no modelo para inferência.

# 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)

Etapa 5: Carregue e instancie o modelo de fala Granite

Agora podemos começar a instanciar nosso modelo de fala.

Primeiro, vamos definir nosso dispositivo de tocha para a CPU. Se o dispositivo estiver configurado para GPU, você poderá encontrar erros de memória ao executar este notebook, mas a CPU deve funcionar muito bem em seu notebook watsonx.ai. Em seguida, podemos configurar nosso processador e tokenizador para o 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

Se Se estiver executando seu notebook na plataforma watsonx.ai, talvez seja necessário executar o seguinte código para editar manualmente o arquivo "adapter_config.json" file. Isso evitará erros ao carregar o 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, agora podemos finalmente carregar o modelo! Usaremos "AutoModelForSpeectSeq2Seq" da biblioteca "transformers" e o método "from_pretrained" para carregar o modelo.

speech_granite = AutoModelForSpeechSeq2Seq.from_pretrained(model_name, trust_remote_code=True).to(device)

Etapa 6: Crie um sistema ASR com o modelo de fala Granite

Agora que temos o modelo carregado e os dados de áudio preparados, podemos usá-lo para gerar texto a partir da fala.

Começaremos criando um prompt para o modelo transcrever os dados de áudio. Usaremos "tokenizer.apply_chat_temlate()" para converter o prompt em um formato que possa ser alimentado no 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
)

Em seguida, podemos configurar uma lista vazia de "generated_texts", para reunir o texto gerado de cada fragmento da entrada de áudio.

Estabelecemos um loop "for" para iterar cada fragmento de áudio e passá-lo para o modelo para geração. Aqui, também rastrearemos o progresso do loop usando uma barra de progresso "tqdm".

As entradas do modelo são criadas por meio do "speech_granite_processor" que estabelecemos anteriormente. O processador utiliza o "texto" e o "fragmento" como entrada e retorna uma versão processada dos dados de áudio para o modelo usar.

As saídas do modelo são produzidas usando o método "generate" do modelo de fala. A partir daí, usamos o "tokenizer" para converter as saídas do modelo em texto legível por humanos e armazenar a transcrição de cada fragmento em nossa 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)

Como as transcrições de fragmentos são cadeias de caracteres individuais em uma lista, nos juntaremos as sequências com um espaço entre elas para fazer uma transcrição completa coesa.

full_transcript = " ".join(generated_texts)

Etapa 7: Use o modelo de instruções Granite para sumarização

Agora que temos uma transcrição completa, usaremos o mesmo modelo para resumi-la. Podemos acessar o modelo Granite-3.3-8B-Instruct diretamente do Granite-speech-3.3-8b simplesmente chamando-o com um prompt de texto que não contenha o token "<|audio|>".

Configuraremos um novo prompt para instruir esse modelo a gerar um resumo da transcrição completa. Podemos usar "tokenizer.apply_chat_template()" novamente para converter o prompt para inferência de 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)

Vamos usar "speech_granite_processor" novamente para criar as entradas do modelo, mas não vamos transmitir nenhum arquivo de áudio desta vez.

model_inputs = speech_granite_processor(
    text,
    device=device, # Computation device; returned tensors are put on CPU
    return_tensors="pt",
).to(device)

Nós receberemos a saída de "speech_granite.generate()" como um tensor. Podemos converter essa saída em texto usando "tokenizer.decode()". E imprima nosso resumo 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)

**Saída: **

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.

Conclusão

Neste tutorial, você baixou um arquivo de áudio em inglês do YouTube. Você transformou o arquivo de áudio para consumo pelo modelo de fala Granite, gerou uma transcrição completa do áudio e usou um modelo de instrução Granite para gerar um resumo da transcrição.

Soluções relacionadas
IBM watsonx Orchestrate

Projete assistentes e agentes de IA escaláveis com facilidade, automatize tarefas repetitivas e simplifique processos complexos com o IBM® watsonx Orchestrate.

Conheça o watsonx Orchestrate
Ferramentas e APIs de processamento de linguagem natural

Acelere o valor comercial da inteligência artificial com um portfólio poderoso e flexível de bibliotecas, serviços e aplicativos.

Explore as soluções de PNL
Consultoria e serviços em IA

Reinvente os fluxos de trabalho e operações críticos adicionando IA para maximizar experiências, tomadas de decisão em tempo real e valor de negócios.

Explore os serviços de IA
Dê o próximo passo

Projete assistentes e agentes de IA escaláveis com facilidade, automatize tarefas repetitivas e simplifique processos complexos com o IBM® watsonx Orchestrate.

Conheça o watsonx Orchestrate Explore as soluções de PLN