Tutoriel : Créer une application de conversion vocale en texte pour la prise de notes

Créez une application qui convertit l’audio parlé en notes organisées , entièrement sur votre appareil. L’application transcrit d’abord un fichier audio à l’aide d’un modèle de reconnaissance vocale, puis utilise un modèle de conversation pour résumer et organiser la transcription en notes propres.

Dans ce tutoriel, vous allez apprendre à :

  • Configurer un projet et installer le Kit de développement logiciel (SDK) Local Foundry
  • Charger un modèle de reconnaissance vocale et transcrire un fichier audio
  • Charger un modèle de conversation et résumer la transcription
  • Combiner la transcription et la synthèse dans une application complète
  • Nettoyer les ressources

Prerequisites

  • Un ordinateur Windows, macOS ou Linux avec au moins 8 Go de RAM.
  • Fichier .wav audio à transcrire (le didacticiel utilise un exemple de fichier).

Installer des packages

Référentiel d’exemples

L’exemple de code complet de cet article est disponible dans le dépôt Foundry Local GitHub. Pour cloner le référentiel et accéder à l’exemple d’utilisation :

git clone https://github.com/microsoft/Foundry-Local.git
cd Foundry-Local/samples/cs/tutorial-voice-to-text

Si vous développez ou expédiez sur Windows, sélectionnez l'onglet Windows. Le package Windows s’intègre au runtime Windows ML . Il fournit la même surface d’surface d’API avec une étendue plus large d’accélération matérielle.

dotnet add package Microsoft.AI.Foundry.Local.WinML
dotnet add package OpenAI

Les exemples C# dans le référentiel GitHub sont des projets préconfigurés. Si vous développez ex nihilo, vous devez lire la référence de Foundry Local SDK pour plus d’informations sur la configuration de votre projet C# avec Foundry Local.

Transcrire un fichier audio

Dans cette étape, vous chargez un modèle de reconnaissance vocale et transcrivez un fichier audio. Le SDK Local Foundry utilise l'alias de modèle whisper pour sélectionner la meilleure variante Whisper pour votre matériel.

  • Ouvrez Program.cs et remplacez son contenu par le code suivant pour initialiser le Kit de développement logiciel (SDK), charger le modèle speech et transcrire un fichier audio :

    // Load the speech-to-text model
    var speechModel = await catalog.GetModelAsync("whisper-tiny")
        ?? throw new Exception("Speech model not found");
    
    await speechModel.DownloadAsync(progress =>
    {
        Console.Write($"\rDownloading speech model: {progress:F2}%");
        if (progress >= 100f) Console.WriteLine();
    });
    
    await speechModel.LoadAsync();
    Console.WriteLine("Speech model loaded.");
    
    // Transcribe the audio file
    var audioClient = await speechModel.GetAudioClientAsync();
    var transcriptionText = new StringBuilder();
    
    Console.WriteLine("\nTranscription:");
    var audioResponse = audioClient
        .TranscribeAudioStreamingAsync("meeting-notes.wav", ct);
    await foreach (var chunk in audioResponse)
    {
        Console.Write(chunk.Text);
        transcriptionText.Append(chunk.Text);
    }
    Console.WriteLine();
    
    // Unload the speech model to free memory
    await speechModel.UnloadAsync();
    

    La GetAudioClientAsync méthode retourne un client pour les opérations audio. La TranscribeAudioStreamingAsync méthode diffuse les blocs de transcription dès qu’ils deviennent disponibles. Vous accumulez le texte pour pouvoir le transmettre au modèle de conversation à l’étape suivante.

Note

Remplacez "meeting-notes.wav" par le chemin d’accès à votre fichier audio. Les formats pris en charge incluent WAV, MP3 et FLAC.

Résumer la transcription

Utilisez maintenant un modèle de conversation pour organiser la transcription brute en notes structurées. Chargez le modèle qwen2.5-0.5b et envoyez la transcription comme contexte avec une invite système qui demande au modèle de produire des notes résumées et bien ordonnées.

Ajoutez le code suivant après l’étape de transcription :

// Load the chat model for summarization
var chatModel = await catalog.GetModelAsync("qwen2.5-0.5b")
    ?? throw new Exception("Chat model not found");

