Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Vytvořte aplikaci, která čte textové soubory a generuje stručné souhrny – zcela na vašem zařízení. To je užitečné, když potřebujete rychle pochopit obsah dokumentů, aniž byste je museli číst úplně, a když dokumenty obsahují citlivé informace, které by neměly opustit váš počítač.
V tomto návodu se naučíte, jak:
- Nastavení projektu a instalace místní sady SDK Foundry
- Čtení textového dokumentu ze systému souborů
- Načtení modelu a vygenerování souhrnu
- Řízení souhrnného výstupu pomocí systémových výzev
- Zpracování více dokumentů v dávce
- Vyčistěte zdroje
Předpoklady
- Počítač s Windows, macOS nebo Linuxem s minimálně 8 GB paměti RAM.
- .NET 8.0 SDK nebo novější.
Úložiště ukázek
Kompletní ukázkový kód pro tento článek najdete v repozitáři Foundry samples na GitHubu. Pokud chcete naklonovat úložiště a přejít k ukázce, použijte:
git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/csharp/foundry-local/tutorial-document-summarizer
Instalace balíčků
Pokud vyvíjíte nebo vydáváte aplikace na Windows, vyberte kartu Windows. Balíček Windows se integruje s runtime modulem Windows ML — poskytuje stejné rozhraní API a nabízí širší možnosti hardwarové akcelerace.
dotnet add package Microsoft.AI.Foundry.Local.WinML
dotnet add package OpenAI
Ukázky jazyka C# v úložišti GitHub jsou předkonfigurované projekty. Pokud vytváříte úplně od začátku, měli byste si přečíst referenční informace k místní sadě SDK Foundry , kde najdete další podrobnosti o tom, jak nastavit projekt jazyka C# pomocí Foundry Local.
Čtení textového dokumentu
Než něco shrnete, budete potřebovat ukázkový dokument, se kterým budete pracovat. Vytvořte soubor volaný document.txt v adresáři projektu a přidejte následující obsah:
Automated testing is a practice in software development where tests are written and executed
by specialized tools rather than performed manually. There are several categories of automated
tests, including unit tests, integration tests, and end-to-end tests. Unit tests verify that
individual functions or methods behave correctly in isolation. Integration tests check that
multiple components work together as expected. End-to-end tests simulate real user workflows
across the entire application.
Adopting automated testing brings measurable benefits to a development team. It catches
regressions early, before they reach production. It reduces the time spent on repetitive
manual verification after each code change. It serves as living documentation of expected
behavior, which helps new team members understand the codebase. Continuous integration
pipelines rely on automated tests to gate deployments and maintain release quality.
Effective test suites follow a few guiding principles. Tests should be deterministic, meaning
they produce the same result every time they run. Tests should be independent, so that one
failing test does not cascade into false failures elsewhere. Tests should run fast, because
slow tests discourage developers from running them frequently. Finally, tests should be
maintained alongside production code so they stay accurate as the application evolves.
Teď otevřete Program.cs a přidejte následující kód, který dokument přečte:
var target = args.Length > 0 ? args[0] : "document.txt";
Kód přijme volitelnou cestu k souboru jako argument příkazového řádku a použije document.txt, pokud žádná není poskytnuta.
Vygenerování souhrnu
Inicializujte sadu Foundry Local SDK, načtěte model a odešlete obsah dokumentu spolu s výzvou systému, která dává modelu pokyn k shrnutí.
Obsah Program.cs nahraďte následujícím kódem:
var systemPrompt =
"Summarize the following document into concise bullet points. " +
"Focus on the key points and main ideas.";
var target = args.Length > 0 ? args[0] : "document.txt";
if (Directory.Exists(target))
{
await SummarizeDirectoryAsync(chatClient, target, systemPrompt, ct);
}
else
{
Console.WriteLine($"--- {Path.GetFileName(target)} ---");
await SummarizeFileAsync(chatClient, target, systemPrompt, ct);
}
Metoda GetModelAsync přijímá alias modelu, což je krátký přátelský název, který odpovídá konkrétnímu modelu v katalogu. Metoda DownloadAsync načte váhy modelu do místní mezipaměti (a přeskočí stahování, pokud už jsou uložené v mezipaměti) a LoadAsync model je připravený k odvozování. Systémová výzva modelu určuje, aby vytvořil souhrny s odrážkami zaměřené na klíčové myšlenky.
Řídicí souhrnný výstup
Různé situace vyžadují různé styly shrnutí. Můžete změnit výzvu systému, abyste mohli řídit, jak model strukturuje svůj výstup. Tady jsou tři užitečné varianty:
Odrážky (výchozí hodnota z předchozího kroku):
var systemPrompt =
"Summarize the following document into concise bullet points. " +
"Focus on the key points and main ideas.";
Shrnutí jednoho odstavce:
var systemPrompt =
"Summarize the following document in a single, concise paragraph. " +
"Capture the main argument and supporting points.";
Hlavní klíčové body:
var systemPrompt =
"Extract the three most important takeaways from the following document. " +
"Number each takeaway and keep each to one or two sentences.";
Pokud chcete vyzkoušet jiný styl, nahraďte Content hodnotu v systémové zprávě jednou z výzev. Model se řídí pokyny v systémovém promptu pro přizpůsobení formátu a hloubky souhrnu.
Zpracování více dokumentů
Rozšiřte aplikaci tak, aby shrnula všechny .txt soubory v adresáři. To je užitečné, když máte složku dokumentů, které potřebují souhrny.
Následující metoda iteruje všechny .txt soubory v daném adresáři a shrnuje jednotlivé soubory:
async Task SummarizeDirectoryAsync(
dynamic chatClient,
string directory,
string systemPrompt,
CancellationToken ct)
{
var txtFiles = Directory.GetFiles(directory, "*.txt")
.OrderBy(f => f)
.ToArray();
if (txtFiles.Length == 0)
{
Console.WriteLine($"No .txt files found in {directory}");
return;
}
foreach (var txtFile in txtFiles)
{
var fileContent = await File.ReadAllTextAsync(txtFile, ct);
var msgs = new List<ChatMessage>
{
new ChatMessage { Role = "system", Content = systemPrompt },
new ChatMessage { Role = "user", Content = fileContent }
};
Console.WriteLine($"--- {Path.GetFileName(txtFile)} ---");
var resp = await chatClient.CompleteChatAsync(msgs, ct);
Console.WriteLine(resp.Choices[0].Message.Content);
Console.WriteLine();
}
}
Každý soubor je přečten, spárován se stejným systémovým promptem a je odeslán do modelu nezávisle. Model nepřenáší kontext mezi soubory, takže každý souhrn je samostatný.
Kompletní kód
Nahraďte obsah Program.cs následujícím úplným kódem:
using Microsoft.AI.Foundry.Local;
using Betalgo.Ranul.OpenAI.ObjectModels.RequestModels;
using Microsoft.Extensions.Logging;
CancellationToken ct = CancellationToken.None;
var config = new Configuration
{
AppName = "foundry_local_samples",
LogLevel = Microsoft.AI.Foundry.Local.LogLevel.Information
};
using var loggerFactory = LoggerFactory.Create(builder =>
{
builder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Information);
});
var logger = loggerFactory.CreateLogger<Program>();
// Initialize the singleton instance
await FoundryLocalManager.CreateAsync(config, logger);
var mgr = FoundryLocalManager.Instance;
// Download and register all execution providers.
var currentEp = "";
await mgr.DownloadAndRegisterEpsAsync((epName, percent) =>
{
if (epName != currentEp)
{
if (currentEp != "") Console.WriteLine();
currentEp = epName;
}
Console.Write($"\r {epName.PadRight(30)} {percent,6:F1}%");
});
if (currentEp != "") Console.WriteLine();
// Select and load a model from the catalog
var catalog = await mgr.GetCatalogAsync();
var model = await catalog.GetModelAsync("qwen2.5-0.5b")
?? throw new Exception("Model not found");
await model.DownloadAsync(progress =>
{
Console.Write($"\rDownloading model: {progress:F2}%");
if (progress >= 100f) Console.WriteLine();
});
await model.LoadAsync();
Console.WriteLine("Model loaded and ready.\n");
// Get a chat client
var chatClient = await model.GetChatClientAsync();
var systemPrompt =
"Summarize the following document into concise bullet points. " +
"Focus on the key points and main ideas.";
var target = args.Length > 0 ? args[0] : "document.txt";
if (Directory.Exists(target))
{
await SummarizeDirectoryAsync(chatClient, target, systemPrompt, ct);
}
else
{
Console.WriteLine($"--- {Path.GetFileName(target)} ---");
await SummarizeFileAsync(chatClient, target, systemPrompt, ct);
}
// Clean up
await model.UnloadAsync();
Console.WriteLine("\nModel unloaded. Done!");
async Task SummarizeFileAsync(
dynamic client,
string filePath,
string prompt,
CancellationToken token)
{
var fileContent = await File.ReadAllTextAsync(filePath, token);
var messages = new List<ChatMessage>
{
new ChatMessage { Role = "system", Content = prompt },
new ChatMessage { Role = "user", Content = fileContent }
};
var response = await client.CompleteChatAsync(messages, token);
Console.WriteLine(response.Choices[0].Message.Content);
}
async Task SummarizeDirectoryAsync(
dynamic client,
string directory,
string prompt,
CancellationToken token)
{
var txtFiles = Directory.GetFiles(directory, "*.txt")
.OrderBy(f => f)
.ToArray();
if (txtFiles.Length == 0)
{
Console.WriteLine($"No .txt files found in {directory}");
return;
}
foreach (var txtFile in txtFiles)
{
Console.WriteLine($"--- {Path.GetFileName(txtFile)} ---");
await SummarizeFileAsync(client, txtFile, prompt, token);
Console.WriteLine();
}
}
Shrnout jeden soubor:
dotnet run -- document.txt
Nebo shrnout každý .txt soubor v adresáři:
dotnet run -- ./docs
Zobrazí se výstup podobný následujícímu:
Downloading model: 100.00%
Model loaded and ready.
--- document.txt ---
- Automated testing uses specialized tools to execute tests instead of manual verification.
- Tests fall into three main categories: unit tests (individual functions), integration tests
(component interactions), and end-to-end tests (full user workflows).
- Key benefits include catching regressions early, reducing manual effort, serving as living
documentation, and gating deployments through continuous integration pipelines.
- Effective test suites should be deterministic, independent, fast, and maintained alongside
production code.
Model unloaded. Done!
- Node.js 20 nebo novější.
Úložiště ukázek
Kompletní vzorový kód pro tento článek je k dispozici v úložišti foundry-samples GitHub. Pokud chcete naklonovat úložiště a přejít na ukázku, použijte:
git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/javascript/foundry-local/tutorial-document-summarizer
Instalace balíčků
Pokud vyvíjíte nebo vydáváte aplikace na Windows, vyberte kartu Windows. Balíček Windows se integruje s runtime modulem Windows ML — poskytuje stejné rozhraní API a nabízí širší možnosti hardwarové akcelerace.
npm install foundry-local-sdk-winml openai
Čtení textového dokumentu
Než něco shrnete, budete potřebovat ukázkový dokument, se kterým budete pracovat. Vytvořte soubor volaný document.txt v adresáři projektu a přidejte následující obsah:
Automated testing is a practice in software development where tests are written and executed
by specialized tools rather than performed manually. There are several categories of automated
tests, including unit tests, integration tests, and end-to-end tests. Unit tests verify that
individual functions or methods behave correctly in isolation. Integration tests check that
multiple components work together as expected. End-to-end tests simulate real user workflows
across the entire application.
Adopting automated testing brings measurable benefits to a development team. It catches
regressions early, before they reach production. It reduces the time spent on repetitive
manual verification after each code change. It serves as living documentation of expected
behavior, which helps new team members understand the codebase. Continuous integration
pipelines rely on automated tests to gate deployments and maintain release quality.
Effective test suites follow a few guiding principles. Tests should be deterministic, meaning
they produce the same result every time they run. Tests should be independent, so that one
failing test does not cascade into false failures elsewhere. Tests should run fast, because
slow tests discourage developers from running them frequently. Finally, tests should be
maintained alongside production code so they stay accurate as the application evolves.
Teď vytvořte volaný index.js soubor a přidejte následující kód pro čtení dokumentu:
const target = process.argv[2] || 'document.txt';
Skript přijme volitelnou cestu k souboru jako argument příkazového řádku a pokud žádná není zadána, použije document.txt.
Vygenerování souhrnu
Inicializujte sadu Foundry Local SDK, načtěte model a odešlete obsah dokumentu spolu s výzvou systému, která dává modelu pokyn k shrnutí.
Obsah index.js nahraďte následujícím kódem:
const systemPrompt =
'Summarize the following document into concise bullet points. ' +
'Focus on the key points and main ideas.';
const target = process.argv[2] || 'document.txt';
try {
const stats = statSync(target);
if (stats.isDirectory()) {
await summarizeDirectory(chatClient, target, systemPrompt);
} else {
console.log(`--- ${basename(target)} ---`);
await summarizeFile(chatClient, target, systemPrompt);
}
} catch {
console.log(`--- ${basename(target)} ---`);
await summarizeFile(chatClient, target, systemPrompt);
}
Metoda getModel přijímá alias modelu, což je krátký přátelský název, který odpovídá konkrétnímu modelu v katalogu. Metoda download načte váhy modelu do místní mezipaměti (a přeskočí stahování, pokud už jsou uložené v mezipaměti) a load model je připravený k odvozování. Systémová výzva modelu určuje, aby vytvořil souhrny s odrážkami zaměřené na klíčové myšlenky.
Řídicí souhrnný výstup
Různé situace vyžadují různé styly shrnutí. Můžete změnit výzvu systému, abyste mohli řídit, jak model strukturuje svůj výstup. Tady jsou tři užitečné varianty:
Odrážky (výchozí hodnota z předchozího kroku):
const systemPrompt =
'Summarize the following document into concise bullet points. ' +
'Focus on the key points and main ideas.';
Shrnutí jednoho odstavce:
const systemPrompt =
'Summarize the following document in a single, concise paragraph. ' +
'Capture the main argument and supporting points.';
Hlavní klíčové body:
const systemPrompt =
'Extract the three most important takeaways from the following document. ' +
'Number each takeaway and keep each to one or two sentences.';
Pokud chcete vyzkoušet jiný styl, nahraďte content hodnotu v systémové zprávě jednou z výzev. Model se řídí pokyny v systémovém promptu pro přizpůsobení formátu a hloubky souhrnu.
Zpracování více dokumentů
Rozšiřte aplikaci tak, aby shrnula všechny .txt soubory v adresáři. To je užitečné, když máte složku dokumentů, které potřebují souhrny.
Následující funkce iteruje všechny .txt soubory v daném adresáři a shrnuje jednotlivé soubory:
import { readdirSync } from 'fs';
import { join, basename } from 'path';
async function summarizeDirectory(chatClient, directory, systemPrompt) {
const txtFiles = readdirSync(directory)
.filter(f => f.endsWith('.txt'))
.sort();
if (txtFiles.length === 0) {
console.log(`No .txt files found in ${directory}`);
return;
}
for (const fileName of txtFiles) {
const fileContent = readFileSync(join(directory, fileName), 'utf-8');
const msgs = [
{ role: 'system', content: systemPrompt },
{ role: 'user', content: fileContent }
];
console.log(`--- ${fileName} ---`);
const resp = await chatClient.completeChat(msgs);
console.log(resp.choices[0]?.message?.content);
console.log();
}
}
Každý soubor je přečten, spárován se stejným systémovým promptem a je odeslán do modelu nezávisle. Model nepřenáší kontext mezi soubory, takže každý souhrn je samostatný.
Kompletní kód
Vytvořte soubor s názvem index.js a přidejte následující úplný kód:
import { FoundryLocalManager } from 'foundry-local-sdk';
import { readFileSync, readdirSync, statSync } from 'fs';
import { join, basename } from 'path';
async function summarizeFile(chatClient, filePath, systemPrompt) {
const content = readFileSync(filePath, 'utf-8');
const messages = [
{ role: 'system', content: systemPrompt },
{ role: 'user', content: content }
];
const response = await chatClient.completeChat(messages);
console.log(response.choices[0]?.message?.content);
}
async function summarizeDirectory(chatClient, directory, systemPrompt) {
const txtFiles = readdirSync(directory)
.filter(f => f.endsWith('.txt'))
.sort();
if (txtFiles.length === 0) {
console.log(`No .txt files found in ${directory}`);
return;
}
for (const fileName of txtFiles) {
console.log(`--- ${fileName} ---`);
await summarizeFile(chatClient, join(directory, fileName), systemPrompt);
console.log();
}
}
// 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.\n');
// Create a chat client
const chatClient = model.createChatClient();
const systemPrompt =
'Summarize the following document into concise bullet points. ' +
'Focus on the key points and main ideas.';
const target = process.argv[2] || 'document.txt';
try {
const stats = statSync(target);
if (stats.isDirectory()) {
await summarizeDirectory(chatClient, target, systemPrompt);
} else {
console.log(`--- ${basename(target)} ---`);
await summarizeFile(chatClient, target, systemPrompt);
}
} catch {
console.log(`--- ${basename(target)} ---`);
await summarizeFile(chatClient, target, systemPrompt);
}
// Clean up
await model.unload();
console.log('\nModel unloaded. Done!');
Shrnout jeden soubor:
node index.js document.txt
Nebo shrnout každý .txt soubor v adresáři:
node index.js ./docs
Zobrazí se výstup podobný následujícímu:
Downloading model: 100.00%
Model downloaded.
Model loaded and ready.
--- document.txt ---
- Automated testing uses specialized tools to execute tests instead of manual verification.
- Tests fall into three main categories: unit tests (individual functions), integration tests
(component interactions), and end-to-end tests (full user workflows).
- Key benefits include catching regressions early, reducing manual effort, serving as living
documentation, and gating deployments through continuous integration pipelines.
- Effective test suites should be deterministic, independent, fast, and maintained alongside
production code.
Model unloaded. Done!
- Python 3.11 nebo novější.
Úložiště ukázek
Kompletní vzorový kód pro tento článek je k dispozici v úložišti foundry-samples GitHub. Pokud chcete naklonovat úložiště a přejít na ukázku, použijte:
git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/python/foundry-local/tutorial-document-summarizer
Instalace balíčků
Pokud vyvíjíte nebo vydáváte aplikace na Windows, vyberte kartu Windows. Balíček Windows se integruje s runtime modulem Windows ML — poskytuje stejné rozhraní API a nabízí širší možnosti hardwarové akcelerace.
pip install foundry-local-sdk-winml openai
Čtení textového dokumentu
Než něco shrnete, budete potřebovat ukázkový dokument, se kterým budete pracovat. Vytvořte soubor volaný document.txt v adresáři projektu a přidejte následující obsah:
Automated testing is a practice in software development where tests are written and executed
by specialized tools rather than performed manually. There are several categories of automated
tests, including unit tests, integration tests, and end-to-end tests. Unit tests verify that
individual functions or methods behave correctly in isolation. Integration tests check that
multiple components work together as expected. End-to-end tests simulate real user workflows
across the entire application.
Adopting automated testing brings measurable benefits to a development team. It catches
regressions early, before they reach production. It reduces the time spent on repetitive
manual verification after each code change. It serves as living documentation of expected
behavior, which helps new team members understand the codebase. Continuous integration
pipelines rely on automated tests to gate deployments and maintain release quality.
Effective test suites follow a few guiding principles. Tests should be deterministic, meaning
they produce the same result every time they run. Tests should be independent, so that one
failing test does not cascade into false failures elsewhere. Tests should run fast, because
slow tests discourage developers from running them frequently. Finally, tests should be
maintained alongside production code so they stay accurate as the application evolves.
Teď vytvořte volaný main.py soubor a přidejte následující kód pro čtení dokumentu:
target = sys.argv[1] if len(sys.argv) > 1 else "document.txt"
target_path = Path(target)
Skript přijme volitelnou cestu k souboru jako argument příkazového řádku a pokud žádná není zadána, použije document.txt. Metoda Path.read_text načte celý soubor do řetězce.
Vygenerování souhrnu
Inicializujte sadu Foundry Local SDK, načtěte model a odešlete obsah dokumentu spolu s výzvou systému, která dává modelu pokyn k shrnutí.
Obsah main.py nahraďte následujícím kódem:
system_prompt = (
"Summarize the following document into concise bullet points. "
"Focus on the key points and main ideas."
)
target = sys.argv[1] if len(sys.argv) > 1 else "document.txt"
target_path = Path(target)
if target_path.is_dir():
summarize_directory(client, target_path, system_prompt)
else:
print(f"--- {target_path.name} ---")
summarize_file(client, target_path, system_prompt)
Metoda get_model přijímá alias modelu, což je krátký přátelský název, který odpovídá konkrétnímu modelu v katalogu. Metoda download načte váhy modelu do místní mezipaměti (a přeskočí stahování, pokud už jsou uložené v mezipaměti) a load model je připravený k odvozování. Systémová výzva modelu určuje, aby vytvořil souhrny s odrážkami zaměřené na klíčové myšlenky.
Řídicí souhrnný výstup
Různé situace vyžadují různé styly shrnutí. Můžete změnit výzvu systému, abyste mohli řídit, jak model strukturuje svůj výstup. Tady jsou tři užitečné varianty:
Odrážky (výchozí hodnota z předchozího kroku):
system_prompt = (
"Summarize the following document into concise bullet points. "
"Focus on the key points and main ideas."
)
Shrnutí jednoho odstavce:
system_prompt = (
"Summarize the following document in a single, concise paragraph. "
"Capture the main argument and supporting points."
)
Hlavní klíčové body:
system_prompt = (
"Extract the three most important takeaways from the following document. "
"Number each takeaway and keep each to one or two sentences."
)
Pokud chcete vyzkoušet jiný styl, nahraďte "content" hodnotu v systémové zprávě jednou z výzev. Model se řídí pokyny v systémovém promptu pro přizpůsobení formátu a hloubky souhrnu.
Zpracování více dokumentů
Rozšiřte aplikaci tak, aby shrnula všechny .txt soubory v adresáři. To je užitečné, když máte složku dokumentů, které potřebují souhrny.
Následující funkce iteruje všechny .txt soubory v daném adresáři a shrnuje jednotlivé soubory:
async def summarize_directory(client, directory):
txt_files = sorted(Path(directory).glob("*.txt"))
if not txt_files:
print(f"No .txt files found in {directory}")
return
for txt_file in txt_files:
content = txt_file.read_text(encoding="utf-8")
messages = [
{
"role": "system",
"content": "Summarize the following document into concise bullet points. "
"Focus on the key points and main ideas."
},
{"role": "user", "content": content}
]
print(f"--- {txt_file.name} ---")
response = client.complete_chat(messages)
print(response.choices[0].message.content)
print()
Každý soubor je přečten, spárován se stejným systémovým promptem a je odeslán do modelu nezávisle. Model nepřenáší kontext mezi soubory, takže každý souhrn je samostatný.
Kompletní kód
Vytvořte soubor s názvem main.py a přidejte následující úplný kód:
import sys
from pathlib import Path
from foundry_local_sdk import Configuration, FoundryLocalManager
def summarize_file(client, file_path, system_prompt):
"""Summarize a single file and print the result."""
content = Path(file_path).read_text(encoding="utf-8")
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": content},
]
response = client.complete_chat(messages)
print(response.choices[0].message.content)
def summarize_directory(client, directory, system_prompt):
"""Summarize all .txt files in a directory."""
txt_files = sorted(Path(directory).glob("*.txt"))
if not txt_files:
print(f"No .txt files found in {directory}")
return
for txt_file in txt_files:
print(f"--- {txt_file.name} ---")
summarize_file(client, txt_file, system_prompt)
print()
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 p: print(f"\rDownloading model: {p:.2f}%", end="", flush=True)
)
print()
model.load()
print("Model loaded and ready.\n")
# Get a chat client
client = model.get_chat_client()
system_prompt = (
"Summarize the following document into concise bullet points. "
"Focus on the key points and main ideas."
)
target = sys.argv[1] if len(sys.argv) > 1 else "document.txt"
target_path = Path(target)
if target_path.is_dir():
summarize_directory(client, target_path, system_prompt)
else:
print(f"--- {target_path.name} ---")
summarize_file(client, target_path, system_prompt)
# Clean up
model.unload()
print("\nModel unloaded. Done!")
if __name__ == "__main__":
main()
Shrnout jeden soubor:
python main.py document.txt
Nebo shrnout každý .txt soubor v adresáři:
python main.py ./docs
Zobrazí se výstup podobný následujícímu:
Downloading model: 100.00%
Model loaded and ready.
--- document.txt ---
- Automated testing uses specialized tools to execute tests instead of manual verification.
- Tests fall into three main categories: unit tests (individual functions), integration tests
(component interactions), and end-to-end tests (full user workflows).
- Key benefits include catching regressions early, reducing manual effort, serving as living
documentation, and gating deployments through continuous integration pipelines.
- Effective test suites should be deterministic, independent, fast, and maintained alongside
production code.
Model unloaded. Done!
- Rust a Cargo nainstalované (Rust 1.70.0 nebo novější).
Úložiště ukázek
Kompletní vzorový kód pro tento článek je k dispozici v úložišti foundry-samples GitHub. Pokud chcete naklonovat úložiště a přejít na ukázku, použijte:
git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/rust/foundry-local/tutorial-document-summarizer
Instalace balíčků
Pokud vyvíjíte nebo vydáváte aplikace na Windows, vyberte kartu Windows. Balíček Windows se integruje s runtime modulem Windows ML — poskytuje stejné rozhraní API a nabízí širší možnosti hardwarové akcelerace.
cargo add foundry-local-sdk --features winml
cargo add tokio --features full
cargo add tokio-stream anyhow
Čtení textového dokumentu
Než něco shrnete, budete potřebovat ukázkový dokument, se kterým budete pracovat. Vytvořte soubor volaný document.txt v adresáři projektu a přidejte následující obsah:
Automated testing is a practice in software development where tests are written and executed
by specialized tools rather than performed manually. There are several categories of automated
tests, including unit tests, integration tests, and end-to-end tests. Unit tests verify that
individual functions or methods behave correctly in isolation. Integration tests check that
multiple components work together as expected. End-to-end tests simulate real user workflows
across the entire application.
Adopting automated testing brings measurable benefits to a development team. It catches
regressions early, before they reach production. It reduces the time spent on repetitive
manual verification after each code change. It serves as living documentation of expected
behavior, which helps new team members understand the codebase. Continuous integration
pipelines rely on automated tests to gate deployments and maintain release quality.
Effective test suites follow a few guiding principles. Tests should be deterministic, meaning
they produce the same result every time they run. Tests should be independent, so that one
failing test does not cascade into false failures elsewhere. Tests should run fast, because
slow tests discourage developers from running them frequently. Finally, tests should be
maintained alongside production code so they stay accurate as the application evolves.
Teď otevřete src/main.rs a přidejte následující kód, který dokument přečte:
let target = env::args()
.nth(1)
.unwrap_or_else(|| "document.txt".to_string());
let target_path = Path::new(&target);
Kód přijme volitelnou cestu k souboru jako argument příkazového řádku a použije document.txt, pokud žádná není poskytnuta.
Vygenerování souhrnu
Inicializujte sadu Foundry Local SDK, načtěte model a odešlete obsah dokumentu spolu s výzvou systému, která dává modelu pokyn k shrnutí.
Obsah src/main.rs nahraďte následujícím kódem:
let system_prompt = "Summarize the following document \
into concise bullet points. Focus on the key \
points and main ideas.";
let target = env::args()
.nth(1)
.unwrap_or_else(|| "document.txt".to_string());
let target_path = Path::new(&target);
if target_path.is_dir() {
summarize_directory(
&client,
target_path,
system_prompt,
)
.await?;
} else {
let file_name = target_path
.file_name()
.map(|n| n.to_string_lossy().to_string())
.unwrap_or_else(|| target.clone());
println!("--- {} ---", file_name);
summarize_file(
&client,
target_path,
system_prompt,
)
.await?;
}
Metoda get_model přijímá alias modelu, což je krátký přátelský název, který odpovídá konkrétnímu modelu v katalogu. Metoda download načte váhy modelu do místní mezipaměti (a přeskočí stahování, pokud už jsou uložené v mezipaměti) a load model je připravený k odvozování. Systémová výzva modelu určuje, aby vytvořil souhrny s odrážkami zaměřené na klíčové myšlenky.
Řídicí souhrnný výstup
Různé situace vyžadují různé styly shrnutí. Můžete změnit výzvu systému, abyste mohli řídit, jak model strukturuje svůj výstup. Tady jsou tři užitečné varianty:
Odrážky (výchozí hodnota z předchozího kroku):
let system_prompt =
"Summarize the following document into concise bullet points. \
Focus on the key points and main ideas.";
Shrnutí jednoho odstavce:
let system_prompt =
"Summarize the following document in a single, concise paragraph. \
Capture the main argument and supporting points.";
Hlavní klíčové body:
let system_prompt =
"Extract the three most important takeaways from the following document. \
Number each takeaway and keep each to one or two sentences.";
Pokud chcete vyzkoušet jiný styl, nahraďte obsah systémové zprávy jedním z výzev. Model se řídí pokyny v systémovém promptu pro přizpůsobení formátu a hloubky souhrnu.
Zpracování více dokumentů
Rozšiřte aplikaci tak, aby shrnula všechny .txt soubory v adresáři. To je užitečné, když máte složku dokumentů, které potřebují souhrny.
Následující funkce iteruje všechny .txt soubory v daném adresáři a shrnuje jednotlivé soubory:
use std::path::Path;
async fn summarize_directory(
client: &foundry_local_sdk::ChatClient,
directory: &Path,
system_prompt: &str,
) -> anyhow::Result<()> {
let mut txt_files: Vec<_> = fs::read_dir(directory)?
.filter_map(|entry| entry.ok())
.filter(|entry| {
entry.path().extension()
.map(|ext| ext == "txt")
.unwrap_or(false)
})
.collect();
txt_files.sort_by_key(|e| e.path());
if txt_files.is_empty() {
println!("No .txt files found in {}", directory.display());
return Ok(());
}
for entry in &txt_files {
let file_content = fs::read_to_string(entry.path())?;
let messages: Vec<ChatCompletionRequestMessage> = vec![
ChatCompletionRequestSystemMessage::new(system_prompt).into(),
ChatCompletionRequestUserMessage::new(&file_content).into(),
];
let file_name = entry.file_name();
println!("--- {} ---", file_name.to_string_lossy());
let resp = client.complete_chat(&messages, None).await?;
let text = resp.choices[0]
.message
.content
.as_deref()
.unwrap_or("");
println!("{}\n", text);
}
Ok(())
}
Každý soubor je přečten, spárován se stejným systémovým promptem a je odeslán do modelu nezávisle. Model nepřenáší kontext mezi soubory, takže každý souhrn je samostatný.
Kompletní kód
Nahraďte obsah src/main.rs následujícím úplným kódem:
use foundry_local_sdk::{
ChatCompletionRequestMessage,
ChatCompletionRequestSystemMessage,
ChatCompletionRequestUserMessage, FoundryLocalConfig,
FoundryLocalManager,
};
use std::io::{self, Write};
use std::path::Path;
use std::{env, fs};
async fn summarize_file(
client: &foundry_local_sdk::openai::ChatClient,
file_path: &Path,
system_prompt: &str,
) -> anyhow::Result<()> {
let content = fs::read_to_string(file_path)?;
let messages: Vec<ChatCompletionRequestMessage> = vec![
ChatCompletionRequestSystemMessage::from(system_prompt)
.into(),
ChatCompletionRequestUserMessage::from(content.as_str())
.into(),
];
let response =
client.complete_chat(&messages, None).await?;
let summary = response.choices[0]
.message
.content
.as_deref()
.unwrap_or("");
println!("{}", summary);
Ok(())
}
async fn summarize_directory(
client: &foundry_local_sdk::openai::ChatClient,
directory: &Path,
system_prompt: &str,
) -> anyhow::Result<()> {
let mut txt_files: Vec<_> = fs::read_dir(directory)?
.filter_map(|entry| entry.ok())
.filter(|entry| {
entry
.path()
.extension()
.map(|ext| ext == "txt")
.unwrap_or(false)
})
.collect();
txt_files.sort_by_key(|e| e.path());
if txt_files.is_empty() {
println!(
"No .txt files found in {}",
directory.display()
);
return Ok(());
}
for entry in &txt_files {
let file_name = entry.file_name();
println!(
"--- {} ---",
file_name.to_string_lossy()
);
summarize_file(
client,
&entry.path(),
system_prompt,
)
.await?;
println!();
}
Ok(())
}
#[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.\n");
// Create a chat client
let client = model
.create_chat_client()
.temperature(0.7)
.max_tokens(512);
let system_prompt = "Summarize the following document \
into concise bullet points. Focus on the key \
points and main ideas.";
let target = env::args()
.nth(1)
.unwrap_or_else(|| "document.txt".to_string());
let target_path = Path::new(&target);
if target_path.is_dir() {
summarize_directory(
&client,
target_path,
system_prompt,
)
.await?;
} else {
let file_name = target_path
.file_name()
.map(|n| n.to_string_lossy().to_string())
.unwrap_or_else(|| target.clone());
println!("--- {} ---", file_name);
summarize_file(
&client,
target_path,
system_prompt,
)
.await?;
}
// Clean up
model.unload().await?;
println!("\nModel unloaded. Done!");
Ok(())
}
Shrnout jeden soubor:
cargo run -- document.txt
Nebo shrnout každý .txt soubor v adresáři:
cargo run -- ./docs
Zobrazí se výstup podobný následujícímu:
Downloading model: 100.00%
Model loaded and ready.
--- document.txt ---
- Automated testing uses specialized tools to execute tests instead of manual verification.
- Tests fall into three main categories: unit tests (individual functions), integration tests
(component interactions), and end-to-end tests (full user workflows).
- Key benefits include catching regressions early, reducing manual effort, serving as living
documentation, and gating deployments through continuous integration pipelines.
- Effective test suites should be deterministic, independent, fast, and maintained alongside
production code.
Model unloaded. Done!
Vyčistěte zdroje
Váhy modelu zůstanou v místní mezipaměti po uvolnění modelu. To znamená, že při příštím spuštění aplikace se krok stahování přeskočí a model se načte rychleji. Pokud nechcete uvolnit místo na disku, není potřeba žádné další vyčištění.