So fangen Sie mit Foundry Local an

In dieser Schnellstartanleitung erstellen Sie eine Konsolenanwendung, die ein lokales KI-Modell herunterlädt, eine Streamingchatantwort generiert und das Modell entlädt. Alles wird auf Ihrem Gerät ohne Cloudabhängigkeit oder Azure Abonnement ausgeführt.

Voraussetzungen

Beispielrepository

Den vollständigen Beispielcode für diesen Artikel finden Sie in den Foundry-Beispielen GitHub Repository. Um das Repository zu klonen und zum Beispielprojekt zu wechseln, verwenden Sie folgenden Befehl:

git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/csharp/foundry-local/native-chat-completions

Pakete installieren

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

Die C#-Beispiele im GitHub Repository sind vorkonfigurierte Projekte. Wenn Sie von Grund auf neu erstellen, sollten Sie die Referenz zum Foundry Local SDK lesen, um weitere Details zum Einrichten Ihres C#-Projekts mit Foundry Local zu erhalten.

Verwenden der API für systemeigene Chatabschlusse

Kopieren Sie den folgenden Code, und fügen Sie ihn in eine C#-Datei mit dem Namen Program.csein:

using Microsoft.AI.Foundry.Local;

CancellationToken ct = new CancellationToken();

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


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


// Discover available execution providers and their registration status.
var eps = mgr.DiscoverEps();
int maxNameLen = 30;
Console.WriteLine("Available execution providers:");
Console.WriteLine($"  {"Name".PadRight(maxNameLen)}  Registered");
Console.WriteLine($"  {new string('─', maxNameLen)}  {"──────────"}");
foreach (var ep in eps)
{
    Console.WriteLine($"  {ep.Name.PadRight(maxNameLen)}  {ep.IsRegistered}");
}

// Download and register all execution providers with per-EP progress.
// EP packages include dependencies and may be large.
// Download is only required again if a new version of the EP is released.
// For cross platform builds there is no dynamic EP download and this will return immediately.
Console.WriteLine("\nDownloading execution providers:");
if (eps.Length > 0)
{
    string currentEp = "";
    await mgr.DownloadAndRegisterEpsAsync((epName, percent) =>
    {
        if (epName != currentEp)
        {
            if (currentEp != "")
            {
                Console.WriteLine();
            }
            currentEp = epName;
        }
        Console.Write($"\r  {epName.PadRight(maxNameLen)}  {percent,6:F1}%");
    });
    Console.WriteLine();
}
else
{
    Console.WriteLine("No execution providers to download.");
}


// Get the model catalog
var catalog = await mgr.GetCatalogAsync();


// Get a model using an alias.
var model = await catalog.GetModelAsync("qwen2.5-0.5b") ?? throw new Exception("Model not found");

// Download the model (the method skips download if already cached)
await model.DownloadAsync(progress =>
{
    Console.Write($"\rDownloading model: {progress:F2}%");
    if (progress >= 100f)
    {
        Console.WriteLine();
    }
});

// Load the model
Console.Write($"Loading model {model.Id}...");
await model.LoadAsync();
Console.WriteLine("done.");

// Create a stateful native chat session and enable streaming.
using var chatSession = new ChatSession(model);
chatSession.SetStreaming(true);
using var request = new Request();
request.AddItem(MessageItem.User("Why is the sky blue?"));

// Get a streaming chat completion response
Console.WriteLine("Chat completion response:");
await using var streamingResponse = chatSession.ProcessStreamingRequestAsync(request, ct);
await foreach (var item in streamingResponse)
{
    using (item)
    {
        if (item is TextItem { Type: TextItemType.Default } text)
        {
            Console.Write(text.Text);
            Console.Out.Flush();
        }
    }
}
using var finalResponse = await streamingResponse.FinalResponse;
Console.WriteLine();

// Tidy up - unload the model
finalResponse.Dispose();
await streamingResponse.DisposeAsync();
request.Dispose();
chatSession.Dispose();
await model.UnloadAsync();

