Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Ebben az oktatóanyagban egy interaktív csevegősegédet készít, amely teljes egészében az eszközön fut. Az asszisztens több csere során is fenntartja a beszélgetési környezetet, így emlékszik a beszélgetés korábbi részében tárgyaltakra. A Foundry Local SDK használatával kiválaszthat egy modellt, meghatározhat egy rendszerpromptot, és tokenenként streamelheti a válaszokat.
Ebben az oktatóanyagban a következőket sajátíthatja el:
- Projekt beállítása és az Foundry Helyi SDK telepítése
- Tallózás a modellkatalógusban, és válasszon ki egy modellt
- Rendszerkérés definiálása az asszisztens viselkedésének alakításához
- Többfordulós beszélgetés megvalósítása üzenetelőzményekkel
- Válaszok streamelése rugalmas élmény érdekében
- Erőforrások törlése a beszélgetés befejezésekor
Előfeltételek
- Legalább 8 GB RAM-mal rendelkező Windows, macOS vagy Linux rendszerű számítógép.
Mintaadattár
A cikk teljes mintakódját az Öntödei minták GitHub adattárban találja. Az adattár klónozásához és a mintához való navigáláshoz használja a következőt:
git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/csharp/foundry-local/tutorial-chat-assistant
Csomagok telepítése
Ha Windows fejleszt vagy szállít, válassza a Windows lapot. A Windows csomag integrálható a Windows ML futtatókörnyezettel – ugyanazt az API-felületet biztosítja a hardveres gyorsítás szélesebb körű használatával.
dotnet add package Microsoft.AI.Foundry.Local.WinML
dotnet add package OpenAI
A GitHub adattár C#-mintái előre konfigurált projektek. Ha az alapoktól épít, olvassa el a Foundry Local SDK-referenciáját , amelyből megtudhatja, hogyan állíthatja be a C#-projektet a Foundry Local használatával.
Tallózás a katalógusban, és modell kiválasztása
A Foundry Local SDK egy modellkatalógust biztosít, amely felsorolja az összes elérhető modellt. Ebben a lépésben inicializálja az SDK-t, és kiválaszt egy modellt a csevegősegéd számára.
Nyissa meg
Program.csés cserélje le a tartalmát a következő kódra az SDK inicializálásához és egy modell kiválasztásához: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();A
GetModelAsyncmetódus egy modell aliasát fogadja el, amely egy rövid felhasználóbarát név, amely leképezi a katalógus egy adott modelljét. ADownloadAsyncmetódus lekéri a modell súlyait a helyi gyorsítótárba, és aLoadAsynckészenlétbe helyezi a modellt az inferenciára.
Rendszerkérés definiálása
A rendszerutasítás beállítja az asszisztens személyiségét és viselkedését. Ez az első üzenet a beszélgetési előzményekben, és a modell a beszélgetés során hivatkozik rá.
Adjon hozzá egy rendszerkérést az asszisztens válaszának alakításához:
// 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."
}
};
Jótanács
Kísérletezzen különböző rendszerkérésekkel az asszisztens viselkedésének módosításához. Például utasíthatja, hogy kalózként, tanárként vagy szakterületi szakértőként válaszoljon.
Többfordulós beszélgetés implementálása
A csevegősegédnek több cserekörnyezetet kell fenntartania. Ezt úgy érheti el, hogy az összes üzenet (rendszer, felhasználó és asszisztens) listáját megőrzi, és a teljes listát minden kéréssel együtt elküldi. A modell ezt az előzményt használja a kontextus szempontjából releváns válaszok létrehozásához.
Adjon hozzá egy olyan beszélgetési ciklust, amely:
- Beolvassa a felhasználói bemenetet a konzolról.
- Hozzáfűzi a felhasználói üzenetet az előzményekhez.
- Elküldi a teljes előzményt a modellnek.
- Hozzáfűzi az asszisztens válaszát a következő forduló előzményeihez.
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 });
}
Minden hívás megkapja CompleteChatAsync a teljes üzenetelőzményt. A modell így "emlékszik" az előző fordulatokra – nem tárolja az állapotot a hívások között.
Streamelési válaszok hozzáadása
A streamelés az egyes jogkivonatokat a generált módon nyomtatja ki, így az asszisztens rugalmasabbnak érzi magát. Cserélje le a CompleteChatAsync hívást CompleteChatStreamingAsync a válasz jogkivonat jogkivonattal való streamelésére.
Frissítse a beszélgetési ciklust a streamelés használatára:
// 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");
A streamelési verzió összegyűjti a teljes választ, így a stream befejezése után hozzáadható a beszélgetési előzményekhez.
Teljes kód
Cserélje le a következő teljes kód tartalmát Program.cs :
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!");
Futtassa a csevegőasszisztenst:
dotnet run
A következőhöz hasonló kimenet jelenik meg:
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!
Figyelje meg, hogyan emlékszik az asszisztens a korábbi fordulatok kontextusára – amikor megkérdezi, hogy "Miért fontos más élőlények számára?", akkor tudja, hogy még mindig fotoszintézisről beszél.
Mintaadattár
A cikk teljes mintakódja az öntödei minták GitHub adattárban érhető el. Az adattár klónozásához és a mintahasználathoz való navigáláshoz:
git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/javascript/foundry-local/tutorial-chat-assistant
Csomagok telepítése
Ha Windows fejleszt vagy szállít, válassza a Windows lapot. A Windows csomag integrálható a Windows ML futtatókörnyezettel – ugyanazt az API-felületet biztosítja a hardveres gyorsítás szélesebb körű használatával.
npm install foundry-local-sdk-winml openai
Tallózás a katalógusban, és modell kiválasztása
A Foundry Local SDK egy modellkatalógust biztosít, amely felsorolja az összes elérhető modellt. Ebben a lépésben inicializálja az SDK-t, és kiválaszt egy modellt a csevegősegéd számára.
Hozzon létre egy
index.jsfájlt.Adja hozzá a következő kódot az SDK inicializálásához és egy modell kiválasztásához:
// 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();A
getModelmetódus egy modell aliasát fogadja el, amely egy rövid felhasználóbarát név, amely leképezi a katalógus egy adott modelljét. Adownloadmetódus lekéri a modell súlyait a helyi gyorsítótárba, és aloadkészenlétbe helyezi a modellt az inferenciára.
Rendszerkérés definiálása
A rendszerutasítás beállítja az asszisztens személyiségét és viselkedését. Ez az első üzenet a beszélgetési előzményekben, és a modell a beszélgetés során hivatkozik rá.
Adjon hozzá egy rendszerkérést az asszisztens válaszának alakításához:
// 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.'
}
];
Jótanács
Kísérletezzen különböző rendszerkérésekkel az asszisztens viselkedésének módosításához. Például utasíthatja, hogy kalózként, tanárként vagy szakterületi szakértőként válaszoljon.
Többfordulós beszélgetés implementálása
A csevegősegédnek több cserekörnyezetet kell fenntartania. Ezt úgy érheti el, hogy az összes üzenet (rendszer, felhasználó és asszisztens) listáját megőrzi, és a teljes listát minden kéréssel együtt elküldi. A modell ezt az előzményt használja a kontextus szempontjából releváns válaszok létrehozásához.
Adjon hozzá egy olyan beszélgetési ciklust, amely:
- Beolvassa a felhasználói bemenetet a konzolról.
- Hozzáfűzi a felhasználói üzenetet az előzményekhez.
- Elküldi a teljes előzményt a modellnek.
- Hozzáfűzi az asszisztens válaszát a következő forduló előzményeihez.
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 });
}
Minden hívás megkapja completeChat a teljes üzenetelőzményt. A modell így "emlékszik" az előző fordulatokra – nem tárolja az állapotot a hívások között.
Streamelési válaszok hozzáadása
A streamelés az egyes jogkivonatokat a generált módon nyomtatja ki, így az asszisztens rugalmasabbnak érzi magát. Cserélje le a completeChat hívást completeStreamingChat a válasz jogkivonat jogkivonattal való streamelésére.
Frissítse a beszélgetési ciklust a streamelés használatára:
// 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');
A streamelési verzió összegyűjti a teljes választ, így a stream befejezése után hozzáadható a beszélgetési előzményekhez.
Teljes kód
Hozzon létre egy elnevezett index.js fájlt, és adja hozzá a következő teljes kódot:
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();
Futtassa a csevegőasszisztenst:
node index.js
A következőhöz hasonló kimenet jelenik meg:
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!
Figyelje meg, hogyan emlékszik az asszisztens a korábbi fordulatok kontextusára – amikor megkérdezi, hogy "Miért fontos más élőlények számára?", akkor tudja, hogy még mindig fotoszintézisről beszél.
Mintaadattár
A cikk teljes mintakódja az öntödei minták GitHub adattárban érhető el. Az adattár klónozásához és a mintahasználathoz való navigáláshoz:
git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/python/foundry-local/tutorial-chat-assistant
Csomagok telepítése
Ha Windows fejleszt vagy szállít, válassza a Windows lapot. A Windows csomag integrálható a Windows ML futtatókörnyezettel – ugyanazt az API-felületet biztosítja a hardveres gyorsítás szélesebb körű használatával.
pip install foundry-local-sdk-winml openai
Tallózás a katalógusban, és modell kiválasztása
A Foundry Local SDK egy modellkatalógust biztosít, amely felsorolja az összes elérhető modellt. Ebben a lépésben inicializálja az SDK-t, és kiválaszt egy modellt a csevegősegéd számára.
Hozzon létre egy
main.pyfájlt.Adja hozzá a következő kódot az SDK inicializálásához és egy modell kiválasztásához:
# 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()A
get_modelmetódus egy modell aliasát fogadja el, amely egy rövid felhasználóbarát név, amely leképezi a katalógus egy adott modelljét. Adownloadmetódus lekéri a modell súlyait a helyi gyorsítótárba, és aloadkészenlétbe helyezi a modellt az inferenciára.
Rendszerkérés definiálása
A rendszerutasítás beállítja az asszisztens személyiségét és viselkedését. Ez az első üzenet a beszélgetési előzményekben, és a modell a beszélgetés során hivatkozik rá.
Adjon hozzá egy rendszerkérést az asszisztens válaszának alakításához:
# 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.",
}
]
Jótanács
Kísérletezzen különböző rendszerkérésekkel az asszisztens viselkedésének módosításához. Például utasíthatja, hogy kalózként, tanárként vagy szakterületi szakértőként válaszoljon.
Többfordulós beszélgetés implementálása
A csevegősegédnek több cserekörnyezetet kell fenntartania. Ezt úgy érheti el, hogy az összes üzenet (rendszer, felhasználó és asszisztens) listáját megőrzi, és a teljes listát minden kéréssel együtt elküldi. A modell ezt az előzményt használja a kontextus szempontjából releváns válaszok létrehozásához.
Adjon hozzá egy olyan beszélgetési ciklust, amely:
- Beolvassa a felhasználói bemenetet a konzolról.
- Hozzáfűzi a felhasználói üzenetet az előzményekhez.
- Elküldi a teljes előzményt a modellnek.
- Hozzáfűzi az asszisztens válaszát a következő forduló előzményeihez.
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})
Minden hívás megkapja complete_chat a teljes üzenetelőzményt. A modell így "emlékszik" az előző fordulatokra – nem tárolja az állapotot a hívások között.
Streamelési válaszok hozzáadása
A streamelés az egyes jogkivonatokat a generált módon nyomtatja ki, így az asszisztens rugalmasabbnak érzi magát. Cserélje le a complete_chat hívást complete_streaming_chat a válasz jogkivonat jogkivonattal való streamelésére.
Frissítse a beszélgetési ciklust a streamelés használatára:
# 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")
A streamelési verzió összegyűjti a teljes választ, így a stream befejezése után hozzáadható a beszélgetési előzményekhez.
Teljes kód
Hozzon létre egy elnevezett main.py fájlt, és adja hozzá a következő teljes kódot:
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()
Futtassa a csevegőasszisztenst:
python main.py
A következőhöz hasonló kimenet jelenik meg:
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!
Figyelje meg, hogyan emlékszik az asszisztens a korábbi fordulatok kontextusára – amikor megkérdezi, hogy "Miért fontos más élőlények számára?", akkor tudja, hogy még mindig fotoszintézisről beszél.
Mintaadattár
A cikk teljes mintakódja az öntödei minták GitHub adattárban érhető el. Az adattár klónozásához és a mintahasználathoz való navigáláshoz:
git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/rust/foundry-local/tutorial-chat-assistant
Csomagok telepítése
Ha Windows fejleszt vagy szállít, válassza a Windows lapot. A Windows csomag integrálható a Windows ML futtatókörnyezettel – ugyanazt az API-felületet biztosítja a hardveres gyorsítás szélesebb körű használatával.
cargo add foundry-local-sdk --features winml
cargo add tokio --features full
cargo add tokio-stream anyhow
Tallózás a katalógusban, és modell kiválasztása
A Foundry Local SDK egy modellkatalógust biztosít, amely felsorolja az összes elérhető modellt. Ebben a lépésben inicializálja az SDK-t, és kiválaszt egy modellt a csevegősegéd számára.
Nyissa meg
src/main.rsés cserélje le a tartalmát a következő kódra az SDK inicializálásához és egy modell kiválasztásához:// 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);A
get_modelmetódus egy modell aliasát fogadja el, amely egy rövid felhasználóbarát név, amely leképezi a katalógus egy adott modelljét. Adownloadmetódus lekéri a modell súlyait a helyi gyorsítótárba, és aloadkészenlétbe helyezi a modellt az inferenciára.
Rendszerkérés definiálása
A rendszerutasítás beállítja az asszisztens személyiségét és viselkedését. Ez az első üzenet a beszélgetési előzményekben, és a modell a beszélgetés során hivatkozik rá.
Adjon hozzá egy rendszerkérést az asszisztens válaszának alakításához:
// 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(),
];
Jótanács
Kísérletezzen különböző rendszerkérésekkel az asszisztens viselkedésének módosításához. Például utasíthatja, hogy kalózként, tanárként vagy szakterületi szakértőként válaszoljon.
Többfordulós beszélgetés implementálása
A csevegősegédnek több cserekörnyezetet kell fenntartania. Ezt úgy érheti el, hogy megtartja az összes üzenet (rendszer, felhasználó és asszisztens) vektorát, és minden kéréssel elküldi a teljes listát. A modell ezt az előzményt használja a kontextus szempontjából releváns válaszok létrehozásához.
Adjon hozzá egy olyan beszélgetési ciklust, amely:
- Beolvassa a felhasználói bemenetet a konzolról.
- Hozzáfűzi a felhasználói üzenetet az előzményekhez.
- Elküldi a teljes előzményt a modellnek.
- Hozzáfűzi az asszisztens válaszát a következő forduló előzményeihez.
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);
}
Minden hívás megkapja complete_chat a teljes üzenetelőzményt. A modell így "emlékszik" az előző fordulatokra – nem tárolja az állapotot a hívások között.
Streamelési válaszok hozzáadása
A streamelés az egyes jogkivonatokat a generált módon nyomtatja ki, így az asszisztens rugalmasabbnak érzi magát. Cserélje le a complete_chat hívást complete_streaming_chat a válasz jogkivonat jogkivonattal való streamelésére.
Frissítse a beszélgetési ciklust a streamelés használatára:
// 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");
A streamelési verzió összegyűjti a teljes választ, így a stream befejezése után hozzáadható a beszélgetési előzményekhez.
Teljes kód
Cserélje le a következő teljes kód tartalmát src/main.rs :
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(())
}
Futtassa a csevegőasszisztenst:
cargo run
A következőhöz hasonló kimenet jelenik meg:
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!
Figyelje meg, hogyan emlékszik az asszisztens a korábbi fordulatok kontextusára – amikor megkérdezi, hogy "Miért fontos más élőlények számára?", akkor tudja, hogy még mindig fotoszintézisről beszél.
Erőforrások tisztítása
A modell súlyai a modell kiürítése után a helyi gyorsítótárban maradnak. Ez azt jelenti, hogy az alkalmazás következő futtatásakor a rendszer kihagyja a letöltési lépést, és a modell gyorsabban betöltődik. Nincs szükség további törlésre, ha vissza szeretné igényelni a lemezterületet.