Share via


Dialoogvensters in een vaardigheid gebruiken

VAN TOEPASSING OP: SDK v4

In dit artikel wordt beschreven hoe u een vaardigheid maakt die ondersteuning biedt voor meerdere acties. Het ondersteunt deze acties met behulp van dialoogvensters. Het hoofddialoogvenster ontvangt de eerste invoer van de vaardigheidsconsumer en start vervolgens de juiste actie. Zie hoe u een vaardigheid kunt gebruiken met behulp van dialoogvensters voor informatie over het implementeren van de vaardigheidsconsumer voor de bijbehorende voorbeeldcode.

In dit artikel wordt ervan uitgegaan dat u al bekend bent met het maken van vaardigheden. Zie hoe u een vaardigheidsbot in het algemeen kunt maken om een vaardigheid te implementeren.

Notitie

De Sdk's voor Bot Framework JavaScript, C# en Python blijven ondersteund, maar de Java SDK wordt buiten gebruik gesteld met definitieve langetermijnondersteuning die eindigt op november 2023.

Bestaande bots die zijn gebouwd met de Java SDK blijven functioneren.

Voor het bouwen van nieuwe bots kunt u Power Virtual Agents gebruiken en lezen over het kiezen van de juiste chatbotoplossing.

Zie De toekomst van botbouw voor meer informatie.

Vereisten

Notitie

Language Understanding (LUIS) wordt op 1 oktober 2025 buiten gebruik gesteld. Vanaf 1 april 2023 kunt u geen nieuwe LUIS-resources maken. Er is nu een nieuwere versie van taalkennis beschikbaar als onderdeel van Azure AI Language.

Conversational Language Understanding (CLU), een functie van Azure AI Language, is de bijgewerkte versie van LUIS. Zie Natuurlijke taalkennis voor meer informatie over ondersteuning voor taalkennis in de Bot Framework SDK.

Over dit voorbeeld

Het skills skillDialog-voorbeeld bevat projecten voor twee bots:

  • De hoofdmap van het dialoogvenster, dat gebruikmaakt van een vaardigheidsdialoogvensterklasse om een vaardigheid te gebruiken.
  • De dialoogvenster-vaardigheidsbot, die een dialoogvenster gebruikt voor het afhandelen van activiteiten die afkomstig zijn van gebruikers van vaardigheden. Deze vaardigheid is een aanpassing van het kernbotvoorbeeld . (Zie hoe u natuurlijke taalkennis toevoegt aan uw bot voor meer informatie over de kernbot.)

In dit artikel wordt uitgelegd hoe u een dialoogvenster binnen een vaardigheidsbot kunt gebruiken om meerdere acties te beheren.

Zie hoe u een vaardigheid kunt gebruiken met behulp van dialoogvensters voor informatie over de vaardigheidsconsumentenbot.

Resources

Voor geïmplementeerde bots vereist bot-naar-bot-verificatie dat elke deelnemende bot een geldige identiteit heeft. U kunt echter lokaal vaardigheden en vaardigheidsgebruikers testen met de Bot Framework Emulator zonder identiteitsgegevens.

Registreer de vaardigheid bij Azure om de vaardigheid beschikbaar te maken voor gebruikersgerichte bots. Zie voor meer informatie hoe u een bot registreert bij Azure AI Bot Service.

Optioneel kan de vaardigheidsbot een LUIS-model voor flight-booking gebruiken. Als u dit model wilt gebruiken, gebruikt u het Bestand CognitiveModels/FlightBooking.json om het LUIS-model te maken, te trainen en te publiceren.

Toepassingsconfiguratie

  1. Voeg eventueel de identiteitsgegevens van de vaardigheid toe aan het configuratiebestand van de vaardigheid. (Als de gebruiker van de vaardigheid of vaardigheid een identiteit opgeeft, moeten beide identiteiten.)

  2. Als u het LUIS-model gebruikt, voegt u de LUIS-app-id, API-sleutel en api-hostnaam toe.

DialogSkillBot\appsettings.json

