feat: Implement AI workload settings and enhance AI processing summaries

This commit is contained in:
MaddoScientisto 2026-05-09 18:54:20 +02:00
commit 88c193549f
8 changed files with 326 additions and 28 deletions

View file

@ -131,7 +131,7 @@ namespace ImageCatalog_2
}
catch (OperationCanceledException)
{
// user cancelled
await InvokeOnUiThreadAsync(() => NumberAiStatsSummary = "OCR annullato.").ConfigureAwait(false);
}
catch (Exception ex)
{
@ -141,6 +141,8 @@ namespace ImageCatalog_2
RefreshNumberAiGpuCapabilities();
}
await InvokeOnUiThreadAsync(() => NumberAiStatsSummary = $"Errore OCR: {ex.GetBaseException().Message}").ConfigureAwait(false);
await ShowErrorMessageAsync("Errore AI", ex.GetBaseException().Message).ConfigureAwait(false);
}
finally
@ -167,9 +169,10 @@ namespace ImageCatalog_2
{
PreviewResults.Clear();
AiProgress = 0;
NumberAiStatsSummary = BuildNumberAiIdleSummary();
}).ConfigureAwait(false);
await _aiExtractionService.RunAsync(
var summary = await _aiExtractionService.RunAsync(
new AiExtractionRequest
{
SearchRoot = searchRoot,
@ -177,6 +180,7 @@ namespace ImageCatalog_2
IncludeThumbnails = IncludeNumberAiThumbnails,
ModelsFolderPath = ModelsFolderPath,
UseGpu = UseNumberAiGpu,
WorkloadLevel = NumberAiWorkloadLevel,
CsvOutputPath = CsvOutputPath
},
token,
@ -187,7 +191,17 @@ namespace ImageCatalog_2
PreviewResults.Add(result);
}
}),
progress => InvokeOnUiThreadAsync(() => AiProgress = progress)).ConfigureAwait(false);
progress => InvokeOnUiThreadAsync(() =>
{
AiProgress = progress.PercentComplete;
NumberAiStatsSummary = BuildNumberAiProgressSummary(progress);
})).ConfigureAwait(false);
await InvokeOnUiThreadAsync(() =>
{
AiProgress = summary.TotalFiles > 0 ? 100 : 0;
NumberAiStatsSummary = BuildNumberAiCompletionSummary(summary);
}).ConfigureAwait(false);
}
/// <summary>
@ -250,6 +264,20 @@ namespace ImageCatalog_2
set => _ai.IncludeNumberAiThumbnails = value;
}
public IReadOnlyList<int> NumberAiWorkloadOptions { get; } = [1, 2, 3, 4, 5];
public int NumberAiWorkloadLevel
{
get => _ai.NumberAiWorkloadLevel;
set => _ai.NumberAiWorkloadLevel = NormalizeNumberAiWorkloadLevel(value);
}
public string NumberAiStatsSummary
{
get => _ai.NumberAiStatsSummary;
private set => _ai.NumberAiStatsSummary = value;
}
public string FaceExecutablePath
{
get => _ai.FaceExecutablePath;
@ -419,6 +447,27 @@ namespace ImageCatalog_2
set => _ai.AiProgress = value;
}
private string BuildNumberAiIdleSummary()
{
var workerCount = ResolveNumberAiWorkerCount(UseNumberAiGpu, NumberAiWorkloadLevel);
return $"In attesa. Carico {NumberAiWorkloadLevel}/5, {workerCount} worker, 0.00 img/s.";
}
private static string BuildNumberAiProgressSummary(AiExtractionProgressUpdate progress)
{
return $"{progress.ProcessedFiles}/{progress.TotalFiles} immagini, media {progress.AverageImagesPerSecond:F2} img/s, carico {progress.WorkloadLevel}/5, {progress.WorkerCount} worker.";
}
private static string BuildNumberAiCompletionSummary(AiExtractionRunSummary summary)
{
if (summary.TotalFiles == 0)
{
return "Nessuna immagine trovata per OCR.";
}
return $"Completato: {summary.ProcessedFiles}/{summary.TotalFiles} immagini, media finale {summary.AverageImagesPerSecond:F2} img/s, errori {summary.FailedFiles}, carico {summary.WorkloadLevel}/5, {summary.WorkerCount} worker.";
}
private List<string> LoadAvailableFonts()
{
#if WINDOWS
@ -2167,6 +2216,36 @@ namespace ImageCatalog_2
return value is >= 1 and <= 5 ? value : 3;
}
private static int NormalizeNumberAiWorkloadLevel(int value)
{
return value is >= 1 and <= 5 ? value : 3;
}
private static int ResolveNumberAiWorkerCount(bool useGpu, int workloadLevel)
{
var normalized = NormalizeNumberAiWorkloadLevel(workloadLevel);
var maxWorkers = Math.Max(1, Environment.ProcessorCount);
var requestedWorkers = useGpu
? normalized switch
{
1 => 1,
2 => 2,
3 => 4,
4 => 6,
_ => 8
}
: normalized switch
{
1 => 1,
2 => 2,
3 => 3,
4 => 4,
_ => 5
};
return Math.Min(requestedWorkers, maxWorkers);
}
private static int NormalizeFaceMinSize(int value)
{
return value > 0 ? value : 35;