Führen Sie den Code mithilfe des folgenden Befehls aus:

dotnet run

Problembehandlung

  • Build-Fehler, die auf net8.0 verweisen: Installieren Sie das .NET 8.0 SDK, und erstellen Sie die App neu.
  • Model not found: Führen Sie den optionalen Modellauflistungscode aus, um einen Alias zu finden, der auf Ihrem Gerät verfügbar ist, und aktualisieren Sie dann den Alias, der an GetModelAsync übergeben wird.
  • Langsame Erstausführung: Modelldownloads können etwas Zeit in Anspruch nehmen, wenn Sie die App zum ersten Mal ausführen.

Voraussetzungen

Beispielrepository

Der vollständige Beispielcode für diesen Artikel ist in den Gießereibeispielen GitHub Repository verfügbar. So klonen Sie das Repository, und navigieren Sie zur Beispielverwendung:

git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/javascript/foundry-local/native-chat-completions

Pakete installieren

npm install foundry-local-sdk openai

Verwenden der API für systemeigene Chatabschlusse

Kopieren Sie den folgenden Code, und fügen Sie ihn in eine JavaScript-Datei mit dem Namen app.jsein:

import {
    ChatSession,
    FoundryLocalManager,
    Item,
    Request
} from 'foundry-local-sdk';

// Initialize the Foundry Local SDK
console.log('Initializing Foundry Local SDK...');

const manager = FoundryLocalManager.create({
    appName: 'foundry_local_samples',
    logLevel: 'info'
});
console.log('✓ SDK initialized successfully');

// Discover available execution providers and their registration status.
const eps = manager.discoverEps();
const maxNameLen = 30;
console.log('\nAvailable execution providers:');
console.log(`  ${'Name'.padEnd(maxNameLen)}  Registered`);
console.log(`  ${'─'.repeat(maxNameLen)}  ──────────`);
for (const ep of eps) {
    console.log(`  ${ep.name.padEnd(maxNameLen)}  ${ep.isRegistered}`);
}

// Download and register all execution providers with per-EP progress.
// EP packages include dependencies and may be large.
// Download is only required again if a new version of the EP is released.
console.log('\nDownloading execution providers:');
if (eps.length > 0) {
    let currentEp = '';
    await manager.downloadAndRegisterEps((epName, percent) => {
        if (epName !== currentEp) {
            if (currentEp !== '') {
                process.stdout.write('\n');
            }
            currentEp = epName;
        }
        process.stdout.write(`\r  ${epName.padEnd(maxNameLen)}  ${percent.toFixed(1).padStart(5)}%`);
    });
    process.stdout.write('\n');
} else {
    console.log('No execution providers to download.');
}

// Get the model object
const modelAlias = 'qwen2.5-0.5b'; // Using an available model from the list above
const model = await manager.catalog.getModel(modelAlias);

// Download the model
console.log(`\nDownloading model ${modelAlias}...`);
await model.download((progress) => {
    process.stdout.write(`\rDownloading... ${progress.toFixed(2)}%`);
});
console.log('\n✓ Model downloaded');

// Load the model
console.log(`\nLoading model ${modelAlias}...`);
await model.load();
console.log('✓ Model loaded');

// Create a stateful native chat session
console.log('\nCreating chat session...');
const chatSession = new ChatSession(model);
chatSession.setOptions({
    search: { temperature: 0.7, maxOutputTokens: 256 }
});
console.log('✓ Chat session created');

// Example chat completion
console.log('\nTesting chat completion...');
const completion = await chatSession.processRequest(
    new Request().addItem(Item.userMessage('Why is the sky blue?'))
);

console.log('\nChat completion result:');
for (const item of completion.output) {
    if (item.type === 'message') {
        process.stdout.write(item.content ?? item.parts?.map((part) => part.text ?? '').join('') ?? '');
    } else if (item.type === 'text' && item.textType === 'default') {
        process.stdout.write(item.text);
    }
}
console.log();

