Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Bouw een toepassing die tekstbestanden leest en beknopte samenvattingen genereert, volledig op uw apparaat. Dit is handig wanneer u snel inzicht moet hebben in de inhoud van documenten zonder ze volledig te lezen en wanneer de documenten gevoelige informatie bevatten die uw computer niet mag verlaten.
In deze handleiding leer je hoe je:
- Een project instellen en de Foundry Local SDK installeren
- Een tekstdocument lezen uit het bestandssysteem
- Een model laden en een samenvatting genereren
- Samenvattingsuitvoer beheren met systeemprompts
- Meerdere documenten in een batch verwerken
- De hulpbronnen opschonen
Vereiste voorwaarden
- Een Windows-, macOS- of Linux-computer met ten minste 8 GB RAM-geheugen.
Pakketten installeren
Opslagplaats met voorbeelden
De volledige voorbeeldcode voor dit artikel is beschikbaar in de opslagplaats Foundry Local GitHub. Om de opslagplaats te klonen en naar het voorbeeld te navigeren, gebruik:
git clone https://github.com/microsoft/Foundry-Local.git
cd Foundry-Local/samples/cs/tutorial-document-summarizer
Als u op Windows ontwikkelt of verzendt, selecteert u het tabblad Windows. Het Windows-pakket kan worden geïntegreerd met de Windows ML runtime. Het biedt hetzelfde API-oppervlak met een grotere breedte van hardwareversnelling.
dotnet add package Microsoft.AI.Foundry.Local.WinML
dotnet add package OpenAI
De C#-voorbeelden in de GitHub opslagplaats zijn vooraf geconfigureerde projecten. Als u helemaal opnieuw bouwt, leest u de referentie voor de Local SDK van Foundry voor meer informatie over het instellen van uw C#-project met Foundry Local.
Een tekstdocument lezen
Voordat u iets samenvat, hebt u een voorbeelddocument nodig om mee te werken. Maak een bestand met de naam document.txt in de projectmap en voeg de volgende inhoud toe:
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.
Program.cs Open en voeg nu de volgende code toe om het document te lezen:
var target = args.Length > 0 ? args[0] : "document.txt";
De code accepteert een optioneel bestandspad als opdrachtregelargument en valt terug op document.txt als er geen wordt opgegeven.
Een samenvatting genereren
Initialiseer de Foundry Local SDK, laad een model en verzend de documentinhoud samen met een systeemprompt waarmee het model wordt samengevat.
Vervang de inhoud van Program.cs met de volgende code:
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);
}
De GetModelAsync methode accepteert een modelalias, een korte beschrijvende naam die wordt toegewezen aan een specifiek model in de catalogus. De DownloadAsync methode haalt de modelgewichten op in uw lokale cache (en slaat de download over als ze al in de cache zijn opgeslagen) en LoadAsync maakt het model gereed voor deductie. De systeemprompt instrueert het model om samenvattingen in opsomming te produceren die zijn gericht op belangrijke ideeën.
Samenvatting van de controle-uitvoer
Verschillende situaties roepen verschillende samenvattingsstijlen op. U kunt de systeemprompt wijzigen om te bepalen hoe het model de uitvoer structureert. Hier volgen drie nuttige variaties:
Opsommingstekens (standaard uit de vorige stap):
var systemPrompt =
"Summarize the following document into concise bullet points. " +
"Focus on the key points and main ideas.";
Samenvatting van één alinea:
var systemPrompt =
"Summarize the following document in a single, concise paragraph. " +
"Capture the main argument and supporting points.";
Belangrijkste conclusies:
var systemPrompt =
"Extract the three most important takeaways from the following document. " +
"Number each takeaway and keep each to one or two sentences.";
Als u een andere stijl wilt proberen, vervangt u de Content waarde in het systeembericht door een van de prompts. Het model volgt de instructies in de systeemprompt om de indeling en diepte van de samenvatting vorm te geven.
Meerdere documenten verwerken
Breid de toepassing uit om elk .txt bestand in een map samen te vatten. Dit is handig wanneer u een map met documenten hebt die allemaal samenvattingen nodig hebben.
Met de volgende methode worden alle .txt bestanden in een bepaalde map geïtereerd en wordt elk bestand samengevat.
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();
}
}
Elk bestand wordt afzonderlijk gelezen, gekoppeld aan dezelfde systeemprompt en naar het model verzonden. Het model draagt geen context tussen bestanden, dus elke samenvatting staat op zichzelf.
Volledige code
Vervang de inhoud van Program.cs door de volgende volledige code:
using Microsoft.AI.Foundry.Local;
using Betalgo.Ranul.OpenAI.ObjectModels.RequestModels;
using Microsoft.Extensions.Logging;
CancellationToken ct = CancellationToken.None;
var config = new Configuration
{
AppName = "foundry_local_samples",
LogLevel = Microsoft.AI.Foundry.Local.LogLevel.Information
};
using var loggerFactory = LoggerFactory.Create(builder =>
{
builder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Information);
});
var logger = loggerFactory.CreateLogger<Program>();
// Initialize the singleton instance
await FoundryLocalManager.CreateAsync(config, logger);
var mgr = FoundryLocalManager.Instance;
// Download and register all execution providers.
var currentEp = "";
await mgr.DownloadAndRegisterEpsAsync((epName, percent) =>
{
if (epName != currentEp)
{
if (currentEp != "") Console.WriteLine();
currentEp = epName;
}
Console.Write($"\r {epName.PadRight(30)} {percent,6:F1}%");
});
if (currentEp != "") Console.WriteLine();
// Select and load a model from the catalog
var catalog = await mgr.GetCatalogAsync();
var model = await catalog.GetModelAsync("qwen2.5-0.5b")
?? throw new Exception("Model not found");
await model.DownloadAsync(progress =>
{
Console.Write($"\rDownloading model: {progress:F2}%");
if (progress >= 100f) Console.WriteLine();
});
await model.LoadAsync();
Console.WriteLine("Model loaded and ready.\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();
}
}
Eén bestand samenvatten:
dotnet run -- document.txt
U kunt ook elk .txt bestand in een map samenvatten:
dotnet run -- ./docs
De uitvoer ziet er ongeveer als volgt uit:
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!
Pakketten installeren
Opslagplaats met voorbeelden
De volledige voorbeeldcode voor dit artikel is beschikbaar in de opslagplaats Foundry Local GitHub. Kloon de repository en navigeer naar het voorbeeld:
git clone https://github.com/microsoft/Foundry-Local.git
cd Foundry-Local/samples/js/tutorial-document-summarizer
Als u op Windows ontwikkelt of verzendt, selecteert u het tabblad Windows. Het Windows-pakket kan worden geïntegreerd met de Windows ML runtime. Het biedt hetzelfde API-oppervlak met een grotere breedte van hardwareversnelling.
npm install foundry-local-sdk-winml openai
Een tekstdocument lezen
Voordat u iets samenvat, hebt u een voorbeelddocument nodig om mee te werken. Maak een bestand met de naam document.txt in de projectmap en voeg de volgende inhoud toe:
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.
Maak nu een bestand met de naam index.js en voeg de volgende code toe om het document te lezen:
const target = process.argv[2] || 'document.txt';
Het script accepteert een optioneel bestandspad als opdrachtregelargument en valt terug op document.txt als er geen wordt opgegeven.
Een samenvatting genereren
Initialiseer de Foundry Local SDK, laad een model en verzend de documentinhoud samen met een systeemprompt waarmee het model wordt samengevat.
Vervang de inhoud van index.js met de volgende code:
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);
}
De getModel methode accepteert een modelalias, een korte beschrijvende naam die wordt toegewezen aan een specifiek model in de catalogus. De download methode haalt de modelgewichten op in uw lokale cache (en slaat de download over als ze al in de cache zijn opgeslagen) en load maakt het model gereed voor deductie. De systeemprompt instrueert het model om opsommingspunten te produceren gericht op belangrijke ideeën.
Samenvatting van controles-uitvoer
Verschillende situaties roepen verschillende samenvattingsstijlen op. U kunt de systeemprompt wijzigen om te bepalen hoe het model de uitvoer structureert. Hier volgen drie nuttige variaties:
Opsommingstekens (standaard uit de vorige stap):
const systemPrompt =
'Summarize the following document into concise bullet points. ' +
'Focus on the key points and main ideas.';
Samenvatting van één alinea:
const systemPrompt =
'Summarize the following document in a single, concise paragraph. ' +
'Capture the main argument and supporting points.';
Belangrijkste conclusies:
const systemPrompt =
'Extract the three most important takeaways from the following document. ' +
'Number each takeaway and keep each to one or two sentences.';
Als u een andere stijl wilt proberen, vervangt u de content waarde in het systeembericht door een van de prompts. Het model volgt de instructies in de systeemprompt om de indeling en diepte van de samenvatting vorm te geven.
Meerdere documenten verwerken
Breid de toepassing uit om elk .txt bestand in een map samen te vatten. Dit is handig wanneer u een map met documenten hebt die allemaal samenvattingen nodig hebben.
Met de volgende functie itereren we over alle .txt bestanden in een bepaalde map en wordt elk bestand samengevat.
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();
}
}
Elk bestand wordt afzonderlijk gelezen, gekoppeld aan dezelfde systeemprompt en naar het model verzonden. Het model draagt geen context tussen bestanden, dus elke samenvatting staat op zichzelf.
Volledige code
Maak een bestand met de naam index.js en voeg de volgende volledige code toe:
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!');
Eén bestand samenvatten:
node index.js document.txt
U kunt ook elk .txt bestand in een map samenvatten:
node index.js ./docs
De uitvoer ziet er ongeveer als volgt uit:
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!
Pakketten installeren
Opslagplaats met voorbeelden
De volledige voorbeeldcode voor dit artikel is beschikbaar in de opslagplaats Foundry Local GitHub. Om de opslagplaats te klonen en naar het voorbeeld te navigeren, gebruikt u:
git clone https://github.com/microsoft/Foundry-Local.git
cd Foundry-Local/samples/python/tutorial-document-summarizer
Als u op Windows ontwikkelt of verzendt, selecteert u het tabblad Windows. Het Windows-pakket kan worden geïntegreerd met de Windows ML runtime. Het biedt hetzelfde API-oppervlak met een grotere breedte van hardwareversnelling.
pip install foundry-local-sdk-winml openai
Een tekstdocument lezen
Voordat u iets samenvat, hebt u een voorbeelddocument nodig om mee te werken. Maak een bestand met de naam document.txt in de projectmap en voeg de volgende inhoud toe:
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.
Maak nu een bestand met de naam main.py en voeg de volgende code toe om het document te lezen:
target = sys.argv[1] if len(sys.argv) > 1 else "document.txt"
target_path = Path(target)
Het script accepteert een optioneel bestandspad als opdrachtregelargument en valt terug op document.txt als er geen wordt opgegeven. De Path.read_text-methode leest het hele bestand in als een tekenreeks.
Een samenvatting genereren
Initialiseer de Foundry Local SDK, laad een model en verzend de documentinhoud samen met een systeemprompt waarmee het model wordt samengevat.
Vervang de inhoud van main.py met de volgende code:
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)
De get_model methode accepteert een modelalias, een korte beschrijvende naam die wordt toegewezen aan een specifiek model in de catalogus. De download methode haalt de modelgewichten op in uw lokale cache (en slaat de download over als ze al in de cache zijn opgeslagen) en load maakt het model gereed voor deductie. De systeemprompt vraagt het model om samenvattingen in opsommingstekens te maken die gericht zijn op belangrijke ideeën.
Uitvoer van de controlesamenvatting
Verschillende situaties roepen verschillende samenvattingsstijlen op. U kunt de systeemprompt wijzigen om te bepalen hoe het model de uitvoer structureert. Hier volgen drie nuttige variaties:
Opsommingstekens (standaard uit de vorige stap):
system_prompt = (
"Summarize the following document into concise bullet points. "
"Focus on the key points and main ideas."
)
Samenvatting van één alinea:
system_prompt = (
"Summarize the following document in a single, concise paragraph. "
"Capture the main argument and supporting points."
)
Belangrijkste conclusies:
system_prompt = (
"Extract the three most important takeaways from the following document. "
"Number each takeaway and keep each to one or two sentences."
)
Als u een andere stijl wilt proberen, vervangt u de "content" waarde in het systeembericht door een van de prompts. Het model volgt de instructies in de systeemprompt om de indeling en diepte van de samenvatting vorm te geven.
Meerdere documenten verwerken
Breid de toepassing uit om elk .txt bestand in een map samen te vatten. Dit is handig wanneer u een map met documenten hebt die allemaal samenvattingen nodig hebben.
Met de volgende functie itereren we over alle .txt bestanden in een bepaalde map en wordt elk bestand samengevat.
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()
Elk bestand wordt afzonderlijk gelezen, gekoppeld aan dezelfde systeemprompt en naar het model verzonden. Het model draagt geen context tussen bestanden, dus elke samenvatting staat op zichzelf.
Volledige code
Maak een bestand met de naam main.py en voeg de volgende volledige code toe:
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()
Eén bestand samenvatten:
python main.py document.txt
U kunt ook elk .txt bestand in een map samenvatten:
python main.py ./docs
De uitvoer ziet er ongeveer als volgt uit:
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!
Pakketten installeren
Opslagplaats met voorbeelden
De volledige voorbeeldcode voor dit artikel is beschikbaar in de opslagplaats Foundry Local GitHub. Om de opslagplaats te klonen en naar het voorbeeld te navigeren, gebruikt u:
git clone https://github.com/microsoft/Foundry-Local.git
cd Foundry-Local/samples/rust/tutorial-document-summarizer
Als u op Windows ontwikkelt of verzendt, selecteert u het tabblad Windows. Het Windows-pakket kan worden geïntegreerd met de Windows ML runtime. Het biedt hetzelfde API-oppervlak met een grotere breedte van hardwareversnelling.
cargo add foundry-local-sdk --features winml
cargo add tokio --features full
cargo add tokio-stream anyhow
Een tekstdocument lezen
Voordat u iets samenvat, hebt u een voorbeelddocument nodig om mee te werken. Maak een bestand met de naam document.txt in de projectmap en voeg de volgende inhoud toe:
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.
src/main.rs Open en voeg nu de volgende code toe om het document te lezen:
let target = env::args()
.nth(1)
.unwrap_or_else(|| "document.txt".to_string());
let target_path = Path::new(&target);
De code accepteert een optioneel bestandspad als opdrachtregelargument en valt terug op document.txt als er geen wordt opgegeven.
Een samenvatting genereren
Initialiseer de Foundry Local SDK, laad een model en verzend de documentinhoud samen met een systeemprompt waarmee het model wordt samengevat.
Vervang de inhoud van src/main.rs met de volgende code:
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?;
}
De get_model methode accepteert een modelalias, een korte beschrijvende naam die wordt toegewezen aan een specifiek model in de catalogus. De download methode haalt de modelgewichten op in uw lokale cache (en slaat de download over als ze al in de cache zijn opgeslagen) en load maakt het model gereed voor deductie. De systeemprompt vraagt het model om samenvattingen in opsommingstekens te maken die gericht zijn op belangrijke ideeën.
Uitvoer van de controlesamenvatting
Verschillende situaties roepen verschillende samenvattingsstijlen op. U kunt de systeemprompt wijzigen om te bepalen hoe het model de uitvoer structureert. Hier volgen drie nuttige variaties:
Opsommingstekens (standaard uit de vorige stap):
let system_prompt =
"Summarize the following document into concise bullet points. \
Focus on the key points and main ideas.";
Samenvatting van één alinea:
let system_prompt =
"Summarize the following document in a single, concise paragraph. \
Capture the main argument and supporting points.";
Belangrijkste conclusies:
let system_prompt =
"Extract the three most important takeaways from the following document. \
Number each takeaway and keep each to one or two sentences.";
Als u een andere stijl wilt proberen, vervangt u de inhoud van het systeembericht door een van de prompts. Het model volgt de instructies in de systeemprompt om de indeling en diepte van de samenvatting vorm te geven.
Meerdere documenten verwerken
Breid de toepassing uit om elk .txt bestand in een map samen te vatten. Dit is handig wanneer u een map met documenten hebt die allemaal samenvattingen nodig hebben.
Met de volgende functie itereren we over alle .txt bestanden in een bepaalde map en wordt elk bestand samengevat.
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(())
}
Elk bestand wordt afzonderlijk gelezen, gekoppeld aan dezelfde systeemprompt en naar het model verzonden. Het model draagt geen context tussen bestanden, dus elke samenvatting staat op zichzelf.
Volledige code
Vervang de inhoud van src/main.rs door de volgende volledige code:
use foundry_local_sdk::{
ChatCompletionRequestMessage,
ChatCompletionRequestSystemMessage,
ChatCompletionRequestUserMessage, FoundryLocalConfig,
FoundryLocalManager,
};
use std::io::{self, 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("doc-summarizer"),
)?;
// 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(())
}
Eén bestand samenvatten:
cargo run -- document.txt
U kunt ook elk .txt bestand in een map samenvatten:
cargo run -- ./docs
De uitvoer ziet er ongeveer als volgt uit:
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!
De hulpbronnen opschonen
De modelgewichten blijven in uw lokale cache staan nadat u een model hebt uitgeladen. Dit betekent dat de volgende keer dat u de toepassing uitvoert, de downloadstap wordt overgeslagen en het model sneller wordt geladen. Er is geen extra opschoonbewerking nodig, tenzij u schijfruimte wilt vrijmaken.