Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Neste quickstart, cria uma aplicação de consola que descarrega um modelo de IA local, gera uma resposta de chat em streaming e descarrega o modelo. Tudo corre no seu dispositivo sem dependência da cloud ou subscrição do Azure.
Pré-requisitos
- .NET 8.0 SDK ou uma versão posterior instalada.
Repositório de samples
Pode encontrar o código de exemplo completo deste artigo no repositório de exemplos do Foundry no GitHub. Para clonar o repositório e navegar até à amostra, utilize:
git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/csharp/foundry-local/native-chat-completions
Instalar pacotes
dotnet add package Microsoft.AI.Foundry.Local
dotnet add package OpenAI
Os exemplos de C# no repositório GitHub são projetos pré-configurados. Se está a construir do zero, deve ler a referência do Foundry Local SDK para mais detalhes sobre como configurar o seu projeto C# com o Foundry Local.
Usar API nativa de completação de chat
Copie e cole o seguinte código num ficheiro C# chamado Program.cs:
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();
Execute o código usando o seguinte comando:
dotnet run
Solução de problemas
-
Erros de compilação referentes a
net8.0: Instala o SDK .NET 8.0 e depois reconstrói a aplicação. -
Model not found: Executa o excerto opcional de listagem de modelos para encontrar um alias disponível no teu dispositivo, depois atualiza o alias passado paraGetModelAsync. - Primeira execução lenta: Os downloads de modelos podem demorar à primeira vez que executas a aplicação.
Pré-requisitos
- Node.js 20 ou mais recentes instalados.
Repositório de samples
O código de exemplo completo deste artigo está disponível no repositório foundry-samples do GitHub. Para clonar o repositório e navegar até ao exemplo de uso:
git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/javascript/foundry-local/native-chat-completions
Instalar pacotes
npm install foundry-local-sdk openai
Usar API nativa de completação de chat
Copie e cole o seguinte código num ficheiro JavaScript chamado app.js:
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`);
Execute o código usando o seguinte comando:
node app.js
Pré-requisitos
- Python 3.11 ou posterior instalado.
Repositório de samples
O código de exemplo completo deste artigo está disponível no repositório foundry-samples do GitHub. Para clonar o repositório e navegar até ao exemplo de uso:
git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/python/foundry-local/native-chat-completions
Instalar pacotes
pip install foundry-local-sdk openai
Usar API nativa de completação de chat
Copie e cole o seguinte código num ficheiro Python chamado app.py:
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()
Execute o código usando o seguinte comando:
python app.py
Solução de problemas
-
ModuleNotFoundError: No module named 'foundry_local_sdk': Instale o SDK executandopip install foundry-local-sdk. -
Model not found: Executa o excerto opcional de listagem de modelos para encontrar um alias disponível no teu dispositivo, depois atualiza o alias passado paraget_model. - Primeira execução lenta: Os downloads de modelos podem demorar à primeira vez que executas a aplicação.
Pré-requisitos
- Rust and Cargo instalado (Rust 1.70.0 ou posterior).
Repositório de samples
O código de exemplo completo deste artigo está disponível no repositório foundry-samples do GitHub. Para clonar o repositório e navegar até ao exemplo de uso:
git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/rust/foundry-local/native-chat-completions
Instalar pacotes
cargo add foundry-local-sdk
cargo add tokio --features full
cargo add tokio-stream anyhow
Usar API nativa de completação de chat
Substitua o conteúdo do main.rs pelo seguinte código:
// 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(())
}
Execute o código usando o seguinte comando:
cargo run
Solução de problemas
-
Erros de compilação: Certifique-se de que tem o Rust 1.70.0 ou posterior instalado. Corre
rustup updatepara obter a versão mais recente. -
Model not found: Verifique se o alias do modelo está correto. Usemanager.catalog().get_models().await?para listar os modelos disponíveis. - Primeira execução lenta: Os downloads de modelos podem demorar à primeira vez que executas a aplicação.
Pré-requisitos
- CMake 3.20 ou versão posterior.
- Um compilador C++20.
- A CLI do NuGet
Repositório de samples
Clone o repositório de samples do Foundry no GitHub e vá ao exemplo de C++:
git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/cpp/foundry-local/native-chat-completions
Instalar pacotes
Os exemplos em C++ requerem:
- CMake 3.20 ou superior.
- Um compilador C++20.
- A CLI do NuGet no seu
PATH.
Configure e construa o exemplo:
cmake -S . -B build
cmake --build build --config Release
Durante a configuração, o sample restaura a versão 2.2.1 do Microsoft.AI.Foundry.Local.Runtime pacote NuGet para build/_packages. O pacote contém os cabeçalhos C++ e as bibliotecas nativas para Windows, Linux e macOS. Não precisas de um pacote WinML separado.
A configuração CMake seleciona os ativos de runtime para o seu sistema operativo e arquitetura e copia as bibliotecas nativas necessárias ao lado do executável. No macOS e Linux, execute o executável a partir de build. No Windows, execute o ficheiro .exe a partir de build.
Use a API nativa de chat completions
O exemplo inicializa o SDK, transfere e carrega um modelo, transmite uma resposta de chat e descarrega o modelo da memória.
#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;
}
Analisa a amostra:
./build/native-chat-completions
Solução de problemas
- Modelo não encontrado: Verifique o alias do modelo com os modelos disponíveis no catálogo.
- Primeira execução lenta: Os downloads de modelos podem demorar à primeira vez que executas a aplicação.