Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
В этом руководстве показано, как создать собственный надстройку C#, использующую Windows Машинное обучение (WinML) в приложении Electron. WinML позволяет выполнять machine learning модели (формат ONNX) локально на устройствах Windows для таких задач, как классификация изображений, обнаружение объектов и многое другое.
Необходимые условия
Перед началом работы с этим руководством убедитесь, что вы:
- Завершена настройка среды разработки
- Windows 11 или Windows 10 (версия 1809 или более поздняя версия)
Замечание
WinML выполняется на любом Windows 10 (1809+) или Windows 11 устройстве. Для повышения производительности рекомендуется использовать устройства с графическими процессорами или NPU, но API также работает на ЦП.
Это важно
Для надстройки WinML требуется experimental Windows App SDK. Если вы выбрали "Стабильные пакеты SDK" во время winapp init установки, необходимо обновить версию пакета SDK. Измените winapp.yaml и измените версию Microsoft.WindowsAppSDK на 2.0.0-experimental3, а затем выполните npx winapp restore для обновления.
Шаг 1. Создание нативной надстройки C#
Давайте создадим собственную надстройку, использующую API WinML. Мы будем использовать шаблон C#, который задействует node-api-dotnet для объединения JavaScript и C#.
npx winapp node create-addon --template cs --name winMlAddon
При этом создается папка с: winMlAddon/
-
addon.cs— Код C#, который будет вызывать API WinML -
winMlAddon.csproj— файл Project со ссылками на пакет SDK для Windows и Windows App SDK -
README.md— Документация по использованию надстройки
Команда также добавляет build-winMlAddon скрипт в package.json для сборки надстройки и clean-winMlAddon скрипт для очистки артефактов сборки.
{
"scripts": {
"build-winMlAddon": "dotnet publish ./winMlAddon/winMlAddon.csproj -c Release",
"clean-winMlAddon": "dotnet clean ./winMlAddon/winMlAddon.csproj"
}
}
Шаблон автоматически включает ссылки на оба пакета SDK, поэтому вы можете сразу же начать вызов Windows API!
Давайте убедимся, что всё настроено правильно, выполнив сборку дополнения:
# Build the C# addon
npm run build-winMlAddon
Замечание
Можно также создать надстройку C++ с помощью npx winapp node create-addon (без флага --template ). Надстройки C++ используют node-addon-api и предоставляют прямой доступ к Windows API с максимальной производительностью. Дополнительные варианты см. в руководстве по добавлению уведомлений C++ или полной документации по команде .
Шаг 2. Скачивание модели SqueezeNet и получение примера кода
Мы будем использовать пример "Классифицировать изображение" из коллекции разработчиков ИИ в качестве нашей ссылки. В этом примере используется модель SqueezeNet 1.1 для классификации изображений.
2.1. Скачивание модели
- Установка AI Dev Gallery
- Перейдите к примеру "Классифицировать изображение"
- Скачайте модель SqueezeNet 1.1 (она поддерживает ЦП, GPU и NPU)
- Нажмите кнопку "Открыть содержащую папку" , чтобы найти
.onnxфайл
- Скопируйте файл
squeezenet1.1.onnxв папкуmodels/в корневом каталоге project
Замечание
Модель также можно скачать непосредственно из репозитория ONNX Model Zoo GitHub
Шаг 3. Добавление обязательных пакетов NuGet
Перед добавлением кода WinML необходимо добавить дополнительные пакеты NuGet, необходимые для обработки изображений, среды выполнения ONNX и поддержки GenAI.
3.1. Обновите файл Directory.packages.props
Добавьте следующие версии пакетов в файл Directory.packages.props, расположенный в корневой директории вашего проекта (этот файл должен был быть создан, когда вы создавали аддон).
<Project>
<PropertyGroup>
<!-- Enable central package versioning -->
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Microsoft.JavaScript.NodeApi" Version="0.9.17" />
<PackageVersion Include="Microsoft.JavaScript.NodeApi.Generator" Version="0.9.17" />
<!-- Add these packages for WinML -->
+ <PackageVersion Include="Microsoft.ML.OnnxRuntime.Extensions" Version="0.14.0" />
+ <PackageVersion Include="System.Drawing.Common" Version="9.0.9" />
+ <PackageVersion Include="Microsoft.Extensions.AI" Version="9.9.1" />
+ <PackageVersion Include="Microsoft.ML.OnnxRuntimeGenAI.Managed" Version="0.10.1" />
+ <PackageVersion Include="Microsoft.ML.OnnxRuntimeGenAI.WinML" Version="0.10.1" />
<!-- These versions may be updated automatically during restore to match yaml -->
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="2.0.0-experimental3" />
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.7175" />
</ItemGroup>
</Project>
3.2. Обновите winMlAddon.csproj
Откройте winMlAddon/winMlAddon.csproj и добавьте ссылки на пакет в <ItemGroup>:
<ItemGroup>
<PackageReference Include="Microsoft.JavaScript.NodeApi" />
<PackageReference Include="Microsoft.JavaScript.NodeApi.Generator" />
<!-- Add these packages for WinML -->
+ <PackageReference Include="Microsoft.ML.OnnxRuntime.Extensions" />
+ <PackageReference Include="System.Drawing.Common" />
+ <PackageReference Include="Microsoft.Extensions.AI" />
+ <PackageReference Include="Microsoft.ML.OnnxRuntimeGenAI.Managed" />
+ <PackageReference Include="Microsoft.ML.OnnxRuntimeGenAI.WinML" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
<PackageReference Include="Microsoft.WindowsAppSDK" />
</ItemGroup>
Что делают эти пакеты:
- Microsoft.ML.OnnxRuntime.Extensions — предоставляет дополнительные операторы и служебные программы для среды выполнения ONNX
- System.Drawing.Common — включает загрузку и обработку изображений для предварительной обработки
- Microsoft. Extensions.AI — абстракции ИИ для .NET
- Microsoft.ML.OnnxRuntimeGenAI.Managed — управляемые привязки для среды выполнения ONNX GenAI
- Microsoft.ML.OnnxRuntimeGenAI.WinML — интеграция WinML для среды выполнения ONNX GenAI
Шаг 4. Добавление примера кода
Галерея разработок ИИ демонстрирует полную реализацию классификации изображений с использованием SqueezeNet:
Мы адаптировали этот код для Electron, и вы можете найти полную реализацию в electron-winml sample. Папка winMlAddon/ содержит измененный код из AI Dev Gallery.
Скопируйте всю winMlAddon/ папку из samples/electron-winml/winMlAddon/в корневой каталог проекта, заменив папку, созданную на шаге 1. Пример включает несколько файлов за пределами addon.cs (вспомогательные классы в Utils/, клиент чата и т. д.), необходимые для сборки и запуска надстройки.
Это важно
Необходимо скопировать всю папку, а не просто addon.cs. Надстройка зависит от вспомогательных файлов в подпапке Utils/ (Prediction.cs, ImageNet.cs, BitmapFunctions.cs и т. д.).
Ключевые сведения о реализации
Давайте выделим важные части реализации и ключевые отличия от кода галереи "AI Dev Gallery":
1. Требование корневого пути проекта
В отличие от кода AI Dev Gallery, наше дополнение для Electron требует передачи корневого пути проекта в коде JavaScript. Это необходимо, так как:
- Надстройка должна найти файл модели ONNX в папке
models/ - Зависимости (библиотеки DLL) должны загружаться из определенных каталогов.
[JSExport]
public static async Task<Addon> CreateAsync(string projectRoot)
{
if (!Path.Exists(projectRoot))
{
throw new Exception("Project root is invalid.");
}
var addon = new Addon(projectRoot);
addon.PreloadNativeDependencies();
string modelPath = Path.Join(projectRoot, "models", @"squeezenet1.1-7.onnx");
await addon.InitModel(modelPath, ExecutionProviderDevicePolicy.DEFAULT, null, false, null);
return addon;
}
При этом автоматически выбирается лучший поставщик выполнения (ЦП, GPU или NPU) на основе возможностей устройств.
2. Предварительная загрузка собственных зависимостей
Надстройка включает PreloadNativeDependencies() метод для загрузки необходимых библиотек DLL. Этот подход подходит для сценариев разработки и рабочей среды без необходимости копирования библиотек DLL в корневой каталог проекта:
private void PreloadNativeDependencies()
{
// Loads required DLLs from the winMlAddon build output
// This ensures dependencies are available regardless of the execution context
}
Это вызывается во время инициализации перед загрузкой модели, обеспечивая доступность всех собственных библиотек.
3. Настройка Electron Forge для пакетирования
Чтобы убедиться, что надстройка работает правильно в рабочих сборках, необходимо настроить пакетный модуль следующим образом:
- Распаковка собственных файлов — библиотеки DLL, модели ONNX и файлы .node должны быть доступны за пределами архива ASAR.
- Исключить ненужные файлы . Сохранение размера пакета небольшим путем исключения артефактов сборки и временных файлов
Для Electron Forge обновите ваш forge.config.js.
// From samples/electron-winml/forge.config.js
module.exports = {
packagerConfig: {
asar: {
// Unpack native files so they can be accessed by the addon
unpack: "**/*.{dll,exe,node,onnx}"
},
ignore: [
// Exclude .winapp folder (SDK packages and headers)
/^\/.winapp\//,
// Exclude MSIX packages
"\\.msix$",
// Exclude winMlAddon source files, but keep the dist folder
/^\/winMlAddon\/(?!dist).+/
]
},
// ... rest of your config
};
Что это делает:
asar.unpack— извлекает библиотеки DLL, исполняемые файлы, двоичные файлы Node.js и модели ONNX вapp.asar.unpacked/- Это делает их доступными во время выполнения с помощью путей файловой системы
- Код JavaScript автоматически настраивает пути (см
app.asar→app.asar.unpackedзамену выше)
ignore— исключается из окончательного пакета:-
.winapp/— пакеты и заголовки пакета SDK (не требуется во время выполнения) -
.msixфайлы — упакованные выходные данные -
winMlAddon/исходные файлы — сохраняет только папкуdist/с скомпилированными двоичными файлами
-
Замечание
Если вы используете другое средство упаковки (электронный построитель и т. д.), необходимо настроить аналогичные параметры для распаковки собственных зависимостей и исключения файлов разработки. Проверьте документацию упаковщика для параметров распаковки ASAR.
4. Классификация изображений
Метод ClassifyImage обрабатывает изображение и возвращает прогнозы:
[JSExport]
public async Task<Prediction[]> ClassifyImage(string imagePath)
{
// Loads the image, preprocesses it, and runs inference
// Returns top predictions with labels and confidence scores
}
Полная реализация обрабатывает:
- Загрузка и предварительная обработка изображений (изменение размера, нормализация)
- Выполнение вывода модели
- Результаты после обработки для получения лучших прогнозов с метками и оценками достоверности
Замечание
Полный исходный код включает предварительную обработку изображений, создание тензоров и анализ результатов. Проверьте пример реализации для всех сведений.
Общие сведения о коде
Надстройка предоставляет следующие основные функции:
- CreateAsync — инициализирует надстройку и загружает модель SqueezeNet
- ClassifyImage — принимает путь к изображению и возвращает прогнозы классификации
WinML автоматически выбирает лучшее устройство выполнения (ЦП, GPU или NPU) на основе доступности.
Шаг 5. Создание аддона на C#
Теперь создайте аддон:
npm run build-winMlAddon
Это компилирует код C# с помощью Native AOT (предварительной компиляции), которая:
- Создает двоичный файл (
.nodeформат нативного плагина) - Удаление неиспользуемого кода с целью уменьшения размера пакета
- На целевых компьютерах не требуется среда выполнения .NET
- Обеспечивает собственную производительность
Скомпилированная надстройка будет находиться в winMlAddon/dist/winMlAddon.node.
Шаг 6. Проверка надстройки
Теперь давайте протестируем, как работает дополнение, вызвав его из основного процесса. Откройте src/main.js и выполните следующие действия:
6.1. Загрузка надстройки
Добавьте оператор require в верхней части:
const winMlAddon = require('../winMlAddon/dist/winMlAddon.node');
6.2. Создание тестовой функции
Добавьте эту функцию для проверки классификации изображений:
const testWinML = async () => {
console.log('Testing WinML addon...');
try {
let projectRoot = path.join(__dirname, '..');
// Adjust path for packaged apps
if (projectRoot.includes('app.asar')) {
projectRoot = projectRoot.replace('app.asar', 'app.asar.unpacked');
}
const addon = await winMlAddon.Addon.createAsync(projectRoot);
console.log('Model loaded successfully!');
// Classify a sample image
const imagePath = path.join(projectRoot, 'test-images', 'sample.jpg');
const predictions = await addon.classifyImage(imagePath);
console.log('Top predictions:');
predictions.slice(0, 5).forEach((pred, i) => {
console.log(`${i + 1}. ${pred.label}: ${(pred.confidence * 100).toFixed(2)}%`);
});
} catch (error) {
console.error('Error testing WinML:', error.message);
}
};
Основные моменты:
- Корректировка пути (
app.asar→app.asar.unpacked) гарантирует, что код работает как в разработке, так и в упакованных приложениях - Это обращается к распакованным собственным файлам, настроенным в
forge.config.js
6.3. Вызов функции тестирования
Добавьте эту строку в конце createWindow() функции:
testWinML();
6.4. Подготовка тестовых образов
Чтобы проверить классификацию изображений, выполните приведенные ниже действия.
- Создайте папку
test-images/в корневом каталоге вашего проекта - Добавление тестового образа с именем
sample.jpg(код ожидает это точное имя файла) - Модель SqueezeNet распознает 1000 различных классов ImageNet (животных, объектов, сцен и т. д.)
При запуске приложения вы увидите результаты классификации в консоли!
Tip
Для получения полной реализации с обработчиками IPC, диалоговыми окнами выбора файлов и пользовательским интерфейсом см. образец electron-winml.
Шаг 7: Обновление идентификатора отладки
Чтобы убедиться, что Windows App SDK загружены и доступны для использования, необходимо убедиться, что мы настроим удостоверение отладки, которое обеспечит загрузку платформы при каждом запуске приложения. Аналогичным образом, когда вы изменяете Package.appxmanifest или изменяете ресурсы, на которые ссылается манифест (например, значки приложений), необходимо обновить идентификатор отладки вашего приложения. Запуск:
npx winapp node add-electron-debug-identity
Эта команда:
- Считывает
Package.appxmanifestсведения о приложении и его возможности - Региструет
electron.exeвnode_modulesс временной идентификацией - Позволяет тестировать API, требующие удостоверения, без полного пакетирования MSIX.
Замечание
Эта команда уже является частью скрипта postinstall , который мы добавили в руководстве по настройке, поэтому он выполняется автоматически после npm install. Тем не менее, его необходимо запускать вручную всякий раз, когда вы:
- Изменить
Package.appxmanifest(изменить возможности, идентификацию или свойства) - Обновление ресурсов приложения (значки, логотипы и т. д.)
Теперь запустите приложение:
npm start
Проверьте выходные данные консоли— вы увидите результаты теста WinML!
⚠️ Известная проблема: сбои приложения или пустое окно (щелкните, чтобы развернуть)
Известна ошибка Windows, связанная с разряженной упаковкой приложений Electron, которая приводит к сбою приложения при запуске или не отображает веб-содержимое. Проблема устранена в Windows, но еще не распространилась на все устройства.
См. инструкции по настройке среды разработки для решения обходным путем.
Дальнейшие шаги
Поздравляю! Вы успешно создали встроенное дополнение, которое может запускать модели машинного обучения с помощью WinML! 🎉
Теперь вы готовы:
- Упаковка приложения для распространения — создание пакета MSIX, который можно распространить
Или ознакомьтесь с другими руководствами:
- Создание дополнения Phi Silica — узнаете, как использовать API Phi Silica AI
- Общие сведения о начале работы - Вернуться к главному руководству
Настройка под вашу модель
Чтобы полностью интегрировать модель ONNX, вам потребуется:
- Общие сведения о входных данных модели — изображения, тензоры, последовательности и т. д.
- Создайте правильные входные привязки - Преобразуйте ваши данные в формат, ожидаемый WinML
- Обработка выходных данных — анализ и интерпретация прогнозов модели
- Корректная обработка ошибок - Загрузка модели и вычисления могут завершиться ошибкой
Дополнительные ресурсы
- Документация По WinML — официальная документация по WinML
- Документация по интерфейсу командной строки winapp — полный справочник по CLI
- Пример приложения Electron — полный рабочий пример
- Коллекция разработчиков ИИ — пример коллекции всех API-интерфейсов ИИ
- Windows App SDK Примеры — коллекция примеров Windows App SDK
- node-api-dotnet — библиотека взаимодействия JavaScript на C# ↔
Troubleshooting
Сбой при сборке с NU1010: элементы PackageReference не определяют соответствующий PackageVersion
Убедитесь, что все пакеты, указанные в winMlAddon.csproj, имеют соответствующие записи в Directory.packages.props. Полный список обязательных пакетов см. на шаге 3.
"недопустимое приложение Win32" при загрузке надстройки
Это означает, что надстройка была создана для архитектуры, отличной от среды выполнения Node.js/Electron. Проверьте архитектуру Node.js:
node -e "console.log(process.arch)"
Затем перестройте надстройку с соответствующим целевым объектом:
# For x64 Node.js:
dotnet publish ./winMlAddon/winMlAddon.csproj -c Release -r win-x64
# For ARM64 Node.js:
dotnet publish ./winMlAddon/winMlAddon.csproj -c Release -r win-arm64
Если вы недавно изменили установку Node.js, также переустановите node_modules , чтобы получить соответствующий двоичный файл Electron:
rm -rf node_modules package-lock.json
npm install
Получение справки
- Обнаружена ошибка?Файл проблемы
- Вопросы WinML? Ознакомьтесь с документацией по WinML
Счастливое машинное обучение! 🤖
Windows developer