WinML Eklentisi Oluşturma

Bu kılavuzda, Electron uygulamanızda Windows Machine Learning (WinML) kullanan bir C# yerel eklentisinin nasıl oluşturulacağı gösterilmektedir. WinML, görüntü sınıflandırma, nesne algılama ve daha fazlası gibi görevler için windows cihazlarında machine learning modelleri (ONNX biçimi) yerel olarak çalıştırmanızı sağlar.

Önkoşullar

Bu kılavuza başlamadan önce şunları yaptığınızdan emin olun:

Uyarı

WinML herhangi bir Windows 10 (1809+) veya Windows 11 cihazda çalışır. En iyi performans için GPU'ları veya NPU'ları olan cihazlar önerilir, ancak API de CPU üzerinde çalışır.

Important

WinML eklentisi experimental Windows Uygulama SDK'sı gerektirir. Kurulum kılavuzunda winapp init "Kararlı SDK'lar" seçeneğini belirlediyseniz SDK sürümünüzü güncelleştirmeniz gerekir. winapp.yaml düzenleyin ve Microsoft.WindowsAppSDK sürümünü 2.0.0-experimental3 olarak değiştirin, ardından güncelleştirmek için npx winapp restore çalıştırın.

1. Adım: C# Yerel Eklentisi Oluşturma

Şimdi WinML API'lerini kullanacak yerel bir eklenti oluşturalım. JavaScript ve C# arasında köprü oluşturmak için node-api-dotnet kullanan bir C# şablonu kullanacağız.

npx winapp node create-addon --template cs --name winMlAddon

Bu, şunu içeren bir winMlAddon/ klasör oluşturur:

  • addon.cs - WinML API'lerini çağıracak C# kodunuz
  • winMlAddon.csproj - Windows SDK ve Windows Uygulama SDK'sı referansları içeren Project Dosyası
  • README.md - Eklentiyi kullanma belgeleri

Komut, eklentiyi oluşturmak için build-winMlAddon betiğine ve derleme yapıtlarını temizlemek için package.json betiğine ekler.

{
  "scripts": {
    "build-winMlAddon": "dotnet publish ./winMlAddon/winMlAddon.csproj -c Release",
    "clean-winMlAddon": "dotnet clean ./winMlAddon/winMlAddon.csproj"
  }
}

Şablon her iki SDK'ya da otomatik olarak başvurular içerdiğinden, hemen Windows API'leri çağırmaya başlayabilirsiniz!

Şimdi eklentiyi oluşturarak her şeyin doğru şekilde ayarlandığını doğrulayalım:

# Build the C# addon
npm run build-winMlAddon

Uyarı

Ayrıca kullanarak npx winapp node create-addon (bayrak olmadan --template ) bir C++ eklentisi de oluşturabilirsiniz. C++ eklentileri node-addon-api kullanır ve maksimum performansla Windows API'lere doğrudan erişim sağlar. İzlenecek yol için C++ Bildirim Eklentisi kılavuzuna veya diğer seçenekler için tam komut belgelerine bakın.

2. Adım: SqueezeNet Modelini İndirme ve Örnek Kod Alma

AI Geliştirme Galerisi'ndenGörüntü Sınıflandırma örneğini başvuru olarak kullanacağız. Bu örnek, görüntü sınıflandırması için SqueezeNet 1.1 modelini kullanır.

2.1. Modeli İndirme

  1. Yapay Zeka Geliştirme Galerisi'ni yükleme
  2. Görüntüyü Sınıflandır örneğine gidin
  3. SqueezeNet 1.1 modelini indirin (CPU, GPU ve NPU destekler)
  4. Dosyayı bulmak için İçerilen Klasörü Aç'a.onnx tıklayın

AI Geliştirme Galerisi'nden SqueezeNet'i indirme

  1. squeezenet1.1.onnx dosyasını project kökünüzdeki bir models/ klasörüne kopyalayın

3. Adım: Gerekli NuGet Paketlerini Ekleme

WinML kodunu eklemeden önce görüntü işleme, ONNX Çalışma Zamanı ve GenAI desteği için gereken ek NuGet paketlerini eklememiz gerekir.

3.1. Directory.packages.props dosyasını güncelleştirin