// Example streaming completion
console.log('\nTesting streaming completion...');
const stream = chatSession.processStreamingRequest(
    new Request().addItem(Item.userMessage(
        'Write a short poem about programming.'
    ))
);
for await (const item of stream) {
    if (item.type === 'text' && item.textType === 'default') {
        process.stdout.write(item.text);
    }
}
await stream.response;
console.log('\n');

// Unload the model
console.log('Unloading model...');
chatSession.dispose();
await model.unload();
console.log(`✓ Model unloaded`);

Führen Sie den Code mithilfe des folgenden Befehls aus:

node app.js

Voraussetzungen

Beispielrepository

Der vollständige Beispielcode für diesen Artikel ist in den Gießereibeispielen GitHub Repository verfügbar. So klonen Sie das Repository, und navigieren Sie zur Beispielverwendung:

git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/python/foundry-local/native-chat-completions

Pakete installieren

pip install foundry-local-sdk openai

Verwenden der API für systemeigene Chatabschlusse

Kopieren Sie den folgenden Code, und fügen Sie ihn in eine Python Datei mit dem Namen app.py ein:

from foundry_local_sdk import (
    ChatSession,
    Configuration,
    FoundryLocalManager,
    MessageItem,
    Request,
    RequestOptions,
    SearchOptions,
    TextItem,
    TextItemType,
)



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

    # Discover and register execution providers that are not already available.
    eps = manager.discover_eps()
    missing_eps = [ep.name for ep in eps if not ep.is_registered]
    if missing_eps:
        manager.download_and_register_eps(missing_eps)

    # Select and load a model from the catalog.
    model = manager.catalog.get_model("qwen2.5-0.5b")
    if model is None:
        raise RuntimeError("Model 'qwen2.5-0.5b' was not found in the catalog.")
    if not model.is_cached:
        model.download(
            lambda progress: print(
                f"\rDownloading model: {progress:.2f}%",
                end="",
                flush=True,
            )
        )
        print()
    model.load()
    print("Model loaded and ready.")

    try:
        # Create a native chat session and stream the response token by token.
        with ChatSession(model) as session:
            session.set_options(
                RequestOptions(
                    search=SearchOptions(temperature=0.0, max_output_tokens=256)
                )
            )
            session.set_streaming(True)
            with Request().add_item(
                MessageItem.user("What is the golden ratio?")
            ) as request:
                print("Assistant: ", end="", flush=True)
                with session.process_streaming_request(request) as stream:
                    for item in stream:
                        if (
                            isinstance(item, TextItem)
                            and item.type == TextItemType.DEFAULT
                        ):
                            print(item.text, end="", flush=True)
                print()
    finally:
        # Clean up
        if model.is_loaded:
            model.unload()
        manager.close()
        print("Model unloaded.")


if __name__ == "__main__":
    main()

Führen Sie den Code mithilfe des folgenden Befehls aus:

python app.py

Problembehandlung

  • ModuleNotFoundError: No module named 'foundry_local_sdk': Installieren Sie das SDK, indem Sie es ausführen pip install foundry-local-sdk.
  • Model not found: Führen Sie den optionalen Modellauflistungscode aus, um einen Alias zu finden, der auf Ihrem Gerät verfügbar ist, und aktualisieren Sie dann den Alias, der an get_model übergeben wird.
  • Langsame Erstausführung: Modelldownloads können etwas Zeit in Anspruch nehmen, wenn Sie die App zum ersten Mal ausführen.

Voraussetzungen

Beispielrepository

Der vollständige Beispielcode für diesen Artikel ist in den Gießereibeispielen GitHub Repository verfügbar. So klonen Sie das Repository, und navigieren Sie zur Beispielverwendung:

git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/rust/foundry-local/native-chat-completions

Pakete installieren

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

Verwenden der API für systemeigene Chatabschlusse

Ersetzen Sie den Inhalt von main.rs durch den folgenden Code.

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

