Kurz: Vytvoření nástroje pro psaní poznámek z hlasu na text

Sestavte aplikaci, která převádí mluvený zvuk na uspořádané poznámky – zcela na vašem zařízení. Aplikace nejprve přepisuje zvukový soubor pomocí modelu převodu řeči na text a pak pomocí chatovacího modelu shrnout a uspořádat přepis do čistých poznámek.

V tomto návodu se naučíte, jak:

  • Nastavení projektu a instalace místní sady SDK Foundry
  • Načtení modelu převodu řeči na text a přepis zvukového souboru
  • Načtení chatovacího modelu a shrnutí přepisu
  • Kombinování přepisu a sumarizace do kompletní aplikace
  • Vyčistěte zdroje

Předpoklady

  • Počítač s Windows, macOS nebo Linuxem s minimálně 8 GB paměti RAM.
  • .wav Zvukový soubor k přepisu (kurz používá ukázkový soubor).

Instalace balíčků

Úložiště ukázek

Kompletní ukázkový kód pro tento článek najdete v repozitáři Foundry samples na GitHubu. Pokud chcete naklonovat úložiště a přejít k ukázce, použijte:

git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/csharp/foundry-local/tutorial-voice-to-text

Pokud vyvíjíte nebo vydáváte aplikace na Windows, vyberte kartu Windows. Balíček Windows se integruje s runtime modulem Windows ML — poskytuje stejné rozhraní API a nabízí širší možnosti hardwarové akcelerace.

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

Ukázky jazyka C# v úložišti GitHub jsou předkonfigurované projekty. Pokud vytváříte úplně od začátku, měli byste si přečíst referenční informace k místní sadě SDK Foundry , kde najdete další podrobnosti o tom, jak nastavit projekt jazyka C# pomocí Foundry Local.

Přepis zvukového souboru

V tomto kroku načtete model převodu řeči na text a přepíšete zvukový soubor. Foundry Local SDK používá whisper alias model k výběru nejlepší varianty Whisper pro váš hardware.

  • Otevřete Program.cs a nahraďte jeho obsah následujícím kódem, který inicializuje sadu SDK, načte model řeči a přepíše zvukový soubor:

    // 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();
    

    Metoda GetAudioClientAsync vrátí klienta pro zvukové operace. Metoda TranscribeAudioStreamingAsync streamuje bloky přepisů, jakmile budou k dispozici. Nashromáždíte text, abyste ho mohli předat do modelu chatu v dalším kroku.

Poznámka:

Nahraďte "meeting-notes.wav" cestou k vašemu zvukovému souboru. Mezi podporované formáty patří WAV, MP3 a FLAC.

Shrnutí přepisu

Teď pomocí modelu chatu uspořádejte nezpracovaný přepis do strukturovaných poznámek. Načtěte qwen2.5-0.5b model a odešlete přepis jako kontext s výzvou systému, která dává modelu pokyn k vytvoření čistých souhrnných poznámek.

Za krok přepisu přidejte následující kód:

// 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.");

Systémový podnět určuje formát výstupu modelu. Když ho dáte pokyn, aby vytvořil "uspořádané a stručné poznámky s odrážkami", získáte strukturovaný obsah místo nezpracované parafráze.

Zkombinování do kompletní aplikace

Nahraďte obsah Program.cs následujícím úplným kódem, který přepisuje zvukový soubor a shrnuje přepis:

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.");

Poznámka:

Nahraďte "meeting-notes.wav" cestou k vašemu zvukovému souboru. Mezi podporované formáty patří WAV, MP3 a FLAC.

Spusťte aplikaci pro pořizování poznámek.

dotnet run

Zobrazí se výstup podobný následujícímu:

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.

Aplikace nejprve přepisuje zvukový obsah výstupem streamování a pak předá nahromaděný text do chatovacího modelu, který extrahuje klíčové body a uspořádá je do strukturovaných poznámek.

Instalace balíčků

