Zelfstudie: Een chat-app bouwen met PhiSilium en WinUI 3

In deze zelfstudie wordt een eenvoudige WinUI 3-desktop-app gebouwd die gebruikmaakt van het PhiSilium-taalmodel op het apparaat. Met de voltooide app kunt u een prompt typen, een vaardigheid kiezen (chatten, samenvatten of herschrijven) en het antwoord zien dat lokaal op uw apparaat is gegenereerd, geen cloudoproep, geen API-sleutel.

Belangrijk

Phi Silicium vereist een Copilot+ pc. Het model wordt uitgevoerd op de NPU van het apparaat en is niet beschikbaar op standaard-pc's. Als u geen Copilot+ pc hebt, raadpleegt u Foundry Local als alternatief dat wordt uitgevoerd op een moderne Windows-pc.

Belangrijk

De Phi Silicium API's maken deel uit van een beperkte toegangsfunctie. Gebruik het LAF-toegangstokenaanvraagformulier voor meer informatie of om een ontgrendelingstoken aan te vragen.

Opmerking

Phi Silicium kenmerken zijn niet beschikbaar in China.

Wat u gaat bouwen

Een WinUI 3-app met:

  • Een snel invoervak
  • Een vaardigheidkiezer (chat/ samenvatten/herschrijven)
  • Een weergavegebied voor antwoorden
  • Statusfeedback tijdens het laden van het model

Schermopname van de voltooide Phi Silicium-chat-app met een prompt en antwoord.

Vereiste voorwaarden

  1. Copilot+ PC - vereist voor NPU-versnelling. Raadpleeg de ontwikkelaarshandleiding voor Copilot+ pc's.

  2. Windows 11 build 26100 of hoger (25H2) - neem contact op met winver Windows Search.

  3. Ontwikkelaarsmodus ingeschakeld: Windows-instellingen → System → Voor ontwikkelaars → ontwikkelaarsmodus.

  4. Visual Studio 2022 waarop de workload windows-toepassingsontwikkeling is geïnstalleerd. Zie Benodigde werkbelasting en onderdelen.

  5. Windows App SDK 2.0 Preview NuGet-pakket : Microsoft.WindowsAppSDK versie 2.0.0-preview1. U installeert dit in de onderstaande stappen.

  6. PhiSilium LAF-ontgrendeltoken - vraag er een aan met behulp van de bovenstaande koppeling. Zonder deze mislukken aanroepen naar de API, met een foutmelding dat de toegang werd geweigerd.

Tip: Voer in één stap de opdracht voor automatische installatie uit in Windows Terminal om Visual Studio en de Windows App SDK te installeren:

winget configure https://raw.githubusercontent.com/microsoft/winget-dsc/refs/heads/main/samples/Configuration%20files/Learn%20tutorials/Windows%20AI/learn_wcr.winget

Stap 1: Het project maken

  1. Open Visual Studio.

  2. Selecteer Een nieuw project maken, zoek naar WinUI en selecteer Blank App, Packaged (WinUI 3 in Desktop).

  3. Geef het project PhiSilicaChateen naam, kies een locatie en selecteer Maken.

  4. Klik in Solution Explorer met de rechtermuisknop op het project en klik op NuGet-pakketten beheren.

  5. Schakel Prerelease inschakelen in, zoek naar Microsoft.WindowsAppSDK, selecteer versie 2.0.0-preview1, en klik op Installeren.

  6. Stel de buildconfiguratie in op ARM64 in de vervolgkeuzelijst op de werkbalk.

  7. Selecteer PhiSilicaChat (Pakket) in de vervolgkeuzelijst met het startprofiel van de werkbalk (naast de afspeelknop), niet het uitgepakte profiel.

    Belangrijk

    De LanguageModel API werkt alleen in een verpakte MSIX-app. Als u het niet-ingepakte profiel per ongeluk uitvoert, zal GetReadyState() een COM-fout genereren. Gebruik altijd het msixPackage-startprofiel .

Stap 2: het app-manifest configureren