await chatModel.DownloadAsync(progress =>
{
    Console.Write($"\rDownloading chat model: {progress:F2}%");
    if (progress >= 100f) Console.WriteLine();
});

await chatModel.LoadAsync();
Console.WriteLine("Chat model loaded.");

// Summarize the transcription into organized notes
var chatClient = await chatModel.GetChatClientAsync();
var messages = new List<ChatMessage>
{
    new ChatMessage
    {
        Role = "system",
        Content = "You are a note-taking assistant. Summarize " +
                  "the following transcription into organized, " +
                  "concise notes with bullet points."
    },
    new ChatMessage
    {
        Role = "user",
        Content = transcriptionText.ToString()
    }
};

var chatResponse = await chatClient.CompleteChatAsync(messages, ct);
var summary = chatResponse.Choices[0].Message.Content;
Console.WriteLine($"\nSummary:\n{summary}");

// Clean up
await chatModel.UnloadAsync();
Console.WriteLine("\nDone. Models unloaded.");

L'invite système détermine le format de sortie du modèle. En lui demandant de produire des notes « organisées et concises avec des points à puces », vous obtenez du contenu structuré plutôt qu’une paraphrase brute.

Combiner dans une application complète

Remplacez le contenu du Program.cs code complet suivant qui transcrit un fichier audio et résume la transcription :

using Microsoft.AI.Foundry.Local;
using Betalgo.Ranul.OpenAI.ObjectModels.RequestModels;
using Microsoft.Extensions.Logging;
using System.Text;

CancellationToken ct = CancellationToken.None;

var config = new Configuration
{
    AppName = "foundry_local_samples",
    LogLevel = Microsoft.AI.Foundry.Local.LogLevel.Information
};

using var loggerFactory = LoggerFactory.Create(builder =>
{
    builder.SetMinimumLevel(
        Microsoft.Extensions.Logging.LogLevel.Information
    );
});
var logger = loggerFactory.CreateLogger<Program>();

// Initialize the singleton instance
await FoundryLocalManager.CreateAsync(config, logger);
var mgr = FoundryLocalManager.Instance;

// Download and register all execution providers.
var currentEp = "";
await mgr.DownloadAndRegisterEpsAsync((epName, percent) =>
{
    if (epName != currentEp)
    {
        if (currentEp != "") Console.WriteLine();
        currentEp = epName;
    }
    Console.Write($"\r  {epName.PadRight(30)}  {percent,6:F1}%");
});
if (currentEp != "") Console.WriteLine();

var catalog = await mgr.GetCatalogAsync();

// Load the speech-to-text model
var speechModel = await catalog.GetModelAsync("whisper-tiny")
    ?? throw new Exception("Speech model not found");

await speechModel.DownloadAsync(progress =>
{
    Console.Write($"\rDownloading speech model: {progress:F2}%");
    if (progress >= 100f) Console.WriteLine();
});

await speechModel.LoadAsync();
Console.WriteLine("Speech model loaded.");

// Transcribe the audio file
var audioClient = await speechModel.GetAudioClientAsync();
var transcriptionText = new StringBuilder();

Console.WriteLine("\nTranscription:");
var audioResponse = audioClient
    .TranscribeAudioStreamingAsync("meeting-notes.wav", ct);
await foreach (var chunk in audioResponse)
{
    Console.Write(chunk.Text);
    transcriptionText.Append(chunk.Text);
}
Console.WriteLine();

// Unload the speech model to free memory
await speechModel.UnloadAsync();

// Load the chat model for summarization
var chatModel = await catalog.GetModelAsync("qwen2.5-0.5b")
    ?? throw new Exception("Chat model not found");

await chatModel.DownloadAsync(progress =>
{
    Console.Write($"\rDownloading chat model: {progress:F2}%");
    if (progress >= 100f) Console.WriteLine();
});

await chatModel.LoadAsync();
Console.WriteLine("Chat model loaded.");

// Summarize the transcription into organized notes
var chatClient = await chatModel.GetChatClientAsync();
var messages = new List<ChatMessage>
{
    new ChatMessage
    {
        Role = "system",
        Content = "You are a note-taking assistant. Summarize " +
                  "the following transcription into organized, " +
                  "concise notes with bullet points."
    },
    new ChatMessage
    {
        Role = "user",
        Content = transcriptionText.ToString()
    }
};

