Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Skapa ett program som läser textfiler och genererar kortfattade sammanfattningar – helt på enheten. Detta är användbart när du snabbt behöver förstå innehållet i dokument utan att läsa dem i sin helhet och när dokumenten innehåller känslig information som inte bör lämna datorn.
I den här tutorialen lär du dig följande:
- Konfigurera ett projekt och installera Foundry Local SDK
- Läsa ett textdokument från filsystemet
- Läsa in en modell och generera en sammanfattning
- Kontrollera sammanfattningsutdata med systemprompter
- Bearbeta flera dokument i en batch
- Rensa resurser
Förutsättningar
- En Windows-, macOS- eller Linux-dator med minst 8 GB RAM-minne.
Installera paket
Exempellagringsplats
Den fullständiga exempelkoden för den här artikeln finns på lagringsplatsen Foundry Local GitHub. Klona lagringsplatsen och gå till exempelanvändningen:
git clone https://github.com/microsoft/Foundry-Local.git
cd Foundry-Local/samples/cs/tutorial-document-summarizer
Om du utvecklar eller skickar på Windows väljer du fliken Windows. Windows-paketet integreras med Windows ML-körning – det ger samma API-yta med en bredare bredd av maskinvaruacceleration.
dotnet add package Microsoft.AI.Foundry.Local.WinML
dotnet add package OpenAI
C#-exemplen på GitHub-lagringsplatsen är förkonfigurerade projekt. Om du skapar från grunden bör du läsa Foundry Local SDK-referensen för mer information om hur du konfigurerar ditt C#-projekt med Foundry Local.
Läsa ett textdokument
Innan du sammanfattar något behöver du ett exempeldokument att arbeta med. Skapa en fil med namnet document.txt i projektkatalogen och lägg till följande innehåll:
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 Öppna nu och lägg till följande kod för att läsa dokumentet:
var target = args.Length > 0 ? args[0] : "document.txt";
Koden accepterar en valfri filsökväg som ett kommandoradsargument och återgår till document.txt om ingen anges.
Generera en sammanfattning
Initiera Foundry Local SDK, läs in en modell och skicka dokumentinnehållet tillsammans med en systemprompt som instruerar modellen att sammanfatta.
Ersätt innehållet i Program.cs med följande kod:
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);
}
Metoden GetModelAsync accepterar ett modellalias, vilket är ett kort eget namn som mappar till en specifik modell i katalogen. Metoden DownloadAsync hämtar modellvikterna till din lokala cache (och hoppar över nedladdningen om de redan är cachelagrade) och LoadAsync gör modellen redo för slutsatsdragning. Systemprompten instruerar modellen att skapa punktsammanfattningar som fokuserar på viktiga idéer.
Kontrollsammanfattningsutdata
Olika situationer kräver olika sammanfattningsformat. Du kan ändra systemprompten för att styra hur modellen strukturerar sina utdata. Här är tre användbara varianter:
Punktpunkter (standard från föregående steg):
var systemPrompt =
"Summarize the following document into concise bullet points. " +
"Focus on the key points and main ideas.";
Sammanfattning av ett stycke:
var systemPrompt =
"Summarize the following document in a single, concise paragraph. " +
"Capture the main argument and supporting points.";
Nyckelinsikter:
var systemPrompt =
"Extract the three most important takeaways from the following document. " +
"Number each takeaway and keep each to one or two sentences.";
För att prova en annan stil, ersätt Content värdet i systemmeddelandet med en av anvisningarna. Modellen följer anvisningarna i systemprompten för att forma sammanfattningens format och djup.
Bearbeta flera dokument
Utöka programmet för att sammanfatta varje .txt fil i en katalog. Detta är användbart när du har en mapp med dokument som alla behöver sammanfattningar.
Följande metod itererar över alla .txt filer i en viss katalog och sammanfattar var och en:
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();
}
}
Varje fil läss, paras ihop med samma systemprompt och skickas till modellen oberoende av varandra. Modellen har inte kontext mellan filer, så varje sammanfattning är fristående.
Fullständig kod
Ersätt innehållet i Program.cs med följande fullständiga kod:
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();
}
}
Sammanfatta en enskild fil:
dotnet run -- document.txt
Eller sammanfatta varje .txt fil i en katalog:
dotnet run -- ./docs
Du ser utdata som liknar:
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!
Installera paket
Exempellagringsplats
Den fullständiga exempelkoden för den här artikeln finns på lagringsplatsen Foundry Local GitHub. Klona lagringsplatsen och gå till exempelanvändningen:
git clone https://github.com/microsoft/Foundry-Local.git
cd Foundry-Local/samples/js/tutorial-document-summarizer
Om du utvecklar eller skickar på Windows väljer du fliken Windows. Windows-paketet integreras med Windows ML-körning – det ger samma API-yta med en bredare bredd av maskinvaruacceleration.
npm install foundry-local-sdk-winml openai
Läsa ett textdokument
Innan du sammanfattar något behöver du ett exempeldokument att arbeta med. Skapa en fil med namnet document.txt i projektkatalogen och lägg till följande innehåll:
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.
Skapa nu en fil med namnet index.js och lägg till följande kod för att läsa dokumentet:
const target = process.argv[2] || 'document.txt';
Skriptet accepterar en valfri filsökväg som kommandoradsargument och återgår till document.txt om ingen anges.
Generera en sammanfattning
Initiera Foundry Local SDK, läs in en modell och skicka dokumentinnehållet tillsammans med en systemprompt som instruerar modellen att sammanfatta.
Ersätt innehållet i index.js med följande kod:
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);
}
Metoden getModel accepterar ett modellalias, vilket är ett kort eget namn som mappar till en specifik modell i katalogen. Metoden download hämtar modellvikterna till din lokala cache (och hoppar över nedladdningen om de redan är cachelagrade) och load gör modellen redo för slutsatsdragning. Systemprompten instruerar modellen att skapa punktsammanfattningar som fokuserar på viktiga idéer.
Kontrollsammanfattningsutdata
Olika situationer kräver olika sammanfattningsformat. Du kan ändra systemprompten för att styra hur modellen strukturerar sina utdata. Här är tre användbara varianter:
Punktpunkter (standard från föregående steg):
const systemPrompt =
'Summarize the following document into concise bullet points. ' +
'Focus on the key points and main ideas.';
Sammanfattning av ett stycke:
const systemPrompt =
'Summarize the following document in a single, concise paragraph. ' +
'Capture the main argument and supporting points.';
Nyckelinsikter:
const systemPrompt =
'Extract the three most important takeaways from the following document. ' +
'Number each takeaway and keep each to one or two sentences.';
För att prova en annan stil, ersätt content värdet i systemmeddelandet med en av anvisningarna. Modellen följer anvisningarna i systemprompten för att forma sammanfattningens format och djup.
Bearbeta flera dokument
Utöka programmet för att sammanfatta varje .txt fil i en katalog. Detta är användbart när du har en mapp med dokument som alla behöver sammanfattningar.
Följande funktion itererar över alla .txt filer i en viss katalog och sammanfattar var och en:
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();
}
}
Varje fil läss, paras ihop med samma systemprompt och skickas till modellen oberoende av varandra. Modellen har inte kontext mellan filer, så varje sammanfattning är fristående.
Fullständig kod
Skapa en fil med namnet index.js och lägg till följande fullständiga kod:
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!');
Sammanfatta en enskild fil:
node index.js document.txt
Eller sammanfatta varje .txt fil i en katalog:
node index.js ./docs
Du ser utdata som liknar:
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!
Installera paket
Exempellagringsplats
Den fullständiga exempelkoden för den här artikeln finns på lagringsplatsen Foundry Local GitHub. Klona lagringsplatsen och gå till exempelanvändningen:
git clone https://github.com/microsoft/Foundry-Local.git
cd Foundry-Local/samples/python/tutorial-document-summarizer
Om du utvecklar eller skickar på Windows väljer du fliken Windows. Windows-paketet integreras med Windows ML-körning – det ger samma API-yta med en bredare bredd av maskinvaruacceleration.
pip install foundry-local-sdk-winml openai
Läsa ett textdokument
Innan du sammanfattar något behöver du ett exempeldokument att arbeta med. Skapa en fil med namnet document.txt i projektkatalogen och lägg till följande innehåll:
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.
Skapa nu en fil med namnet main.py och lägg till följande kod för att läsa dokumentet:
target = sys.argv[1] if len(sys.argv) > 1 else "document.txt"
target_path = Path(target)
Skriptet accepterar en valfri filsökväg som kommandoradsargument och återgår till document.txt om ingen anges. Metoden Path.read_text läser in hela filen i en sträng.
Generera en sammanfattning
Initiera Foundry Local SDK, läs in en modell och skicka dokumentinnehållet tillsammans med en systemprompt som instruerar modellen att sammanfatta.
Ersätt innehållet i main.py med följande kod:
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)
Metoden get_model accepterar ett modellalias, vilket är ett kort eget namn som mappar till en specifik modell i katalogen. Metoden download hämtar modellvikterna till din lokala cache (och hoppar över nedladdningen om de redan är cachelagrade) och load gör modellen redo för slutsatsdragning. Systemprompten instruerar modellen att skapa punktsammanfattningar som fokuserar på viktiga idéer.
Kontrollsammanfattningsutdata
Olika situationer kräver olika sammanfattningsformat. Du kan ändra systemprompten för att styra hur modellen strukturerar sina utdata. Här är tre användbara varianter:
Punktpunkter (standard från föregående steg):
system_prompt = (
"Summarize the following document into concise bullet points. "
"Focus on the key points and main ideas."
)
Sammanfattning av ett stycke:
system_prompt = (
"Summarize the following document in a single, concise paragraph. "
"Capture the main argument and supporting points."
)
Nyckelinsikter:
system_prompt = (
"Extract the three most important takeaways from the following document. "
"Number each takeaway and keep each to one or two sentences."
)
För att prova en annan stil, ersätt "content" värdet i systemmeddelandet med en av anvisningarna. Modellen följer anvisningarna i systemprompten för att forma sammanfattningens format och djup.
Bearbeta flera dokument
Utöka programmet för att sammanfatta varje .txt fil i en katalog. Detta är användbart när du har en mapp med dokument som alla behöver sammanfattningar.
Följande funktion itererar över alla .txt filer i en viss katalog och sammanfattar var och en:
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()
Varje fil läss, paras ihop med samma systemprompt och skickas till modellen oberoende av varandra. Modellen har inte kontext mellan filer, så varje sammanfattning är fristående.
Fullständig kod
Skapa en fil med namnet main.py och lägg till följande fullständiga kod:
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()
Sammanfatta en enskild fil:
python main.py document.txt
Eller sammanfatta varje .txt fil i en katalog:
python main.py ./docs
Du ser utdata som liknar:
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!
Installera paket
Exempellagringsplats
Den fullständiga exempelkoden för den här artikeln finns på lagringsplatsen Foundry Local GitHub. Klona lagringsplatsen och gå till exempelanvändningen:
git clone https://github.com/microsoft/Foundry-Local.git
cd Foundry-Local/samples/rust/tutorial-document-summarizer
Om du utvecklar eller skickar på Windows väljer du fliken Windows. Windows-paketet integreras med Windows ML-körning – det ger samma API-yta med en bredare bredd av maskinvaruacceleration.
cargo add foundry-local-sdk --features winml
cargo add tokio --features full
cargo add tokio-stream anyhow
Läsa ett textdokument
Innan du sammanfattar något behöver du ett exempeldokument att arbeta med. Skapa en fil med namnet document.txt i projektkatalogen och lägg till följande innehåll:
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 Öppna nu och lägg till följande kod för att läsa dokumentet:
let target = env::args()
.nth(1)
.unwrap_or_else(|| "document.txt".to_string());
let target_path = Path::new(&target);
Koden accepterar en valfri filsökväg som ett kommandoradsargument och återgår till document.txt om ingen anges.
Generera en sammanfattning
Initiera Foundry Local SDK, läs in en modell och skicka dokumentinnehållet tillsammans med en systemprompt som instruerar modellen att sammanfatta.
Ersätt innehållet i src/main.rs med följande kod:
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?;
}
Metoden get_model accepterar ett modellalias, vilket är ett kort eget namn som mappar till en specifik modell i katalogen. Metoden download hämtar modellvikterna till din lokala cache (och hoppar över nedladdningen om de redan är cachelagrade) och load gör modellen redo för slutsatsdragning. Systemprompten instruerar modellen att skapa punktsammanfattningar som fokuserar på viktiga idéer.
Kontrollsammanfattningsutdata
Olika situationer kräver olika sammanfattningsformat. Du kan ändra systemprompten för att styra hur modellen strukturerar sina utdata. Här är tre användbara varianter:
Punktpunkter (standard från föregående steg):
let system_prompt =
"Summarize the following document into concise bullet points. \
Focus on the key points and main ideas.";
Sammanfattning av ett stycke:
let system_prompt =
"Summarize the following document in a single, concise paragraph. \
Capture the main argument and supporting points.";
Nyckelinsikter:
let system_prompt =
"Extract the three most important takeaways from the following document. \
Number each takeaway and keep each to one or two sentences.";
Om du vill prova ett annat format ersätter du innehållet i systemmeddelandet med någon av anvisningarna. Modellen följer anvisningarna i systemprompten för att forma sammanfattningens format och djup.
Bearbeta flera dokument
Utöka programmet för att sammanfatta varje .txt fil i en katalog. Detta är användbart när du har en mapp med dokument som alla behöver sammanfattningar.
Följande funktion itererar över alla .txt filer i en viss katalog och sammanfattar var och en:
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(())
}
Varje fil läss, paras ihop med samma systemprompt och skickas till modellen oberoende av varandra. Modellen har inte kontext mellan filer, så varje sammanfattning är fristående.
Fullständig kod
Ersätt innehållet i src/main.rs med följande fullständiga kod:
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(())
}
Sammanfatta en enskild fil:
cargo run -- document.txt
Eller sammanfatta varje .txt fil i en katalog:
cargo run -- ./docs
Du ser utdata som liknar:
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!
Rensa resurser
Modellvikterna finns kvar i din lokala cache efter att du har avladdat en modell. Det innebär att nästa gång du kör programmet utelämnas nedladdningssteget och modellen läses in snabbare. Ingen extra rensning krävs om du inte vill frigöra diskutrymme.