Lenguaje

Reconocimiento de voz con su propio modelo de Whisper mediante Windows ML

Importante

Las API de tiempo de ejecución y reconocimiento de voz de ML de Windows son actualmente experimentales y no se admiten para su uso en entornos de producción. Las aplicaciones que prueban estas API no deben publicarse en Microsoft Store.

Importante

Las API de Windows ML Runtime y de reconocimiento de voz están disponibles actualmente en C++ y Python; C# no es compatible por el momento. Si te interesa utilizar estas API desde C#, ¡háznoslo saber publicando una incidencia en el repositorio de GitHub de Windows ML!

La API de reconocimiento de voz de Windows ML simplifica la ejecución del reconocimiento automático de voz (ASR) con tu propio modelo de Whisper. Esta API compone un canal de codificación de Whisper, un canal de decodificación y un tokenizador, y luego se encarga por ti del bucle de transcripción autorregresivo, la salida en streaming y la cancelación, todo ello sobre la base de la API de Windows ML Runtime. Windows no incluye un modelo para esta API; tú eliges, empaquetas y distribuyes el modelo de Whisper —los archivos de codificación y decodificación, además de un tokenizador— junto con tu aplicación.

Tip

Si no necesita un modelo de Whisper específico o una implementación personalizada y solo desea voz a texto en el dispositivo con un modelo administrado por Microsoft, use la Speech Recognition API lista para usar en su lugar.

Todavía se crean los objetos Runtime subyacentes (los modelos de codificador y descodificador, el destino de ejecución y las canalizaciones) y se pasan a la sesión. La API no oculta la ubicación del hardware; solo quita la necesidad de escribir su propio bucle de descodificación.

Modelos compatibles

La API de reconocimiento de voz se ha creado específicamente para la arquitectura de codificador y descodificador Whisper; no es una API de ASR genérica. Debes proporcionar:

  • Modelos de codificador y decodificador ONNX (encoder_model.onnx y decoder_model.onnx), que se ejecutan a través de ONNX Runtime

Un archivo de tokenizador acompaña al par codificador/descodificador. El tensor de entrada contiene ejemplos de PCM de punto flotante mono, además de metadatos de frecuencia de muestreo y longitud válida.

Transcribir audio

Proporcione un tensor Runtime que contenga muestras de forma de onda. Carga los modelos de codificador y decodificador de Whisper, crea una canalización para cada uno y combínalos con un tokenizador en una sesión:

// Create the runtime and an execution target (CPU here; GPU/NPU also available).
ComPtr<IWinMLRuntime> runtime;
THROW_IF_FAILED(WinMLCreateRuntime(IID_PPV_ARGS(runtime.GetAddressOf())));
ComPtr<IWinMLExecutionTarget> target;
THROW_IF_FAILED(runtime->CreateCpuExecutionTarget(target.GetAddressOf()));

// Load the Whisper encoder as its own single-stage pipeline.
ComPtr<IWinMLModel> encoderModel;
THROW_IF_FAILED(runtime->LoadModelFromFile(
    L"C:\\models\\whisper\\encoder_model.onnx", nullptr, encoderModel.GetAddressOf()));
ComPtr<IWinMLPipelineBuilder> encoderBuilder;
THROW_IF_FAILED(runtime->CreatePipelineBuilder(encoderBuilder.GetAddressOf()));
ComPtr<IWinMLStage> encoderStage;
THROW_IF_FAILED(encoderBuilder->AddModelStage(
    encoderModel.Get(), target.Get(), L"whisper-encoder", encoderStage.GetAddressOf()));
ComPtr<IWinMLPipeline> encoderPipeline;
THROW_IF_FAILED(encoderBuilder->Build(encoderPipeline.GetAddressOf()));

// Load the Whisper decoder the same way.
ComPtr<IWinMLModel> decoderModel;
THROW_IF_FAILED(runtime->LoadModelFromFile(
    L"C:\\models\\whisper\\decoder_model.onnx", nullptr, decoderModel.GetAddressOf()));
ComPtr<IWinMLPipelineBuilder> decoderBuilder;
THROW_IF_FAILED(runtime->CreatePipelineBuilder(decoderBuilder.GetAddressOf()));
ComPtr<IWinMLStage> decoderStage;
THROW_IF_FAILED(decoderBuilder->AddModelStage(
    decoderModel.Get(), target.Get(), L"whisper-decoder", decoderStage.GetAddressOf()));
ComPtr<IWinMLPipeline> decoderPipeline;
THROW_IF_FAILED(decoderBuilder->Build(decoderPipeline.GetAddressOf()));

ComPtr<IWinMLTokenizer> tokenizer;
THROW_IF_FAILED(WinMLCreateTokenizerFromFile(
    L"C:\\models\\whisper\\tokenizer.json", tokenizer.GetAddressOf()));

// Compose the encoder/decoder pipelines and tokenizer into a session.
const winml::tasks::speech::asr::AutomaticSpeechRecognitionArguments arguments{
    runtime.Get(),
    tokenizer.Get(),
    {
        encoderPipeline.Get(),
        encoderStage.Get(),
        decoderPipeline.Get(),
        decoderStage.Get(),
        target.Get(),
    },
};
winml::tasks::speech::asr::AutomaticSpeechRecognition speechRecognition;
THROW_IF_FAILED(winml::tasks::speech::asr::BuildAutomaticSpeechRecognition(
    arguments, speechRecognition));

Llame a TranscribeWaveform para iniciar una operación de streaming y, a continuación, extraiga fragmentos de la secuencia devuelta hasta que notifique la finalización:

ComPtr<IWinMLCancellationSource> cancellation;
THROW_IF_FAILED(speechRecognition.tasks->CreateCancellationSource(
    cancellation.GetAddressOf()));

ComPtr<IWinMLAutomaticSpeechRecognitionPullStream> stream;
THROW_IF_FAILED(speechRecognition.session->TranscribeWaveform(
    waveform.Get(),
    &waveformMetadata,
    cancellation.Get(),
    stream.GetAddressOf()));

// Pull transcript text one fragment at a time until the stream completes.
WINML_AUTOMATIC_SPEECH_RECOGNITION_READ_STATUS status{};
LPCWSTR fragment = nullptr;
while (SUCCEEDED(stream->ReadNext(&status, &fragment)) &&
    status == WINML_AUTOMATIC_SPEECH_RECOGNITION_READ_STATUS_UPDATE)
{
    std::wprintf(L"%ls", fragment);
}

// The terminal result is the authoritative transcript and finish reason.
ComPtr<IWinMLAutomaticSpeechRecognitionResult> result;
THROW_IF_FAILED(stream->GetResult(result.GetAddressOf()));

waveform y waveformMetadata proceden de su propio código de carga de audio: un tensor en tiempo de ejecución que contiene muestras de PCM de punto flotante mono, además de la frecuencia de muestreo y los metadatos de longitud válida que lo describen.

El resultado completado notifica la transcripción completa y un motivo de finalización, como un token de finalización de la transcripción, una cancelación o un error.

C++ y Python

La API nativa se expone a través de WinMLTasks.h y los asistentes de C++ tipados en winml/tasks/speech/asr/WhisperAutomaticSpeechRecognition.hpp. Las aplicaciones de Python usan la windowsml.tasks proyección junto con windowsml.runtime.

Los Windows ML samples incluyen un ejemplo de transcripción con Whisper en C++ y Python. En el ejemplo se muestra la configuración completa de Runtime junto a la configuración de reconocimiento de voz para que pueda ver dónde comienza la abstracción y cómo personalizar el flujo de trabajo subyacente.

Consulte también