Eğitim: Belge Özetleyici Oluşturun

Metin dosyalarını okuyan ve tamamen cihazınızda kısa özetler oluşturan bir uygulama oluşturun. Bu, belgelerin içeriğini tam olarak okumadan hızlı bir şekilde anlamanız gerektiğinde ve belgeler makinenizden ayrılmaması gereken hassas bilgiler içerdiğinde kullanışlıdır.

Bu eğitimde şunları öğreniyorsunuz:

  • Bir proje ayarlama ve Foundry Yerel SDK'sını yükleme
  • Dosya sisteminden metin belgesi okuma
  • Model yükleme ve özet oluşturma
  • Sistem istemleriyle özet çıktıyı denetleme
  • Toplu işlemde birden çok belgeyi işleme
  • Kaynakları temizle

Önkoşullar

  • En az 8 GB RAM'e sahip bir Windows, macOS veya Linux bilgisayar.

Örnekler deposu

Bu makalenin örnek kodunun tamamına foundry-samples GitHub deposundan ulaşabilirsiniz. Depoyu klonlamak ve örneğe gitmek için şu adımları kullanın:

git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/csharp/foundry-local/tutorial-document-summarizer

Paketleri yükleme

Windows üzerinde geliştiriyor veya gönderiyorsanız Windows sekmesini seçin. Windows paketi Windows ML çalışma zamanıyla tümleşir; aynı API yüzey alanını daha geniş bir donanım hızlandırmasıyla sağlar.

dotnet add package Microsoft.AI.Foundry.Local.WinML
dotnet add package OpenAI

GitHub deposundaki C# örnekleri önceden yapılandırılmış projelerdir. Sıfırdan oluşturuyorsanız, C# projenizi Foundry Local ile nasıl ayarlayacağınız hakkında daha fazla ayrıntı için Foundry Yerel SDK başvurusunu okumalısınız.

Metin belgesini okuma

Herhangi bir şeyi özetlemeden önce, çalışmak için örnek bir belge gerekir. Proje dizininizde adlı document.txt bir dosya oluşturun ve aşağıdaki içeriği ekleyin:

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.

Şimdi belgeyi okumak için aşağıdaki kodu açın Program.cs ve ekleyin:

var target = args.Length > 0 ? args[0] : "document.txt";

Kod, isteğe bağlı bir dosya yolunu komut satırı bağımsız değişkeni olarak kabul eder ve hiçbir dosya yolu sağlanmadığında document.txt varsayılanına geri döner.

Özet oluşturma

Foundry Yerel SDK'sını başlatın, bir model yükleyin ve belge içeriğini, modeli özetlemesini isteyen bir sistem istemiyle birlikte gönderin.

Program.cs içeriğini aşağıdaki kodla değiştirin:

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);
}

Bu GetModelAsync yöntemi, katalogdaki belirli bir modelle eşleşen kısa ve kolay bir ad olan model takma adını kabul eder. yöntemi, DownloadAsync model ağırlıklarını yerel önbelleğinize getirir (ve zaten önbelleğe alınmışsa indirmeyi atlar) ve LoadAsync modeli çıkarım için hazır hale getirir. Sistem komutu, modele ana fikirlere odaklanan madde işareti özetleri üretmesini söyler.

Denetim özeti çıkışı

Farklı durumlar, farklı özet stilleri için çağrıda bulunur. Modelin çıktısını nasıl yapılandıracağını kontrol etmek için sistem istemini değiştirebilirsiniz. İşte üç yararlı çeşitleme:

Madde işareti noktaları (önceki adımdan varsayılan):

var systemPrompt =
    "Summarize the following document into concise bullet points. " +
    "Focus on the key points and main ideas.";

Bir paragraflık özet:

var systemPrompt =
    "Summarize the following document in a single, concise paragraph. " +
    "Capture the main argument and supporting points.";

Anahtar çıkarımlar:

var systemPrompt =
    "Extract the three most important takeaways from the following document. " +
    "Number each takeaway and keep each to one or two sentences.";

Farklı bir stil denemek için sistem iletisindeki değeri istemlerden biriyle değiştirin Content . Model, özetin biçimini ve derinliğini şekillendirmek için sistem istemindeki yönergeleri izler.

Birden çok belgeyi işleme

