Verwenden von Dialogen in einem Skill

GILT FÜR: SDK v4

In diesem Artikel wird veranschaulicht, wie ein Skill erstellt werden kann, der mehrere Aktionen unterstützt. Diese Aktionen werden mithilfe von Dialogen unterstützt. Der Hauptdialog erhält die erste Eingabe vom Skillconsumer und startet dann die entsprechende Aktion. Informationen zur Implementierung des Skillconsumers für den zugehörigen Beispielcode finden Sie unter Verwendung eines Skills mithilfe von Dialogen.

In diesem Artikel wird davon ausgegangen, dass Sie bereits mit den Skills zur Erstellung von Texten vertraut sind. Informationen zum Erstellen eines Skillbots im Allgemeinen finden Sie unter Implementieren eines Skills.

Hinweis

Die JavaScript-, C#- und Python-SDKs für Bot Framework werden weiterhin unterstützt, das Java-SDK wird jedoch eingestellt und der langfristige Support endet im November 2023.

Bestehende Bots, die mit dem Java SDK erstellt wurden, werden weiterhin funktionieren.

Wenn Sie einen neuen Bot erstellen möchten, sollten Sie den Einsatz von Power Virtual Agents in Betracht ziehen und sich über die Auswahl der richtigen Chatbot-Lösung informieren.

Weitere Informationen finden Sie unter Die Zukunft des Bot-Design.

Voraussetzungen

Hinweis

Language Understanding (LUIS) wird am 1. Oktober 2025 eingestellt. Ab dem 1. April 2023 können Sie keine neuen LUIS-Ressourcen erstellen. Eine neuere Version von Language Understanding ist jetzt als Teil von Azure KI Language verfügbar.

Conversational Language Understanding (CLU), ein Feature von Azure KI Language, ist die aktualisierte Version von LUIS. Weitere Informationen zur Unterstützung von Language Understanding im Bot Framework SDK finden Sie unter Natürliches Sprachverständnis.

Informationen zu diesem Beispiel

Das Beispiel skills skillDialog enthält Projekte für zwei Bots:

  • dialog root bot, das eine skill dialog-Klasse verwendet, um einen Skill zu nutzen.
  • dialog skill bot, das einen Dialog verwendet, um von Skillconsumern stammende Aktivitäten zu behandeln. Dieser Skill ist eine Adaption des Beispiels core bot. (Weitere Informationen zu „core bot“ finden Sie unter Hinzufügen von Features zum Verstehen natürlicher Sprache zu Ihrem Bot.)

Dieser Artikel konzentriert sich auf die Verwendung von Dialogen innerhalb eines Skillbots zur Abwicklung mehrerer Aktionen.

Weitere Informationen zum Skillconsumerbot finden Sie unter Nutzen eines Skills mithilfe von Dialogen.

Ressourcen

Bei eingesetzten Bots erfordert die Bot-zu-Bot-Authentifizierung, dass jeder teilnehmende Bot über eine gültige Identität verfügt. Sie können jedoch Skills und Skill-Verbraucher lokal mit dem Bot Framework Emulator ohne Identitätsinformationen testen.

Um den Skill für benutzerseitige Bots verfügbar zu machen, registrieren Sie den Skill bei Azure. Weitere Informationen finden Sie unter Registrieren eines Bots bei Azure KI Bot Service.

Optional kann der Skillbot ein LUIS-Modell für die Flugbuchung verwenden. Um dieses Modell zu nutzen, verwenden Sie die Datei „CognitiveModels/FlightBooking.json“, um das LUIS-Modell zu erstellen, zu trainieren und zu veröffentlichen.

Anwendungskonfiguration

  1. Fügen Sie optional die Identitätsinformationen der Skills zur Konfigurationsdatei der Skills hinzu. (Wenn entweder der Skill oder Skill-Verbraucher eine Identität angibt, müssen beide eine Identität angeben.)

  2. Wenn Sie das LUIS-Modell verwenden, fügen Sie LUIS-App-ID, den API-Schlüssel und den API-Hostnamen hinzu.

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": [ "*" ]
}

Logik für das Weiterleiten von Aktivitäten