{
  "MicrosoftAppType": "",
  "MicrosoftAppId": "",
  "MicrosoftAppPassword": "",
  "MicrosoftAppTenantId": "",
  "ConnectionName": "",

  "LuisAppId": "",
  "LuisAPIKey": "",
  "LuisAPIHostName": "",

  // This is a comma separate list with the App IDs that will have access to the skill.
  // This setting is used in AllowedCallersClaimsValidator.
  // Examples: 
  //    [ "*" ] allows all callers.
  //    [ "AppId1", "AppId2" ] only allows access to parent bots with "AppId1" and "AppId2".
  "AllowedCallers": [ "*" ]
}

Logica voor routering van activiteit

De vaardigheid ondersteunt een aantal verschillende functies. Het kan een vlucht boeken of het weer voor een stad krijgen. Als er bovendien een bericht buiten een van deze contexten wordt ontvangen, kan luis worden gebruikt om het bericht te interpreteren. Het manifest van de vaardigheid beschrijft deze acties, hun invoer- en uitvoerparameters en de eindpunten van de vaardigheid. Opmerking: de vaardigheid kan een gebeurtenis 'BookFlight' of 'GetWeather' afhandelen. Het kan ook berichtactiviteiten verwerken.

De vaardigheid definieert een dialoogvenster voor het doorsturen van activiteiten dat wordt gebruikt om te selecteren welke actie moet worden gestart, op basis van de initiële inkomende activiteit van de gebruiker van de vaardigheid. Indien opgegeven, kan het LUIS-model boekvlucht en intenties voor get-weather herkennen in een eerste bericht.

De actie boekvlucht is een proces met meerdere stappen, geïmplementeerd als een afzonderlijk dialoogvenster. Zodra de actie is gestart, worden binnenkomende activiteiten verwerkt door dat dialoogvenster. De actie get-weather heeft tijdelijke aanduidingenlogica die in een volledig geïmplementeerde bot wordt vervangen.

Het dialoogvenster activiteitsroutering bevat code voor:

De dialoogvensters die in de vaardigheid worden gebruikt, nemen over van de dialoogvensterklasse van het onderdeel. Zie voor meer informatie over onderdeeldialoogvensters hoe u de complexiteit van dialoogvensters beheert.

Het dialoogvenster initialiseren

Het dialoogvenster activiteitsroutering bevat een onderliggend dialoogvenster voor het boeken van een vlucht. Het hoofddialoogvenster voor waterval heeft één stap waarmee een actie wordt gestart op basis van de initiële activiteit die is ontvangen.

Het accepteert ook een LUIS-recognizer. Als deze recognizer is geïnitialiseerd, wordt het dialoogvenster gebruikt om de intentie van een initiële berichtactiviteit te interpreteren.

DialogSkillBot\Dialogs\ActivityRouterDialog.cs

private readonly DialogSkillBotRecognizer _luisRecognizer;

public ActivityRouterDialog(DialogSkillBotRecognizer luisRecognizer)
    : base(nameof(ActivityRouterDialog))
{
    _luisRecognizer = luisRecognizer;

    AddDialog(new BookingDialog());
    AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[] { ProcessActivityAsync }));

    // The initial child Dialog to run.
    InitialDialogId = nameof(WaterfallDialog);
}

Een initiële activiteit verwerken

In de eerste (en enige) stap van het hoofddialoogvenster voor waterval controleert de vaardigheid het binnenkomende activiteitstype.

  • Gebeurtenisactiviteiten worden doorgestuurd naar een gebeurtenisactiviteit-handler die de juiste actie start op basis van de naam van de gebeurtenis.
  • Berichtactiviteiten worden doorgestuurd naar een berichtenactiviteitshandler die extra verwerking uitvoert voordat wordt bepaald wat u moet doen.

Als de vaardigheid het type van de binnenkomende activiteit of de naam van de gebeurtenis niet herkent, wordt er een foutbericht verzonden en beëindigd.

DialogSkillBot\Dialogs\ActivityRouterDialog.cs