De app heeft de systemAIModels mogelijkheid en een minimale versie van het besturingssysteem 10.0.26100.0 nodig om toegang te krijgen tot PhiSilium.

  1. Klik in Solution Explorer met de rechtermuisknop Package.appxmanifest en selecteer Code weergeven.

  2. Zoek de openingstag <Package en vervang de volledige <Package ...> openingstag door deze versie:

    <Package
      xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
      xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
      xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
      xmlns:systemai="http://schemas.microsoft.com/appx/manifest/systemai/windows10"
      IgnorableNamespaces="uap rescap systemai">
    

    Belangrijk

    De xmlns:systemai declaratie moet worden weergegeven in de <Package> openingslabel. Het toevoegen van <systemai:Capability> zonder de naamruimteverklaring hier veroorzaakt een parseerfout met een 'niet-gedefinieerd voorvoegsel'.

  3. Zoek het <Dependencies>-element en vervang het volledig — het verhogen van MinVersion naar 10.0.26100.0 is vereist. Als de minimale versie lager is, negeert Windows op de achtergrond de systemai:Capability en GetReadyState() genereert 'Niet gedeclareerd door app':

    <Dependencies>
      <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.26100.0" MaxVersionTested="10.0.26300.0" />
      <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.26100.0" MaxVersionTested="10.0.26300.0" />
    </Dependencies>
    
  4. Zoek het <Capabilities> element en vervang het volledig door :

    <Capabilities>
      <rescap:Capability Name="runFullTrust"/>
      <systemai:Capability Name="systemAIModels"/>
    </Capabilities>
    

Stap 3: Het projectbestand configureren