var chatResponse = await chatClient.CompleteChatAsync(messages, ct);
var summary = chatResponse.Choices[0].Message.Content;
Console.WriteLine($"\nSummary:\n{summary}");

// Clean up
await chatModel.UnloadAsync();
Console.WriteLine("\nDone. Models unloaded.");

Note

Remplacez "meeting-notes.wav" par le chemin d’accès à votre fichier audio. Les formats pris en charge incluent WAV, MP3 et FLAC.

Exécutez le taker de notes :

dotnet run

Vous voyez un résultat similaire à :

Downloading speech model: 100.00%
Speech model loaded.

Transcription:
OK so let's get started with the weekly sync. First, the backend
API is nearly done. Sarah finished the authentication endpoints
yesterday. We still need to add rate limiting before we go to
staging. On the frontend, the dashboard redesign is about seventy
percent complete. Jake, can you walk us through the new layout?
Great. The charts look good. I think we should add a filter for
date range though. For testing, we have about eighty percent code
coverage on the API. We need to write integration tests for the
new auth flow before Friday. Let's plan to do a full regression
test next Tuesday before the release. Any blockers? OK, sounds
like we are in good shape. Let's wrap up.

Downloading chat model: 100.00%
Chat model loaded.

Summary:
- **Backend API**: Authentication endpoints complete. Rate limiting
  still needed before staging deployment.
- **Frontend**: Dashboard redesign 70% complete. New chart layout
  reviewed. Action item: add a date range filter.
- **Testing**: API code coverage at 80%. Integration tests for the
  auth flow due Friday. Full regression test scheduled for next
  Tuesday before release.
- **Status**: No blockers reported. Team is on track.

Done. Models unloaded.

L’application transcrit d’abord le contenu audio avec une sortie de diffusion en continu, puis transmet le texte cumulé à un modèle de conversation qui extrait les points clés et les organise en notes structurées.

Installer des packages

Référentiel d’exemples

L’exemple de code complet de cet article est disponible dans le dépôt Foundry Local GitHub. Pour cloner le référentiel et accéder à l’exemple d’utilisation :

git clone https://github.com/microsoft/Foundry-Local.git
cd Foundry-Local/samples/js/tutorial-voice-to-text

Si vous développez ou expédiez sur Windows, sélectionnez l'onglet Windows. Le package Windows s’intègre au runtime Windows ML . Il fournit la même surface d’surface d’API avec une étendue plus large d’accélération matérielle.

npm install foundry-local-sdk-winml openai

Transcrire un fichier audio

Dans cette étape, vous chargez un modèle de reconnaissance vocale et transcrivez un fichier audio. Le SDK Local Foundry utilise l'alias de modèle whisper pour sélectionner la meilleure variante Whisper pour votre matériel.

  1. Créez un fichier appelé app.js.

  2. Ajoutez le code suivant pour initialiser le Kit de développement logiciel (SDK), charger le modèle speech et transcrire un fichier audio :

    // Load the speech-to-text model
    const speechModel = await manager.catalog.getModel('whisper-tiny');
    await speechModel.download((progress) => {
        process.stdout.write(
            `\rDownloading speech model: ${progress.toFixed(2)}%`
        );
    });
    console.log('\nSpeech model downloaded.');
    
    await speechModel.load();
    console.log('Speech model loaded.');
    
    // Transcribe the audio file
    const audioClient = speechModel.createAudioClient();
    const transcription = await audioClient.transcribe(
        path.join(__dirname, 'meeting-notes.wav')
    );
    console.log(`\nTranscription:\n${transcription.text}`);
    
    // Unload the speech model to free memory
    await speechModel.unload();
    

    La createAudioClient méthode retourne un client pour les opérations audio. La transcribe méthode accepte un chemin d’accès de fichier et retourne un objet avec une text propriété contenant le contenu transcrit.

Note

Remplacez './meeting-notes.wav' par le chemin d’accès à votre fichier audio. Les formats pris en charge incluent WAV, MP3 et FLAC.

Résumer la transcription

Utilisez maintenant un modèle de conversation pour organiser la transcription brute en notes structurées. Chargez le modèle qwen2.5-0.5b et envoyez la transcription comme contexte avec une invite système qui demande au modèle de produire des notes résumées et bien ordonnées.