private async Task<DialogTurnResult> ProcessActivityAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    // A skill can send trace activities, if needed.
    await stepContext.Context.TraceActivityAsync($"{GetType().Name}.ProcessActivityAsync()", label: $"Got ActivityType: {stepContext.Context.Activity.Type}", cancellationToken: cancellationToken);

    switch (stepContext.Context.Activity.Type)
    {
        case ActivityTypes.Event:
            return await OnEventActivityAsync(stepContext, cancellationToken);

        case ActivityTypes.Message:
            return await OnMessageActivityAsync(stepContext, cancellationToken);

        default:
            // We didn't get an activity type we can handle.
            await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Unrecognized ActivityType: \"{stepContext.Context.Activity.Type}\".", inputHint: InputHints.IgnoringInput), cancellationToken);
            return new DialogTurnResult(DialogTurnStatus.Complete);
    }
}
// This method performs different tasks based on the event name.
private async Task<DialogTurnResult> OnEventActivityAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    var activity = stepContext.Context.Activity;
    await stepContext.Context.TraceActivityAsync($"{GetType().Name}.OnEventActivityAsync()", label: $"Name: {activity.Name}. Value: {GetObjectAsJsonString(activity.Value)}", cancellationToken: cancellationToken);

    // Resolve what to execute based on the event name.
    switch (activity.Name)
    {
        case "BookFlight":
            return await BeginBookFlight(stepContext, cancellationToken);

        case "GetWeather":
            return await BeginGetWeather(stepContext, cancellationToken);

        default:
            // We didn't get an event name we can handle.
            await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Unrecognized EventName: \"{activity.Name}\".", inputHint: InputHints.IgnoringInput), cancellationToken);
            return new DialogTurnResult(DialogTurnStatus.Complete);
    }
}

Berichtactiviteiten verwerken

Als de LUIS-recognizer is geconfigureerd, roept de vaardigheid LUIS aan en start vervolgens een actie op basis van de intentie. Als de LUIS-recognizer niet is geconfigureerd of de intentie niet wordt ondersteund, verzendt de vaardigheid een foutbericht en eindigt deze.

DialogSkillBot\Dialogs\ActivityRouterDialog.cs

// This method just gets a message activity and runs it through LUIS. 
private async Task<DialogTurnResult> OnMessageActivityAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    var activity = stepContext.Context.Activity;
    await stepContext.Context.TraceActivityAsync($"{GetType().Name}.OnMessageActivityAsync()", label: $"Text: \"{activity.Text}\". Value: {GetObjectAsJsonString(activity.Value)}", cancellationToken: cancellationToken);

    if (!_luisRecognizer.IsConfigured)
    {
        await stepContext.Context.SendActivityAsync(MessageFactory.Text("NOTE: LUIS is not configured. To enable all capabilities, add 'LuisAppId', 'LuisAPIKey' and 'LuisAPIHostName' to the appsettings.json file.", inputHint: InputHints.IgnoringInput), cancellationToken);
    }
    else
    {
        // Call LUIS with the utterance.
        var luisResult = await _luisRecognizer.RecognizeAsync<FlightBooking>(stepContext.Context, cancellationToken);

        // Create a message showing the LUIS results.
        var sb = new StringBuilder();
        sb.AppendLine($"LUIS results for \"{activity.Text}\":");
        var (intent, intentScore) = luisResult.Intents.FirstOrDefault(x => x.Value.Equals(luisResult.Intents.Values.Max()));
        sb.AppendLine($"Intent: \"{intent}\" Score: {intentScore.Score}");

        await stepContext.Context.SendActivityAsync(MessageFactory.Text(sb.ToString(), inputHint: InputHints.IgnoringInput), cancellationToken);

        // Start a dialog if we recognize the intent.
        switch (luisResult.TopIntent().intent)
        {
            case FlightBooking.Intent.BookFlight:
                return await BeginBookFlight(stepContext, cancellationToken);

            case FlightBooking.Intent.GetWeather:
                return await BeginGetWeather(stepContext, cancellationToken);

            default:
                // Catch all for unhandled intents.
                var didntUnderstandMessageText = $"Sorry, I didn't get that. Please try asking in a different way (intent was {luisResult.TopIntent().intent})";
                var didntUnderstandMessage = MessageFactory.Text(didntUnderstandMessageText, didntUnderstandMessageText, InputHints.IgnoringInput);
                await stepContext.Context.SendActivityAsync(didntUnderstandMessage, cancellationToken);
                break;
        }
    }

    return new DialogTurnResult(DialogTurnStatus.Complete);
}

Een actie met meerdere stappen starten

De actie Boekvlucht start een dialoogvenster met meerdere stappen om de reserveringsgegevens van de gebruiker op te halen.