Projenizin kökündeki dosyaya Directory.packages.props aşağıdaki paket sürümlerini ekleyin (eklentiyi oluşturduğunuzda oluşturulmuş olması gerekir):

<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 dosyasını güncelle

Açın winMlAddon/winMlAddon.csproj ve paket başvurularını <ItemGroup>'e ekleyin.

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

Bu paketler ne yapar:

  • Microsoft.ML.OnnxRuntime.Extensions - ONNX Çalışma Zamanı için ek işleçler ve yardımcı programlar sağlar
  • System.Drawing.Common - Ön işleme için görüntü yükleme ve işlemeyi etkinleştirir
  • Microsoft. Extensions.AI - .NET için yapay zeka soyutlamaları
  • Microsoft.ML.OnnxRuntimeGenAI.Managed - ONNX Runtime GenAI için yönetilen bağlamalar
  • Microsoft.ML.OnnxRuntimeGenAI.WinML - ONNX Runtime GenAI için WinML tümleştirmesi

4. Adım: Örnek Kodu Ekleme

AI Geliştirme Galerisi, SqueezeNet ile görüntü sınıflandırması için tam uygulamayı gösterir:

SqueezeNet Örnek Kodu

Bu kodu Electron için uyarladık ve tam uygulamayı electron-winml örneğinde bulabilirsiniz. klasörü, winMlAddon/ AI Geliştirme Galerisi'nden değiştirilen kodu içerir.

winMlAddon/ tamamını proje kökünüze kopyalayın ve 1. Adımda oluşturulan klasörü değiştirin. Örnek, addon.cs haricinde (Utils/ içinde yer alan yardımcı sınıflar, bir sohbet istemcisi vb.) eklentinin derlenip çalışması için gereken birden çok dosya içerir.

Important

Yalnızca klasörünü değiladdon.cs kopyalamanız gerekir. Eklenti, alt klasördeki Utils/ (Prediction.cs, ImageNet.cs, BitmapFunctions.csvb.) yardımcı dosyalara bağlıdır.

Önemli Uygulama Ayrıntıları

Şimdi uygulamanın önemli bölümlerini ve Yapay Zeka Geliştirme Galerisi kodundan önemli farkları vurgulayalım:

1. Proje Kök Dizin Gereksinimi

AI Geliştirme Galerisi kodundan farklı olarak, Electron eklentimiz proje kök yolunu geçirmek için JavaScript kodunu gerektirir. Aşağıdakiler nedeniyle bu gereklidir:

  • Eklentinin belirtilen models/ klasöründe ONNX model dosyasını bulması gerekiyor.
  • Yerel bağımlılıkların (DLL) belirli dizinlerden yüklenmesi gerekir
[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;
}

Bu, cihaz özelliklerine göre en iyi yürütme sağlayıcısını (CPU, GPU veya NPU) otomatik olarak seçer.

2. Yerel Bağımlılıkları Önceden Yükleme

Eklenti, gerekli DLL'leri yüklemek için bir PreloadNativeDependencies() yöntem içerir. Bu yaklaşım, DLL'leri proje köküne kopyalamaya gerek kalmadan hem geliştirme hem de üretim senaryolarında çalışır:

private void PreloadNativeDependencies()
{
    // Loads required DLLs from the winMlAddon build output
    // This ensures dependencies are available regardless of the execution context
}

Bu, modeli yüklemeden önce başlatma sırasında çağrılır ve tüm yerel kitaplıkların kullanılabilir olduğundan emin olur.

3. Paketleme için Elektron Çatalı Yapılandırma

Eklentinin üretim derlemelerinde doğru çalıştığından emin olmak için paketleyicinizi şu şekilde yapılandırmanız gerekir:

  1. Yerel dosyaları açma - DLL'ler, ONNX modelleri ve .node dosyalarına ASAR arşivi dışından erişilebilir olmalıdır
  2. Gereksiz dosyaları dışlama - Derleme yapıtlarını ve geçici dosyaları dışlayarak paket boyutunu küçük tutun

Electron Forge için güncelleme yapınforge.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
};

