Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
V tomto kurzu vytvoříte interaktivního chatovacího asistenta, který běží zcela na vašem zařízení. Asistent udržuje kontext konverzace napříč několika výměnami, takže si pamatuje, co jste probírali dříve v konverzaci. Pomocí sady Foundry Local SDK můžete vybrat model, definovat systémový prompt a streamovat odpovědi token po tokenu.
V tomto návodu se naučíte, jak:
- Nastavení projektu a instalace místní sady SDK Foundry
- Procházení katalogu modelů a výběr modelu
- Definujte systémový požadavek k formování chování asistenta
- Implementace vícekrokové konverzace s historií zpráv
- Odpovědi streamu pro responzivní prostředí
- Uvolněte prostředky po ukončení konverzace
Předpoklady
- Počítač s Windows, macOS nebo Linuxem s minimálně 8 GB paměti RAM.
Ú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/csharp/foundry-local/tutorial-chat-assistant
Instalace balíčků
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.
Procházení katalogu a výběr modelu
Sada Foundry Local SDK poskytuje katalog modelů, který obsahuje seznam všech dostupných modelů. V tomto kroku inicializujete sadu SDK a vyberete model pro chatovacího asistenta.
Otevřete
Program.csa nahraďte jeho obsah následujícím kódem, který inicializuje sadu SDK a vybere 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();Metoda
GetModelAsyncpřijímá alias modelu, což je krátký přátelský název, který odpovídá konkrétnímu modelu v katalogu. MetodaDownloadAsyncnačte váhy modelu do místní mezipaměti aLoadAsyncpřipraví model k odvozování.
Definování systémové výzvy
Systémová výzva nastaví osobnost a chování asistenta. Jedná se o první zprávu v historii konverzací a model ji odkazuje v celé konverzaci.
Přidejte systémovou výzvu k tvarování způsobu reakce asistenta:
// 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."
}
};
Návod
Experimentujte s různými výzvami systému ke změně chování asistenta. Můžete například dát pokyn, aby odpověděl jako pirát, učitel nebo odborník na doménu.
Implementace vícekrokové konverzace
Chatovací asistent musí udržovat kontext napříč několika výměnami. Toho dosáhnete tak, že si necháte seznam všech zpráv (systém, uživatel a asistent) a odešlete úplný seznam s každou žádostí. Model používá tuto historii ke generování kontextově relevantních odpovědí.
Přidejte smyčku dialogu, která:
- Načte uživatelský vstup z konzoly.
- Připojí zprávu uživatele k historii.
- Odešle do modelu úplnou historii.
- Připojí odpověď asistenta k historii dalšího turnu.
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 });
}
Každé volání CompleteChatAsync obdrží celou historii zpráv. Takto si model pamatuje předchozí dialogy – neukládá stav mezi vyvoláními.
Přidat streamované odpovědi
Streamování vypisuje každý token při jeho generování, čímž je asistent vnímán jako pohotovější. Nahraďte volání CompleteChatAsync voláním CompleteChatStreamingAsync, abyste mohli streamovat odpověď po jednotlivých tokenech.
Aktualizujte smyčku konverzace tak, aby používala streamování:
// 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");
Verze streamování shromažďuje úplnou odpověď, aby se po dokončení streamu přidala do historie konverzací.
Kompletní kód
Nahraďte obsah Program.cs následujícím úplným kódem:
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!");
Spusťte chatovacího asistenta:
dotnet run
Zobrazí se výstup podobný následujícímu:
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!
Všimněte si, jak si asistent pamatuje kontext z předchozích kroků – když se zeptáte "Proč je důležité pro ostatní živé věci?", ví, že pořád mluvíte o fotosyntéze.
Ú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-chat-assistant
Instalace balíčků
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
Procházení katalogu a výběr modelu
Sada Foundry Local SDK poskytuje katalog modelů, který obsahuje seznam všech dostupných modelů. V tomto kroku inicializujete sadu SDK a vyberete model pro chatovacího asistenta.
Vytvořte soubor s názvem
index.js.Přidejte následující kód pro inicializaci sady SDK a vyberte 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();Metoda
getModelpřijímá alias modelu, což je krátký přátelský název, který odpovídá konkrétnímu modelu v katalogu. Metodadownloadnačte váhy modelu do místní mezipaměti aloadpřipraví model k odvozování.
Definování systémové výzvy
Systémová výzva nastaví osobnost a chování asistenta. Jedná se o první zprávu v historii konverzací a model ji odkazuje v celé konverzaci.
Přidejte systémovou výzvu k tvarování způsobu reakce asistenta:
// 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.'
}
];
Návod
Experimentujte s různými výzvami systému ke změně chování asistenta. Můžete například dát pokyn, aby odpověděl jako pirát, učitel nebo odborník na doménu.
Implementace vícekrokové konverzace
Chatovací asistent musí udržovat kontext napříč několika výměnami. Toho dosáhnete tak, že si necháte seznam všech zpráv (systém, uživatel a asistent) a odešlete úplný seznam s každou žádostí. Model používá tuto historii ke generování kontextově relevantních odpovědí.
Přidejte smyčku dialogu, která:
- Načte uživatelský vstup z konzoly.
- Připojí zprávu uživatele k historii.
- Odešle do modelu úplnou historii.
- Připojí odpověď asistenta k historii dalšího turnu.
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 });
}
Každé volání completeChat obdrží celou historii zpráv. Takto si model pamatuje předchozí dialogy – neukládá stav mezi vyvoláními.
Přidat streamované odpovědi
Streamování vypisuje každý token při jeho generování, čímž je asistent vnímán jako pohotovější. Nahraďte volání completeChat voláním completeStreamingChat, abyste mohli streamovat odpověď po jednotlivých tokenech.
Aktualizujte smyčku konverzace tak, aby používala streamování:
// 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');
Verze streamování shromažďuje úplnou odpověď, aby se po dokončení streamu přidala do historie konverzací.
Kompletní kód
Vytvořte soubor s názvem index.js a přidejte následující úplný kód:
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();
Spusťte chatovacího asistenta:
node index.js
Zobrazí se výstup podobný následujícímu:
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!
Všimněte si, jak si asistent pamatuje kontext z předchozích kroků – když se zeptáte "Proč je důležité pro ostatní živé věci?", ví, že pořád mluvíte o fotosyntéze.
Ú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-chat-assistant
Instalace balíčků
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
Procházení katalogu a výběr modelu
Sada Foundry Local SDK poskytuje katalog modelů, který obsahuje seznam všech dostupných modelů. V tomto kroku inicializujete sadu SDK a vyberete model pro chatovacího asistenta.
Vytvořte soubor s názvem
main.py.Přidejte následující kód pro inicializaci sady SDK a vyberte 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()Metoda
get_modelpřijímá alias modelu, což je krátký přátelský název, který odpovídá konkrétnímu modelu v katalogu. Metodadownloadnačte váhy modelu do místní mezipaměti aloadpřipraví model k odvozování.
Definování systémové výzvy
Systémová výzva nastaví osobnost a chování asistenta. Jedná se o první zprávu v historii konverzací a model ji odkazuje v celé konverzaci.
Přidejte systémovou výzvu k tvarování způsobu reakce asistenta:
# 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.",
}
]
Návod
Experimentujte s různými výzvami systému ke změně chování asistenta. Můžete například dát pokyn, aby odpověděl jako pirát, učitel nebo odborník na doménu.
Implementace vícekrokové konverzace
Chatovací asistent musí udržovat kontext napříč několika výměnami. Toho dosáhnete tak, že si necháte seznam všech zpráv (systém, uživatel a asistent) a odešlete úplný seznam s každou žádostí. Model používá tuto historii ke generování kontextově relevantních odpovědí.
Přidejte smyčku dialogu, která:
- Načte uživatelský vstup z konzoly.
- Připojí zprávu uživatele k historii.
- Odešle do modelu úplnou historii.
- Připojí odpověď asistenta k historii dalšího turnu.
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})
Každé volání complete_chat obdrží celou historii zpráv. Takto si model pamatuje předchozí dialogy – neukládá stav mezi vyvoláními.
Přidat streamované odpovědi
Streamování vypisuje každý token při jeho generování, čímž je asistent vnímán jako pohotovější. Nahraďte volání complete_chat voláním complete_streaming_chat, abyste mohli streamovat odpověď po jednotlivých tokenech.
Aktualizujte smyčku konverzace tak, aby používala streamování:
# 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")
Verze streamování shromažďuje úplnou odpověď, aby se po dokončení streamu přidala do historie konverzací.
Kompletní kód
Vytvořte soubor s názvem main.py a přidejte následující úplný kód:
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()
Spusťte chatovacího asistenta:
python main.py
Zobrazí se výstup podobný následujícímu:
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!
Všimněte si, jak si asistent pamatuje kontext z předchozích kroků – když se zeptáte "Proč je důležité pro ostatní živé věci?", ví, že pořád mluvíte o fotosyntéze.
Ú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-chat-assistant
Instalace balíčků
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
Procházení katalogu a výběr modelu
Sada Foundry Local SDK poskytuje katalog modelů, který obsahuje seznam všech dostupných modelů. V tomto kroku inicializujete sadu SDK a vyberete model pro chatovacího asistenta.
Otevřete
src/main.rsa nahraďte jeho obsah následujícím kódem, který inicializuje sadu SDK a vybere 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);Metoda
get_modelpřijímá alias modelu, což je krátký přátelský název, který odpovídá konkrétnímu modelu v katalogu. Metodadownloadnačte váhy modelu do místní mezipaměti aloadpřipraví model k odvozování.
Definování systémové výzvy
Systémová výzva nastaví osobnost a chování asistenta. Jedná se o první zprávu v historii konverzací a model ji odkazuje v celé konverzaci.
Přidejte systémovou výzvu k tvarování způsobu reakce asistenta:
// 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(),
];
Návod
Experimentujte s různými výzvami systému ke změně chování asistenta. Můžete například dát pokyn, aby odpověděl jako pirát, učitel nebo odborník na doménu.
Implementace vícekrokové konverzace
Chatovací asistent musí udržovat kontext napříč několika výměnami. Toho dosáhnete tak, že zachováte vektor všech zpráv (systém, uživatel a asistent) a odešlete úplný seznam s každou žádostí. Model používá tuto historii ke generování kontextově relevantních odpovědí.
Přidejte smyčku dialogu, která:
- Načte uživatelský vstup z konzoly.
- Připojí zprávu uživatele k historii.
- Odešle do modelu úplnou historii.
- Připojí odpověď asistenta k historii dalšího turnu.
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);
}
Každé volání complete_chat obdrží celou historii zpráv. Takto si model pamatuje předchozí dialogy – neukládá stav mezi vyvoláními.
Přidat streamované odpovědi
Streamování vypisuje každý token při jeho generování, čímž je asistent vnímán jako pohotovější. Nahraďte volání complete_chat voláním complete_streaming_chat, abyste mohli streamovat odpověď po jednotlivých tokenech.
Aktualizujte smyčku konverzace tak, aby používala streamování:
// 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");
Verze streamování shromažďuje úplnou odpověď, aby se po dokončení streamu přidala do historie konverzací.
Kompletní kód
Nahraďte obsah src/main.rs následujícím úplným kódem:
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(())
}
Spusťte chatovacího asistenta:
cargo run
Zobrazí se výstup podobný následujícímu:
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!
Všimněte si, jak si asistent pamatuje kontext z předchozích kroků – když se zeptáte "Proč je důležité pro ostatní živé věci?", ví, že pořád mluvíte o fotosyntéze.
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í.