De actie get-weather is niet geïmplementeerd. Op dit moment wordt een tijdelijke aanduiding verzonden en eindigt het.

DialogSkillBot\Dialogs\ActivityRouterDialog.cs

private async Task<DialogTurnResult> BeginBookFlight(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    var activity = stepContext.Context.Activity;
    var bookingDetails = new BookingDetails();
    if (activity.Value != null)
    {
        bookingDetails = JsonConvert.DeserializeObject<BookingDetails>(JsonConvert.SerializeObject(activity.Value));
    }

    // Start the booking dialog.
    var bookingDialog = FindDialog(nameof(BookingDialog));
    return await stepContext.BeginDialogAsync(bookingDialog.Id, bookingDetails, cancellationToken);
}
private static async Task<DialogTurnResult> BeginGetWeather(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    var activity = stepContext.Context.Activity;
    var location = new Location();
    if (activity.Value != null)
    {
        location = JsonConvert.DeserializeObject<Location>(JsonConvert.SerializeObject(activity.Value));
    }

    // We haven't implemented the GetWeatherDialog so we just display a TODO message.
    var getWeatherMessageText = $"TODO: get weather for here (lat: {location.Latitude}, long: {location.Longitude}";
    var getWeatherMessage = MessageFactory.Text(getWeatherMessageText, getWeatherMessageText, InputHints.IgnoringInput);
    await stepContext.Context.SendActivityAsync(getWeatherMessage, cancellationToken);
    return new DialogTurnResult(DialogTurnStatus.Complete);
}

Een resultaat retourneren

De vaardigheid start een boekingsdialoogvenster voor de boekvluchtactie. Aangezien het dialoogvenster activiteitsroutering slechts één stap heeft, eindigt het dialoogvenster voor het doorsturen van activiteiten en wordt het dialoogvenster voor het doorsturen van activiteiten het dialoogvenster het dialoogvenster voor het routeren van activiteiten.

De actie get-weather eindigt gewoon zonder een retourwaarde in te stellen.

Een actie met meerdere stappen annuleren

Het dialoogvenster reservering en het onderliggende dialoogvenster datum-resolver zijn beide afgeleid van het basisdialoogvenster voor annuleren en help, waarmee berichten van de gebruiker worden gecontroleerd.

  • Bij 'help' of '?' wordt een Help-bericht weergegeven en wordt vervolgens de gespreksstroom voortgezet op de volgende beurt.
  • Bij 'annuleren' of 'afsluiten' worden alle dialoogvensters geannuleerd, waardoor de vaardigheid wordt beëindigd.

Zie voor meer informatie hoe u onderbrekingen van gebruikers kunt afhandelen.

Serviceregistratie

De services die nodig zijn voor deze vaardigheid zijn hetzelfde als de services die nodig zijn voor een vaardigheidsbot in het algemeen. Bekijk hoe u een vaardigheid implementeert voor een bespreking van de vereiste services.

Vaardigheidsmanifest

Een vaardigheidsmanifest is een JSON-bestand dat de activiteiten beschrijft die de vaardigheid kan uitvoeren, de invoer- en uitvoerparameters en de eindpunten van de vaardigheid. Het manifest bevat de informatie die u nodig hebt om toegang te krijgen tot de vaardigheid van een andere bot.

DialogSkillBot\wwwroot\manifest\dialogchildbot-manifest-1.0.json

