Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In deze zelfstudie bouwt u een interactieve chatassistent die volledig op uw apparaat wordt uitgevoerd. De assistent behoudt de gesprekscontext over meerdere uitwisselingen, waardoor het onthoudt wat u eerder hebt besproken in het gesprek. U gebruikt de Foundry Local SDK om een model te kiezen, een systeemprompt op te stellen en antwoorden per token te streamen.
In deze handleiding leer je hoe je:
- Een project instellen en de Foundry Local SDK installeren
- Blader door de modelcatalogus en selecteer een model
- Een systeemprompt definiëren om het gedrag van de assistent vorm te geven
- Implementeer een meertrapsgesprek met berichtgeschiedenis
- Reacties streamen voor een responsieve ervaring
- Resources opruimen wanneer de sessie afloopt
Vereiste voorwaarden
- Een Windows-, macOS- of Linux-computer met ten minste 8 GB RAM-geheugen.
Opslagplaats met voorbeelden
De volledige voorbeeldcode voor dit artikel is beschikbaar in de opslagplaats Foundry Local GitHub. Om de opslagplaats te klonen en naar het voorbeeld te navigeren, gebruikt u:
git clone https://github.com/microsoft/Foundry-Local.git
cd Foundry-Local/samples/cs/tutorial-chat-assistant
Pakketten installeren
Als u op Windows ontwikkelt of verzendt, selecteert u het tabblad Windows. Het Windows-pakket kan worden geïntegreerd met de Windows ML runtime. Het biedt hetzelfde API-oppervlak met een grotere breedte van hardwareversnelling.
dotnet add package Microsoft.AI.Foundry.Local.WinML
dotnet add package OpenAI
De C#-voorbeelden in de GitHub opslagplaats zijn vooraf geconfigureerde projecten. Als u helemaal opnieuw bouwt, leest u de referentie voor de Local SDK van Foundry voor meer informatie over het instellen van uw C#-project met Foundry Local.
Door de catalogus bladeren en een model selecteren
De Foundry Local SDK biedt een modelcatalogus met alle beschikbare modellen. In deze stap initialiseert u de SDK en selecteert u een model voor uw chatassistent.
Open
Program.csde inhoud en vervang deze door de volgende code om de SDK te initialiseren en een model te selecteren: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();De
GetModelAsyncmethode accepteert een modelalias, een korte beschrijvende naam die wordt toegewezen aan een specifiek model in de catalogus. DeDownloadAsyncmethode haalt de modelgewichten op in uw lokale cache enLoadAsyncmaakt het model gereed voor deductie.
Een systeemprompt definiëren
Een systeemprompt stelt de persoonlijkheid en het gedrag van de assistent in. Het is het eerste bericht in de gespreksgeschiedenis en het model verwijst ernaar tijdens het gesprek.
Voeg een systeemprompt toe om vorm te geven aan hoe de assistent reageert:
// 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."
}
};
Aanbeveling
Experimenteer met verschillende systeemprompts om het gedrag van de assistent te wijzigen. U kunt het bijvoorbeeld instrueren om te reageren als piraat, docent of domeinexpert.
Een conversatie met meerdere beurten implementeren
Een chatassistent moet context onderhouden tussen meerdere uitwisselingen. U bereikt dit door een lijst met alle berichten (systeem, gebruiker en assistent) bij te houden en de volledige lijst met elke aanvraag te verzenden. Het model gebruikt deze geschiedenis om contextafhankelijk relevante antwoorden te genereren.
Voeg een gesprekslus toe die:
- Leest gebruikersinvoer van de console.
- Voegt het gebruikersbericht toe aan de geschiedenis.
- Hiermee wordt de volledige geschiedenis naar het model verzonden.
- Voegt het antwoord van de assistent toe aan de historie voor de volgende beurt.
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 });
}
Elke oproep naar CompleteChatAsync ontvangt de volledige berichtgeschiedenis. Dit is hoe het model vorige beurten onthoudt. De status tussen aanroepen wordt niet opgeslagen.
Streamingantwoorden toevoegen
Streaming drukt elk token af terwijl het wordt gegenereerd, waardoor de assistent sneller reageert. Vervang de CompleteChatAsync aanroep door CompleteChatStreamingAsync om het antwoord token voor token te streamen.
Werk de gesprekslus bij om streaming te gebruiken:
// 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");
De streamingversie verzamelt het volledige antwoord, zodat deze kan worden toegevoegd aan de gespreksgeschiedenis nadat de stream is voltooid.
Volledige code
Vervang de inhoud van Program.cs door de volgende volledige code:
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!");
Voer de chatassistent uit:
dotnet run
De uitvoer ziet er ongeveer als volgt uit:
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!
U ziet hoe de assistent context van vorige beurten onthoudt, wanneer u vraagt 'Waarom is het belangrijk voor andere levende dingen?', weet u dat u nog steeds praat over fotosynthese.
Opslagplaats met voorbeelden
De volledige voorbeeldcode voor dit artikel is beschikbaar in de opslagplaats Foundry Local GitHub. Om de opslagplaats te klonen en naar het voorbeeld te navigeren, gebruikt u:
git clone https://github.com/microsoft/Foundry-Local.git
cd Foundry-Local/samples/js/tutorial-chat-assistant
Pakketten installeren
Als u op Windows ontwikkelt of verzendt, selecteert u het tabblad Windows. Het Windows-pakket kan worden geïntegreerd met de Windows ML runtime. Het biedt hetzelfde API-oppervlak met een grotere breedte van hardwareversnelling.
npm install foundry-local-sdk-winml openai
Door de catalogus bladeren en een model selecteren
De Foundry Local SDK biedt een modelcatalogus met alle beschikbare modellen. In deze stap initialiseert u de SDK en selecteert u een model voor uw chatassistent.
Maak een bestand met de naam
index.js.Voeg de volgende code toe om de SDK te initialiseren en een model te selecteren:
// 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();De
getModelmethode accepteert een modelalias, een korte beschrijvende naam die wordt toegewezen aan een specifiek model in de catalogus. Dedownloadmethode haalt de modelgewichten op in uw lokale cache enloadmaakt het model gereed voor deductie.
Een systeemprompt definiëren
Een systeemprompt stelt de persoonlijkheid en het gedrag van de assistent in. Het is het eerste bericht in de gespreksgeschiedenis en het model verwijst ernaar tijdens het gesprek.
Voeg een systeemprompt toe om vorm te geven aan hoe de assistent reageert:
// 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.'
}
];
Aanbeveling
Experimenteer met verschillende systeemprompts om het gedrag van de assistent te wijzigen. U kunt het bijvoorbeeld instrueren om te reageren als piraat, docent of domeinexpert.
Een conversatie met meerdere beurten implementeren
Een chatassistent moet context onderhouden tussen meerdere uitwisselingen. U bereikt dit door een lijst met alle berichten (systeem, gebruiker en assistent) bij te houden en de volledige lijst met elke aanvraag te verzenden. Het model gebruikt deze geschiedenis om contextafhankelijk relevante antwoorden te genereren.
Voeg een gesprekslus toe die:
- Leest gebruikersinvoer van de console.
- Voegt het gebruikersbericht toe aan de geschiedenis.
- Hiermee wordt de volledige geschiedenis naar het model verzonden.
- Voegt het antwoord van de assistent toe aan de historie voor de volgende beurt.
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 });
}
Elke oproep naar completeChat ontvangt de volledige berichtgeschiedenis. Dit is hoe het model vorige beurten onthoudt. De status tussen aanroepen wordt niet opgeslagen.
Streamingantwoorden toevoegen
Streaming drukt elk token af terwijl het wordt gegenereerd, waardoor de assistent sneller reageert. Vervang de completeChat aanroep door completeStreamingChat om het antwoord token voor token te streamen.
Werk de gesprekslus bij om streaming te gebruiken:
// 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');
De streamingversie verzamelt het volledige antwoord, zodat deze kan worden toegevoegd aan de gespreksgeschiedenis nadat de stream is voltooid.
Volledige code
Maak een bestand met de naam index.js en voeg de volgende volledige code toe:
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) => rl.question(prompt, resolve));
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();
Voer de chatassistent uit:
node index.js
De uitvoer ziet er ongeveer als volgt uit:
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!
U ziet hoe de assistent context van vorige beurten onthoudt, wanneer u vraagt 'Waarom is het belangrijk voor andere levende dingen?', weet u dat u nog steeds praat over fotosynthese.
Opslagplaats met voorbeelden
De volledige voorbeeldcode voor dit artikel is beschikbaar in de opslagplaats Foundry Local GitHub. Om de opslagplaats te klonen en naar het voorbeeld te navigeren, gebruikt u:
git clone https://github.com/microsoft/Foundry-Local.git
cd Foundry-Local/samples/python/tutorial-chat-assistant
Pakketten installeren
Als u op Windows ontwikkelt of verzendt, selecteert u het tabblad Windows. Het Windows-pakket kan worden geïntegreerd met de Windows ML runtime. Het biedt hetzelfde API-oppervlak met een grotere breedte van hardwareversnelling.
pip install foundry-local-sdk-winml openai
Door de catalogus bladeren en een model selecteren
De Foundry Local SDK biedt een modelcatalogus met alle beschikbare modellen. In deze stap initialiseert u de SDK en selecteert u een model voor uw chatassistent.
Maak een bestand met de naam
main.py.Voeg de volgende code toe om de SDK te initialiseren en een model te selecteren:
# 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()De
get_modelmethode accepteert een modelalias, een korte beschrijvende naam die wordt toegewezen aan een specifiek model in de catalogus. Dedownloadmethode haalt de modelgewichten op in uw lokale cache enloadmaakt het model gereed voor deductie.
Een systeemprompt definiëren
Een systeemprompt stelt de persoonlijkheid en het gedrag van de assistent in. Het is het eerste bericht in de gespreksgeschiedenis en het model verwijst ernaar tijdens het gesprek.
Voeg een systeemprompt toe om vorm te geven aan hoe de assistent reageert:
# 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."
}
]
Aanbeveling
Experimenteer met verschillende systeemprompts om het gedrag van de assistent te wijzigen. U kunt het bijvoorbeeld instrueren om te reageren als piraat, docent of domeinexpert.
Een conversatie met meerdere beurten implementeren
Een chatassistent moet context onderhouden tussen meerdere uitwisselingen. U bereikt dit door een lijst met alle berichten (systeem, gebruiker en assistent) bij te houden en de volledige lijst met elke aanvraag te verzenden. Het model gebruikt deze geschiedenis om contextafhankelijk relevante antwoorden te genereren.
Voeg een gesprekslus toe die:
- Leest gebruikersinvoer van de console.
- Voegt het gebruikersbericht toe aan de geschiedenis.
- Hiermee wordt de volledige geschiedenis naar het model verzonden.
- Voegt het antwoord van de assistent toe aan de historie voor de volgende beurt.
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):
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})
Elke oproep naar complete_chat ontvangt de volledige berichtgeschiedenis. Dit is hoe het model vorige beurten onthoudt. De status tussen aanroepen wordt niet opgeslagen.
Streamingantwoorden toevoegen
Streaming drukt elk token af terwijl het wordt gegenereerd, waardoor de assistent sneller reageert. Vervang de complete_chat aanroep door complete_streaming_chat om het antwoord token voor token te streamen.
Werk de gesprekslus bij om streaming te gebruiken:
# Stream the response token by token
print("Assistant: ", end="", flush=True)
full_response = ""
for chunk in client.complete_streaming_chat(messages):
content = chunk.choices[0].delta.content
if content:
print(content, end="", flush=True)
full_response += content
print("\n")
De streamingversie verzamelt het volledige antwoord, zodat deze kan worden toegevoegd aan de gespreksgeschiedenis nadat de stream is voltooid.
Volledige code
Maak een bestand met de naam main.py en voeg de volgende volledige code toe:
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):
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()
Voer de chatassistent uit:
python main.py
De uitvoer ziet er ongeveer als volgt uit:
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!
U ziet hoe de assistent context van vorige beurten onthoudt, wanneer u vraagt 'Waarom is het belangrijk voor andere levende dingen?', weet u dat u nog steeds praat over fotosynthese.
Opslagplaats met voorbeelden
De volledige voorbeeldcode voor dit artikel is beschikbaar in de opslagplaats Foundry Local GitHub. Om de opslagplaats te klonen en naar het voorbeeld te navigeren, gebruikt u:
git clone https://github.com/microsoft/Foundry-Local.git
cd Foundry-Local/samples/rust/tutorial-chat-assistant
Pakketten installeren
Als u op Windows ontwikkelt of verzendt, selecteert u het tabblad Windows. Het Windows-pakket kan worden geïntegreerd met de Windows ML runtime. Het biedt hetzelfde API-oppervlak met een grotere breedte van hardwareversnelling.
cargo add foundry-local-sdk --features winml
cargo add tokio --features full
cargo add tokio-stream anyhow
Door de catalogus bladeren en een model selecteren
De Foundry Local SDK biedt een modelcatalogus met alle beschikbare modellen. In deze stap initialiseert u de SDK en selecteert u een model voor uw chatassistent.
Open
src/main.rsde inhoud en vervang deze door de volgende code om de SDK te initialiseren en een model te selecteren:// Initialize the Foundry Local SDK let manager = FoundryLocalManager::create(FoundryLocalConfig::new("chat-assistant"))?; // 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);De
get_modelmethode accepteert een modelalias, een korte beschrijvende naam die wordt toegewezen aan een specifiek model in de catalogus. Dedownloadmethode haalt de modelgewichten op in uw lokale cache enloadmaakt het model gereed voor deductie.
Een systeemprompt definiëren
Een systeemprompt stelt de persoonlijkheid en het gedrag van de assistent in. Het is het eerste bericht in de gespreksgeschiedenis en het model verwijst ernaar tijdens het gesprek.
Voeg een systeemprompt toe om vorm te geven aan hoe de assistent reageert:
// 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(),
];
Aanbeveling
Experimenteer met verschillende systeemprompts om het gedrag van de assistent te wijzigen. U kunt het bijvoorbeeld instrueren om te reageren als piraat, docent of domeinexpert.
Een conversatie met meerdere beurten implementeren
Een chatassistent moet context onderhouden tussen meerdere uitwisselingen. U bereikt dit door een vector van alle berichten (systeem, gebruiker en assistent) te bewaren en de volledige lijst met elke aanvraag te verzenden. Het model gebruikt deze geschiedenis om contextafhankelijk relevante antwoorden te genereren.
Voeg een gesprekslus toe die:
- Leest gebruikersinvoer van de console.
- Voegt het gebruikersbericht toe aan de geschiedenis.
- Hiermee wordt de volledige geschiedenis naar het model verzonden.
- Voegt het antwoord van de assistent toe aan de historie voor de volgende beurt.
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);
}
Elke oproep naar complete_chat ontvangt de volledige berichtgeschiedenis. Dit is hoe het model vorige beurten onthoudt. De status tussen aanroepen wordt niet opgeslagen.
Streamingantwoorden toevoegen
Streaming drukt elk token af terwijl het wordt gegenereerd, waardoor de assistent sneller reageert. Vervang de complete_chat aanroep door complete_streaming_chat om het antwoord token voor token te streamen.
Werk de gesprekslus bij om streaming te gebruiken:
// 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");
De streamingversie verzamelt het volledige antwoord, zodat deze kan worden toegevoegd aan de gespreksgeschiedenis nadat de stream is voltooid.
Volledige code
Vervang de inhoud van src/main.rs door de volgende volledige code:
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("chat-assistant"))?;
// 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(())
}
Voer de chatassistent uit:
cargo run
De uitvoer ziet er ongeveer als volgt uit:
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!
U ziet hoe de assistent context van vorige beurten onthoudt, wanneer u vraagt 'Waarom is het belangrijk voor andere levende dingen?', weet u dat u nog steeds praat over fotosynthese.
De hulpbronnen opschonen
De modelgewichten blijven in uw lokale cache staan nadat u een model hebt uitgeladen. Dit betekent dat de volgende keer dat u de toepassing uitvoert, de downloadstap wordt overgeslagen en het model sneller wordt geladen. Er is geen extra opschoonbewerking nodig, tenzij u schijfruimte wilt vrijmaken.