İşlevi:

  1. asar.unpack - DLL'leri, exe dosyalarını, .node ikili dosyalarını ve ONNX modellerini app.asar.unpacked/

    • Bu, çalışma zamanında dosya sistemi yolları aracılığıyla erişilebilir olmalarını sağlar
    • JavaScript kodu yolları otomatik olarak ayarlar (yukarıdaki → app.asar değiştirme bölümüne app.asar.unpacked bakın)
  2. ignore - Son paketin dışında tutulur:

    • .winapp/ - SDK paketleri ve üst bilgileri (çalışma zamanında gerekli değildir)
    • .msix files: Paketlenmiş çıkışlar
    • winMlAddon/ kaynak dosyalar - Yalnızca derlenmiş ikili dosyaların bulunduğu dist/ klasörü tutar

Uyarı

Farklı bir paketleme aracı (elektron oluşturucu vb.) kullanıyorsanız, yerel bağımlılıkları açmak ve geliştirme dosyalarını dışlamak için benzer ayarları yapılandırmanız gerekir. ASAR paket açma seçenekleri için paketleyicinizin belgelerine bakın.

4. Görüntü Sınıflandırma

ClassifyImage yöntemi bir görüntüyü işler ve tahminler döndürür:

[JSExport]
public async Task<Prediction[]> ClassifyImage(string imagePath)
{
    // Loads the image, preprocesses it, and runs inference
    // Returns top predictions with labels and confidence scores
}

Uygulamanın tamamı şunu işler:

  • Görüntü yükleme ve ön işleme (yeniden boyutlandırma, normalleştirme)
  • Model çıkarımı çalıştırma
  • Etiketler ve güvenilirlik puanlarıyla en iyi tahminleri almak için işleme sonrası sonuçlar

Uyarı

Tam kaynak kodu görüntü ön işleme, tensor oluşturma ve sonuç ayrıştırma içerir. Tüm ayrıntılar için örnek uygulamayı denetleyin.

Kodu Anlama

Eklenti şu ana işlevleri sağlar:

  1. CreateAsync - Eklentiyi başlatır ve SqueezeNet modelini yükler
  2. ClassifyImage - Bir görüntü yolu alır ve sınıflandırma tahminlerini döndürür

WinML, kullanılabilirliğe göre en iyi yürütme cihazını (CPU, GPU veya NPU) otomatik olarak seçer.

5. Adım: C# Eklentisini Oluşturma

Şimdi eklentiyi derleyin:

npm run build-winMlAddon

Bu, C# kodunuzu Yerel AOT (Önceden Derleme) kullanarak derler:

  • Oluşturur .node ikili dosya (yerel eklenti biçimi)
  • Kullanılmayan kodu daha küçük paket boyutu için kırpıyor
  • Hedef makinelerde .NET çalışma zamanı gerektirmez
  • Yerel performans sağlar

Derlenen eklenti winMlAddon/dist/winMlAddon.node içinde olacaktır.

6. Adım: Eklentiyi Test Edin

Şimdi eklentiyi ana işlemden çağırarak çalışmasını test edelim. src/main.js'yi açın ve şu adımları izleyin:

6.1. Eklentiyi Yükleme

Require deyimlerini en üste ekleyin:

const winMlAddon = require('../winMlAddon/dist/winMlAddon.node');

6.2. Test İşlevi Oluşturma

Görüntü sınıflandırmasını test etmek için bu işlevi ekleyin:

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

Önemli noktalar:

  • Yol ayarı (app.asarapp.asar.unpacked), kodun hem geliştirme hem de paketlenmiş uygulamalarda çalışmasını sağlar
  • Bu, içinde yapılandırılan paketlenmemiş yerel dosyalara erişir forge.config.js

6.3. Test İşlevini Çağırma

İşlevin sonuna createWindow() şu satırı ekleyin:

testWinML();

6.4. Test Görüntülerini Hazırlama

Görüntü sınıflandırmasını test etmek için:

  1. test-images/ Proje kökünde klasör oluşturma
  2. adlı sample.jpg bir test görüntüsü ekleyin (kod tam olarak bu dosya adını bekler)
  3. SqueezeNet modeli 1000 farklı ImageNet sınıfını (hayvanlar, nesneler, sahneler vb.) tanır

Uygulamayı çalıştırdığınızda, sınıflandırma sonuçlarını konsolda görürsünüz!

