Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Dalam tutorial ini, Anda membangun asisten obrolan interaktif yang berjalan sepenuhnya di perangkat Anda. Asisten mempertahankan konteks percakapan di berbagai pertukaran dialog, sehingga mengingat apa yang Anda bahas sebelumnya dalam dialog tersebut. Anda menggunakan Foundry Local SDK untuk memilih model, menetapkan prompt sistem, dan mengalirkan respons secara berurutan satu per satu.
Dalam tutorial ini, Anda akan belajar cara:
- Menyiapkan proyek dan menginstal SDK Lokal Foundry
- Telusuri katalog model dan pilih model
- Menentukan permintaan sistem untuk membentuk perilaku asisten
- Menerapkan percakapan multi-giliran dengan riwayat pesan
- Memproses respons untuk pengalaman yang responsif
- Membersihkan sumber daya saat percakapan berakhir
Prasyarat
- Komputer Windows, macOS, atau Linux dengan RAM minimal 8 GB.
Repositori Penampung Sampel
Kode sampel lengkap untuk artikel ini tersedia di repositori GitHub foundry-samples. Untuk mengkloning repositori dan menavigasi ke penggunaan sampel:
git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/csharp/foundry-local/tutorial-chat-assistant
Memasang paket
Jika Anda mengembangkan atau mengirim di Windows, pilih tab Windows. Paket Windows terintegrasi dengan runtime Windows ML — ini menyediakan area permukaan API yang sama dengan luas akselerasi perangkat keras yang lebih luas.
dotnet add package Microsoft.AI.Foundry.Local.WinML
dotnet add package OpenAI
Sampel C# di repositori GitHub adalah proyek yang telah dikonfigurasi sebelumnya. Jika Anda membangun dari awal, Anda harus membaca referensi Foundry Local SDK untuk detail selengkapnya tentang cara menyiapkan proyek C# Anda dengan Foundry Local.
Telusuri katalog dan pilih model
Foundry Local SDK menyediakan katalog model yang mencantumkan semua model yang tersedia. Dalam langkah ini, Anda menginisialisasi SDK dan memilih model untuk asisten obrolan Anda.
Buka
Program.csdan ganti kontennya dengan kode berikut untuk menginisialisasi SDK dan pilih model: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(); // Select and load a model from the catalog var catalog = await mgr.GetCatalogAsync(); var model = await catalog.GetModelAsync("qwen2.5-0.5b") ?? throw new Exception("Model not found"); await model.DownloadAsync(progress => { Console.Write($"\rDownloading model: {progress:F2}%"); if (progress >= 100f) Console.WriteLine(); }); await model.LoadAsync(); Console.WriteLine("Model loaded and ready."); // Get a chat client var chatClient = await model.GetChatClientAsync();Metode
GetModelAsyncmenerima alias model, yaitu nama pendek yang mudah diingat dan mewakili model tertentu dalam katalog. Metode iniDownloadAsyncmengambil bobot model ke cache lokal Anda, danLoadAsyncmembuat model siap untuk inferensi.
Tentukan perintah sistem
Permintaan sistem mengatur kepribadian dan perilaku asisten. Ini adalah pesan pertama dalam riwayat percakapan dan model mereferensikannya di seluruh percakapan.
Tambahkan permintaan sistem untuk membentuk bagaimana asisten merespons:
// Start the conversation with a system prompt
var messages = new List<ChatMessage>
{
new ChatMessage
{
Role = "system",
Content = "You are a helpful, friendly assistant. Keep your responses " +
"concise and conversational. If you don't know something, say so."
}
};
Tip
Bereksperimenlah dengan permintaan sistem yang berbeda untuk mengubah perilaku asisten. Misalnya, Anda dapat menginstruksikannya untuk merespons sebagai bajak laut, guru, atau pakar domain.
Menerapkan percakapan bergiliran banyak
Asisten obrolan perlu mempertahankan konteks di beberapa pertukaran. Anda mencapai ini dengan menyimpan daftar semua pesan (sistem, pengguna, dan asisten) dan mengirim daftar lengkap dengan setiap permintaan. Model ini menggunakan riwayat ini untuk menghasilkan respons yang relevan secara kontekstual.
Tambahkan perulangan percakapan yang:
- Membaca input pengguna dari konsol.
- Menambahkan pesan pengguna ke riwayat.
- Mengirim riwayat lengkap ke model.
- Menambahkan respons asisten ke riwayat untuk putaran berikutnya.
while (true)
{
Console.Write("You: ");
var userInput = Console.ReadLine();
if (string.IsNullOrWhiteSpace(userInput) ||
userInput.Equals("quit", StringComparison.OrdinalIgnoreCase) ||
userInput.Equals("exit", StringComparison.OrdinalIgnoreCase))
{
break;
}
// Add the user's message to conversation history
messages.Add(new ChatMessage { Role = "user", Content = userInput });
// Stream the response token by token
Console.Write("Assistant: ");
var fullResponse = string.Empty;
var streamingResponse = chatClient.CompleteChatStreamingAsync(messages, ct);
await foreach (var chunk in streamingResponse)
{
var content = chunk.Choices[0].Message.Content;
if (!string.IsNullOrEmpty(content))
{
Console.Write(content);
Console.Out.Flush();
fullResponse += content;
}
}
Console.WriteLine("\n");
// Add the complete response to conversation history
messages.Add(new ChatMessage { Role = "assistant", Content = fullResponse });
}
Setiap panggilan untuk CompleteChatAsync menerima riwayat pesan lengkap. Inilah bagaimana model "mengingat" interaksi sebelumnya — model tersebut tidak menyimpan status di antara setiap panggilan.
Tambahkan respons streaming
Streaming mencetak setiap token saat dihasilkan, yang membuat asisten merasa lebih responsif. Ganti panggilan CompleteChatAsync dengan CompleteChatStreamingAsync untuk mengalirkan token respons secara token demi token.
Perbarui loop percakapan agar menggunakan streaming.
// Stream the response token by token
Console.Write("Assistant: ");
var fullResponse = string.Empty;
var streamingResponse = chatClient.CompleteChatStreamingAsync(messages, ct);
await foreach (var chunk in streamingResponse)
{
var content = chunk.Choices[0].Message.Content;
if (!string.IsNullOrEmpty(content))
{
Console.Write(content);
Console.Out.Flush();
fullResponse += content;
}
}
Console.WriteLine("\n");
Versi streaming mengakumulasi respons penuh sehingga dapat ditambahkan ke riwayat percakapan setelah streaming selesai.
Kode lengkap
Ganti konten Program.cs dengan kode lengkap berikut:
using Microsoft.AI.Foundry.Local;
using Betalgo.Ranul.OpenAI.ObjectModels.RequestModels;
using Microsoft.Extensions.Logging;
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();
// Select and load a model from the catalog
var catalog = await mgr.GetCatalogAsync();
var model = await catalog.GetModelAsync("qwen2.5-0.5b")
?? throw new Exception("Model not found");
await model.DownloadAsync(progress =>
{
Console.Write($"\rDownloading model: {progress:F2}%");
if (progress >= 100f) Console.WriteLine();
});
await model.LoadAsync();
Console.WriteLine("Model loaded and ready.");
// Get a chat client
var chatClient = await model.GetChatClientAsync();
// Start the conversation with a system prompt
var messages = new List<ChatMessage>
{
new ChatMessage
{
Role = "system",
Content = "You are a helpful, friendly assistant. Keep your responses " +
"concise and conversational. If you don't know something, say so."
}
};
Console.WriteLine("\nChat assistant ready! Type 'quit' to exit.\n");
while (true)
{
Console.Write("You: ");
var userInput = Console.ReadLine();
if (string.IsNullOrWhiteSpace(userInput) ||
userInput.Equals("quit", StringComparison.OrdinalIgnoreCase) ||
userInput.Equals("exit", StringComparison.OrdinalIgnoreCase))
{
break;
}
// Add the user's message to conversation history
messages.Add(new ChatMessage { Role = "user", Content = userInput });
// Stream the response token by token
Console.Write("Assistant: ");
var fullResponse = string.Empty;
var streamingResponse = chatClient.CompleteChatStreamingAsync(messages, ct);
await foreach (var chunk in streamingResponse)
{
var content = chunk.Choices[0].Message.Content;
if (!string.IsNullOrEmpty(content))
{
Console.Write(content);
Console.Out.Flush();
fullResponse += content;
}
}
Console.WriteLine("\n");
// Add the complete response to conversation history
messages.Add(new ChatMessage { Role = "assistant", Content = fullResponse });
}
// Clean up - unload the model
await model.UnloadAsync();
Console.WriteLine("Model unloaded. Goodbye!");
Jalankan asisten obrolan:
dotnet run
Anda melihat output yang mirip dengan:
Downloading model: 100.00%
Model loaded and ready.
Chat assistant ready! Type 'quit' to exit.
You: What is photosynthesis?
Assistant: Photosynthesis is the process plants use to convert sunlight, water, and carbon
dioxide into glucose and oxygen. It mainly happens in the leaves, inside structures
called chloroplasts.
You: Why is it important for other living things?
Assistant: It's essential because photosynthesis produces the oxygen that most living things
breathe. It also forms the base of the food chain — animals eat plants or eat other
animals that depend on plants for energy.
You: quit
Model unloaded. Goodbye!
Perhatikan bagaimana asisten mengingat konteks dari giliran sebelumnya - ketika Anda bertanya "Mengapa penting untuk makhluk hidup lainnya?", itu tahu Anda masih berbicara tentang fotosintesis.
Repositori Penampung Sampel
Kode sampel lengkap untuk artikel ini tersedia di repositori GitHub foundry-samples. Untuk mengkloning repositori dan menavigasi ke penggunaan sampel:
git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/javascript/foundry-local/tutorial-chat-assistant
Memasang paket
Jika Anda mengembangkan atau mengirim di Windows, pilih tab Windows. Paket Windows terintegrasi dengan runtime Windows ML — ini menyediakan area permukaan API yang sama dengan luas akselerasi perangkat keras yang lebih luas.
npm install foundry-local-sdk-winml openai
Telusuri katalog dan pilih model
Foundry Local SDK menyediakan katalog model yang mencantumkan semua model yang tersedia. Dalam langkah ini, Anda menginisialisasi SDK dan memilih model untuk asisten obrolan Anda.
Buat file yang disebut
index.js.Tambahkan kode berikut untuk menginisialisasi SDK dan pilih model:
// 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'); // Select and load a model from the catalog const model = await manager.catalog.getModel('qwen2.5-0.5b'); await model.download((progress) => { process.stdout.write(`\rDownloading model: ${progress.toFixed(2)}%`); }); console.log('\nModel downloaded.'); await model.load(); console.log('Model loaded and ready.'); // Create a chat client const chatClient = model.createChatClient();Metode
getModelmenerima alias model, yaitu nama pendek yang mudah diingat dan mewakili model tertentu dalam katalog. Metode inidownloadmengambil bobot model ke cache lokal Anda, danloadmembuat model siap untuk inferensi.
Tentukan perintah sistem
Permintaan sistem mengatur kepribadian dan perilaku asisten. Ini adalah pesan pertama dalam riwayat percakapan dan model mereferensikannya di seluruh percakapan.
Tambahkan permintaan sistem untuk membentuk bagaimana asisten merespons:
// Start the conversation with a system prompt
const messages = [
{
role: 'system',
content: 'You are a helpful, friendly assistant. Keep your responses ' +
'concise and conversational. If you don\'t know something, say so.'
}
];
Tip
Bereksperimenlah dengan permintaan sistem yang berbeda untuk mengubah perilaku asisten. Misalnya, Anda dapat menginstruksikannya untuk merespons sebagai bajak laut, guru, atau pakar domain.
Menerapkan percakapan bergiliran banyak
Asisten obrolan perlu mempertahankan konteks di beberapa pertukaran. Anda mencapai ini dengan menyimpan daftar semua pesan (sistem, pengguna, dan asisten) dan mengirim daftar lengkap dengan setiap permintaan. Model ini menggunakan riwayat ini untuk menghasilkan respons yang relevan secara kontekstual.
Tambahkan perulangan percakapan yang:
- Membaca input pengguna dari konsol.
- Menambahkan pesan pengguna ke riwayat.
- Mengirim riwayat lengkap ke model.
- Menambahkan respons asisten ke riwayat untuk putaran berikutnya.
while (true) {
const userInput = await askQuestion('You: ');
if (userInput.trim().toLowerCase() === 'quit' ||
userInput.trim().toLowerCase() === 'exit') {
break;
}
// Add the user's message to conversation history
messages.push({ role: 'user', content: userInput });
// Stream the response token by token
process.stdout.write('Assistant: ');
let fullResponse = '';
for await (const chunk of chatClient.completeStreamingChat(messages)) {
const content = chunk.choices?.[0]?.delta?.content;
if (content) {
process.stdout.write(content);
fullResponse += content;
}
}
console.log('\n');
// Add the complete response to conversation history
messages.push({ role: 'assistant', content: fullResponse });
}
Setiap panggilan untuk completeChat menerima riwayat pesan lengkap. Inilah bagaimana model "mengingat" interaksi sebelumnya — model tersebut tidak menyimpan status di antara setiap panggilan.
Tambahkan respons streaming
Streaming mencetak setiap token saat dihasilkan, yang membuat asisten merasa lebih responsif. Ganti panggilan completeChat dengan completeStreamingChat untuk mengalirkan token respons secara token demi token.
Perbarui loop percakapan agar menggunakan streaming.
// Stream the response token by token
process.stdout.write('Assistant: ');
let fullResponse = '';
for await (const chunk of chatClient.completeStreamingChat(messages)) {
const content = chunk.choices?.[0]?.delta?.content;
if (content) {
process.stdout.write(content);
fullResponse += content;
}
}
console.log('\n');
Versi streaming mengakumulasi respons penuh sehingga dapat ditambahkan ke riwayat percakapan setelah streaming selesai.
Kode lengkap
Buat file bernama index.js dan tambahkan kode lengkap berikut:
import { FoundryLocalManager } from 'foundry-local-sdk';
import * as readline from 'readline';
// 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');
// Select and load a model from the catalog
const model = await manager.catalog.getModel('qwen2.5-0.5b');
await model.download((progress) => {
process.stdout.write(`\rDownloading model: ${progress.toFixed(2)}%`);
});
console.log('\nModel downloaded.');
await model.load();
console.log('Model loaded and ready.');
// Create a chat client
const chatClient = model.createChatClient();
// Start the conversation with a system prompt
const messages = [
{
role: 'system',
content: 'You are a helpful, friendly assistant. Keep your responses ' +
'concise and conversational. If you don\'t know something, say so.'
}
];
// Set up readline for console input
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const askQuestion = (prompt) => new Promise((resolve) => {
if (rl.closed) return resolve('quit');
const onClose = () => resolve('quit');
rl.once('close', onClose);
try {
rl.question(prompt, (answer) => {
rl.off('close', onClose);
resolve(answer);
});
} catch {
rl.off('close', onClose);
resolve('quit');
}
});
console.log('\nChat assistant ready! Type \'quit\' to exit.\n');
while (true) {
const userInput = await askQuestion('You: ');
if (userInput.trim().toLowerCase() === 'quit' ||
userInput.trim().toLowerCase() === 'exit') {
break;
}
// Add the user's message to conversation history
messages.push({ role: 'user', content: userInput });
// Stream the response token by token
process.stdout.write('Assistant: ');
let fullResponse = '';
for await (const chunk of chatClient.completeStreamingChat(messages)) {
const content = chunk.choices?.[0]?.delta?.content;
if (content) {
process.stdout.write(content);
fullResponse += content;
}
}
console.log('\n');
// Add the complete response to conversation history
messages.push({ role: 'assistant', content: fullResponse });
}
// Clean up - unload the model
await model.unload();
console.log('Model unloaded. Goodbye!');
rl.close();
Jalankan asisten obrolan:
node index.js
Anda melihat output yang mirip dengan:
Downloading model: 100.00%
Model downloaded.
Model loaded and ready.
Chat assistant ready! Type 'quit' to exit.
You: What is photosynthesis?
Assistant: Photosynthesis is the process plants use to convert sunlight, water, and carbon
dioxide into glucose and oxygen. It mainly happens in the leaves, inside structures
called chloroplasts.
You: Why is it important for other living things?
Assistant: It's essential because photosynthesis produces the oxygen that most living things
breathe. It also forms the base of the food chain — animals eat plants or eat other
animals that depend on plants for energy.
You: quit
Model unloaded. Goodbye!
Perhatikan bagaimana asisten mengingat konteks dari giliran sebelumnya - ketika Anda bertanya "Mengapa penting untuk makhluk hidup lainnya?", itu tahu Anda masih berbicara tentang fotosintesis.
Repositori Penampung Sampel
Kode sampel lengkap untuk artikel ini tersedia di repositori GitHub foundry-samples. Untuk mengkloning repositori dan menavigasi ke penggunaan sampel:
git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/python/foundry-local/tutorial-chat-assistant
Memasang paket
Jika Anda mengembangkan atau mengirim di Windows, pilih tab Windows. Paket Windows terintegrasi dengan runtime Windows ML — ini menyediakan area permukaan API yang sama dengan luas akselerasi perangkat keras yang lebih luas.
pip install foundry-local-sdk-winml openai
Telusuri katalog dan pilih model
Foundry Local SDK menyediakan katalog model yang mencantumkan semua model yang tersedia. Dalam langkah ini, Anda menginisialisasi SDK dan memilih model untuk asisten obrolan Anda.
Buat file yang disebut
main.py.Tambahkan kode berikut untuk menginisialisasi SDK dan pilih model:
# 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() # Select and load a model from the catalog model = manager.catalog.get_model("qwen2.5-0.5b") model.download( lambda progress: print( f"\rDownloading model: {progress:.2f}%", end="", flush=True ) ) print() model.load() print("Model loaded and ready.") # Get a chat client client = model.get_chat_client()Metode
get_modelmenerima alias model, yaitu nama pendek yang mudah diingat dan mewakili model tertentu dalam katalog. Metode inidownloadmengambil bobot model ke cache lokal Anda, danloadmembuat model siap untuk inferensi.
Tentukan perintah sistem
Permintaan sistem mengatur kepribadian dan perilaku asisten. Ini adalah pesan pertama dalam riwayat percakapan dan model mereferensikannya di seluruh percakapan.
Tambahkan permintaan sistem untuk membentuk bagaimana asisten merespons:
# Start the conversation with a system prompt
messages = [
{
"role": "system",
"content": "You are a helpful, friendly assistant. Keep your responses "
"concise and conversational. If you don't know something, say so.",
}
]
Tip
Bereksperimenlah dengan permintaan sistem yang berbeda untuk mengubah perilaku asisten. Misalnya, Anda dapat menginstruksikannya untuk merespons sebagai bajak laut, guru, atau pakar domain.
Menerapkan percakapan bergiliran banyak
Asisten obrolan perlu mempertahankan konteks di beberapa pertukaran. Anda mencapai ini dengan menyimpan daftar semua pesan (sistem, pengguna, dan asisten) dan mengirim daftar lengkap dengan setiap permintaan. Model ini menggunakan riwayat ini untuk menghasilkan respons yang relevan secara kontekstual.
Tambahkan perulangan percakapan yang:
- Membaca input pengguna dari konsol.
- Menambahkan pesan pengguna ke riwayat.
- Mengirim riwayat lengkap ke model.
- Menambahkan respons asisten ke riwayat untuk putaran berikutnya.
while True:
user_input = input("You: ")
if user_input.strip().lower() in ("quit", "exit"):
break
# Add the user's message to conversation history
messages.append({"role": "user", "content": user_input})
# Stream the response token by token
print("Assistant: ", end="", flush=True)
full_response = ""
for chunk in client.complete_streaming_chat(messages):
if not chunk.choices:
continue
content = chunk.choices[0].delta.content
if content:
print(content, end="", flush=True)
full_response += content
print("\n")
# Add the complete response to conversation history
messages.append({"role": "assistant", "content": full_response})
Setiap panggilan untuk complete_chat menerima riwayat pesan lengkap. Inilah bagaimana model "mengingat" interaksi sebelumnya — model tersebut tidak menyimpan status di antara setiap panggilan.
Tambahkan respons streaming
Streaming mencetak setiap token saat dihasilkan, yang membuat asisten merasa lebih responsif. Ganti panggilan complete_chat dengan complete_streaming_chat untuk mengalirkan token respons secara token demi token.
Perbarui loop percakapan agar menggunakan streaming.
# Stream the response token by token
print("Assistant: ", end="", flush=True)
full_response = ""
for chunk in client.complete_streaming_chat(messages):
if not chunk.choices:
continue
content = chunk.choices[0].delta.content
if content:
print(content, end="", flush=True)
full_response += content
print("\n")
Versi streaming mengakumulasi respons penuh sehingga dapat ditambahkan ke riwayat percakapan setelah streaming selesai.
Kode lengkap
Buat file bernama main.py dan tambahkan kode lengkap berikut:
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()
# Select and load a model from the catalog
model = manager.catalog.get_model("qwen2.5-0.5b")
model.download(
lambda progress: print(
f"\rDownloading model: {progress:.2f}%", end="", flush=True
)
)
print()
model.load()
print("Model loaded and ready.")
# Get a chat client
client = model.get_chat_client()
# Start the conversation with a system prompt
messages = [
{
"role": "system",
"content": "You are a helpful, friendly assistant. Keep your responses "
"concise and conversational. If you don't know something, say so.",
}
]
print("\nChat assistant ready! Type 'quit' to exit.\n")
while True:
user_input = input("You: ")
if user_input.strip().lower() in ("quit", "exit"):
break
# Add the user's message to conversation history
messages.append({"role": "user", "content": user_input})
# Stream the response token by token
print("Assistant: ", end="", flush=True)
full_response = ""
for chunk in client.complete_streaming_chat(messages):
if not chunk.choices:
continue
content = chunk.choices[0].delta.content
if content:
print(content, end="", flush=True)
full_response += content
print("\n")
# Add the complete response to conversation history
messages.append({"role": "assistant", "content": full_response})
# Clean up - unload the model
model.unload()
print("Model unloaded. Goodbye!")
if __name__ == "__main__":
main()
Jalankan asisten obrolan:
python main.py
Anda melihat output yang mirip dengan:
Downloading model: 100.00%
Model loaded and ready.
Chat assistant ready! Type 'quit' to exit.
You: What is photosynthesis?
Assistant: Photosynthesis is the process plants use to convert sunlight, water, and carbon
dioxide into glucose and oxygen. It mainly happens in the leaves, inside structures
called chloroplasts.
You: Why is it important for other living things?
Assistant: It's essential because photosynthesis produces the oxygen that most living things
breathe. It also forms the base of the food chain — animals eat plants or eat other
animals that depend on plants for energy.
You: quit
Model unloaded. Goodbye!
Perhatikan bagaimana asisten mengingat konteks dari giliran sebelumnya - ketika Anda bertanya "Mengapa penting untuk makhluk hidup lainnya?", itu tahu Anda masih berbicara tentang fotosintesis.
Repositori Penampung Sampel
Kode sampel lengkap untuk artikel ini tersedia di repositori GitHub foundry-samples. Untuk mengkloning repositori dan menavigasi ke penggunaan sampel:
git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/rust/foundry-local/tutorial-chat-assistant
Memasang paket
Jika Anda mengembangkan atau mengirim di Windows, pilih tab Windows. Paket Windows terintegrasi dengan runtime Windows ML — ini menyediakan area permukaan API yang sama dengan luas akselerasi perangkat keras yang lebih luas.
cargo add foundry-local-sdk --features winml
cargo add tokio --features full
cargo add tokio-stream anyhow
Telusuri katalog dan pilih model
Foundry Local SDK menyediakan katalog model yang mencantumkan semua model yang tersedia. Dalam langkah ini, Anda menginisialisasi SDK dan memilih model untuk asisten obrolan Anda.
Buka
src/main.rsdan ganti kontennya dengan kode berikut untuk menginisialisasi SDK dan pilih model:// 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!(); // Select and load a model from the catalog let model = manager.catalog().get_model("qwen2.5-0.5b").await?; if !model.is_cached().await? { println!("Downloading model..."); model .download(Some(|progress: f64| { print!("\r {progress:.1}%"); io::stdout().flush().ok(); })) .await?; println!(); } model.load().await?; println!("Model loaded and ready."); // Create a chat client let client = model.create_chat_client().temperature(0.7).max_tokens(512);Metode
get_modelmenerima alias model, yaitu nama pendek yang mudah diingat dan mewakili model tertentu dalam katalog. Metode inidownloadmengambil bobot model ke cache lokal Anda, danloadmembuat model siap untuk inferensi.
Tentukan perintah sistem
Permintaan sistem mengatur kepribadian dan perilaku asisten. Ini adalah pesan pertama dalam riwayat percakapan dan model mereferensikannya di seluruh percakapan.
Tambahkan permintaan sistem untuk membentuk bagaimana asisten merespons:
// Start the conversation with a system prompt
let mut messages: Vec<ChatCompletionRequestMessage> = vec![
ChatCompletionRequestSystemMessage::from(
"You are a helpful, friendly assistant. Keep your responses \
concise and conversational. If you don't know something, say so.",
)
.into(),
];
Tip
Bereksperimenlah dengan permintaan sistem yang berbeda untuk mengubah perilaku asisten. Misalnya, Anda dapat menginstruksikannya untuk merespons sebagai bajak laut, guru, atau pakar domain.
Menerapkan percakapan bergiliran banyak
Asisten obrolan perlu mempertahankan konteks di beberapa pertukaran. Anda mencapai ini dengan menyimpan vektor semua pesan (sistem, pengguna, dan asisten) dan mengirim daftar lengkap dengan setiap permintaan. Model ini menggunakan riwayat ini untuk menghasilkan respons yang relevan secara kontekstual.
Tambahkan perulangan percakapan yang:
- Membaca input pengguna dari konsol.
- Menambahkan pesan pengguna ke riwayat.
- Mengirim riwayat lengkap ke model.
- Menambahkan respons asisten ke riwayat untuk putaran berikutnya.
loop {
print!("You: ");
io::stdout().flush()?;
let mut input = String::new();
stdin.lock().read_line(&mut input)?;
let input = input.trim();
if input.eq_ignore_ascii_case("quit") || input.eq_ignore_ascii_case("exit") {
break;
}
// Add the user's message to conversation history
messages.push(ChatCompletionRequestUserMessage::from(input).into());
// Stream the response token by token
print!("Assistant: ");
io::stdout().flush()?;
let mut full_response = String::new();
let mut stream = client.complete_streaming_chat(&messages, None).await?;
while let Some(chunk) = stream.next().await {
let chunk = chunk?;
if let Some(choice) = chunk.choices.first() {
if let Some(ref content) = choice.delta.content {
print!("{content}");
io::stdout().flush()?;
full_response.push_str(content);
}
}
}
println!("\n");
// Add the complete response to conversation history
let assistant_msg: ChatCompletionRequestMessage = serde_json::from_value(
serde_json::json!({"role": "assistant", "content": full_response}),
)?;
messages.push(assistant_msg);
}
Setiap panggilan untuk complete_chat menerima riwayat pesan lengkap. Inilah bagaimana model "mengingat" interaksi sebelumnya — model tersebut tidak menyimpan status di antara setiap panggilan.
Tambahkan respons streaming
Streaming mencetak setiap token saat dihasilkan, yang membuat asisten merasa lebih responsif. Ganti panggilan complete_chat dengan complete_streaming_chat untuk mengalirkan token respons secara token demi token.
Perbarui loop percakapan agar menggunakan streaming.
// Stream the response token by token
print!("Assistant: ");
io::stdout().flush()?;
let mut full_response = String::new();
let mut stream = client.complete_streaming_chat(&messages, None).await?;
while let Some(chunk) = stream.next().await {
let chunk = chunk?;
if let Some(choice) = chunk.choices.first() {
if let Some(ref content) = choice.delta.content {
print!("{content}");
io::stdout().flush()?;
full_response.push_str(content);
}
}
}
println!("\n");
Versi streaming mengakumulasi respons penuh sehingga dapat ditambahkan ke riwayat percakapan setelah streaming selesai.
Kode lengkap
Ganti konten src/main.rs dengan kode lengkap berikut:
use foundry_local_sdk::{
ChatCompletionRequestMessage,
ChatCompletionRequestSystemMessage, ChatCompletionRequestUserMessage,
FoundryLocalConfig, FoundryLocalManager,
};
use std::io::{self, BufRead, Write};
use tokio_stream::StreamExt;
#[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!();
// Select and load a model from the catalog
let model = manager.catalog().get_model("qwen2.5-0.5b").await?;
if !model.is_cached().await? {
println!("Downloading model...");
model
.download(Some(|progress: f64| {
print!("\r {progress:.1}%");
io::stdout().flush().ok();
}))
.await?;
println!();
}
model.load().await?;
println!("Model loaded and ready.");
// Create a chat client
let client = model.create_chat_client().temperature(0.7).max_tokens(512);
// Start the conversation with a system prompt
let mut messages: Vec<ChatCompletionRequestMessage> = vec![
ChatCompletionRequestSystemMessage::from(
"You are a helpful, friendly assistant. Keep your responses \
concise and conversational. If you don't know something, say so.",
)
.into(),
];
println!("\nChat assistant ready! Type 'quit' to exit.\n");
let stdin = io::stdin();
loop {
print!("You: ");
io::stdout().flush()?;
let mut input = String::new();
stdin.lock().read_line(&mut input)?;
let input = input.trim();
if input.eq_ignore_ascii_case("quit") || input.eq_ignore_ascii_case("exit") {
break;
}
// Add the user's message to conversation history
messages.push(ChatCompletionRequestUserMessage::from(input).into());
// Stream the response token by token
print!("Assistant: ");
io::stdout().flush()?;
let mut full_response = String::new();
let mut stream = client.complete_streaming_chat(&messages, None).await?;
while let Some(chunk) = stream.next().await {
let chunk = chunk?;
if let Some(choice) = chunk.choices.first() {
if let Some(ref content) = choice.delta.content {
print!("{content}");
io::stdout().flush()?;
full_response.push_str(content);
}
}
}
println!("\n");
// Add the complete response to conversation history
let assistant_msg: ChatCompletionRequestMessage = serde_json::from_value(
serde_json::json!({"role": "assistant", "content": full_response}),
)?;
messages.push(assistant_msg);
}
// Clean up - unload the model
model.unload().await?;
println!("Model unloaded. Goodbye!");
Ok(())
}
Jalankan asisten obrolan:
cargo run
Anda melihat output yang mirip dengan:
Downloading model: 100.00%
Model loaded and ready.
Chat assistant ready! Type 'quit' to exit.
You: What is photosynthesis?
Assistant: Photosynthesis is the process plants use to convert sunlight, water, and carbon
dioxide into glucose and oxygen. It mainly happens in the leaves, inside structures
called chloroplasts.
You: Why is it important for other living things?
Assistant: It's essential because photosynthesis produces the oxygen that most living things
breathe. It also forms the base of the food chain — animals eat plants or eat other
animals that depend on plants for energy.
You: quit
Model unloaded. Goodbye!
Perhatikan bagaimana asisten mengingat konteks dari giliran sebelumnya - ketika Anda bertanya "Mengapa penting untuk makhluk hidup lainnya?", itu tahu Anda masih berbicara tentang fotosintesis.
Membersihkan sumber daya
Bobot model akan tetap berada di cache lokal Anda setelah Anda menghapus model. Ini berarti lain kali Anda menjalankan aplikasi, langkah unduhan dilewati dan model dimuat lebih cepat. Tidak diperlukan pembersihan tambahan kecuali Anda ingin mengklaim kembali ruang disk.