use std::io::{self, Write};

use foundry_local_sdk::{
    ChatSession, FoundryLocalConfig, FoundryLocalManager, Item, Request, RequestOptions,
    SearchOptions, TextKind,
};
use tokio_stream::StreamExt;

const ALIAS: &str = "qwen2.5-0.5b";

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("Native Chat Completions");
    println!("=======================\n");

    // ── 1. Initialise the manager ────────────────────────────────────────
    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  {ep_name:<30}  {percent:5.1}%");
                io::stdout().flush().ok();
            }
        })
        .await?;
    println!();

    // ── 2. Pick a model and ensure it is downloaded ─────────────────────
    let model = manager.catalog().get_model(ALIAS).await?;
    println!("Model: {} (id: {})", model.alias(), model.id());

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

    println!("Loading model...");
    model.load().await?;
    println!("✓ Model loaded\n");

    // ── 3. Create a stateful chat session ────────────────────────────────
    let session = ChatSession::new(&model).await?;
    session
        .set_options(RequestOptions {
            search: SearchOptions {
                temperature: Some(0.7),
                max_output_tokens: Some(256),
                ..Default::default()
            },
            ..Default::default()
        })
        .await?;

    // ── 4. Non-streaming chat completion ────────────────────────────────
    let request = Request::from_items(vec![
        Item::system_message(vec![Item::text("You are a helpful assistant.")]),
        Item::user_message(vec![Item::text("What is Rust's ownership model?")]),
    ]);

    println!("--- Non-streaming completion ---");
    let response = session.process_request(request).await?;
    print!("Assistant: ");
    for item in &response.items {
        if let Some(message) = item.as_message() {
            print!("{}", message.text());
        }
    }
    println!();

    // ── 5. Streaming chat completion ────────────────────────────────────
    let request = Request::from_items(vec![Item::user_message(vec![Item::text(
        "Explain the borrow checker in two sentences.",
    )])]);

    println!("\n--- Streaming completion ---");
    print!("Assistant: ");
    let mut stream = session.process_streaming_request(request);
    while let Some(item) = stream.next().await {
        if let Item::Text {
            text,
            kind: TextKind::Default,
        } = item?
        {
            print!("{text}");
            io::stdout().flush().ok();
        }
    }
    println!("\n");

    // ── 6. Unload the model ─────────────────────────────────────────────
    drop(session);
    println!("Unloading model...");
    model.unload().await?;
    println!("Done.");

    Ok(())
}

Führen Sie den Code mithilfe des folgenden Befehls aus:

cargo run

Problembehandlung

  • Buildfehler: Stellen Sie sicher, dass Rust 1.70.0 oder höher installiert ist. Führen Sie rustup update aus, um die neueste Version abzurufen.
  • Model not found: Überprüfen Sie, ob der Modellalias korrekt ist. Verwenden Sie manager.catalog().get_models().await?, um verfügbare Modelle aufzulisten.
  • Langsame Erstausführung: Modelldownloads können etwas Zeit in Anspruch nehmen, wenn Sie die App zum ersten Mal ausführen.

Voraussetzungen

  • CMake 3.20 oder höher.
  • Ein C++20-Compiler.
  • Die NuGet CLI.

Beispielrepository

Klonen Sie das GitHub-Repository für Foundry-Beispiele, und wechseln Sie zum C++-Beispiel:

git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/cpp/foundry-local/native-chat-completions

Pakete installieren

Für die C++-Beispiele ist Folgendes erforderlich:

  • CMake 3.20 oder höher.
  • Ein C++20-Compiler.
  • Die NuGet-CLI auf Ihrem PATH.

Beispiel konfigurieren und erstellen:

cmake -S . -B build
cmake --build build --config Release

Während der Konfiguration stellt das Beispiel die Version 2.2.1 des Microsoft.AI.Foundry.Local.Runtime NuGet-Pakets in build/_packages wieder her. Das Paket enthält die C++-Header und systemeigene Bibliotheken für Windows, Linux und macOS. Sie benötigen kein separates WinML-Paket.