Ajoutez le code suivant après l’étape de transcription :

// Load the chat model for summarization
const chatModel = await manager.catalog.getModel('qwen2.5-0.5b');
await chatModel.download((progress) => {
    process.stdout.write(
        `\rDownloading chat model: ${progress.toFixed(2)}%`
    );
});
console.log('\nChat model downloaded.');

await chatModel.load();
console.log('Chat model loaded.');

// Summarize the transcription into organized notes
const chatClient = chatModel.createChatClient();
const messages = [
    {
        role: 'system',
        content: 'You are a note-taking assistant. Summarize ' +
                 'the following transcription into organized, ' +
                 'concise notes with bullet points.'
    },
    {
        role: 'user',
        content: transcription.text
    }
];

const response = await chatClient.completeChat(messages);
const summary = response.choices[0]?.message?.content;
console.log(`\nSummary:\n${summary}`);

// Clean up
await chatModel.unload();
console.log('\nDone. Models unloaded.');

L'invite système détermine le format de sortie du modèle. En lui demandant de produire des notes « organisées et concises avec des points à puces », vous obtenez du contenu structuré plutôt qu’une paraphrase brute.

Combiner dans une application complète

Créez un fichier nommé app.js et ajoutez le code complet suivant qui transcrit un fichier audio et récapitule la transcription :

import { FoundryLocalManager } from 'foundry-local-sdk';
import { fileURLToPath } from 'url';
import path from 'path';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

// Initialize the Foundry Local SDK
const manager = FoundryLocalManager.create({
    appName: 'foundry_local_samples',
    logLevel: 'info'
});

// Download and register all execution providers.
let currentEp = '';
await manager.downloadAndRegisterEps((epName, percent) => {
    if (epName !== currentEp) {
        if (currentEp !== '') process.stdout.write('\n');
        currentEp = epName;
    }
    process.stdout.write(`\r  ${epName.padEnd(30)}  ${percent.toFixed(1).padStart(5)}%`);
});
if (currentEp !== '') process.stdout.write('\n');

// Load the speech-to-text model
const speechModel = await manager.catalog.getModel('whisper-tiny');
await speechModel.download((progress) => {
    process.stdout.write(
        `\rDownloading speech model: ${progress.toFixed(2)}%`
    );
});
console.log('\nSpeech model downloaded.');

await speechModel.load();
console.log('Speech model loaded.');

// Transcribe the audio file
const audioClient = speechModel.createAudioClient();
const transcription = await audioClient.transcribe(
    path.join(__dirname, 'meeting-notes.wav')
);
console.log(`\nTranscription:\n${transcription.text}`);

// Unload the speech model to free memory
await speechModel.unload();

// Load the chat model for summarization
const chatModel = await manager.catalog.getModel('qwen2.5-0.5b');
await chatModel.download((progress) => {
    process.stdout.write(
        `\rDownloading chat model: ${progress.toFixed(2)}%`
    );
});
console.log('\nChat model downloaded.');

await chatModel.load();
console.log('Chat model loaded.');

// Summarize the transcription into organized notes
const chatClient = chatModel.createChatClient();
const messages = [
    {
        role: 'system',
        content: 'You are a note-taking assistant. Summarize ' +
                 'the following transcription into organized, ' +
                 'concise notes with bullet points.'
    },
    {
        role: 'user',
        content: transcription.text
    }
];

const response = await chatClient.completeChat(messages);
const summary = response.choices[0]?.message?.content;
console.log(`\nSummary:\n${summary}`);

// Clean up
await chatModel.unload();
console.log('\nDone. Models unloaded.');

Note

Remplacez './meeting-notes.wav' par le chemin d’accès à votre fichier audio. Les formats pris en charge incluent WAV, MP3 et FLAC.

Exécutez le taker de notes :

node app.js

Vous voyez un résultat similaire à :

Downloading speech model: 100.00%
Speech model downloaded.
Speech model loaded.

Transcription:
OK so let's get started with the weekly sync. First, the backend
API is nearly done. Sarah finished the authentication endpoints
yesterday. We still need to add rate limiting before we go to
staging. On the frontend, the dashboard redesign is about seventy
percent complete. Jake, can you walk us through the new layout?
Great. The charts look good. I think we should add a filter for
date range though. For testing, we have about eighty percent code
coverage on the API. We need to write integration tests for the
new auth flow before Friday. Let's plan to do a full regression
test next Tuesday before the release. Any blockers? OK, sounds
like we are in good shape. Let's wrap up.