{
  "$schema": "https://schemas.botframework.com/schemas/skills/skill-manifest-2.0.0.json",
  "$id": "DialogSkillBot",
  "name": "Skill bot with dialogs",
  "version": "1.0",
  "description": "This is a sample skill definition for multiple activity types.",
  "publisherName": "Microsoft",
  "privacyUrl": "https://dialogskillbot.contoso.com/privacy.html",
  "copyright": "Copyright (c) Microsoft Corporation. All rights reserved.",
  "license": "",
  "iconUrl": "https://dialogskillbot.contoso.com/icon.png",
  "tags": [
    "sample",
    "travel",
    "weather",
    "luis"
  ],
  "endpoints": [
    {
      "name": "default",
      "protocol": "BotFrameworkV3",
      "description": "Default endpoint for the skill.",
      "endpointUrl": "https://dialogskillbot.contoso.com/api/messages",
      "msAppId": "00000000-0000-0000-0000-000000000000"
    }
  ],
  "activities": {
    "bookFlight": {
      "description": "Books a flight (multi turn).",
      "type": "event",
      "name": "BookFlight",
      "value": {
        "$ref": "#/definitions/bookingInfo"
      },
      "resultValue": {
        "$ref": "#/definitions/bookingInfo"
      }
    },
    "getWeather": {
      "description": "Retrieves and returns the weather for the user's location.",
      "type": "event",
      "name": "GetWeather",
      "value": {
        "$ref": "#/definitions/location"
      },
      "resultValue": {
        "$ref": "#/definitions/weatherReport"
      }
    },
    "passthroughMessage": {
      "type": "message",
      "description": "Receives the user's utterance and attempts to resolve it using the skill's LUIS models.",
      "value": {
        "type": "object"
      }
    }
  },
  "definitions": {
    "bookingInfo": {
      "type": "object",
      "required": [
        "origin"
      ],
      "properties": {
        "origin": {
          "type": "string",
          "description": "This is the origin city for the flight."
        },
        "destination": {
          "type": "string",
          "description": "This is the destination city for the flight."
        },
        "travelDate": {
          "type": "string",
          "description": "The date for the flight in YYYY-MM-DD format."
        }
      }
    },
    "weatherReport": {
      "type": "array",
      "description": "Array of forecasts for the next week.",
      "items": [
        {
          "type": "string"
        }
      ]
    },
    "location": {
      "type": "object",
      "description": "Location metadata.",
      "properties": {
        "latitude": {
          "type": "number",
          "title": "Latitude"
        },
        "longitude": {
          "type": "number",
          "title": "Longitude"
        },
        "postalCode": {
          "type": "string",
          "title": "Postal code"
        }
      }
    }
  }
}

Het manifestschema voor vaardigheden is een JSON-bestand dat het schema van het vaardigheidsmanifest beschrijft. De nieuwste schemaversie is v2.1.

De vaardigheidsbot testen

U kunt de vaardigheid in de emulator testen met de gebruiker van de vaardigheid. Hiervoor moet u zowel de vaardigheden als de vaardigheden van consumentenbots tegelijkertijd uitvoeren. Lees hoe u een dialoogvenster gebruikt om een vaardigheid te gebruiken voor informatie over het configureren van de vaardigheid.

Download en installeer de nieuwste Bot Framework Emulator.

  1. Voer de bot voor dialoogvenstervaardigheden en de hoofdmap van het dialoogvenster lokaal uit op uw computer. Als u instructies nodig hebt, raadpleegt u het bestand van README het voorbeeld voor C#, JavaScript, Java of Python.
  2. Gebruik de emulator om de bot te testen.
    • Wanneer u voor het eerst deelneemt aan het gesprek, geeft de bot een welkomstbericht weer en wordt u gevraagd welke vaardigheid u wilt bellen. De vaardigheidsbot voor dit voorbeeld heeft slechts één vaardigheid.
    • Selecteer DialogSkillBot.
  3. Vervolgens vraagt de bot u om een actie voor de vaardigheid te kiezen. Kies 'BookFlight'.
    1. De vaardigheid begint zijn boekvluchtactie; beantwoord de aanwijzingen.
    2. Wanneer de vaardigheid is voltooid, geeft de hoofdbot de reserveringsgegevens weer voordat u opnieuw wordt gevraagd om de vaardigheid die u wilt aanroepen.
  4. Selecteer DialogSkillBot opnieuw en 'BookFlight'.
    1. Beantwoord de eerste prompt en voer vervolgens 'annuleren' in om de actie te annuleren.
    2. De vaardigheidsbot eindigt zonder de actie te voltooien en de consument vraagt om de vaardigheid die u wilt aanroepen.

Meer informatie over foutopsporing

Omdat verkeer tussen vaardigheden en vaardigheidsgebruikers wordt geverifieerd, zijn er extra stappen bij het opsporen van fouten in dergelijke bots.

Anders kunt u fouten opsporen in een vaardigheidsconsumer of vaardigheid, net zoals bij het opsporen van fouten in andere bots. Zie Fouten opsporen in een bot en fouten opsporen met de Bot Framework Emulator voor meer informatie.

Aanvullende informatie