Der Skill unterstützt verschiedene Features. Er kann einen Flug buchen oder das Wetter an einem Ort abfragen. Wenn er darüber hinaus eine Nachricht außerhalb eines dieser beiden Kontexte empfängt, kann er mithilfe von LUIS versuchen, die Nachricht zu interpretieren. Im Manifest des Skills werden diese Aktionen, ihre Ein- und Ausgabeparameter sowie die Endpunkte des Skills beschrieben. Beachten Sie, dass der Skill Ereignisse des Typs „BookFlight“ oder „GetWeather“ verarbeiten kann. Er kann auch Nachrichtenaktivitäten verarbeiten.

Der Skill definiert einen Dialog zum Weiterleiten von Aktivitäten, den er verwendet, um auf Grundlage der anfänglichen vom Skillconsumer eingehenden Aktivität auszuwählen, welche Aktion eingeleitet werden soll. Falls vorgesehen, kann das LUIS-Modell die Absichten „Flugbuchung“ und „Wetterbericht“ in einer ersten Nachricht erkennen.

Die Flugbuchungsaktion ist ein mehrstufiger Prozess, der als separater Dialog implementiert wird. Nach Beginn der Aktion werden eingehende Aktivitäten von diesem Dialog bearbeitet. Die Wetterberichtsaktion hat Platzhalterlogik, die in einem vollständig implementierten Bot ersetzt würde.

Der Dialog zum Weiterleiten von Aktivitäten enthält Code für Folgendes:

Die im Skill verwendeten Dialoge erben von der component dialog-Klasse. Weitere Informationen zu Komponentendialogen finden Sie unter Verwalten der Dialogkomplexität.

Initialisieren des Dialogs

Der Dialog zum Weiterleiten von Aktivitäten enthält einen untergeordneten Dialog zur Buchung eines Flugs. Der Hauptwasserfall-Dialog weist einen Schritt auf, mit dem eine Aktion auf Grundlage der empfangenen Anfangsaktivität gestartet wird.

Er akzeptiert auch eine LUIS-Erkennungsfunktion. Wenn diese Erkennungsfunktion initialisiert ist, interpretiert der Dialog damit die Absicht einer anfänglichen Nachrichtenaktivität.

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

Verarbeiten einer anfänglichen Aktivität

Im ersten (und einzigen) Schritt des Hauptwasserfall-Dialogs prüft der Skill den eingehenden Aktivitätstyp.

  • Ereignisaktivitäten werden an einen on event activity-Handler weitergeleitet, der die entsprechende Aktion basierend auf dem Namen des Ereignisses startet.
  • Nachrichtenaktivitäten werden an einen on message activity-Handler weitergeleitet, der zusätzliche Verarbeitungsvorgänge ausführt, bevor er entscheidet, was zu tun ist.

Wenn der Skill den Typ der eingehenden Aktivität oder den Namen des Ereignisses nicht erkennt, sendet er eine Fehlermeldung und wird beendet.

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

Behandeln von Nachrichtenaktivitäten

Wenn die LUIS-Erkennungsfunktion konfiguriert ist, ruft der Skill LUIS auf und startet dann eine auf der Absicht basierende Aktion. Wenn die LUIS-Erkennungsfunktion nicht konfiguriert ist oder die Absicht nicht unterstützt wird, sendet der Skill eine Fehlermeldung und wird beendet.

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

Beginnen einer mehrstufigen Aktion

Die Flugbuchungsaktion leitet einen mehrstufigen Dialog ein, um die Buchungsdetails vom Benutzer abzufragen.

Die Wetterberichtsaktion ist nicht implementiert. Derzeit sendet sie eine Platzhalternachricht und wird dann beendet.

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

Zurückgeben eines Ergebnisses

Der Skill startet einen Buchungsdialog für die Flugbuchungsaktion. Da der Dialog zum Weiterleiten von Aktivitäten nur einen Schritt hat, wird mit dem Ende des Buchungsdialogs auch der Dialog zum Weiterleiten von Aktivitäten beendet. Das Dialogergebnis aus dem Buchungsdialog wird zum Dialogergebnis für den Dialog zum Weiterleiten von Aktivitäten.

Die Wetterberichtsaktion wird einfach beendet, ohne einen Rückgabewert festzulegen.

Abbrechen einer mehrstufigen Aktion