Die CMake-Konfiguration wählt die Laufzeitressourcen für Ihr Betriebssystem und die Architektur aus und kopiert die erforderlichen nativen Bibliotheken neben der ausführbaren Datei. Führen Sie unter macOS und Linux die ausführbare Datei aus build aus. Führen Sie unter Windows die .exe-Datei aus build aus.

Native Chat-Vervollständigungs-API verwenden

Im Beispiel wird das SDK initialisiert, ein Modell heruntergeladen und geladen, eine Chatantwort gestreamt und das Modell entladen.

#include <foundry_local/foundry_local_cpp.h>

#include <iostream>
#include <memory>
#include <string>

using namespace foundry_local;

std::unique_ptr<IModel> SelectChatModel(ICatalog& catalog) {
  for (const std::string alias : {"qwen2.5-0.5b", "qwen3.5-0.8b"}) {
    auto model = catalog.GetModel(alias);
    if (!model) {
      continue;
    }
    for (const auto& variant : model->GetVariants()) {
      const ModelInfo info = variant->GetInfo();
      if (info.DeviceType() == FOUNDRY_LOCAL_DEVICE_CPU &&
          (info.Task() == "chat-completion" || info.Task() == "coding")) {
        model->SelectVariant(*variant);
        return model;
      }
    }
  }
  return nullptr;
}

void PrintMessages(const Response& response) {
  for (const Item& item : response.GetItems()) {
    if (item.GetType() != FOUNDRY_LOCAL_ITEM_MESSAGE) {
      continue;
    }
    for (const Item& part : item.GetMessage().parts) {
      if (part.GetType() == FOUNDRY_LOCAL_ITEM_TEXT &&
          part.GetText().type == FOUNDRY_LOCAL_TEXT_ITEM_TYPE_DEFAULT) {
        std::cout << part.GetText().text;
      }
    }
  }
  std::cout << "\n";
}

int main() {
  try {
    Configuration config("foundry_local_cpp_native_chat");
    Manager manager(std::move(config));
    auto model = SelectChatModel(manager.GetCatalog());
    if (!model) {
      throw std::runtime_error("No supported CPU chat model was found.");
    }

    if (!model->IsCached()) {
      model->Download([](float progress) {
        std::cout << "\rDownloading model: " << static_cast<int>(progress) << "%" << std::flush;
        return 0;
      });
      std::cout << "\n";
    }
    model->Load();

    {
      ChatSession session(*model);
      Request request{UserMessage("What is the capital of France?")};
      std::cout << "Assistant: ";
      PrintMessages(session.ProcessRequest(request));
    }

    {
      ChatSession session(*model);
      session.SetStreamingCallback([](Item item) {
        if (item.GetType() == FOUNDRY_LOCAL_ITEM_TEXT &&
            item.GetText().type == FOUNDRY_LOCAL_TEXT_ITEM_TYPE_DEFAULT) {
          std::cout << item.GetText().text << std::flush;
        }
        return 0;
      });
      Request request{UserMessage("Name two landmarks in Paris.")};
      std::cout << "Streaming assistant: ";
      session.ProcessRequest(request);
      std::cout << "\n";
    }

    model->Unload();
    manager.Shutdown();
  } catch (const Error& error) {
    std::cerr << "Foundry Local error [" << error.Code() << "]: " << error.what() << "\n";
    return 1;
  } catch (const std::exception& error) {
    std::cerr << "Error: " << error.what() << "\n";
    return 1;
  }

  return 0;
}

Führen Sie das Beispiel aus:

./build/native-chat-completions

Problembehandlung

  • Modell nicht gefunden: Überprüfen Sie den Modellalias anhand der im Katalog verfügbaren Modelle.
  • Langsame Erstausführung: Modelldownloads können etwas Zeit in Anspruch nehmen, wenn Sie die App zum ersten Mal ausführen.