Downloading chat model: 100.00%
Chat model downloaded.
Chat model loaded.

Summary:
- **Backend API**: Authentication endpoints complete. Rate limiting
  still needed before staging deployment.
- **Frontend**: Dashboard redesign 70% complete. New chart layout
  reviewed. Action item: add a date range filter.
- **Testing**: API code coverage at 80%. Integration tests for the
  auth flow due Friday. Full regression test scheduled for next
  Tuesday before release.
- **Status**: No blockers reported. Team is on track.

Done. Models unloaded.

L’application transcrit d’abord le contenu audio, puis transmet ce texte à un modèle de conversation qui extrait les points clés et les organise en notes structurées.

Installer des packages

Référentiel d’exemples

L’exemple de code complet de cet article est disponible dans le dépôt Foundry Local GitHub. Pour cloner le référentiel et accéder à l’exemple d’utilisation :

git clone https://github.com/microsoft/Foundry-Local.git
cd Foundry-Local/samples/python/tutorial-voice-to-text

Si vous développez ou expédiez sur Windows, sélectionnez l'onglet Windows. Le package Windows s’intègre au runtime Windows ML . Il fournit la même surface d’surface d’API avec une étendue plus large d’accélération matérielle.

pip install foundry-local-sdk-winml openai

Transcrire un fichier audio

Dans cette étape, vous chargez un modèle de reconnaissance vocale et transcrivez un fichier audio. Le SDK Local Foundry utilise l'alias de modèle whisper pour sélectionner la meilleure variante Whisper pour votre matériel.

  1. Créez un fichier appelé app.py.

  2. Ajoutez le code suivant pour initialiser le Kit de développement logiciel (SDK), charger le modèle speech et transcrire un fichier audio :

    # Load the speech-to-text model
    speech_model = manager.catalog.get_model("whisper-tiny")
    speech_model.download(
        lambda progress: print(
            f"\rDownloading speech model: {progress:.2f}%",
            end="",
            flush=True,
        )
    )
    print()
    speech_model.load()
    print("Speech model loaded.")
    
    # Transcribe the audio file
    audio_client = speech_model.get_audio_client()
    transcription = audio_client.transcribe("meeting-notes.wav")
    print(f"\nTranscription:\n{transcription.text}")
    
    # Unload the speech model to free memory
    speech_model.unload()
    

    La get_audio_client méthode retourne un client pour les opérations audio. La transcribe méthode accepte un chemin d’accès de fichier et retourne un objet avec une text propriété contenant le contenu transcrit.

Note

Remplacez "meeting-notes.wav" par le chemin d’accès à votre fichier audio. Les formats pris en charge incluent WAV, MP3 et FLAC.

Résumer la transcription

Utilisez maintenant un modèle de conversation pour organiser la transcription brute en notes structurées. Chargez le modèle qwen2.5-0.5b et envoyez la transcription comme contexte avec une invite système qui demande au modèle de produire des notes résumées et bien ordonnées.

Ajoutez le code suivant après l’étape de transcription :

# Load the chat model for summarization
chat_model = manager.catalog.get_model("qwen2.5-0.5b")
chat_model.download(
    lambda progress: print(
        f"\rDownloading chat model: {progress:.2f}%",
        end="",
        flush=True,
    )
)
print()
chat_model.load()
print("Chat model loaded.")

# Summarize the transcription into organized notes
client = chat_model.get_chat_client()
messages = [
    {
        "role": "system",
        "content": "You are a note-taking assistant. "
                   "Summarize the following transcription "
                   "into organized, concise notes with "
                   "bullet points.",
    },
    {"role": "user", "content": transcription.text},
]

response = client.complete_chat(messages)
summary = response.choices[0].message.content
print(f"\nSummary:\n{summary}")

# Clean up
chat_model.unload()
print("\nDone. Models unloaded.")

L'invite système détermine le format de sortie du modèle. En lui demandant de produire des notes « organisées et concises avec des points à puces », vous obtenez du contenu structuré plutôt qu’une paraphrase brute.

Combiner dans une application complète