Der Buchungsdialog und sein untergeordneter Datumsauflösungsdialog leiten sich beide vom grundlegenden Abbruch- und Hilfedialog ab, der Nachrichten des Benutzers prüft.

  • Bei „Hilfe“ oder „?“ wird eine Hilfemeldung angezeigt. Anschließend wird der Konversationsfluss im folgenden Durchgang fortgesetzt.
  • Bei „cancel“ oder „quit“ werden alle Dialoge abgebrochen, wodurch der Skill beendet wird.

Weitere Informationen finden Sie unter Behandeln von Benutzerunterbrechungen.

Dienstregistrierung

Die Dienste, die für diesen Skill benötigt werden, sind die gleichen, die für einen Skillbot im Allgemeinen benötigt werden. Eine Erläuterung der erforderlichen Dienste finden Sie unter Implementieren eines Skills.

Qualifikationsmanifest

Ein Qualifikationsmanifest ist eine JSON-Datei, in der die von der Qualifikation durchführbaren Aktivitäten, die Eingabe- und Ausgabeparameter und die Endpunkte der Qualifikation beschrieben sind. Das Manifest enthält die Informationen, die Sie für den Zugriff auf die Qualifikation mit einem anderen Bot benötigen.

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

Das Schema des Qualifikationsmanifests ist eine JSON-Datei, in der das Schema des Qualifikationsmanifests beschrieben ist. Die neueste Schema-Version ist v2.1.

Testen des Skillbots

Sie können den Skill im Emulator mit dem Skillconsumer testen. Dazu müssen Sie die Skill- und Skillconsumerbots gleichzeitig ausführen. Informationen zum Konfigurieren des Skills finden Sie unter Verwenden eines Dialogs zum Nutzen eines Skills.

Laden Sie die aktuelle Version von Bot Framework Emulator herunter, und installieren Sie sie.

  1. Führen Sie den „dialog skill bot“ und den „dialog root bot“ lokal auf Ihrem Computer aus. Wenn Sie eine Anleitung benötigen, helfen Ihnen die README-Datei des Beispiels für C#, JavaScript, Java oder Python weiter.
  2. Testen Sie den Bot im Emulator.
    • Wenn Sie sich zum ersten Mal an der Konversation beteiligen, zeigt der Bot eine Begrüßung an und fragt Sie, welchen Skill Sie aufrufen möchten. Der Skillbot für dieses Beispiel hat nur einen Skill.
    • Wählen Sie DialogSkillBot aus.
  3. Als Nächstes bittet Sie der Bot, eine Aktion für den Skill auszuwählen. Wählen Sie „BookFlight“ aus.
    1. Der Skill beginnt seine Flugbuchungsaktion. Beantworten Sie die Aufforderungen.
    2. Wenn der Skill abgeschlossen ist, zeigt der Stammbot die Buchungsdetails an, bevor er erneut nach dem Skill fragt, den Sie aufrufen möchten.
  4. Wählen Sie erneut DialogSkillBot und „BookFlight“ aus.
    1. Beantworten Sie die erste Aufforderung, und geben Sie „Abbrechen“ ein, um die Aktion abzubrechen.
    2. Der Skillbot endet, ohne die Aktion abzuschließen. Der Consumer fordert zur Angabe des Skills auf, den Sie aufrufen möchten.

Mehr über Debuggen

Da der Datenverkehr zwischen Skills und Skill-Verbraucher authentifiziert wird, gibt es zusätzliche Schritte beim Debuggen solcher Bots.

  • Der Skill-Verbraucher und alle Skills, die er direkt oder indirekt verbraucht, müssen ausgeführt werden.
  • Wenn die Bots lokal ausgeführt werden und einer der Bots über eine App-ID und ein Passwort verfügt, müssen alle Bots gültige IDs und Passwörter besitzen.
  • Wenn alle Bots bereitgestellt werden, erfahren Sie, wie Sie einen Bot über einen beliebigen Kanal mit ngrok debuggen.
  • Wenn einige der Bots lokal ausgeführt werden und einige bereitgestellt werden, erfahren Sie, wie Sie einen Skill oder einen Skill-Verbraucher debuggen.

Andernfalls können Sie einen Skill-Verbraucher oder einen Skill ähnlich debuggen, wie Sie andere Bots debuggen. Weitere Informationen finden Sie unter Debuggen eines Bots und Debuggen mit dem Bot Framework Emulator.

Weitere Informationen