Mulai menggunakan Phi3 dan model bahasa lain di aplikasi Windows Anda dengan ONNX Runtime Generative AI
Artikel ini memandu Anda membuat aplikasi WinUI 3 yang menggunakan model Phi3 dan pustaka ONNX Runtime Generative AI untuk mengimplementasikan aplikasi obrolan AI generatif sederhana. Model bahasa besar (LLM) memungkinkan Anda menambahkan kemampuan pembuatan teks, transformasi, penalaran, dan terjemahan ke aplikasi Anda. Untuk informasi selengkapnya tentang menggunakan model AI dan pembelajaran mesin di aplikasi windows Anda, lihat Mulai menggunakan AI di Windows. Untuk informasi selengkapnya tentang ONNX runtime dan AI generatif, lihat AI Generatif dengan ONNX Runtime.
Saat menggunakan fitur AI, kami sarankan Anda meninjau: Mengembangkan Aplikasi dan Fitur AI Generatif yang Bertanggung Jawab di Windows.
Apa itu ONNX Runtime
ONNX Runtime adalah akselerator model pembelajaran mesin lintas platform, dengan antarmuka fleksibel untuk mengintegrasikan pustaka khusus perangkat keras. ONNX Runtime dapat digunakan dengan model dari PyTorch, Tensorflow/Keras, TFLite, scikit-learn, dan kerangka kerja lainnya. Untuk informasi selengkapnya, lihat situs web ONNX Runtime di https://onnxruntime.ai/docs/.
Prasyarat
- Perangkat Anda harus mengaktifkan mode pengembang. Untuk informasi selengkapnya, silakan lihat Mengaktifkan perangkat Anda untuk pengembangan.
- Visual Studio 2022 atau yang lebih baru dengan beban kerja pengembangan desktop .NET.
Membuat aplikasi C# WinUI baru
Di Visual Studio, buat proyek baru. Dalam dialog Buat proyek baru, atur filter bahasa ke "C#" dan filter tipe proyek ke "winui", lalu pilih template aplikasi Kosong, Dipaketkan (WinUI3 di Desktop) . Beri nama proyek baru "GenAIExample".
Menambahkan referensi ke paket nuget ONNX Runtime Generative AI
Di Penjelajah Solusi, klik kanan Dependensi dan pilih Kelola paket NuGet.... Di manajer paket NuGet, pilih tab Telusuri. Cari "Microsoft.ML.OnnxRuntimeGenAI.DirectML", pilih versi stabil terbaru di daftar drop-down Versi lalu klik Instal.
Menambahkan model dan file kosakata ke proyek Anda
Di Penjelajah Solusi, klik kanan proyek Anda dan pilih Tambah>Folder Baru. Beri nama folder baru "Model". Untuk contoh ini, kita akan menggunakan model dari https://huggingface.co/microsoft/Phi-3-mini-4k-instruct-onnx/tree/main/directml/directml-int4-awq-block-128.
Ada beberapa cara berbeda untuk mendapatkan model. Untuk panduan ini, kita akan menggunakan Hugging Face Command Line Interface (CLI). Jika Anda mendapatkan model menggunakan metode lain, Anda mungkin harus menyesuaikan jalur file ke model dalam kode contoh. Untuk informasi tentang menginstal Hugging Face CLI dan menyiapkan akun Anda untuk menggunakannya, lihat Command Line Interface (CLI).
Setelah menginstal CLI, buka terminal, navigasikan ke direktori Models
yang Anda buat, dan ketik perintah berikut.
huggingface-cli download microsoft/Phi-3-mini-4k-instruct-onnx --include directml/* --local-dir .
Ketika operasi selesai verifikasi bahwa file berikut ada: [Project Directory]\Models\directml\directml-int4-awq-block-128\model.onnx
.
Di Penjelajah Solusi, perluas folder "directml-int4-awq-block-128" dan pilih semua file dalam folder. Di panel File Properti, atur Salin ke Direktori Output menjadi "Salin jika lebih baru".
Menambahkan antarmuka pengguna sederhana untuk berinteraksi dengan model
Untuk contoh ini, kita akan membuat UI yang sangat sederhana yang memiliki TextBox untuk menentukan perintah, tombol untuk mengirimkan perintah, dan TextBlock untuk menampilkan pesan status dan respons dari model. Ganti elemen StackPanel default di MainWindow.xaml
dengan XAML berikut.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column ="0">
<TextBox x:Name="promptTextBox" Text="Compose a haiku about coding."/>
<Button x:Name="myButton" Click="myButton_Click">Submit prompt</Button>
</StackPanel>
<Border Grid.Column="1" Margin="20">
<TextBlock x:Name="responseTextBlock" TextWrapping="WrapWholeWords"/>
</Border>
</Grid>
Menginisialisasi model
Di
using Microsoft.ML.OnnxRuntimeGenAI;
Deklarasikan variabel anggota di dalam definisi kelas MainPage untuk Model dan Tokenizer. Atur lokasi untuk file model yang kami tambahkan di langkah-langkah sebelumnya.
private Model? model = null;
private Tokenizer? tokenizer = null;
private readonly string ModelDir =
Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
@"Models\directml\directml-int4-awq-block-128");
Buat metode pembantu untuk menginisialisasi model secara asinkron. Metode ini memanggil konstruktor untuk kelas Model , dengan meneruskan jalur ke direktori model. Selanjutnya membuat Tokenizer baru dari model.
public Task InitializeModelAsync()
{
DispatcherQueue.TryEnqueue(() =>
{
responseTextBlock.Text = "Loading model...";
});
return Task.Run(() =>
{
var sw = Stopwatch.StartNew();
model = new Model(ModelDir);
tokenizer = new Tokenizer(model);
sw.Stop();
DispatcherQueue.TryEnqueue(() =>
{
responseTextBlock.Text = $"Model loading took {sw.ElapsedMilliseconds} ms";
});
});
}
Untuk contoh ini, kita akan memuat model ketika jendela utama diaktifkan. Perbarui konstruktor halaman untuk mendaftarkan handler untuk acara yang mengaktifkan.
public MainWindow()
{
this.InitializeComponent();
this.Activated += MainWindow_Activated;
}
Peristiwa Diaktifkan dapat dipanggil beberapa kali, jadi di penanganan peristiwa, pastikan dengan memeriksa bahwa model null sebelum menginisialisasinya.
private async void MainWindow_Activated(object sender, WindowActivatedEventArgs args)
{
if (model == null)
{
await InitializeModelAsync();
}
}
Mengirimkan perintah ke model
Buat metode bantu yang mengirimkan permintaan ke model dan kemudian mengembalikan hasil secara asinkron kepada pemanggil dengan IAsyncEnumerable.
Dalam metode ini, kelas Generator digunakan dalam perulangan, memanggil GenerateNextToken pada setiap pengulangan untuk mengambil karakter berikutnya yang diprediksi oleh model, yang disebut token, berdasarkan prompt input. Perulangan beroperasi hingga metode IsDone dari generator
public async IAsyncEnumerable<string> InferStreaming(string prompt)
{
if (model == null || tokenizer == null)
{
throw new InvalidOperationException("Model is not ready");
}
var generatorParams = new GeneratorParams(model);
var sequences = tokenizer.Encode(prompt);
generatorParams.SetSearchOption("max_length", 2048);
generatorParams.SetInputSequences(sequences);
generatorParams.TryGraphCaptureWithMaxBatchSize(1);
using var tokenizerStream = tokenizer.CreateStream();
using var generator = new Generator(model, generatorParams);
StringBuilder stringBuilder = new();
while (!generator.IsDone())
{
string part;
try
{
await Task.Delay(10).ConfigureAwait(false);
generator.ComputeLogits();
generator.GenerateNextToken();
part = tokenizerStream.Decode(generator.GetSequence(0)[^1]);
stringBuilder.Append(part);
if (stringBuilder.ToString().Contains("<|end|>")
|| stringBuilder.ToString().Contains("<|user|>")
|| stringBuilder.ToString().Contains("<|system|>"))
{
break;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
break;
}
yield return part;
}
}
Tambahkan kode antarmuka pengguna untuk mengirimkan perintah dan menampilkan hasilnya
Di handler klik Tombol , pertama-tama verifikasi bahwa model tidak null. Buat string prompt dengan sistem dan permintaan pengguna dan panggil InferStreaming, memperbarui TextBlock dengan setiap bagian respons.
Model yang digunakan dalam contoh ini telah dilatih untuk menerima perintah dalam format berikut, di mana systemPrompt
adalah instruksi tentang bagaimana model harus bersifat, dan userPrompt
adalah pertanyaan dari pengguna.
<|system|>{systemPrompt}<|end|><|user|>{userPrompt}<|end|><|assistant|>
Model sebaiknya mendokumentasikan konvensi prompt mereka. Untuk model ini, format didokumenkan pada kartu model Huggingface.
private async void myButton_Click(object sender, RoutedEventArgs e)
{
responseTextBlock.Text = "";
if(model != null)
{
var systemPrompt = "You are a helpful assistant.";
var userPrompt = promptTextBox.Text;
var prompt = $@"<|system|>{systemPrompt}<|end|><|user|>{userPrompt}<|end|><|assistant|>";
await foreach (var part in InferStreaming(prompt))
{
responseTextBlock.Text += part;
}
}
}
Jalankan contoh
Di Visual Studio, di drop-down Platform Solusi, pastikan prosesor target diatur ke x64. Pustaka AI Generatif ONNXRuntime tidak mendukung x86. Bangun dan jalankan proyek. Tunggu hingga TextBlock menunjukkan bahwa model telah dimuat. Ketik perintah ke dalam kotak teks perintah dan klik tombol kirim. Anda seharusnya melihat hasilnya secara bertahap terisi pada blok teks.