Créez un fichier nommé app.py et ajoutez le code complet suivant qui transcrit un fichier audio et récapitule la transcription :

from foundry_local_sdk import Configuration, FoundryLocalManager


def main():
    # Initialize the Foundry Local SDK
    config = Configuration(app_name="foundry_local_samples")
    FoundryLocalManager.initialize(config)
    manager = FoundryLocalManager.instance

    # Download and register all execution providers.
    current_ep = ""
    def ep_progress(ep_name: str, percent: float):
        nonlocal current_ep
        if ep_name != current_ep:
            if current_ep:
                print()
            current_ep = ep_name
        print(f"\r  {ep_name:<30}  {percent:5.1f}%", end="", flush=True)

    manager.download_and_register_eps(progress_callback=ep_progress)
    if current_ep:
        print()

    # Load the speech-to-text model
    speech_model = manager.catalog.get_model("whisper-tiny")
    speech_model.download(
        lambda progress: print(
            f"\rDownloading speech model: {progress:.2f}%",
            end="",
            flush=True,
        )
    )
    print()
    speech_model.load()
    print("Speech model loaded.")

    # Transcribe the audio file
    audio_client = speech_model.get_audio_client()
    transcription = audio_client.transcribe("meeting-notes.wav")
    print(f"\nTranscription:\n{transcription.text}")

    # Unload the speech model to free memory
    speech_model.unload()

    # Load the chat model for summarization
    chat_model = manager.catalog.get_model("qwen2.5-0.5b")
    chat_model.download(
        lambda progress: print(
            f"\rDownloading chat model: {progress:.2f}%",
            end="",
            flush=True,
        )
    )
    print()
    chat_model.load()
    print("Chat model loaded.")

    # Summarize the transcription into organized notes
    client = chat_model.get_chat_client()
    messages = [
        {
            "role": "system",
            "content": "You are a note-taking assistant. "
                       "Summarize the following transcription "
                       "into organized, concise notes with "
                       "bullet points.",
        },
        {"role": "user", "content": transcription.text},
    ]

    response = client.complete_chat(messages)
    summary = response.choices[0].message.content
    print(f"\nSummary:\n{summary}")

    # Clean up
    chat_model.unload()
    print("\nDone. Models unloaded.")


if __name__ == "__main__":
    main()

Note

Remplacez "meeting-notes.wav" par le chemin d’accès à votre fichier audio. Les formats pris en charge incluent WAV, MP3 et FLAC.

Exécutez le taker de notes :

python app.py

Vous voyez un résultat similaire à :

Downloading speech model: 100.00%
Speech model loaded.

Transcription:
OK so let's get started with the weekly sync. First, the backend
API is nearly done. Sarah finished the authentication endpoints
yesterday. We still need to add rate limiting before we go to
staging. On the frontend, the dashboard redesign is about seventy
percent complete. Jake, can you walk us through the new layout?
Great. The charts look good. I think we should add a filter for
date range though. For testing, we have about eighty percent code
coverage on the API. We need to write integration tests for the
new auth flow before Friday. Let's plan to do a full regression
test next Tuesday before the release. Any blockers? OK, sounds
like we are in good shape. Let's wrap up.

Downloading chat model: 100.00%
Chat model loaded.

Summary:
- **Backend API**: Authentication endpoints complete. Rate limiting
  still needed before staging deployment.
- **Frontend**: Dashboard redesign 70% complete. New chart layout
  reviewed. Action item: add a date range filter.
- **Testing**: API code coverage at 80%. Integration tests for the
  auth flow due Friday. Full regression test scheduled for next
  Tuesday before release.
- **Status**: No blockers reported. Team is on track.

Done. Models unloaded.

L’application transcrit d’abord le contenu audio, puis transmet ce texte à un modèle de conversation qui extrait les points clés et les organise en notes structurées.

Installer des packages

Référentiel d’exemples

L’exemple de code complet de cet article est disponible dans le dépôt Foundry Local GitHub. Pour cloner le référentiel et accéder à l’exemple d’utilisation :

git clone https://github.com/microsoft/Foundry-Local.git
cd Foundry-Local/samples/rust/tutorial-voice-to-text

Si vous développez ou expédiez sur Windows, sélectionnez l'onglet Windows. Le package Windows s’intègre au runtime Windows ML . Il fournit la même surface d’surface d’API avec une étendue plus large d’accélération matérielle.