Bir dizindeki her .txt dosyayı özetlemek için uygulamayı genişletin. Bu, tüm özetlere ihtiyaç duyan bir belge klasörünüz olduğunda kullanışlıdır.

Aşağıdaki yöntem, belirli bir dizindeki tüm .txt dosyalar üzerinde yinelenir ve her birini özetler:

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();
    }
}

Her dosya okunur, aynı sistem istemiyle eşleştirilir ve modele bağımsız olarak gönderilir. Model dosyalar arasında bağlam taşımaz, bu nedenle her özet bağımsızdır.

Kodu tamamlama

Program.cs öğesinin içeriğini aşağıdaki tam kod ile değiştirin:

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();
    }
}

Tek bir dosyayı özetleme:

dotnet run -- document.txt

Veya bir dizindeki her .txt dosyayı özetleyin:

dotnet run -- ./docs

Şuna benzer bir çıkış görürsünüz:

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!

Örnekler deposu

Bu makalenin örnek kodunun tamamına foundry-samples GitHub deposundan ulaşabilirsiniz. Depoyu klonlamak ve örneğe gitmek için şu adımları kullanın:

git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/javascript/foundry-local/tutorial-document-summarizer

Paketleri yükleme

Windows üzerinde geliştiriyor veya gönderiyorsanız Windows sekmesini seçin. Windows paketi Windows ML çalışma zamanıyla tümleşir; aynı API yüzey alanını daha geniş bir donanım hızlandırmasıyla sağlar.

npm install foundry-local-sdk-winml openai

Metin belgesini okuma

Herhangi bir şeyi özetlemeden önce, çalışmak için örnek bir belge gerekir. Proje dizininizde adlı document.txt bir dosya oluşturun ve aşağıdaki içeriği ekleyin:

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.

Şimdi adlı index.js bir dosya oluşturun ve belgeyi okumak için aşağıdaki kodu ekleyin:

const target = process.argv[2] || 'document.txt';

Betik, isteğe bağlı bir dosya yolunu komut satırı bağımsız değişkeni olarak kabul eder ve hiçbiri sağlanmadığında document.txt'ye geri döner.

Özet oluşturma

Foundry Yerel SDK'sını başlatın, bir model yükleyin ve belge içeriğini, modeli özetlemesini isteyen bir sistem istemiyle birlikte gönderin.

index.js içeriğini aşağıdaki kodla değiştirin:

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);
}

Bu getModel yöntemi, katalogdaki belirli bir modelle eşleşen kısa ve kolay bir ad olan model takma adını kabul eder. yöntemi, download model ağırlıklarını yerel önbelleğinize getirir (ve zaten önbelleğe alınmışsa indirmeyi atlar) ve load modeli çıkarım için hazır hale getirir. Sistem komutu, modele ana fikirlere odaklanan madde işareti özetleri üretmesini söyler.

Denetim özeti çıkışı

Farklı durumlar, farklı özet stilleri için çağrıda bulunur. Modelin çıktısını nasıl yapılandıracağını kontrol etmek için sistem istemini değiştirebilirsiniz. İşte üç yararlı çeşitleme:

Madde işareti noktaları (önceki adımdan varsayılan):

const systemPrompt =
    'Summarize the following document into concise bullet points. ' +
    'Focus on the key points and main ideas.';

Bir paragraflık özet:

const systemPrompt =
    'Summarize the following document in a single, concise paragraph. ' +
    'Capture the main argument and supporting points.';

Anahtar çıkarımlar:

const systemPrompt =
    'Extract the three most important takeaways from the following document. ' +
    'Number each takeaway and keep each to one or two sentences.';

Farklı bir stil denemek için sistem iletisindeki değeri istemlerden biriyle değiştirin content . Model, özetin biçimini ve derinliğini şekillendirmek için sistem istemindeki yönergeleri izler.

Birden çok belgeyi işleme

Bir dizindeki her .txt dosyayı özetlemek için uygulamayı genişletin. Bu, tüm özetlere ihtiyaç duyan bir belge klasörünüz olduğunda kullanışlıdır.

Aşağıdaki işlev, belirli bir dizindeki tüm .txt dosyalar üzerinde yinelenir ve her birini özetler:

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();
    }
}

Her dosya okunur, aynı sistem istemiyle eşleştirilir ve modele bağımsız olarak gönderilir. Model dosyalar arasında bağlam taşımaz, bu nedenle her özet bağımsızdır.

Kodu tamamlama