İpucu

IPC işleyicileri, dosya seçimi iletişim kutuları ve kullanıcı arabirimi ile eksiksiz bir uygulama için bkz. electron-winml örneği.

7. Adım: Hata Ayıklama Kimliğini Güncelleştirme

Windows Uygulama SDK'sı yüklendiğinden ve kullanılabilir olduğundan emin olmak için uygulamamız her çalıştırıldığında çerçevenin yüklendiğinden emin olmak için hata ayıklama kimliği ayarlamamız gerekir. Benzer şekilde, Package.appxmanifest ögesini her değiştirdiğinizde veya bildirimde belirtilen varlıkları (örneğin, uygulama simgeleri) değiştirdiğinizde, uygulamanızın hata ayıklama kimliğini güncelleştirmeniz gerekir. Koş!

npx winapp node add-electron-debug-identity

Bu komut:

  1. Package.appxmanifest öğesini okuyarak uygulama ayrıntılarını ve özelliklerini alır
  2. electron.exe Geçici bir kimlikle kaydınızı gerçekleştirir node_modules
  3. Tam MSIX paketlemesi olmadan kimlik gerektiren API'leri test etmenizi sağlar

Uyarı

Bu komut, kurulum kılavuzuna postinstall eklediğimiz betiğin bir parçasıdır, bu nedenle komutundan sonra npm installotomatik olarak çalışır. Ancak, her seferinde manuel çalıştırmanız gerekir:

  • Değiştir Package.appxmanifest (yetenekleri, kimliği veya özellikleri değiştirme)
  • Uygulama varlıklarını (simgeler, logolar vb.) güncelleştirme

Şimdi uygulamanızı çalıştırın:

npm start

Konsol çıkışını denetleyin- WinML test sonuçlarını görmeniz gerekir!

⚠️ Bilinen Sorun: Uygulama Kilitlenmeleri veya Boş Pencere (genişletmek için tıklayın)

Bilinen bir Windows hatası, Electron uygulamalarının seyrek paketleme yönteminde başlangıçta çökmesine veya web içeriğini göstermemesine neden olabilir. Sorun Windows düzeltildi ancak henüz tüm cihazlara yayılmadı.

Geçici çözüm için bkz. geliştirme ortamı kurulumu .

Sonraki Adımlar

Tebrikler! WinML ile makine öğrenmesi modellerini çalıştırabilen yerel bir eklentiyi başarıyla oluşturdunuz! 🎉

Artık şunu yapmaya hazırsınız:

Veya diğer kılavuzları keşfedin:

Modeliniz için Özelleştirme

ONNX modelinizi tam olarak tümleştirmek için şunları yapmanız gerekir:

  1. Modelinizin girişlerini anlama : Görüntüler, tensorlar, diziler vb.
  2. Uygun giriş bağlamaları oluşturma - Verilerinizi WinML'nin beklediği biçime dönüştürün
  3. Çıkışları işleme - Modelin tahminlerini ayrıştırma ve yorumlama
  4. Hataları düzgün bir şekilde işleme - Model yükleme ve çıkarım başarısız olabilir

Ek Kaynaklar

Sorun giderme

NU1010 ile derleme başarısız oluyor: PackageReference öğeleri ilgili PackageVersion öğesini tanımlamaz

winMlAddon.csproj içinde başvurulan tüm paketlerin Directory.packages.props içinde eşleşen girişlere sahip olduğundan emin olun. Gerekli paketlerin tam listesi için 3. adıma bakın.

eklentisini yüklerken "geçerli bir Win32 uygulaması değil"

Bu, eklentinin Node.js/Electron çalışma zamanınızdan farklı bir mimari için oluşturulduğu anlamına gelir. Node.js mimarinizi denetleyin:

node -e "console.log(process.arch)"

Ardından eklentiyi eşleşen hedefle yeniden derleyin:

# 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 yüklemenizi yakın zamanda değiştirdiyseniz, eşleşen Electron ikili dosyasını elde etmek için node_modules bileşenini de yeniden yükleyin.

rm -rf node_modules package-lock.json
npm install

Yardım Alın

Makine öğrenmesi kutlu olsun! 🤖