Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Lernprogramm erstellen Sie einen interaktiven Chat-Assistenten, der vollständig auf Ihrem Gerät ausgeführt wird. Der Assistent verwaltet den Unterhaltungskontext über mehrere Interaktionen hinweg. Er kann sich also daran erinnern, was Sie früher in der Unterhaltung diskutiert haben. Sie verwenden das Foundry Local SDK, um ein Modell auszuwählen, eine Systemaufforderung zu definieren und die Antworten Token für Token im Datenstrom zu übertragen.
In diesem Tutorial erfahren Sie, wie:
- Einrichten eines Projekts und Installieren des Foundry Local SDK
- Durchsuchen des Modellkatalogs und Auswählen eines Modells
- Definieren Sie eine Systemaufforderung zur Gestaltung des Verhaltens des Assistenten
- Implementieren einer mehrteiligen Unterhaltung mit Nachrichtenverlauf
- Streamingantworten für eine reagierende Benutzererfahrung
- Bereinigen von Ressourcen, wenn die Unterhaltung endet
Voraussetzungen
- Ein Windows, macOS oder Linux-Computer mit mindestens 8 GB RAM.
Beispielrepository
Der vollständige Beispielcode für diesen Artikel ist im Repository Foundry Local GitHub repository verfügbar. So klonen Sie das Repository, und navigieren Sie zur Beispielverwendung:
git clone https://github.com/microsoft/Foundry-Local.git
cd Foundry-Local/samples/cs/tutorial-chat-assistant
Pakete installieren
Wenn Sie Windows entwickeln oder versenden, wählen Sie die Registerkarte Windows aus. Das Windows-Paket ist in die Windows ML Laufzeit integriert. Es bietet den gleichen API-Oberflächenbereich mit einer breiteren Hardwarebeschleunigung.
dotnet add package Microsoft.AI.Foundry.Local.WinML
dotnet add package OpenAI
Die C#-Beispiele im GitHub Repository sind vorkonfigurierte Projekte. Wenn Sie von Grund auf neu erstellen, sollten Sie die Referenz zum Foundry Local SDK lesen, um weitere Details zum Einrichten Ihres C#-Projekts mit Foundry Local zu erhalten.
Durchsuchen des Katalogs und Auswählen eines Modells
Das Foundry Local SDK stellt einen Modellkatalog bereit, der alle verfügbaren Modelle auflistet. In diesem Schritt initialisieren Sie das SDK und wählen ein Modell für Ihren Chat-Assistenten aus.
öffnen Sie
Program.cs, und ersetzen Sie den Inhalt durch den folgenden Code, um das SDK zu initialisieren und ein Modell auszuwählen.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();Die Methode
GetModelAsyncakzeptiert einen Modellalias, bei dem es sich um einen kurzen Anzeigenamen handelt, der einem bestimmten Modell im Katalog zugeordnet ist. DieDownloadAsyncMethode ruft die Modellgewichtung in Den lokalen Cache ab undLoadAsyncmacht das Modell zur Ableitung bereit.
Definieren einer Systemaufforderung
Eine Systemaufforderung legt die Persönlichkeit und das Verhalten des Assistenten fest. Es ist die erste Nachricht im Unterhaltungsverlauf, und das Modell verweist darauf während der gesamten Unterhaltung.
Fügen Sie eine Systemaufforderung hinzu, um zu gestalten, wie der Assistent reagiert:
// 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."
}
};
Tipp
Experimentieren Sie mit verschiedenen Systemaufforderungen, um das Verhalten des Assistenten zu ändern. Sie können sie beispielsweise anweisen, als Piraten, Lehrer oder Domänenexperte zu reagieren.
Implementieren einer mehrteiligen Unterhaltung
Ein Chat-Assistent muss den Kontext über mehrere Austausch hinweg pflegen. Sie erreichen dies, indem Sie eine Liste aller Nachrichten (System, Benutzer und Assistent) beibehalten und die vollständige Liste mit jeder Anforderung senden. Das Modell verwendet diesen Verlauf, um kontextbezogene Antworten zu generieren.
Fügen Sie eine Unterhaltungsschleife hinzu, die:
- Liest Benutzereingaben aus der Konsole.
- Fügt die Benutzernachricht an den Verlauf an.
- Sendet den vollständigen Verlauf an das Modell.
- Fügt die Antwort des Assistenten für den nächsten Durchgang zum Verlauf hinzu.
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 });
}
Jeder Aufruf von CompleteChatAsync erhält den vollständigen Nachrichtenverlauf. Dies ist, wie das Modell "merkt sich" vorherige Wendungen – es speichert den Zustand nicht zwischen Aufrufen.
Hinzufügen von Streaming-Antworten
Streaming druckt jedes Token bei seiner Generierung, wodurch der Assistent einen reaktionsfähigeren Eindruck erweckt. Ersetzen Sie den Aufruf CompleteChatAsync durch CompleteChatStreamingAsync, um das Antworttoken nach und nach zu streamen.
Aktualisieren Sie die Gesprächsschleife zur Nutzung von 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");
Die gestreamte Version sammelt die vollständige Antwort, damit sie nach Abschluss des Streams dem Gesprächsverlauf hinzugefügt werden kann.
Vollständiger Code
Ersetzen Sie den Inhalt von Program.cs durch den folgenden vollständigen 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!");
Führen Sie den Chat-Assistenten aus:
dotnet run
Es wird eine ähnliche Ausgabe angezeigt wie:
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!
Beachten Sie, wie sich der Assistent aus früheren Wendungen an den Kontext erinnert – wenn Sie fragen, "Warum ist es wichtig für andere Lebewesen?", weiß es, dass Sie immer noch über Photosynthese sprechen.
Beispielrepository
Der vollständige Beispielcode für diesen Artikel ist im Repository Foundry Local GitHub repository verfügbar. So klonen Sie das Repository, und navigieren Sie zur Beispielverwendung:
git clone https://github.com/microsoft/Foundry-Local.git
cd Foundry-Local/samples/js/tutorial-chat-assistant
Pakete installieren
Wenn Sie Windows entwickeln oder versenden, wählen Sie die Registerkarte Windows aus. Das Windows-Paket ist in die Windows ML Laufzeit integriert. Es bietet den gleichen API-Oberflächenbereich mit einer breiteren Hardwarebeschleunigung.
npm install foundry-local-sdk-winml openai
Durchsuchen des Katalogs und Auswählen eines Modells
Das Foundry Local SDK stellt einen Modellkatalog bereit, der alle verfügbaren Modelle auflistet. In diesem Schritt initialisieren Sie das SDK und wählen ein Modell für Ihren Chat-Assistenten aus.
Erstellen Sie eine Datei namens
index.js.Fügen Sie den folgenden Code hinzu, um das SDK zu initialisieren und ein Modell auszuwählen:
// 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();Die Methode
getModelakzeptiert einen Modellalias, bei dem es sich um einen kurzen Anzeigenamen handelt, der einem bestimmten Modell im Katalog zugeordnet ist. DiedownloadMethode ruft die Modellgewichtung in Den lokalen Cache ab undloadmacht das Modell zur Ableitung bereit.
Definieren einer Systemaufforderung
Eine Systemaufforderung legt die Persönlichkeit und das Verhalten des Assistenten fest. Es ist die erste Nachricht im Unterhaltungsverlauf, und das Modell verweist darauf während der gesamten Unterhaltung.
Fügen Sie eine Systemaufforderung hinzu, um zu gestalten, wie der Assistent reagiert:
// 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.'
}
];
Tipp
Experimentieren Sie mit verschiedenen Systemaufforderungen, um das Verhalten des Assistenten zu ändern. Sie können sie beispielsweise anweisen, als Piraten, Lehrer oder Domänenexperte zu reagieren.
Implementieren einer mehrteiligen Unterhaltung
Ein Chat-Assistent muss den Kontext über mehrere Austausch hinweg pflegen. Sie erreichen dies, indem Sie eine Liste aller Nachrichten (System, Benutzer und Assistent) beibehalten und die vollständige Liste mit jeder Anforderung senden. Das Modell verwendet diesen Verlauf, um kontextbezogene Antworten zu generieren.
Fügen Sie eine Unterhaltungsschleife hinzu, die:
- Liest Benutzereingaben aus der Konsole.
- Fügt die Benutzernachricht an den Verlauf an.
- Sendet den vollständigen Verlauf an das Modell.
- Fügt die Antwort des Assistenten für den nächsten Durchgang zum Verlauf hinzu.
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 });
}
Jeder Aufruf von completeChat erhält den vollständigen Nachrichtenverlauf. Dies ist, wie das Modell "merkt sich" vorherige Wendungen – es speichert den Zustand nicht zwischen Aufrufen.
Hinzufügen von Streaming-Antworten
Streaming druckt jedes Token bei seiner Generierung, wodurch der Assistent einen reaktionsfähigeren Eindruck erweckt. Ersetzen Sie den Aufruf completeChat durch completeStreamingChat, um das Antworttoken nach und nach zu streamen.
Aktualisieren Sie die Gesprächsschleife zur Nutzung von 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');
Die gestreamte Version sammelt die vollständige Antwort, damit sie nach Abschluss des Streams dem Gesprächsverlauf hinzugefügt werden kann.
Vollständiger Code
Erstellen Sie eine Datei mit dem Namen index.js , und fügen Sie den folgenden vollständigen Code hinzu:
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();
Führen Sie den Chat-Assistenten aus:
node index.js
Es wird eine ähnliche Ausgabe angezeigt wie:
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!
Beachten Sie, wie sich der Assistent aus früheren Wendungen an den Kontext erinnert – wenn Sie fragen, "Warum ist es wichtig für andere Lebewesen?", weiß es, dass Sie immer noch über Photosynthese sprechen.
Beispielrepository
Der vollständige Beispielcode für diesen Artikel ist im Repository Foundry Local GitHub repository verfügbar. So klonen Sie das Repository, und navigieren Sie zur Beispielverwendung:
git clone https://github.com/microsoft/Foundry-Local.git
cd Foundry-Local/samples/python/tutorial-chat-assistant
Pakete installieren
Wenn Sie Windows entwickeln oder versenden, wählen Sie die Registerkarte Windows aus. Das Windows-Paket ist in die Windows ML Laufzeit integriert. Es bietet den gleichen API-Oberflächenbereich mit einer breiteren Hardwarebeschleunigung.
pip install foundry-local-sdk-winml openai
Durchsuchen des Katalogs und Auswählen eines Modells
Das Foundry Local SDK stellt einen Modellkatalog bereit, der alle verfügbaren Modelle auflistet. In diesem Schritt initialisieren Sie das SDK und wählen ein Modell für Ihren Chat-Assistenten aus.
Erstellen Sie eine Datei namens
main.py.Fügen Sie den folgenden Code hinzu, um das SDK zu initialisieren und ein Modell auszuwählen:
# 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()Die Methode
get_modelakzeptiert einen Modellalias, bei dem es sich um einen kurzen Anzeigenamen handelt, der einem bestimmten Modell im Katalog zugeordnet ist. DiedownloadMethode ruft die Modellgewichtung in Den lokalen Cache ab undloadmacht das Modell zur Ableitung bereit.
Definieren einer Systemaufforderung
Eine Systemaufforderung legt die Persönlichkeit und das Verhalten des Assistenten fest. Es ist die erste Nachricht im Unterhaltungsverlauf, und das Modell verweist darauf während der gesamten Unterhaltung.
Fügen Sie eine Systemaufforderung hinzu, um zu gestalten, wie der Assistent reagiert:
# 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."
}
]
Tipp
Experimentieren Sie mit verschiedenen Systemaufforderungen, um das Verhalten des Assistenten zu ändern. Sie können sie beispielsweise anweisen, als Piraten, Lehrer oder Domänenexperte zu reagieren.
Implementieren einer mehrteiligen Unterhaltung
Ein Chat-Assistent muss den Kontext über mehrere Austausch hinweg pflegen. Sie erreichen dies, indem Sie eine Liste aller Nachrichten (System, Benutzer und Assistent) beibehalten und die vollständige Liste mit jeder Anforderung senden. Das Modell verwendet diesen Verlauf, um kontextbezogene Antworten zu generieren.
Fügen Sie eine Unterhaltungsschleife hinzu, die:
- Liest Benutzereingaben aus der Konsole.
- Fügt die Benutzernachricht an den Verlauf an.
- Sendet den vollständigen Verlauf an das Modell.
- Fügt die Antwort des Assistenten für den nächsten Durchgang zum Verlauf hinzu.
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})
Jeder Aufruf von complete_chat erhält den vollständigen Nachrichtenverlauf. Dies ist, wie das Modell "merkt sich" vorherige Wendungen – es speichert den Zustand nicht zwischen Aufrufen.
Hinzufügen von Streaming-Antworten
Streaming druckt jedes Token bei seiner Generierung, wodurch der Assistent einen reaktionsfähigeren Eindruck erweckt. Ersetzen Sie den Aufruf complete_chat durch complete_streaming_chat, um das Antworttoken nach und nach zu streamen.
Aktualisieren Sie die Gesprächsschleife zur Nutzung von Streaming.
# 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")
Die gestreamte Version sammelt die vollständige Antwort, damit sie nach Abschluss des Streams dem Gesprächsverlauf hinzugefügt werden kann.
Vollständiger Code
Erstellen Sie eine Datei mit dem Namen main.py , und fügen Sie den folgenden vollständigen Code hinzu:
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()
Führen Sie den Chat-Assistenten aus:
python main.py
Es wird eine ähnliche Ausgabe angezeigt wie:
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!
Beachten Sie, wie sich der Assistent aus früheren Wendungen an den Kontext erinnert – wenn Sie fragen, "Warum ist es wichtig für andere Lebewesen?", weiß es, dass Sie immer noch über Photosynthese sprechen.
Beispielrepository
Der vollständige Beispielcode für diesen Artikel ist im Repository Foundry Local GitHub repository verfügbar. So klonen Sie das Repository, und navigieren Sie zur Beispielverwendung:
git clone https://github.com/microsoft/Foundry-Local.git
cd Foundry-Local/samples/rust/tutorial-chat-assistant
Pakete installieren
Wenn Sie Windows entwickeln oder versenden, wählen Sie die Registerkarte Windows aus. Das Windows-Paket ist in die Windows ML Laufzeit integriert. Es bietet den gleichen API-Oberflächenbereich mit einer breiteren Hardwarebeschleunigung.
cargo add foundry-local-sdk --features winml
cargo add tokio --features full
cargo add tokio-stream anyhow
Durchsuchen des Katalogs und Auswählen eines Modells
Das Foundry Local SDK stellt einen Modellkatalog bereit, der alle verfügbaren Modelle auflistet. In diesem Schritt initialisieren Sie das SDK und wählen ein Modell für Ihren Chat-Assistenten aus.
öffnen Sie
src/main.rs, und ersetzen Sie den Inhalt durch den folgenden Code, um das SDK zu initialisieren und ein Modell auszuwählen.// 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);Die Methode
get_modelakzeptiert einen Modellalias, bei dem es sich um einen kurzen Anzeigenamen handelt, der einem bestimmten Modell im Katalog zugeordnet ist. DiedownloadMethode ruft die Modellgewichtung in Den lokalen Cache ab undloadmacht das Modell zur Ableitung bereit.
Definieren einer Systemaufforderung
Eine Systemaufforderung legt die Persönlichkeit und das Verhalten des Assistenten fest. Es ist die erste Nachricht im Unterhaltungsverlauf, und das Modell verweist darauf während der gesamten Unterhaltung.
Fügen Sie eine Systemaufforderung hinzu, um zu gestalten, wie der Assistent reagiert:
// 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(),
];
Tipp
Experimentieren Sie mit verschiedenen Systemaufforderungen, um das Verhalten des Assistenten zu ändern. Sie können sie beispielsweise anweisen, als Piraten, Lehrer oder Domänenexperte zu reagieren.
Implementieren einer mehrteiligen Unterhaltung
Ein Chat-Assistent muss den Kontext über mehrere Austausch hinweg pflegen. Sie erreichen dies, indem Sie einen Vektor aller Nachrichten (System, Benutzer und Assistent) beibehalten und die vollständige Liste mit jeder Anforderung senden. Das Modell verwendet diesen Verlauf, um kontextbezogene Antworten zu generieren.
Fügen Sie eine Unterhaltungsschleife hinzu, die:
- Liest Benutzereingaben aus der Konsole.
- Fügt die Benutzernachricht an den Verlauf an.
- Sendet den vollständigen Verlauf an das Modell.
- Fügt die Antwort des Assistenten für den nächsten Durchgang zum Verlauf hinzu.
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);
}
Jeder Aufruf von complete_chat erhält den vollständigen Nachrichtenverlauf. Dies ist, wie das Modell "merkt sich" vorherige Wendungen – es speichert den Zustand nicht zwischen Aufrufen.
Hinzufügen von Streaming-Antworten
Streaming druckt jedes Token bei seiner Generierung, wodurch der Assistent einen reaktionsfähigeren Eindruck erweckt. Ersetzen Sie den Aufruf complete_chat durch complete_streaming_chat, um das Antworttoken nach und nach zu streamen.
Aktualisieren Sie die Gesprächsschleife zur Nutzung von 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");
Die gestreamte Version sammelt die vollständige Antwort, damit sie nach Abschluss des Streams dem Gesprächsverlauf hinzugefügt werden kann.
Vollständiger Code
Ersetzen Sie den Inhalt von src/main.rs durch den folgenden vollständigen 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(())
}
Führen Sie den Chat-Assistenten aus:
cargo run
Es wird eine ähnliche Ausgabe angezeigt wie:
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!
Beachten Sie, wie sich der Assistent aus früheren Wendungen an den Kontext erinnert – wenn Sie fragen, "Warum ist es wichtig für andere Lebewesen?", weiß es, dass Sie immer noch über Photosynthese sprechen.
Bereinigen von Ressourcen
Die Gewichtungen des Modells verbleiben im lokalen Cache, nachdem Sie ein Modell entladen haben. Dies bedeutet, dass beim nächsten Ausführen der Anwendung der Downloadschritt übersprungen wird und das Modell schneller geladen wird. Es ist keine zusätzliche Bereinigung erforderlich, es sei denn, Sie möchten Speicherplatz freigeben.