Начало работы с API каталога моделей Машинного обучения Windows

В этом руководстве показано, как использовать API каталога моделей Машинного обучения Windows для совместного использования моделей ИИ на пк пользователя. Вы узнаете, как настроить источники каталога, найти совместимые модели и скачать их в общее расположение на устройстве для всех приложений.

Предпосылки

Шаг 1. Создание источника каталога моделей

Сначала необходимо создать или получить источник каталога моделей, который является индексом моделей, включая сведения о том, как получить доступ к модели. Дополнительные сведения см. в документации по исходным документам каталога моделей.

Исходный JSON-файл каталога моделей можно размещать в сети, использовать через https:// конечные точки или использовать локальный файл, на который ссылаются через пути к файлам, такие как C:\Users\....

Шаг 2: Инициализируйте каталог, используя ваш источник

Инициализация каталога с одним источником каталога:

using Microsoft.Windows.AI.MachineLearning;
using Windows.Foundation;
using System;
using System.Threading.Tasks;

// Create a catalog source from a URI
var source = await ModelCatalogSource.CreateFromUriAsync(
    new Uri("https://contoso.com/models"));

// Create the catalog with the source
var catalog = new ModelCatalog(new ModelCatalogSource[] { source });

Можно также настроить несколько источников каталога с различными приоритетами:

var catalog = new ModelCatalog(new ModelCatalogSource[0]);

// Add sources in order of preference (highest priority first)
catalog.Sources.Add(await ModelCatalogSource.CreateFromUriAsync(
    new Uri("https://contoso.com/models")));
catalog.Sources.Add(await ModelCatalogSource.CreateFromUriAsync(
    new Uri("https://contoso.com/secondaryModels")));

Шаг 3. Поиск модели по имени

Выполните поиск модели во всех настроенных источниках:

// Find a model by its name
CatalogModelInfo model = await catalog.FindModelAsync("phi-3.5-reasoning");

if (model != null)
{
    Console.WriteLine($"Found model: {model.Name}");
    Console.WriteLine($"Version: {model.Version}");
    Console.WriteLine($"Publisher: {model.Publisher}");
    Console.WriteLine($"Size: {model.ModelSizeInBytes / (1024 * 1024)} MB");
    Console.WriteLine($"Supported execution providers: {string.Join(", ", model.ExecutionProviders)}");
}

Шаг 4. Скачивание и использование модели

Получите экземпляр модели и используйте его с требуемой платформой:

// Get an instance of the model (downloads if necessary)
var progress = new Progress<double>(percent => 
    Console.WriteLine($"Download progress: {percent:P}"));

CatalogModelInstanceResult result = await model.GetInstanceAsync().AsTask(progress);

if (result.Status == CatalogModelInstanceStatus.Available)
{
    CatalogModelInstance instance = result.GetInstance();

    // Get the model path
    string modelPath = instance.ModelPaths[0];
    
    Console.WriteLine($"Model path: {modelPath}");
    
    // Inference your model using your own code
}
else
{
    Console.WriteLine($"Failed to get model: {result.ExtendedError}");
    Console.WriteLine($"Details: {result.DiagnosticText}");
}

Полный пример

Ниже приведен полный пример, который объединяет все это:

using Microsoft.Windows.AI.MachineLearning;
using System;
using System.Threading.Tasks;

try
{
    // Create catalog with source
    var source = await ModelCatalogSource.CreateFromUriAsync(
        new Uri("https://contoso.com/models"));
    var catalog = new ModelCatalog(new ModelCatalogSource[] { source });
    
    // Find a model
    Console.WriteLine("Searching for model...");
    CatalogModelInfo model = await catalog.FindModelAsync("phi-3.5-reasoning");
    
    if (model != null)
    {
        Console.WriteLine($"Found model: {model.Name}");
        Console.WriteLine($"Version: {model.Version}");
        Console.WriteLine($"Publisher: {model.Publisher}");
        Console.WriteLine($"Size: {model.ModelSizeInBytes / (1024 * 1024)} MB");
        Console.WriteLine($"Supported execution providers: {string.Join(", ", model.ExecutionProviders)}");
        
        // Get an instance of the model (downloads if necessary)
        var progress = new Progress<double>(percent => 
            Console.WriteLine($"Download progress: {percent:P}"));
        
        CatalogModelInstanceResult result = await model.GetInstanceAsync().AsTask(progress);
        
        if (result.Status == CatalogModelInstanceStatus.Available)
        {
            CatalogModelInstance instance = result.GetInstance();

            // Get the model path
            string modelPath = instance.ModelPaths[0];
            
            Console.WriteLine($"Model path: {modelPath}");
            
            // Inference your model using your own code
        }
        else
        {
            Console.WriteLine($"Failed to get model: {result.ExtendedError}");
            Console.WriteLine($"Details: {result.DiagnosticText}");
        }
    }
    else
    {
        Console.WriteLine("Model not found");
    }
}
catch (Exception ex)
{
    Console.WriteLine($"Error: {ex.Message}");
}