Úložiště ukázek

Kompletní vzorový kód pro tento článek je k dispozici v úložišti foundry-samples GitHub. Pokud chcete naklonovat úložiště a přejít na ukázku, použijte:

git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/javascript/foundry-local/tutorial-voice-to-text

Pokud vyvíjíte nebo vydáváte aplikace na Windows, vyberte kartu Windows. Balíček Windows se integruje s runtime modulem Windows ML — poskytuje stejné rozhraní API a nabízí širší možnosti hardwarové akcelerace.

npm install foundry-local-sdk-winml openai

Přepis zvukového souboru

V tomto kroku načtete model převodu řeči na text a přepíšete zvukový soubor. Foundry Local SDK používá whisper alias model k výběru nejlepší varianty Whisper pro váš hardware.

  1. Vytvořte soubor s názvem app.js.

  2. Přidejte následující kód pro inicializaci sady SDK, načtení modelu řeči a přepis zvukového souboru:

    // 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();
    

    Metoda createAudioClient vrátí klienta pro zvukové operace. Metoda transcribe přijímá cestu k souboru a vrací objekt s text vlastností obsahující přepisovaný obsah.

Poznámka:

Nahraďte './meeting-notes.wav' cestou k vašemu zvukovému souboru. Mezi podporované formáty patří WAV, MP3 a FLAC.

Shrnutí přepisu

Teď pomocí modelu chatu uspořádejte nezpracovaný přepis do strukturovaných poznámek. Načtěte qwen2.5-0.5b model a odešlete přepis jako kontext s výzvou systému, která dává modelu pokyn k vytvoření čistých souhrnných poznámek.

Za krok přepisu přidejte následující kód:

// 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.');

Systémový podnět určuje formát výstupu modelu. Když ho dáte pokyn, aby vytvořil "uspořádané a stručné poznámky s odrážkami", získáte strukturovaný obsah místo nezpracované parafráze.

Zkombinování do kompletní aplikace

Vytvořte soubor s názvem app.js a přidejte následující úplný kód, který přepisuje a shrnuje přepis:

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.');

Poznámka:

Nahraďte './meeting-notes.wav' cestou k vašemu zvukovému souboru. Mezi podporované formáty patří WAV, MP3 a FLAC.

Spusťte aplikaci pro pořizování poznámek.

node app.js

Zobrazí se výstup podobný následujícímu:

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.

Aplikace nejprve přepisuje zvukový obsah a pak tento text předá modelu chatu, který extrahuje klíčové body a uspořádá je do strukturovaných poznámek.

Instalace balíčků

Úložiště ukázek

Kompletní vzorový kód pro tento článek je k dispozici v úložišti foundry-samples GitHub. Pokud chcete naklonovat úložiště a přejít na ukázku, použijte:

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

Pokud vyvíjíte nebo vydáváte aplikace na Windows, vyberte kartu Windows. Balíček Windows se integruje s runtime modulem Windows ML — poskytuje stejné rozhraní API a nabízí širší možnosti hardwarové akcelerace.

pip install foundry-local-sdk-winml openai

Přepis zvukového souboru

V tomto kroku načtete model převodu řeči na text a přepíšete zvukový soubor. Foundry Local SDK používá whisper alias model k výběru nejlepší varianty Whisper pro váš hardware.

  1. Vytvořte soubor s názvem app.py.

  2. Přidejte následující kód pro inicializaci sady SDK, načtení modelu řeči a přepis zvukového souboru:

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

    Metoda get_audio_client vrátí klienta pro zvukové operace. Metoda transcribe přijímá cestu k souboru a vrací objekt s text vlastností obsahující přepisovaný obsah.

Poznámka:

Nahraďte "meeting-notes.wav" cestou k vašemu zvukovému souboru. Mezi podporované formáty patří WAV, MP3 a FLAC.

Shrnutí přepisu