Voorkomen dat Visual Studio de instellingen voor de manifestversie overschrijft.

  1. Klik in Solution Explorer met de rechtermuisknop op de projectnaam (het knooppunt op het hoogste niveau met het C#-pictogram, net onder de oplossing) en selecteer Projectbestand bewerken. Hiermee opent u het .csproj bestand rechtstreeks in de editor. Het wordt niet weergegeven als een bestand in Solution Explorer.

  2. Voeg binnen het element het <PropertyGroup> volgende toe:

    <AppxOSMinVersionReplaceManifestVersion>false</AppxOSMinVersionReplaceManifestVersion>
    <AppxOSMaxVersionTestedReplaceManifestVersion>false</AppxOSMaxVersionTestedReplaceManifestVersion>
    

Stap 4: de gebruikersinterface bouwen

Vervang de inhoud van MainWindow.xaml door het volgende:

<Window
    x:Class="PhiSilicaChat.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Phi Silica Chat">

    <Grid Margin="24" RowSpacing="12">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <TextBlock Grid.Row="0" Text="Phi Silica Chat" Style="{StaticResource TitleTextBlockStyle}"/>

        <TextBox Grid.Row="1"
                 x:Name="PromptBox"
                 PlaceholderText="Enter your prompt here..."
                 AcceptsReturn="True"
                 MinHeight="80"
                 TextWrapping="Wrap"/>

        <StackPanel Grid.Row="2" Orientation="Horizontal" Spacing="12">
            <ComboBox x:Name="SkillSelector" SelectedIndex="0" MinWidth="160">
                <ComboBoxItem Content="Chat (no skill)"/>
                <ComboBoxItem Content="Summarize"/>
                <ComboBoxItem Content="Rewrite"/>
            </ComboBox>
            <Button x:Name="SendButton" Content="Generate" Click="OnSendClicked" Style="{StaticResource AccentButtonStyle}"/>
        </StackPanel>

        <ScrollViewer Grid.Row="3" VerticalScrollBarVisibility="Auto" Margin="0,8,0,0">
            <TextBlock x:Name="ResponseText"
                       TextWrapping="Wrap"
                       IsTextSelectionEnabled="True"
                       FontSize="14"/>
        </ScrollViewer>

        <TextBlock Grid.Row="4" x:Name="StatusText" Opacity="0.6" FontSize="12"/>
    </Grid>
</Window>

Stap 5: Voeg de code-behind toe

Opmerking

De LanguageModelSkill opsomming (Summarize, Rewrite) is niet beschikbaar in alle experimentele builds van de Windows App SDK. In deze zelfstudie wordt prompt-engineering gebruikt om hetzelfde resultaat te bereiken, waarbij het model wordt geïnstrueerd via de prompttekst. Wanneer de Skill-API beschikbaar wordt in een stabiele release, kunt u de prompttekenreeksconstructie vervangen door new LanguageModelOptions { Skill = LanguageModelSkill.Summarize }.

Vervang de inhoud van MainWindow.xaml.cs door het volgende:

using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.Windows.AI;
using Microsoft.Windows.AI.Text;
using System;
using Windows.ApplicationModel;

namespace PhiSilicaChat;

public sealed partial class MainWindow : Window
{
    private LanguageModel? _languageModel;

    public MainWindow()
    {
        InitializeComponent();
        InitializeModelAsync();
    }

    private async void InitializeModelAsync()
    {
        SendButton.IsEnabled = false;
        StatusText.Text = "Checking model availability...";

        // Unlock the Limited Access Feature.
        // Replace these values with the token and attestation string provided by Microsoft.
        // Request your token at https://go.microsoft.com/fwlink/?linkid=2271232&c1cid=04x409
        var access = LimitedAccessFeatures.TryUnlockFeature(
            "com.microsoft.windows.ai.languagemodel",
            "YOUR_TOKEN_HERE",
            "YOUR_ATTESTATION_STRING_HERE");

        if (access.Status != LimitedAccessFeatureStatus.Available &&
            access.Status != LimitedAccessFeatureStatus.AvailableWithoutToken)
        {
            StatusText.Text = $"Feature access denied (LAF status: {access.Status}). Check your token.";
            return;
        }

        try
        {
            var readyState = LanguageModel.GetReadyState();

            if (readyState == AIFeatureReadyState.NotReady)
            {
                StatusText.Text = "Model not ready — installing. This may take a few minutes...";
                var ensureResult = await LanguageModel.EnsureReadyAsync();

                if (ensureResult.ExtendedError != null)
                {
                    StatusText.Text = $"Model installation failed: {ensureResult.ExtendedError.Message}";
                    return;
                }
            }
            else if (readyState == AIFeatureReadyState.NotSupportedOnCurrentSystem)
            {
                StatusText.Text = "Phi Silica is not supported on this device. A Copilot+ PC is required.";
                ResponseText.Text = "Phi Silica requires a Copilot+ PC with an NPU.\n\n" +
                                     "For on-device AI on any Windows PC, see Foundry Local:\n" +
                                     "https://learn.microsoft.com/windows/ai/foundry-local/get-started";
                return;
            }

            _languageModel = await LanguageModel.CreateAsync();
            StatusText.Text = "Model ready.";
            SendButton.IsEnabled = true;
        }
        catch (Exception ex)
        {
            StatusText.Text = $"Model init failed: {ex.Message}";
        }
    }

        if (readyState == AIFeatureReadyState.NotReady)
        {
            StatusText.Text = "Model not ready — installing. This may take a few minutes...";
            var ensureResult = await LanguageModel.EnsureReadyAsync();

            if (ensureResult.ExtendedError != null)
            {
                StatusText.Text = $"Model installation failed: {ensureResult.ExtendedError.Message}";
                return;
            }
        }
        else if (readyState == AIFeatureReadyState.NotSupportedOnCurrentSystem)
        {
            // This device does not have a compatible NPU or is not a Copilot+ PC.
            // Consider falling back to Foundry Local or an Azure OpenAI endpoint.
            StatusText.Text = "Phi Silica is not supported on this device. A Copilot+ PC is required.";
            ResponseText.Text = "Phi Silica requires a Copilot+ PC with an NPU.\n\n" +
                                 "For on-device AI on any Windows PC, see Foundry Local:\n" +
                                 "https://learn.microsoft.com/windows/ai/foundry-local/get-started";
            return;
        }

        _languageModel = await LanguageModel.CreateAsync();
        StatusText.Text = "Model ready.";
        SendButton.IsEnabled = true;
    }

    private async void OnSendClicked(object sender, RoutedEventArgs e)
    {
        if (_languageModel is null) return;

        string prompt = PromptBox.Text.Trim();
        if (string.IsNullOrEmpty(prompt)) return;

        SendButton.IsEnabled = false;
        ResponseText.Text = string.Empty;
        StatusText.Text = "Generating response...";

        try
        {
            string fullPrompt;
            int skillIndex = SkillSelector.SelectedIndex;

            if (skillIndex == 1)
            {
                // Summarize: inject an instruction into the prompt
                fullPrompt = $"Summarize the following text concisely:\n\n{prompt}";
            }
            else if (skillIndex == 2)
            {
                // Rewrite: inject an instruction into the prompt
                fullPrompt = $"Rewrite the following text to be clearer and more professional:\n\n{prompt}";
            }
            else
            {
                // Plain chat
                fullPrompt = prompt;
            }

            var result = await _languageModel.GenerateResponseAsync(fullPrompt);
            ResponseText.Text = result.Text;
            StatusText.Text = "Done.";
        }
        catch (Exception ex)
        {
            ResponseText.Text = $"Error: {ex.Message}";
            StatusText.Text = "An error occurred.";
        }
        finally
        {
            SendButton.IsEnabled = true;
        }
    }
}