cargo add foundry-local-sdk --features winml
cargo add tokio --features full
cargo add tokio-stream anyhow

Transcrire un fichier audio

Dans cette étape, vous chargez un modèle de reconnaissance vocale et transcrivez un fichier audio. Le SDK Local Foundry utilise l'alias de modèle whisper pour sélectionner la meilleure variante Whisper pour votre matériel.

  • Ouvrez src/main.rs et remplacez son contenu par le code suivant pour initialiser le Kit de développement logiciel (SDK), charger le modèle speech et transcrire un fichier audio :

    // Load the speech-to-text model
    let speech_model = manager
        .catalog()
        .get_model("whisper-tiny")
        .await?;
    
    if !speech_model.is_cached().await? {
        println!("Downloading speech model...");
        speech_model
            .download(Some(|progress: f64| {
                print!("\r  {progress:.1}%");
                io::stdout().flush().ok();
            }))
            .await?;
        println!();
    }
    
    speech_model.load().await?;
    println!("Speech model loaded.");
    
    // Transcribe the audio file
    let audio_client = speech_model.create_audio_client();
    let transcription = audio_client
        .transcribe("meeting-notes.wav")
        .await?;
    println!("\nTranscription:\n{}", transcription.text);
    
    // Unload the speech model to free memory
    speech_model.unload().await?;
    

    La create_audio_client méthode retourne un client pour les opérations audio. La transcribe méthode accepte un chemin d’accès de fichier et retourne un objet avec un text champ contenant le contenu transcrit.

Note

Remplacez "meeting-notes.wav" par le chemin d’accès à votre fichier audio. Les formats pris en charge incluent WAV, MP3 et FLAC.

Résumer la transcription

Utilisez maintenant un modèle de conversation pour organiser la transcription brute en notes structurées. Chargez le modèle qwen2.5-0.5b et envoyez la transcription comme contexte avec une invite système qui demande au modèle de produire des notes résumées et bien ordonnées.

Ajoutez le code suivant après l’étape de transcription, à l’intérieur de la main fonction :

// Load the chat model for summarization
let chat_model = manager
    .catalog()
    .get_model("qwen2.5-0.5b")
    .await?;

if !chat_model.is_cached().await? {
    println!("Downloading chat model...");
    chat_model
        .download(Some(|progress: f64| {
            print!("\r  {progress:.1}%");
            io::stdout().flush().ok();
        }))
        .await?;
    println!();
}

chat_model.load().await?;
println!("Chat model loaded.");

// Summarize the transcription into organized notes
let client = chat_model
    .create_chat_client()
    .temperature(0.7)
    .max_tokens(512);

let messages: Vec<ChatCompletionRequestMessage> = vec![
    ChatCompletionRequestSystemMessage::from(
        "You are a note-taking assistant. Summarize \
         the following transcription into organized, \
         concise notes with bullet points.",
    )
    .into(),
    ChatCompletionRequestUserMessage::from(
        transcription.text.as_str(),
    )
    .into(),
];

let response = client
    .complete_chat(&messages, None)
    .await?;
let summary = response.choices[0]
    .message
    .content
    .as_deref()
    .unwrap_or("");
println!("\nSummary:\n{}", summary);

// Clean up
chat_model.unload().await?;
println!("\nDone. Models unloaded.");

L'invite système détermine le format de sortie du modèle. En lui demandant de produire des notes « organisées et concises avec des points à puces », vous obtenez du contenu structuré plutôt qu’une paraphrase brute.

Combiner dans une application complète

Remplacez le contenu du src/main.rs code complet suivant qui transcrit un fichier audio et résume la transcription :