Фильтрация по поставщикам выполнения

Настройте, какие поставщики выполнения следует учитывать:

public async Task FilterByExecutionProvidersAsync(ModelCatalog catalog)
{
    // Only look for CPU-compatible models
    catalog.ExecutionProviders.Clear();
    catalog.ExecutionProviders.Add("cpuexecutionprovider");
    
    var cpuModels = await catalog.FindAllModelAsync();
    Console.WriteLine($"Found {cpuModels.Count} CPU-compatible models");
    
    // Look for DirectML-compatible models
    catalog.ExecutionProviders.Clear();
    catalog.ExecutionProviders.Add("dmlexecutionprovider");
    
    var dmlModels = await catalog.FindAllModelAsync();
    Console.WriteLine($"Found {dmlModels.Count} DirectML-compatible models");
}

Проверка состояния модели

Проверьте, доступна ли модель локально:

public void CheckModelStatus(ModelCatalog catalog)
{
    var availableModels = catalog.GetAvailableModels();
    
    foreach (var model in availableModels)
    {
        var status = model.GetStatus();
        Console.WriteLine($"Model {model.Name}: {status}");
        
        switch (status)
        {
            case CatalogModelStatus.Ready:
                Console.WriteLine("  ✓ Available locally");
                break;
            case CatalogModelStatus.NotReady:
                Console.WriteLine("  ⚠ Needs to be downloaded");
                break;
        }
    }
}

Использование файлов локального каталога

Создайте источник каталога из локального файла:

public async Task<ModelCatalog> CreateLocalCatalogAsync()
{
    // Load catalog from a local JSON file
    var localFile = Path.Combine(Package.Current.EffectivePath, "my-models.json");
    var source = await ModelCatalogSource.CreateFromUriAsync(new Uri(localFile));
    
    var catalog = new ModelCatalog(new ModelCatalogSource[] { source });
    return catalog;
}

Добавление пользовательских заголовков для загрузок

Укажите аутентификацию или пользовательские заголовки при загрузке моделей.

public async Task DownloadWithCustomHeadersAsync(CatalogModelInfo model)
{
    var headers = new Dictionary<string, string>
    {
        ["Authorization"] = "Bearer your-token-here",
        ["User-Agent"] = "MyApp/1.0"
    };
    
    var result = await model.GetInstanceAsync(headers);
    // Handle result...
}

Обработка ошибок

Всегда включать правильную обработку ошибок при работе с каталогом моделей:

public async Task<bool> SafeModelUsageAsync(string modelName)
{
    try
    {
        var source = await ModelCatalogSource.CreateFromUriAsync(
            new Uri("https://contoso.com/models"));
        var catalog = new ModelCatalog(new ModelCatalogSource[] { source });
        
        var model = await catalog.FindModelAsync(modelName);
        if (model == null)
        {
            Console.WriteLine($"Model '{modelName}' not found");
            return false;
        }
        
        var result = await model.GetInstanceAsync();
        if (result.Status != CatalogModelInstanceStatus.Available)
        {
            Console.WriteLine($"Failed to get model: {result.ExtendedError}");
            if (!string.IsNullOrEmpty(result.DiagnosticText))
            {
                Console.WriteLine($"Details: {result.DiagnosticText}");
            }
            return false;
        }
        
        using var instance = result.GetInstance();
        // Use the model...
        return true;
    }
    catch (UnauthorizedAccessException)
    {
        Console.WriteLine("Access denied - check permissions");
        return false;
    }
    catch (System.Net.Http.HttpRequestException ex)
    {
        Console.WriteLine($"Network error: {ex.Message}");
        return false;
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Unexpected error: {ex.Message}");
        return false;
    }
}

Лучшие практики

  1. Повторное использование экземпляров каталога: Повторное использование ModelCatalog экземпляров в вашем приложении
  2. Обработка хода загрузки. Предоставление отзывов пользователей во время загрузки модели
  3. Удаление экземпляров модели. Используйте using инструкции для правильного удаления экземпляров модели
  4. Проверка совместимости. Проверка соответствия поставщиков моделей требованиям
  5. Корректная обработка сбоев: всегда проверяйте состояние результатов перед использованием моделей
  6. Используйте имена моделей: используйтеFindModelAsync имена моделей для автоматического выбора оптимального варианта модели на основе возможностей устройства.

Дальнейшие шаги