Stap 6: Uw LAF-token toevoegen

Opmerking

Wat is een LAF-token? Een LAF-token (Limited Access Feature) is hoe Microsoft toegang beperkt tot pre-release of gecontroleerde Windows-API's. Wanneer u het aanvraagformulier indient, stuurt Microsoft u twee waarden per e-mail:

  • Een token : een korte base64-tekenreeks (bijvoorbeeld xK9mP2nQrL8vZw==)
  • Een attestation-tekenreeks : een zin in het formulier "<id> has registered their use of <feature> with Microsoft and agrees to the terms of use."

Beide waarden zijn specifiek voor de familienaam van uw app — ze zullen niet werken bij een andere app. Plak ze in TryUnlockFeature() precies zoals ontvangen.

Phi Silica is een functie met beperkte toegang. Vervang voordat u gaat bouwen de tijdelijke waarden in InitializeModelAsync door uw werkelijke token- en attestation-reeks.

  1. Verzend het laf-toegangstokenaanvraagformulier.

  2. Wanneer u uw token-e-mail ontvangt, zoekt u uw pakketfamilienaam door de app eenmaal te implementeren (Build → Deploy Solution) en vervolgens in PowerShell uit te voeren:

    Get-AppxPackage | Where-Object {$_.Name -like "*PhiSilicaChat*"} | Select-Object PackageFamilyName
    

    Aanbeveling

    Als uw project Identity Name een GUID is (de standaardinstelling voor nieuwe projecten), zoekt u in plaats daarvan op die waarde: Get-AppxPackage | Where-Object {$_.Name -like "*YOUR-GUID*"}

  3. Beantwoord het token-e-mailadres met de familienaam van uw pakket. Microsoft stuurt u een tokenwaarde en attestation-tekenreeks.

  4. Vervang de waarden van de tijdelijke aanduiding in MainWindow.xaml.cs.

    LimitedAccessFeatures.TryUnlockFeature(
        "com.microsoft.windows.ai.languagemodel",
        "YOUR_TOKEN_HERE",           // ← replace with token from email
        "YOUR_ATTESTATION_HERE");    // ← replace with full attestation string from email
    

    Belangrijk

    Het token is gebonden aan de familienaam van uw app-pakket. Voer deze niet door naar een openbare opslagplaats.

Stap 7: Bouwen en uitvoeren

  1. Controleer of de build configuratie ARM64 is.

  2. Druk op F5 om te bouwen en uit te voeren.

  3. Wacht totdat op de statusbalk 'Model gereed' wordt weergegeven.

  4. Typ een prompt, selecteer een vaardigheid en klik op Genereren.

Probeer deze aanwijzingen om elke vaardigheid te testen:

Vaardigheid Voorbeeldprompt
Chat What are the differences between WinUI 3 and WPF?
Samenvatten Een lang artikel of documentatiegedeelte plakken
Herschrijven make this formal: hey can u help me fix this bug

Troubleshooting

Status toont 'niet ondersteund op dit apparaat'
Uw pc is geen Copilot+-pc of voldoet niet aan de minimale Windows-versie (build 26200+). Controleer winver en controleer of uw apparaat een NPU heeft.

Build-fout: naamruimte niet gevonden
Controleer of Microsoft.WindowsAppSDK1.8.250410001-experimental1 (of hoger) geïnstalleerd is en dat de build is ingesteld op ARM64 (niet x64 of AnyCPU).

API retourneert toegang geweigerd/E_ACCESSDENIED
De PhiSilium-API vereist een ontgrendelingstoken voor beperkte toegangsfuncties. Vraag er een op het laf-toegangstokenaanvraagformulier aan. Het token moet worden geregistreerd voordat aanroepen lukken.

EnsureReadyAsync mislukt of loopt vast
Controleer de Windows Update-instellingen > voor de voortgang van het downloaden van het AI-model. Het downloaden van het model vereist een internetverbinding en kan enkele minuten duren.

Volgende stappen