Przejdź do treści

TailoredApps.Shared.MediatR.ML

NuGet License: MIT


Opis

Biblioteka integruje klasyfikację obrazów przez ML.NET z pipeline MediatR. Dostarcza gotowe komendy (ClassifyImage, TrainImageClassificationModel) i ich handlery, dzięki czemu klasyfikacja obrazów staje się pełnoprawnym elementem architektury CQRS.

Pod spodem działa ImageClassificationService oparty na ML.NET z poolem silników predykcji (PredictionEnginePool) dla wydajnej współbieżnej inferencji. Biblioteka obsługuje też trening modelu z poziomu aplikacji — możesz wytrenować nowy model podając zestaw oznaczonych obrazów.


Instalacja

dotnet add package TailoredApps.Shared.MediatR.ML

Rejestracja w DI

// Program.cs
using TailoredApps.Shared.MediatR.ImageClassification.Infrastructure;

builder.Services.AddPredictionEngine(config =>
{
    config.AddImageClassificationModel(modelBuilder =>
    {
        modelBuilder.AddFromFile("Models/image-classifier.zip");
    });
});

// MediatR
builder.Services.AddMediatR(cfg =>
    cfg.RegisterServicesFromAssembly(typeof(Program).Assembly));

Konfiguracja appsettings.json

{
  "ML": {
    "ImageClassification": {
      "ModelPath": "Models/image-classifier.zip",
      "LabelsPath": "Models/labels.txt"
    }
  }
}

Przykład użycia

Klasyfikacja obrazu

public class ImageAnalysisController : ControllerBase
{
    private readonly IMediator _mediator;

    public ImageAnalysisController(IMediator mediator) => _mediator = mediator;

    [HttpPost("classify")]
    public async Task<IActionResult> ClassifyImage(IFormFile imageFile)
    {
        using var ms = new MemoryStream();
        await imageFile.CopyToAsync(ms);

        var result = await _mediator.Send(new ClassifyImage
        {
            FileByteArray = ms.ToArray(),
            FileName = imageFile.FileName
        });

        return Ok(new
        {
            result.FileName,
            result.PredictedLabel,
            result.PredictedScore,
            Confidence = $"{result.PredictedScore:P2}"
        });
    }
}

Trening modelu

var trainingResult = await _mediator.Send(new TrainImageClassificationModel
{
    TrainingSetFolder = "/data/training-images",   // katalog z podfolderami per klasa
    ModelDestinationPath = "Models/new-model.zip"
});

Console.WriteLine($"Trained! Labels: {string.Join(", ", trainingResult.Labels)}");
Console.WriteLine(trainingResult.EvaluationInfo);

API Reference

Typ Rodzaj Opis
ClassifyImage Command Dane obrazu do klasyfikacji: FileByteArray, FileName
ClassifyImageResponse Klasa Wynik: FileName, PredictedLabel, PredictedScore
TrainImageClassificationModel Command Parametry treningu: TrainingSetFolder, ModelDestinationPath
TrainImageClassificationModelResponse Klasa Wynik treningu: Labels[], EvaluationInfo
IImageClassificationService Interfejs Predict(byte[], fileName), Train(images, folder, dest), GetModelInfo()
IPredictionEnginePoolAdapter<TData, TPred> Interfejs Abstrakcja nad ML.NET PredictionEnginePool
ModelInfo Klasa Metadane modelu: nazwa, checksum, wersja, etykiety
ImagePrediction Klasa Wynik predykcji: etykieta, score, nazwa pliku
InMemoryImageData Klasa Dane wejściowe do modelu: obraz jako byte[]
AddPredictionEngineExtension.AddPredictionEngine Metoda ext. Rejestruje cały stack ML w DI

🤖 AI Agent Prompt

## TailoredApps.Shared.MediatR.ML — Instrukcja dla agenta AI

Używasz TailoredApps.Shared.MediatR.ML do klasyfikacji obrazów przez ML.NET i MediatR.

### Rejestracja
```csharp
builder.Services.AddPredictionEngine(config =>
    config.AddImageClassificationModel(b => b.AddFromFile("Models/model.zip")));

Klasyfikacja obrazu

var result = await _mediator.Send(new ClassifyImage
{
    FileByteArray = imageBytes,
    FileName = "photo.jpg"
});
// result.PredictedLabel  — przewidywana klasa
// result.PredictedScore  — pewność (0-1)

Trening modelu

var result = await _mediator.Send(new TrainImageClassificationModel
{
    TrainingSetFolder = "/data/images",       // podfoldery = nazwy klas
    ModelDestinationPath = "Models/new.zip"
});

Zasady

  • Model musi być plikiem ZIP (ML.NET format)
  • Folder treningowy: każdy podfolder = jedna klasa, nazwa folderu = etykieta
  • PredictionEnginePool jest thread-safe — bezpieczne współbieżne użycie
  • PredictedScore ∈ [0,1] — im bliżej 1, tym wyższe zaufanie modelu ```