adlı index.js bir dosya oluşturun ve aşağıdaki tam kodu ekleyin:

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!');

Tek bir dosyayı özetleme:

node index.js document.txt

Veya bir dizindeki her .txt dosyayı özetleyin:

node index.js ./docs

Şuna benzer bir çıkış görürsünüz:

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!

Örnekler deposu

Bu makalenin örnek kodunun tamamına foundry-samples GitHub deposundan ulaşabilirsiniz. Depoyu klonlamak ve örneğe gitmek için şu adımları kullanın:

git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/python/foundry-local/tutorial-document-summarizer

Paketleri yükleme

Windows üzerinde geliştiriyor veya gönderiyorsanız Windows sekmesini seçin. Windows paketi Windows ML çalışma zamanıyla tümleşir; aynı API yüzey alanını daha geniş bir donanım hızlandırmasıyla sağlar.

pip install foundry-local-sdk-winml openai

Metin belgesini okuma

Herhangi bir şeyi özetlemeden önce, çalışmak için örnek bir belge gerekir. Proje dizininizde adlı document.txt bir dosya oluşturun ve aşağıdaki içeriği ekleyin:

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.

Şimdi adlı main.py bir dosya oluşturun ve belgeyi okumak için aşağıdaki kodu ekleyin:

target = sys.argv[1] if len(sys.argv) > 1 else "document.txt"
target_path = Path(target)

Betik, isteğe bağlı bir dosya yolunu komut satırı bağımsız değişkeni olarak kabul eder ve hiçbiri sağlanmadığında document.txt'ye geri döner. yöntemi, Path.read_text dosyanın tamamını bir dizeye okur.

Özet oluşturma

Foundry Yerel SDK'sını başlatın, bir model yükleyin ve belge içeriğini, modeli özetlemesini isteyen bir sistem istemiyle birlikte gönderin.

main.py içeriğini aşağıdaki kodla değiştirin:

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)

Bu get_model yöntemi, katalogdaki belirli bir modelle eşleşen kısa ve kolay bir ad olan model takma adını kabul eder. yöntemi, download model ağırlıklarını yerel önbelleğinize getirir (ve zaten önbelleğe alınmışsa indirmeyi atlar) ve load modeli çıkarım için hazır hale getirir. Sistem komutu, modele ana fikirlere odaklanan madde işareti özetleri üretmesini söyler.

Denetim özeti çıkışı

Farklı durumlar, farklı özet stilleri için çağrıda bulunur. Modelin çıktısını nasıl yapılandıracağını kontrol etmek için sistem istemini değiştirebilirsiniz. İşte üç yararlı çeşitleme:

Madde işareti noktaları (önceki adımdan varsayılan):

system_prompt = (
    "Summarize the following document into concise bullet points. "
    "Focus on the key points and main ideas."
)

Bir paragraflık özet:

system_prompt = (
    "Summarize the following document in a single, concise paragraph. "
    "Capture the main argument and supporting points."
)

Anahtar çıkarımlar:

system_prompt = (
    "Extract the three most important takeaways from the following document. "
    "Number each takeaway and keep each to one or two sentences."
)

Farklı bir stil denemek için sistem iletisindeki değeri istemlerden biriyle değiştirin "content" . Model, özetin biçimini ve derinliğini şekillendirmek için sistem istemindeki yönergeleri izler.

Birden çok belgeyi işleme

Bir dizindeki her .txt dosyayı özetlemek için uygulamayı genişletin. Bu, tüm özetlere ihtiyaç duyan bir belge klasörünüz olduğunda kullanışlıdır.

Aşağıdaki işlev, belirli bir dizindeki tüm .txt dosyalar üzerinde yinelenir ve her birini özetler:

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()

Her dosya okunur, aynı sistem istemiyle eşleştirilir ve modele bağımsız olarak gönderilir. Model dosyalar arasında bağlam taşımaz, bu nedenle her özet bağımsızdır.

Kodu tamamlama

adlı main.py bir dosya oluşturun ve aşağıdaki tam kodu ekleyin:

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()

Tek bir dosyayı özetleme:

python main.py document.txt

Veya bir dizindeki her .txt dosyayı özetleyin:

python main.py ./docs

Şuna benzer bir çıkış görürsünüz:

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!

Örnekler deposu