Teď pomocí modelu chatu uspořádejte nezpracovaný přepis do strukturovaných poznámek. Načtěte qwen2.5-0.5b model a odešlete přepis jako kontext s výzvou systému, která dává modelu pokyn k vytvoření čistých souhrnných poznámek.

Za krok přepisu přidejte následující kód:

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

Systémový podnět určuje formát výstupu modelu. Když ho dáte pokyn, aby vytvořil "uspořádané a stručné poznámky s odrážkami", získáte strukturovaný obsah místo nezpracované parafráze.

Zkombinování do kompletní aplikace

Vytvořte soubor s názvem app.py a přidejte následující úplný kód, který přepisuje a shrnuje přepis:

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

Poznámka:

Nahraďte "meeting-notes.wav" cestou k vašemu zvukovému souboru. Mezi podporované formáty patří WAV, MP3 a FLAC.

Spusťte aplikaci pro pořizování poznámek.

python app.py

Zobrazí se výstup podobný následujícímu:

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.

Aplikace nejprve přepisuje zvukový obsah a pak tento text předá modelu chatu, který extrahuje klíčové body a uspořádá je do strukturovaných poznámek.

Instalace balíčků

Úložiště ukázek

Kompletní vzorový kód pro tento článek je k dispozici v úložišti foundry-samples GitHub. Pokud chcete naklonovat úložiště a přejít na ukázku, použijte:

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

Pokud vyvíjíte nebo vydáváte aplikace na Windows, vyberte kartu Windows. Balíček Windows se integruje s runtime modulem Windows ML — poskytuje stejné rozhraní API a nabízí širší možnosti hardwarové akcelerace.

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

Přepis zvukového souboru

V tomto kroku načtete model převodu řeči na text a přepíšete zvukový soubor. Foundry Local SDK používá whisper alias model k výběru nejlepší varianty Whisper pro váš hardware.

  • Otevřete src/main.rs a nahraďte jeho obsah následujícím kódem, který inicializuje sadu SDK, načte model řeči a přepíše zvukový soubor:

    // 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?;
    

    Metoda create_audio_client vrátí klienta pro zvukové operace. Metoda transcribe přijme cestu k souboru a vrátí objekt s polem text obsahujícím přepisovaný obsah.

Poznámka:

Nahraďte "meeting-notes.wav" cestou k vašemu zvukovému souboru. Mezi podporované formáty patří WAV, MP3 a FLAC.

Shrnutí přepisu

Teď pomocí modelu chatu uspořádejte nezpracovaný přepis do strukturovaných poznámek. Načtěte qwen2.5-0.5b model a odešlete přepis jako kontext s výzvou systému, která dává modelu pokyn k vytvoření čistých souhrnných poznámek.

Do funkce přidejte následující kód za krok přepisu main :

// 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.");

Systémový podnět určuje formát výstupu modelu. Když ho dáte pokyn, aby vytvořil "uspořádané a stručné poznámky s odrážkami", získáte strukturovaný obsah místo nezpracované parafráze.

Zkombinování do kompletní aplikace

Nahraďte obsah src/main.rs následujícím úplným kódem, který přepisuje zvukový soubor a shrnuje přepis:

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("foundry_local_samples"),
    )?;

    // 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(())
}

Poznámka:

Nahraďte "meeting-notes.wav" cestou k vašemu zvukovému souboru. Mezi podporované formáty patří WAV, MP3 a FLAC.

Spusťte aplikaci pro pořizování poznámek.

cargo run

Zobrazí se výstup podobný následujícímu:

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.

Aplikace nejprve přepisuje zvukový obsah a pak tento text předá modelu chatu, který extrahuje klíčové body a uspořádá je do strukturovaných poznámek.

Vyčistěte zdroje

Váhy modelu zůstanou v místní mezipaměti po uvolnění modelu. To znamená, že při příštím spuštění aplikace se krok stahování přeskočí a model se načte rychleji. Pokud nechcete uvolnit místo na disku, není potřeba žádné další vyčištění.