use foundry_local_sdk::{
    ChatCompletionRequestMessage,
    ChatCompletionRequestSystemMessage,
    ChatCompletionRequestUserMessage,
    FoundryLocalConfig, FoundryLocalManager,
};
use std::io::{self, Write};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Initialize the Foundry Local SDK
    let manager = FoundryLocalManager::create(
        FoundryLocalConfig::new("note-taker"),
    )?;

    // Download and register all execution providers.
    manager
        .download_and_register_eps_with_progress(None, {
            let mut current_ep = String::new();
            move |ep_name: &str, percent: f64| {
                if ep_name != current_ep {
                    if !current_ep.is_empty() {
                        println!();
                    }
                    current_ep = ep_name.to_string();
                }
                print!("\r  {:<30}  {:5.1}%", ep_name, percent);
                io::stdout().flush().ok();
            }
        })
        .await?;
    println!();

    // Load the speech-to-text model
    let speech_model = manager
        .catalog()
        .get_model("whisper-tiny")
        .await?;

    if !speech_model.is_cached().await? {
        println!("Downloading speech model...");
        speech_model
            .download(Some(|progress: f64| {
                print!("\r  {progress:.1}%");
                io::stdout().flush().ok();
            }))
            .await?;
        println!();
    }

    speech_model.load().await?;
    println!("Speech model loaded.");

    // Transcribe the audio file
    let audio_client = speech_model.create_audio_client();
    let transcription = audio_client
        .transcribe("meeting-notes.wav")
        .await?;
    println!("\nTranscription:\n{}", transcription.text);

    // Unload the speech model to free memory
    speech_model.unload().await?;

    // Load the chat model for summarization
    let chat_model = manager
        .catalog()
        .get_model("qwen2.5-0.5b")
        .await?;

    if !chat_model.is_cached().await? {
        println!("Downloading chat model...");
        chat_model
            .download(Some(|progress: f64| {
                print!("\r  {progress:.1}%");
                io::stdout().flush().ok();
            }))
            .await?;
        println!();
    }

    chat_model.load().await?;
    println!("Chat model loaded.");

    // Summarize the transcription into organized notes
    let client = chat_model
        .create_chat_client()
        .temperature(0.7)
        .max_tokens(512);

    let messages: Vec<ChatCompletionRequestMessage> = vec![
        ChatCompletionRequestSystemMessage::from(
            "You are a note-taking assistant. Summarize \
             the following transcription into organized, \
             concise notes with bullet points.",
        )
        .into(),
        ChatCompletionRequestUserMessage::from(
            transcription.text.as_str(),
        )
        .into(),
    ];

    let response = client
        .complete_chat(&messages, None)
        .await?;
    let summary = response.choices[0]
        .message
        .content
        .as_deref()
        .unwrap_or("");
    println!("\nSummary:\n{}", summary);

    // Clean up
    chat_model.unload().await?;
    println!("\nDone. Models unloaded.");

    Ok(())
}

Note

Remplacez "meeting-notes.wav" par le chemin d’accès à votre fichier audio. Les formats pris en charge incluent WAV, MP3 et FLAC.

Exécutez le taker de notes :

cargo run

Vous voyez un résultat similaire à :

Downloading speech model: 100.00%
Speech model loaded.

Transcription:
OK so let's get started with the weekly sync. First, the backend
API is nearly done. Sarah finished the authentication endpoints
yesterday. We still need to add rate limiting before we go to
staging. On the frontend, the dashboard redesign is about seventy
percent complete. Jake, can you walk us through the new layout?
Great. The charts look good. I think we should add a filter for
date range though. For testing, we have about eighty percent code
coverage on the API. We need to write integration tests for the
new auth flow before Friday. Let's plan to do a full regression
test next Tuesday before the release. Any blockers? OK, sounds
like we are in good shape. Let's wrap up.

Downloading chat model: 100.00%
Chat model loaded.

Summary:
- **Backend API**: Authentication endpoints complete. Rate limiting
  still needed before staging deployment.
- **Frontend**: Dashboard redesign 70% complete. New chart layout
  reviewed. Action item: add a date range filter.
- **Testing**: API code coverage at 80%. Integration tests for the
  auth flow due Friday. Full regression test scheduled for next
  Tuesday before release.
- **Status**: No blockers reported. Team is on track.

Done. Models unloaded.

L’application transcrit d’abord le contenu audio, puis transmet ce texte à un modèle de conversation qui extrait les points clés et les organise en notes structurées.

Nettoyer les ressources

Les poids du modèle restent dans votre cache local après avoir déchargé un modèle. Cela signifie que la prochaine fois que vous exécutez l’application, l’étape de téléchargement est ignorée et le modèle se charge plus rapidement. Aucun nettoyage supplémentaire n’est nécessaire, sauf si vous souhaitez récupérer de l’espace disque.