Bu makalenin örnek kodunun tamamına foundry-samples GitHub deposundan ulaşabilirsiniz. Depoyu klonlamak ve örneğe gitmek için şu adımları kullanın:

git clone https://github.com/microsoft-foundry/foundry-samples.git
cd foundry-samples/samples/rust/foundry-local/tutorial-document-summarizer

Paketleri yükleme

Windows üzerinde geliştiriyor veya gönderiyorsanız Windows sekmesini seçin. Windows paketi Windows ML çalışma zamanıyla tümleşir; aynı API yüzey alanını daha geniş bir donanım hızlandırmasıyla sağlar.

cargo add foundry-local-sdk --features winml
cargo add tokio --features full
cargo add tokio-stream anyhow

Metin belgesini okuma

Herhangi bir şeyi özetlemeden önce, çalışmak için örnek bir belge gerekir. Proje dizininizde adlı document.txt bir dosya oluşturun ve aşağıdaki içeriği ekleyin:

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.

Şimdi belgeyi okumak için aşağıdaki kodu açın src/main.rs ve ekleyin:

let target = env::args()
    .nth(1)
    .unwrap_or_else(|| "document.txt".to_string());
let target_path = Path::new(&target);

Kod, isteğe bağlı bir dosya yolunu komut satırı bağımsız değişkeni olarak kabul eder ve hiçbir dosya yolu sağlanmadığında document.txt varsayılanına geri döner.

Özet oluşturma

Foundry Yerel SDK'sını başlatın, bir model yükleyin ve belge içeriğini, modeli özetlemesini isteyen bir sistem istemiyle birlikte gönderin.

src/main.rs içeriğini aşağıdaki kodla değiştirin:

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?;
}

Bu get_model yöntemi, katalogdaki belirli bir modelle eşleşen kısa ve kolay bir ad olan model takma adını kabul eder. yöntemi, download model ağırlıklarını yerel önbelleğinize getirir (ve zaten önbelleğe alınmışsa indirmeyi atlar) ve load modeli çıkarım için hazır hale getirir. Sistem komutu, modele ana fikirlere odaklanan madde işareti özetleri üretmesini söyler.

Denetim özeti çıkışı

Farklı durumlar, farklı özet stilleri için çağrıda bulunur. Modelin çıktısını nasıl yapılandıracağını kontrol etmek için sistem istemini değiştirebilirsiniz. İşte üç yararlı çeşitleme:

Madde işareti noktaları (önceki adımdan varsayılan):

let system_prompt =
    "Summarize the following document into concise bullet points. \
     Focus on the key points and main ideas.";

Bir paragraflık özet:

let system_prompt =
    "Summarize the following document in a single, concise paragraph. \
     Capture the main argument and supporting points.";

Anahtar çıkarımlar:

let system_prompt =
    "Extract the three most important takeaways from the following document. \
     Number each takeaway and keep each to one or two sentences.";

Farklı bir stil denemek için sistem iletisi içeriğini istemlerden biriyle değiştirin. Model, özetin biçimini ve derinliğini şekillendirmek için sistem istemindeki yönergeleri izler.

Birden çok belgeyi işleme

Bir dizindeki her .txt dosyayı özetlemek için uygulamayı genişletin. Bu, tüm özetlere ihtiyaç duyan bir belge klasörünüz olduğunda kullanışlıdır.

Aşağıdaki işlev, belirli bir dizindeki tüm .txt dosyalar üzerinde yinelenir ve her birini özetler:

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(())
}

Her dosya okunur, aynı sistem istemiyle eşleştirilir ve modele bağımsız olarak gönderilir. Model dosyalar arasında bağlam taşımaz, bu nedenle her özet bağımsızdır.

Kodu tamamlama

src/main.rs öğesinin içeriğini aşağıdaki tam kod ile değiştirin:

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(())
}

Tek bir dosyayı özetleme:

cargo run -- document.txt

Veya bir dizindeki her .txt dosyayı özetleyin:

cargo run -- ./docs

Şuna benzer bir çıkış görürsünüz:

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!

Kaynakları temizle

Modeli kaldırmanızın ardından model ağırlıkları yerel önbelleğinizde kalır. Bu, uygulamayı bir sonraki çalıştırmanızda indirme adımının atlandığı ve modelin daha hızlı yüklendiği anlamına gelir. Disk alanını geri kazanmak istemediğiniz sürece fazladan temizleme gerekmez.